为了讲解filter 和interceptor之间的区别,我会从 作用范围,作用原理,作用效果来说明两者之间的关系。
springMVC拦截器:
作用范围:拦截的目标只是controller ,也就是处理器(handler)。一般要继承 HandlerInterceptorAdapter,其中方法如下:
/* preHandle是一开始就 执行的 方法,并由返回的结果决定--> 后面的 拦截器是否执行 */
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
if(condition){
return true;
}else{
return false;
}
}
/* postHandle 是controller正常执行完成后,执行的方法。如果没有正常执行完成,所有的postHandle 方法都不会执行 */
/* 该方法在controller正常执行完成之后 才会执行,并且在 中央处理器 渲染页面之前 执行。 */
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("postHandle 执行!!!");
}
/* afterCompletion 是只要该拦截器的preHandle 方法执行的结果为true ,该方法就执行 */
/*
* afterCompletion 在所有的工作完成之后,且该该拦截器的 preHandle 返回的结果是 true ,该方法相当于
* try-catch-finally 中的finally ,用来释放一些资源。
*/
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("afterCompletion 执行!!!");
}
并且要在 spring-mvc.xml文件中配置:
<!--配置拦截器, 多个拦截器,顺序执行 ,路径拦截的相同也是互不影响的。-->
<mvc:interceptors>
<mvc:interceptor>
<!-- 匹配的是url路径, 如果不配置 或 /**,将拦截所有的Controller -->
<mvc:mapping path="/**" />
<bean class="interceptor.MyInterceptor"></bean>
</mvc:interceptor>
<!-- 当设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法 -->
</mvc:interceptors>
这里有必要展示一下web.xml 中的 DispatcherServlet的配置:
<servlet>
<servlet-name>mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:config/spring-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>mvc</servlet-name>
<url-pattern>/</url-pattern> <!-- 不可以用 /* 来代替所有的路径 -->
</servlet-mapping>
因为拦截器是在DispatcherServlet的基础上进一步处理的,这是因为只有经过DispatcherServlet处理后的路径并转发到相应的Controller上,这样同时也理解为springmvc框架处理的路径是 DispatcherServlet处理路径的子集。并且拦截器只能包装到controller上,无法直接拦截静态资源,或jsp、servlet等资源。另一方面,只要是满足路径的匹配,就会拦截,没有根据请求方式选择是否拦截的途径。
Filter:
使用的话要实现 javax.servlet.Filter 接口,
public class JspFilter implements Filter {
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
//首先将闯过来的值 扩展到大的子类
HttpServletRequest request=(HttpServletRequest)req ;
HttpServletResponse response=(HttpServletResponse)resp;
System.out.println("过滤之前");
chain.doFilter(request, response);
System.out.println("过滤之后");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化web.xml中的值,方便配值,比如填上排除过滤的相
}
}
在web.xml 中的配置:
<filter> <filter-name>myFilter</filter-name> <filter-class>filter.JspFilter</filter-class> </filter> <filter-mapping> <filter-name>myFilter</filter-name> <url-pattern>/*</url-pattern>
<!-- <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> <dispatcher>ERROR</dispatcher> --> </filter-mapping>
这里说明Filter的拦截方式:
<dispatcher>REQUEST</dispatcher> (默认的) :直接访问目标资源时,包括在地址栏中直接访问,表单提交,超链接,重定向,只要是在地址栏中可以看到目标资源路径就是 REQUEST
<dispatcher>FORWARD</dispatcher> :转发执行过滤器,包括requestDispatcher.forward()方法。以及<jsp:forward >标签都是转发访问。
<dispatcher>INCLUDE</dispatcher> :包含访问执行过滤器,包括requestDispatcher.include()方法。<jsp:include> 标签都是包含访问。
<dispatcher>ERROR</dispatcher> 当目标资源在web.xml中配置<error-page>中时,并且真的出现了异常,转发到目标资源时,就会执行过滤器。这些都是非常重要的配置。
相信大家从中可以了解一些新的见解,自己能力毕竟有限,希望大家指出不足之处。