当前位置:文档之家› 02-Struts2的工作流程及配置文件

02-Struts2的工作流程及配置文件

Struts2的工作流程及配置文件--- ---Struts2.0的流程图从图中看到Struts2的工作流程如下:1.服务器接收到的请求首先经过一组过滤器链(实际中的其他过滤器可能还包括诸如Spring 的字符过滤器CharactorEncodingFilter、V elocity的过滤器等,一般FilterDispatcher位于过滤器的最后一个执行),过滤器链按照你在web.xml中的配置顺序在接收客户请求时顺序执行,在向客户发送响应时反序执行,Struts2的核心FilterDispatcher在web.xml中的配置如下:<filter><filter-name>setCharactor</filter-name><!-- 配置字符过滤--><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param></filter><filter><filter-name>struts2</filter-name><!-- 配置Struts2过滤器--><filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> </filter><filter-mapping><filter-name>setCharactor</filter-name><url-pattern>/*</url-pattern></filter-mapping><filter-mapping><filter-name>struts2</filter-name><url-pattern>/*</url-pattern></filter-mapping>注意:如果你使用的是W ebLogic6.1作为应用服务器,需要使用FilterDispatcherCompatW eblogic61替代FilterDispatcher。

2.请求被送到FilterDispatcher之后,FilterDispatcher会通过其私有静态的属性ActionMapper 询问这个请求是否需要调用Action处理,如果需要调用Action,FilterDispatcher会把请求委托给ActionProxy,ActionProxy调用ActionInvocation查找配置文件中该Action的所有信息,并以这个Action为目标创建代理对象(因为Struts2中的Action由于XWork的设计理念,并没有与Servlet的API被调用,所以如果直接调用Action的实例,那么显然基于HTTP 的请求都将无法传入Action。

Struts2通过创建Action的代理对象,并使用拦截器将HTTP 的请求信息传入代理对象,这是典型的AOP处理方式,这也实现了控制器与Servlet的API 的分离,这是Struts1.x所欠缺的优秀的设计方式),然后执行该Action之前的所配置的所有拦截器,与过滤器相同,在接受请求时,会顺序执行你在配置文件中为该Action配置的拦截器顺序;3.在穿越拦截器之后,就会执行Action,当Action执行完毕,ActionInvocation就要使用result加载结果(可以是JSP、PDF、XML、V elocity、EXCEL、Action等,Struts2为我们提供了丰富的视图模板可以调用),加载完结果之后会再次反向穿越拦截器和过滤器链,将响应结果发送给客户;从上面不难看出,拦截器(Interceptor)是Struts2中非常重要的组成部分,在Struts2中绝大多数功能都是通过配置拦截器实现的,例如防止表单的重复提交、文件上传等等。

在上图中的action与Struts1有很大的不同,Struts1在接收到第一个请求时,会创建Action 实例,将其放到HashMap中,以后的请求会直接返回这个实例,也就是说一个Action的实例是多线程共享的,这样虽然节省了资源,但在Action中应谨慎使用全局变量,因为全局变量是多线程共享的,所以Struts1+Hibernate3+Spring2整合的时候,其中一种方式是把Struts1的Action交给Spring容器管理,我们在Spring的XML文件中用<bean>元素配置Action的时候,Spring建议我们设置singleton=”false”(Spring2.0之后改为scope=”prototype”),也就是一个请求产生一个Action实例!在Struts2中的Action是线程安全的,因为Struts2会为每个请求创建一个Action实例,所以我们可以大胆的使用全局变量。

另外,Struts2的POJO并不要求继承任何类或实现任何接口,Action也不要求继承任何类或实现任何接口,不像Struts1那样要求POJO继承ActionForm或其子类,Action要求继承Action 或其子类。

Struts2都是通过配置文件和拦截器与POJO、Action建立关联,实现了非侵入性,这是优越于Struts1的重要优势!另外要注意的是,最好对Action中的POJO进行初始化,防止空指针异常。

但实际上Struts2建议取消类似于FormBean这样的累赘对象,主张使用POJO代替Action和FormBean,这点和JSF是一致的,在JSF中也是用一个普通的POJO 完成接受表单数据并处理请求的目的。

_______________________________________________________________________________ Struts2的API为两个部分:Struts2 core和Xwork,两个部分分工协作。

Struts2在接受到用户请求时会遍历HttpSession等对象,将所有值装入Action Context Map对象(请求参数会装入值栈ValueStack中的根对象),在Xwork中(也就是Action)操作经过包装的对象,而不是直接操作Servlet的API,这实现了Xwork与Servlet API的分离,大大降低了系统的耦合度,使得逻辑层不依赖于表现层(Web层),因为XWork并不是专为Servlet容器设计的。

注意:关于OGNL的具体部分请参看本教程第四篇的内容。

XWork的API提供了两种访问Servlet的API的方式供我们选择:1.IOC方式,也就是通过setXXX()方法进行依赖注入,这要求我们的Action实现ServletRequestAware、SerlvetResponseAware、SessionAware接口,通过实现接口中的setXXX()方法传递Servlet的API,这是由struts-default.xml的默认拦截器栈中的”servlet-config”拦截器提供的,如下图所示:Struts2默认地会为每个Action配置defaultSatck(因为我们自己定义的package一般都会使用extends=”struts-default”继承struts-default.xml中的name属性为”struts-default”的<package>,这个文件在struts-core-2.0.6,jar的根目录中,大家可以参看API很好的了解这个文件里的东东都是做什么的。

),这是Struts2的默认拦截器栈,里面包含了一组拦截器,通常我们不需要再为Action配置拦截器,因为这些默认的已经足够了!2.非IOC方式,因为每个请求都有一个Action的上下文,所以我们可以使用com.opensymphony.xwork2.ActionContext访问session对象,方法:ActionContext.getContext.getSession().put(“”,””),或者使用ActionContext的子类org.apache.struts2.ServletActionContext的静态方法访问请求、响应等对象,方法:ServletActionContext.getRequest()、ServletActionContext.getResponse()、ServletActionContext.getPageContext(),但一般建议能使用ActionContext完成的功能,尽量不要使用ServlvetActionContext,从包名上就能看出来,ActionContext是XWork是的API,使用装饰过后的Map对象,而ServletActionContext是Struts2的API,使用ServletActionContext无疑是把Servlet的API引入了XWork中。

有人可能会问,那ActionContext使用请求和响应对象不是很方便哦,这很简单,因为你在实际开发中很少在Action中使用request和response对象,使用response无非是利用它的重定向功能,但这个功能使用<result name=”success” type=”redirect”>JSP文件</result>就可以解决了;使用request无非是在请求中设置参数,利用request.setAttribute(“”,””),这个功能完全可以交给POJO哦!你可以在POJO中定义一个变量,向里面传递值,JSP页面上直接取POJO的值就可以了。

3.Struts2的Action是控制器,并不是标准的Servlet,如果我们想在Action结束的时候向客户端输出,我们可以获取HttpServletResponse对象,调用其输出字符流或者字节流的方法,最后加上return null;即可完成。

你也可以使用result的type=stream向客户端写入流,这个会在文件上传和下载中看到!4.当然,我们也可以完全不接触Servlet的API进行操作,而是直接利用ActionContext对象,例如:在JSP中我们可以利用EL表达式进行输出这些值,如下图所示:从上面的图我们可以看出EL表达式可以独立使用,也可以配合JSTL的c:out标签进行输出。

相关主题