Spring 我对如何使用@SessionAttributes感到困惑

Spring 我对如何使用@SessionAttributes感到困惑,spring,spring-mvc,session-variables,Spring,Spring Mvc,Session Variables,我试图理解SpringMVC的体系结构。然而,@SessionAttributes的行为让我完全困惑 请看下面的SampleController,它是通过超级表单类处理post方法的。事实上,正如我所期望的,SuperForm类的just字段只是绑定的 然而,在我将@SessionAttributes放入控制器之后,处理方法将绑定为子表单。谁能给我解释一下这本书里发生了什么事 ------------------------------------------------------- @Co

我试图理解SpringMVC的体系结构。然而,@SessionAttributes的行为让我完全困惑

请看下面的SampleController,它是通过超级表单类处理post方法的。事实上,正如我所期望的,SuperForm类的just字段只是绑定的

然而,在我将@SessionAttributes放入控制器之后,处理方法将绑定为子表单。谁能给我解释一下这本书里发生了什么事

-------------------------------------------------------

@Controller
@SessionAttributes("form")
@RequestMapping(value = "/sample")
public class SampleController {

    @RequestMapping(method = RequestMethod.GET)
    public String getCreateForm(Model model) {
        model.addAttribute("form", new SubAForm());
        return "sample/input";
    }

    @RequestMapping(method = RequestMethod.POST)
    public String register(@ModelAttribute("form") SuperForm form, Model model) {
        return "sample/input";
    }
}

-------------------------------------------------------

public class SuperForm {

    private Long superId;

    public Long getSuperId() {
        return superId;
    }

    public void setSuperId(Long superId) {
        this.superId = superId;
    }

}

-------------------------------------------------------

public class SubAForm extends SuperForm {

    private Long subAId;

    public Long getSubAId() {
        return subAId;
    }

    public void setSubAId(Long subAId) {
        this.subAId = subAId;
    }

}

-------------------------------------------------------

<form:form modelAttribute="form" method="post">
    <fieldset>
        <legend>SUPER FIELD</legend>
        <p>
            SUPER ID:<form:input path="superId" />
        </p>
    </fieldset>
    <fieldset>
        <legend>SUB A FIELD</legend>
        <p>
            SUB A ID:<form:input path="subAId" />
        </p>
    </fieldset>
    <p>
        <input type="submit" value="register" />
    </p>
</form:form>
-------------------------------------------------------
@控制器
@会期贡献(“表格”)
@请求映射(value=“/sample”)
公共类采样控制器{
@RequestMapping(method=RequestMethod.GET)
公共字符串getCreateForm(模型){
addAttribute(“form”,new subform());
返回“样本/输入”;
}
@RequestMapping(method=RequestMethod.POST)
公共字符串寄存器(@modeldattribute(“form”)超级表单,模型模型){
返回“样本/输入”;
}
}
-------------------------------------------------------
公共类超级表单{
私人长上司;
公共长getSuperId(){
返回上级;
}
public void setSuperId(长superId){
this.superId=superId;
}
}
-------------------------------------------------------
公共类子窗体扩展了超窗体{
私有长子曲面;
公共长getSubAId(){
返回子面;
}
公共无效setSubAId(长subAId){
this.subAId=subAId;
}
}
-------------------------------------------------------
超场

超级标识:

分田 子A ID:


当处理
POST
请求时,Spring执行以下操作:

  • 不使用
    @SessionAttributes
    :Spring实例化
    超级表单的新实例(类型从
    register()
    的签名推断),通过表单字段中的值填充其属性,并将其传递给
    register()
    方法

  • 使用
    @SessionAttributes
    :Spring从会话中获取model属性的实例(由于存在
    @SessionAttributes
    ,因此在处理
    GET
    时放置该实例),通过from字段中的值更新其属性,并将其传递给
    register()
    方法


也就是说,使用
@SessionAttributes
register()
获取模型属性对象的相同实例,该对象是通过
getCreateForm()
添加到@axtavt所说的内容中的:假设在
getCreateForm
中为下拉列表(列表或映射)输入一些值,或者,您正在将一些值放入希望在register方法中显示的表单中,但不希望它们显示在表单中(甚至不在隐藏字段中)。现在假设
register
方法中发生错误,您需要再次显示表单。要填充下拉列表值和下一篇文章中需要的其他值,必须在表单中重新填充它们。
@SessionAttribute
在这里很有帮助,因为@axtavt在上面有很好的描述。

根据Spring参考文档
@modeldattribute
注释的方法参数解析如下:

@Controller
@SessionAttributes("test")
public class Controller{
    Customer customer;

    public Controller() {
        super();
        customer = new Customer();
    }

    @ModelAttribute("test")
    public Customer getCustomer() {
       customer.setName("Savac");
       return customer;
    }

    @RequestMapping({"/index"})
    public ModelAndView showMainPage (@ModelAttribute("test") Customer customer, ModelMap model, method = RequestMethod.GET) {
        //in the view you set the name
        return new ModelAndView("index");
    }

    @RequestMapping(value = "customer/{customerID}", method = RequestMethod.GET)
    public ModelAndView viewAdvice(@PathVariable("customerID") int customerID, @ModelAttribute("test") Customer customer, ModelMap model) {
        customer.setName("AnotherName");
        model.addAttribute("test", customer);
        return new ModelAndView("customer");
    }

}
  • 从模型对象(如果存在)检索(通常通过
    @modeldattribute
    注释方法添加)
  • 使用
    @SessionAttributes
    从HTTP会话检索
  • 通过转换器使用与
    @modeldattribute
    名称匹配的URI path变量创建
  • 使用默认构造函数创建并将其添加到
    模型
处理程序类可以用
@SessionAttributes
注释,并将名称列表作为其参数。这是为了指示Spring持久化(在会话中)模型数据中存在的那些与
@SessionAttributes
注释中指定的名称匹配的数据项


因此,在
SampleController
中,由于上述解析方法,post方法的
@ModelAttribute
参数通过
@SessionAttributes
字段解析

感谢您的解释,我对“也就是说,@SessionAttribute register()获得的模型属性对象的实例与getCreateForm()放置到模型中的实例相同”感到有点困惑。无论哪种方式,您都会收到用户在表单中输入的内容,那么这句话是什么意思?我的意思是,不管怎样,您都会收到每个字段的正确值,那么使用sessionAttribute有什么意义呢?我遗漏了什么吗?是@SessionAttributes还是@SessionAttributes?:pis it@SessionAttribute还是SessionAttribute?:P