2012-07-23 69 views
9

我有一个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类将请求参数名称(包括查询字符串参数和表单字段)与名称建模属性字段相匹配。在必要时应用类型转换(从字符串到目标字段类型)后匹配字段已填充。

但是,我认为这种情况相当普遍,其他人怎么处理呢?如果我的发现是正确的,并且这是预期的行为(或错误),这似乎是非常容易出错的。

可能的解决方案:

  1. 变化@PathVariable("id")@PathVariable("somethingElse")。工作,但它不像@RequestParam一样简单(例如,我不知道如何将jqgrid的请求参数id更改为别的东西,但这是另一个问题)。
  2. @PathVariable("id")类型从Long更改为Int。这将使User.idid类型不同,但投给龙看起来很难看:)
  3. 请不要在这里使用@ModelAttribute并再次查询User的DB。与其他方法不一致并涉及冗余的数据库调用。

有什么建议吗?

+0

一个黑客第四选项,如果你更改顺序 - '@ ModelAttribute'先'@ PathVariable' 。 – 2012-07-23 20:07:56

+0

结果是一样的,但它是值得的尝试。 – Ulises 2012-07-23 22:23:47

+0

是的,后来实际上意识到User的匹配属性将与uri变量匹配。你的方法看起来不错,我又增加了一个答案。 – 2012-07-24 00:18:28

回答

5

如何对这种做法 -

@RequestMapping(value = "/{id}", method = RequestMethod.GET) 
public String showItem(@PathVariable("id") Long id, 
      Model uiModel) { 
     User user = (User)uiModel.asMap().get("user"); 
    ...  
} 
+0

不错。这是一个小小的变化,它的工作原理。快速的问题,我没有看到'模型'getAttribute()',我应该只是'(用户)uiModel.asMap()。get(“user”)'? – Ulises 2012-07-24 01:26:13

+0

是的,我的错!让我编辑答案来改变这一点。 – 2012-07-24 01:35:03

+0

+1我喜欢你的答案,但是我会标记它,但我想看看我是否听到更多。非常感谢您的帮助。 – Ulises 2012-07-24 01:36:01

0

使用@SessionAttribute

@RequestMapping(value = "/{id}", method = RequestMethod.GET) 
    public String showItem(@PathVariable("id") Long id, @SessionAttribute("user") User user, 
      Model uiModel) { 
    ...  
}