我有一个User
对象存储在与@SessionAttributes
的会话中。一个简单的方法用@ModelAttribute
修饰,以便在会话的值为空时对其进行初始化。@PathVariable和@ModelAttribute重叠的值
用户等级:
@Entity
@Table(name="USER")
public class User implements java.io.Serializable {
private Long id;
private String username;
private String password;
....
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name ="ID")
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
...
控制器:
@RequestMapping("/item")
@Controller
@SessionAttributes({"user"})
public class MyController {
@ModelAttribute方法:
@ModelAttribute("user")
public User createUser(Principal principal) {
return userService.findByUsername(principal.getName());
}
这一切似乎按预期方式工作,除了在这个特殊的方法:
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public String showItem(@PathVariable("id") Long id, @ModelAttribute("user") User user,
Model uiModel) {
...
}
问题是User.id
设置为@PathVariable("id")
。我相信我也碰到过@RequestParam
。我假设这是因为两者具有相同的名称和类型。在阅读Spring's documentation(见下文)后,我假设这是预期行为:
下一步是数据绑定。 WebDataBinder类将请求参数名称(包括查询字符串参数和表单字段)与名称建模属性字段相匹配。在必要时应用类型转换(从字符串到目标字段类型)后匹配字段已填充。
但是,我认为这种情况相当普遍,其他人怎么处理呢?如果我的发现是正确的,并且这是预期的行为(或错误),这似乎是非常容易出错的。
可能的解决方案:
- 变化
@PathVariable("id")
到@PathVariable("somethingElse")
。工作,但它不像@RequestParam一样简单(例如,我不知道如何将jqgrid的请求参数id更改为别的东西,但这是另一个问题)。 - 将
@PathVariable("id")
类型从Long更改为Int。这将使User.id
和id
类型不同,但投给龙看起来很难看:) - 请不要在这里使用
@ModelAttribute
并再次查询User
的DB。与其他方法不一致并涉及冗余的数据库调用。
有什么建议吗?
一个黑客第四选项,如果你更改顺序 - '@ ModelAttribute'先'@ PathVariable' 。 – 2012-07-23 20:07:56
结果是一样的,但它是值得的尝试。 – Ulises 2012-07-23 22:23:47
是的,后来实际上意识到User的匹配属性将与uri变量匹配。你的方法看起来不错,我又增加了一个答案。 – 2012-07-24 00:18:28