2010-03-30 27 views
50

Tôi đang cố gắng tìm ra cách "bảo tồn" BindingResult để nó có thể được sử dụng trong GET tiếp theo thông qua thẻ Spring <form:errors>. Lý do tôi muốn làm điều này là do các giới hạn SSL của Google App Engine. Tôi có một biểu mẫu được hiển thị qua HTTP và bài đăng là URL HTTPS. Nếu tôi chỉ chuyển tiếp thay vì chuyển hướng thì người dùng sẽ thấy URL https://whatever.appspot.com/my/form. Tôi đang cố tránh điều này. Bất kỳ ý tưởng làm thế nào để tiếp cận này?Mùa xuân - Chuyển hướng sau POST (ngay cả với lỗi xác thực)

Dưới đây là những gì tôi muốn làm, nhưng tôi chỉ thấy lỗi xác thực khi tôi sử dụng return "create".

@RequestMapping(value = "/submit", method = RequestMethod.POST) 
public final String submit(
    @ModelAttribute("register") @Valid final Register register, 
    final BindingResult binding) { 

    if (binding.hasErrors()) { 
     return "redirect:/register/create"; 
    } 

    return "redirect:/register/success"; 
} 

Trả lời

-1

Có thể đây là một chút đơn giản, nhưng bạn đã thử thêm nó vào Mô hình của mình chưa? Tức là, bao gồm Mô hình trong đối số của phương thức của bạn, sau đó thêm BindingResult vào nó, sau đó có sẵn trong chế độ xem của bạn.

model.addAttribute("binding",binding); 

Tôi nghĩ rằng bạn có thể phải sử dụng một tiền đạo chứ không phải là một chuyển hướng (trong đầu của tôi, tôi không thể nhớ nếu một chuyển hướng mất phiên hay không — Tôi có thể sai về vấn đề này như tôi không có bất kỳ tài liệu nào có ích, tức là, nếu bạn không nhận được BindingResult sau khi thêm nó vào Model, hãy thử sử dụng một forward để xác nhận điều này).

+0

Tôi sẽ thử sau ngày hôm nay, nhưng nó đã hoạt động tốt nếu tôi chuyển tiếp. Tôi đang cố gắng làm cho nó hoạt động khi tôi chuyển hướng. –

+0

Đã hiểu, tôi chỉ đề xuất về phía trước nếu sau khi thêm BindingResult bạn không thực sự thấy nó. –

+0

Tôi vừa thử và không hoạt động trên chuyển hướng. –

1

Vấn đề là bạn đang chuyển hướng đến bộ điều khiển mới, thay vì hiển thị chế độ xem và trả về trang biểu mẫu đã xử lý. Bạn cần phải làm điều gì đó dọc theo các dòng:

String FORM_VIEW = wherever_your_form_page_resides 

... 

if (binding.hasErrors()) 
    return FORM_VIEW; 

Tôi sẽ giữ đường dẫn bên ngoài bất kỳ phương pháp nào do sao chép mã chuỗi.

+2

Toàn bộ vấn đề là tôi muốn thực hiện chuyển hướng và vẫn hiển thị lỗi biểu mẫu. Tôi biết nó sẽ hoạt động tốt nếu tôi chuyển trực tiếp đến một chế độ xem. –

+0

@Lewis: Cảm ơn người đàn ông. Giải pháp này đã giúp tôi giải quyết vấn đề của mình. Tôi đã có 'bài đăng' trả về danh sách các mục và người dùng được chuyển hướng đến một trang khác (chi tiết) khi nhấp vào từng chi tiết đơn hàng riêng lẻ. Tôi muốn chuyển hướng trở lại trang trước đó từ trang chi tiết. Tôi đã thêm một GET trong bộ điều khiển và truyền mô hình đã xử lý trước đó cho chế độ xem ban đầu như bạn đã nói. –

1

