[SPRING] 봄 필터 예외 처리
SPRING봄 필터 예외 처리
@ExceptionHandler를 사용하여 봄에 예외를 처리하고 있습니다. 컨트롤러에 의해 Throw 된 모든 예외는 @ExceptionHandler로 주석 된 메소드를 사용하여 캐치되며 이에 따라 조치가 취해집니다. 모든 컨트롤러에 대해 @exceptionHandler를 작성하지 않으려면 @ControllerAdvice 주석을 사용하고 있습니다.
예상대로 잘 작동합니다.
이제는 DelegatingFilterProxy와 ContextLoaderListener를 사용하여 구현 된 필터 (예, 인터셉터가 아닌 특정 요구 사항 처리)가 있습니다.
내가 위의 필터에서 동일한 예외를 던질 때 컨트롤러의 경우 에서처럼 처리되지 않았습니다. 그것은 사용자에게 직접 던져진다.
여기서 뭐가 잘못 됐니?
해결법
-
==============================
1.컨트롤러가 해결되기 전에 필터가 발생하기 때문에 필터에서 발생하는 예외는 컨트롤러 조언에 의해 포착 될 수 없습니다.
컨트롤러가 해결되기 전에 필터가 발생하기 때문에 필터에서 발생하는 예외는 컨트롤러 조언에 의해 포착 될 수 없습니다.
필터는 서블릿의 일부이며 MVC 스택이 아닙니다.
-
==============================
2.아마도 필터에 예외가 throw 된 결과로 HTTP 상태 코드를 설정하려고 할 것입니다. 그렇다면 단순히 다음과 같이 상태를 설정하십시오.
아마도 필터에 예외가 throw 된 결과로 HTTP 상태 코드를 설정하려고 할 것입니다. 그렇다면 단순히 다음과 같이 상태를 설정하십시오.
HttpServletResponse 응답 = (HttpServletResponse) res; response.setStatus (HttpServletResponse.SC_UNAUTHORIZED);
-
==============================
3.예외는 컨트롤러가 아니라 필터에서 발생하므로 @ControllerAdvice는 예외를 catch하지 않습니다.
예외는 컨트롤러가 아니라 필터에서 발생하므로 @ControllerAdvice는 예외를 catch하지 않습니다.
그래서, 사방을 살펴본 후에 발견 한 가장 좋은 해결책은이 내부 오류에 대한 필터를 만드는 것이 었습니다.
public class ExceptionHandlerFilter extends OncePerRequestFilter { @Override public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { try { filterChain.doFilter(request, response); } catch (JwtException e) { setErrorResponse(HttpStatus.BAD_REQUEST, response, e); e.printStackTrace(); } catch (RuntimeException e) { e.printStackTrace(); setErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR, response, e); } } public void setErrorResponse(HttpStatus status, HttpServletResponse response, Throwable ex){ response.setStatus(status.value()); response.setContentType("application/json"); // A class used for errors ApiError apiError = new ApiError(status, ex); try { String json = apiError.convertToJson(); System.out.println(json); response.getWriter().write(json); } catch (IOException e) { e.printStackTrace(); } } }
귀하의 설정에 추가, 나는 WebSecurityConfigurerAdapter 구현을 사용하고 있습니다 :
// Custom JWT based security filter httpSecurity .addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class); // Custom Exception Filter for filter httpSecurity .addFilterBefore(exceptionHandlerFilterBean(), JwtAuthenticationTokenFilter.class);
오류 클래스 :
public class ApiError { private HttpStatus status; @JsonSerialize(using = LocalDateTimeSerializer.class) @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss") private LocalDateTime timestamp; private String message; private String debugMessage; private ApiError() { timestamp = LocalDateTime.now(); } public ApiError(HttpStatus status) { this(); this.status = status; } public ApiError(HttpStatus status, Throwable ex) { this(); this.status = status; this.message = "Unexpected error"; this.debugMessage = ex.getLocalizedMessage(); } public ApiError(HttpStatus status, String message, Throwable ex) { this(); this.status = status; this.message = message; this.debugMessage = ex.getLocalizedMessage(); } public String convertToJson() throws JsonProcessingException { if (this == null) { return null; } ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new JavaTimeModule()); mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); return mapper.writeValueAsString(this); } //Setters and getters }
-
==============================
4.아래 코드 스 니펫을 확인하십시오.
아래 코드 스 니펫을 확인하십시오.
final HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper((HttpServletResponse) res); wrapper.sendError(HttpServletResponse.SC_UNAUTHORIZED, "<your error msg>"); res = wrapper.getResponse();
이 필터를 사용하여 return 문을 추가하면 chain.doFilter (req, res)가이를 재정의합니다.
-
==============================
5.이것은 내 필터 클래스에서 오류를 throw하기 위해 수행 한 작업입니다.
이것은 내 필터 클래스에서 오류를 throw하기 위해 수행 한 작업입니다.
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; if (req.getHeader("Content-Type") == null) { HttpServletResponse httpResponse = (HttpServletResponse) response; httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, "Required headers not specified in the request"); } chain.doFilter(request, response); }
-
==============================
6.나처럼 스프링 3.1 (@ControllerAdvice 뒤에 0.1 vesrsions)이 붙어 있다면 방금 전에이 솔루션을 사용해 볼 수 있습니다.
나처럼 스프링 3.1 (@ControllerAdvice 뒤에 0.1 vesrsions)이 붙어 있다면 방금 전에이 솔루션을 사용해 볼 수 있습니다.
그럼, 당신은 예외 결정자 들었어? 그렇지 않다면 여기를 읽으십시오.
@Component public class RestExceptionResolver extends ExceptionHandlerExceptionResolver { @Autowired //If you have multiple handlers make this a list of handlers private RestExceptionHandler restExceptionHandler; /** * This resolver needs to be injected because it is the easiest (maybe only) way of getting the configured MessageConverters */ @Resource private ExceptionHandlerExceptionResolver defaultResolver; @PostConstruct public void afterPropertiesSet() { setMessageConverters(defaultResolver.getMessageConverters()); setOrder(2); // The annotation @Order(2) does not work for this type of component super.afterPropertiesSet(); } @Override protected ServletInvocableHandlerMethod getExceptionHandlerMethod(HandlerMethod handlerMethod, Exception exception) { ExceptionHandlerMethodResolver methodResolver = new ExceptionHandlerMethodResolver(restExceptionHandler.getClass()); Method method = methodResolver.resolveMethod(exception); if (method != null) { return new ServletInvocableHandlerMethod(restExceptionHandler, method); } return null; } public void setRestExceptionHandler(RestExceptionHandler restExceptionHandler) { this.restExceptionHandler = restExceptionHandler; } public void setDefaultResolver(ExceptionHandlerExceptionResolver defaultResolver) { this.defaultResolver = defaultResolver; } }
그러면 예제 핸들러는 다음과 같이 보일 것이다.
@Component public class RestExceptionHandler { @ExceptionHandler(ResourceNotFoundException.class) @ResponseStatus(HttpStatus.NOT_FOUND) @ResponseBody public Map<String, Object> handleException(ResourceNotFoundException e, HttpServletResponse response) { Map<String, Object> error = new HashMap<>(); error.put("error", e.getMessage()); error.put("resource", e.getResource()); return error; } }
물론 콩을 등록하는 것을 잊지 않을 것입니다.
그런 다음 원하는 필터 앞에 호출되는 필터를 만듭니다 (선택적으로 모두 'em').
그런 다음 그 필터에서
try{ chain.doFilter(request, response); catch(Exception e){ exceptionResolver(request, response, exceptionHandler, e); //Make the processing stop here... return; //just in case }
-
==============================
7.나머지 API를 사용하여 응용 프로그램을 작성 했으므로 예외를 throw 한 후 다시 쓸 수있는 필터에서이 문제를 잡아 해결했습니다. filterChain.doFilter (request, response);를 기억하십시오. 포함되어야합니다.
나머지 API를 사용하여 응용 프로그램을 작성 했으므로 예외를 throw 한 후 다시 쓸 수있는 필터에서이 문제를 잡아 해결했습니다. filterChain.doFilter (request, response);를 기억하십시오. 포함되어야합니다.
@Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { try { // something may throw an exception filterChain.doFilter(request, response); } catch (Exception e) { // ResponseWrapper is a customized class ResponseWrapper responseWrapper = new ResponseWrapper().fail().msg(e.getMessage()); response.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE); response.getWriter().write(JSON.toJSONString(responseWrapper)); } }
from https://stackoverflow.com/questions/17715921/exception-handling-for-filter-in-spring by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] Spring Boot, @Configurable을 사용하여 관리되지 않는 클래스에 @Autowire로드 및 시간 짜기 (0) | 2019.03.29 |
---|---|
[SPRING] Spring 4와 주석을 사용하여 비동기 동작을 검증하기위한 단위 테스트를 작성하려면 어떻게해야합니까? (0) | 2019.03.29 |
[SPRING] AOP의 Advisor와 Aspect의 차이점은 무엇입니까? (0) | 2019.03.29 |
[SPRING] Hibernate EntityManager, 그것은 싱글 톤으로 사용되어야 하는가? (0) | 2019.03.29 |
[SPRING] Spring 3 디버그 로깅을 끄는 방법? (0) | 2019.03.29 |