2017-01-24 1 views
0

주석을 통해 구성된 Spring Boot를 사용하고 있으며 예외 처리기가 catch 할 수없는 오류를 발생시키는 문제가 발생했습니다. 내가 던져지는 오류를 막을 방법을 알았지 만 왜 그것이 작동하는지 전혀 모른다. 컬 curl -v -H "Accept: application/xhtml xml" 'http://localhost:8080/testEndpoint'와이 예외를 트리거Spring Boot ExceptionHandler 더 많은 오류가 발생했습니다.

@ControllerAdvice 
public class MyExceptionAdvice { 
    ...snip... 
    @ResponseBody 
    @ExceptionHandler(HttpMediaTypeNotAcceptableException.class) 
    void mediaTypeExceptionHandler(HttpMediaTypeNotAcceptableException e) { 
     logger.info("exception: {}", e.getMessage()); 
    } 
} 

는 다음과 같은 결과가 기록되는 :

2017-01-24 11:08:20 [http-nio-8080-exec-1] [INFO] MyExceptionAdvice - exception: Could not parse 'Accept' header [application/xhtml xml]: Invalid mime type "application/xhtml xml": Invalid token character ' ' in token "xhtml xml" - 

2017-01-24 11:08:20 [http-nio-8080-exec-1] [WARN] org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver - Failed to invoke @ExceptionHandler method: void MyExceptionAdvice.mediaTypeExceptionHandler(javax.servlet.http.HttpServletRequest,org.springframework.web.HttpMediaTypeNotAcceptableException) - org.springframework.web.HttpMediaTypeNotAcceptableException: Could not parse 'Accept' header [application/xhtml xml]: Invalid mime type "application/xhtml xml": Invalid token character ' ' in token "xhtml xml" 
    at org.springframework.web.accept.HeaderContentNegotiationStrategy.resolveMediaTypes(HeaderContentNegotiationStrategy.java:59) 
    ...snip... 

2017-01-24 11:08:20 [http-nio-8080-exec-1] [WARN] org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver - Handling of [org.springframework.web.HttpMediaTypeNotAcceptableException] resulted in Exception - java.lang.IllegalStateException: Cannot call sendError() after the response has been committed 
    at org.apache.catalina.connector.ResponseFacade.sendError(ResponseFacade.java:472) 
    ...snip... 

2017-01-24 11:08:20 [http-nio-8080-exec-1] [ERROR] org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Could not parse 'Accept' header [application/xhtml xml]: Invalid mime type "application/xhtml xml": Invalid token character ' ' in token "xhtml xml"] with root cause - org.springframework.web.HttpMediaTypeNotAcceptableException: Could not parse 'Accept' header [application/xhtml xml]: Invalid mime type "application/xhtml xml": Invalid token character ' ' in token "xhtml xml" 
    at org.springframework.web.accept.HeaderContentNegotiationStrategy.resolveMediaTypes(HeaderContentNegotiationStrategy.java:59) 
    ...snip... 

그리고 클라이언트에 대한 응답은 HTML의 혼란과 스택 추적했다 :

<!DOCTYPE html><html><head><title>Apache Tomcat/8.5.6 - Error report</title><style type="text/css">H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}.line {height: 1px; background-color: #525D76; border: none;}</style> </head><body><h1>HTTP Status 500 - Could not parse 'Accept' header [application/xhtml xml]: Invalid mime type &quot;application/xhtml xml&quot;: Invalid token character ' ' in token &quot;xhtml xml&quot;</h1><div class="line"></div><p><b>type</b> Exception report</p><p><b>message</b> <u>Could not parse 'Accept' header [application/xhtml xml]: Invalid mime type &quot;application/xhtml xml&quot;: Invalid token character ' ' in token &quot;xhtml xml&quot;</u></p><p><b>description</b> <u>The server encountered an internal error that prevented it from fulfilling this request.</u></p><p><b>exception</b></p><pre>org.springframework.web.HttpMediaTypeNotAcceptableException: Could not parse 'Accept' header [application/xhtml xml]: Invalid mime type &quot;application/xhtml xml&quot;: Invalid token character ' ' in token &quot;xhtml xml&quot; 
org.springframework.web.accept.HeaderContentNegotiationStrategy.resolveMediaTypes(HeaderContentNegotiationStrategy.java:59) 
...snip... 

다른 값을 기록하면서 놀고있는 동안 예외를 매개 변수로 갖기 위해 예외 처리기를 수정했습니다.

@ResponseBody 
@ExceptionHandler(HttpMediaTypeNotAcceptableException.class) 
void mediaTypeExceptionHandler(HttpServletResponse response, HttpMediaTypeNotAcceptableException e) { 
    logger.info("exception: {}", e.getMessage()); 
} 

이제는 동일한 컬이 로그를 생성하고 처음에는 예상했던 로그에 오류가 더 이상 발생하지 않습니다.

2017-01-24 11:30:31 [http-nio-8080-exec-1] [INFO] com.gwm.cat2.core.resource.CAT2ExceptionAdvice - exception: Could not parse 'Accept' header [application/xhtml xml]: Invalid mime type "application/xhtml xml": Invalid token character ' ' in token "xhtml xml" - 

그리고 클라이언트가받는 응답이 정확합니다.

내 질문은 왜입니까? 응답 객체를 매개 변수로 사용하면 처리기로 전달하기 전에 업스트림에 무언가를 수행합니까? 그것이 일어나지 않는 것은 후속 오류가 다운 스트림에서 발생하는 이유입니다. 감사.

답변

0

봄이 오류 메시지를 반환하려고하면 'Accept'헤더 요청의 미디어 유형을 사용하여 응답 형식을 지정하는 방법을 찾습니다. 스프링은 'Accept'헤더를 파싱합니다. 그 이유는 값의 형식이 잘못되어 또 다른 예외가 발생했기 때문입니다. 당신은 예를 들어, 컨트롤러 클래스 나 메소드에 @Request 매핑하여 API에 의해 허용되는 미디어 유형을 제한 할 수 있습니다

솔루션 :

import org.springframework.http.MediaType; 
@RequestMapping(MediaType.APPLICATION_JSON_VALUE) 

당신은 그렇게 할 경우, 다른 미디어 요청 형식이 전혀 받아 들여지지 않아야하고 HTTP 406 'Not Acceptable'이 반환됩니다. 내용이 만들어지지 않기 때문에 설명 된 문제가 더 이상 발생하지 않아야합니다.

+0

감사합니다. 하지만 그 행동은 예외 처리기의 메서드 서명에 관계없이 일관성이있을 것이라고 기대합니다. 그게 날 여기에서 넘어 뜨리는거야. 응답 객체를 수정하지 않더라도 매개 변수로 자동으로 포함하면 Spring 내부에서 오류를 처리합니다. – ArmedChef

0

로그 메시지에서 "application/xhtml xml"을 확인하십시오. 올바른 형식은 "application/xhtml + xml"입니다. SpringMVC는 콘트롤러 메소드가 리턴 된 후에 org.springframework.util.MimeTypeUtils.checkToken (String type)의 'Accept'헤더를 검사 할 것이고, 이는 콘텐트 타입의 공간을 허용하지 않고 예외를 던질 것이다.

+0

공간을 차지하는 클라이언트/브라우저를 알고 있습니까? – digitebs

관련 문제