Spring @RestController:验证@ResponseBody(而不是@RequestBody)

Spring @RestController:验证@ResponseBody(而不是@RequestBody),spring,spring-mvc,Spring,Spring Mvc,我如何实现@ResponseBody(在我的例子中是somepojoininterface类型的类)的自动验证(比如通过JSR-303验证)。如果验证失败,处理程序将抛出一个异常,可以在一些@ControllerAdvice注释类中处理 我的代码到目前为止 @RestController public class MyRestController { @GetMapping(value = "validate", produces = MediaType.APPLICATION_JSO

我如何实现@ResponseBody(在我的例子中是somepojoininterface类型的类)的自动验证(比如通过JSR-303验证)。如果验证失败,处理程序将抛出一个
异常
,可以在一些
@ControllerAdvice
注释类中处理

我的代码到目前为止

@RestController
public class MyRestController {

    @GetMapping(value = "validate", produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody 
    protected SomePojo validateResponse() {
        return new SomePojo();
    }
}

@ControllerAdvice
class GlobalControllerExceptionHandler {

    @ResponseStatus(HttpStatus.XXX)
    @ExceptionHandler(MyResponseValidationException.class)
    public void handleResponseValidationException() {
        // ...
    }
}

public class SomePojo implements SomePojoInterface {

    @NotNull
    private String someValue;

    // getter / setter
}

如果您已经为类SomePojo添加了注释,那么:

     @GetMapping(value = "validate", produces = MediaType.APPLICATION_JSON_VALUE)
        protected SomePojo validateResponse() {
           ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
           Validator validator = factory.getValidator();

           SomePojo somePojo = new SomePojo(null);

          Set<ConstraintViolation<Car>> constraintViolations = validator.validate(somePojo);
          // Other stuff
        }
@GetMapping(value=“validate”,products=MediaType.APPLICATION\u JSON\u value)
受保护的SomePojo validateResponse(){
ValidatorFactory=Validation.buildDefaultValidatorFactory();
Validator Validator=factory.getValidator();
SomePojo SomePojo=新的SomePojo(null);
Set constraintViolations=validator.validate(somePojo);
//其他东西
}

@有效的注释可供请求。更多的例子来自他们的网站。我不确定您想要验证的是什么

如果您已经为类SomePojo添加了注释,那么:

     @GetMapping(value = "validate", produces = MediaType.APPLICATION_JSON_VALUE)
        protected SomePojo validateResponse() {
           ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
           Validator validator = factory.getValidator();

           SomePojo somePojo = new SomePojo(null);

          Set<ConstraintViolation<Car>> constraintViolations = validator.validate(somePojo);
          // Other stuff
        }
@GetMapping(value=“validate”,products=MediaType.APPLICATION\u JSON\u value)
受保护的SomePojo validateResponse(){
ValidatorFactory=Validation.buildDefaultValidatorFactory();
Validator Validator=factory.getValidator();
SomePojo SomePojo=新的SomePojo(null);
Set constraintViolations=validator.validate(somePojo);
//其他东西
}

@有效的注释可供请求。更多的例子来自他们的网站。我不确定您想要验证什么

我通过
@RestControllerAdvice
实现了这一点

@RestControllerAdvice
public class RestPostProcessingAdvice implements ResponseBodyAdvice<SomePojoInterface> {

    @Inject
    private Validator validator;

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        if(doSomeChecksIfEligiable(returnType, converterType)) {
            return true;
        }
        return false;
    }

    @Override
    public SomePojoInterface beforeBodyWrite(SomePojoInterface body, MethodParameter returnType,
            MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType,
            ServerHttpRequest request, ServerHttpResponse response) {
        Set<ConstraintViolation<Object>> constraintViolations = validator.validate(body);
        if(constraintViolations.size() > 0) {
            response.setStatusCode(HttpStatus.XXX);
            LOG.fatal("Sorry, I'm sending crap");
        }

        return body;
    }
}
@RestControllerAdvice
公共类RestPostProcessingAdvice实现ResponseBodyAdvice{
@注入
私人验证器;
@凌驾
公共布尔支持(MethodParameter returnType,Class>converterType){
if(DOSOMECHECKSIFELIABLE(返回类型、转换器类型)){
返回true;
}
返回false;
}
@凌驾
BodyWrite之前的公共SomePoJoinInterface(SomePoJoinInterface主体,方法参数returnType,
MediaType selectedContentType,类>selectedConverterType,
ServerHttpRequest请求,ServerHttpResponse响应){
Set constraintViolations=validator.validate(body);
if(constraintViolations.size()>0){
response.setStatusCode(HttpStatus.XXX);
LOG.fatal(“对不起,我在发送垃圾”);
}
返回体;
}
}

请注意,抛出一个
异常
并在一个
@ExceptionHandler
中捕获它,该异常处理程序将在
@ResponseBody
中发送同一个(mofied)对象,这可能会导致无休止的循环,由于将再次检查对象,因此我通过
@RestControllerAdvice
成功地实现了这一点

@RestControllerAdvice
public class RestPostProcessingAdvice implements ResponseBodyAdvice<SomePojoInterface> {

    @Inject
    private Validator validator;

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        if(doSomeChecksIfEligiable(returnType, converterType)) {
            return true;
        }
        return false;
    }

    @Override
    public SomePojoInterface beforeBodyWrite(SomePojoInterface body, MethodParameter returnType,
            MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType,
            ServerHttpRequest request, ServerHttpResponse response) {
        Set<ConstraintViolation<Object>> constraintViolations = validator.validate(body);
        if(constraintViolations.size() > 0) {
            response.setStatusCode(HttpStatus.XXX);
            LOG.fatal("Sorry, I'm sending crap");
        }

        return body;
    }
}
@RestControllerAdvice
公共类RestPostProcessingAdvice实现ResponseBodyAdvice{
@注入
私人验证器;
@凌驾
公共布尔支持(MethodParameter returnType,Class>converterType){
if(DOSOMECHECKSIFELIABLE(返回类型、转换器类型)){
返回true;
}
返回false;
}
@凌驾
BodyWrite之前的公共SomePoJoinInterface(SomePoJoinInterface主体,方法参数returnType,
MediaType selectedContentType,类>selectedConverterType,
ServerHttpRequest请求,ServerHttpResponse响应){
Set constraintViolations=validator.validate(body);
if(constraintViolations.size()>0){
response.setStatusCode(HttpStatus.XXX);
LOG.fatal(“对不起,我在发送垃圾”);
}
返回体;
}
}

请注意,抛出一个
异常
并在一个
@ExceptionHandler
中捕获它,该异常处理程序将在
@ResponseBody
中发送同一个(mofied)对象,这可能会导致一个无休止的循环,因为该对象将在此
@RestControllerAdvice
中再次被检查。您是否尝试过一些示例?像这样的。在Spring 3.2中,您可以添加@Valid annotation;)那么我应该把@Valid注释放在哪里呢?我正在尝试验证响应对象。哦,这是响应!然后您必须创建验证器。我将发布Ansery您不信任自己的数据?我们的回复数据来自多个国外系统,并在我们这方面进行了整合。所以,不,我不相信这些数据。我主要想在发送无效数据时进行日志记录。您是否用一些示例进行了尝试?像这样的。在Spring 3.2中,您可以添加@Valid annotation;)那么我应该把@Valid注释放在哪里呢?我正在尝试验证响应对象。哦,这是响应!然后您必须创建验证器。我将发布Ansery您不信任自己的数据?我们的回复数据来自多个国外系统,并在我们这方面进行了整合。所以,不,我不相信这些数据。我主要想在发送无效数据时进行日志记录。如上所述,请求使用@Valid,因为被备份的用户没有创建它。因为backed创建了响应,所以它有望被创建,所以它不是无效的(类不变)@Hrabosh,我知道如何验证。我指的是我可以在某个阶段触发的某个处理程序,以便“在后台”执行此操作。@user871611然后我不知道。对于请求,我通过
@Valid
知道它,但是对于响应,我不知道其他的方式,然后我回答,对不起:(如上所述,@Valid用于请求,因为被备份者没有创建它。因为被备份者创建响应,所以它可以被创建,所以它不是无效的(类不变)@Hrabosh,我知道如何验证。我指的是某个处理程序,我可以在某个阶段触发它来“在后台”执行此操作。@user871611然后我不知道。我知道它是通过
@Valid
进行请求的,但对于响应我不知道
@RestControllerAdvice
public class RestPostProcessingAdvice implements ResponseBodyAdvice<SomePojoInterface> {

    @Inject
    private Validator validator;

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        if(doSomeChecksIfEligiable(returnType, converterType)) {
            return true;
        }
        return false;
    }

    @Override
    public SomePojoInterface beforeBodyWrite(SomePojoInterface body, MethodParameter returnType,
            MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType,
            ServerHttpRequest request, ServerHttpResponse response) {
        Set<ConstraintViolation<Object>> constraintViolations = validator.validate(body);
        if(constraintViolations.size() > 0) {
            response.setStatusCode(HttpStatus.XXX);
            LOG.fatal("Sorry, I'm sending crap");
        }

        return body;
    }
}