拦截器HandlerInterceptor
1.Spring Boot拦截器
拦截器主要应用于登陆校验、权限验证、乱码解决、性能监控和异常处理等功能,Spring Boot 同样提供了拦截器功能。
1.1定义拦截器
在 Spring Boot 中定义拦截器十分的简单,只需要创建一个拦截器类,并实现 HandlerInterceptor 接口即可。
HandlerInterceptor 接口中定义以下 3 个方法,如下表。
返回值类型 | 方法声明 | 描述 |
boolean | preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) | 该方法在控制器处理请求方法前执行,其返回值表示是否中断后续操作,返回 true 表示继续向下执行,返回 false 表示中断后续操作。 |
void | postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) | 该方法在控制器处理请求方法调用之后、解析视图之前执行,可以通过此方法对请求域中的模型和视图做进一步修改。 |
void | afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) | 该方法在视图渲染结束后执行,可以通过此方法实现资源清理、记录日志信息等工作。 |
LoginInterceptor
package com.hmdp.interceptor;
import cn.hutool.core.util.ObjectUtil;
import com.hmdp.entity.User;
import com.hmdp.threadlocal.UserThreadLocal;
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;
/**
* 登录拦截器,+ThreadLocal 保存用户信息
*/
public class LoginInterceptor implements HandlerInterceptor {
/**
* 前置拦截器,防止user信息
*
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//1. 获取session
HttpSession session = request.getSession();
//2. 获取session中得用户
User user = (User) session.getAttribute("user");
//3. 判断用户是否存在
if (ObjectUtil.isEmpty(user)) {
//4. 不存在,拦截 401未授权
response.setStatus(401);
return false;
}
//5. 存在 , 保存到threadlocal
UserThreadLocal.saveUser(user);
//6.放行
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
/**
* 后置拦截器,删除user信息,避免内存泄露
*
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
UserThreadLocal.removeUser();
}
}
UserThreadLocal
package com.hmdp.threadlocal;
import com.hmdp.entity.User;
/**
* UserThreadLocal 跨类跨方法保存用户信息
*/
public class UserThreadLocal {
private static final ThreadLocal<User> userThreadLocal = new ThreadLocal<>();
public static void saveUser(User user) {
userThreadLocal.set(user);
}
public static User getUser() {
return userThreadLocal.get();
}
public static void removeUser() {
userThreadLocal.remove();
}
}
1.2注册拦截器
创建一个实现了 WebMvcConfigurer 接口的配置类(使用了 @Configuration 注解的类),重写 addInterceptors() 方法,并在该方法中调用 registry.addInterceptor() 方法将自定义的拦截器注册到容器中。
package com.hmdp.config;
import com.hmdp.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 配置拦截器生效 LoginInterceptor
*/
@Configuration
public class MvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
}
}
1.3指定拦截规则
package com.hmdp.config;
import com.hmdp.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 配置拦截器生效 LoginInterceptor
*/
@Configuration
public class MvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.excludePathPatterns(
"user/login",
"user/code",
"blog/hot",
"shop/**",
"shop-type/**",
"upload/**",
"voucher/**"
);
}
}
在指定拦截器拦截规则时,调用了两个方法,这两个方法的说明如下:
-
addPathPatterns:该方法用于指定拦截路径,例如拦截路径为“/**”,表示拦截所有请求,包括对静态资源的请求。
-
excludePathPatterns:该方法用于排除拦截路径,即指定不需要被拦截器拦截的请求。