我使用bean验证(JSR303)来验证两个字段,这些字段是使用注释和验证器验证的,注释的目标是注释是我的bean的类级别约束。 问题是如何在我的观点上表达错误? (我使用groovy) SignupForm:
package core.model
import core.validation.PasswordConfirmation
import core.validation.UniqueEmail
import core.validation.UniqueUsername
import groovy.util.logging.Slf4j
import org.hibernate.validator.constraints.Email
import org.hibernate.validator.constraints.NotBlank
import static core.model.AuthoritiesEnum.ROLE_USER
@Slf4j
@PasswordConfirmation
class SignupForm {
static final String NOT_BLANK_MESSAGE = "{notBlank.message}"
static final String UNIQUE_USERNAME_MESSAGE = "{uniqueUsername.message}"
static final String EMAIL_MESSAGE = "{username.message}"
static final String UNIQUE_EMAIL_MESSAGE = "{uniqueEmail.message}"
@UniqueUsername
@NotBlank(message = SignupForm.NOT_BLANK_MESSAGE)
String username
@UniqueEmail
@NotBlank(message = SignupForm.NOT_BLANK_MESSAGE)
@Email(message = SignupForm.EMAIL_MESSAGE)
String email
@NotBlank(message = SignupForm.NOT_BLANK_MESSAGE)
String password
@NotBlank(message = SignupForm.NOT_BLANK_MESSAGE)
String confirmPassword
User createAccount() {
new User(username: email, email: email, password: password, role: ROLE_USER)
}
}
PasswordConfirmation验证注释:
package core.validation
import javax.validation.Constraint
import javax.validation.Payload
import java.lang.annotation.Retention
import java.lang.annotation.Target
import static java.lang.annotation.ElementType.TYPE
import static java.lang.annotation.RetentionPolicy.RUNTIME
@Target(TYPE)
@Retention(RUNTIME)
@Constraint(validatedBy = PasswordConfirmationValidator)
@interface PasswordConfirmation {
String message() default "{core.signup.validation.passwordConfirmation.message}"
Class<?>[] groups() default []
Class<? extends Payload>[] payload() default []
}
密码确认验证码:
package core.validation
import core.model.SignupForm
import groovy.util.logging.Slf4j
import javax.validation.ConstraintValidator
import javax.validation.ConstraintValidatorContext
@Slf4j
class PasswordConfirmationValidator implements ConstraintValidator<PasswordConfirmation, SignupForm> {
@Override
void initialize(PasswordConfirmation constraintAnnotation) {
}
@Override
boolean isValid(SignupForm form, ConstraintValidatorContext context) {
log.info "password : ${form.password}"
log.info "confirmPassword : ${form.confirmPassword}"
println "password : ${form.password}"
println "confirmPassword : ${form.confirmPassword}"
println "defaultConstraintMessageTemplate : ${context.defaultConstraintMessageTemplate}"
form.password.equals form.confirmPassword
}
}
thymeleaf view signup.html:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<title th:text="#{view.signup.title}">Inscription</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link href="../../../resources/css/bootstrap.min.css" rel="stylesheet" media="screen"
th:href="@{/resources/css/bootstrap.min.css}"/>
<link href="../../../resources/css/core.css" rel="stylesheet" media="screen" th:href="@{/resources/css/core.css}"/>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script src="../../../resources/js/bootstrap.min.js" th:src="@{/resources/js/bootstrap.min.js}"></script>
</head>
<body>
<div th:replace="fragments/header_signup :: header">Header</div>
<form class="form-narrow form-horizontal" method="post"
th:action="@{/signup}" th:object="${signupForm}">
<!-- /* Show general error message when form contains errors */ -->
<th:block th:if="${#fields.hasErrors('${signupForm.*}')}">
<div th:replace="fragments/alert :: alert (type='danger', message='Form contains errors. Please try again.')">
Alert
</div>
</th:block>
<fieldset>
<div class="form-group" th:classappend="${#fields.hasErrors('username')}? 'has-error'">
<label for="username" class="col-lg-2 control-label">Username</label>
<div class="col-lg-10">
<input type="text" class="form-control" id="username" placeholder="Username" th:field="*{username}"/>
<span class="help-block" th:if="${#fields.hasErrors('username')}"
th:errors="*{username}">Incorrect username</span>
</div>
</div>
<div class="form-group" th:classappend="${#fields.hasErrors('email')}? 'has-error'">
<label for="email" class="col-lg-2 control-label">Email</label>
<div class="col-lg-10">
<input type="text" class="form-control" id="email" placeholder="Email address" th:field="*{email}"/>
<span class="help-block" th:if="${#fields.hasErrors('email')}"
th:errors="*{email}">Incorrect email</span>
</div>
</div>
<div class="form-group" th:classappend="${#fields.hasErrors('password')}? 'has-error'">
<label for="password" class="col-lg-2 control-label">Password</label>
<div class="col-lg-10">
<input type="password" class="form-control" id="password" placeholder="Password"
th:field="*{password}"/>
<span class="help-block" th:if="${#fields.hasErrors('password')}" th:errors="*{password}">Incorrect password</span>
</div>
</div>
<div class="form-group" th:classappend="${#fields.hasErrors('confirmPassword')}? 'has-error'">
<label for="confirmPassword" class="col-lg-2 control-label">Password confirmation</label>
<div class="col-lg-10">
<input type="password" class="form-control" id="confirmPassword" placeholder="Password confirmation"
th:field="*{confirmPassword}"/>
<!--how to show classe level constraint validation-->
<span class="help-block" th:if="${#fields.hasErrors('confirmPassword')}" th:errors="*{confirmPassword}">Incorrect password confirmation</span>
</div>
</div>
<div class="form-group">
<div class="col-lg-offset-2 col-lg-10">
<button type="submit" class="btn btn-default" th:text="#{view.signup.label}">Sign up</button>
</div>
</div>
</fieldset>
</form>
</body>
</html>
答案 0 :(得分:2)
为了显示类级别约束消息,我使用全局常量成功,就像更新的html代码一样,如documentation
所示<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<title th:text="#{view.signup.title}">Inscription</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link href="../../../resources/css/bootstrap.min.css" rel="stylesheet" media="screen"
th:href="@{/resources/css/bootstrap.min.css}"/>
<link href="../../../resources/css/core.css" rel="stylesheet" media="screen" th:href="@{/resources/css/core.css}"/>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script src="../../../resources/js/bootstrap.min.js" th:src="@{/resources/js/bootstrap.min.js}"></script>
</head>
<body>
<div th:replace="fragments/header_signup :: header">Header</div>
<form class="form-narrow form-horizontal" method="post"
th:action="@{/signup}" th:object="${signupForm}">
<!-- /* Show general error message when form contains errors */ -->
<th:block th:if="${#fields.hasErrors('${signupForm.*}')}">
<div th:replace="fragments/alert :: alert (type='danger', message='Form contains errors. Please try again.')">
Alert
</div>
</th:block>
<fieldset>
<div class="form-group" th:classappend="${#fields.hasErrors('username')}? 'has-error'">
<label for="username" class="col-lg-2 control-label">Username</label>
<div class="col-lg-10">
<input type="text" class="form-control" id="username" placeholder="Username" th:field="*{username}"/>
<span class="help-block" th:if="${#fields.hasErrors('username')}"
th:errors="*{username}">Incorrect username</span>
</div>
</div>
<div class="form-group" th:classappend="${#fields.hasErrors('email')}? 'has-error'">
<label for="email" class="col-lg-2 control-label">Email</label>
<div class="col-lg-10">
<input type="text" class="form-control" id="email" placeholder="Email address" th:field="*{email}"/>
<span class="help-block" th:if="${#fields.hasErrors('email')}"
th:errors="*{email}">Incorrect email</span>
</div>
</div>
<div class="form-group" th:classappend="${#fields.hasErrors('password')}? 'has-error'">
<label for="password" class="col-lg-2 control-label">Password</label>
<div class="col-lg-10">
<input type="password" class="form-control" id="password" placeholder="Password"
th:field="*{password}"/>
<span class="help-block" th:if="${#fields.hasErrors('password')}" th:errors="*{password}">Incorrect password</span>
</div>
</div>
<div class="form-group" th:classappend="${#fields.hasErrors('confirmPassword')}? 'has-error'">
<label for="confirmPassword" class="col-lg-2 control-label">Password confirmation</label>
<div class="col-lg-10">
<input type="password" class="form-control" id="confirmPassword" placeholder="Password confirmation"
th:field="*{confirmPassword}"/>
<span class="help-block" th:if="${#fields.hasErrors('confirmPassword')}" th:errors="*{confirmPassword}">Incorrect password confirmation</span>
<span class="help-block" th:if="${#fields.hasErrors('global')}" th:errors="*{global}">Incorrect password confirmation</span>
</div>
</div>
<div class="form-group">
<div class="col-lg-offset-2 col-lg-10">
<button type="submit" class="btn btn-default" th:text="#{view.signup.label}">Sign up</button>
</div>
</div>
</fieldset>
</form>
</body>
</html>