Cách duy nhất để duy trì các đối tượng giữa các yêu cầu (tức là chuyển hướng) là lưu trữ đối tượng trong thuộc tính phiên. Vì vậy, bạn sẽ bao gồm "HttpServletRequest request" trong các tham số phương thức cho cả hai phương thức (ví dụ, get và post) và truy lục đối tượng thông qua request.getAttribute ("binding"). Điều đó nói rằng, và đã không thử nó bản thân mình, bạn có thể cần phải tìm ra cách để ràng buộc lại ràng buộc với đối tượng trong yêu cầu mới.

Cách "không đẹp hơn" khác là chỉ cần thay đổi URL trình duyệt bằng cách sử dụng javascript

+0

cách đề xuất của bạn là thú vị, tuy nhiên tôi nghĩ rằng nó sẽ tốt hơn nếu bạn có thể bao gồm một số mã mẫu –

1

Tôi sẽ hỏi tại sao bạn cần chuyển hướng. Tại sao không chỉ gửi cùng một URL và có phản hồi khác với POST? Tuy nhiên, nếu bạn thực sự muốn làm điều này:

@RequestMapping(value = "/submit", method = RequestMethod.POST) 
public final String submit(
    @ModelAttribute("register") @Valid final Register register, 
    final BindingResult binding, 
    HttpSession session) { 

    if (binding.hasErrors()) { 
     session.setAttribute("register",register); 
     session.setAttribute("binding",binding); 
     return "redirect:/register/create"; 
    } 

    return "redirect:/register/success"; 
} 

Sau đó, trong phương pháp "tạo ra" của bạn:

model.put("register",session.getAttribute("register")); 
model.put("org.springframework.validation.BindingResult.register",session.getAttribute("register")); 
+0

Đã thử phương pháp của bạn, ngoại lệ được ném: "Cả BindingResult lẫn đối tượng đích đều không có tên bean 'xxxx' có sẵn dưới dạng thuộc tính yêu cầu" – user979051

+0

Rất có thể là lỗi trong JSP của bạn. http://www.mkyong.com/spring-mvc/spring-mvc-neither-bindingresult-nor-plain-target-object-for-bean-name-xxx-available-as-request-attribute/ – rjsang

+0

Như Điểm của tôi thêm tất cả các thuộc tính vào phiên làm việc xấu (trừ khi cần thiết). FlashAttributes có thể sử dụng một lần vì vậy tôi thích sử dụng nó hơn phiên. Nhưng nó phụ thuộc vào khía cạnh phát triển của bạn. Tôi sử dụng FlashAttributes khi tôi sử dụng jsp đơn cho biểu mẫu gửi và Hiển thị thành công hoặc thông báo không thành công mà không cần sử dụng JavaScript. –

59

Kể từ mùa xuân 3.1 bạn có thể sử dụng RedirectAttributes. Thêm các thuộc tính mà bạn muốn có sẵn trước khi thực hiện chuyển hướng. Thêm cả hai, BindingResult và đối tượng mà bạn đang sử dụng để xác nhận hợp lệ, trong trường hợp này là Register.

Đối với BindingResult, bạn sẽ sử dụng tên: "org.springframework.validation.BindingResult. [Name of ModelAttribute]".

Đối với đối tượng mà bạn đang sử dụng để xác thực, bạn sẽ sử dụng tên của ModelAttribute.

Để sử dụng RedirectAttributes, bạn phải thêm phần này vào tệp cấu hình của mình.Trong số những thứ khác mà bạn đang nói đến mùa xuân để sử dụng một số các lớp học mới:

<mvc:annotation-driven /> 

Bây giờ các lỗi sẽ được hiển thị bất cứ nơi nào bạn đang chuyển hướng

@RequestMapping(value = "/submit", method = RequestMethod.POST) 
public final String submit(@ModelAttribute("register") @Valid final Register register, final BindingResult binding, RedirectAttributes attr, HttpSession session) { 

if (binding.hasErrors()) { 
    attr.addFlashAttribute("org.springframework.validation.BindingResult.register", binding); 
    attr.addFlashAttribute("register", register); 
    return "redirect:/register/create"; 
} 

return "redirect:/register/success"; 
} 
+3

