Java springbootbean验证
在我的SpringBoot项目中,我有一个POJO类用于读取yaml配置文件Java springbootbean验证,java,spring,spring-boot,spring-validator,Java,Spring,Spring Boot,Spring Validator,在我的SpringBoot项目中,我有一个POJO类用于读取yaml配置文件 @Configuration @ConfigurationProperties("filenet") @Data public class ApplicationConfig { @NotNull(message = "Input directory cannot be null") @NotBlank(message = "Input directory cannot be blank") p
@Configuration
@ConfigurationProperties("filenet")
@Data
public class ApplicationConfig {
@NotNull(message = "Input directory cannot be null")
@NotBlank(message = "Input directory cannot be blank")
private String **inputDir**;
@NotNull(message = "Working directory cannot be null")
@NotBlank(message = "Working directory cannot be blank")
private String **workingDir**;
@Pattern(regexp = "[0-9]+",message = "Invalid value for SMTP port")
private String port;
}
有时,inputDir或workingDir或配置文件的其他字段为空。我正在使用javax.validation.constraints
检查是否为空。当应用程序启动时,我看到一条异常消息,程序终止。
例如:端口已验证它必须是一个数字。
我想做的是优雅地处理这个异常,并向相关团队发送电子邮件来处理它
我已经创建了一个类,我在其中验证配置文件的内容
@Component
public class ConfigParamValidation {
public List<String> validateApplicationConfigFile(ApplicationConfig applicationConfig) {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<ApplicationConfig.ContentEngine>> contentEngineVoilations = validator.validate(applicationConfig.contentEngine);
exceptionMessgae = contentEngineVoilations.stream().map(ConstraintViolation::getMessage).collect(Collectors.toList());
if(!exceptionMessgae.isEmpty()) {
through new ConfigFileException(<by passing all required params>);
}
}
}
@组件
公共类配置参数验证{
公共列表验证应用程序配置文件(应用程序配置应用程序配置){
ValidatorFactory=Validation.buildDefaultValidatorFactory();
Validator Validator=factory.getValidator();
设置ContentEngineVillations=validator.validate(applicationConfig.contentEngine);
ExceptionMessageGae=contentEngineVoilations.stream().map(ConstraintViolation::getMessage).collect(Collectors.toList());
如果(!ExceptionMessageGae.isEmpty()){
通过新的ConfigFileException();
}
}
}
我试图创建一个扩展RuntimeException的类
public class ConfigFileException extends RuntimeException {
private String message;
private List<String> details;
private String hint;
private String nextActions;
private String support;
private HttpStatus httpStatus;
private ZonedDateTime zonedDateTime;
public ConfigFileException(String message) {
super(message);
}
public ConfigFileException(String message, Throwable cause) {
super(message, cause);
}
public ConfigFileException(String message, Throwable cause, List<String> details, String hint, String nextActions, String support, HttpStatus httpStatus, ZonedDateTime zonedDateTime) {
super(message, cause);
this.message = message;
this.details=details;
this.hint=hint;
this.nextActions=nextActions;
this.support=support;
this.httpStatus=httpStatus;
this.zonedDateTime = zonedDateTime;
}
}
公共类ConfigFileException扩展RuntimeException{
私有字符串消息;
私人名单详情;
私有字符串提示;
私人字符串连接;
私有字符串支持;
私有HttpStatus HttpStatus;
私有ZonedDateTime ZonedDateTime;
公共ConfigFileException(字符串消息){
超级(信息);
}
公共ConfigFileException(字符串消息,可丢弃原因){
超级(消息、原因);
}
public ConfigFileException(字符串消息、可丢弃原因、列表详细信息、字符串提示、字符串下一步操作、字符串支持、HttpStatus HttpStatus、ZonedDateTime ZonedDateTime){
超级(消息、原因);
this.message=消息;
this.details=细节;
this.hint=hint;
this.nextActions=nextActions;
这个。支持=支持;
this.httpStatus=httpStatus;
this.zonedDateTime=zonedDateTime;
}
}
另一个带有@ExceptionHandler的类
@Data
@ControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class SupportTeamException {
@ExceptionHandler(value = {ConfigFileException.class})
public ResponseEntity<Object> handleConfigFileException(ConfigFileException e) {
ConfigFileException configFileException = new ConfigFileException(e.getMessage(), e, e.getDetails(), e.getHint(), e.getNextActions(), e.getSupport(), e.getHttpStatus(), e.getZonedDateTime());
return new ResponseEntity<Object>(configFileException,e.getHttpStatus());
}
}
@数据
@控制器建议
@顺序(有序。最高优先级)
公共类SupportTeamException{
@ExceptionHandler(值={ConfigFileException.class})
公共响应handleConfigFileException(ConfigFileException e){
ConfigFileException ConfigFileException=新的ConfigFileException(e.getMessage(),e,e.getDetails(),e.getHint(),e.getNextActions(),e.getSupport(),e.getHttpStatus(),e.getZonedDateTime());
返回新的ResponseEntity(configFileException,例如getHttpStatus());
}
}
问题是由于某种原因,控制权没有传递给我的SupportTeamException
类,我可以在该类中发送电子邮件
还是有更好的方法来处理这个问题?据我所知,
@ControllerAdvice
仅适用于用@Controller
或@RestController
注释的组件
由于验证发生在spring boot应用程序启动时(而不是http请求的结果),因此它永远不会进入其中。您可以使用@PostConstructor
方法创建一个组件。(见下文)我强烈建议您注入验证器,而不是自己构建它(以充分利用Spring Boot的潜力)
我不完全理解的是,为什么您希望优雅地处理此异常。如果应用程序启动时没有必需的属性,那么当应用程序实际使用该属性时,它将进一步失败。如果根据情况(如环境),某些属性不需要存在,我建议使用
最后,small aside@NotBlank
还将检查它是否为非空。您不需要同时使用这两种注释,除非您想对您的消息进行具体说明
package com.yourpackage;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.validation.ConstraintViolation;
import javax.validation.ValidationException;
import javax.validation.Validator;
import java.util.Set;
import static java.util.stream.Collectors.joining;
@Component
public class PropertiesValidator {
private final Validator validator;
public final YourProperties properties;
public PropertiesValidator(final Validator validator, final YourProperties properties) {
this.validator = validator;
this.properties = properties;
}
@PostConstruct
public void propertiesShouldBeValid() {
final Set<ConstraintViolation<YourProperties>> constraintViolations = validator.validate(properties);
if (!constraintViolations.isEmpty()) {
final String message = constraintViolations.stream()
.map(ConstraintViolation::getMessage)
.collect(joining(","));
throw new ValidationException(message); //Or send your email
}
}
}
package.com.yourpackage;
导入org.springframework.stereotype.Component;
导入javax.annotation.PostConstruct;
导入javax.validation.ConstraintViolation;
导入javax.validation.ValidationException;
导入javax.validation.Validator;
导入java.util.Set;
导入静态java.util.stream.Collectors.joining;
@组成部分
公共类属性验证器{
私人最终验证器;
公共财产;
公共属性验证器(最终验证器验证器,最终YourProperties属性){
this.validator=验证程序;
这个。属性=属性;
}
@施工后
公共无效属性应为有效(){
最终设置constraintViolations=validator.validate(属性);
如果(!constraintViolations.isEmpty()){
最终字符串消息=constraintViolations.stream()
.map(ConstraintViolation::getMessage)
.收取(加入(“,”);
抛出新的ValidationException(消息);//或发送电子邮件
}
}
}