2013-08-06 29 views
21

Tôi muốn đăng ký một tùy chỉnh HandlerMethodArgumentResolver mà có thể xử lý các phương pháp định nghĩa @Controller xử lý sauSpring MVC @Valid Validation với tùy chỉnh HandlerMethodArgumentResolver

@RequestMapping(method = RequestMethod.POST) 
public String createDomain(@Valid Domain domain, BindingResult errors, @RequestParam("countryId") Long countryId) { 

Tôi có thể đăng ký giải quyết của tôi, mà chỉ tạo ra một đối tượng Domain thông qua các thông số yêu cầu, bằng cách ghi đè addArgumentResolver() từ WebMvcConfigurerAdapter. Khi Spring cố gắng giải quyết tham số Domain, nó đi qua danh sách HandlerMethodArgumentResolver (có rất nhiều) và chọn số đầu tiên là supports().

Trong ví dụ trên, mặc dù phân giải của tôi sẽ được gọi và tranh luận Domain của tôi sẽ được khởi tạo, chú thích @Valid sẽ không đã được xử lý resolver cho BindingResult, một ErrorsMethodArgumentResolver sẽ thất bại vì nó đòi hỏi một @ModelAttribute, @RequestBody hoặc đối số @RequestPart trong phương thức xử lý mà tôi không có.

Nếu tôi cố gắng sửa chữa nó bằng cách thêm @ModelAttribute

@RequestMapping(method = RequestMethod.POST) 
public String createDomain(@Valid @ModelAttribute Domain domain, BindingResult errors, @RequestParam("countryId") Long countryId) { 

một thực hiện HandlerMethodArgumentResolver, ModelAttributeMethodProcessor, sẽ được kiểm tra đầu tiên với supports() và giải quyết các tranh cãi (với @ModelAttribute@Valid) trước khi phân giải tùy chỉnh của tôi. BindingResult sẽ không thành công, nhưng tôi sẽ không có hành vi tạo tùy chỉnh của mình trên phiên bản Domain.

Tôi chỉ có thể sao chép và dán mã để xác thực và thêm vào mô hình trong ModelAttributeMethodProcessor, nhưng tôi đã hy vọng có cách dễ dàng hơn để giải quyết tham số và thực hiện xác thực mà không thêm đối tượng vào mô hình. Có cách nào không?

Trả lời

8

Mô tả hay về sự cố bạn đang gặp phải.

Tôi đã kiểm tra mã mà bạn đã vạch ra và đã đi đến cùng một kết luận mà bạn có - không có cách tích hợp để có cả tùy chỉnh HandlerMethodArgumentResolver cũng như @Valid xác thực liên quan được áp dụng cùng một lúc, lựa chọn duy nhất là làm những gì mà ModelAttributeMethodProcessor thực hiện để kiểm tra xem tham số có chú thích @Valid và gọi mã liên quan đến logic hợp lệ hay không.

Bạn có thể lấy được số HandlerMethodResolverArgumentResolver từ ModelAttributeMethodProcessor và gọi super.validateIfApplicable(..) ít nhất theo cách này mã hiện tại được thừa hưởng.

4

Nó có thể là quá muộn, nhưng HandlerMethodArgumentResolver của bạn được WebDataBinderFactory đối tượng như là đối số cuối cùng, sau đó, để treo lên xác nhận, chỉ cần thêm này để thực hiện giải quyết của bạn:

Object resolvedObject = // your logic 
if(parameter.hasParameterAnnotation(Valid.class){ 
      binderFactory.createBinder(webRequest,resolvedObject,"resolvedObjectLogicalName").validate(); 
} 
+0

Rất rất hiệu quả. Cảm ơn. – Khodabakhsh

+0

Đây phải là câu trả lời được chấp nhận, vì nó hoạt động hoàn hảo mà không cần phải lấy được từ 'HandlerMethodResolverArgumentResolver'. – msparer

+0

@Alexander Tôi đã thử điều này, nhưng nó ném java.lang.IllegalStateException tức là .. "Một đối số lỗi/BindingResult dự kiến ​​sẽ ngay lập tức sau đối số thuộc tính mô hình trong chữ ký của phương thức điều khiển". – Sankar

Các vấn đề liên quan