• 在Spring Filter中抛出异常的一种办法


    转自:在Spring Filter中抛出异常的一种办法

    先说办法,如果看官觉得合适再往下看原理吧

    解决办法

    步骤:

    1、创建一个专门抛出Filter中异常的Controller及接口方法,例如该接口地址为:/filter/login_auth_fail

     1 @RequestMapping("/filter")
     2 @RestController
     3 public class FilterController {
     4     @RequestMapping("/login_auth_fail")
     5     public void loginAuthFail(HttpServletRequest request) {
     6       // 此处构造一个合适的异常并抛出即可
     7       String code = request.getAttribute("code");
     8       throw new CustomException(code);
     9     }
    10 }

    2、在Filter中,需要抛出异常的地方,将异常信息存起来(例如:可以存在HttpServletRequest中),并将请求转发给上面创建的接口地址:

    1 request.setAttribute("code", "xxx");
    2 request.getRequestDispatcher("/filter/login_auth_fail").forward(request, response);

    原理

    可能大家尝试过一种拦截办法:使用@ControllerAdvice和@ExceptionHanlder组合拦截,但并没有成功拦截Filter中的异常

    1 @ControllerAdvice
    2 public class ExpHanlder {
    3   @ExceptionHandler(Exception.class)
    4   public void handle() {
    5     // do somthing...
    6   }
    7 }

    那为什么没有成功呢?关键在于@ControllerAdvice只是对Controller做了加强,而Filter在Controller之前进行,故而异常就这样逃出了咱们的“掌心”。
    本文中介绍的办法,恰是利用了这样的运行顺序,让异常乖乖地抛出去:既然Filter中不能抛出,那我先把错误信息记录下来,把请求转发到一个特定的接口(可认为是一个“陷阱”),然后在这个接口中利用记录的错误信息复原一个异常抛出即可。

    到这,解决办法的原理已经介绍完了了,后面内容按需观看,将和大家一起回顾Filter与Controller的业务流程。

    借用Spring 梳理 - filter、interceptor、aop实现与区别 -第二篇中的顺序图:
    Filter与Controller运行顺序
    可以看到,Spring在将请求交给Controller的接口处理前、后分别调用Filter链中Filter的方法对处理进行增强。当preHandle中将异常抛出时,并没有到Controller,故而@ControllerAdvice未能拦截该异常。

    笔者是在集成Shiro时,需要保留原有项目功能:在身份验证失败或越权时返回JSON格式错误信息而遇到了这个问题,因为Shiro是基于Filter做的拦截,故而需要将Filter中的错误信息抛出。
    项目原先的登陆验证是放在AOP做的,而AOP也在Filter之后进行,关于Filter、Interceptor、AOP及其异常抛出顺序,可以看下这篇文章:Spring:过滤器filter、拦截器interceptor、和AOP的区别与联系

  • 相关阅读:
    css颜色表示法&颜色表
    css单位
    DOM与BOM
    position定位
    grid layout
    Linux禁止Ping方法
    tracert(traceroute)与ping
    服务器负载均衡技术的原理
    Struts2与webx的比较
    SpringAOP的原理
  • 原文地址:https://www.cnblogs.com/nemowang1996/p/13816363.html
Copyright © 2020-2023  润新知