登録APIはRESTfulになります

登録APIはRESTfulになります

1. 概要

the Registration series here on exampleの最後のいくつかの記事では、必要な機能のほとんどをMVC方式で構築しました。

これらのAPIの一部をよりRESTfulなアプローチに移行します。

2. Register操作

メインのレジスタ操作から始めましょう:

@RequestMapping(value = "/user/registration", method = RequestMethod.POST)
@ResponseBody
public GenericResponse registerUserAccount(
      @Valid UserDto accountDto, HttpServletRequest request) {
    logger.debug("Registering user account with information: {}", accountDto);
    User registered = createUserAccount(accountDto);
    if (registered == null) {
        throw new UserAlreadyExistException();
    }
    String appUrl = "http://" + request.getServerName() + ":" +
      request.getServerPort() + request.getContextPath();

    eventPublisher.publishEvent(
      new OnRegistrationCompleteEvent(registered, request.getLocale(), appUrl));

    return new GenericResponse("success");
}

では、この異なる形式は、元のMVCに焦点を合わせた実装とはどのようなものですか?

これが行きます:

  • リクエストがHTTP POSTに正しくマッピングされるようになりました

  • 現在、適切なDTOを返し、@ResponseBodyアノテーションを介して応答の本文に直接マーシャリングしています。

  • メソッドでのエラー処理は一切処理していません

また、古いshowRegistrationPage()も削除します。これは、登録ページを表示するだけでは必要ないためです。

3. registration.html

これらの変更に伴い、registration.htmlを次のように変更する必要があります。

  • Ajaxを使用して登録フォームを送信する

  • 操作の結果をJSONとして受け取ります

これが行きます:



form


4. 例外処理

RESTfulなAPIに加えて、例外処理ロジックももちろんより成熟します。

同じ@ControllerAdviceメカニズムを使用して、アプリケーションによってスローされた例外をクリーンに処理しています。次に、新しいタイプの例外を処理する必要があります。

これはBindExceptionです–UserDtoが検証されたときにスローされます(無効な場合)。 デフォルトのResponseEntityExceptionHandlerメソッドhandleBindException()をオーバーライドして、応答本文にエラーを追加します。

@Override
protected ResponseEntity handleBindException
  (BindException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
    logger.error("400 Status Code", ex);
    BindingResult result = ex.getBindingResult();
    GenericResponse bodyOfResponse =
      new GenericResponse(result.getFieldErrors(), result.getGlobalErrors());

    return handleExceptionInternal(
      ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
}


また、カスタムExceptionUserAlreadyExistExceptionを処理する必要があります。これは、ユーザーが既存の電子メールに登録するときにスローされます。

@ExceptionHandler({ UserAlreadyExistException.class })
public ResponseEntity handleUserAlreadyExist(RuntimeException ex, WebRequest request) {
    logger.error("409 Status Code", ex);
    GenericResponse bodyOfResponse = new GenericResponse(
      messages.getMessage("message.regError", null, request.getLocale()), "UserAlreadyExist");

    return handleExceptionInternal(
      ex, bodyOfResponse, new HttpHeaders(), HttpStatus.CONFLICT, request);
}




5. GenericResponse

また、これらの検証エラーを保持するために、GenericResponseの実装を改善する必要があります。

public class GenericResponse {

    public GenericResponse(List fieldErrors, List globalErrors) {
        super();
        ObjectMapper mapper = new ObjectMapper();
        try {
            this.message = mapper.writeValueAsString(fieldErrors);
            this.error = mapper.writeValueAsString(globalErrors);
        } catch (JsonProcessingException e) {
            this.message = "";
            this.error = "";
        }
    }
}

6. UI –フィールドエラーとグローバルエラー

最後に、jQueryを使用してフィールドエラーとグローバルエラーの両方を処理する方法を見てみましょう。

var serverContext = [[function register(){
    $(".alert").html("").hide();
    var formData= $('form').serialize();
    $.post(serverContext + "/user/registration",formData ,function(data){
        if(data.message == "success"){
            window.location.href = serverContext +"/successRegister.html";
        }
    })
    .fail(function(data) {
        if(data.responseJSON.error.indexOf("MailError") > -1)
        {
            window.location.href = serverContext + "/emailError.html";
        }
        else if(data.responseJSON.error.indexOf("InternalError") > -1){
            window.location.href = serverContext +
              "/login.html?message=" + data.responseJSON.message;
        }
        else if(data.responseJSON.error == "UserAlreadyExist"){
            $("#emailError").show().html(data.responseJSON.message);
        }
        else{
            var errors = $.parseJSON(data.responseJSON.message);
            $.each( errors, function( index,item ){
                $("#"+item.field+"Error").show().html(item.defaultMessage);
            });
            errors = $.parseJSON(data.responseJSON.error);
            $.each( errors, function( index,item ){
                $("#globalError").show().append(item.defaultMessage+"
"); }); } }

ご了承ください:

  • 検証エラーがある場合–messageオブジェクトにはフィールドエラーが含まれ、errorオブジェクトにはグローバルエラーが含まれます

  • 各フィールドのエラーをそのフィールドの横に表示します

  • フォームの最後の1か所にすべてのグローバルエラーを表示します

7. 結論

この簡単な記事の焦点は、APIをよりRESTfulな方向に導き、フロントエンドでそのAPIを処理する簡単な方法を示すことです。

jQueryフロントエンド自体はフォーカスではなく、任意の数のJSフレームワークに実装できる基本的な潜在的なクライアントですが、APIはまったく同じです。

このチュートリアルのfull implementationは、the github projectにあります。これはEclipseベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。