我的spring应用程序中有两种类型的控制器。
API和View控制器都是同一个Spring调度程序servlet的一部分。 Spring 3.2引入了@ControllerAdvice
注释,以允许全局位置处理异常。
文档暗示@ControllerAdvice
将应用于与Dispatcher Servlet关联的每个控制器。
有没有办法配置哪些控制器@ControllerAdvice
适用?
例如,在我的场景中,我希望我的视图控制器使用@ControllerAdvice
,并为我的API控制器分隔@ControllerAdvice
。
答案 0 :(得分:6)
对于仍会发现此问题的人:
从Spring 4开始,ControlerAdvice可以限制为带有指定注释的Controler。看看:
http://blog.codeleak.pl/2013/11/controlleradvice-improvements-in-spring.html
(本文的后半部分)了解更多详情。
答案 1 :(得分:3)
我认为现在不可能。如果你可以让API和View控制器抛出不同的Exception类型,那么你可以定义两个不同的@ExceptionHandler并实现你想要的。
// For handling API Exceptions
@ExceptionHandler(APIException.class) // Single API Exception
@ExceptionHandler({APIException.class, ..., ,,,}) // Multiple API Exceptions
// For handling View Exceptions
@ExceptionHandler(ViewException.class) // Single View Exception
@ExceptionHandler({ViewException.class, ..., ...}) // Multiple View Exceptions
您可以使用aop将来自API的异常转换为标准的APIException。请参阅此thread on spring forums。
希望它有所帮助。
答案 2 :(得分:3)
您的例外不应规定您的回复的内容类型。而是检查请求的Accept
标题以了解浏览器的期望。
@ExceptionHandler(Throwable.class)
public @ResponseBody String handleThrowable(HttpServletRequest request, HttpServletResponse response, Throwable ex) throws IOException {
...
String header = request.getHeader("Accept");
if(supportsJsonResponse(header)) {
//return response as JSON
response.setContentType(JSON_MEDIA_TYPE.toString());
return Json.stringify(responseMap);
} else {
//return as HTML
response.setContentType("text/html");
}
答案 3 :(得分:1)
@ExceptionHandler(value=Exception.class)
public ModelAndView error(Exception ex) {
return new ModelAndView("redirect:/error/m");
}
...//ErrorController
@RequestMapping(value = "/m", produces="text/html")
public ModelAndView error()...
@RequestMapping(value = "/m", produces="application/json")
@ResponseBody
public Map errorJson()...
答案 4 :(得分:1)
更新
我正在使用spring4。您可以执行以下2个选项之一。
(1)您可以添加所需的软件包。 (在这些软件包中,您有要遵循@ControllerAdvice
的控制器)。
例如:
@ControllerAdvice(basePackages={"my.pkg.a", "my.pkg.b"})
(2)您可以直接添加所需的控制器类。
例如:
@ControllerAdvice(basePackageClasses={MyControllerA.class, MyControllerB.class})