引言
在做后台管理系统时,要进入功能页需要判断一下用户是否登录,此时就体现出拦截器的作用了。
springBoot实现拦截器主要有三步:
- 编写一个拦截器实现HandlerInterceptor接口,并实现preHandle拦截方法
- 将拦截器注册到容器中(实现WebMvcConfigurer接口,并重写addInterceptors方法)
- 编写拦截器规则【注意静态资源的拦截】
内容
编写一个web项目,访问/main路径时候,要判断是否登录,登录即可进入,否则跳回登录页面并给予提示。
拦截器:
package com.xiao.boot.interceptor;
import com.xiao.boot.bean.User.User;
import org.omg.PortableInterceptor.Interceptor;
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 {
/**
* 目标方法执行前
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
User user = (User) session.getAttribute("user");
if (user == null){
// 拦截
request.setAttribute("msg","请先登录");
request.getRequestDispatcher("/").forward(request,response);
return false;
}
// 放行
return true;
}
/**
* 目标方法执行后
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
/**
* 页面渲染以后
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
配置拦截器。注意要将静态资源放行
package com.xiao.boot.config;
import com.xiao.boot.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
//标明配置类
@Configuration
public class AdminWebConfig implements WebMvcConfigurer {
// 添加拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**") //拦截所有,包括静态资源
.excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**"); //放行
}
}
登录的controller
package com.xiao.boot.controller;
import com.sun.org.apache.xpath.internal.operations.Mod;
import com.xiao.boot.bean.User.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.thymeleaf.util.StringUtils;
import javax.servlet.http.HttpSession;
@Controller
public class UserController {
@GetMapping(value = {"/","/login"})
public String loginPage(){
return "login";
}
@PostMapping(value = "/login")
public String main(User user, HttpSession session,Model model){
if (!StringUtils.isEmpty(user.getUserName()) && user.getPassword().equals("123456")){
session.setAttribute("user",user);
return "redirect:/main.html";
}else {
model.addAttribute("msg","账号或密码错误");
return "login";
}
}
@GetMapping(value = "/main.html")
public String mainPage(HttpSession session, Model model){
return "main";
}
}
结果
首先进入登录页面
直接访问main,被拦截,并且提示登录
输入账号和密码进行登录
拦截器原理
- 根据当前请求,找到HandlerExecutionChain【可以处理请求的handler以及handler的所有 拦截器】
- 先来顺序执行 所有拦截器的preHandle方法
- 如果当前拦截器prehandler返回为true。则执行下一个拦截器的preHandle
- 如果当前拦截器返回为false。直接倒序执行所有已经执行了的拦截器的afterCompletion;
- 如果任何一个拦截器返回false。直接跳出不执行目标方法
- 所有拦截器都返回True。执行目标方法
- 倒序执行所有拦截器的postHandle方法。
- 前面的步骤有任何异常都会直接倒序触发 afterCompletion
- 页面成功渲染完成以后,也会倒序触发 afterCompletion