过滤器分析
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern> <!--过滤器应用的范围,如果为/*,则如果域名设置形如/a 或/abc等都会调用过滤器-->
<pre> </filter-mapping>
1、Servlet的一种,因此也有init和destroy方法,还有一个服务方法,只是这里提供的服务是过滤;
2、public void init(FilterConfig filterConfig) throws ServletException由 Web 容器调用,指示将放入服务中的过滤器。servlet 容器只在实例化过滤器之后调用一次 init 方法。在要求过滤器做任何过滤工作之前,init 方法必须成功完成。
3、Filter 用 doFilter 方法执行过滤。每个 Filter 都有对 FilterConfig 对象的访问权,可从该对象获得其初始化参数以及对它可以使用的 ServletContext 的引用,以便为过滤任务加载所需的资源。
<span style="font-family:Microsoft YaHei;"> public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws java.io.IOException, ServletException{
chain.doFilter(req,resp); //执行Servlet操作;
}</span>
每次由于对链末尾的某个资源的客户端请求而通过链传递请求/响应对时,容器都会调用 Filter 的 doFilter 方法。传入此方法的 FilterChain 允许 Filter 将请求和响应传递到链中的下一个实体。
此方法的典型实现遵循以下模式:
1. 检查请求
2. 有选择地将带有自定义实现的请求对象包装到用于输入过滤的过滤器内容或头中
3. 有选择地将带有自定义实现的响应对象包装到用于输出过滤的过滤器内容或头中
4. a) 既可以使用 FilterChain 对象 (chain.doFilter()) 调用链中的下一个实体,
4. b) 也可以不将请求/响应对传递给过滤器链中的下一个实体,从而阻塞请求处理
5. 在调用过滤器链中的下一个实体之后直接设置响应上的头。
4、Servlet过滤器是在Java Servlet 2.3 规范中定义的,它是一种可以插入的Web组件,它能够对Servlet 容器的接收到的客户端请求和向客户端发出的响应对象进行截获,过滤器支持对Servlet程序和JSP页面的基本请求处理功能,如日志、性能、安全、会话处理、XSLT转换等。5、Servlet过滤器本身不产生请求和响应,它只提供过滤作用,Servlet过滤器能够在Servlet程序(JSP页面)被调用之前检查request对象,修改请求头和请求内容,在Servlet程序(JSP页面)被调用之后,检查response对象,修改响应头和响应内容
6、Servlet过滤器是 Servlet 程序的一种特殊用法,主要用来完成一些通用的操作,如编码的过滤、判断用户的登录状态。过滤器使得Servlet开发者能够在客户端请求到达Servlet资源之前被截获,在处理之后再发送给被请求的Servlet资源,并且还可以截获响应,修改之后再发送给用户。而Servlet监听器可以监听客户端发出的请求、服务器端的操作,通过监听器,可以自动激发一些操作,如监听在线人数。
总结:
需要自动执行的操作需要过滤器;
完整的Filter流程是:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。
Filter有如下几个作用:
1. 在HttpServletRequest到达Servlet之前,拦截客户的HttpServletRequest请求;
2. 根据需要检查HttpServletRequest,也可以对HttpServletRequest头和数据进行修改;
3. 在HttpServletResponse到达客户端之前,拦截HttpServletResponse;
4. 根据需要检查HttpServletResponse,也可以对HttpServletResponse头和数据进行修改;
5. Filter可以拦截多个请求和响应,一个请求和响应可以被多个Filter拦截。
Filter有以下几个种类:
1. 用户授权的Filter:Filter负责检查用户的请求,根据请求过滤用户的非法请求;
2. 日志Filter:详细记录用户的请求信息;
3. 负责解码的Filter:对非标准编码的解码;
4. 能改变XML内容的XSLT Filter等。
对于某类配置节而言,与它们出现的顺序是有关的。以 filter 为例,web.xml 中当然可以定义多个 filter,与 filter 相关的一个配置节是 filter-mapping,这里一定要注意,对于拥有相同 filter-name 的 filter 和 filter-mapping 配置节而言,filter-mapping 必须出现在 filter 之后,否则当解析到 filter-mapping 时,它所对应的 filter-name 还未定义。
web 容器启动时初始化每个 filter 时,是按照 filter 配置节出现的顺序来初始化的,当请求资源匹配多个filter-mapping 时,filter 拦截资源是按照 filter-mapping 配置节出现的顺序来依次调用 doFilter() 方法的。
注释*******************************************************************************************************************************************************
7、strust2 url-pattern三种写法
完全匹配
<url-pattern>/test/list.do</url-pattern>
<!-- 必须以一个“/”开头,可以有扩展名,但不是必需的。 -->
路径匹配
<url-pattern>/*</url-pattern> struts2匹配根路径下的全部请求
<!-- 必须以一个“/”开头,目录可以是虚拟或实际的,总是以一个“/*”结束 -->
扩展名匹配
<url-pattern>*.do</url-pattern> struts1
<url-pattern>*.html</url-pattern> 匹配全部html结尾的请求
<url-pattern>*</url-pattern> 不能用*,否则报错
<!-- 必须以“*”加“.”加扩展名的形式 -->
8、servlet-mapping的重要规则:容器会首先查找完全匹配,如果找不到,再查找目录匹配,如果也找不到,就查找扩展名匹配。
如果一个请求匹配多个“目录匹配”,容器会选择最长的匹配。
9、servlet容器对url的匹配过程:
当一个请求发送到servlet容器的时候,容器先会将请求的url减去当前应用上下文的路径作为servlet的映射url,比如我访问的
是http://localhost/test/aaa.html,我的应用上下文是test,容器会将http://localhost/test去掉,剩下的/aaa.html部分拿来做servlet的映射匹配。这个映射匹配过程是有顺序的,而且当有一个servlet匹配成功以后,就不会去理会剩下的servlet了(filter不同,后文会提到)。其匹配规则和顺序如下:
1、精确路径匹配。
例子:比如servletA 的url-pattern为 /test,servletB的url-pattern为 /* ,这个时候,如果我访问的url为http://localhost/test ,这个时候容器就会先进行精确路径匹配,发现/test正好被servletA精确匹配,那么就去调用servletA,也不会去理会其他的servlet了。
2、最长路径匹配。
例子:servletA的url-pattern为/test/*,而servletB的url-pattern为/test/a/*,此时访问http://localhost/test/a时,容器会选择路径最长的servlet来匹配,也就是这里的servletB。
3、扩展匹配,如果url最后一段包含扩展,容器将会根据扩展选择合适的servlet。例子:servletA的url-pattern:*.action
4、如果前面三条规则都没有找到一个servlet,容器会根据url选择对应的请求资源。如果应用定义了一个default servlet,则
容器会将请求丢给default servlet(什么是default servlet?后面会讲)。根据这个规则表,就能很清楚的知道servlet的匹配过程,所以定义servlet的时候也要考虑url-pattern的写法,以免出错。
对于filter,不会像servlet那样只匹配一个servlet,因为filter的集合是一个链,所以只会有处理的顺序不同,而不会出现只选择一个filter。Filter的处理顺序和filter-mapping在web.xml中定义的顺序相同。
10、总结:
在web.xml文件中,以下语法用于定义映射:
以”/’开头和以”/*”结尾的是用来做路径映射的。
以前缀”*.”开头的是用来做扩展映射的。
“/” 是用来定义default servlet映射的。
剩下的都是用来定义详细映射的。比如: /aa/bb/cc.action
所以,为什么定义”/*.action”这样一个看起来很正常的匹配会错?因为这个匹配即属于路径映射,也属于扩展映射,导致容器无法判断。
注释部分转载自http://hi.baidu.com/horsewhite/item/9a38c29d7aed67cbb62531c4的<web.xml中<url-pattern>的写法>部分。感谢他的分享 ********************************************************************************************************************************************************注释