springboot中自定义拦截器

        拦截器应该分属于web框架的组件,每个框架提供的自己的支持,实现方式也就不同。例如Struts和Spring,以下是Spring 的拦截器总结,它是基于动态代理(反射)实现的。

        Spring 中声明拦截器需要实现 HandlerInterceptor 接口,当然也可以通过继承HandlerInterceptorAdapter 抽象类,HandlerInterceptorAdapter也是实现了HandlerInterceptor 接口。

拦截器中有四个方法:

preHandle:在Controller中的方法之前执行,决定是否放行,return true表示放行。一旦放行其对应的afterCompletion就一定会执行。

postHandle:Controller中的方法处理完之后,DispatcherServlet进行视图的渲染之前,也就是说在这个方法中你可以对ModelAndView进行操作

afterCompletion:DispatcherServlet进行视图的渲染之后

afterConcurrentHandlingStarted:与异步相关

​    下面通过代码实践,备注了是否放行和异常对拦截器内方法执行的影响结论。其实只需对方法执行的时机进行分析,我们就可以得出相同的结论。

如果想深入了解每个方法的执行时机,可以阅读SpringMVC的 DispatcherServlet 源码

@Component
public class InterceptorTwo extends HandlerInterceptorAdapter {

    /**
    * handler 对应@RequestMapping对应的controller对象
    */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //这里我们是没办法拿到方法参数的,parameters是空的,但是可以拿到controller种注入的bean
        //可以断点验证
        HandlerMethod handlerMethod = (HandlerMethod)handler;
        MethodParameter [] parameters = handlerMethod.getMethodParameters();
        return true;//放行
    }


    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        //在拦截器链中,只要有一个不放行的,所有的postHandle都不会执行
        //如果Controller方法抛异常了,所有的postHandle也不会执行
        System.out.println("postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //只要对应的preHandle放行了就一定会执行,Controller方法抛异常也不会影响
        System.out.println("afterCompletion");
    }

    @Override
    public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("afterConcurrentHandlingStarted");
    }
}

使拦截器生效

//Springboot 是1.x版本的项目中是extends WebMvcConfigurerAdapter ,代码也是一样的
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

    @Autowired
    private SourceAccessInterceptor interceptor;
    @Autowired
    private InterceptorOne interceptorOne;
    @Override
    public void addInterceptors(InterceptorRegistry interceptorRegistry) {
        //1.加入的顺序就是拦截器执行的顺序,设置@Order也不会影响
        //2.按顺序执行所有拦截器的preHandle
        //3.所有的preHandle 执行完再反向执行全部postHandle 最后是反向执行afterCompletion,
        //如果其中有一个未放行,或者抛异常了会影响执行顺序吗?怎样影响
        interceptorRegistry.addInterceptor(interceptor).addPathPatterns("/**");
        interceptorRegistry.addInterceptor(interceptorOne);
    }
}

应用示例

        这个拦截器是用来拦截请求是否有携带token的,如果请求未携带token,将会302重定向到登录界面。

@Component
public class AuthInterceptor extends HandlerInterceptorAdapter {

  
    @Autowired
    private JwtUtil jwtUtil;

    @Value("${login.url}")
    private String loginUrl;

    /**
     * 验证access_token
     *
     * @param request  请求
     * @param response 响应
     * @param handler  处理器controller
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        HandlerMethod handlerMethod = (HandlerMethod) handler;
        //WithoutToken是我自定义的注解,标注在方法上,表示不需要验证token
        if (handlerMethod.getMethod().isAnnotationPresent(WithoutToken.class)) {
            //不需要验证token
            return true;
        } else {
            try {
                //校验jwt
                String access_token = request.getHeader("access_token");
                jwtUtil.verifierToken(access_token);
                //获取用户信息
                final String account = jwtUtil.getAccount(access_token);
                //TODO 可以在这里查询用户信息,然后将用户信息设置到线程变量
                
            } catch (NullPointerException | JWTVerificationException e) {
                //TODO 重定向到登陆页
                response.sendRedirect(loginUrl);
                return false;
            }
            return true;

        }
    }
}

Spring Boot 和 MyBatis 结合使用时,自定义拦截器是一种强大的工具,允许开发者在执行 SQL 之前、之后或在特定业务逻辑点进行额外的操作。以下是如何使用自定义拦截器的一般步骤: 1. **创建拦截器接口**: 首先,你需要定义一个实现了 `org.apache.ibatis.interceptor.Interceptor` 接口的类,这个类通常是抽象的,包含你想要执行的业务逻辑方法。 ```java public interface CustomInterceptor extends Interceptor { // 自定义方法,例如预处理SQL前、后操作 Object before(Invocation invocation); // 其他可能的方法,如执行SQL后处理 Object after(Invocation invocation) throws Throwable; } ``` 2. **实现具体拦截器类**: 在具体类,你需要重写上述接口的方法,并添加你需要的业务逻辑。 ```java public class YourCustomInterceptor implements CustomInterceptor { @Override public Object before(Invocation invocation) { // 在这里执行预处理操作 Object parameter = invocation.getArgs(); // 获取参数 // ...你的代码... return parameter; // 返回处理后的参数 } @Override public Object after(Invocation invocation) { // 执行SQL后处理 // ...你的代码... } } ``` 3. **注册拦截器**: 在 Spring Boot 的 MyBatis 配置,通过 `SqlSessionFactoryBean` 或者 `SqlSessionBuilder` 注册你的拦截器。可以通过 `interceptors` 属性来添加自定义拦截器列表。 ```java @Configuration public class MyBatisConfig { @Bean public SqlSessionFactory sqlSessionFactory(MyBatisMapperScannerConfigurer scannerConfigurer) throws Exception { SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); factoryBean.setMapperScannerConfigurer(scannerConfigurer); // 添加你的拦截器 factoryBean.setPlugins(Arrays.asList(new YourCustomInterceptor())); return factoryBean.getObject(); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值