我在库包中创建了验证注释类,例如@IpV4
,@IpV4List
。这些批注返回违反验证时可以在MessageSource
中使用的密钥(代码)。
message.properties
文件位于common资源文件夹中,并且在注册MessageSource
bean时,每个在库包中使用注释的模块都会尝试指定路径。
但是,当注释引发诸如MethodArgumentNotValidException
之类的异常时,MessageSource
找不到带有消息模板(注释中定义的代码)的任何消息。
我已经尝试过与该问题相关的StackOverFlow上发布的大多数方法。
spring.messages.basename=messages/messages, file:/path/to/file
@Configuration
类中的基本名称(没有静态位置)@Bean
public MessageSource messageSource(){
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasenames("messages/messages", "file:/path/to/file");
// some other settings...
return messageSource;
}
spring.messages.basename=messages/messages, messages/vailidation_messages
spring.resources.static-locations=file:/path/to/parent_of_messages
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("file:/path/to/parent_of_messages")
// some other settings
;
}
我尝试了许多其他方法,但是我无法通过调用MessageSource.getMessage()
得到消息,并且发生了ConstraintViolationException
。
我的项目结构如下。
foo-cloud
│
├─ foo-config
│ ├─ resources
│ │ ├─ messages << message properties here
│ │ │ ├─ validation_messages.properties
│ │ │ ├─ validation_messages_en.properties
│ │ │ ├─ validation_messages_ja.properties
│ │ │ └─ validation_messages_ko.properties
│ │ └─ ...
│ └─ ...
├─ foo-auth
├─ ...
├─ foo-gateway
│
├─ foo-resource
│ ├─ ...
│ ├─ foo-application << module to register Bean for MessageSource here
│ └─ ...
│
├─ foo-library
│ ├─ ...
│ └─ util-lib << annotation for validation here
│
└─ foo-web
└─ ...
edited
)spring.messages.basename=messages/messages, messages/validation_messages # <- how to fix?
spring.messages.encoding=UTF-8
# spring.resources.static-locations=file:../../foo-config/resources #not used anymore
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;
@Documented
@Constraint(validatedBy = {})
@Target({ FIELD, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Pattern(regexp = IpV4.PATTERN, message = IpV4.NOT_MATCH)
@NotEmpty(message = IpV4.NOT_EMPTY)
public @interface IpV4 {
String PATTERN = "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
String NOT_EMPTY = "validation.ip-v4.not_empty";
String NOT_MATCH = "validation.ip-v4.not_match";
String message() default "invalid ip format";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Map<String, String> validationExceptionCaught(
MethodArgumentNotValidException e) {
return Collections.singletonMap("message", messageSource.getMessage(
e.getBindingResult().getFieldError().getDefaultMessage()));
}
/**
* for debugging
*/
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Map<String, String> validationExceptionCaught(
MethodArgumentTypeMismatchException e) {
return Collections.singletonMap("message", e.getMessage());
}
@ExceptionHandler(ConstraintViolationException.class)
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Map<String, String> validationExceptionCaught(
ConstraintViolationException e) {
return Collections.singletonMap("message",
messageSource.getMessage(
e.getConstraintViolations().stream().findFirst()
.map(ConstraintViolation::getMessageTemplate)
.orElse(e.getMessage())));
}
import foo.bar.lib.common.validator.IpV4;
import lombok.Data;
@Data
public class BarRequest {
@IpV4
private String startIp;
@IpV4
private String endIp;
private String description;
}
如何使用外部文件作为MessageSource共享验证消息的资源?
恐怕我的英语能力不足以沟通。
答案 0 :(得分:0)
最后,我解决了这个问题。
问题是尝试各种方法时配置文件扭曲或文件路径中有错字。
我从MessageSource
文件中删除了与application.properties
相关的所有属性,并将MessageSource
类中的@Configuration
bean注册为以下来源。
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasenames("classpath:messages/messages",
"file:D:/foo-cloud/foo-config/resources/messages_validation");
messageSource.setCacheSeconds(600);
messageSource.setUseCodeAsDefaultMessage(true);
messageSource.setDefaultEncoding(StandardCharsets.UTF_8.name());
return messageSource;
}
感谢M.Deinum
为我提供帮助。