Я сам столкнулся с этой проблемой и выполнил следующие шаги, чтобы повторно использовать свой ExceptionController
, помеченный @ControllerAdvise
для Exceptions
добавления в зарегистрированный фильтр.
Очевидно, существует много способов обработки исключения, но в моем случае я хотел, чтобы исключение обрабатывалось мной, ExceptionController
потому что я упрямый, а также потому, что я не хочу копировать / вставлять тот же код (т.е. у меня есть некоторая обработка / ведение журнала код в ExceptionController
). Я хотел бы вернуть красивый JSON
ответ, как и остальные исключения, созданные не из фильтра.
{
"status": 400,
"message": "some exception thrown when executing the request"
}
Как бы то ни было, мне удалось воспользоваться своим ExceptionHandler
и мне пришлось сделать немного больше, как показано ниже в шагах:
Шаги
- У вас есть собственный фильтр, который может вызывать или не вызывать исключение.
- У вас есть контроллер Spring, который обрабатывает исключения, используя,
@ControllerAdvise
например, MyExceptionController
Образец кода
//sample Filter, to be added in web.xml
public MyFilterThatThrowException implements Filter {
//Spring Controller annotated with @ControllerAdvise which has handlers
//for exceptions
private MyExceptionController myExceptionController;
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void init(FilterConfig arg0) throws ServletException {
//Manually get an instance of MyExceptionController
ApplicationContext ctx = WebApplicationContextUtils
.getRequiredWebApplicationContext(arg0.getServletContext());
//MyExceptionHanlder is now accessible because I loaded it manually
this.myExceptionController = ctx.getBean(MyExceptionController.class);
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
try {
//code that throws exception
} catch(Exception ex) {
//MyObject is whatever the output of the below method
MyObject errorDTO = myExceptionController.handleMyException(req, ex);
//set the response object
res.setStatus(errorDTO .getStatus());
res.setContentType("application/json");
//pass down the actual obj that exception handler normally send
ObjectMapper mapper = new ObjectMapper();
PrintWriter out = res.getWriter();
out.print(mapper.writeValueAsString(errorDTO ));
out.flush();
return;
}
//proceed normally otherwise
chain.doFilter(request, response);
}
}
А теперь пример Spring Controller, который обрабатывает Exception
в обычных случаях (т.е. исключения, которые обычно не выбрасываются на уровне фильтра, который мы хотим использовать для исключений, созданных в фильтре)
//sample SpringController
@ControllerAdvice
public class ExceptionController extends ResponseEntityExceptionHandler {
//sample handler
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
@ExceptionHandler(SQLException.class)
public @ResponseBody MyObject handleSQLException(HttpServletRequest request,
Exception ex){
ErrorDTO response = new ErrorDTO (400, "some exception thrown when "
+ "executing the request.");
return response;
}
//other handlers
}
Совместное использование решения с теми, кто хочет использовать ExceptionController
для Exceptions
добавления фильтра.