2013-11-04 91 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可以用來觸發會話屬性的清理。