如何在同一个 SpringMvc 应用程序中有两个 ControllerAdvice

Posted

技术标签:

【中文标题】如何在同一个 SpringMvc 应用程序中有两个 ControllerAdvice【英文标题】:How to have two ControllerAdvice in the same SpringMvc application 【发布时间】:2016-04-25 00:56:48 【问题描述】:

我想通过两种方式管理简单控制器或 RestController 抛出的异常: 1)html重定向 2) json错误

我测试了下面的代码:

@ControllerAdvice(annotations = Controller.class)
public class ExceptionHandlerController

    @ExceptionHandler(Exception.class)
    public ModelAndView handleException(HttpServletRequest _req, Exception _ex)
    
        K_LOGGER.info("test");
        return new ModelAndView();
    


@ControllerAdvice(annotations = RestController.class)
public class ExceptionHandlerRestController


    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleException(HttpServletRequest _req, Exception _ex)
    
        return new ResponseEntity<>("test", HttpStatus.INTERNAL_SERVER_ERROR);
    



@RestController
public class GreetingController

    @RequestMapping("/greetingexception")
    public Greeting greetingException(@RequestParam(value = "name", defaultValue = "World") String name)
        throws Exception
    
        throw new Exception();
    

它不能正常工作,我总是通过ExceptionHandlerController而不是ExceptionHandlerRestController。

我认为这是因为@RestController 继承了@Controller。

您还有其他解决方案吗?

【问题讨论】:

【参考方案1】:

eg04lt3r 答案是正确的,尽管更多细节可能对某人有用。

如果您有全局 @ControllerAdvice 并希望在您的一个控制器中以不同的方式处理某些异常,您需要在 @ControllerAdvice 上设置 @Order(Ordered.HIGHEST_PRECEDENCE),它应该具有更高的优先级。

例如:

@ControllerAdvice
public class GeneralExceptionHandler 

    @ExceptionHandler(Exception.class)
    protected ResponseEntity<Error> handleException(Exception ex) 
        ...
    


@ControllerAdvice(assignableTypes = MyController.class)
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MyExceptionHandler 

    @ExceptionHandler(Exception.class)
    protected ResponseEntity<Error> handleException(Exception ex) 
        ...
    

@Order 是必需的,因为在启动时,其中一个处理程序将自动以更高的顺序注册,无论如何,您的异常处理将变得不可预测。例如,我最近看到一个案例,如果您使用 bootRun gradle task MyExceptionHandler 启动应用程序是主要的,但是当以 jar 启动时 GeneralExceptionHandler 是主要的。

【讨论】:

【参考方案2】:

尝试将@Order(Ordered.HIGHEST_PRECEDENCE) 注释添加到其余异常处理程序。它可能对你有帮助。

【讨论】:

谢谢很多,它有效。为什么优先级很重要? Spring根据加载顺序应用ControllerAdvices? 在这种情况下他先定义了,因为它们处理相同的异常。当解析器尝试查找异常处理程序时,如果您没有提供订单,他首先定义。

以上是关于如何在同一个 SpringMvc 应用程序中有两个 ControllerAdvice的主要内容,如果未能解决你的问题,请参考以下文章

当一个方法有两个参数是同类型的时候,springMVC是如何准确把数据放进去

springMVC @autowired 注入失败

尴尬:原来java中有两个 ModelAndView类

SpringMVC之旅-开发到部署过程中遇到的问题整理(不断更新)

springmvc请求处理方法中有多个Bean类型参数解决方法(使用封装类将多个Bean设为属性,通过对封装类的注入实现多个Bean注入)

springMVc中事务控制无效,循环插值时候一样无法同步数据如何解决?