1、拦截器概述
SpringMVC的处置惩罚器拦截器 类似于Servlet开发中的过滤器 Filter ,用于对 Handler 举行预处置惩罚和后处置惩罚。开发者可以本身定义一些拦截器来实现特定的功能。
过滤器与拦截器的区别:
- 过滤器
- servlet规范中的一部分,任何JavaWeb工程都可以使用
- 在url-pattern中配置了/*之后,可以对所有要访问的资源举行过滤
- 拦截器
- 拦截器是SpringMVC框架本身的,只有使用了SpringMVC框架的工程才气使用
- 拦截器只会拦截进入Spring体系中的请求,即 进入DispatcherServlet中的请求
- 像.jsp这种的资源请求,拦截器不会执行,因为它并没用进入DispatcherServlet,而是进到Tomcat内置的 JspServlet中
拦截器是AOP思想的详细应用!
2、拦截器使用
自定义拦截器
那如何实现拦截器呢?
想要自定义拦截器,必须实现 HandlerInterceptor 接口- public interface HandlerInterceptor {
- default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
- throws Exception {
- return true;
- }
- default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
- @Nullable ModelAndView modelAndView) throws Exception {
- }
- default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,@Nullable Exception ex) throws Exception {
- }
- }
复制代码
- preHandle
- 在 Handler执行 之前执行
- 返回true: 放行,执行下一个拦截器
- 返回false: 拦截,终止此次请求后面的处置惩罚链,接下来需要本身处置惩罚request和response来控制网页
- postHandle
- 在 Handler执行 之后,ViewResolver解析逻辑视图之前 执行
- 可以修改ModelAndView 来控制 模型数据 和 接下来将要跳转的视图(仅限于返回逻辑视图名的Handler)
- afterCompletion
- 一次请求 在Spring体系处置惩罚工作完成 之后的回调(即,ViewResolver渲染出物理视图之后)
- 不管Handler是否正常执行(大概抛异常),此方法都会执行
- 类似于try-catch语法中的finally,常用来做资源清算和根据异常的处置惩罚
自定义拦截器 MyInterceptor- public class MyInterceptor implements HandlerInterceptor {
- public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {
- System.out.println("------------preHandle------------");
- return !"false".equals(httpServletRequest.getParameter("status"));
- }
- public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
- System.out.println("------------postHandle------------");
- }
- public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
- System.out.println("------------afterCompletion------------");
- System.out.println(e);
- if (e != null)
- httpServletRequest.getRequestDispatcher("/").forward(httpServletRequest, httpServletResponse);
- }
- }
复制代码 配置拦截器
在Spring的配置文件中定义- <mvc:interceptors>
- <mvc:interceptor>
-
-
-
- <mvc:mapping path="/**"/>
- <mvc:exclude-mapping path="/login"/>
-
- <bean />
- </mvc:interceptor>
- </mvc:interceptors>
复制代码
- mvc:mapping
- mvc:exclude-mapping
- bean
测试
添加Controller- @RestController
- public class TestController {
- @RequestMapping("test1")
- public String test1() {
- System.out.println("Handler执行");
- // int i = 1 / 0;
- return "hello";
- }
- }
复制代码
- 拦截器拦截:后面的处置惩罚链不会执行
- 拦截器放行:请求正常处置惩罚
- Handler 出现异常:postHandle不会执行,异常被afterCompletion捕获,并由afterCompletion处置惩罚请求
3、拦截器执行次序
添加 MyInterceptor2- public class MyInterceptor2 implements HandlerInterceptor {
- public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {
- System.out.println("------------preHandle-2------------");
- return true;
- }
- public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
- System.out.println("------------postHandle-2------------");
- }
- public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
- System.out.println("------------afterCompletion-2------------");
- }
- }
复制代码- <mvc:interceptors>
- <mvc:interceptor>
-
-
-
- <mvc:mapping path="/**"/>
- <mvc:exclude-mapping path="/login"/>
-
- <bean />
- </mvc:interceptor>
- </mvc:interceptors><mvc:interceptors>
- <mvc:interceptor>
- <mvc:mapping path="/**"/>
- <bean id="loginInterceptor" />
- </mvc:interceptor>
- </mvc:interceptors>
复制代码 执行测试,观察控制台输出
由图可知,
- 在 preHandle阶段,拦截器按注册次序执行
- 在 postHandle阶段 和 afterCompletion阶段,拦截器逆序执行
这好比进入一个有多重门的院子,进去 要先开外门,再开内门,出去 要先开内门,再开外门。
4、验证用户是否登录 (项目案例)
实现思路
- 有一个登陆页面,需要写一个controller访问页面。
- 登陆页面有一提交表单的动作。需要在controller中处置惩罚。
- 判断用户名密码是否正确。如果正确,向session中写入用户信息。返回登陆成功。
- 拦截用户请求,判断用户是否登陆。
- 如果用户已经登陆。放行, 如果用户未登陆,跳转到登陆页面。
编写一个登陆页面 login.jsp- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>Title</title>
- </head>
-
- <h1>登录页面</h1>
- <hr>
-
- <body>
- <form action="${pageContext.request.contextPath}/user/login">
- 用户名:<input type="text" name="username">
- 密码: <input type="password" name="pwd">
- <input type="submit" value="提交">
- </form>
- </body>
- </html>
复制代码 编写一个Controller处置惩罚请求- @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>
-
- ${user}
- <a target="_blank" href="https://www.cnblogs.com/${pageContext.request.contextPath}/user/logout">注销</a>
- </body>
- </html>
复制代码 在 index 页面上测试跳转!启动Tomcat 测试,未登录也可以进入主页!- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>$Title$</title>
- </head>
- <body>
- <h1>首页</h1>
- <hr>
- <%--登录--%>
- <a target="_blank" href="https://www.cnblogs.com/${pageContext.request.contextPath}/user/jumplogin">登录</a>
- <a target="_blank" href="https://www.cnblogs.com/${pageContext.request.contextPath}/user/jumpSuccess">成功页面</a>
- </body>
- </html>
复制代码 编写用户登录拦截器- public class LoginInterceptor implements HandlerInterceptor {
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException {
- // 如果是登陆页面则放行
- System.out.println("uri: " + request.getRequestURI());
- if (request.getRequestURI().contains("login")) {
- return true;
- }
- HttpSession session = request.getSession();
- // 如果用户已登陆也放行
- if(session.getAttribute("user") != null) {
- return true;
- }
- // 用户没有登陆跳转到登陆页面
- request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
- return false;
- }
-
- public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
- }
-
- public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
- }
-
- }
复制代码 在Spring的配置文件中注册拦截器- <mvc:interceptors>
- <mvc:interceptor>
- <mvc:mapping path="/**"/>
- <bean id="loginInterceptor" />
- </mvc:interceptor>
- </mvc:interceptors>
复制代码 再次重启Tomcat测试!
OK,测试登录拦截功能无误.
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |