1.前提知识
1)scope默认值
进行SSH整合开发时,Struts2的action需要用spring容器进行管理,只要涉及到类以bean的形式入到spring容器中,不管是xml配置还是使用注解方式进行配置,都会涉及到spring管理bean的scope,其一共有五种取值,而其默认值为singleton,也就是单例模型,所有对此bean引用为同一个对象。
2)action应为多例
struts2作为MVC中视图(View)层框架,其最主要任务就是接收用户请求,然后调用业务逻辑层进行处理,这种特征也就是意味着每个HTTP请求都必须对应一个单独的action,不然会出现数据冲突。
3)那么问题来了
通过上述两点可以看出两者是矛盾的,所以当spring需要管理action时,就必须更改其scope为prototype,而不是使用其默认值-singleton。
2.错误现象
进行用户添加时,如果spring管理action的方式为默认值(singleton)就会造成添加完用户后,当进行再次添加时发现数据进行自动回显(前提使用了struts2标签并且使用了ModelDriven),不管是关闭浏览器还是换其它浏览器都是如此,使用<s:debug>标签调用时,发现值栈的root栈的栈顶就是之前添加的用户(model)。
3.原因分析
1)spring容器启动
spring容器启动时,会创建添加用户action的实例,因为其scope为singleton方式,所以以后每次请求此action都会调用同一个action对象,由此也埋下了灭亡的种子。
2)经过modelDriven拦截器
用户在输入完信息,点击提交。因为添加用户需要对表单输入数据进行封装,此时采用了封装数据最标准的做法实现ModelDriven接口,那么当请求添加的action时,会经过modelDriven拦截器,此拦截器通过getModel方法获取目标model然后push到valuestack的栈顶;
2)经过param拦截器
当经过拦截器params时,其会对栈顶的model进行赋值。
3)执行action
执行添加action进行添加操作,并且完成后续。
4)再次请求添加action转发
此时又从spring容器中取出添加的action,由于其scope为singleton,所以此action与之前的action为同一个,而此前添加的还保存在action中。
5)再次经过modelDriven拦截器
再次经过拦截器modelDriven,此时action中的model再次被放到valuestack的栈顶,再次提醒model中是有值的。
6)到达界面
到达界面时,就会根据model中值进行回显。