Sam natknąłem się na ten problem i wykonałem poniższe kroki, aby ponownie użyć mojego, ExceptionController
który jest oznaczony adnotacją @ControllerAdvise
do Exceptions
wrzucenia do zarejestrowanego filtru.
Jest oczywiście wiele sposobów obsługi wyjątków, ale w moim przypadku chciałem, aby wyjątek był obsługiwany przez mój, ExceptionController
ponieważ jestem uparty, a także dlatego, że nie chcę kopiować / wklejać tego samego kodu (tj. Mam trochę przetwarzania / logowania kod w ExceptionController
). Chciałbym zwrócić piękną JSON
odpowiedź, tak jak pozostałe wyjątki wyrzucone nie z filtra.
{
"status": 400,
"message": "some exception thrown when executing the request"
}
W każdym razie udało mi się wykorzystać moje ExceptionHandler
i musiałem zrobić trochę więcej, jak pokazano poniżej w krokach:
Kroki
- Masz niestandardowy filtr, który może zgłosić wyjątek lub nie
- Masz kontroler Spring, który obsługuje wyjątki przy użyciu
@ControllerAdvise
np. MyExceptionController
Przykładowy kod
//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);
}
}
A teraz przykładowy kontroler sprężyny, który obsługuje Exception
w normalnych przypadkach (tj. Wyjątki, które zwykle nie są zgłaszane na poziomie filtru, ten, którego chcemy użyć do wyjątków rzucanych w filtrze)
//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
}
Udostępnianie rozwiązania tym, którzy chcą użyć ExceptionController
do Exceptions
wrzucenia do filtra.