@PathVariable和@ModelAttribute重叠的值

时间:2012-07-23 19:09:39

标签: spring spring-mvc

我在User的会话中存储了@SessionAttributes个对象。还有一个直接的方法,用@ModelAttribute修饰,以便在会话值为null时初始化它。

用户类:

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

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

可能的解决方案:

  1. @PathVariable("id")更改为@PathVariable("somethingElse")。可以工作,但是使用@RequestParam不是那么简单(例如我不知道如何将jqgrid的请求参数id更改为其他内容,但这是另一个问题)。
  2. @PathVariable("id")类型从Long更改为Int。这将使User.idid类型有所不同,但对Long的演员看起来很丑:)
  3. 请勿在此处使用@ModelAttribute,并再次向数据库查询User。与其他方法不一致,涉及冗余的数据库调用。
  4. 有什么建议吗?

2 个答案:

答案 0 :(得分:5)

这种方法怎么样 -

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

答案 1 :(得分:0)

使用@SessionAttribute

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