[英]Spring Validation not working on Service Layer level
我有一個 Spring 引導項目( 2.3.3 ),我想在其中驗證服務層方法輸入參數。 所以在我的 pom.xml 我添加了
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
因為它不再是父母的一部分。 接下來我有我的服務方法接口和實現服務方法。 我的實施服務用@Validated 注釋,我的方法看起來像
public void deleteGreetingById(@NotNull(message = "greetingId must not be null.")Integer greetingId) {
我還讀到驗證默認僅綁定到 controller 層。 因此,為了也為服務層啟用它,我添加了一個 PostValidationProcesser。
@Configuration
public class MethodValidationConfig {
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
}
當我現在使用 null 作為輸入參數執行我的測試時,什么都沒有發生,也沒有拋出異常。 當我做
Assert.notNull(greetingId,"greetingId must not be null");
在該方法內部,會像預期的那樣拋出 InvalidParameterException。 但我更喜歡基於注釋的驗證,因為整個 class 對象的 @Valid 驗證作為輸入參數。
有人可以解釋為什么不觸發驗證嗎?
編輯:
@RestController
public class GreetingsConsumerController {
private final GreetingsService greetingsService;
public GreetingsConsumerController(GreetingsService greetingsService) {
this.greetingsService = greetingsService;
}
@PostMapping(value = "/greetings", consumes = MediaType.APPLICATION_JSON_VALUE)
public Greeting createGreeting( @RequestBody @Valid GreetingDto greetingDto){
return greetingsService.addGreeting(greetingDto);
}
@GetMapping(value = "/greetings/{id}")
public Greeting getGreetingById(@PathVariable Integer id){
return greetingsService.findGreetingById(id);
}
@GetMapping(value = "/greetings")
public List<Greeting> getAllGreetings(){
return greetingsService.findAllGreetings();
}
@DeleteMapping(value = "/greetings/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteGreetingById(@PathVariable Integer id){
greetingsService.deleteGreetingById(id);
}
}
界面:
public interface GreetingsService {
Greeting findGreetingById(Integer greetingId);
List<Greeting> findAllGreetings();
Greeting addGreeting( GreetingDto greetingDto);
void deleteGreetingById( Integer greetingId);
}
接口實現:
@Service
@Validated
public class GreetingsServiceImpl implements GreetingsService {
.
.
.
@Override
public void deleteGreetingById(@NotNull(message = "greetingId must not be null. ") Integer greetingId) {
...
}
}
我還將 Bean 添加到我的 SpringBootApplication 但仍然沒有拋出異常。
@SpringBootApplication
public class GreetingsConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(GreetingsConsumerApplication.class, args
);
}
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
}
下面是在服務層驗證 model 的示例示例。
class TestModel{
@NotNull
private String name;
}
TestModel model= new TestModel();
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<TestModel>> violations = validator.validate(model);
我“解決”了這個問題。 我的錯誤是我錯誤地配置了我的測試。 我配置了測試
@Extendwith(SpringExtension.class)
因為我之前只編寫了單元測試而不使用此 class 中的上下文。 顯然,以這種方式使用參數驗證,您必須使用使整個場景成為集成測試的 Context。 我很高興它現在可以工作,對於不必要的討論我深表歉意。 我也應該在代碼中發布我的測試。
雖然我很高興它現在可以工作,但我也有點困惑。 一般來說,我不想僅僅為了約束驗證而啟動 Spring 上下文。 但這是另一個問題。
當您有實現接口的服務並引用該接口時,您需要在接口上進行驗證注釋,而不是實現 class。 將驗證注釋添加到 GreetingsService 接口。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.