Filter和Interceptor的对比

问题引入

在开发过程中需要对某些接口进行鉴权,一开始的想法是写个Filter,然后拦截指定的路径,通过获取header中的信息进行鉴权,没有权限则抛出自定义异常,然后自定义全局异常处理器再去拦截。

程序测试时发现,没权限时确实被拦截了,但是并没有进入到全局异常处理器,而是直接抛出500。通过查找发现,Filter的在进入Servlet之前进行拦截的,而全局异常是SpringBoot中的(本质是Servlet),所以全局异常处理并不能拦截到Filter抛出的异常。

基本概念

与这个相关的一些概念如下:
web.xml 的加载顺序是:context- param -> listener -> filter -> servlet

1、servlet:servlet是一种运行服务器端的java应用程序,具有独立于平台和协议的特性,并且可以动态的生成web页面,它工作在客户端请求与服务器响应的中间层。

2、filter:filter是一个可以复用的代码片段,可以用来转换HTTP请求、响应和头信息。Filter不像Servlet,它不能产生一个请求或者响应,它只是修改对某一资源的请求,或者修改从某一的响应。

3、listener:监听器,从字面上可以看出listener主要用来监听只用。通过listener可以监听web服务器中某一个执行动作,并根据其要求作出相应的响应。通俗的语言说就是在application,session,request三个对象创建消亡或者往其中添加修改删除属性时自动执行代码的功能组件。

4、interceptor:是在面向切面编程的,就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法,比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。

img

Filter和Interceptor对比

img

过滤器Filter是在请求进入容器后,但在进入servlet之前进行预处理,请求结束是在servlet处理完以后。

拦截器 Interceptor 是在请求进入servlet后,在进入Controller之前进行预处理的,Controller 中渲染了对应的视图之后请求结束。

解决Filter抛出异常无法全局捕获

由上面知道,在filter中抛出的自定义异常是无法在spring的全局异常处理器中捕获到的。那么介绍三种方案去解决这个问题。

1.自定义response返回

@Component
@Slf4j
public class authFilter implements Filter {
   
    private String elasticJobCode;
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
   
        elasticJobCode = ConfigService.getAppConfig().getProperty("wormhole.code", "");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
   
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
     // 认证相关
        String signNew = "";
        if(signNew.equals(sign)){
   
            //认证成功
            filterChain.doFilter(request, response);
        } else{
   
            //认证失败
            updateResponse(response, ReturnCode.NO_PERMISSION);
        }
    }

    @Override
    public void destroy() {
   

    }
    private void updateResponse(HttpServletResponse response, ReturnCode errorCode) {
   
        PrintWriter writer = null;
        response.setContentType("text/html");
        response.setCharacterEncoding("UTF-8");
        try {
   
            writer = response.getWriter();
            if (writer != null) {
   
                writer.print(errorCode.toString());
            }
        } catch (IOException e) {
   
            log.error("authenticate error : {}", errorCode, e);
        } finally {
   
            if (writer != null) {
   
                writer.flush();
                writer.close();
            }
            writer = null;
        }
    }
}

2.重写SpringBoot内置的对异常进行统一处理的Controller–BasicErrorController(不建议)

  • 自定义异常
public class MyException extends RuntimeException  {
   

    private static final long serialVersionUID = -1909845654770784460L;

    private final int code;

    public int getCode() {
   
        return code
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值