string boot 与 自定义interceptor的实例讲解
前面学习过过滤器,但是过滤器是针对servlet的,用在springmvc和spring boot里面,功能上,感觉并不是很好用. 那这里来学习一下拦截器. 一. 拦截器的执行顺序 1. 目录 2. 拦截器 拦截器里面,我加了三个(First,Two,Third),但是内容都差不多. package org.elvin.boot.interceptor; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class FirstInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse,Object o) throws Exception { System.out.println("FirstInterceptor preHandle"); return true; } @Override public void postHandle(HttpServletRequest httpServletRequest,Object o,ModelAndView modelAndView) throws Exception { System.out.println("FirstInterceptor postHandle"); } @Override public void afterCompletion(HttpServletRequest httpServletRequest,Exception e) throws Exception { System.out.println("FirstInterceptor afterCompletion"); } } preHandle 返回true,才会继续下面的执行. 拦截器注册: package org.elvin.boot.interceptor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration public class RegisterInterceptor extends WebMvcConfigurerAdapter { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new FirstInterceptor()); registry.addInterceptor(new TwoInterceptor()); registry.addInterceptor(new ThirdInterceptor()); super.addInterceptors(registry); } } 为了验证执行顺序,这里使用了 thymeleaf,然后在前台访问了我后台传过去的属性,在访问的时候,就会打印信息到控制台 package org.elvin.boot.pojo; public class Book { private String name ; public String getName() { System.out.println("view : Book'name is " + name); return name; } public void setName(String name) { this.name = name; } } Controller: package org.elvin.boot.Controller; import org.elvin.boot.pojo.Book; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping("first") public class FirstController { private String controllerPath = "first/"; @GetMapping("index") public String index(Model model){ System.out.println("controller : FirstController index doing..."); Book book = new Book(); book.setName("spring boot"); model.addAttribute("book",book); return controllerPath + "index"; } } View: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>Title</title> </head> <body> <h1 th:text="${book.name}"></h1> </body> </html> 在访问 localhost:8080/first/index 的时候,就会在控制台输出响应的信息. 这样,就能看出单个拦截器的执行顺序. 1. 在控制器方法执行之前,执行的 preHandle 方法 2. 执行控制器的action方法 3. 执行完action,解析view之前(如果有的话),执行拦截器的 posthandle 方法 4. 解析view 5. 解析完之后,执行 afterCompletion 方法 当注册多个拦截器的时候,执行顺序,如图上所示了. 二. 拦截器实现权限验证 同样的,先加入权限拦截器 package org.elvin.boot.interceptor; import org.elvin.boot.annotation.NoLogin; import org.springframework.util.StringUtils; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handle) throws Exception { HandlerMethod method = (HandlerMethod ) handle; Class<?> controllerType = method.getBeanType(); if(method.getMethodAnnotation(NoLogin.class) != null || controllerType.getAnnotation(NoLogin.class) != null){ return true; } HttpSession session = request.getSession(); String token = (String)session.getAttribute("token"); if(!StringUtils.isEmpty(token)){ return true; } response.sendRedirect("/login/index"); return false; } @Override public void postHandle(HttpServletRequest httpServletRequest,ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest httpServletRequest,Exception e) throws Exception { } } 然后注册权限拦截器 package org.elvin.boot.interceptor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration public class RegisterInterceptor extends WebMvcConfigurerAdapter { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()); super.addInterceptors(registry); } } 在控制器中加入登录控制器,提供登录页面和注销方法 package org.elvin.boot.Controller; import org.elvin.boot.annotation.NoLogin; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; @NoLogin @Controller @RequestMapping("login") public class LoginController { @Autowired private HttpServletRequest request; @Autowired private HttpServletResponse response; private String controllerPath = "login/"; //@NoLogin @GetMapping("index") public String index(){ HttpSession session = request.getSession(); session.setAttribute("token","token"); return controllerPath + "index"; } //@NoLogin @PostMapping("checkOut") @ResponseBody public String checkOut(){ HttpSession session = request.getSession(); session.setAttribute("token",null); return "ok"; } } 这里我做了一个免登录注解,可以加在Controller上,也可以加在 action 上. package org.elvin.boot.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface NoLogin { } 注解里面,并不需要任何内容. 登录页面(这里登录页面只是为了注销用的,所以访问过这个页面之后,就表示登录成功了). <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"/> <title>Title</title> </head> <body> <div class="container"> <input type="button" value="注销" id="checkOut"/> </div> <script th:src="@{/js/jquery-1.11.1.js}"></script> <script th:inline="javascript"> $(function () { $(".container").delegate("#checkOut","click",function () { $.ajax({ url: [[@{/login/checkOut}]],type: 'post',data: {},success: function (res) { if (res == "ok") { alert("注销成功"); } } }); }); }); </script> </body> </html> 结果演示方式: 在浏览器中,先打开 http://localhost:8080/login/index 页面,然后在新标签中访问 http://localhost:8080/first/index 页面. 你会发现访问 first/index 的时候,是可以访问的. 此时,在login/index页面中,点击注销按钮之后,再刷新 first/index 页面,就会直接跳去登录页面. 以上这篇string boot 与 自定义interceptor的实例讲解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持编程小技巧。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |