spring mvc 中的拦截器
拦截器和过滤器的作用是相同的,都是要把不符合情况的代码给拦截或者可以说是过滤掉,如:登录的密码或用户名不符合时,不可以登录等,这些都是需要被拦截或者过滤的。
1)编写拦截器(实现 HandlerInterceptor 接口)
@Component public class Interceptor1 implements HandlerInterceptor { // 在控制器方法执行前被调用, 返回 true 放行请求, 如果返回 false 拦截请求(不会前进了) @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //代码 return true|false; } // 在控制器方法执行后被调用 @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { //代码 } // 在控制器和视图都完成后被调用 @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { //代码 } }
2)配置拦截器
<!-- 某个拦截器 --> <mvc:interceptor> <!-- 拦截器要匹配的路径 如:/hello --> <mvc:mapping path="路径" /> <!-- 要调用的拦截器的名字,也就是实现 HandlerInterceptor 接口的类 --> <ref bean="拦截器名"/> </mvc:interceptor>
- * 表示只能匹配一层地址,如:/user/insert,不能是 /user/mvc/insert
- ** 表示多层地址,如:/user/insert 和 /user/mvc/insert 都行
代码演示
1、拦截器演示
springmvc.xml 里拦截器的配置如下:
<!-- 扫描拦截器 -->
<context:component-scan base-package="com.westos.interceptor"/>
<!-- 配置 要拦截哪些控制器 -->
<mvc:interceptors>
<!-- 某个拦截器 -->
<mvc:interceptor>
<!--
/* 只能匹配一层
/user/insert
/user/update
/user/delete
不能匹配
/user/abc/insert
/** 匹配任意层
-->
<mvc:mapping path="/user/**" />
<!-- bean ="bean的id" -->
<ref bean="interceptor1"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/user/**"/>
<ref bean="interceptor2"/>
</mvc:interceptor>
</mvc:interceptors>
HelloController类 控制器,用来使拦截器的调用方法突出而设置的
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloController {
@RequestMapping("/user/insert")
public String insert() {
System.out.println("进入了 insert 方法");
//跳转到hello.jsp页面
return "hello";
}
@RequestMapping("/user/update")
public String update() {
System.out.println("进入了 update 方法");
return "hello";
}
@RequestMapping("/user/detail/insert")
public String dinsert() {
System.out.println("进入了 detail/insert 方法");
return "hello";
}
}
hello.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
hello.jsp
</body>
</html>
<%--为了看出拦截器的 afterCompletion 方法会在在控制器和视图都完成后被调用 故意设置此输出--%>
<%
System.out.println("jsp 执行完毕");
%>
拦截器1
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//有了Component 就不需要配置bean了,interceptor1 以当前类名字首字母小写作为 bean 的id
@Component
public class Interceptor1 implements HandlerInterceptor {
// 在控制器方法执行前被调用, 返回 true 放行请求, 如果返回 false 拦截请求(不会前进了)
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("==========> 进入了 Interceptor1 preHandle");
return true;
}
// 在控制器方法执行后被调用
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("==========> 进入了 Interceptor1 postHandle");
}
// 在控制器和视图都完成后被调用
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("==========> 进入了 Interceptor1 afterCompletion");
}
}
拦截器2
@Component
public class Interceptor2 implements HandlerInterceptor {
// 在控制器方法执行前被调用, 返回 true 放行请求, 如果返回 false 拦截请求(不会前进了)
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("==========> 进入了 Interceptor2 preHandle");
return true;
}
// 在控制器方法执行后被调用
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("==========> 进入了 Interceptor2 postHandle");
}
// 在控制器和视图都完成后被调用
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("==========> 进入了 Interceptor2 afterCompletion");
}
}
结果
hello.jsp页面,以上 HelloController类中的方法成功执行,都会跳转到该页面:
当地址栏输入 http://localhost:8080/user/insert 时,结果如下:
==========> 进入了 Interceptor1 preHandle
==========> 进入了 Interceptor2 preHandle
进入了 insert 方法
==========> 进入了 Interceptor2 postHandle
==========> 进入了 Interceptor1 postHandle
jsp 执行完毕
==========> 进入了 Interceptor2 afterCompletion
==========> 进入了 Interceptor1 afterCompletion
当地址栏输入 http://localhost:8080/user/update 时,结果如下:
==========> 进入了 Interceptor1 preHandle
==========> 进入了 Interceptor2 preHandle
进入了 update 方法
==========> 进入了 Interceptor2 postHandle
==========> 进入了 Interceptor1 postHandle
jsp 执行完毕
==========> 进入了 Interceptor2 afterCompletion
==========> 进入了 Interceptor1 afterCompletion
当地址栏输入 http://localhost:8080/user/detail/insert 时,结果如下:
==========> 进入了 Interceptor1 preHandle
==========> 进入了 Interceptor2 preHandle
进入了 detail/insert 方法
==========> 进入了 Interceptor2 postHandle
==========> 进入了 Interceptor1 postHandle
jsp 执行完毕
==========> 进入了 Interceptor2 afterCompletion
==========> 进入了 Interceptor1 afterCompletion
从以上结果可以看出拦截器的 preHandle 方法是调用在控制器方法之前,postHandle 是在之后,afterCompletion 是在控制器和视图之后调用的,后面调用的 postHandle 和 afterCompletion 调用方法的顺序是和 preHandle 相反的,这里有一点要注意,那就是配置 springmvc.xml 中的拦截器配置时,如果把拦截器1和拦截器2位置颠倒,那么会先进入拦截器1,然后在进入拦截器2,如:进入 http://localhost:8080/user/detail/insert 时,结果如下:
==========> 进入了 Interceptor2 preHandle
==========> 进入了 Interceptor1 preHandle
进入了 detail/insert 方法
==========> 进入了 Interceptor1 postHandle
==========> 进入了 Interceptor2 postHandle
jsp 执行完毕
==========> 进入了 Interceptor1 afterCompletion
==========> 进入了 Interceptor2 afterCompletion