问题:action的scope=session的场合,如何使浏览器提交的list和服务器端接收到的保持完全一致。
咱们知道,action的scope设置为session后,除非浏览器提交数据到服务器,否则服务器端form中的数据不会发生变化。
昨天遇到了一个问题,MyAction中有一个变量nameList(有getter,setter方法),把这个nameList显示在浏览器的表单中,然后用js删除几行后再次提交到MyAction中,发现服务器端的nameList大小没有发生变化。然后继续尝试,结果如下:
【服务器】
nameList = ["a1","a2","a3"];
↓
【浏览器显示】
nameList[0]=a1
nameList[1]=a2
nameList[2]=a3
↓
【浏览器修改后】
nameList[3]=b4
nameList[5]=b6
这里的意思是删除了原有的3个,新加了两个,并且下标是不连续的。
↓
【提交服务器】
nameList = ["a1","a2","a3","b4",null,"b6"];
通过form提交的nameList到了服务器后,服务器端并不重新初始化nameList这个变量,而是根据浏览器传递过来的下标单独进行设定。
想要的结果是:服务器端接收到的nameList与浏览器发送的完全一致。
开始的解决思路是查找struts2的设定,如果可以让服务器接收到list类型的数据后先初始化服务器端变量然后再设定,就可以解决。但最终没有找到。
然后想到在服务器端使用两个list变量,一个变量用来给浏览器提供显示的数据,另一个变量用来接收浏览器传递过来的数据。这个方法只停留在了思考阶段,因为我又想到了到了一个较为简洁的替代方案。
JSP会被编译成servlet,servlet执行后生成了用于浏览器显示的html,那么如果在servlet的最后加上初始化服务器变量的代码,这样一来,浏览器再次把数据发送到服务器时,服务器的nameList就是被初始化过的了,兴奋不已啊,只是struts2与struts1不一样啊,setAttribute不好使啊咋办啊,那就直接取得action实例吧,终于搞定。
这段用于初始化的代码写在jsp的最后(因为前面还要使用nameList来显示)
<%
HttpServletRequest req = ServletActionContext.getRequest();
ServletContext sc = req.getSession().getServletContext();
ApplicationContext ac = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
// 取得action的实例
// (因为scope是session,所以这里取到的action与上次访问的是同一个实例)
MyAction action = (MyAction) ac.getBean("MyAction");
// 初始化变量
action.setNameList(new ArrayList());
%>