`

FilterDispatcher处理流程

阅读更多
9.4  Struts 2的核心机制

Struts 2的处理流程已经和Struts 1大相径庭了,但是和WebWork比较相似,这都是因为Struts 2和WebWork合并的缘故,并吸取了WebWork大部分设计思想。下面讲解Struts 2的核心流程,以及其他一些处理机制。

9.4.1  FilterDispatcher处理流程

在Struts 2中,最重要的一个类是org.apache.struts2.dispatcher.FilterDispatcher,从前面的示例可以看出,用户通过浏览器提交一个(HttpServletRequest)请求后,请求被在web.xml中定义的过滤器FilterDispatcher拦截,在FilterDispatcher中主要经过大概3层过滤器的处理,分别是ActionContext CleanUp、其他过滤器(Othter Filters、SiteMesh等)、FilterDispatcher。

在FilterDispatcher过滤器中首先询问ActionMapper是否需要调用某个Action来处理请求,如果ActionMapper决定需要调用某个Action,FilterDispatcher则把请求的处理交给ActionProxy,ActionProxy通过配置文件struts.xml找到需要调用的Action类,然后ActionProxy创建一个ActionInvocation实例并调用该Action,但在调用之前,ActionInvocation会根据配置加载Action相关的所有Interceptor,等Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果result。

在详细介绍FilterDispatcher之前,先讲解一下Servlet中过滤器的概念,以使读者对此有一个深入的认识。过滤器提供一种面向对象的模块化机制,用以将公共任务封装到可插入的组件中,这些组件通过一个配置文件来声明并动态地处理。实现一个过滤器需要3个步骤:首先编写过滤器实现类的程序,然后把该过滤器添加到web.xml 中声明,最后把过滤器与应用程序一起打包并部署。

过滤器 API 一共包含 3 个简单的接口:Filter、FilterChain 和 FilterConfig。过滤器类必须实现 Filter 接口:

init():这个方法在容器实例化过滤器时被调用,它主要设计用于使过滤器为处理做准备。容器为这个方法传递一个FilterConfig,其中包含有配置信息。

doFilter():与Servlet拥有一个service()方法来处理请求一样,过滤器拥有单个用于处理请求和响应的方法doFilter()。这个方法接收3个输入参数: ServletRequest、ServletResponse和FilterChain。FilterChain对于正确的过滤操作至关重要,doFilter()方法必须调用FilterChain的doFilter()方法,除非该方法用来拦截以后的下游处理。

destroy():该方法由容器在销毁过滤器实例之前调用,以便能够执行任何必需的清理代码。

过滤器通过 web.xml 文件中的两个XML标签来声明。<filter>标签定义过滤器的名称,并且声明实现类和init()参数。<filter-mapping>标签将过滤器与Servlet或URL模式相关联。<filter>标签负责把一个过滤器名和一个特定的类关联起来,这种关联是通过<filter-name>和<filter-class>元素指定的。<filter>必须有一个<ulr-pattern>或者<servlet-name>元素,可以通过<ulr-pattern>来指定通配符,将过滤器应用到Web资源范围;也可以通过<servlet-name>将过滤器指定到某一个特定的Servlet上。应该注意这些声明的顺序,所引用的过滤器名必须在前面的过滤器定义中给出。下面给出一个过滤器配置的示例代码。

<!--编码过滤器--> 
<filter> 
<filter-name>SetCharacterEncoding</filter-name> 
<filter-class>  com.gd.web.filter.GdSetCharacterEncodingFilter  </filter-class> 
<init-param> 
<param-name>encoding</param-name> 
<param-value>GBK</param-value> 
</init-param> 
<init-param> 
<param-name>ignore</param-name> 
<param-value>true</param-value> 
</init-param> 
</filter> 
<!--过滤所有的访问--> 
<filter-mapping> 
<filter-name>SetCharacterEncoding</filter-name> 
<url-pattern>/*</url-pattern> 
</filter-mapping>
然也可以配置多个过滤器,多个过滤器将按照配置的顺序执行。

通过上面的介绍,相信读者对过滤器会有一个深入的了解。打开FilterDispatcher的源代码可以看到,FilterDispatcher也同样遵循这样的原则,同样实现了init()、doFilter ()、destroy()这3个接口,在init()接口里主要实现了创建Dispatcher和设置默认包的功能,示例代码如下:

public void init(FilterConfig filterConfig) throws ServletException {  
try {  this.filterConfig = filterConfig;  
//初始化日志  
initLogging();  
//创建一个Dispatcher  
dispatcher = createDispatcher(filterConfig);  
dispatcher.init();  
dispatcher.getContainer().inject(this);  
//设定默认包  
staticResourceLoader.setHostConfig(new FilterHostConfig(filterConfig));  
} finally {  
ActionContext.setContext(null);  
}  
} 


在destroy()接口里主要实现了销毁Dispatcher和上下文的功能,示例代码如下: 
public void destroy() {  
//如果Dispatcher为空,则正常结束  
if (dispatcher == null) {  
log.warn("something is seriously wrong, Dispatcher is not initialized (null) ");  
} else {  
try {  
//销毁Dispatcher  dispatcher.cleanup();  
} finally {  
ActionContext.setContext(null);  
}  
}  
} 

在doFilter()接口里主要实现了创建Dispatcher和设置默认包的功能,示例代码如下:

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws   IOException, ServletException {  
//获取用户请求的request  
HttpServletRequest request = (HttpServletRequest) req;  HttpServletResponse response = (HttpServletResponse) res;  ServletContext servletContext = getServletContext();  
//加上时间戳  
String timerKey = "FilterDispatcher_doFilter: ";  
try {  
//设定上下文或栈  
ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).  createValueStack();  
ActionContext ctx = new ActionContext(stack.getContext());  ActionContext.setContext(ctx);  
//重新封装request,记录使用的语言、编码方式、是否是上传文件等  UtilTimerStack.push(timerKey);  
request = prepareDispatcherAndWrapRequest(request, response);  
//获取ActionMapping  ActionMapping mapping;  
try {  
mapping = actionMapper.getMapping(request, dispatcher.getConfigurationManager());  
} catch (Exception ex) {  
//如果没有找到合适的ActionMapping,则抛出异常  
dispatcher.sendError(request, response, servletContext,HttpServletResponse.  SC_INTERNAL_SERVER_ERROR, ex);  return;  
}  
//如果没有配置ActionMapping,则判断是否为静态资源  
if (mapping == null) {  
//获取访问请求的路径  
String resourcePath = RequestUtils.getServletPath(request);  
if ("".equals(resourcePath) && null != request.getPathInfo()) {  resourcePath = request.getPathInfo();  
}  
//判断是否为静态资源  
if (staticResourceLoader.canHandle(resourcePath)) {  staticResourceLoader.findStaticResource(resourcePath, request, response);  
} else {  
// 如果不是,则继续执行下一个过滤器  
chain.doFilter(request, response);  
}  
return;  
}  

//在正常情况下,调用serviceAction方法  
dispatcher.serviceAction(request, response, servletContext, mapping);  
//清空上下文和时间戳  
} finally {  
try {  
ActionContextCleanUp.cleanUp(req);  
} finally {  
UtilTimerStack.pop(timerKey);  
}  
}  
} 
分享到:
评论

相关推荐

    Struts 2详细工作流程

    核心控制器FilterDispatcher是Struts 2框架的基础,包含了框架内部的控制流程和处理机制。业务控制器Action和业务逻辑组件是需要用户来自己实现的。用户在开发Action和业务逻辑组件的同时,还需要编写相关的配置文件...

    struts2流程与流程图

     FilterDispatcher询问ActionMapper是否需要调用某个Action来处理这个(HttpServlet Request)请求,如果ActionMapper决定需要调用某个Action,FilterDispatcher则把请求的处理交给ActionProxy。  ActionProxy...

    Struts2详细工作流程

    核心控制器FilterDispatcher是Struts 2框架的基础,包含了框架内部的控制流程和处理机制。业务控制器Action和业务逻辑组件是需要用户来自己实现的。用户在开发Action和业务逻辑组件的同时,还需要编写相关的配置文件...

    Struts2的工作原理和流程

    4 如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy 5 ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类 6 ActionProxy创建一个...

    Struts2基本原理

    核心控制器FilterDispatcher是Struts 2框架的基础,包含了框架内部的控制流程和处理机制。业务控制器Action和业务逻辑组件是需要用户来自己实现的。用户在开发Action和业务逻辑组件的同时,还需要编写相关的配置...

    SSH的jar包.rar

    下面粗略的分析下FilterDispatcher工作流程和原理:FilterDispatcher进行初始化并启用核心doFilter。 Hibernate 的原理 1.通过Configuration().configure();读取并解析hibernate.cfg.xml配置文件 2.由hibernate....

    struts2开发文档

    struts2的所有知识点 流程 原理 一个请求在Struts2框架中的处理大概分为以下几个步骤: 1 客户端初始化一个指向Servlet容器(例如Tomcat)的请求; 2 这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个...

    Struts2请求处理流程及源码分析

    a)客户端初始化一个指向Servlet容器...d)请求经过核心过滤器FilterDispatcher,执行doFilter方法,在该方法中,询问ActionMapper来决定这个请求是否需要调用某个Action;e)如果ActionMapper决定需要调用某个Action,则

    Java Struts 实现拦截器

    Struts2的处理流程: • 客户端产生一个HttpServletRequest的请求,该请求被提交到一系列的标准过滤器(Filter)组建链中(如ActionContextCleanUp:它主要是清理当前线程的ActionContext、Dispatcher,...

    java面试题

    Struts2以核心控制器FilterDispatcher为基础,包含了框架内部的控制流程和处理机制。 Hibernate工作原理,Hibernate数据持久化? 答:Hibernate工作原理: 1:读取并解析映射信息,创建SessionFactory 2:打开...

    SSH-Jsp期末考试简答题带答案

    Struts2 的工作流程如下:客户端浏览器发出HTTP请求,程序根据web.xml配置,FilterDispatcher接收吸收该请求,根据struts.xml配置,找到需要调用的Action类和方法,并通过IoC方式,将值注入给Action。Action调用业务...

    J2EE应用开发详解

    141 9.1.2 JSF应用程序配置 142 9.2 一个简单的JSF应用 142 9.2.1 JSF应用程序开发步骤 143 9.2.2 用户登录实例 143 9.3 JSF应用程序架构 147 9.3.1 JSF请求处理生命周期 147 9.3.2 JSF事件驱动模型 148 9.3.3 JSF...

Global site tag (gtag.js) - Google Analytics