Struts2源码试读1-filter
来源:互联网 发布:兄贵pat it 编辑:程序博客网 时间:2024/05/01 05:11
一直没对struts好好研究过,最近拿出来好好看看。
首先,struts1和struts2还是有很大区别的,鉴于struts1的项目越来越少,就直接跳过。struts2是WebWork的升级版,不过与其这么说不如说struts2是webwork的再封装,让他“看上去”更像struts,但是骨子里却是webwork。
struts属于apache的开源项目,可以直接从http://struts.apache.org/上下载源码包,不过如果想了解更多包括WebWork的内容则需要进一步下载webword的源码包,地址为http://www.opensymphony.com/xwork/download.action。
这边不过多赘述struts2的每个包有什么作用了,从项目运行的开始一步步分析struts2是如何运行并得到结果的。
struts说白了也还是个web项目,所以没什么特别的东西。在我的理解,框架只是让我们更加方便、快捷的开发,框架里屏蔽了部分复杂却又不实用的东西,增加了部分常用东西。看一个web项目,首先就是查看web.xml中的定义。
<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>
上面就是常见的struts的xml配置,而关键就是配置了一个Filter,过滤器。顾名思义,过滤器就是用于过滤请求的,它的功能,个人觉得可以近似为一个uri rewrite,当然,它还只属于一个代码的入口,不像WebServer的重写规则那么强大,但功能上是很近似的。
所以在Filter里,可能会做一些错误页重定向(例如50X,40X等页面的定向),当然也可以根据uri判断是哪个接口,调用并返回,这就是一般MVC框架单一入口的思想。
package demo.struts.filter;import javax.servlet.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.util.Date;public class MyFilter implements Filter{ public void destroy() { // TODO Auto-generated method stub } public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { //将ServletRequest变成HttpServletRequest HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; // TODO Auto-generated method stub // System.out.println("in Filter" + (new Date()).getTime()); //这里使用uri获取当前请求 System.out.println(RequestUtils.getUri(request)); //真正的struts通过namespace和actionName区分action的name和对应的类,通过method区分调用的方法 chain.doFilter(request, response);//这句是关键,表示接口放行,通过filterChain执行 } public void init(FilterConfig filterConfig) throws ServletException { // TODO Auto-generated method stub System.out.println("in init" + (new Date()).getTime()); }}上面给出了一个最简单的Filter的写法,首先Filter需要复写接口Filter,并重写init、doFilter、destroy方法。init方法在项目启动时运行,destroy在项目结束时运行(可以认为是构造和析构),比较关键的是doFilter方法,该方法在所有http请求时都会运行。
不难想到,首先通过获取uri和struts.xml的配置获得ActionMap,如果map成功则执行ActionClass,否则就执行chain.doFilter(request, response);
当然,实际的struts也是这么实现的。
package org.apache.struts2.dispatcher.ng.filter;import org.apache.struts2.StrutsStatics;import org.apache.struts2.dispatcher.Dispatcher;import org.apache.struts2.dispatcher.mapper.ActionMapping;import org.apache.struts2.dispatcher.ng.ExecuteOperations;import org.apache.struts2.dispatcher.ng.InitOperations;import org.apache.struts2.dispatcher.ng.PrepareOperations;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;/** * Executes the discovered request information. This filter requires the {@link StrutsPrepareFilter} to have already * been executed in the current chain. */public class StrutsExecuteFilter implements StrutsStatics, Filter { protected PrepareOperations prepare; protected ExecuteOperations execute; protected FilterConfig filterConfig; public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; } protected synchronized void lazyInit() { if (execute == null) { InitOperations init = new InitOperations(); Dispatcher dispatcher = init.findDispatcherOnThread(); init.initStaticContentLoader(new FilterHostConfig(filterConfig), dispatcher); prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher); execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher); } } public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; if (excludeUrl(request)) { chain.doFilter(request, response); return; } // This is necessary since we need the dispatcher instance, which was created by the prepare filter if (execute == null) { lazyInit(); } ActionMapping mapping = prepare.findActionMapping(request, response); //if recusrion counter is > 1, it means we are in a "forward", in that case a mapping will still be //in the request, if we handle it, it will lead to an infinte loop, see WW-3077 Integer recursionCounter = (Integer) request.getAttribute(PrepareOperations.CLEANUP_RECURSION_COUNTER); if (mapping == null || recursionCounter > 1) { boolean handled = execute.executeStaticResourceRequest(request, response); if (!handled) { chain.doFilter(request, response); } } else { execute.executeAction(request, response, mapping); } } private boolean excludeUrl(HttpServletRequest request) { return request.getAttribute(StrutsPrepareFilter.REQUEST_EXCLUDED_FROM_ACTION_MAPPING) != null; } public void destroy() { prepare = null; execute = null; filterConfig = null; }}
当然在初始化时,struts使用了lazyinit模式,减轻在初始时的压力,节省资源。延迟加载的主要是两个对象,prepare和execute,两个都是工具性质的操作类,一个是用于获取ActionMapper的,一个用于执行Action的。
Filter作为struts的入口,是所有接口的一个过滤器,(当然也可以理解为一个拦截器,此处是为了过滤struts请求,交给struts处理)。过滤出请求之后,根据请求的uri定位到struts资源,唤起ActionSupport的execute方法。
- Struts2源码试读1-filter
- struts2源码试读——FilterChain、PrepareOperations
- zookeeper curator 源码试读
- EventBus 源码试读(一)
- EventBus 源码试读(二)
- EventBus 源码试读(三)
- struts2 filter
- Struts2 Filter
- Struts2源码阅读(二)_ActionContext及CleanUP Filter
- Struts2源码阅读(二)_ActionContext及CleanUP Filter
- Struts2源码阅读(二)_ActionContext及CleanUP Filter
- Struts2源码阅读(二)_ActionContext及CleanUP Filter .
- Struts2源码阅读(二)_ActionContext及CleanUP Filter
- Struts2源码阅读(二)_ActionContext及CleanUP Filter
- Struts2 源码分析——过滤器(Filter)
- 小问题1:Exception starting filter struts2
- Struts2.0 Filter错误
- Exception starting filter struts2
- 30天自制操作系统之第13天 定时器(2)
- Android Service在测试工程中使用的注意事项
- 要想快,先慢下来
- 使用aireplay-ng时报错“mon0 is on channel ×, but the AP uses channel ×”
- Ubuntu中解决解压zip文件中文乱码问题
- Struts2源码试读1-filter
- 【奇偶剪枝】HDU 1010 Tempter of the Bone
- memcpy的自定义实现的源代码
- hdu oj 2544 最短路(最短路径)
- nyoj 107
- 键盘快捷键
- 使用BlockingQueue进行多线程间的异步通信
- Java 同步与锁
- 字典树