一、基本概念
1、拦截器与过滤器
1、拦截器是使用JDK动态代理实现的,拦截的是对应调用方法的拦截
2、过滤器是使用Filter实现的,拦截是的request对象
2、Spring MVC 拦截器的配置和应用
- Spring MVC也可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能,自定义的拦截器必须实现 Handlerlnterceptor 接口
- preHandle():这个方法在业务处理器 处理请求之前被调用,在该方法中对用户请求request进行处理。
如果程序员决定该拦截器对请求进行拦截处理后还要调用其他的拦截器,或者是业务处理器去进行处理,则返回 true;如果程序员决定不需要再调用其他的组件去处理请求,则返回 false。 - postHandle():这个方法在业务处理器处理完请求后,但是 DispatcherServlet 向客户端返回响应前被调用,在该方法中对用户请求 request 进行处理。
- afterCompletion():这个方法在 DispatcherServlet 完全处理完请求后被调用,可以在该方法中进行一些资源清理的操作。
二、web.xml 中 spring配置文件的路径配置
1、默认方式
[servlet-name]-servlet.xml 比如:mocSpringMvc.xml
2、 命名空间 namespace
该方式必须配置文件在放入在web-inf目录下。
在 <servlet> 的配置添加初始参数 属性:namespace 值:配置文件名
3、通过:contextConfigLocation
在 <servlet> 的配置添加初始参数
属性:contextConfigLocation 值:文件路径
经测试在 IntelliJ 中直接把配置文件放在 resources 目录下即可,名称任意。
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 命名空间方式 -->
<!--<init-param>-->
<!--<param-name>namespace</param-name>-->
<!--<param-value>mocSpringMVC</param-value>-->
<!--</init-param>-->
<!-- contextConfigLocation方式 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:mocSpringMvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
三、拦截器实例
1、spring配置
<!-- 配置自定义扫描包 -->
<context:component-scan base-package="com.moc.web"></context:component-scan>
<!-- 拦截器的注册 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- * 只能匹配一级目录, ** 能匹配多级目录 -->
<mvc:mapping path="/user/**"></mvc:mapping>
<!--exclude-mapping在所有拦截中进行排除,一般在有通配符会有意义。-->
<mvc:exclude-mapping path="/user/updatepwd"></mvc:exclude-mapping>
<mvc:exclude-mapping path="/user/ground/*"></mvc:exclude-mapping>
<bean class="com.moc.core.LoginInterceptor1"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/user/**"/>
<mvc:exclude-mapping path="/user/ex/*"/>
<bean class="com.moc.core.LoginInterceptor2"/>
</mvc:interceptor>
</mvc:interceptors>
<!-- 视图解析器:映射物理路径 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
2、拦截器类
// 拦截器1
public class LoginInterceptor1 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("拦截器1的 preHandle 方法");
return true; // 为false时会终止所有的请求
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("拦截器1的 postHandle 方法");
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("拦截器1的 afterCompletion 方法");
}
}
// 拦截器2
public class LoginInterceptor2 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("拦截器2的 preHandle 方法");
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("拦截器2的 postHandle 方法");
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("拦截器2的 afterCompletion 方法");
}
}
3、控制器业务处理
@Controller
@RequestMapping("/user")
public class UserController {
//查询用户
@RequestMapping("/search")
public String search(HttpSession session){
System.out.println(" 业务方法执行啦... ");
return "user/search";
}
}
4、结果
注意调用的顺序。
-
正常运行流程
拦截器的preHandle ---- 目标方法 ---- 拦截器postHandle ---- 页面 ---- 拦截器的afterCompletion (谁配置在前谁优先) -
其他流程
1、只要preHandle不放行就没有以后的流程
2、只要有拦截器没放行,就不会来的页面
3、只要有拦截器放行了,它的afterCompletion都会执行(相当与 finally)
-
什么时候用Filter什么时候用拦截器?
如果某些功能;需要其他组件配合完成,我们就使用拦截器
其他情况可以写filter