目录
一、什么是拦截器
拦截器是Spring框架提供的核心功能之一,主要用来拦截用户的请求,在指定方法前后,根据业务需要执行预先设定的代码。
开发人员可以提前定义一些逻辑,在用户的请求响应前后执行,比如通过拦截器来拦截前端发来的请求,要求用户强制进行登录,判断Session中是否有登录用户的信息,如果有就可以放行,如果没有就拦截。
举个例子:比如我们去银行办理业务,在办理业务前后,就可以加一些拦截操作。
在办理业务之前,先取号,如果带身份证了就取号成功;业务办理结束,给业务办理人员的服务进行评价,这些就是“拦截器”做的工作。
二、拦截器的基本使用
在使用拦截器之前,先创建一些类:
- User类:
@Data
public class User {
private String username;
private String password;
}
UserController类:
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
GetUser getUser;
@RequestMapping("/login")
public String login(String username, String password, HttpServletRequest request) {
User user = getUser.getUser(username, password);
if (user == null) {
return "账号或密码错误";
}
request.getSession().setAttribute("user", user);
return "账号密码正确,登录成功";
}
@RequestMapping("/enter")
public String Enter(){
return "进入页面";
}
}
- GetUser类
@Service
public class GetUser {
public User getUser(String username, String password) {
if (username == null || password == null) {
return null;
}
if (!"zhangsan".equals(username) ||!"123".equals(password)) {
return null;
}
User user = new User();
user.setUsername("zhangsan");
user.setPassword("123");
return user;
}
}
拦截器的使用步骤
- 定义拦截器
- 注册配置拦截器
1.自定义拦截器:实现HandlerInterceptor接口,并重写其所有方法:
//自定义拦截器,实现HandlerInterceptor接口并重写其所有方法
@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
log.info("拦截开始");
HttpSession session = request.getSession();
User user = (User) session.getAttribute( "user");
if (user == null) {
log.info("被拦截");
return false;
}else {
log.info("不拦截,放行");
return true;
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
log.info("enter方法执行后");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("LoginInterceptor 视图渲染完毕后执⾏,最后执⾏");
}
}
- preHandle()方法:目标方法执行前执行。返回true时,表示目标方法未被拦截,放行,继续执行后续操作;返回false时,拦截目标方法,中断后续操作。
- postHandle()方法:目标方法后执行。
- afterCompletion()方法:视图渲染完毕后执行,最后执行(了解)。
2.注册拦截器:实现WebMvcConfigurer接口,并重写addInterceptors方法。
@Configuration
public class WebConfig implements WebMvcConfigurer {
//自定义拦截器对象
@Autowired
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor)
.addPathPatterns("/**")
//排除拦截的页面,登录页
.excludePathPatterns("/user/login");
}
}
补充:上面的拦截路径中,addPathPatterns方法表示拦截的路径,excludePathPatterns表示为排除要拦截的路径,排除了/user/login这个路径了。
完毕后启动服务,试试访问请求,观察后端日志。
- 首先先尝试直接访问enter页面,URL:http://127.0.0.1:8080/user/enter
可以看到,enter路径的被拦截了,因为没有进行登录操作。
- 然后再尝试着先访问login页面进行登录然后再进行访问enter页面。
然后再访问URL:http://127.0.0.1:8080/user/enter,观察日志。
可以看到,进行登录之后,保存了登录信息,再进行访问enter页面时就不会被拦截了。
拦截器路径设置
拦截器中除了可以设置 /** 拦截所有资源外,还有一些常见拦截路径设置:
拦截路径 | 含义 | 举例 |
/* | 一级路径 | 能匹配/user,/book,/login,不能匹配/user/login |
/** | 任意级路径 | 能匹配/user,/user/login,/user/reg |
/book/* | /book下的一级路径 | 能匹配/book/addBook,不能匹配/book/addBook/1,/book |
/book/** | /book下的任意级路径 | 能匹配/book,/book/addBook,/book/addBook/2,不能匹配/user/login |
补充:以上拦截规则可以拦截此项目中使用的URL,包括静态文件(图片文件,JS和CSS等文件)。
拦截器执行流程
正常的调用顺序:
有了拦截器之后,会在调用Controller之前进行相应的业务处理,执行的流程如下图:
1.添加拦截器后,执行Controller的方法之前,请求会先被拦截器拦截住,执行preHandle()方法,这个方法需要返回一个布尔类型的值,如果返回true,就表示放行本次操作,继续访问controller中的方法;如果返回false,则不会放行(controller中的方法也不会执行)。
2.controller当中的方法执行完毕后,再回来执行postHandle()这个方法以及afterCompletion()方法,执行完毕之后,最终给浏览器相应数据。