转自:http://blog.csdn.net/zjtimef/article/details/12027767
当用户发送一个请求后,web.xml中配置的FilterDispatche(Struts 2核心控制器)就会过滤该请求,FilterDispatcher根据配置,将请求转发给Action。
以下是详解过程:
1、 当Web容器收到 请求(HttpServletRequest),例如http://localhost:8080/Struts 2.0/hello.jsp就是一个请求。
2、 请求被提交到一系列的(主要有三层)过滤器(Filter),如(ActionContextCleanUp)过滤器,然后经过Other filters(SiteMesh ,etc),最后才到达FilterDispatcher,这里是顺序执行的。
3、 FilterDispatcher是控制器的核心,就是mvc的struts2实现控制层(controller)的核心。然后它调用ActionMapper确定请求那个Action,ActionMapper返回一个收集Action详细信息的ActionMaping对象。
4、 FilterDispatcher将控制权委派给ActionProxy,ActionProxy调用配置管理器Configuration Manager(struts.xml),找到需要调用的Action类。例如上一篇的StrutsAction类就是Action类。
5、 接着ActionProxy创建一个ActionInvocation对象,ActionInvocation在调用Action之前会依次根据配置加载Action相关的所有拦截器(Interceptor )
6、 一旦Action执行完毕,ActionInvocation负责根据struts.xml中配置找到对应的返回结果result。
首先用到的是web.xml
- <span style="font-size:18px"><?xml version="1.0" encoding="UTF-8"?>
- <web-app version="2.5"
- xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
- http://java.sun.com/xml/ns/JavaEE/web-app_2_5.xsd">
- <filter>
- <filter-name>struts 2</filter-name>
- <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>struts 2</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- </web-app>
- </span>
最上面是普通的xml文件头,然后是一些引用文件。后面的webapp标签中配置了下面这样一段:
…
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>所有过滤器必须实现java.Serlvet.Filter接口,这个接口中含有3个过滤器类必须实现的方法:(该过滤器类的源代码可在struts2包中获得)
init(FilterConfig):Servlet过滤器的初始化方法,Servlet容器创建Servlet过滤器实例后将调用这个方法。
doFilter(ServletRequest,ServletResponse,FilterChain):完成实际的过滤操作,当用户请求与过滤器关联的URL时,Servlet容器将先调用过滤器的doFilter方法,返回响应之前也会调用此方法。FilterChain参数用于访问过滤器链上的下一个过滤器。
在该方法中将调用dispatcher.serviceAction(),该方法如果找到相应的Action,将把用户的请求交给ActionProxy。
destroy():Servlet容器在销毁过滤器实例前调用该方法,这个方法可以释放Servlet过滤器占用的资源。
过滤器类编写完成后,必须要在web.xml中进行配置,格式如下:
<filter>
<!--自定义的名称-->
<filter-name>过滤器名</filter-name>
<!--自定义的过滤器类,注意,这里要在包下,要加包名-->
<filter-class>过滤器对应类</filter-class>
<init-param>
<!--类中参数名称-->
<param-name>参数名称</param-name>
<!--对应参数的值-->
<param-value>参数值</param-value>
</init-param>
</filter>
过滤器必须和特定的URL关联才能发挥作用,过滤器的关联方式有3种:与一个URL资源关联、与一个URL目录下的所有资源关联、与一个Servlet关联。
① 与一个URL资源关联:
<filter-mapping>
<!- -这里与上面配置的名称要相同-->
<filter-name>过滤器名</filter-name>
<!- -与该URL资源关联-->
<url-pattern>xxx.jsp</url-pattern>
</filter-mapping>
② 与一个URL目录下的所有资源关联:
<filter-mapping>
<filter-name>过滤器名</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
③ 与一个Servlet关联:
<filter-mapping>
<filter-name>过滤器名</filter-name>
<url-pattern>Servlet名称</url-pattern>
</filter-mapping>
struts.xml文件
- <span style="font-size:18px"><?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE struts PUBLIC
- "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
- "http://struts.apache.org/dtds/struts-2.0.dtd">
- <struts>
- <package name="default" extends="struts-default">
- <action name="struts" class="org.action.StrutsAction">
- <result name="success">/welcome.jsp</result>
- <result name="error">/hello.jsp</result>
- </action>
- </package>
- </struts>
- </span>
package有以下几个常用属性:
name(必选):指定包名,这个名字将作为引用该包的键。注意,包的名字必须是唯一的,在一个struts.xml文件中不能出现两个同名的包。
extends(可选):允许一个包继承一个或多个先前定义的包。
abstract(可选):将其设置为true,可以把一个包定义为抽象的。抽象包不能有action定义,只能作为“父”包被其他包所继承。
namespace(可选):将保存的action配置为不同的名称空间。
看下面这个例子:
- <span style="font-size:18px"><package name="default">
- <action name="foo" class="mypackage.simpleAction">
- <result name="success">/foo.jsp</result>
- </action>
- <action name="bar" class="mypackage.simpleAction">
- <result name="success">/bar.jsp</result>
- </action>
- </package>
- <package name="mypackage1" namespace="/">
- <action name="moo" class="mypackage.simpleAction">
- <result name="success">/moo.jsp</result>
- </action>
- </package>
- <package name="mypackage2" namespace="/barspace">
- <action name="bar" class="mypackage.simpleAction">
- <result name="success">/bar.jsp</result>
- </action>
- </package></span>
Action元素
当一个请求匹配到某个Action名字时,框架就使用这个映射来确定如何处理请求。
<actionname="struts" class="org.action.StrutsAction">
<resultname="success">/welcome.jsp</result>
<resultname="error">/hello.jsp</result>
</action>
在上面代码中,当一个请求映射到struts时,就会执行该Action配置的class属性对应的Action类,然后根据Action类的返回值决定跳转的方向。其实一个Action类中不一定只能有execute()方法。如果一个请求要调用Action类中的其他方法,就需要在Action配置中加以配置。例如,如果在org.action.StrutsAction中有另外一个方法为:
public String find()throws Exception{return SUCCESS;}
那么如果想要调用这个方法,就必须在Action中配置method属性,配置方法为:
<! - - name值是用来和请求匹配的- - >
<actionname="find" class="org.action.StrutsAction"method="find">
<resultname="success">/welcome.jsp</result>
<resultname="error">/hello.jsp</result>
</action>
result元素
一个result代表一个可能的输出。当Action类中的方法执行完成时,返回一个字符串类型的结果代码,框架根据这个结果代码选择对应的result,向用户输出。
<result name="逻辑视图名" type="视图结果类型"/>
<param name ="参数名">参数值</param>
</result>
param中的name属性有两个值:
① location:指定逻辑视图。
② parse:是否允许在实际视图名中使用OGNL表达式,参数默认为true。
result中的name属性有如下值:
success:表示请求处理成功,该值也是默认值。
error:表示请求处理失败。
none:表示请求处理完成后不跳转到任何页面。
input:表示输入时如果验证失败应该跳转到什么地方(关于验证后面会介绍)。
login:表示登录失败后跳转的目标。
type(非默认类型)属性支持的结果类型有以下几种:
chain:用来处理Action链。
chart:用来整合JFreeChart的结果类型。
dispatcher:用来转向页面,通常处理JSP,该类型也为默认类型。
freemarker:处理FreeMarker模板。
httpheader:控制特殊HTTP行为的结果类型。
jasper:用于JasperReports整合的结果类型。
jsf:JSF整合的结果类型。
redirect:重定向到一个URL。
redirect-action:重定向到一个Action。
stream:向浏览器发送InputStream对象,通常用来处理文件下载,还可用于返回AJAX数据。
tiles:与Tiles整合的结果类型。
velocity:处理Velocity模板。
xslt:处理XML/XLST模板。
plaintext:显示原始文件内容,如文件源代码。
其中,最常用的类型就是dispatcher和redirect-action。dispatcher类型是默认类型,通常不写,主要用于与JSP页面整合。redirect-action类型用于当一个Action处理结束后,直接将请求重定向到另一个Action。如下列配置:
…
<actionname="struts" class="org.action.StrutsAction" >
<resultname="success">/welcome.jsp</result>
<resultname="error">/hello.jsp</result>
</action>
<actionname="login" class="org.action.StrutsAction">
<result name="success"type="redirect-action">struts</result>
</action>
…
ActionSupport类
下面是ActionSupport类所实现的接口:
- <span style="font-size:18px">public class ActionSupport implements Action, Validateable, ValidationAware,
- TextProvider, LocaleProvider,Serializable {
- }
- Action接口同样位于com.opensymphony.xwork2包,定义了一些常量和一个execute()方法。
- public interface Action {
- public static final String SUCCESS="success";
- public static final String NONE="none";
- public static final String ERROR="error";
- public static final String INPUT="input";
- public static final String LOGIN="login";
- public String execute() throws Exception;
- }
- </span>
- <span style="font-size:18px">package org.action;
- import java.util.Map;
- import com.opensymphony.xwork2.ActionContext;
- import com.opensymphony.xwork2.ActionSupport;
- public class StrutsAction extends ActionSupport{
- private String name;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name=name;
- }
- public String execute() throws Exception {
- if(!name.equals("HelloWorld")){
- Map request=(Map)ActionContext.getContext().get("request");
- request.put("name",getName());
- return "success";
- }else{
- return "error";
- }
- }
- }
- </span>
Action类继承了ActionSupport类,所以可以看出,在execute的返回值中,其代码可以改为:
…
public Stringexecute() throws Exception {
if(!name.equals("HelloWorld")){
Map request=(Map)ActionContext.getContext().get("request");
request.put("name",getName());
returnSUCCESS;
}else{
returnERROR;
}
}
…