簡體   English   中英

Spring 驗證在服務層級別不起作用

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM