1概要


登録シリーズはここBaeldung

の最後の数記事では、必要な機能のほとんどを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として受け取る

これが行きます:

<html>
<head>
<title th:text="#{label.form.title}">form</title>
</head>
<body>
<form action="/" method="POST" enctype="utf8">
    <input  name="firstName" value=""/>
    <span id="firstNameError" style="display:none"></span>

    <input  name="lastName" value=""/>
    <span id="lastNameError" style="display:none"></span>

    <input  name="email" value=""/>
    <span id="emailError" style="display:none"></span>

    <input name="password" value="" type="password"/>
    <span id="passwordError" style="display:none"></span>

    <input name="matchingPassword" value="" type="password"/>
    <span id="globalError" style="display:none"></span>

    <a href="#" onclick="register()" th:text="#{label.form.submit}>submit</a>
</form>


<script src="jquery.min.js"></script>
<script type="text/javascript">
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+"<br>");
            });
 }
}
</script>
</body>
</html>


4例外処理

よりRESTfulなAPIと共に、例外処理ロジックももちろんより成熟したものになるでしょう。

アプリケーションによってスローされた例外を明確に処理するために、同じ

@ ControllerAdvice

メカニズムを使用しています – そして今、私たちは新しいタイプの例外を必要とします。

これは

BindException

です。これは

UserDto

が検証されたときにスローされます(無効な場合)。レスポンスボディにエラーを追加するには、デフォルトの

ResponseEntityExceptionHandler

メソッド

handleBindException()

をオーバーライドします。

@Override
protected ResponseEntity<Object> 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);
}

また、カスタムの

Exception


UserAlreadyExistException

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

@ExceptionHandler({ UserAlreadyExistException.class })
public ResponseEntity<Object> 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<FieldError> fieldErrors, List<ObjectError> 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+"<br>");
            });
 }
}

ご了承ください:

  • 検証エラーがある場合 –

    message

    オブジェクトには

フィールドerrorsと

error

オブジェクトはグローバルエラーを含みます
** 各フィールドエラーをそのフィールドの横に表示します

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


7. 結論

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

jQueryのフロントエンド自体は焦点ではありません – APIはまったく同じでありながら、任意の数のJSフレームワークに実装できる基本的な潜在的なクライアントにすぎません。

このチュートリアルの

完全な実装

はhttps://github.com/eugenp/spring-security-registration[the github project]にあります – これはEclipseベースのプロジェクトなので、インポートして実行するのは簡単です。そうです。




  • «** 前へ