Struts架构
首先客户端通过HttpServletRequest向Servlet容器(Tomcat)发送请求,这个请求会经过相关的过滤器(ActionContextCleanUp和其他过滤器),到达核心控制器,在Struts2.1.3之后,核心控制器变为了StrutsPrepareAndExcuteFilter。
经过核心控制器后,访问ActionMapping来判断该请求是否要执行Action。若需要执行Action则会由核心控制器去访问ActionProxy,Action代理会通过Configuration Manager对象配置管理器,来加载Struts的核心配置文件struts.xml。
如果在配置文件中找到了需要执行的Action则通过ActionProxy创建一个Action Invocation实例。在调用Action之前,还会依次执行其中的拦截器,直到Action。
在Action中返回一个result结果,在结果中反馈一个字符串。之后需要再反向执行一遍拦截器,才会进行最终的相应,通过HttpServletResponse反馈给用户。
这样就形成了Struts2整个请求相应的流程。
什么是拦截器
- Struts的核心功能都是通过拦截器来实现的,在Action执行之前或之后,实现某一项功能,例如:数据转移,类型转换,数据校验。
- 拦截器栈:从结构上看,是由多个拦截器来实现的;从功能上看,拦截器栈本身就是一个拦截器。
拦截器的工作原理
拦截器的执行在本质上就是一个递归的过程。
自定义拦截器
- 实现Intercept接口
- void init():初始化拦截器所需的资源
- void distory():释放init()中分配的资源
- String Intercept(ActionInvocation ai) throws Exception:实现拦截器功能;利用ActionInvocation获取action状态;返回result字符串作为逻辑视图。
- 继承AbstractInterceptor类
- 提供了init()和destory()的空方法;
- 只需要实现Intercept()方法即可。
一般常用第二类方法来定义拦截器。
Struts2内建拦截器
- params:负责将请求参数设置为Action属性;
- StaticParams:将配置文件中Action的子元素param设置为Action属性;
- servletConfig:将原Servlet API中的对象注入到Action中,需要实现接口方法;
- fileUpload:对文件上传提供支持,将文件和元数据设置到Action配置中;
- exception:捕获异常,并将异常映射到用户自定义的 错误界面;
- validation:校验用户的输入参数。
Struts内建拦截器,都存储在struts2-core-2.3.37.jar包下struts-default.xml配置文件中,可以在配置文件查找到所有拦截器和已经写好的拦截器栈。
<interceptors>
<interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
<interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>
<interceptor name="chain" class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>
······
</interceptors>
在struts-default.xml文件中定义了一个defaultStack拦截器栈,并将其指定为默认拦截器。
<interceptor-stack name="defaultStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="prepare"/>
········
</interceptor-stack>
如果struts.xml文件中package包配置是继承struts-default的话且没有指定拦截器的时候,会按照核心文件中<default-interceptor-ref name="defaultStack"/>
加载所有默认的拦截器,而且加载拦截器的顺序也是有着重要的意义(如果struts.xml中指定了拦截器,就需要手动引入)。