SessionAttributes导致多个选项卡出现问题

时间:2015-07-14 08:21:03

标签: java spring spring-mvc session

我有一个Spring Web应用程序(Spring 3.2),我使用了以下场景来处理编辑页面:

@Controller
@SessionAttributes(value = { "packet" })
public class PacketController {

@RequestMapping(value = "/edit-packet/{packet_id}", method = RequestMethod.GET)
public String editPacketForm(@PathVariable(value = "packet_id") Long packet_id, Model model)
{
    model.addAttribute("packet", packetService.findById(packet_id));
    return "packets/packetEdit";
}

POST方法:

@RequestMapping(value = "/edit-packet/{packet_id}", method = RequestMethod.POST)
    public String packetEditAction(Model model, @Valid @ModelAttribute(value = "packet") 
                                   Packet packet, BindingResult result, SessionStatus status)
    {
    if (result.hasErrors())
    {
        return "packets/packetEdit";
    }

    packetService.update(packet);
    status.setComplete();
    return "redirect:/";
}

现在问题是,如果有人试图使用不同的ID为/ edit-packet / {id}打开多个标签。每个新的打开标签都会显示会话数据包'对象将被覆盖。然后在尝试在多个选项卡上提交表单后,将提交第一个选项卡,但它实际上会更改第二个数据包,因为在会话中是第二个对象,第二个选项卡将导致错误,因为已调用setComplete,因此没有'数据包&#39 ;会话中的对象。

(这是已知问题https://jira.spring.io/browse/SPR-4160)。

我正在尝试实施此解决方案http://duckranger.com/2012/11/add-conversation-support-to-spring-mvc/来解决此问题。我复制了ConversationalSessionAttributeStore.java ConversationIdRequestProcessor.java类和我的servlet-config.xml中我做了这个:

<mvc:annotation-driven />

<bean id="conversationalSessionAttributeStore"
    class="com.xx.session.ConversationalSessionAttributeStore">
</bean>

<bean name="requestDataValueProcessor" class="com.xx.session.ConversationIdRequestProcessor" />

但它不起作用,在我的POST方法中我没有看到任何新参数,我是否错过了什么?

更新:实际上,它已经开始运作,但也许有人有更好的想法来解决这个问题?

我的另一个想法是在每个新标签上强制使用新会话,但这不是一个好的解决方案。

1 个答案:

答案 0 :(得分:1)

不要使用会话属性,使控制器无状态,只需使用路径变量来检索正确的模型属性。

@Controller
public class PacketController {

    @ModelAttribute
    public Packet packet(@PathVariable(value = "packet_id") Long packet_id) {
        return packetService.findById(packet_id);
    }

    @RequestMapping(value = "/edit-packet/{packet_id}", method = RequestMethod.GET)
    public String editPacketForm() {
        return "packets/packetEdit";
    }

    @RequestMapping(value = "/edit-packet/{packet_id}", method = RequestMethod.POST)
    public String packetEditAction(Model model, @Valid @ModelAttribute(value = "packet") 
                                   Packet packet, BindingResult result) {
        if (result.hasErrors()) {
            return "packets/packetEdit";
        }

        packetService.update(packet);
        return "redirect:/";
    }
}

这样的事情应该可以解决问题。