Struts 2 常用技术
《独门架构——java web 开发应用详解》 ch 9
1. 常用类和接口
1.1 getter 和 setter 方法
Struts 2 的 Action 类可以是一个普通的 POJO 类,类中须有一个execute()
方法来处理请求。
Action 类的属性 的getter
、setter
方法 ,不仅可以封装HTTP请求参数,同时可以为要转入的页面传递处理结果信息。但Struts 2不区分属性封装的是请求参数还是处理结果,因而,Struts 2的标签不仅可以输出处理结果,也可以输出请求参数。
如,设Action类中有属性 result
用于返回处理结果,并生成了 getter
、setter
方法,则在结果jsp中可使用<s:property value="result"/>
来输出结果值。
1.2 Action 接口
Struts 2提供了一个Action接口,定义了一些常用结果常量,如Action.SUCCESS="success";
,以及一个 execute()
方法。
若Struts 2的控制器类实现了Action接口,但使用了其他方法,如
process()
来处理请求,而不是默认的execute()
方法,此时execute()
方法也是必须要实现的。
不过这样做事画蛇添足了。若只想用其中的常量,使用Action.SUCCESS
或静态导入import static com.opensymphony.xwork2.Action.*
,然后直接写 SUCCESS 即可。
1.3 ActionSupport 类
ActionSupport 类是很多Struts 2内建接口(包括Action接口)的默认实现。控制器类(Action类)继承ActionSupport可以简化开发。
ActionSupport 类中的
execute()
方法的实现,只是返回了一个SUCCESS
。
1.4 通过 ActionContext 访问 Servlet API
Struts 2中Action不能直接访问 Servlet API。
Web 中最常访问 Servlet API 的是 HttpServletRequest、HttpSession 和 ServletContext,分布对于JSP中的request、session和application。
Struts 2 的 ActionContext 类可使用两种方法来访问 ServletAPI:
- getXxx 方法获得Map对象
- get 方法获得相应的 Servlet API 类的对象实例
getXxx方法
1. getContext:返回ActionContext对象。对象的 put 方法可加入 k-v 对,相当于使用 HttpServletRequest 类的setAttribute
方法加入 k-v 对。get 方法类似
2. getApplication:Map 对象
3. getSession: Map对象
例:
ActionContext ctx = ActionContext.getContext(); Map app = ctx.getApplication(); Map session = ctx.getSession();
get方法
ServletContext ctx = (ServletContext)ActionContext.getContext().get(SERVLET_CONTEXT);
HttpServletRequest request = ( HttpServletRequest ) ActionContext.getContext().get(HTTP_REQUEST);
HttpServletResponse response= ( HttpServletResponse ) ActionContext.getContext().get(HTTP_RESPONSE);
通过ServletActionContext
直接getResponse()
和getRequest()
1.5 通过感知拦截器访问 ServletAPI
在org.apache.struts2.interceptor
包中有一类名称含 Aware 的拦截器类。通过它们, 可获得相应的 Servlet API 对象或向相应的 Servlet API 对象写入 K-V 对的Map对象:
1. ApplicationAware接口:获得和ServletContext关联的Map对象
2. CookieAware接口:Cookie数组关联的Map对象
3. ParameterAware接口:和请求参数关联的Map对象
4. ServletRequestAware接口:获得HttpServletRequest对象
5. ServletResponseAware接口:获得HttpServletResponse对象
Action类只要实现上述接口,即可获得相应的Map对象或ServletAPI对象。
一般定义本地对象(如
private HttpServletRequest request;
),然后通过其getter
、setter
方法应用即可
1.6 动态方法处理多个提交请求
Action类的默认请求处理方法是execute()
方法(即使没有实现 Action 接口)。但可以在不修改配置文件的条件下改变处理方法。如,通过process()
方法处理请求,而execute()
方法处理另一请求。
此时访问process
需要使用特殊的 Action URL:~/actionname!process.action
,即在 action 名称后面加!,然后紧跟要调用的方法名
1.7 通过 method 属性处理多个请求
基本原理: 在配置文件中为同一个 Action 类指定多个 name 值,这样一个 Action 类就变成多个 Action 类了,再通过<action>
标签的 method 属性为每一个 Action 类指定一个处理请求的方法。
如,让 cn.action.LoginRegisterAction 类同时能够处理 login 和 register 请求:
<package name="struts2" extends="struts-default" namespace="/ch9">
<action name="loginAction" class="cn.action.LoginRegisterAction" method="login">
<result name="success">/jsp/success.jsp</result>
</action>
<action name="register Action " class="cn.action.LoginRegisterAction" method=" register ">
<result name=" register ">/jsp/register.jsp</result>
</action>
...
</package>
1.8 在配置中使用通配符
若采用下面的配置(name=*Action),任何以 Action 结尾的action,如 / loginAction 等都可以匹配,且此时 method 属性的值为Action名中的第一个值 login。
<action name=" * Action" class="cn.action.LoginRegisterAction" method="{1}">
<result name="success">/jsp/success.jsp</result>
</action>
class属性也可以使用通配符,如
<action name=" * Action" class="cn.action.{1}Action" method="{1}">
<result name="result">/jsp/result.jsp</result>
</action>
由于Java中类的名称一般是 开头大写,方法名称开头小写,因此,若想达到 cn.action.{1}Action
中 {1} 值为大写,只能使用两个通配符来表达,如 "*_*",即
<action name=" *_* Action" class="cn.action.{1}Action" method="{2}">
<result name="result">/jsp/result.jsp</result>
</action>
*_* 中第一个*为类名,第二个*为方法名,如 User_add , 对应的类是
cn.action.UserAction
,方法(method)是 add . 等价的配置是
<action name="User _add Action" class="cn.action.UserAction" method="add">
<result name="result">/jsp/result.jsp</result>
</action>
2 Result - 结果
一般Action只处理用户请求,不直接负责提供对浏览器的响应。Action中请求处理完成之后,返回一个字符串,将结果交由视图资源来完成。
控制器的作用应该是控制将哪个视图呈现给用户。
2.1 配置 result
Action中方法处理请求之后返回的字符串称为 结果名 或 视图名。结果可通过 <result>
子标签进行配置。一个action可有多个 <result>
子标签。
<result>
有两个属性name 和 type:
- name: 结果名 ,action返回的字符串必须和其的一个<result>
标签的name属性相匹配。
- type: 结果类型。 type 的默认值是 dispatcher
(此时可以省略type属性),即转发,相当于使用 forward 方法。
全局结果可使用<global-results>
来定义:
<global-results> <result name="success">/success.jsp</result> </global-results>
2.2 result 类型
Struts2的result
中可使用的type
可以在 struts-default.xml
中找到,包括chain
、freemarker
、redirect
等;
<package name="struts-default" abstract="true" strict-method-invocation="true">
<result-types>
<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
<result-type name="dispatcher" class="org.apache.struts2.result.ServletDispatcherResult" default="true"/>
<result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
<result-type name="redirect" class="org.apache.struts2.result.ServletRedirectResult"/>
<result-type name="redirectAction" class="org.apache.struts2.result.ServletActionRedirectResult"/>
<result-type name="stream" class="org.apache.struts2.result.StreamResult"/>
<result-type name="velocity" class="org.apache.struts2.result.VelocityResult"/>
...
</result-types>
...
</package>
```
有些类型需要在相应的**插件包**中找到,如 **`json`**类型位于`json-plugin`下面的`struts-pliugin.xml`中。注意package的名称是`json-default`,**使用json类型时其package的**`extends="json-default"`
2.2 通配符配置 result
<action name=" * Action" class="cn.action.{1}Action" method="{1}">
<result name="result">/jsp/{1}.jsp</result>
</action>
为了安全等原因,JSP文件一般放到 WEB-INF 目录中,因为 WEB-INF 中的资源客户端无法直接访问。在strut2中可以通过Action进行转发实现jsp文件的访问。具体方法是配置一个name=“*”,不指定 class (此时默认是ActionSupport类)的action:
<package name="struts2" extends="struts-default" namespace="/ch9">
<!-- 配置其他action -->
...
<!-- 配置访问jsp的action:处理所有无效的action -->
<action name="*" >
<result name="success">/WEB-INF/jsp/{1}.jsp</result>
</action>
...
</package>
此时访问url: http://localhost:8080/ch9/a.action, 由于默认的action类是ActionSupport,其execute方法返回success,因此访问会转到/WEB-INF/jsp/
下面的a.jsp
。
2.3 用请求参数指定 result
由于Action的属性既可以获得请求参数值,也可以传递参数值(可在要转入的jsp页面中使用EL表达式获得其值),因此可通过请求参数来指定结果的URL。
例如在类中定义参数 forward,设置其 getter/setter方法,请求执行之后,将jsp页面名称赋予 forward 参数,即可通过url来访问web-inf下的资源:
<!-- 配置其他action -->
...
<!-- 配置访问jsp的action:处理所有无效的action -->
<action name="forwardAction" class="..." >
<result name="success">/WEB-INF/jsp/${forward}.jsp</result>
</action>
3 模型驱动
ModelDriven即用一个JavaBean将用户请求和处理结果单独封装在一起,然后让action同时实现ModelDriven接口。
使用getModel().setResult("resultMsg");
之后,可以在JSP中使用<s:property value="model.result">
或<s:property value="result">
获取处理结果值。