• 作者:老汪软件技巧
  • 发表时间:2024-11-29 00:08
  • 浏览量:

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    // 检查用户是否登录,假设用户登录信息存储在 session 中
    Object user = request.getSession().getAttribute("user");
    if (user == null) {
        // 如果未登录,返回 false,终止请求
        return false;
    }
    // 记录请求开始时间
    long startTime = System.currentTimeMillis();
    request.setAttribute("startTime", startTime);
    return true;
}

postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView):

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    if (modelAndView!= null) {
        // 假设向模型中添加一个全局的页面标题信息
        modelAndView.addObject("pageTitle", "Blog - Article Detail");
    }
}

afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex):

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    // 获取之前在 preHandle 中设置的请求开始时间
    long startTime = (Long) request.getAttribute("startTime");
    long endTime = System.currentTimeMillis();
    long processingTime = endTime - startTime;
    // 记录请求处理时间到日志文件中
    Logger logger = LoggerFactory.getLogger(MyInterceptor.class);
    logger.info("Request processing time: {}ms", processingTime);
    // 假设之前在请求处理中有打开的数据库连接资源,这里进行关闭(实际代码中应根据具体的数据库连接管理方式进行处理)

_spring源代码深度解析_aop拦截接口上的注解

// Connection connection = (Connection) request.getAttribute("dbConnection"); // if (connection!= null) { // connection.close(); // } }

(二)配置拦截器

拦截器需要通过 WebMvcConfigurer 配置到 Spring MVC 中。在一个配置类中,通过重写 addInterceptors 方法来注册拦截器:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor())
             .addPathPatterns("/**"); // 配置拦截所有的请求路径
    }
}

这里使用 InterceptorRegistry 来添加自定义拦截器,并能够灵活地配置拦截的 URL 模式。例如,如果只想拦截以“/admin”开头的后台管理相关请求路径,可以这样配置:

registry.addInterceptor(new MyInterceptor())
     .addPathPatterns("/admin/**");

(三)拦截链的执行顺序

当请求到达 Spring MVC 的 DispatcherServlet 时,拦截器链按照添加的顺序依次执行:

preHandle:拦截器链中的 preHandle 方法按添加顺序逐个执行。只要有一个拦截器的 preHandle 方法返回 false,请求就会被终止,后续的拦截器和请求处理都不再执行。例如,在一个系统中有多个拦截器分别进行登录校验、权限校验和数据格式校验,如果登录校验的拦截器 preHandle 方法返回 false,那么权限校验和数据格式校验的拦截器以及目标处理器都不会被调用。请求处理:若所有拦截器的 preHandle 方法都返回 true,请求才会传递到目标处理器(Controller)进行实际的业务逻辑处理。postHandle:在处理器执行完成后,postHandle 方法按添加顺序执行。每个拦截器都可以在这个阶段对模型和视图进行修改或添加信息。afterCompletion:请求完成后,afterCompletion 方法按添加顺序执行,主要用于资源清理等操作。三、Spring 拦截链的应用场景(一)日志记录

在企业级应用中,日志记录是不可或缺的。通过 Spring 拦截链,可以在 preHandle 方法中记录请求的详细信息,如请求的 URL、请求参数等,在 afterCompletion 方法中记录请求处理的时间以及是否出现异常等信息。这样可以方便开发人员在系统出现问题时快速定位问题,也有助于对系统的性能和使用情况进行分析。例如,在一个金融交易系统中,记录每一笔交易请求的相关信息,包括请求时间、交易类型、用户信息等,以便在出现交易纠纷或系统故障时进行追溯和排查。

(二)权限检查

对于大多数应用来说,权限控制是保障系统安全的关键。利用拦截链的 preHandle 方法,可以根据用户的角色、权限等信息对请求进行权限检查。例如,在一个企业资源管理系统中,只有具有特定角色(如财务管理员)的用户才能访问财务报表相关的请求路径,普通员工则会被拦截并提示无权限访问。

(三)性能监控

性能是应用的重要指标之一。通过在 preHandle 中记录请求开始时间,在 afterCompletion 中计算处理时间,可以对系统的各个请求处理性能进行监控。在一个大型电商平台中,可以监控不同商品搜索请求、订单处理请求等的处理时间,以便及时发现性能瓶颈并进行优化,比如优化数据库查询语句、增加缓存策略等。

(四)请求修改

有时候需要对请求数据或响应数据进行动态修改。在 postHandle 方法中,可以对模型数据进行修改从而影响最终的视图展示,或者在 preHandle 方法中对请求参数进行预处理,如添加默认值等。例如,在一个多语言支持的应用中,根据用户的语言偏好设置,在 postHandle 中修改页面显示的文本信息为对应的语言内容。

Spring 拦截链为 Spring 应用程序提供了强大的功能扩展能力,熟练掌握其原理和应用,能够让开发者更加高效地构建出功能丰富、安全可靠且性能优良的应用程序。