欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

springboot自定义拦截器的方法

程序员文章站 2022-03-04 13:35:33
拦截器应该分属于web框架的组件,每个框架提供的自己的支持,实现方式也就不同。例如struts和spring,以下是spring 的拦截器总结,它是基于动态代理(反射)实现的。spring 中声明拦截...

拦截器应该分属于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;
 
        }
    }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。