Điều đáng chú ý là các thuộc tính RedirectAttributes không hoạt động cùng với khái niệm ModelAndView (lỗi thời). Họ giả sử phương thức của bạn trả về một chuỗi đơn giản, như ví dụ trên. – kevinmrohr

+0

Sau này (trong trường hợp của tôi) thuộc tính bây giờ là trong mô hình của bộ điều khiển xử lý chuyển hướng, nhưng kết quả ràng buộc không có lỗi. Tôi đã phải vượt qua danh sách các lỗi và thêm chúng vào các kết quả ràng buộc như thế này: https://gist.github.com/OscarRyz/6381954 – OscarRyz

+2

khi làm điều này tôi nhận được lỗi: java.io.NotSerializableException: org.springframework. format.support.DefaultFormattingConversionService – Jens

45

Ngoài câu trả lời đẹp Oscar, nếu bạn đang theo dõi mà RedirectAttributes cách tiếp cận, đừng quên rằng bạn đang thực sự chuyển modelAttribute đến trang được chuyển hướng. Điều này có nghĩa là nếu bạn tạo một phiên bản mới của modelAttribute đó cho trang được chuyển hướng (trong một bộ điều khiển), bạn sẽ mất các lỗi xác thực. Vì vậy, nếu POST phương pháp điều khiển của bạn là một cái gì đó như thế này:

@RequestMapping(value = "/submit", method = RequestMethod.POST) 
public final String submit(@ModelAttribute("register") @Valid final Register register, final BindingResult binding, RedirectAttributes attr, HttpSession session) { 

if (binding.hasErrors()) { 
    attr.addFlashAttribute("org.springframework.validation.BindingResult.register", binding); 
    attr.addFlashAttribute("register", register); 
    return "redirect:/register/create"; 
} 

return "redirect:/register/success"; 
} 

Sau đó, bạn có thể sẽ cần phải làm một sửa đổi trong sổ đăng ký của bạn tạo trang GET điều khiển. Từ này:

@RequestMapping(value = "/register/create", method = RequestMethod.GET) 
public String registerCreatePage(Model model) { 
    // some stuff 
    model.addAttribute("register", new Register()); 
    // some more stuff 
} 

để

@RequestMapping(value = "/register/create", method = RequestMethod.GET) 
public String registerCreatePage(Model model) { 
    // some stuff 
    if (!model.containsAttribute("register")) { 
     model.addAttribute("register", new Register()); 
    } 
    // some more stuff 
} 

Nguồn: http://gerrydevstory.com/2013/07/11/preserving-validation-error-messages-on-spring-mvc-form-post-redirect-get/

+0

Điều này giải quyết nó cho tôi. Bài viết được liên kết giải thích nó thậm chí còn tốt hơn. Cảm ơn. – adnans

+4

Lỗ hổng thông thường: thay đổi "đăng ký" trong "org.springframework.validation.BindingResult.register" thành tên modelAttribute – borjab

+0

Đây là cách tiếp cận đúng hơn !!!!!!!! Tôi không thấy câu trả lời này và đang gặp khó khăn với câu trả lời @Oscar, một gợi ý, cho oscar, vui lòng thêm câu trả lời này vào câu trả lời của bạn để câu trả lời của bạn hoàn thành và không ai đấu tranh như tôi đã làm. :) cảm ơn các bạn đã cứu được thời gian của tôi. –

0

Tôi không biết vấn đề chính xác với Google App Engine nhưng sử dụng ForwardedHeaderFilter có thể giúp bảo vệ kế hoạch ban đầu mà các khách hàng đã sử dụng. Bộ lọc này đã được thêm vào trong Spring Framework 4.3 nhưng một số thùng chứa Servlet cung cấp các bộ lọc tương tự và bộ lọc tự cung tự cấp để bạn cũng có thể lấy nguồn nếu cần.

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