3

数値を期待する残りの 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」でクライアントに応答します。これは理にかなっていますか?

4

1 に答える 1