目录
一、拦截器概念
二、拦截器和过滤器的区别
三、拦截器的定义和使用
拦截器的定义:以实现HandleInterceptor接口为例
注册拦截器及其配置
测试自定义拦截器
运行测试
控制台输出成功
四、实例测试
需求:验证用户是否登录 (认证用户)
编写一个登陆页面 login.jsp
编写一个Controller处理请求
编写一个登陆成功的页面 success.jsp
在 index 页面上测试跳转!启动Tomcat 测试,此时未登录也可以进入主页!
编写用户登录拦截器
在Springmvc的配置文件中注册拦截器
启动Tomcat进行测试
五、拦截器执行流程
一、拦截器概念
SpringMVC中的拦截器(interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并做相应的处理。
在实际项目中会经常使用到拦截器,例如:
- 在购物网站中通过拦截器可以拦截未登录的用户,禁止其购买商品
- 使用它来验证已登录用户是否有相应的操作权限(即权限验证)
- 记录请求信息的日志等应用
所谓拦截器,就是能够在进行某个操作之前拦截请求,如果请求符合条件就允许在往下执行。比如说,海关就是一个拦截器,他拦截进出口的货物,如果货物满足进出口条件,则放行,否则就拦截,退回处理。
二、拦截器和过滤器的区别
拦截器和过滤器的功能比较类似,但是有区别:
- 过滤器是Servlet规范的一部分,任何框架都可以使用过滤器技术。
- 拦截器是SpringMVC框架独有的。
- 过滤器配置了/*,可以拦截任何资源。
- 拦截器只会对控制器中的方法进行拦截。
三、拦截器的定义和使用
在SpringMVC中要使用拦截器,就需要对拦截器类进行定义和配置,通常拦截器类可以通过两种方式来定义。
- 第一种通过实现HandleInterceptor接口,或者继承HandleInterceptor接口的实现类HandleInterceptorAdapter来定义;
- 第二种通过实现WebRequestInterceptor接口,或继承WebRequestInterceptor接口的实现类来定义。
!!!拦截器也是AOP思想的一种实现方式!!!
拦截器的定义:以实现HandleInterceptor接口为例
public class MyInterceptor implements HandlerInterceptor {//在请求处理的方法之前执行//如果返回true执行下一个拦截器//如果返回false就不执行下一个拦截器public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {System.out.println("------------before------------");return true;}//在请求处理方法执行之后执行public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {System.out.println("------------after------------");}//在dispatcherServlet处理后执行,做清理工作.public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {System.out.println("------------clear------------");}
}
从以上可以看出,自定义的拦截器类实现了HandlerInterceptor接口,并且实现了接口中的三个方法。对这三个方法解释如下:
preHandle()方法
该方法会在控制器方法前执行,其返回值表示是否中断后续操作。当返回值为true时,表示继续向下执行;当返回值为false时,会中断后续的所有操作(包括调用下一个拦截器和控制器类中的方法执行等)。
postHandle()方法
该方法会在控制器方法调用之后,且解析视图之前执行。可以通过此方法对请求域中的模型和视图做出进一步的修改。
afterCompletion()方法
该方法会在整个请求完成,即视图渲染结束之后执行。可以通过此方法实现一些资源清理、记录日志信息等工作。
注册拦截器及其配置
<mvc:interceptors><mvc:interceptor><!--/** 包括路径及其子路径--><!--/admin/* 拦截的是/admin/add等等这种 , /admin/add/user不会被拦截--><!--/admin/** 拦截的是/admin/下的所有--><mvc:mapping path="/**"/><!--bean配置的就是拦截器--><bean class="com.zlh.interceptor.MyInterceptor"/></mvc:interceptor></mvc:interceptors>
测试自定义拦截器
@RestController
public class InterceptorController {@RequestMapping("/interceptor")public String testFunction() {System.out.println("Test MyInterceptor Success");return "hello";}
}
运行测试
控制台输出成功
四、实例测试
需求:验证用户是否登录 (认证用户)
实现思路
- 有一个登陆页面,需要写一个controller访问页面。
- 登陆页面有一提交表单的动作。需要在controller中处理。将用户名写入session中。返回登陆成功。
- 拦截用户请求,判断用户是否登陆。如果用户已经登陆。放行, 如果用户未登陆,跳转到登陆页面
编写一个登陆页面 login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head><h1>Longin Page</h1>
<hr><body>
<form action="/user/login">UserName:<input type="text" name="username"> <br>Password:<input type="password" name="pwd"> <br><input type="submit" value="提交">
</form>
</body>
</html>
编写一个Controller处理请求
package com.zlh.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpSession;@Controller
@RequestMapping("/user")
public class UserController {//跳转到登陆页面@RequestMapping("/jumpLogin")public String jumpLogin() throws Exception {return "login";}//跳转到成功页面@RequestMapping("/jumpSuccess")public String jumpSuccess() throws Exception {return "success";}//登陆提交@RequestMapping("/login")public String login(HttpSession session, String username, String pwd) throws Exception {// 向session记录用户身份信息System.out.println("接收前端==="+username);session.setAttribute("user", username);return "success";}//退出登陆@RequestMapping("logout")public String logout(HttpSession session) throws Exception {// session 过期session.invalidate();return "login";}
}
编写一个登陆成功的页面 success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body><h1>首页</h1>
<hr>
<span>${user} Login Success</span>
<br/>
<a href="/user/logout">注销</a>
</body>
</html>
在 index 页面上测试跳转!启动Tomcat 测试,此时未登录也可以进入主页!
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>首页</title>
</head>
<body>
<hr>
<%--登录--%>
<a href="/user/jumpLogin">登录页面</a>
<br/>
<a href="/user/jumpSuccess">首页</a>
</body>
</html>
编写用户登录拦截器
package com.zlh.interceptor;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;public class LoginInterceptor implements HandlerInterceptor {public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException {// 如果是登陆页面则放行if (request.getRequestURI().contains("login")) {return true;}//获取SessionHttpSession session = request.getSession();// 如果用户已登陆也放行if(session.getAttribute("user") != null) {return true;}// 用户没有登陆跳转到登陆页面request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);return false;}
}
在Springmvc的配置文件中注册拦截器
如果上面已经注册了拦截器,需要删除其它拦截器或将映射路径改成具体路径,否则拦截器会失效
<mvc:interceptors><mvc:interceptor><mvc:mapping path="/**"/><bean id="loginInterceptor" class="com.zlh.interceptor.LoginInterceptor"/></mvc:interceptor></mvc:interceptors>
配置说明:
- mvc:mapping:指定处理的请求路径。
- mvc:exclude-mapping:指定排除的请求路径。
- bean:指定应用到给定路径的拦截器 bean。
启动Tomcat进行测试
初始页面
点击首页,由于未进行登录,需要先进行登录才能访问首页
登录成功,进入首页成功
!!!此时再次进入首页就不需要进行登录了,注销后需要重新登录,拦截器设置成功!!!
五、拦截器执行流程
不包含拦截器的情况下,DispatcherServlet 处理请求的流程可以简化如下。
添加了拦截器做登录检查后,DispatcherServlet 请求处理的流程可以简化如下。
至此鸣谢:Spring MVC 系列之拦截器 Interceptor 最全总结_springmvc interceptor-CSDN博客