2012-04-04 28 views
5

mvc mùa xuân mới nhất, sử dụng freemarker.Bối rối như làm thế nào để xác nhận hình thức mùa xuân mvc, lựa chọn của tôi là gì?

Hy vọng một người nào đó có thể cho tôi biết các tùy chọn của tôi là gì về việc xác thực biểu mẫu có mvc mùa xuân và cách đề xuất sẽ là thực hiện điều này.

Tôi có biểu mẫu không ánh xạ trực tiếp vào một mô hình, nó sẽ được sử dụng để khởi tạo 2 đối tượng mô hình mà sau đó tôi sẽ cần xác thực và nếu chúng vượt qua, tôi sẽ lưu chúng .

Nếu không thành công, tôi muốn quay lại biểu mẫu, điền trước các giá trị với những gì người dùng đã nhập và hiển thị thông báo lỗi.

Tôi đã đọc ở đâu đó về 2 phương pháp, một lần trong số đó tôi đã làm và hiểu cách hoạt động:

@RequestMapping(...., method = RequestMethod.POST) 
public ModelAndView myMethod(@Valid MyModel, BindingResult bindingResult) { 
    ModelAndView mav = new ModelAndView("some/view"); 
    mav.addObject("mymodel", myModel); 

    if(bindingResult.hasErrors()) { 
    return mav; 
    } 

} 

Bây giờ điều này đã làm việc nếu hình thức của tôi ánh xạ trực tiếp đến hình thức, nhưng trong hoàn cảnh của tôi tôi có:

  1. trường biểu mẫu không ánh xạ tới bất kỳ mô hình cụ thể nào, chúng có một vài thuộc tính từ 2 mô hình.

  2. trước khi xác nhận occurrs, tôi cần phải tạo ra các mô hình 2 bằng tay, thiết lập các giá trị từ các hình thức, và tự thiết lập một số thuộc tính cũng:

  3. Gọi validate trên cả hai mô hình (MODEL1, MODEL2), và thêm các thông báo lỗi này đến bộ sưu tập lỗi mà tôi cần phải quay lại cùng một trang xem nếu mọi thứ không hoạt động.

  4. khi biểu mẫu đăng bài, tôi phải thực hiện một số cuộc gọi cơ sở dữ liệu và dựa trên những kết quả đó có thể cần thêm thông báo bổ sung vào bộ sưu tập lỗi.

Ai đó có thể cho tôi biết cách thực hiện loại xác thực này?

Pseudo mã bên dưới:

Model1 model1 = new Model1(); 
    Model2 model2 = new Model2(); 

    // manually or somehow automatically set the posted form values to model1 and model2. 

    // set some fields manually, not from posted form 
    model1.setProperty10(GlobalSettings.getDefaultProperty10()); 
    model2.setProperty11(GlobalSettings.getDefaultProperty11()); 

    // db calls, if they fail, add to errors collection 

    if(bindingResult.hasErrors()) { 
    return mav; 
    } 

    // validation passed, save 
    Model1Service.save(model1); 
    Model2Service.save(model2); 

    redirect to another view 

Cập nhật

Tôi đã sử dụng các chú thích JSR 303 trên mô hình của tôi ngay bây giờ, và nó sẽ tuyệt vời nếu tôi có thể sử dụng những vẫn còn.

Cập nhật II

Xin mời đọc kỹ mô tả tiền thưởng dưới đây cho một bản tóm tắt về những gì tôi đang tìm kiếm.

Trả lời

8

Dựa trên trải nghiệm tương tự, tôi đề xuất những điều sau đây và ở bên cạnh, tôi có một nhận xét về bước cuối cùng về phương pháp mà bạn muốn thực hiện. Tôi sử dụng danh sách các bước được đánh số của bạn.

Bước 1: Mẫu Bean

Có hai cách cho việc này.Phương pháp đơn giản là để xác định một bean hình thức (mà tôi đoán bạn đã làm):

class MyModel { 
    private Model1 model1; 
    private Model2 model2; 
    // standard Java bean stuff 
} 

Một cách chính xác hơn là để thực sự xác định MyModel như vậy mà tôi chỉ mượn các lĩnh vực đòi hỏi từ Model1Model2 nhưng Tôi không chắc chắn nếu điều này phù hợp với cách của bạn.

Bước 2: Binding dữ liệu

mùa xuân thực hiện điều này cho bạn nếu bạn có ví dụ form cấu trúc theo quan điểm của bạn:

<form:form modelAttribute="myModel"> 
    <form:input path="model1.somePropertyToBeSet" /> 
</form:form> 

Bước 3: Xác nhận

Sử dụng Spring custom validations, bạn có thể xác định lệnh giữ hạn chế om:

@interface Model1Constraint {} 
@interface Model2Constraint {} 

class MyModel1 { 

    @Model1Constraint 
    private Model1 model1; 

    @Model2Constraint 
    private Model2 model2; 

    // ... 

} 

Sau đó đăng ký xác nhận của bạn tùy chỉnh cho những hạn chế tùy chỉnh:

class Model1ConstraintValidator implements ConstraintValidator<Model1Constraint, Model1> { 
// implementation of isValid and initalize 
} 

