用户提交一次请求的执行过程
总结:
struts值栈中 两个内容 一个是栈 一个是map
值栈(数据中心)的范围是一个请求 它代替了request作用域
struts自定义标签有一个特点 比如遍历集合的时候 把每次循环得到的
对象 自动放在栈顶 此次循环结束之后 把它从栈顶拿掉(弹出)
下次循环到第二个对象 再把它放在栈顶
%{ognl}表达式 从栈顶找对应属性 找不到 去map中找对应的key的值
jsp页面中${}是el表达式
ognl表达式 在struts.xml中的格式为 ${} 在jsp页面的格式为%{}
ognl表达式 只能写在struts的自定义标签中
一般都不写%{} 直接name="属性值" name="%{属性值}"
页面直接使用的对象一般都放在栈顶 而对于集合数据 都放在map中
(单个对象一般是放在栈顶的 因为如果是一个集合 那么放在map中 在遍历的时候也是取出一个对象 放在栈顶 然后得到其中的每个值)
#value 直接从map中查找key对应的值
%{user} 先找值栈 找不到 继续找map
%{#user} 直接找map
el :page->request->session->application
el表达式操作的数据都是4个作用域中的内容 是不正确的
el表达式在jsp页面 找request中的内容的时候
先找作用域 再找值栈 再找map
例如 ${name} 先从作用域中进行查找 如果没有找到 然后就先找值栈,然后找map中的key对应的值
所以 正确的顺序
page->request-> valueStack.findValue()->session->application
关于数据回显的问题
<S:from action="">
<s:textfield name="name"></s:textfield>
<s:textfield name="name" value="%{name}"></s:textfield>
</s:from>
上面两句效果是一样的 默认都有value="%{name}"的行为 写不写 都会从栈中找对应的属性值 所以这就实现了数据的回显 每次把之前的数据提前放入栈中 然后在页面 就能回显
下面举几个例子
下拉列表的显示以及回显数据
单击修改用户的时候 数据需要进行下拉列表显示 以及下拉列表回显操作
/** 修改页面 */ public String editUI() throws Exception { // 准备数据 部门 List<Department> topDepartmentList = this.departmentService .findTopList(); List<Department> departmentList = DepartmentUtils .findTopDepartment(topDepartmentList); // ServletActionContext.getRequest().setAttribute("departmentList",departmentList); // 使用struts标签 把集合放入map集合中 ActionContext.getContext().put("departmentList", departmentList); // 准备数据 岗位 List<Role> roleList = this.roleService.findAll(); // ServletActionContext.getRequest().setAttribute("roleList",roleList); // 因为页面需要使用struts标签 所以这里把查到的数据放在map集合中 在页面显示所有的岗位信息 ActionContext.getContext().put("roleList", roleList); // 回显基本数据 User user = this.userService.getById(model.getId()); //ServletActionContext.getRequest().setAttribute("user", user); //把user对象放入栈顶 可以对user中的对象属性也进行回显 比如department这个属性 它是一个对象 ActionContext.getContext().getValueStack().push(user); // 用于回显用户已经选择的岗位 if (user.getRoles() != null) { roleIds = new Long[user.getRoles().size()]; int index = 0; for (Role role : user.getRoles()) { roleIds[index++] = role.getId(); } } /* * ServletActionContext.getContext().put("roleList", roleList); if * (user.getRoles() != null) { roleids = new * Long[user.getRoles().size()]; int index = 0; for (Role role : * user.getRoles()) { roleids[index++] = role.getId(); } } */ return "saveUI"; }
首先是部门列表的显示 以及回显
在action中把查询到的部门列表放进了map中 所以这里使用#departmentList直接从map中取出key='departmentList" 所对应的集合 而且在遍历的时候 会把每次得到的对象都放在栈顶 操作完成之后 弹出栈 第二个对象也是如此 依次遍历.....
因为取出的对象是dempartment类型 listKey="id" listValue="name" 对应的是department这个对象中的id字段和name字段 而headerKey="" headerValue="===请选择部门====" 应该可以猜到 如果第一次没有选择任何部门 那么就不进行回显 所以显示的就是headervalue
中的内容 而如果在提价的时候也没有选择任何的部门 那么就提交id为空字符串 在这里我想说的是 name="department.id"属性 因为action中使用的是modelDriver 在user对象的属性中有department这个对象属性 所以这里如果想要完成自动封装 还是必须得写成该形式 否则就在action中创建一个departmentID字段 设置gett和set方法 然后这里可以写departmentID也能够实现 另外这里还有一个重点就是 我们发现数据竟然可以回显 是为什么呢 主要是在action中 我们把当前修改的对象查询了出来 放在了栈顶
ActionContext.getContext().getValueStack().push(user);即该语句 如果没有该语句 部门列表这个地方是不能进行数据的回显的 这就是框架的强大之处 使用框架提供的标签 无需关心它是怎么回显的
否则 如果使用jstl中的c:foreach标签还得需要进行判断才能实现数据的回显 如下代码:
<select name="department.id" cssClass="SelectStyle"> <option value="">请选择:</option> <c:forEach items="${departmentList}" var="department"> <option value="${department.id }" <c:if test="${user.department.id==department.id}" >selected</c:if>> ${department.name} </option> </c:forEach> </select>
举例2:下拉列表 多选操作 以及回显功能
<s:select name="roleIds" cssClass="SelectStyle" multiple="true" size="10" list="#roleList" listKey="id" listValue="name" /> 按住Ctrl键可以多选或取消选择
代码很简单 主要是action中准备的数据 roleIds在action中是另外创建出来的一个数组 就是保存用户选择的多个岗位值
![](https://images2017.cnblogs.com/blog/1025941/201708/1025941-20170815211604271-641890895.jpg)
举例3:用户列表的显示
<s:iterator value="#userList"> <tr class="TableDetail1 template"> <td>${loginName} </td> <td>${name} </td> <td>${department.name} </td> <td> <s:iterator value="roles"> ${name} </s:iterator> </td> <td>${description} </td> <td> <s:a action="user_delete?id=%{id}" onclick="return delConfirm()">删除</s:a> <s:a action="user_editUI?id=%{id}">修改</s:a> <s:a action="user_initPassword?id=%{id}" onclick="return window.confirm('您确定要初始化密码为1234吗?')">初始化密码</s:a> </td> </tr> </s:iterator>
举例4:单选按钮的回显
两个代码效果一样 都能实现回显 但是都有一个前提 那就是需要把将要修改的user对象 查询出来 放在栈顶即可