如何在自定义注释中获取默认消息中的字段名称?
How to get field Name in default message in custom annotation?
我创建了自定义注释来检查我的模型 class 属性在我的 REST API 项目中的非空值。
@Documented
@Target({ ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@ReportAsSingleViolation
@Constraint(validatedBy = CheckNotNull.NotNullValidator.class)
public @interface CheckNotNull {
String value() default "";
String message() default "{value} can not be null or empty ";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
class NotNullValidator implements ConstraintValidator<CheckNotNull, String> {
@Override
public void initialize(CheckNotNull constraintAnnotation) {
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
return "null".equalsIgnoreCase(value) ? true : value == null ? true : value.trim().equals("") ? true :false;
}
}
}
但是,如果我在属性上使用此注释。
例如:
@CheckNotNull(value = "UserName")
private String login
我还有另一个 class,其中捕获了 ConstraintViloationException。使用@NotNull 注释,它可以完美地工作。
public final class ValidationExceptionMapper implements ExceptionMapper<ValidationException> {
@Override
public Response toResponse(final ValidationException exception) {
RestError error = new RestError();
if (exception instanceof ConstraintViolationException) {
error.setHttpStatusCode(Response.Status.BAD_REQUEST.getStatusCode());
error.setCode(ErrorCodes.ERR_INVALID_INPUT);
final ConstraintViolationException cve = (ConstraintViolationException) exception;
StringBuilder msgBuilder = new StringBuilder("Following constraint violations have been detected: ");
for(ConstraintViolation<?> violation: cve.getConstraintViolations()) {
msgBuilder.append(StringEscapeUtils.escapeHtml(violation.getMessage()));
}
error.setMessage(msgBuilder.toString());
}
return Response.status(error.getHttpStatusCode())
.entity(error)
.type(MediaType.APPLICATION_JSON)
.build();
}
}
我的逻辑不适用于应用自定义注释。我的自定义注释有什么问题吗?
欢迎任何意见。谢谢。
无论您声明为任何动态消息,您都需要使用字段传递该属性 {value}
;
在您的情况下,您需要将其作为 @CheckNotNull(value="name").
传递
@CheckNotNull(value="name")
private String firstName;
@CheckNotNull(value="UserName")
private String name;
这对你有帮助。
我已经覆盖了 ValidationMessages.properties 文件。
javax.validation.constraints.NotNull.message = {0} cannot be null or empty.
org.hibernate.validator.constraints.NotBlank.message = {0} cannot be null or empty
org.hibernate.validator.constraints.NotEmpty.message = {0} cannot be null or empty
然后,在我的回复中 class
public Response toResponse(final ValidationException exception) {
RestError error = new RestError();
StringBuilder errorPath = new StringBuilder();
if (exception instanceof ConstraintViolationException) {
error.setHttpStatusCode(Response.Status.BAD_REQUEST.getStatusCode());
final ConstraintViolationException cve = (ConstraintViolationException) exception;
StringBuilder msgBuilder = new StringBuilder("Following constraint violations have been detected: ");
for(ConstraintViolation<?> violation: cve.getConstraintViolations()) {
Class<?> annotationType = violation.getConstraintDescriptor().getAnnotation().annotationType();
if (annotationType == NotEmpty.class || annotationType == NotNull.class
|| annotationType == NotBlank.class) {
msgBuilder = getErrorMessage(violation, msgBuilder);
}
else {
msgBuilder.append(StringEscapeUtils.escapeHtml(violation.getMessage()));
}
errorPath.append(" path: ").append(violation.getPropertyPath().toString());
}
error.setMessage(msgBuilder.toString());
}
return Response.status(error.getHttpStatusCode())
.entity(error)
.type(MediaType.APPLICATION_JSON)
.build();
}
并且我已经为 getErrorMessage 编写了单独的方法
private StringBuilder getErrorMessage(ConstraintViolation<?> violation, StringBuilder msgBuilder) {
// For default error message
if (violation.getMessage().contains("{0}")) {
String[] splitPath = violation.getPropertyPath().toString().split("[.]");
String fieldName = splitPath[splitPath.length - 1];
String messageWithFieldName = MessageFormat.format(violation.getMessage(), fieldName);
msgBuilder.append((messageWithFieldName)).append(";");
} else {
// For customized error message
msgBuilder.append(violation.getMessage()).append(";");
}
return msgBuilder;
}
因此,如果它们不是@NotNull、@NotEmpty 和@NotBlank 注释的自定义消息,则将默认消息中的占位符替换为从路径中提取的字段名称,以便获得 user-friendly 错误消息。
示例:
@NotNull
private String name;
message: "Following constraint violations have been detected: name cannot be null or empty"
@NotNull(message = "UserName can not be null")
private String name;
message: "Following constraint violations have been detected: UserName can not be null"
@NotNull
@JsonProperty("username")
private String name;
message: "Following constraint violations have been detected: name cannot be null or empty"
我创建了自定义注释来检查我的模型 class 属性在我的 REST API 项目中的非空值。
@Documented
@Target({ ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@ReportAsSingleViolation
@Constraint(validatedBy = CheckNotNull.NotNullValidator.class)
public @interface CheckNotNull {
String value() default "";
String message() default "{value} can not be null or empty ";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
class NotNullValidator implements ConstraintValidator<CheckNotNull, String> {
@Override
public void initialize(CheckNotNull constraintAnnotation) {
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
return "null".equalsIgnoreCase(value) ? true : value == null ? true : value.trim().equals("") ? true :false;
}
}
}
但是,如果我在属性上使用此注释。 例如:
@CheckNotNull(value = "UserName")
private String login
我还有另一个 class,其中捕获了 ConstraintViloationException。使用@NotNull 注释,它可以完美地工作。
public final class ValidationExceptionMapper implements ExceptionMapper<ValidationException> {
@Override
public Response toResponse(final ValidationException exception) {
RestError error = new RestError();
if (exception instanceof ConstraintViolationException) {
error.setHttpStatusCode(Response.Status.BAD_REQUEST.getStatusCode());
error.setCode(ErrorCodes.ERR_INVALID_INPUT);
final ConstraintViolationException cve = (ConstraintViolationException) exception;
StringBuilder msgBuilder = new StringBuilder("Following constraint violations have been detected: ");
for(ConstraintViolation<?> violation: cve.getConstraintViolations()) {
msgBuilder.append(StringEscapeUtils.escapeHtml(violation.getMessage()));
}
error.setMessage(msgBuilder.toString());
}
return Response.status(error.getHttpStatusCode())
.entity(error)
.type(MediaType.APPLICATION_JSON)
.build();
}
}
我的逻辑不适用于应用自定义注释。我的自定义注释有什么问题吗?
欢迎任何意见。谢谢。
无论您声明为任何动态消息,您都需要使用字段传递该属性 {value}
;
在您的情况下,您需要将其作为 @CheckNotNull(value="name").
传递@CheckNotNull(value="name")
private String firstName;
@CheckNotNull(value="UserName")
private String name;
这对你有帮助。
我已经覆盖了 ValidationMessages.properties 文件。
javax.validation.constraints.NotNull.message = {0} cannot be null or empty.
org.hibernate.validator.constraints.NotBlank.message = {0} cannot be null or empty
org.hibernate.validator.constraints.NotEmpty.message = {0} cannot be null or empty
然后,在我的回复中 class
public Response toResponse(final ValidationException exception) {
RestError error = new RestError();
StringBuilder errorPath = new StringBuilder();
if (exception instanceof ConstraintViolationException) {
error.setHttpStatusCode(Response.Status.BAD_REQUEST.getStatusCode());
final ConstraintViolationException cve = (ConstraintViolationException) exception;
StringBuilder msgBuilder = new StringBuilder("Following constraint violations have been detected: ");
for(ConstraintViolation<?> violation: cve.getConstraintViolations()) {
Class<?> annotationType = violation.getConstraintDescriptor().getAnnotation().annotationType();
if (annotationType == NotEmpty.class || annotationType == NotNull.class
|| annotationType == NotBlank.class) {
msgBuilder = getErrorMessage(violation, msgBuilder);
}
else {
msgBuilder.append(StringEscapeUtils.escapeHtml(violation.getMessage()));
}
errorPath.append(" path: ").append(violation.getPropertyPath().toString());
}
error.setMessage(msgBuilder.toString());
}
return Response.status(error.getHttpStatusCode())
.entity(error)
.type(MediaType.APPLICATION_JSON)
.build();
}
并且我已经为 getErrorMessage 编写了单独的方法
private StringBuilder getErrorMessage(ConstraintViolation<?> violation, StringBuilder msgBuilder) {
// For default error message
if (violation.getMessage().contains("{0}")) {
String[] splitPath = violation.getPropertyPath().toString().split("[.]");
String fieldName = splitPath[splitPath.length - 1];
String messageWithFieldName = MessageFormat.format(violation.getMessage(), fieldName);
msgBuilder.append((messageWithFieldName)).append(";");
} else {
// For customized error message
msgBuilder.append(violation.getMessage()).append(";");
}
return msgBuilder;
}
因此,如果它们不是@NotNull、@NotEmpty 和@NotBlank 注释的自定义消息,则将默认消息中的占位符替换为从路径中提取的字段名称,以便获得 user-friendly 错误消息。 示例:
@NotNull
private String name;
message: "Following constraint violations have been detected: name cannot be null or empty"
@NotNull(message = "UserName can not be null")
private String name;
message: "Following constraint violations have been detected: UserName can not be null"
@NotNull
@JsonProperty("username")
private String name;
message: "Following constraint violations have been detected: name cannot be null or empty"