这是我的控制器。它接受一个multipart/form-data
有两个字段的请求,form
and file
. The form
字段是一个MyObject
, the file
字段是一个MultipartFile
。两个变量都注释为@Valid
,因此,我希望 Spring 调用Validator
每个各自领域的类。然而,这只发生在MyObject
, and not with 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);
}
}
My MyObjectValidator
被触发了,但是我的FileValidator
没有被触发。这两个类都实现了 SpringValidator
界面。MyObjectValidator.supports(Class<?> aClass)
is称为,而FileValidator.supports(Class<?> aClass)
is never叫。除此之外,我的Controller
运行完美,并努力将对象保存到我的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)
因此,但行为仍然相同。
在控制器.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);
}