2017-01-24 17 views
0

私は注釈で設定されたSpring Bootを使用していますが、例外ハンドラが私が捕まえられなかったエラーを投げる問題が発生しました。私は、エラーがスローされるのを止める方法を考え出しましたが、なぜそれが機能するのか分かりません。カール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」ヘッダーのメディアタイプが使用され、レスポンスをフォーマットする方法がわかります。 Springは '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型)の 'Accept'ヘッダをチェックします。これは、コンテンツタイプのスペースを受け付けず、例外をスローします。

+0

スペースに設定しているクライアント/ブラウザを知っていますか? – digitebs

関連する問題