4

这是我的控制器。它接受multipart/form-data具有两个字段的请求,form并且file. form字段是 a ,字段MyObjectfilea MultipartFile。这两个变量都用 注释@Valid,因此,我希望 Spring 调用Validator每个字段的类。但是,这只发生在MyObject,而不是MultipartFile

@RequestMapping("/api")
@RestController
public class Controller {

    private MyObjectRepository repo;
    private MyObjectValidator myObjectValidator;
    private FileValidator fileValidator;

    @Autowired
    public myObjectController(MyObjectRepository repo, MyObjectValidator myObjectValidator,
                              FileValidator fileValidator) {
        this.repo = repo;
        this.myObjectValidator = myObjectValidator;
        this.fileValidator = fileValidator;
    }

    @InitBinder("form")
    public void initMyObjectBinder(WebDataBinder binder) {
        binder.setValidator(this.myObjectValidator);
    }

    @InitBinder("file")
    public void initFileBinder(WebDataBinder binder) {
        binder.setValidator(this.fileValidator);
    }

    @PostMapping("myObject")
    @ResponseStatus(HttpStatus.CREATED)
    @ResponseBody
    public MyObject createMyObject(@RequestPart("form") @Valid MyObject myObject,
                                   @RequestPart("file") @Valid MultipartFile... file) {
        return repo.save(myObject);
    }
}

MyObjectValidator的被​​触发了,但我FileValidator的没有被触发。这两个类都实现了 SpringValidator接口。MyObjectValidator.supports(Class<?> aClass) 调用,而FileValidator.supports(Class<?> aClass)从未调用。除此之外, myController运行良好,并且努力将对象保存到 my repo.

这里可能是什么问题?我读过类似的问题,常见的错误是没有在@InitBinder注释中使用适当的参数,或者将@InitBinder方法设置为private而不是public,但这都不适用于我的情况。

这个丑陋的解决方法做了它应该做的,但它不像 Spring。我在方法中FileValidator手动调用我的Controller.createMyObject方法,而不是让 Spring 通过@Valid注释自动调用它。

@PostMapping("myObject")
@ResponseStatus(HttpStatus.CREATED)
@ResponseBody
public MyObject createMyObject(@RequestPart("form") @Valid MyObject myObject,
                               @RequestPart("file") @Valid MultipartFile... file) {
    if (fileValidator.supports(file.getClass())) {
        Errors errors = new BeanPropertyBindingResult(file, "Uploaded file.");
        fileValidator.validate(file,errors);
        if (errors.hasErrors()) {
            throw new BadRequestException();
        }
    }
    return repo.save(myObject);
}

编辑:我Validator根据要求包括了我的课程。

import org.springframework.validation.Validator;

public abstract class AbstractValidator implements Validator {
    // One shared method here.
}
public class FileValidator extends AbstractValidator {

    public boolean supports(Class<?> aClass) { // This method is never triggered.
        boolean isSingleFile = MultipartFile.class.isAssignableFrom(aClass); // This line has a breakpoint, it is never triggered in the debugger.
        boolean isFileArray = aClass.equals(MultipartFile[].class);
        return (isSingleFile || isFileArray);
    }

    public void validate(Object o, Errors e) {
        //Several validation methods go here.
    }
public class MyObjectValidator extends AbstractValidator {

    public boolean supports(Class<?> aClass) { // This method is triggered.
        return (MyObject.class.equals(aClass)); // This line has a breakpoint, and it is always triggered in the debugger.
    }

    public void validate(Object o, Errors e) {
        // Several validation methods go here.
    }

编辑:我像 NiVeR 建议的那样对我的代码进行了一些更改,删除了 varargs 参数并相应地更改了我的代码FileValidator.supports(Class<?> aClass),但行为仍然相同。

在 Controller.java 中:

@PostMapping("myObject")
@ResponseStatus(HttpStatus.CREATED)
@ResponseBody
public MyObject createMyObject(@RequestPart("form") @Valid MyObject myObject, @RequestPart("file") @Valid MultipartFile file) {
    return repo.save(myObject);
}

在 FileValidator.java 中:

public boolean supports(Class<?> aClass) {
    return MultipartFile.class.isAssignableFrom(aClass);
}
4

2 回答 2

1

我认为问题与可变Multipart...参数有关。在supports验证器的方法中,您正在检查数组,Multipart但我怀疑这不是正确的方法。作为一个试验,我会制作Multipart一个单一的对象参数(并相应地更改验证器)来测试它是否以这种方式工作。

于 2018-07-17T12:25:55.720 回答
0

@Magnus 我认为您必须在所有验证器类中添加注释,例如。

@Component
public class MyObjectValidator extends AbstractValidator {

    public boolean supports(Class<?> aClass) { //This method is triggered.
        return (MyObject.class.equals(aClass));
    }

    public void validate(Object o, Errors e) {
        //Several validation methods goes here.
    }
}
于 2018-07-17T11:50:41.483 回答