目录
拦截器
一、定义
SpringMVC 的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。
二、创建拦截器
1.一号拦截器
实现HandlerInterceptor接口,如下
/**
* 自定义拦截器
* @author
*
*/
public class MyInterceptor1 implements HandlerInterceptor {
//方法执行后被执行
//处理异常,清资源,记录日志等等
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("MyInterceptor.afterCompletion.......");
}
//方法执行之后,返回ModelAndView之前被执行
//设置页面的共用参数等等
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
System.out.println("MyInterceptor.postHandle.......");
}
//进入方法前被执行
//登录拦截,权限验证等等
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
System.out.println("MyInterceptor.preHandle.......");
//true放行,false拦截
return true;
}
}
2.二号拦截器
为了学习多个拦截器的运行流程,这里多创建一个二号拦截器,代码copy一号拦截器,输出语句改写一下即可
/**
* 自定义拦截器
* @author
*
*/
public class MyInterceptor2 implements HandlerInterceptor {
//方法执行后被执行
//处理异常,清资源,记录日志等等
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("MyInterceptor2.afterCompletion.......");
}
//方法执行之后,返回ModelAndView之前被执行
//设置页面的共用参数等等
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
System.out.println("MyInterceptor2.postHandle.......");
}
//进入方法前被执行
//登录拦截,权限验证等等
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
System.out.println("MyInterceptor2.preHandle.......");
//true放行,false拦截
return true;
}
}
3.配置拦截器
<!-- 拦截器定义 -->
<mvc:interceptors>
<!-- 定义一个拦截器 -->
<mvc:interceptor>
<!-- path配置</**>拦截所有请求,包括二级以上目录,</*>拦截所有请求,不包括二级以上目录 -->
<mvc:mapping path="/**"/>
<bean class="com.rosinante.springmvc.interceptor.MyInterceptor1" />
</mvc:interceptor>
<!-- 定义一个拦截器 -->
<mvc:interceptor>
<!-- path配置</**>拦截所有请求,包括二级以上目录,</*>拦截所有请求,不包括二级以上目录 -->
<mvc:mapping path="/**"/>
<bean class="com.rosinante.springmvc.interceptor.MyInterceptor2" />
</mvc:interceptor>
</mvc:interceptors>
三、正常流程测试
浏览器访问地址:http://localhost:8088/项目名/itemList.action
控制台打印结果:
四、拦截器运行流程分析
1.情形一:
HandlerInterceptor1 的 preHandler 方法返回false,HandlerInterceptor2 返回 true。
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
System.out.println("MyInterceptor.preHandle.......");
//true放行,false拦截
//拦截器1不放行
return false;
}
控制台输出:
从日志可以看出第一个拦截器的 preHandler 方法返回 false 后第一个拦截器执行了 preHandler 方法,其他两个方法没有执行,第二个拦截器的所有方法不执行,且 Controller 也不执行。
2.情形二:
HandlerInterceptor1 的 preHandler 方法返回 true,HandlerInterceptor2 返回 false
运行结果如下:
从日志可以看出第二个拦截器的 preHandler 方法返回 false 后第一个拦截器的 postHandler 没有执行,第二个拦截器的 postHandler 和 afterCompletion 没哟执行,且 controller 也不执行了。
总结:
- preHandler 按拦截器定义顺序调用
- postHandler 按拦截器定义逆序调用
- afterCompletion 按拦截器定义逆序调用
- postHandler 在拦截器连内所有拦截器反成功调用
- afterCompletion 只有preHandler 返回 true 才调用
五、拦截器的应用:登录拦截器
1.思路
- 有一个登录页面,需要写一个controller访问页面
- 登录页面有一提交表单的动作。需要在controller中处理。
- 判断用户名密码是否正确
- 如果正确 想session中写入用户信息
- 返回登录成功,或者跳转到商品列表
- 拦截器。
- 拦截用户请求,判断用户是否登录
- 如果用户已经登录。放行
- 如果用户未登录,跳转到登录页面。
2.login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>用户登录</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/user/login.action">
用户名:<input type="text" name="username" /><br>
密码:<input type="password" name="password" /><br>
<input type="submit">
</form>
</body>
</html>
3.UserController
/**
* 用户请求处理器
* @author
*
*/
@Controller
@RequestMapping("user")
public class UserController {
@RequestMapping("toLogin")
public String toLogin(){
return "login";
}
@RequestMapping("login")
public String login(String username,String password,HttpSession session){
if(username.equals("admin")){
session.setAttribute("username", username);
return "redirect:/itemList.action";
}
return "login";
}
}
4.LoginInterceptor拦截器
/**
* 登录拦截器
* @author
*
*/
public class LoginInterceptor implements HandlerInterceptor {
//方法执行后被执行
//处理异常,清资源,记录日志等等
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
}
//方法执行之后,返回ModelAndView之前被执行
//设置页面的共用参数等等
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
}
//进入方法前被执行
//登录拦截,权限验证等等
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
//判断用户有没有登录
Object object = request.getSession().getAttribute("username");
if(object == null){
response.sendRedirect(request.getContextPath() + "/user/toLogin.action");
}
//true放行,false拦截
return true;
}
}
5.配置拦截器
<!-- 登录拦截器 -->
<mvc:interceptor>
<!-- path配置</**>拦截所有请求,包括二级以上目录,</*>拦截所有请求,不包括二级以上目录 -->
<mvc:mapping path="/**"/>
<!-- 配置不拦截请求的地址 -->
<!-- <mvc:exclude-mapping path="/user/toLogin.action"/>
<mvc:exclude-mapping path="/user/login.action"/> -->
<mvc:exclude-mapping path="/user/*"/>
<bean class="com.rosinante.springmvc.interceptor.LoginInterceptor" />
</mvc:interceptor>
6.测试
访问:http://localhost:8088/项目名/itemList.action
页面自动跳转: