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ベースのプロジェクトなので、インポートして実行するのは簡単です。そうです。
次
”
-
«** 前へ