【发布时间】:2014-10-17 02:53:01
【问题描述】:
我有一个包含站点列表的客户实体,如下所示:
public class Customer {
@Id
@GeneratedValue
private int id;
@NotNull
private String name;
@NotNull
@AccountNumber
private String accountNumber;
@Valid
@OneToMany(mappedBy="customer")
private List<Site> sites
}
public class Site {
@Id
@GeneratedValue
private int id;
@NotNull
private String addressLine1;
private String addressLine2;
@NotNull
private String town;
@PostCode
private String postCode;
@ManyToOne
@JoinColumn(name="customer_id")
private Customer customer;
}
我正在创建一个表单以允许用户通过输入名称和帐号并提供网站的 CSV 文件(格式为“addressLine1”、“addressLine2”、“town”、 “邮政编码”)。需要验证用户的输入并将错误返回给他们(例如“文件不是 CSV 文件”、“第 7 行出现问题”)。
我首先创建了一个 Converter 来接收 MultipartFile 并将其转换为站点列表:
public class CSVToSiteConverter implements Converter<MultipartFile, List<Site>> {
public List<Site> convert(MultipartFile csvFile) {
List<Site> results = new List<Site>();
/* open MultipartFile and loop through line-by-line, adding into List<Site> */
return results;
}
}
这可行,但没有验证(即,如果用户上传二进制文件或其中一个 CSV 行不包含城镇),似乎没有办法将错误传回(并且转换器似乎不是执行验证的正确位置)。
然后我创建了一个表单支持对象来接收 MultipartFile 和 Customer,并对 MultipartFile 进行验证:
public class CustomerForm {
@Valid
private Customer customer;
@SiteCSVFile
private MultipartFile csvFile;
}
@Documented
@Constraint(validatedBy = SiteCSVFileValidator.class)
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SiteCSVFile {
String message() default "{SiteCSVFile}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
public class SiteCSVFileValidator implements ConstraintValidator<SiteCSVFile, MultipartFile> {
@Override
public void initialize(SiteCSVFile siteCSVFile) { }
@Override
public boolean isValid(MultipartFile csvFile, ConstraintValidatorContext cxt) {
boolean wasValid = true;
/* test csvFile for mimetype, open and loop through line-by-line, validating number of columns etc. */
return wasValid;
}
}
这也行得通,但我必须重新打开 CSV 文件并循环访问它以实际填充客户中的列表,这似乎并不那么优雅:
@RequestMapping(value="/new", method = RequestMethod.POST)
public String newCustomer(@Valid @ModelAttribute("customerForm") CustomerForm customerForm, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "NewCustomer";
} else {
/*
validation has passed, so now we must:
1) open customerForm.csvFile
2) loop through it to populate customerForm.customer.sites
*/
customerService.insert(customerForm.customer);
return "CustomerList";
}
}
我的 MVC 配置将文件上传限制为 1MB:
@Bean
public MultipartResolver multipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(1000000);
return multipartResolver;
}
是否有一种同时转换和验证的弹簧方式,而无需打开 CSV 文件并循环两次,一次用于验证,另一次用于实际读取/填充数据?
【问题讨论】:
标签: java validation spring-mvc csv