p { margin-bottom: 0.08in; }h1 { margin-bottom: 0.08in; }h1.western { font-family: "Times New Roman",serif; }h1.cjk { font-family: "DejaVu Sans"; }h1.ctl { font-family: "DejaVu Sans"; }h3 { margin-bottom: 0.08in; }a:link { }
知识回顾:
Struts 与 webwork 已合并为 Struts2 框架 ,Struts2 框架良好的扩展性与简洁性使其适用于任何规模的企业 web 程序的开发 . 本节我们将向大家展示 Struts2 框架的结构
在 Struts2 中一个请求的生存周期:
1. 用户发送请求 : 用户为访问资源向服务器发送请求 .
2. FilterDispatcher 决定适当的 action : FilterDispatcher 接受请求然后决定调用适当的 action
3. 调用拦截器 : 配置拦截器来应用常用的功能如工作流 , 验证 , 文件上传等 , 都是自动应用于请求的 .
4. action 的执行 : 然后 action 将被执行来调用诸如存储数据、检索数据之类的数据库相关操作 .
5. 呈递输出 : 结果呈递到输出
6. 返回请求 : 请求通过拦截器按照相反的顺序返回 , 返回的请求可以允许我们执行一些清理或额外的处理
7. 向用户展示结果 : 控制权最终回归到输出结果至用户浏览器的 Servlet 容器
图 :Struts2 中请求流程的高度概括
Struts2 结构 :
Struts2 框架拥有良好的简洁性与易扩展的前端控制器 , 基于很多像 Java Filters, Java Beans, ResourceBundles, XML 等标准技术 .
对于模型层来说 ,Struts2 可以使用任何数据访问技术 , 像 JDBC, EJB, Hibernate 等 , 对于视图层来说 ,Struts2 可以与 JSP, JTL, JSF, Jakarta Velocity Engine, Templates, PDF, XSLT 等整合 .
异常处理 :
Struts2 允许我们定义异常处理器和拦截器
l 异常处理器
异常处理器允许我们定义基于局部和全局的异常处理程序 .Struts2 捕获到异常后会将恰当的信息和异常的详情显示在我们指定的页面上 .
l 拦截器
拦截器详细说明了一个 action 的请求流程的生存周期 . 配置的拦截器对请求实现了一些常用的功能如工作流 , 验证等 .
Struts2 结构
下图描述了 Struts2 的结构 , 同时展示了初始请求如何转到像 Tomcat 这类的 serlet 容器 , 然后通过过滤链
图 : Struts2 结构
过滤器链包括 :
l Action ContextCleanUp filter :
Action ContextCleanUp filter 是可选的 , 当与其他的技术如 SiteMash 插件整合的时候会很有帮助 .
l FilterDispatcher :
接着 FilterDispatcher 被调用 , 然后依次调用 ActionMapper 来决定是不是要引用一个 action. 如果一个 action 需要被引用 , FilterDispatcher 将托付 ActionProxy 来管理
l ActionProxy :
Action 代理能从初始化自 struts.xml 的配置文件管理器那得到帮助 , 接着 ActionProxy 创建一个实现了命令模式的 ActionInvocation,ActionInvocation 在处理的过程中调用拦截器 ( 如果配置了 ) 然后调用 Action ActionInvocation 寻找恰当的结果 , 然后结果呈递到 JSP 或者模板上 .
之后拦截器再按照相反的顺序执行了一遍 , 最终响应通过配置在 web.xml 中的过滤器返回 . 如果配置了 ActionContextCleanUp filter, FilterDispatcher 不会清理线程局部 ActionContext. 如果 ActionContextCleanUp filter 没有被配置 , FilterDispatcher 会清理所有当前的线程局部 .
Struts2的工作是基于 filter的,其核心控制器就是一个 filter: FilterDispatcher。框架流程大致如下:
1、客户端初始化一个请求;
2、这个请求经过一系列的过滤器 Filter
3、 FilterDispatcher被调用, FilterDispatcher根据 ActionMapper来决定这个请求是否调用某个 Action;
4、 ActionMapper决定需要调用某个 Action, FilterDispatcher把请求的处理交给 ActionProxy;
5、 ActionProxy通过 Configuration Manager询问框架的配置文件,找到需要调用的 Action类;
6、 ActionProxy创建一个 ActionInvocation的实例。
7、 ActionInvocation实例使用命名模式来调用,在调用 Action的过程前后,会调用拦截器 Intercepter
8、一旦 Action执行完毕, ActionInvocation负责根据 struts.xml中的配置找到对应的返回结果。
显然, filter比 struts2 interaptor范围要大。 Filter除了过滤请求外通过通配符可以保护页面,图片,文件等等,而 Interceptor只能过滤请求。
对于 filter:
使用方法是创建一个类 XXXFilter实现 Filter接口,并在该类中的 doFilter方法中声明过滤规则,然后在配置文件 web.xml中声明他所过滤的路径
对于 Interceptor
使用方法也是创建一个类 XXXInterceptor实现 Interceptor 接口 ,在该类中 intercept方法写过滤规则,不过与 strut.xml结合使用。
另外一些不同:
1. filter基于回调函数, doFilter方法就是回调函数,而 interceptor则基于java本身的反射机制 ,这是两者最本质的区别。
2. filter是依赖于 servlet容器的,即只能在 servlet容器中执行。而 interceptor与 servlet容器无关。
3. Filter的过滤例外一般是在加载的时候在 init方法声明 ,而 Interceptor可以通过在 xml声明是 guest请求还是 user请求来辨别是否过滤
前段时间参与一个项目,过滤器用的是 Interceptor 觉得比以前用的 Filter 好用很多,现在拿出来比较一下
Filter
该过滤器的方法是创建一个类 XXXFilter 实现此接口,并在该类中的 doFilter 方法中声明过滤规则,然后在配置文件 web.xml 中声明他所过滤的路径
<filter>
<filter-name>XXXFilter</filter-name>
<filter-class>
com.web.util.XXXFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>XXXFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
Interceptor
该过滤器的方法也是创建一个类 XXXInterceptor 实现此接口 , 在该类中 intercept 方法写过滤规则,不过它过滤路径的方法和 Filter 不同,它与 strut.xml 结合使用,
创建一个 strus.xml 的子配置文件 struts-l99-default.xml ,它继承与 struts2 的 struts-default ,此配置文件是其他子配置文件的父类,只要是继承与该文件的配置文件所声明的路径都会被它过滤 如下
<package name="XXX-default" namespace="/" extends="struts-default">
<interceptors>
<interceptor name="authentication" class="com.util.XXXInterceptor" />
<interceptor-stack name="user">
<interceptor-ref name="defaultStack" />
<interceptor-ref name="authentication" />
</interceptor-stack>
<interceptor-stack name="user-submit">
<interceptor-ref name="user" />
<interceptor-ref name="token" />
</interceptor-stack>
<interceptor-stack name="guest">
<interceptor-ref name="defaultStack" />
</interceptor-stack>
<interceptor-stack name="guest-submit">
<interceptor-ref name="defaultStack" />
<interceptor-ref name="token" />
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="user" />
</package>
比较一 ,filter 基于回调函数,我们需要实现的 filter 接口中 doFilter 方法就是回调函数,而 interceptor 则基于java本身的反射机制 , 这是两者最本质的区别。
比较二 ,filter 是依赖于 servlet 容器的,即只能在 servlet 容器中执行,很显然没有 servlet 容器就无法来回调 doFilter 方法。而 interceptor 与 servlet 容器无关。
比较三, Filter 的过滤范围比 Interceptor 大 ,Filter 除了过滤请求外通过通配符可以保护页面,图片,文件等等,而 Interceptor 只能过滤请求。
比较四, Filter 的过滤例外一般是在加载的时候在 init 方法声明 , 而 Interceptor 可以通过在 xml 声明是 guest 请求还是 user 请求来辨别是否过滤