Spring拦截器:HandlerInterceptor使用

概述

有时候我们需要进行一些预处理后处理,或者是拦截请求,在请求前后后做一些处理
使用Spring MVC框架,那么建议使用HandlerInterceptor,它可以类似于普通bean直接注册到Spring容器中被管理

HandlerInterceptor的三个抽象方法

public interface HandlerInterceptor {
    
    
    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
    
        return true;
    }

    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    
    
    }

    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    
    
    }
}

preHandle

在执行Handler之前(执行业务逻辑之前),根据拦截器链顺序执行

  • 每个Interceptor 的调用会依据它的声明顺序依次执行,而且最先执行的都是Interceptor 中的preHandle 方法
  • 所以可以在这个方法中进行一些前置初始化操作或者是对当前请求的一个预处理
  • 也可以在这个方法中进行一些判断来决定请求是否要继续进行下去
  • 该方法的返回值是布尔值Boolean 类型的,
    • 当它返回为false 时,表示请求结束,后续的Interceptor 和Controller 都不会再执行
    • 当返回值为true 时就会继续调用下一个Interceptor 的preHandle 方法如果已经是最后一个Interceptor 的时候就会是调用当前请求的Controller 方法

postHandle

在执行Handler成功(执行业务逻辑成功)之后,根据拦截器链倒序执行,如果前面的流程中抛出异常或者请求被拦截则不会执行!

  • 在当前所属的Interceptor 的preHandle 方法的返回值为true 时才能被调用
  • 在当前请求进行处理之后,也就是Controller 方法调用之后执行,但是它会在DispatcherServlet 进行视图返回渲染之前被调用,
  • 所以我们可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作
  • postHandle 方法被调用的方向跟preHandle 是相反的,也就是说先声明的Interceptor 的postHandle 方法反而会后执行

afterCompletion

在请求处理完毕之后执行,无论是否有响应视图,无论有没有通过preHandle,无论有没有抛出异常。只会对此前放行成功(preHandle返回true)的拦截器进行倒序调用

  • 在当前所属的Interceptor 的preHandle 方法的返回值为true 时才能被调用
  • 该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行。
  • 这个方法的主要作用是用于进行资源清理工作的

使用

构建拦截器(HandlerInterceptor )


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.gildata.gup.domain.User;
import com.gildata.gup.domain.UserEncryptReset;
import com.gildata.gup.repository.UserEncryptResetRepository;

@Component // 不可少
public class xxxStateInterceptor implements HandlerInterceptor {
    
     // 必须实现HandlerInterceptor接口

    
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
    
    
        // TODO Auto-generated method stub
        // ....
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
    
    
        // TODO Auto-generated method stub
        return;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
    
    
        // TODO Auto-generated method stub
    }
}

注册拦截器(WebMvcConfigurerAdapter )

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import com.gildata.gup.interceptor.PasswordStateInterceptor;

@Configuration // 配置
public class WebConfigfilter extends WebMvcConfigurerAdapter{
    
    
    
    @Autowired
    private XxxStateInterceptor xxxStateInterceptor ; // 实例化拦截器

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    
    
        // super.addInterceptors(registry);
        // 注册自定义的拦截器passwordStateInterceptor
        registry.addInterceptor(xxxStateInterceptor)
            .addPathPatterns("/api/*") //匹配要过滤的路径
            .excludePathPatterns("/api/changeUser/*") //匹配不过滤的路径。/api/changeUser后面的所有接口不能拦截
            .excludePathPatterns("/api/getAge""/api/getName") // /api/getAge也不能拦截,/api/getName这个接口的请求不能拦截
    }
}

两个常用方法:

  • .addPathPatterns():增加url的拦截路径,“/**”意思是所有请求都要拦截;
  • .excludePathPatterns():排除url的拦截路径,如:“/api/getAge”, “/api/getName”:意为这两个接口不做拦截;

注意

springBoot2.0以上 WebMvcConfigurerAdapter 方法过时,有两种替代方案:

  • 继承 WebMvcConfigurationSupport 类
  • 实现 WebMvcConfigurer 接口
  • 但是,继承WebMvcConfigurationSupport会让Spring-boot对mvc的自动配置失效,所以 建议用实现WebMvcConfigurer接口的方式
  • 所以上面的注册拦截器更改为:
@Configuration // 配置
public class WebConfigfilter implements WebMvcConfigurer{
    
    
    
    @Autowired
    private XxxStateInterceptor xxxStateInterceptor ; // 实例化拦截器

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    
    
        // super.addInterceptors(registry);
        // 注册自定义的拦截器passwordStateInterceptor
        registry.addInterceptor(xxxStateInterceptor)
            .addPathPatterns("/api/*") //匹配要过滤的路径
            .excludePathPatterns("/api/changeUser/*") //匹配不过滤的路径。/api/changeUser后面的所有接口不能拦截
            .excludePathPatterns("/api/getAge""/api/getName") // /api/getAge也不能拦截,/api/getName这个接口的请求不能拦截
    }
}

猜你喜欢

转载自blog.csdn.net/yyuggjggg/article/details/129772586
今日推荐