string boot 与 自定义interceptor的实例讲解
作者:Sniper_ZL 时间:2023-10-27 17:03:20
前面学习过过滤器, 但是过滤器是针对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, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("FirstInterceptor postHandle");
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, 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, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, 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 页面, 就会直接跳去登录页面.
来源:http://www.cnblogs.com/elvinle/archive/2017/12/23/8093062.html