2013-11-04 125 views
3

我一直在处理以下问题:模型属性设置为null由thymeleaf

我有一个简单的模型类称为用户。

public class User{ 

    private Long id; 
    private String name; 
    ...} 

,这是我的控制器代码:

@RequestMapping (value = "/users", params = { "id" }) 
public String showEditForm(final Model model, final HttpServletRequest req) 
{ 
    User edit = this.userRepository.findOne(Long.valueOf(req.getParameter("id"))); 
    model.addAttribute("user", edit); 
    return "edit-user"; 
} 


@RequestMapping (value = "/users", method = RequestMethod.POST, params = {"edit"  
}) 
public String editUser(@Valid @ModelAttribute ("user") final User user, 
final BindingResult bindingResult, final Model model) 
{ 
    if (bindingResult.hasErrors()) 
    { 
     return "edit-user"; 
    } 

    return "redirect:/users"; 
} 

以下是代码片段,以显示所有用户:

<div class="userlist" th:unless="${#lists.isEmpty(users)}"> 
    <h2 th:text="#{list.user.title}"></h2> 
    <table> 
     <thead> 
      <tr> 
       <th th:text="#{name}" /> 
       <th th:text="#{details}" />     
      </tr> 
     </thead> 
     <tbody> 
      <tr th:each="u : ${users}"> 
       <td th:text="${u.name}" />     
       <td><a th:href="@{/users(id=${tc.id})}" th:text="#{edit}"></a></td> 
      </tr> 
     </tbody> 
    </table> 
</div> 

,并最终提交形式:

<form action="#" th:action="@{/users}" th:object="${user}" 
     method="post"> 
     <fieldset> 
      <ul th:if="${#fields.hasErrors('*')}" class="errorlist"> 
       <li th:each="err : ${#fields.errors('*')}" th:text="${err}"></li> 
      </ul> 
      <div> 
       <input type="text" th:field="*{id}"/> 
      </div> 
      <div> 
       <label for="name"> <span th:text="#{name}"></span> 
       </label> <input type="text" th:field="*{name}" 
        th:class=" ${#fields.hasErrors('name')}? 'fieldError'" /> 
      </div>   
      <div class="submit"> 
       <button type="submit" th:text="#{update}" name="edit"></button>     
      </div> 
     </fieldset> 
    </form> 

而现在t他的问题描述: 只要'id'字段出现在提交表单中,一切正常。如果我从提交表单中删除'id'字段,但由于id属性不能修改,工作流程不再有效。事实上,editUser()方法中的id为null。我假设Thymeleaf确实将id属性的值设置为null,如果它不在提交表单中。但我不确定这一点。我认为除了必须让id属性驻留在提交表单中之外,还必须解决这个问题。

我希望任何人都可以在这里帮忙。

谢谢。

爱德蒙

回答

0

Id字段应以形式存在,否则控制器将如何知道应更新哪个用户。

如果这个字段对客户端没有意义(即它是一些生成的唯一ID),它应该隐藏。如果它可能对客户有些兴趣,则该字段可以只读方式完成。

+1

您应该尽可能避免在屏幕上暴露技术键/ id。如果我是恶意用户,我可以更改ID并修改一个完全不同的用户。所以从安全的角度来看,这不是一件明智的事情。 –

+1

M.Deinum - 是的,但这就是为什么表单应该在服务器端进行验证(例如使用BindingResult) –

10

这已无关Thymeleaf,但如何工作的结合。 Spring只会将属性绑定到作为请求中参数存在的模型对象。如果你删除不存在的id,并且不能绑定(应该绑定什么?)。

对此的解决方案是要么将id指定为隐藏表单,以便它存在。或者在请求之间将对象存储在会话中(使用控制器上的@SessionAttributes),这样以前检索到的对象将用于绑定。

@Controller 
@SessionAttributes("user") 
public class UserController { 

    @ModelAttribute("user") 
    public User initUser(@RequestParam("id") Long id) { 
     return this.userRepository.findOne(id); 
    } 

    RequestMapping (value = "/users", params = { "id" }) 
    public String showEditForm() { 
     return "edit-user"; 
    } 

    @RequestMapping (value = "/users", method = RequestMethod.POST, params = {"edit"}) 
    public String editUser(@Valid @ModelAttribute ("user") final User user, final BindingResult bindingResult, SessionStatus status;) { 
     if (bindingResult.hasErrors()) { 
      return "edit-user"; 
     } 
     status.setComplete(); // Indicate we are done,so @SessionAttributes can be cleaned up 
     return "redirect:/users"; 
    } 

类似的东西应该保留会话之间的用户,然后SessionStatus可以用来触发会话属性的清理。