我目前有一个采用 MultipartFile 的 Spring MVC 控制器
@RequestMapping(method = RequestMethod.POST)
public String doUpload(@RequestParam("file") final MultipartFile file) {
/* ... */
}
Run Code Online (Sandbox Code Playgroud)
该文件包含将用于创建域对象列表的 csv 数据,每行一个。这是有效的。
我为行数据编写了一个转换器:
class MyObjectConverter implements org.springframework...Converter<String[], MyObject> {
/* ... */
}
Run Code Online (Sandbox Code Playgroud)
和文件的验证器
class UploadFileValidator implements org.springframework.validation.Validator {
/* ... */
}
Run Code Online (Sandbox Code Playgroud)
我有一个表格可以上传:
<form method="post"
action="<@spring.url '/upload'/>"
enctype="multipart/form-data">
<input id="upload" type="file" name="file"/>
<input type="submit" id="uploadButton"/>
</form
Run Code Online (Sandbox Code Playgroud)
但我真正想做的是将它们联系在一起,这样我的控制器就可以有一个类似的方法
@RequestMapping(method = RequestMethod.POST)
public String doUpload(
@Valid final List<MyObject> objList,
final BindingResult result) { ...}
Run Code Online (Sandbox Code Playgroud)
我知道 Spring MVC 框架支持转换器和验证器,但我不明白如何让它们协同工作。
首先,我将 MultipartFile 包装在一个表单支持对象中:
public class UploadBackingForm {
private MultipartFile multipartFile;
/* ... getter/setter */
}
Run Code Online (Sandbox Code Playgroud)
然后我绑定到我的表单:
<form method="post" enctype="multipart/form-data">
<@spring.bind "backingform.*"/>
<tr>
<td><@spring.formInput 'backingform.multipartFile' '' 'file' /></td>
<td> <button type="submit">Upload</button> </td>
</tr>
</form>
Run Code Online (Sandbox Code Playgroud)
在控制器中,我分配了一个验证器:
@InitBinder
public void initBinder(final DataBinder binder) {
binder.setValidator(new UploadValidator());
}
Run Code Online (Sandbox Code Playgroud)
这是验证器:
public class UploadValidator implements Validator {
private final Converter<String[], MyObject> converter
= new MyObjectConverter();
@Override
public boolean supports(final Class<?> clazz) {
return UploadBackingForm.class.equals(clazz);
}
@Override
public void validate(final Object target, final Errors errors) {
final UploadBackingForm backingForm = (UploadBackingForm) target;
final MultipartFile multipartFile = backingForm.getMultipartFile();
final List<String[]> uploadData = /* parse file */
for (final String[] uploadDataRow : uploadData){
try {
converter.convert(uploadDataRow);
} catch (IllegalArgumentException e) {
errors.rejectValue("multipartFile", "line.invalid", ...);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
验证器使用转换器将行项目转换为 MyObj。
doPost 方法现在看起来像这样:
@RequestMapping(method = RequestMethod.POST)
public String doUpload(
@Valid @ModelAttribute("backingform") UploadBackingForm backingForm,
final BindingResult result,
final HttpSession session) throws IOException {
final UploadConverter converter = new UploadConverter();
final List<MyObj> imports =
converter.convert(backingForm.getMultipartFile().getInputStream());
}
Run Code Online (Sandbox Code Playgroud)
UploadConverter 与 UploadValidator 非常相似:
public class UploadConverter implements Converter<InputStream, List<MyObject>> {
private final Converter<String[], MyObject> converter = new MyObjectConverter();
@Override
public List<MyObject> convert(final InputStream source) {
final List<String[]> detailLines = /* ... getDetailLines */
final List<MyObject> importList =
new ArrayList<MyObject>(detailLines.size());
for (final String[] row : detailLines) {
importList.add(converter.convert(row));
}
return importList;
}
}
Run Code Online (Sandbox Code Playgroud)
唯一的问题是验证和转换过程是一样的。幸运的是,上传的文件不会很大,因此重复工作不是大问题。
| 归档时间: |
|
| 查看次数: |
14524 次 |
| 最近记录: |