1、web.xml的配置
web.xml文件实现了spring和struts的整合。
1)加载struts2核心及拦截过滤
<filter> <filter-name>struts2</filter-name> <filter-class> org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter </filter-class> </filter> <!-- --> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
2)指明spring配置文件的位置
默认情况下,加载的是WEB-INF/applicationContext.xml文件;通过配置参数来改变文件的路径。
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-main.xml</param-value> </context-param>
3)配置ContextLoaderListener监听器,使容器在启动时,自动加载applicationContext配置。它实现了ServletContextListener接口,容器启动时会自动执行它实现的方法。
<listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener>
4)编码设置
<filter> <filter-name>encoding</filter-name> <filter-class>com.sdo.demo.EncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
2、struts.xml的配置
1)包配置 - package
在struts.xml文件中package元素用于定义包配置,每个package元素定义了一个包配置。它的常用属性有:
。name:必选属性,指定包的名字
。extends:可选属性,用来指定该包继承的包(可以继承其他包中的action定义、拦截器定义)。默认值:struts-default
。namespace:可选属性,指定该包的命名空间。
同一个web应用中可能需要同名的action,而同一个命名空间不能有同名的action,struts2以命名空间的方式来管理action。对应的url:命名空间/Action名。默认的命名空间是""
。abstract:可选。设置package的属性为抽象的,抽象的package不能定义action。值true:false
2)包含配置
可以将一个配置文件分解成多个配置文件,那么必须在struts.xml中包这些配置文件
<includefile="struts-default.xml"/>
3)常量配置
<!-- 指定Web应用的默认编码集,相当于调用HttpServletRequest的setCharacterEncoding方法 --> <constant name="struts.i18n.encoding" value="UTF-8" /> <!-- 该属性指定需要Struts 2处理的请求后缀,该属性的默认值是action,即所有匹配*.action的请求都由Struts 2处理。如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开. --> <constant name="struts.action.extension" value="do" /> <!-- 设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭 --> <constant name="struts.serve.static.browserCache " value="false" /> <!-- 当struts的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下使用),开发阶段最好打开 --> <constant name="struts.configuration.xml.reload" value="true" /> <!-- 开发模式下使用,这样可以打印出更详细的错误信息 --> <constant name="struts.devMode" value="true" /> <!-- 默认的视图主题 --> <constant name="struts.ui.theme" value="simple" /> <!-- 该属性指定Struts 2中的action由Spring容器创建 --> <constant name="struts.objectFactory" value="spring" />
4、Action类
Struts2中通常直接使用Action来封装HTTP请求参数,因此,Action类里还应该包含与请求参数对应的属性,并且为属性提供对应的getter和setter方法。
action访问servlet API:struts2中的action并没有和任何servlet api耦合,但是提供了一个ActionContext类来访问servlet api。Struts2中通过ActionContext来访问Servlet API,让Action彻底从Servlet API 中分离出来,最大的好处就是可以脱离Web容器测试Action。另外,Struts2中还提供了一个ServletActionContext类,Action只要继承自该类,就可以直接访问Servlet API。
5、对于结果的处理
action处理完用户请求后,将返回一个普通字符串,整个普通字符串就是一个逻辑视图名。struts2通过配置逻辑视图名和物理视图资源之间的映射关系,将物理视图资源呈现出来。
struts2通过在struts.xml文件中使用<result>元素来配置结果,strust2提供了2中结果:
1)局部结果:将<result …/>作为<action …>元素的子元素配置;
2)全部结果:将<result …/>作为<global-results …>元素的子元素配置;
处理结果的类型:
名字
|
说明
|
chain
|
用来处理Action链
|
dispatcher
|
用来转向页面,通常处理JSP,这是默认的结果类型
|
freeMarker
|
处理FreeMarker模板
|
httpHeader
|
用来控制特殊的Http行为
|
redirect
|
重定向到一个URL
|
redirect-action
|
重定向到一个Action
|
stream
|
向浏览器发送InputSream对象,通常用来处理文件下载
|
velocity
|
处理Velocity模板
|
xslt
|
处理XML/XLST模板
|
plaintext
|
显示原始文件内容,例如文件源代码
|
tiles
|
结合Tile使用
|
6、异常处理机制
struts2的异常处理机制通过在struts.xml文件中配置<exception-mapping>元素完成的,配置该元素时,需要制定两个属性:
exception:此属性指定该异常映射所设置的异常类型;
result:指定action出现该异常时,系统转入result属性所指向的结果
异常映射也分为两种:
。局部异常映射:<exception-mapping…>元素作为<action…>元素的子元素配置
。全局异常映射:<exception-mapping…>元素作为<global-exception-mappings>元素的子元素配置
输出异常信息(使用struts2标签来输出异常信息):
。<s:property value="exception.message" />:输出异常对象本身
。<s:property value="exceptionStack" />:输出异常堆栈信息
<global-results> <!-- 逻辑名为sql的结果,映射到/exception.jsp页面 --> <result name="sql">/exception.jsp</result> </global-results> <global-exception-mappings> <!-- 当Action抛出SQLException异常时,转入名为sql的结果 --> <exception-mapping exception="java.sql.SQLException" result="sql"/> </global-exception-mappings>
7、拦截器
原理:拦截器方法是通过代理的方式来调用的,当请求到达struts2的servletDispatcher时,struts2会查找配置文件,并根据其配置实例化对应的拦截器对象,然后串成一个列表,最后一个一个地调用列表中的拦截器。
动态代理是代理对象根据客户的需求做出不同的处理。当action请求到来的时候,会由系统的代理生成一个Action的代理对象(ActionProxy),由这个代理对象调用Action的execute()货指定的方法,并在strust.xml中查找与该Action对应的拦截器,如果有对应的拦截器,就在action的方法执行前(后)调用这些拦截器,没有就执行action方法。其中系统对于拦截器的调用,是通过ActionInvocation来实现的。
执行分析:Interceptor的接口中的intercept方法是实现整个拦截器机制的核心方法。而其所依赖的参数ActionInvocation是action的调度者。
actionInvocation中的invoke()方法是action代码真正的拦截点,它具备两个含义:
。如果拦截器栈中还有其他的Intercept,那么invoke()将调用堆栈中下一个Interceptor的执行;
。如果栈中只有Action,那么invoke将调用action执行
如何确保拦截器、action和result之间的执行顺序?
action层的4个不同的层次,分别是:拦截器、action、preresultListener和Result。保证了这些层次的有序调用和执行。
在intercept()方法中又对invoke()方法进行递归调用,ActionInvoke循环嵌套在intercept()中,一直到语句invocation.invoke()执行结束。这样,Interceptor又会按照刚开始执行的逆向顺序依次执行结束。一个有序链表,通过递归调用,变成了一个堆栈执行过程,将一段有序执行的代码变成了2段执行顺序完全相反的代码过程,从而巧妙地实现了AOP。这也就成为了Struts2的Action层的AOP基础。