Và tương tự cho Model2Constraint. Sử dụng trình xác thực tùy chỉnh, bạn có thể kiểm tra xem bạn cần đảm bảo logic gì trước khi MyModel được chuyển vào phương thức xử lý yêu cầu. Tôi cũng giả sử rằng bạn đã sử dụng <mvc:annotation-driven /> để Spring đăng ký trình xác thực; nếu không, bạn nên cấu hình chúng.

Bước 4: Mô hình xử lý Tuỳ chỉnh trước khi xử lý yêu cầu

ý tưởng ban đầu của bạn là sử dụng một số dữ liệu kết dính cho công việc này. Trong mô tả của bạn, bạn cũng đề cập rằng việc xử lý dữ liệu này không phụ thuộc vào dữ liệu đến từ dữ liệu biểu mẫu.

Về thiết kế và mô đun, tôi không tin rằng một chất kết dính dữ liệu là một nơi tốt cho một mục đích như vậy. Thứ hai, vì không có sự phụ thuộc dữ liệu vào biểu mẫu, lý do chính cho bạn là cho phép xử lý lỗi ràng buộc dữ liệu.

Vì vậy, đề xuất của tôi là chúng ta hãy nói rằng bây giờ bạn đang ở trong public ModelAndView myMethod(@Valid MyModel model, BindingResult bindingResult). Có lẽ, bạn có quyền truy cập vào các bean dịch vụ khác tại đây. Vì vậy, bạn có thể có một phương pháp trong một số bean dịch vụ có thể refine hoặc prepare (chỉ có tên) là model mà bạn đã điền vào thời điểm này. Dựa trên ngoại lệ hoặc bất kỳ cơ chế nào khác phù hợp với bạn, bạn có thể sử dụng bindingResult để trả lại lỗi.

Là một đề xuất khác, bạn cũng có thể tận dụng lợi thế của Spring interceptors nếu bạn muốn có thêm DI/IoC cách để làm điều đó. Nhưng theo cách này, bạn nên trích xuất MyModel từ ModelAndView trong quá trình chặn và tiếp tục.

Tôi hy vọng điều này sẽ hữu ích.

0

Hibernate Validator 4.2 hỗ trợ xác thực cấp phương thức. Bạn có thể cấu trúc lại mã của bạn một chút để truyền hai mô hình trong một phương thức và xác nhận chúng.

http://java.dzone.com/articles/method-validation-spring-31

bạn có thể có một cái gì đó như thế này

public void persistUser(@NotNull @Valid Model1 model1, @NotNull @Valid Model2 model2) { 

     //continue ... 
} 
0

Đây là một vấn đề không bình thường, vì nó thường làm cho ý nghĩa nhất để xác nhận người dùng nhập vào, vì đó là dữ liệu chúng tôi không thể điều khiển. Với điều đó được nói, và vì tôi chắc rằng bạn đã biết rằng ...

Một tùy chọn sẽ là sử dụng api xác thực JSR 303 trực tiếp để xác thực đối tượng mô hình của bạn sau khi chúng được nhập từ người dùng, cơ sở dữ liệu , vv ..

Dưới đây là một ví dụ:

@RequestMapping(value=...) 
public String myMethod(MyForm form, Model m) { 

    ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); 
    Validator validator = factory.getValidator(); 

    Model1 model1 = createModel1FromUserInput(form); 
    Model2 model2 = createModel2FromUserInput(form); 

    Set<ConstraintViolation<?>> modelViolations = validator.validate(model1); 
    modelViolations.add(validator.validate(model2)); 
    if(modelViolations.size() != 0) { 
     m.addAttribute("violations", modelViolations); 
     m.addAttribute("form", myForm); // add the form back to the model so it is populated 
     return "formPage"; 
    } 
    return "successPage"; 
} 

Bạn có thể thích để ràng buộc vào một BindingResult mùa xuân hoặc một tập hợp các sai sót. Tôi đã không kiểm tra các mã sau đây, và tôi không phải là rất thoải mái làm việc trực tiếp với BindingResult, vì vậy nó sẽ đòi hỏi tinh chỉnh:

BindingResult result = ... // not sure about the constructor 
for(ConstraintViolation<?> violation : modelViolations) { 
     result.addError(new ObjectError(violation.getPropertyPath().toString(),violation.getMessage())); 
} 

Nếu bạn chỉ cố gắng nhổ ra các lỗi trên JSP, sau đó sử dụng một Set<ConstraintViolation> có thể hoạt động tốt đủ cho nhu cầu của bạn:

<c:forEach items="${violations}" var="violation"> 
    ${violation.propertyPath}: ${violation.message} <br/> 
</c:forEach> 

Nếu bạn đang cố gắng sử dụng thẻ <form:errors> của Spring, bạn sẽ cần phải sử dụng kết quả ràng buộc.

HTH! Hãy cho tôi biết nếu bạn có bất kỳ câu hỏi nhiều hơn nữa. Hoặc nếu tôi hoàn toàn bị mất dấu trên câu trả lời này, tôi sẽ cố gắng làm rõ.

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