1.拦截器Interceptor介绍
拦截器就是面向切面编程----AOP的具体实现。
可以使用Interceptor来执行某些任务,例如在Controller处理之前编写日志,权限校验,通用行为(读取cookie得到用户信息并将用户对象放入请求,方便后续使用)等。
在Spring中,当请求发送到Controller时,在被Controller处理之前,它经过Interceptors(0个或多个)拦截器。
2.拦截器的使用场景
✦ 在将请求发送到控制器(Controller)之前
✦ 在将响应发送给客户端之前
3.拦截器的三种方法
自定义拦截器必须实现HandlerInterceptor接口或者继承Handler InterceptorAdapter类。一般得话都用实现HandlerInterceptor接口的方式来定义拦截器。
HandlerInterceptor接口需要重写下面的3个方法:
· preHandler方法,该方法在请求处理(进入Controller)之前被调用,用来进行一些前置初始化或者对该请求的做预先处理,也可以进行一些判断该请求是否继续执行下去。该方法的返回至是 Boolean 类型,当它返回 false 时,表示请求结束,后续的 Interceptor 和 Controller 都不会再执行;当它返回为 true 时会继续调用下一个 Interceptor 的 preHandle 方法,如果已经是最后一个 Interceptor 的时候就会调用当前请求的 Controller 方法。
· postHandle方法,该方法在控制器(controller)处理请求方法调用之后,解析视图之前执行,可以通过此方法对请求域中的模型和视图做进一步的修改。
· afterHandle方法,该方法在视图渲染结束后执行,可以通过此方法首先资源清理,记录日志信息等工作。
4. 代码实例
✦ 自定义一个拦截器
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
/**
* controller方法之前前
*
* @param request
* @param response
* @param handler
* @return 是否执行controller的处理,true:执行,flase:不执行
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Object loginUser = request.getSession().getAttribute("loginUser");
if (loginUser == null) {
// 未登录时返回登录页面
request.setAttribute("msg", "没有权限进行此操作,请先登录!");
request.getRequestDispatcher("/login.html").forward(request, response);
return false;
}
return true;
}
/**
* controller方法执行后
*
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("postHandle执行{}", modelAndView);
}
/**
* 页面渲染后
*
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("afterCompletion执行异常{}", ex);
}
}
✦ 注册自定义的拦截器
创建一个实现WebMvcConfigurer接口配置类(使用@Configuration注解),重写addInterceptors()方法,并在该方法中调用registry.addInterceptor()方法将自定义的拦截器注册到容器中。
在配置类 MyMvcConfig 中,添加以下方法注册拦截器,代码如下。
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
log.info("注册拦截器");
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**") //拦截所有请求,包括静态资源文件
.excludePathPatterns("/", "/login", "/index.html", "/user/login", "/css/**", "/images/**", "/js/**", "/fonts/**"); //放行登录页,登陆操作,静态资源
}
}
※在指定拦截器规则时,调用了两个方法,这两个方法的说明如下:
• addPathPatterns(): 该方法用户指定拦截路径,例如拦截路径为“/**”, 表示拦截所有请求,包括对静态资源的请求。
• excludePathyPatterns(): 该方法用户排除拦截路径,即指定不需要被拦截器拦截的请求。
到这里,拦截器的基本功能已经完成,
✦ 自定义一个Controller
@Slf4j
@Controller
public class LoginController {
@RequestMapping("/user/login")
public String doLogin(User user, Map<String, Object> map, HttpSession session) {
if (user != null && StringUtils.hasText(user.getUsername()) && "123456".equals(user.getPassword())) {
session.setAttribute("loginUser", user);
log.info("登陆成功,用户名:" + user.getUsername());
//防止重复提交使用重定向
return "redirect:/main.html";
} else {
map.put("msg", "用户名或密码错误");
log.error("登陆失败");
return "login";
}
}
/**
* 访问该路径时,经过配置拦截器,没有登录的情况,自动跳转到登录页面。
*/
@RequestMapping("/main")
public String mainPage(){
return "main";
}
}
5. 拦截器的性能优化和常见问题
☛ 拦截器性能优化策略
拦截器在请求处理过程中可能会影响系统性能,以下是一些性能优化策略:
减少拦截器数量:尽量将相关功能集中到一个拦截器中,避免创建过多的拦截器。
精确配置拦截规则:通过addPathPatterns和excludePathPatterns方法精确配置拦截规则,避免不必要的拦截。
使用异步处理:在拦截器中使用异步处理,避免阻塞请求处理过程。
使用缓存:在拦截器中使用缓存,减少对数据库或其他资源的访问。
☛ 拦截器的常见问题和解决方案
拦截器是一种用于处理请求和响应的中间件,它可以在请求到达目标处理器之前或响应返回客户端之前执行一些操作。然而,在实际使用过程中,我们可能会遇到一些问题,如拦截器不生效、执行顺序错误或影响性能等。接下来,我们将逐一分析这些问题的原因及解决方法。
拦截器不生效:拦截器不生效的可能原因有很多,其中最常见的包括拦截器未注册到InterceptorRegistry、拦截规则配置错误等。为了解决这个问题,我们需要首先检查拦截器是否已经正确注册到InterceptorRegistry中,然后再检查拦截规则是否配置正确。如果发现问题,需要及时进行调整和修复。
拦截器执行顺序错误:拦截器执行顺序错误的主要原因是拦截器的注册顺序错误。在实际应用中,拦截器的执行顺序是根据它们在InterceptorRegistry中的注册顺序来决定的。因此,为了解决这个问题,我们需要调整拦截器在InterceptorRegistry中的注册顺序,确保它们按照预期的顺序执行。
拦截器影响性能:拦截器影响性能的主要原因是拦截器中的处理逻辑过于复杂或资源消耗过大。为了解决这个问题,我们需要对拦截器的处理逻辑进行优化,尽量减少不必要的计算和资源消耗。同时,我们还可以考虑使用一些性能监控工具,如JProfiler等,来对拦截器的性能进行实时监控和分析,从而找到性能瓶颈并进行优化。
拦截器在实际应用中可能会遇到一些问题,但只要我们能够深入了解其原理和机制,就可以找到合适的解决方案。
总结
本文详细介绍了SpringBoot中的拦截器,包括拦截器的概念、作用、实现方式、执行顺序、生命周期以及高级应用。我们还探讨了拦截器的性能优化策略和常见问题。希望本文能帮助您更好地理解和使用SpringBoot中的拦截器。