spring 启动自定义验证程序注释对参数不起作用
spring boot custom Validator annotation not working on parameter
我创建了一个新注释来验证我在控制器上的参数:
@Constraint(validatedBy = ValueValidator.class)
@Target( { ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidValue {
String message() default "Invalid value";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
这是我的验证器:
public class ValueValidator implements ConstraintValidator<ValidValue, String> {
@Override
public void initialize(ValidValue constraintAnnotation) {
ConstraintValidator.super.initialize(constraintAnnotation);
}
@Override
public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
if (s.contains("hello")) {
throw new IllegalArgumentException("hello is not valid");
}
return true;
}
}
这是我的控制器:
@GetMapping(value = "/extraction-date", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "Find customers by extraction date")
public ResponseEntity<List<Customer>> findAllCustomersByExtractionDate(@RequestParam @ValidValue String value)
{
System.out.println(value);
return null;
}
我的控制器注释为:
@RestController
@RequestMapping("api/v1/customers")
@AllArgsConstructor
@Controller
@Validated
@CrossOrigin
@Tag(name = "customer-controller", description = "Controller managing operations related to customers ")
我还有一个 Advice 控制器,我打算用它来捕获抛出的异常:
@ControllerAdvice()
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
private static final Logger LOG = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
* @param ex a Throwable
* @return a responseEntity with a descriptive message and some other information
*/
@ExceptionHandler(Throwable.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ErrorMessage globalExceptionHandler(Throwable ex) {
LOG.error(ex.getMessage());
return getErrorMessage();
}
/**
* @param ex a Exception
* @return a responseEntity with a descriptive message and some other information
*/
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ErrorMessage globalExceptionHandler(Exception ex) {
LOG.error(ex.getMessage());
return getErrorMessage();
}
/**
* @param ex an InvalidInputException
* @return a responseEntity with a descriptive message and some other information
*/
@ExceptionHandler({InvalidInputException.class})
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public ErrorMessage invalidInputExceptionHandler(Exception ex) {
LOG.error(ex.getMessage());
return getErrorMessage(ex, ErrorCode.INVALID_INPUT_ERROR);
}
/**
* @param ex an ResourceNotFoundException
* @param request the request from the client
* @return a responseEntity with a descriptive message and some other information
*/
@ExceptionHandler({ResourceNotFoundException.class})
@ResponseStatus(HttpStatus.NOT_FOUND)
@ResponseBody
public ErrorMessage resourceNotFoundException(Exception ex, WebRequest request) {
LOG.error(ex.getMessage());
return getErrorMessage(ex, ErrorCode.RESOURCE_NOT_FOUND);
}
/**
* @param ex thrown exception
* @param errorCode to be returned to the client in message
* @return the error message with all attributes
*/
private ErrorMessage getErrorMessage(Exception ex, ErrorCode errorCode) {
return new ErrorMessage(
errorCode.code,
new Date(),
ex.getMessage(),
errorCode.description);
}
/**
* @return the error message with all attributes
*/
private ErrorMessage getErrorMessage() {
return new ErrorMessage(
ErrorCode.INTERNAL_ERROR.code,
new Date(),
"Error while proceeding a joinPoint, unhandled exception: see log messages for more details.",
ErrorCode.INTERNAL_ERROR.description);
}
}
这是我从邮递员那里调用方法后得到的:
我在控制台上得到的:
INFO |2021-11-17T08:51:48,898|88D0657C2A8042FDBD32C05E96280791| [http-nio-8080-exec-1] com.obs.dqsc.api.controller.CustomerController - Entered in CustomerController.findAllCustomersByExtractionDate(hello)
hello
INFO |2021-11-17T08:51:48,903|88D0657C2A8042FDBD32C05E96280791| [http-nio-8080-exec-1] com.obs.dqsc.api.controller.CustomerController - Exit from CustomerController.findAllCustomersByExtractionDate(..); Execution time: 2 ms;
我在 pom.xml 中的依赖项:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.5.12</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
谁能告诉我我错过了什么?
我缺少启动验证器来让它工作,所以我所要做的就是添加这个依赖项:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
我创建了一个新注释来验证我在控制器上的参数:
@Constraint(validatedBy = ValueValidator.class)
@Target( { ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidValue {
String message() default "Invalid value";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
这是我的验证器:
public class ValueValidator implements ConstraintValidator<ValidValue, String> {
@Override
public void initialize(ValidValue constraintAnnotation) {
ConstraintValidator.super.initialize(constraintAnnotation);
}
@Override
public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
if (s.contains("hello")) {
throw new IllegalArgumentException("hello is not valid");
}
return true;
}
}
这是我的控制器:
@GetMapping(value = "/extraction-date", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "Find customers by extraction date")
public ResponseEntity<List<Customer>> findAllCustomersByExtractionDate(@RequestParam @ValidValue String value)
{
System.out.println(value);
return null;
}
我的控制器注释为:
@RestController
@RequestMapping("api/v1/customers")
@AllArgsConstructor
@Controller
@Validated
@CrossOrigin
@Tag(name = "customer-controller", description = "Controller managing operations related to customers ")
我还有一个 Advice 控制器,我打算用它来捕获抛出的异常:
@ControllerAdvice()
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
private static final Logger LOG = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
* @param ex a Throwable
* @return a responseEntity with a descriptive message and some other information
*/
@ExceptionHandler(Throwable.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ErrorMessage globalExceptionHandler(Throwable ex) {
LOG.error(ex.getMessage());
return getErrorMessage();
}
/**
* @param ex a Exception
* @return a responseEntity with a descriptive message and some other information
*/
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ErrorMessage globalExceptionHandler(Exception ex) {
LOG.error(ex.getMessage());
return getErrorMessage();
}
/**
* @param ex an InvalidInputException
* @return a responseEntity with a descriptive message and some other information
*/
@ExceptionHandler({InvalidInputException.class})
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public ErrorMessage invalidInputExceptionHandler(Exception ex) {
LOG.error(ex.getMessage());
return getErrorMessage(ex, ErrorCode.INVALID_INPUT_ERROR);
}
/**
* @param ex an ResourceNotFoundException
* @param request the request from the client
* @return a responseEntity with a descriptive message and some other information
*/
@ExceptionHandler({ResourceNotFoundException.class})
@ResponseStatus(HttpStatus.NOT_FOUND)
@ResponseBody
public ErrorMessage resourceNotFoundException(Exception ex, WebRequest request) {
LOG.error(ex.getMessage());
return getErrorMessage(ex, ErrorCode.RESOURCE_NOT_FOUND);
}
/**
* @param ex thrown exception
* @param errorCode to be returned to the client in message
* @return the error message with all attributes
*/
private ErrorMessage getErrorMessage(Exception ex, ErrorCode errorCode) {
return new ErrorMessage(
errorCode.code,
new Date(),
ex.getMessage(),
errorCode.description);
}
/**
* @return the error message with all attributes
*/
private ErrorMessage getErrorMessage() {
return new ErrorMessage(
ErrorCode.INTERNAL_ERROR.code,
new Date(),
"Error while proceeding a joinPoint, unhandled exception: see log messages for more details.",
ErrorCode.INTERNAL_ERROR.description);
}
}
这是我从邮递员那里调用方法后得到的:
我在控制台上得到的:
INFO |2021-11-17T08:51:48,898|88D0657C2A8042FDBD32C05E96280791| [http-nio-8080-exec-1] com.obs.dqsc.api.controller.CustomerController - Entered in CustomerController.findAllCustomersByExtractionDate(hello)
hello
INFO |2021-11-17T08:51:48,903|88D0657C2A8042FDBD32C05E96280791| [http-nio-8080-exec-1] com.obs.dqsc.api.controller.CustomerController - Exit from CustomerController.findAllCustomersByExtractionDate(..); Execution time: 2 ms;
我在 pom.xml 中的依赖项:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.5.12</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
谁能告诉我我错过了什么?
我缺少启动验证器来让它工作,所以我所要做的就是添加这个依赖项:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>