Struts2 入门

来源:互联网 发布:复杂网络建模基本概念 编辑:程序博客网 时间:2024/05/19 13:20

1、原理

可参考:http://blog.csdn.net/laner0515/article/details/27692673/ 、 http://blog.csdn.net/wuwenxiang91322/article/details/11070513

2、第一个项目——HelloWorld

(1)步骤:

①建立web项目,拷贝struts-2.5.10.1-min-lib/lib中的jar包。还需添加一个log4j-core


②在web.xml中配置Struts2的前端控制器-StrutsPrepareAndExecuteFilter

③定义一个POJO类:HelloAction

public class HelloAction {public String sayHello(){System.out.println("Hello World!");//返回逻辑视图return "success";}}
④拷贝struts.xml文件到项目的类路径或资源文件中,文件名不能修改


但可以针对每个action类设定一个struts的xml配置文件,该文件可改名字


但是在struts.xml配置文件中需要引入该配置文件

<include file="\action\helloworld\struts-hello.xml"></include>

⑤在struts.xml文件中,配置HelloAction.(把HelloAction交给Struts框架管理)


⑥访问Action

协议+主机地址+端口号+上下文路径+命名空间(namespace)+资源名称(action name)

3、Struts2中的6大配置文件

(1)Struts2框架按照如下顺序加载struts2配置:
①default.properties 该文件保存在 struts2-core-2.5.10.1.jar 中 org.apache.struts2包里面:包含了Struts2的默认常量配置
②struts-default.xml 该文件保存在 struts2-core-2.5.10.1.jar:包含了框架依赖的对象配置和结果类型,拦截器等配置.
③struts-plugin.xml 该文件保存在Struts2框架的插件中:struts-Xxx-2.5.10.1.jar.由插件提供

上述三个文件时框架自带的,不能修改,只能使用。
---------------------------------------------------------
④struts.xml 该文件是web应用默认的struts配置文件.重点.配置自定义的Action和其他信息.
⑤struts.properties 该文件是Struts的默认配置文件-->可以修改default.properties 的常量配置.
⑥web.xml 该文件是Web应用的配置文件

上述三个文件是可以修改操作的。
---------------------------------------------------------
如果多个文件配置了同一个struts2 常量,则后一个文件中配置的常量值会覆盖前面文件配置的常量值.
注意:一般在struts.xml中做常量配置.

4、常见常量配置

(1)指定默认编码集,作用于HttpServletRequest的setCharacterEncoding方法和freemarker 、velocity的输出
<constantname="struts.i18n.encoding" value="UTF-8"/>

(2)指定需要Struts2处理的请求后缀,该属性的默认值是action,即所有匹配*.action的请求都由Struts2处理。如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开

<constant name="struts.action.extension" value="action,,"/>

(3)开发模式下使用,这样可以打印出更详细的错误信息
<constant name="struts.devMode" value="true" />:修改struts.xml之后,不需要重启Tomcat.

5、struts.xml配置文件元素详解

(1)package元素—— <struts>根元素的子元素

用来对多个<action>元素分类管理,和Java中的package没有关系.

①常见的属性:
name: <package>的名字
extends: 表示当前<package>继承哪一个<package>,一般都是:struts-default。而struts-default其实就是struts-default.xml中<package>元素的名字,继承struts-default之后,就拥有了该<package>定义的所有资源.(结果返回类型,拦截器..)
namespace: 表示命名空间,一般的以"/"打头.,命名一般以模块名.如: /crm, /oa. 和<action>的name决定了一个Action类的访问路径.
abstract: 抽象的,缺省值是false. 若一个<package>的abstract="true",那么该<package>中就不能再定义<action>元素,只能用来继承.

(2)action元素——<package>元素的子元素

专门用来配置Action类的,理论上一个Action类匹配一个<action>元素.
<action name="" class="" method=""/>

①常见的属性:
name: action的名称,在同一个<package>中,action的名字必须唯一. 和<package>的namespace共同决定了一个Action类的访问路径.
注意:action的name值不能以"/"打头.
class:一个Action类的全限定名. 缺省值:com.opensymphony.xwork2.ActionSupport类.


method:当前Action动作访问的方法, 缺省值:execute.
如果不填class和method,默认会找com.opensymphony.xwork2.ActionSupport类的execute方法

(3)result元素——配置结果视图

①局部结果视图:<result>定义在<action>中。优先级较高

②全局结果视图:<result>定义在<global-results>中,而<global-results>在<package>中


③常见的属性:
name:Action方法返回的逻辑视图名称. 缺省值:success
type:结果的跳转类型.该类型的值在struts-default.xml中已经预定义好了. 缺省值:dispatcher

常见的type值(结果类型):
dispatcher: 表示从Action请求转发到页面(JSP).
redirect: 表示从Action重定向到页面(JSP).
chain: 表示从Action请求转发到另一个Action.
redirectAction: 表示从Action重定向到另一个Action.


stream: 表示返回流. 文件下载时使用.

6、创建Action类的三种方式

(1)使用公共的POJO类作为Action. 提供公共的无参数的Action方法.(不推荐).

①缺点:
没有一种方式约束Action方法必须是公共的无参数的.
Action方法的返回逻辑视图名可以自定指定. 有时起名不规范. 比如:"ooxx".


(2)定义一个类,实现于com.opensymphony.xwork2.Action接口.并覆写execute方法即可.(不推荐)

①缺点: 不支持国际化,数据校验,消息机制


(3)定义一个Action类,继承于com.opensymphony.xwork2.ActionSupport类.(推荐)


7、Action多方法调用

(1)原始方式

StudentAction.java

public class StudentAction extends ActionSupport{private static final long serialVersionUID = 1L;public String list(){System.out.println("学生列表");return NONE;}public String save(){System.out.println("添加学生");return NONE;}public String delete(){System.out.println("删除学生");return NONE;}public String update(){System.out.println("更新学生");return NONE;}}

Action中多个Action方法会造成<action>配置的臃肿。


(2)解决方案:
方案1: DMI:动态方法调用 :官方不推荐

格式:  action名!方法名

缺点:不安全,调用需要使用方法名。

在Struts2新的版本中,默认的关闭了DMI.若我们需要使用DMI,就需要struts.xml配置常量,启用动态方法调用.


此时:<action/>元素不需要指定method属性值.

测试:


方案2: 使用通配符的方式类配置: 通配符:*
①使用单个通配符


测试:



②使用多个通配符


测试:


8、访问ServletApi

有三种方式

(1)通过让Action类去实现感知接口(ServletRequestAware、ServletResponseAware、ServletSessionAware)

缺点:和ServletAPI藕合严重

eg:

getServletApi1Action.java

public class getServletApi1Action extends ActionSupport implements ServletRequestAware,ServletResponseAware{private static final long serialVersionUID = 1L;private HttpServletResponse resp;private HttpServletRequest req;public String execute(){System.out.println(req.getParameter("username"));return NONE;}@Overridepublic void setServletResponse(HttpServletResponse resp) {this.resp = resp;}@Overridepublic void setServletRequest(HttpServletRequest req) {this.req = req;}}
②struts.xml

<struts><package name="getServletPkg" extends="struts-default"namespace="/getServlet"><action name="api1" class="action.getServletApi.getServletApi1Action"></action></package></struts>
③测试:



实现原理:

通过拦截器实现



(2)使用ServletActionContext类,该类提供很多静态方法可以返回Servelet API对象

eg:

①getServletApi2Action.java

public class getServletApi2Action extends ActionSupport {private static final long serialVersionUID = 1L;public String execute() {HttpServletRequest req = ServletActionContext.getRequest();req.setAttribute("requestName","requestVal");HttpSession session = ServletActionContext.getRequest().getSession();session.setAttribute("sessionName", "sessionVal");ServletContext context = ServletActionContext.getServletContext();context.setAttribute("contextName","contextVal");return SUCCESS;}}

②struts.xml

<struts><package name="getServletPkg" extends="struts-default"namespace="/getServlet"><action name="api2" class="action.getServletApi.getServletApi2Action"><result>/views/getServletApi/getServlet.jsp</result></action></package></struts>

③getServlet.jsp

<h3>使用ServletActionContext</h3><hr>request:${requestName}<br>session:${sessionName}<br>servletContext:${contextName}<br>
④测试:


(3)使用ActionContext类,本身是Struts2对Servlet API的封装.(推荐使用)

ActionContext:——Action的环境对象,每一次请求都是一个新的Action对象,一个ActionContext对象封装了这一次请求的相关数据.
ActionContext使用了ThreadLocal模式,所以说是线程安全的.

eg:

①getServletApi3Action.java

public class getServletApi3Action extends ActionSupport{private static final long serialVersionUID = 1L;public String execute(){ActionContext context = ActionContext.getContext();context.put("requestKey","requestValue");context.getApplication().put("appKey","applicationVal");context.getSession().put("sessionKey","sessionValue");return SUCCESS;}}

②struts.xml

<struts><package name="getServletPkg" extends="struts-default"namespace="/getServlet"><action name="api3" class="action.getServletApi.getServletApi3Action"><result>/views/getServletApi/getServlet.jsp</result></action></package></struts>

getServlet.jsp

<h3>使用ActionContext</h3><hr>request:${requestKey}<br>session:${sessionKey}<br>servletContext:${appKey}<br> <hr>
④测试:


9、Action获取请求参数

两种方式:

(1)Action本身作为Model对象,通过setter方法封装(属性注入)

①把Action本身作为一个领域模型;
②要求页面提交的参数名称和Action中对应属性名称相同(只需要有属性的setter方法即可),但是如果把Action本身当成模型,则也需要提供相应的getter方法;
③该功能是由拦截器完成的;并且自带类型转换;
④在Servlet中,因为线程安全的问题,不能在Servlet中定义成员变量;但是在Struts2中,Action是每次请求都重新创建,所以肯定在Action中定义模型属性;
优点:简单;缺点:如果模型参数过多,Action中的属性会非常多,就会把模型和业务混淆在一起;
eg:

①GetParameterAction.java

public class GetParameterAction extends ActionSupport {private static final long serialVersionUID = 1L;private String username;private String password;@Overridepublic String execute() throws Exception {System.out.println("username:"+username);System.out.println("password:"+password);return NONE;}public void setUsername(String username) {this.username = username;}public void setPassword(String password) {this.password = password;}public String getUsername() {return username;}public String getPassword() {return password;}}
②struts.xml

<struts><package name="getparamPkg" extends="struts-default" namespace="/"><action name="login1" class="action.getParam.GetParameterAction"/></package></struts>
③getParam.jsp

<fieldset><legend>Action本身作为Model对象,通过setter方法封装</legend><form action="${pageContext.request.contextPath}/login1" method="post">账户:<input type="text" name="username"><br> 密码:<inputtype="text" name="password"><br> <input type="submit"value="登陆"></form></fieldset>
④测试:


(2)创建独立Model对象,页面通过ognl表达式封装(属性注入)

两种写法:
i.一个字段,并提供对应的getter和setter
ii.一个字段,action自己new出来,并提供getter方法
优点:action和model责任分离;缺点:页面必须按照和domain一致的规则来写;
①User.java

public class User {private String age;private String username;private String password;public String getAge() {return age;}public void setAge(String age) {this.age = age;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Overridepublic String toString() {return "User [username=" + username + ", password=" + password + "]";}}
②GetParameterAction2.java

public class GetParameterAction2 extends ActionSupport {private static final long serialVersionUID = 1L; private User user;       //自己new出来,并提供getter方法       //private User user = new User();       @Overridepublic String execute() throws Exception {System.out.println("username:  "+user.getUsername());System.out.println("password: "+user.getPassword());System.out.println("age: "+user.getAge());return NONE;}public void setUser(User user) {this.user = user;}public User getUser() {return user;}}
③struts.xml

<package name="getparamPkg" extends="struts-default" namespace="/"><action name="login2" class="action.getParam.GetParameterAction2"/></package>
④getParam.jsp

 <fieldset><legend>创建独立model对象,页面通过ognl表达式封装</legend><form action="${pageContext.request.contextPath}/login2" method="post">账户:<input type="text" name="user.username"><br> 密码:<inputtype="text" name="user.password"><br> <input type="submit"value="登陆"></form></fieldset>
⑤测试



注意


如果Action中没有user的getter方法会出现什么情况?

针对两种写法:
i.一个字段,并提供对应的getter和setter

以该例子注入username为例,找到user.username,在Action类中寻找user属性,判断user是否为空,若为空则创建一个,调用setUser方法,然后调用user.setUserName方法注入数据到user模型。然后继续处理user.password,判断user是否为空,若为空则创建一个,此时如果没有提供getter方法,则无法取得user对象,继续创建,那么前面注入的数据将会丢失。

ii.一个字段,action自己new出来,并提供getter方法

此时无需setUser方法,因为已经自行创建(user不为空)但仍然需要提供getter方法,否则无法取出user对象,设置值或取出值无法进行。