数値を期待する残りの Web サービスがあります。
@RequestMapping(value = "/bb/{number}", method = RequestMethod.GET, produces = "plain/text")
public void test(@PathVariable final double number, final HttpServletResponse response)
ただし、クライアントが数字の代わりに「QQQ」などのテキストを渡すと、クライアントは次のようなスプリングからエラーを受け取ります。
HTTP Status 500 -
The server encountered an internal error () that prevented it from fulfilling this request.
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'double'; nested exception is java.lang.NumberFormatException: For input string: "QQQ"
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:894)
...
このケースを処理し、次のような適切なエラー メッセージを表示する必要があります。
<MyError>
<InvalidParameter parameterName="number"/>
<message>...</message>
</MyError>
どうやってやるの?
これは、org.springframework.beans.TypeMismatchException 例外をキャッチすることで実現できますが (次のコードを参照)、多くの問題があります。たとえば、Web サービス要求のパラメーターの解析と変換に関連しない他の TypeMismatchException 例外が存在する可能性があります。
import org.springframework.beans.TypeMismatchException;
import javax.annotation.*;
import javax.servlet.http.*;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping(value = "/aa")
public class BaseController {
@RequestMapping(value = "/bb/{number}", method = RequestMethod.GET, produces = "plain/text")
public void test(@PathVariable final double number, final HttpServletResponse response) throws IOException {
throw new MyException("whatever");
}
@ResponseBody
@ExceptionHandler
public MyError handleException(final Exception exception) throws IOException {
if (exception instanceof TypeMismatchException) {
response.setStatus(HttpStatus.BAD_REQUEST.value());
TypeMismatchException e = (TypeMismatchException) exception;
String msg = "the value for parameter " + e.getPropertyName() + " is invalid: " + e.getValue();
return new MyError(msg);
}
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
return MyError("Unknown internal error");
}
}
では、クライアントがhttp://example.com/aa/bb/QQQなどの無効な番号で呼び出した場合にカスタム エラー メッセージを表示するにはどうすればよいでしょうか。
ps: 1 つの解決策は、「数値」パラメーターを文字列として定義し、関数内から変換を行うことです (その後、カスタム例外をキャッチしてスローすることができます)。この質問では、スプリングの自動パラメータ変換はそのままで解決策を求めています。
ps: さらに、Spring は「HTTP 400 Bad Request」ではなく「HTTP 500 Internal Server Error」でクライアントに応答します。これは理にかなっていますか?