要部分更新实体,应使用
@SessionAttributes
模型在请求之间的会话中存储模型。您可以使用隐藏的表单字段,但是会话更为安全。要将P / R / G与验证一起使用,请使用
flashAttributes
要保护字段安全,请使用
webDataBinder.setAllowedFields("field1","field2",...)或创建特定于表单的类,然后将值复制到您的实体。实体不需要ID和版本的设置器(如果使用Hibernate)。要使用乐观并发控制
@Version
,请在实体中使用注释,并@SessionAttributes
在控制器上使用。
示例代码:
@Controller@RequestMapping("/foo/edit/{id}")@SessionAttributes({FooEditController.ATTRIBUTE_NAME})public class FooEditController { static final String ATTRIBUTE_NAME = "foo"; static final String BINDING_RESULT_NAME = "org.springframework.validation.BindingResult." + ATTRIBUTE_NAME; @Autowired private FooRepository fooRepository; @InitBinder void allowFields(WebDataBinder webDataBinder){ webDataBinder.setAllowedFields("name"); } @RequestMapping(method = RequestMethod.GET) String getForm(@PathVariable("id") long id, Model model) { if(!model.containsAttribute(BINDING_RESULT_NAME)) { Foo foo = fooRepository.findOne(id); if(foo == null) throw new ResourceNotFoundException(); model.addAttribute(ATTRIBUTE_NAME, foo); } return "foo/edit-form"; } @RequestMapping(method = RequestMethod.POST) String saveForm( @Validated @ModelAttribute(ATTRIBUTE_NAME) Foo foo, BindingResult bindingResult, RedirectAttributes redirectAttributes, HttpServletRequest request, SessionStatus sessionStatus ) { if(!bindingResult.hasErrors()) { try { fooRepository.save(foo); } catch (JpaOptimisticLockingFailureException exp){ bindingResult.reject("", "This record was modified by another user. Try refreshing the page."); } } if(bindingResult.hasErrors()) { //put the validation errors in Flash session and redirect to self redirectAttributes.addFlashAttribute(BINDING_RESULT_NAME, bindingResult); return "redirect:" + request.getRequestURI(); } sessionStatus.setComplete(); //remove Foo from session redirectAttributes.addFlashAttribute("message", "Success. The record was saved"); return "redirect:" + request.getRequestURI(); }}Foo.java:
@Entitypublic class Foo { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Version //for optimistic concurrency control private int version; @NotBlank private String name; public Long getId() { return id; } public String getName() { return name; } public void setName(String name) { this.name = name; }}edit-form.jsp(兼容Twitter Bootstrap):
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %><%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %><%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %><form:form modelAttribute="foo"> <spring:hasBindErrors name="foo"> <c:if test="${errors.globalErrorCount > 0}"> <div role="alert"><form:errors/></div> </c:if> </spring:hasBindErrors> <c:if test="${not empty message}"> <div ><c:out value="${message}"/></div> </c:if> <div > <div > <button name="btnSave">Save</button> </div> <div > <spring:bind path="name"> <div > <form:label path="name" >Name <form:errors path="name"/></form:label> <form:input path="name" /> </div> </spring:bind> </div> </div></form:form>ResourceNotFoundException.java:
@ResponseStatus(HttpStatus.NOT_FOUND)public class ResourceNotFoundException extends RuntimeException {}


