I want to handle exception for both normal and rest/ajax requests. Here is my code,
@ControllerAdvice
public class MyExceptionHandler {
@ExceptionHandler(Exception.class)
public ModelAndView handleCustomException(Exception ex) {
ModelAndView model = new ModelAndView("error");
model.addObject("errMsg", ex.getMessage());
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
ex.printStackTrace(pw);
sw.toString();
model.addObject("errTrace", sw);
return model;
}
@ExceptionHandler(Exception.class)
@ResponseBody
public String handleAjaxException(Exception ex) {
JSONObject model = new JSONObject();
model.put("status", "error");
model.put("errMsg", ex.getMessage());
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
ex.printStackTrace(pw);
sw.toString();
model.put("errTrace", sw);
return model.toString();
}
}
This will give me an error as I cant have @ExceptionHandler(Exception.class) twice. So what could be the solution?
see the configuration of @ControllerAdvice: http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/ControllerAdvice.html
So you can create two classes(error handlers) and specify annotations/basePackages/assignibaleTypes
For example for REST(ajax) use @RestController annotation for your controllers and you can handle errors like this:
@ControllerAdvice(annotations = RestController.class)
public class MyExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public String handleAjaxException(Exception ex) {
...
}
}
for other cases it can be error handler with annotation
@ControllerAdvice(annotations = Controller.class)
This is global exception handler in spring mvc.this is called every time when exception found in your application.I think you to control only 404 exception with the help of web.xml.
@ControllerAdvice
public class GlobalExceptionController {
@ExceptionHandler(Throwable.class)
@ResponseBody
public ModelAndView handleAllException(Throwable ex,
HttpServletResponse response) {
ex.printStackTrace();
// Set Status
response.setStatus(500);
// Set View
ModelAndView model = new ModelAndView("500");
model.addObject("navlabel", "");
model.addObject("userActivity", new ArrayList<String>());
// Set exception Message
model.addObject("errMsg", ex.getMessage());
return model;
}
}
You can create inner static class @RestControllerAdvice. Noot needed to create separated @RestController for this.
@ControllerAdvice
public class BaseController {
private static final Logger logger =
LoggerFactory.getLogger(BaseController.class);
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public String handleException(Exception error, Model model) {
logger.error("Error was: " + error.getMessage(), error);
model.addAttribute("message", error.getMessage());
model.addAttribute("stackTrace", error.getStackTrace());
model.addAttribute("exception", error);
return "error"; //return view
}
@RestControllerAdvice
public static class RestBaseController {
private static final Logger logger = LoggerFactory.getLogger(RestBaseController.class);
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public String handleException(Exception error) {
logger.error("Error was: " + error.getMessage(), error);
return "error"; //return "error"
}
}
}
You can write two exception handler to handle both normal and rest/ajax requests exception. Here is sample code to illustrate the solution.
@ControllerAdvice(annotations = RestController.class)
@Order(1)
class RestExceptionHandler {
@ExceptionHandler(MyException.class)
@ResponseBody
ResponseEntity<ErrorResponse> exceptionHandler() {
....
}
}
@ControllerAdvice(annotations = Controller.class)
@Order(2)
class ExceptionHandler {
@ExceptionHandler(Exception.class)
public ModelAndView handleError500(HttpServletRequest request, HttpServletResponse response, Exception ex) {
ModelAndView mav = new ModelAndView("error");
mav.addObject("error", "500");
return mav;
}
}
来源:https://stackoverflow.com/questions/32070793/spring-mvc-exceptionhandler-for-restful-and-normal