在资费新增页面,输入完资费名称后,光标切换时,验证资费名称是否重复,并在资费名文本框后面给与提示。
该需求中包含2个请求,一个是打开新增资费页面,另一个是输入完资费名称后进行唯一性校验。
其中打开资费页面很简单,参考打开登录页面完成即可,本案例中要完成该请求。
输入完资费名后在光标切换时验证资费名是否重复,这需要发起一次新请求,并且页面不能刷新,因此需要采用异步的方式来实现。而对于异步请求,我们需要在页面上使用JQuery发起请求,在Action中处理请求并使用json类型的result处理请求,将结果发送给异步请求的回调函数。
本案例中要求完成异步请求的服务端代码,包括DAO、Action、struts.xml,其中
实现此案例需要按照如下步骤进行。
请求1:打开新增页面
步骤一:在struts.xml中配置请求action
在struts.xml中,配置打开新增资费页面的请求action,代码如下:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN" "http://struts.apache.org/dtds/struts-2.1.7.dtd"> <struts> <!-- 资费模块配置信息: 一般情况下,一个模块的配置单独封装在一个package下, 并且以模块名来命名package的name和namespace。 --> <package name="cost" namespace="/cost" extends="struts-default"> <!—此处略去其他Action的配置... --> #cold_bold <!-- 打开资费新增页 --> #cold_bold <action name="toAddCost"> #cold_bold <result name="success"> #cold_bold /WEB-INF/cost/add_cost.jsp #cold_bold </result> #cold_bold </action> </package> <!-- 登录模块 --> <package name="login" namespace="/login" extends="struts-default"> <!—此处略去其他Action的配置... --> </package> </struts>
步骤二:创建新增资费页面
在WEB-INF/cost下,创建add_cost.jsp,并将静态页面的代码复制到该JSP中,代码如下:
<%@page pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>达内-NetCTOSS</title> <link type="text/css" rel="stylesheet" media="all" href="../styles/global.css" /> <link type="text/css" rel="stylesheet" media="all" href="../styles/global_color.css" /> <script language="javascript" type="text/javascript"> //保存结果的提示 function showResult() { showResultDiv(true); window.setTimeout("showResultDiv(false);", 3000); } function showResultDiv(flag) { var divResult = document.getElementById("save_result_info"); if (flag) divResult.style.display = "block"; else divResult.style.display = "none"; } //切换资费类型 function feeTypeChange(type) { var inputArray = document.getElementById("main").getElementsByTagName("input"); if (type == 1) { inputArray[4].readonly = true; inputArray[4].value = ""; inputArray[4].className += " readonly"; inputArray[5].readonly = false; inputArray[5].className = "width100"; inputArray[6].readonly = true; inputArray[6].className += " readonly"; inputArray[6].value = ""; } else if (type == 2) { inputArray[4].readonly = false; inputArray[4].className = "width100"; inputArray[5].readonly = false; inputArray[5].className = "width100"; inputArray[6].readonly = false; inputArray[6].className = "width100"; } else if (type == 3) { inputArray[4].readonly = true; inputArray[4].value = ""; inputArray[4].className += " readonly"; inputArray[5].readonly = true; inputArray[5].value = ""; inputArray[5].className += " readonly"; inputArray[6].readonly = false; inputArray[6].className = "width100"; } } </script> </head> <body> <!--Logo区域开始--> <div id="header"> <img src="../images/logo.png" alt="logo" class="left"/> <a href="#">[退出]</a> </div> <!--Logo区域结束--> <!--导航区域开始--> <div id="navi"> <ul id="menu"> <li><a href="../index.html" class="index_off"></a></li> <li><a href="../role/role_list.html" class="role_off"></a></li> <li><a href="../admin/admin_list.html" class="admin_off"></a></li> <li><a href="../fee/fee_list.html" class="fee_on"></a></li> <li><a href="../account/account_list.html" class="account_off"></a></li> <li><a href="../service/service_list.html" class="service_off"></a></li> <li><a href="../bill/bill_list.html" class="bill_off"></a></li> <li><a href="../report/report_list.html" class="report_off"></a></li> <li><a href="../user/user_info.html" class="information_off"></a></li> <li><a href="../user/user_modi_pwd.html" class="password_off"></a></li> </ul> </div> <!--导航区域结束--> <!--主要区域开始--> <div id="main"> <div id="save_result_info" class="save_fail">保存失败,资费名称重复!</div> <form action="" method="" class="main_form"> <div class="text_info clearfix"><span>资费名称:</span></div> <div class="input_info"> <input type="text" class="width300" value=""/> <span class="required">*</span> <div class="validate_msg_short">50长度的字母、数字、汉字和下划线的组合</div> </div> <div class="text_info clearfix"><span>资费类型:</span></div> <div class="input_info fee_type"> <input type="radio" name="radFeeType" id="monthly" onclick="feeTypeChange(1);" /> <label for="monthly">包月</label> <input type="radio" name="radFeeType" checked="checked" id="package" onclick="feeTypeChange(2);" /> <label for="package">套餐</label> <input type="radio" name="radFeeType" id="timeBased" onclick="feeTypeChange(3);" /> <label for="timeBased">计时</label> </div> <div class="text_info clearfix"><span>基本时长:</span></div> <div class="input_info"> <input type="text" value="" class="width100" /> <span class="info">小时</span> <span class="required">*</span> <div class="validate_msg_long">1-600之间的整数</div> </div> <div class="text_info clearfix"><span>基本费用:</span></div> <div class="input_info"> <input type="text" value="" class="width100" /> <span class="info">元</span> <span class="required">*</span> <div class="validate_msg_long error_msg">0-99999.99之间的数值</div> </div> <div class="text_info clearfix"><span>单位费用:</span></div> <div class="input_info"> <input type="text" value="" class="width100" /> <span class="info">元/小时</span> <span class="required">*</span> <div class="validate_msg_long error_msg">0-99999.99之间的数值</div> </div> <div class="text_info clearfix"><span>资费说明:</span></div> <div class="input_info_high"> <textarea class="width300 height70"></textarea> <div class="validate_msg_short error_msg">100长度的字母、数字、汉字和下划线的组合</div> </div> <div class="button_info clearfix"> <input type="button" value="保存" class="btn_save" onclick="showResult();" /> <input type="button" value="取消" class="btn_save" /> </div> </form> </div> <!--主要区域结束--> <div id="footer"> <span>[源自北美的技术,最优秀的师资,最真实的企业环境,最适用的实战项目]</span> <br /> <span>版权所有(C)加拿大达内IT培训集团公司 </span> </div> </body> </html>
步骤三:列表页面上给增加按钮指定跳转的URL
在列表页面find_cost.jsp中,给增加按钮设置访问路径,代码如下:
<%@page pageEncoding="utf-8" isELIgnored="false"%> <%@taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>达内-NetCTOSS</title> <link type="text/css" rel="stylesheet" media="all" href="../styles/global.css" /> <link type="text/css" rel="stylesheet" media="all" href="../styles/global_color.css" /> <script language="javascript" type="text/javascript"> //排序按钮的点击事件 function sort(btnObj) { if (btnObj.className == "sort_desc") btnObj.className = "sort_asc"; else btnObj.className = "sort_desc"; } //启用 function startFee() { var r = window.confirm("确定要启用此资费吗?资费启用后将不能修改和删除。"); document.getElementById("operate_result_info").style.display = "block"; } //删除 function deleteFee(id) { var r = window.confirm("确定要删除此资费吗?"); if(r) { // 如果用户确认,则调用删除资费action window.location.href = "deleteCost?id="+id; } } </script> </head> <body> <!--Logo区域开始--> <div id="header"> <img src="../images/logo.png" alt="logo" class="left"/> <a href="#">[退出]</a> </div> <!--Logo区域结束--> <!--导航区域开始--> <div id="navi"> <ul id="menu"> <li><a href="../index.html" class="index_off"></a></li> <li><a href="../role/role_list.html" class="role_off"></a></li> <li><a href="../admin/admin_list.html" class="admin_off"></a></li> <li><a href="../fee/fee_list.html" class="fee_on"></a></li> <li><a href="../account/account_list.html" class="account_off"></a></li> <li><a href="../service/service_list.html" class="service_off"></a></li> <li><a href="../bill/bill_list.html" class="bill_off"></a></li> <li><a href="../report/report_list.html" class="report_off"></a></li> <li><a href="../user/user_info.html" class="information_off"></a></li> <li><a href="../user/user_modi_pwd.html" class="password_off"></a></li> </ul> </div> <!--导航区域结束--> <!--主要区域开始--> <div id="main"> <form action="" method=""> <!--排序--> <div class="search_add"> <div> <!--<input type="button" value="月租" class="sort_asc" onclick="sort(this);" />--> <input type="button" value="基费" class="sort_asc" onclick="sort(this);" /> <input type="button" value="时长" class="sort_asc" onclick="sort(this);" /> </div> #cold_bold <input type="button" value="增加" class="btn_add" onclick="location.href='toAddCost';" /> </div> <!--启用操作的操作提示--> <div id="operate_result_info" class="operate_success"> <img src="../images/close.png" onclick="this.parentNode.style.display='none';" /> 删除成功! </div> <!--数据区域:用表格展示数据--> <div id="data"> <table id="datalist"> <tr> <th>资费ID</th> <th class="width100">资费名称</th> <th>基本时长</th> <th>基本费用</th> <th>单位费用</th> <th>创建时间</th> <th>开通时间</th> <th class="width50">状态</th> <th class="width200"></th> </tr> <!-- 使用Struts2标签遍历集合,使用OGNL表达式输出内容。 --> <s:iterator value="costs"> <tr> <td><s:property value="id"/></td> <td><a href="fee_detail.html"><s:property value="name"/></a></td> <td><s:property value="baseDuration"/></td> <td><s:property value="baseCost"/></td> <td><s:property value="unitCost"/></td> <td><s:property value="createTime"/></td> <td><s:property value="startTime"/></td> <td> <s:if test="status==0">开通</s:if> <s:else>暂停</s:else> </td> <td> <input type="button" value="启用" class="btn_start" onclick="startFee();" /> <input type="button" value="修改" class="btn_modify" onclick="location.href='fee_modi.html';" /> <input type="button" value="删除" class="btn_delete" onclick="deleteFee(<s:property value="id"/>);" /> </td> </tr> </s:iterator> </table> <p>业务说明:<br /> 1、创建资费时,状态为暂停,记载创建时间;<br /> 2、暂停状态下,可修改,可删除;<br /> 3、开通后,记载开通时间,且开通后不能修改、不能再停用、也不能删除;<br /> 4、业务账号修改资费时,在下月底统一触发,修改其关联的资费ID(此触发动作由程序处理) </p> </div> <!--分页--> <div id="pages"> <a href="#">上一页</a> <a href="#" class="current_page">1</a> <a href="#">2</a> <a href="#">3</a> <a href="#">4</a> <a href="#">5</a> <a href="#">下一页</a> </div> </form> </div> <!--主要区域结束--> <div id="footer"> <p>[源自北美的技术,最优秀的师资,最真实的企业环境,最适用的实战项目]</p> <p>版权所有(C)加拿大达内IT培训集团公司 </p> </div> </body> </html>
步骤四:测试
重新部署项目并重启tomcat,打开资费列表页面,点击增加按钮,效果如下图:
图-1
请求2:资费名称唯一性校验
步骤一:导包
由于需要使用json类型的result,因此需要导入新的包,名为struts2-json-plugin-2.1.8.jar。
步骤二:在DAO中追加根据名称查询资费的方法
在ICostDao中,追加根据名称查询资费的方法,代码如下:
package com.netctoss.dao; import java.util.List; import com.netctoss.entity.Cost; /** * 资费DAO接口 */ public interface ICostDao { // 此处略去其他方法的声明... #cold_bold /** #cold_bold * 根据名称查询资费 #cold_bold * @param name 资费名 #cold_bold * @return #cold_bold */ #cold_bold Cost findByName(String name); }
在CostDaoImpl类中,实现根据名称查询资费的方法,代码如下:
package com.netctoss.dao; import java.util.ArrayList; import java.util.List; import com.netctoss.entity.Cost; /** * 当前阶段学习重点是Struts2,对于DAO的实现就模拟实现了。 * 同学们可以使用JDBC/MyBatis自行实现该DAO。 */ public class CostDaoImpl implements ICostDao { // 此处略去其他方法的实现... #cold_bold @Override #cold_bold public Cost findByName(String name) { #cold_bold // 模拟根据名称查询资费数据,假设资费表中只有一条名为tarena的数据 #cold_bold if("tarena".equals(name)) { #cold_bold Cost c = new Cost(); #cold_bold c.setId(97); #cold_bold c.setName("tarena"); #cold_bold c.setBaseDuration(99); #cold_bold c.setBaseCost(9.9); #cold_bold c.setUnitCost(0.9); #cold_bold c.setDescr("tarena套餐"); #cold_bold c.setStatus("0"); #cold_bold c.setCostType("2"); #cold_bold return c; #cold_bold } #cold_bold return null; #cold_bold } }
步骤三:追加校验资费名Action
在com.netctoss.action包下,创建资费名称校验Action类CheckCostNameAction,该Action的输入属性是资费名,输出属性设置为一个Map,这样方便封装多个输出内容。在业务方法中根据资费名查询资费数据,并从结果是否为空来判断资费名是否重复,最终将判断结果封装于Map中输出给回调函数,代码如下:
package com.netctoss.action; import java.util.HashMap; import java.util.Map; import com.netctoss.dao.DAOFactory; import com.netctoss.dao.ICostDao; import com.netctoss.entity.Cost; public class CheckCostNameAction { // input private String name; // 资费名 // output private Map<String, Object> info = new HashMap<String, Object>(); // 提示信息 public String execute() { ICostDao dao = DAOFactory.getCostDAO(); Cost cost = null; try { cost = dao.findByName(name); } catch (Exception e) { e.printStackTrace(); /* * 由于是异步请求,并通过json类型的result处理结果, * 那么该result一定会把结构发给回调函数,因此这里 * 不要返回error了,否则result会把error.jsp中的代码 * 发给回调函数,因此这里只给出提示信息即可。 * */ info.put("success", false); info.put("message", "系统发生异常,请联系管理员."); } if(cost == null) { // 没找到资费,说明名称没重复 info.put("success", true); info.put("message", "有效的资费名称."); } else { //找到了资费数据,说明名称重复了 info.put("success", false); info.put("message", "资费名称已存在."); } return "success"; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Map<String, Object> getInfo() { return info; } public void setInfo(Map<String, Object> info) { this.info = info; } }
步骤四:在struts.xml中配置校验资费名Action
在struts.xml中,配置资费名校验action。由于该action需要使用json类型的result,因此需要先将它所在的package继承修改为json-default,然后再配置资费名校验action,并使用json类型的result将结果输出给回调函数,代码如下:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN" "http://struts.apache.org/dtds/struts-2.1.7.dtd"> <struts> <!-- 资费模块配置信息: 一般情况下,一个模块的配置单独封装在一个package下, 并且以模块名来命名package的name和namespace。 --> #cold_bold <package name="cost" namespace="/cost" extends="json-default"> <!—此处略去其他Action的配置... --> #cold_bold <!-- 资费名唯一性校验 --> #cold_bold <action name="checkCostName" #cold_bold class="com.netctoss.action.CheckCostNameAction"> #cold_bold <!-- 使用json类型的result把结果输出给回调函数 --> #cold_bold <result name="success" type="json"> #cold_bold <param name="root">info</param> #cold_bold </result> #cold_bold </action> </package> <!-- 登录模块 --> <package name="login" namespace="/login" extends="struts-default"> <!—此处略去其他Action的配置... --> </package> </struts>
步骤五:测试
在浏览器中,直接输入地址访问此action,并给name参数赋值,路径为http://localhost:8088/NETCTOSS/cost/checkCostName?name=aaa,通过观察浏览器中的内容可以达到测试目的。注意,有些浏览器可能不是直接显示结果,而是将接收的结果保存到文件中,这是浏览器设置的问题,也可以将内容保存后再行浏览。效果如下图:
图-2
本案例的完整代码如下。
ICostDao完整代码:
package com.netctoss.dao; import java.util.List; import com.netctoss.entity.Cost; /** * 资费DAO接口 */ public interface ICostDao { /** * 查询全部资费数据 */ List<Cost> findAll(); /** * 删除一条资费数据 * @param id 主键 */ void delete(int id); /** * 根据名称查询资费 * @param name 资费名 * @return */ Cost findByName(String name); }
CostDaoImpl完整代码:
package com.netctoss.dao; import java.util.ArrayList; import java.util.List; import com.netctoss.entity.Cost; /** * 当前阶段学习重点是Struts2,对于DAO的实现就模拟实现了。 * 同学们可以使用JDBC/MyBatis自行实现该DAO。 */ public class CostDaoImpl implements ICostDao { @Override public List<Cost> findAll() { // 模拟查询全部资费数据 List<Cost> list = new ArrayList<Cost>(); Cost c1 = new Cost(); c1.setId(95); c1.setName("6元套餐"); c1.setBaseDuration(66); c1.setBaseCost(6.6); c1.setUnitCost(0.6); c1.setDescr("6元套餐"); c1.setStatus("0"); c1.setCostType("2"); list.add(c1); Cost c2 = new Cost(); c2.setId(96); c2.setName("8元套餐"); c2.setBaseDuration(88); c2.setBaseCost(8.8); c2.setUnitCost(0.8); c2.setDescr("8元套餐"); c2.setStatus("0"); c2.setCostType("2"); list.add(c2); Cost c3 = new Cost(); c3.setId(97); c3.setName("tarena"); c3.setBaseDuration(99); c3.setBaseCost(9.9); c3.setUnitCost(0.9); c3.setDescr("tarena套餐"); c3.setStatus("0"); c3.setCostType("2"); list.add(c3); return list; } @Override public void delete(int id) { // 模拟根据id删除资费数据 System.out.println("删除ID为[" + id + "]的资费数据."); } @Override public Cost findByName(String name) { // 模拟根据名称查询资费数据,假设资费表中只有一条名为tarena的数据 if("tarena".equals(name)) { Cost c = new Cost(); c.setId(97); c.setName("tarena"); c.setBaseDuration(99); c.setBaseCost(9.9); c.setUnitCost(0.9); c.setDescr("tarena套餐"); c.setStatus("0"); c.setCostType("2"); return c; } return null; } }
CheckCostNameAction完整代码:
package com.netctoss.action; import java.util.HashMap; import java.util.Map; import com.netctoss.dao.DAOFactory; import com.netctoss.dao.ICostDao; import com.netctoss.entity.Cost; public class CheckCostNameAction { // input private String name; // 资费名 // output private Map<String, Object> info = new HashMap<String, Object>(); // 提示信息 public String execute() { ICostDao dao = DAOFactory.getCostDAO(); Cost cost = null; try { cost = dao.findByName(name); } catch (Exception e) { e.printStackTrace(); /* * 由于是异步请求,并通过json类型的result处理结果, * 那么该result一定会把结构发给回调函数,因此这里 * 不要返回error了,否则result会把error.jsp中的代码 * 发给回调函数,因此这里只给出提示信息即可。 * */ info.put("success", false); info.put("message", "系统发生异常,请联系管理员."); } if(cost == null) { // 没找到资费,说明名称没重复 info.put("success", true); info.put("message", "有效的资费名称."); } else { //找到了资费数据,说明名称重复了 info.put("success", false); info.put("message", "资费名称已存在."); } return "success"; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Map<String, Object> getInfo() { return info; } public void setInfo(Map<String, Object> info) { this.info = info; } }
struts.xml完整代码:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN" "http://struts.apache.org/dtds/struts-2.1.7.dtd"> <struts> <!-- 资费模块配置信息: 一般情况下,一个模块的配置单独封装在一个package下, 并且以模块名来命名package的name和namespace。 --> <package name="cost" namespace="/cost" extends="json-default"> <!-- 查询资费数据 --> <action name="findCost" class="com.netctoss.action.FindCostAction"> <!-- 正常情况下跳转到资费列表页面。 一般一个模块的页面要打包在一个文件夹下,并且文件夹以模块名命名。 --> <result name="success"> /WEB-INF/cost/find_cost.jsp </result> <!-- 错误情况下,跳转到错误页面。 错误页面可以被所有模块复用,因此放在main下, 该文件夹用于存放公用的页面。 --> <result name="error"> /WEB-INF/main/error.jsp </result> </action> <!-- 删除资费 --> <action name="deleteCost" class="com.netctoss.action.DeleteCostAction"> <!-- 删除完之后,重定向到查询action --> <result name="success" type="redirectAction"> findCost </result> <result name="error"> /WEB-INF/main/error.jsp </result> </action> <!-- 打开资费新增页 --> <action name="toAddCost"> <result name="success"> /WEB-INF/cost/add_cost.jsp </result> </action> <!-- 资费名唯一性校验 --> <action name="checkCostName" class="com.netctoss.action.CheckCostNameAction"> <!-- 使用json类型的result把结果输出给回调函数 --> <result name="success" type="json"> <param name="root">info</param> </result> </action> </package> <!-- 登录模块 --> <package name="login" namespace="/login" extends="struts-default"> <!-- 打开登录页面: 1、action的class属性可以省略,省略时Struts2 会自动实例化默认的Action类ActionSupport, 该类中有默认业务方法execute,返回success。 2、action的method属性可以省略,省略时Struts2 会自动调用execute方法。 --> <action name="toLogin"> <result name="success"> /WEB-INF/main/login.jsp </result> </action> <!-- 登录校验 --> <action name="login" class="com.netctoss.action.LoginAction"> <!-- 校验成功,跳转到系统首页 --> <result name="success"> /WEB-INF/main/index.jsp </result> <!-- 登录失败,跳转回登录页面 --> <result name="fail"> /WEB-INF/main/login.jsp </result> <!-- 报错,跳转到错误页面 --> <result name="error"> /WEB-INF/main/error.jsp </result> </action> <!-- 生成验证码 --> <action name="createImage" class="com.netctoss.action.CreateImageAction"> <!-- 使用stream类型的result --> <result name="success" type="stream"> <!-- 指定输出的内容 --> <param name="inputName">imageStream</param> </result> </action> </package> </struts>
find_cost.jsp完整代码:
<%@page pageEncoding="utf-8" isELIgnored="false"%> <%@taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>达内-NetCTOSS</title> <link type="text/css" rel="stylesheet" media="all" href="../styles/global.css" /> <link type="text/css" rel="stylesheet" media="all" href="../styles/global_color.css" /> <script language="javascript" type="text/javascript"> //排序按钮的点击事件 function sort(btnObj) { if (btnObj.className == "sort_desc") btnObj.className = "sort_asc"; else btnObj.className = "sort_desc"; } //启用 function startFee() { var r = window.confirm("确定要启用此资费吗?资费启用后将不能修改和删除。"); document.getElementById("operate_result_info").style.display = "block"; } //删除 function deleteFee(id) { var r = window.confirm("确定要删除此资费吗?"); if(r) { // 如果用户确认,则调用删除资费action window.location.href = "deleteCost?id="+id; } } </script> </head> <body> <!--Logo区域开始--> <div id="header"> <img src="../images/logo.png" alt="logo" class="left"/> <a href="#">[退出]</a> </div> <!--Logo区域结束--> <!--导航区域开始--> <div id="navi"> <ul id="menu"> <li><a href="../index.html" class="index_off"></a></li> <li><a href="../role/role_list.html" class="role_off"></a></li> <li><a href="../admin/admin_list.html" class="admin_off"></a></li> <li><a href="../fee/fee_list.html" class="fee_on"></a></li> <li><a href="../account/account_list.html" class="account_off"></a></li> <li><a href="../service/service_list.html" class="service_off"></a></li> <li><a href="../bill/bill_list.html" class="bill_off"></a></li> <li><a href="../report/report_list.html" class="report_off"></a></li> <li><a href="../user/user_info.html" class="information_off"></a></li> <li><a href="../user/user_modi_pwd.html" class="password_off"></a></li> </ul> </div> <!--导航区域结束--> <!--主要区域开始--> <div id="main"> <form action="" method=""> <!--排序--> <div class="search_add"> <div> <!--<input type="button" value="月租" class="sort_asc" onclick="sort(this);" />--> <input type="button" value="基费" class="sort_asc" onclick="sort(this);" /> <input type="button" value="时长" class="sort_asc" onclick="sort(this);" /> </div> <input type="button" value="增加" class="btn_add" onclick="location.href='toAddCost';" /> </div> <!--启用操作的操作提示--> <div id="operate_result_info" class="operate_success"> <img src="../images/close.png" onclick="this.parentNode.style.display='none';" /> 删除成功! </div> <!--数据区域:用表格展示数据--> <div id="data"> <table id="datalist"> <tr> <th>资费ID</th> <th class="width100">资费名称</th> <th>基本时长</th> <th>基本费用</th> <th>单位费用</th> <th>创建时间</th> <th>开通时间</th> <th class="width50">状态</th> <th class="width200"></th> </tr> <!-- 使用Struts2标签遍历集合,使用OGNL表达式输出内容。 --> <s:iterator value="costs"> <tr> <td><s:property value="id"/></td> <td><a href="fee_detail.html"><s:property value="name"/></a></td> <td><s:property value="baseDuration"/></td> <td><s:property value="baseCost"/></td> <td><s:property value="unitCost"/></td> <td><s:property value="createTime"/></td> <td><s:property value="startTime"/></td> <td> <s:if test="status==0">开通</s:if> <s:else>暂停</s:else> </td> <td> <input type="button" value="启用" class="btn_start" onclick="startFee();" /> <input type="button" value="修改" class="btn_modify" onclick="location.href='fee_modi.html';" /> <input type="button" value="删除" class="btn_delete" onclick="deleteFee(<s:property value="id"/>);" /> </td> </tr> </s:iterator> </table> <p>业务说明:<br /> 1、创建资费时,状态为暂停,记载创建时间;<br /> 2、暂停状态下,可修改,可删除;<br /> 3、开通后,记载开通时间,且开通后不能修改、不能再停用、也不能删除;<br /> 4、业务账号修改资费时,在下月底统一触发,修改其关联的资费ID(此触发动作由程序处理) </p> </div> <!--分页--> <div id="pages"> <a href="#">上一页</a> <a href="#" class="current_page">1</a> <a href="#">2</a> <a href="#">3</a> <a href="#">4</a> <a href="#">5</a> <a href="#">下一页</a> </div> </form> </div> <!--主要区域结束--> <div id="footer"> <p>[源自北美的技术,最优秀的师资,最真实的企业环境,最适用的实战项目]</p> <p>版权所有(C)加拿大达内IT培训集团公司 </p> </div> </body> </html>
add_cost.jsp完整代码:
<%@page pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>达内-NetCTOSS</title> <link type="text/css" rel="stylesheet" media="all" href="../styles/global.css" /> <link type="text/css" rel="stylesheet" media="all" href="../styles/global_color.css" /> <script language="javascript" type="text/javascript"> //保存结果的提示 function showResult() { showResultDiv(true); window.setTimeout("showResultDiv(false);", 3000); } function showResultDiv(flag) { var divResult = document.getElementById("save_result_info"); if (flag) divResult.style.display = "block"; else divResult.style.display = "none"; } //切换资费类型 function feeTypeChange(type) { var inputArray = document.getElementById("main").getElementsByTagName("input"); if (type == 1) { inputArray[4].readonly = true; inputArray[4].value = ""; inputArray[4].className += " readonly"; inputArray[5].readonly = false; inputArray[5].className = "width100"; inputArray[6].readonly = true; inputArray[6].className += " readonly"; inputArray[6].value = ""; } else if (type == 2) { inputArray[4].readonly = false; inputArray[4].className = "width100"; inputArray[5].readonly = false; inputArray[5].className = "width100"; inputArray[6].readonly = false; inputArray[6].className = "width100"; } else if (type == 3) { inputArray[4].readonly = true; inputArray[4].value = ""; inputArray[4].className += " readonly"; inputArray[5].readonly = true; inputArray[5].value = ""; inputArray[5].className += " readonly"; inputArray[6].readonly = false; inputArray[6].className = "width100"; } } </script> </head> <body> <!--Logo区域开始--> <div id="header"> <img src="../images/logo.png" alt="logo" class="left"/> <a href="#">[退出]</a> </div> <!--Logo区域结束--> <!--导航区域开始--> <div id="navi"> <ul id="menu"> <li><a href="../index.html" class="index_off"></a></li> <li><a href="../role/role_list.html" class="role_off"></a></li> <li><a href="../admin/admin_list.html" class="admin_off"></a></li> <li><a href="../fee/fee_list.html" class="fee_on"></a></li> <li><a href="../account/account_list.html" class="account_off"></a></li> <li><a href="../service/service_list.html" class="service_off"></a></li> <li><a href="../bill/bill_list.html" class="bill_off"></a></li> <li><a href="../report/report_list.html" class="report_off"></a></li> <li><a href="../user/user_info.html" class="information_off"></a></li> <li><a href="../user/user_modi_pwd.html" class="password_off"></a></li> </ul> </div> <!--导航区域结束--> <!--主要区域开始--> <div id="main"> <div id="save_result_info" class="save_fail">保存失败,资费名称重复!</div> <form action="" method="" class="main_form"> <div class="text_info clearfix"><span>资费名称:</span></div> <div class="input_info"> <input type="text" class="width300" value=""/> <span class="required">*</span> <div class="validate_msg_short">50长度的字母、数字、汉字和下划线的组合</div> </div> <div class="text_info clearfix"><span>资费类型:</span></div> <div class="input_info fee_type"> <input type="radio" name="radFeeType" id="monthly" onclick="feeTypeChange(1);" /> <label for="monthly">包月</label> <input type="radio" name="radFeeType" checked="checked" id="package" onclick="feeTypeChange(2);" /> <label for="package">套餐</label> <input type="radio" name="radFeeType" id="timeBased" onclick="feeTypeChange(3);" /> <label for="timeBased">计时</label> </div> <div class="text_info clearfix"><span>基本时长:</span></div> <div class="input_info"> <input type="text" value="" class="width100" /> <span class="info">小时</span> <span class="required">*</span> <div class="validate_msg_long">1-600之间的整数</div> </div> <div class="text_info clearfix"><span>基本费用:</span></div> <div class="input_info"> <input type="text" value="" class="width100" /> <span class="info">元</span> <span class="required">*</span> <div class="validate_msg_long error_msg">0-99999.99之间的数值</div> </div> <div class="text_info clearfix"><span>单位费用:</span></div> <div class="input_info"> <input type="text" value="" class="width100" /> <span class="info">元/小时</span> <span class="required">*</span> <div class="validate_msg_long error_msg">0-99999.99之间的数值</div> </div> <div class="text_info clearfix"><span>资费说明:</span></div> <div class="input_info_high"> <textarea class="width300 height70"></textarea> <div class="validate_msg_short error_msg">100长度的字母、数字、汉字和下划线的组合</div> </div> <div class="button_info clearfix"> <input type="button" value="保存" class="btn_save" onclick="showResult();" /> <input type="button" value="取消" class="btn_save" /> </div> </form> </div> <!--主要区域结束--> <div id="footer"> <span>[源自北美的技术,最优秀的师资,最真实的企业环境,最适用的实战项目]</span> <br /> <span>版权所有(C)加拿大达内IT培训集团公司 </span> </div> </body> </html>
完成资费名唯一性校验。
在资费新增页面上,给资费名文本框增加光标移除事件,并绑定资费名唯一性校验函数。该函数中,使用JQuery发送异步请求访问资费名校验action,并在回调函数中根据返回结果设置提示信息。
实现此案例需要按照如下步骤进行。
步骤一:引入JQuery
在WebRoot下创建js文件夹,将jquery-1.4.3.js文件复制到此文件夹下,完成后WebRoot结构如下图:
图-3
步骤二:新增页面上发起异步校验请求
在add_cost.jsp上,给资费名称文本框的onblur事件绑定资费名唯一性校验函数check_name,然后在<head>通过script标记引入JQuery,并实现check_name函数中的异步校验逻辑,代码如下:
<%@page pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>达内-NetCTOSS</title> <link type="text/css" rel="stylesheet" media="all" href="../styles/global.css" /> <link type="text/css" rel="stylesheet" media="all" href="../styles/global_color.css" /> #cold_bold <script language="javascript" type="text/javascript" src="../js/jquery-1.4.3.js"></script> <script language="javascript" type="text/javascript"> #cold_bold //校验资费名是否重复 #cold_bold function check_name() { #cold_bold var cost_name = $("#cost_name").val(); #cold_bold // 校验资费名是否为空 #cold_bold if(cost_name == "") { #cold_bold $("#name_msg").text("资费名不能为空.").addClass("error_msg"); #cold_bold return; #cold_bold } #cold_bold // 异步校验资费名是否重复 #cold_bold $.post( #cold_bold "checkCostName", #cold_bold {"name":cost_name}, #cold_bold function(data) { #cold_bold // 回调函数的参数就是返回的info属性 #cold_bold var info = data; #cold_bold // 根据返回值设置提示信息 #cold_bold if(info.success) { #cold_bold // 验证通过,设置提示信息并移除错误样式 #cold_bold $("#name_msg").text(info.message).removeClass("error_msg"); #cold_bold } else { #cold_bold // 验证失败,设置提示信息并添加错误样式 #cold_bold $("#name_msg").text(info.message).addClass("error_msg"); #cold_bold } #cold_bold } #cold_bold ); #cold_bold } //保存结果的提示 function showResult() { showResultDiv(true); window.setTimeout("showResultDiv(false);", 3000); } function showResultDiv(flag) { var divResult = document.getElementById("save_result_info"); if (flag) divResult.style.display = "block"; else divResult.style.display = "none"; } //切换资费类型 function feeTypeChange(type) { var inputArray = document.getElementById("main").getElementsByTagName("input"); if (type == 1) { inputArray[4].readonly = true; inputArray[4].value = ""; inputArray[4].className += " readonly"; inputArray[5].readonly = false; inputArray[5].className = "width100"; inputArray[6].readonly = true; inputArray[6].className += " readonly"; inputArray[6].value = ""; } else if (type == 2) { inputArray[4].readonly = false; inputArray[4].className = "width100"; inputArray[5].readonly = false; inputArray[5].className = "width100"; inputArray[6].readonly = false; inputArray[6].className = "width100"; } else if (type == 3) { inputArray[4].readonly = true; inputArray[4].value = ""; inputArray[4].className += " readonly"; inputArray[5].readonly = true; inputArray[5].value = ""; inputArray[5].className += " readonly"; inputArray[6].readonly = false; inputArray[6].className = "width100"; } } </script> </head> <body> <!--Logo区域开始--> <div id="header"> <img src="../images/logo.png" alt="logo" class="left"/> <a href="#">[退出]</a> </div> <!--Logo区域结束--> <!--导航区域开始--> <div id="navi"> <ul id="menu"> <li><a href="../index.html" class="index_off"></a></li> <li><a href="../role/role_list.html" class="role_off"></a></li> <li><a href="../admin/admin_list.html" class="admin_off"></a></li> <li><a href="../fee/fee_list.html" class="fee_on"></a></li> <li><a href="../account/account_list.html" class="account_off"></a></li> <li><a href="../service/service_list.html" class="service_off"></a></li> <li><a href="../bill/bill_list.html" class="bill_off"></a></li> <li><a href="../report/report_list.html" class="report_off"></a></li> <li><a href="../user/user_info.html" class="information_off"></a></li> <li><a href="../user/user_modi_pwd.html" class="password_off"></a></li> </ul> </div> <!--导航区域结束--> <!--主要区域开始--> <div id="main"> <div id="save_result_info" class="save_fail">保存失败,资费名称重复!</div> <form action="" method="" class="main_form"> <div class="text_info clearfix"><span>资费名称:</span></div> <div class="input_info"> #cold_bold <input type="text" class="width300" id="cost_name" onblur="check_name();"/> <span class="required">*</span> <div class="validate_msg_short" id="name_msg">50长度的字母、数字、汉字和下划线的组合</div> </div> <div class="text_info clearfix"><span>资费类型:</span></div> <div class="input_info fee_type"> <input type="radio" name="radFeeType" id="monthly" onclick="feeTypeChange(1);" /> <label for="monthly">包月</label> <input type="radio" name="radFeeType" checked="checked" id="package" onclick="feeTypeChange(2);" /> <label for="package">套餐</label> <input type="radio" name="radFeeType" id="timeBased" onclick="feeTypeChange(3);" /> <label for="timeBased">计时</label> </div> <div class="text_info clearfix"><span>基本时长:</span></div> <div class="input_info"> <input type="text" value="" class="width100" /> <span class="info">小时</span> <span class="required">*</span> <div class="validate_msg_long">1-600之间的整数</div> </div> <div class="text_info clearfix"><span>基本费用:</span></div> <div class="input_info"> <input type="text" value="" class="width100" /> <span class="info">元</span> <span class="required">*</span> <div class="validate_msg_long error_msg">0-99999.99之间的数值</div> </div> <div class="text_info clearfix"><span>单位费用:</span></div> <div class="input_info"> <input type="text" value="" class="width100" /> <span class="info">元/小时</span> <span class="required">*</span> <div class="validate_msg_long error_msg">0-99999.99之间的数值</div> </div> <div class="text_info clearfix"><span>资费说明:</span></div> <div class="input_info_high"> <textarea class="width300 height70"></textarea> <div class="validate_msg_short error_msg">100长度的字母、数字、汉字和下划线的组合</div> </div> <div class="button_info clearfix"> <input type="button" value="保存" class="btn_save" onclick="showResult();" /> <input type="button" value="取消" class="btn_save" /> </div> </form> </div> <!--主要区域结束--> <div id="footer"> <span>[源自北美的技术,最优秀的师资,最真实的企业环境,最适用的实战项目]</span> <br /> <span>版权所有(C)加拿大达内IT培训集团公司 </span> </div> </body> </html>
步骤三:测试
重新部署项目并重启tomcat,打开新增页面,输入一个已存在的资费名称,切换光标时效果如下图:
图-4
本案例的完整代码如下。
add_cost.jsp完整代码:
<%@page pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>达内-NetCTOSS</title> <link type="text/css" rel="stylesheet" media="all" href="../styles/global.css" /> <link type="text/css" rel="stylesheet" media="all" href="../styles/global_color.css" /> <script language="javascript" type="text/javascript" src="../js/jquery-1.4.3.js"></script> <script language="javascript" type="text/javascript"> //校验资费名是否重复 function check_name() { var cost_name = $("#cost_name").val(); // 校验资费名是否为空 if(cost_name == "") { $("#name_msg").text("资费名不能为空.").addClass("error_msg"); return; } // 异步校验资费名是否重复 $.post( "checkCostName", {"name":cost_name}, function(data) { // 回调函数的参数就是返回的info属性 var info = data; // 根据返回值设置提示信息 if(info.success) { // 验证通过,设置提示信息并移除错误样式 $("#name_msg").text(info.message).removeClass("error_msg"); } else { // 验证失败,设置提示信息并添加错误样式 $("#name_msg").text(info.message).addClass("error_msg"); } } ); } //保存结果的提示 function showResult() { showResultDiv(true); window.setTimeout("showResultDiv(false);", 3000); } function showResultDiv(flag) { var divResult = document.getElementById("save_result_info"); if (flag) divResult.style.display = "block"; else divResult.style.display = "none"; } //切换资费类型 function feeTypeChange(type) { var inputArray = document.getElementById("main").getElementsByTagName("input"); if (type == 1) { inputArray[4].readonly = true; inputArray[4].value = ""; inputArray[4].className += " readonly"; inputArray[5].readonly = false; inputArray[5].className = "width100"; inputArray[6].readonly = true; inputArray[6].className += " readonly"; inputArray[6].value = ""; } else if (type == 2) { inputArray[4].readonly = false; inputArray[4].className = "width100"; inputArray[5].readonly = false; inputArray[5].className = "width100"; inputArray[6].readonly = false; inputArray[6].className = "width100"; } else if (type == 3) { inputArray[4].readonly = true; inputArray[4].value = ""; inputArray[4].className += " readonly"; inputArray[5].readonly = true; inputArray[5].value = ""; inputArray[5].className += " readonly"; inputArray[6].readonly = false; inputArray[6].className = "width100"; } } </script> </head> <body> <!--Logo区域开始--> <div id="header"> <img src="../images/logo.png" alt="logo" class="left"/> <a href="#">[退出]</a> </div> <!--Logo区域结束--> <!--导航区域开始--> <div id="navi"> <ul id="menu"> <li><a href="../index.html" class="index_off"></a></li> <li><a href="../role/role_list.html" class="role_off"></a></li> <li><a href="../admin/admin_list.html" class="admin_off"></a></li> <li><a href="../fee/fee_list.html" class="fee_on"></a></li> <li><a href="../account/account_list.html" class="account_off"></a></li> <li><a href="../service/service_list.html" class="service_off"></a></li> <li><a href="../bill/bill_list.html" class="bill_off"></a></li> <li><a href="../report/report_list.html" class="report_off"></a></li> <li><a href="../user/user_info.html" class="information_off"></a></li> <li><a href="../user/user_modi_pwd.html" class="password_off"></a></li> </ul> </div> <!--导航区域结束--> <!--主要区域开始--> <div id="main"> <div id="save_result_info" class="save_fail">保存失败,资费名称重复!</div> <form action="" method="" class="main_form"> <div class="text_info clearfix"><span>资费名称:</span></div> <div class="input_info"> <input type="text" class="width300" id="cost_name" onblur="check_name();"/> <span class="required">*</span> <div class="validate_msg_short" id="name_msg">50长度的字母、数字、汉字和下划线的组合</div> </div> <div class="text_info clearfix"><span>资费类型:</span></div> <div class="input_info fee_type"> <input type="radio" name="radFeeType" id="monthly" onclick="feeTypeChange(1);" /> <label for="monthly">包月</label> <input type="radio" name="radFeeType" checked="checked" id="package" onclick="feeTypeChange(2);" /> <label for="package">套餐</label> <input type="radio" name="radFeeType" id="timeBased" onclick="feeTypeChange(3);" /> <label for="timeBased">计时</label> </div> <div class="text_info clearfix"><span>基本时长:</span></div> <div class="input_info"> <input type="text" value="" class="width100" /> <span class="info">小时</span> <span class="required">*</span> <div class="validate_msg_long">1-600之间的整数</div> </div> <div class="text_info clearfix"><span>基本费用:</span></div> <div class="input_info"> <input type="text" value="" class="width100" /> <span class="info">元</span> <span class="required">*</span> <div class="validate_msg_long error_msg">0-99999.99之间的数值</div> </div> <div class="text_info clearfix"><span>单位费用:</span></div> <div class="input_info"> <input type="text" value="" class="width100" /> <span class="info">元/小时</span> <span class="required">*</span> <div class="validate_msg_long error_msg">0-99999.99之间的数值</div> </div> <div class="text_info clearfix"><span>资费说明:</span></div> <div class="input_info_high"> <textarea class="width300 height70"></textarea> <div class="validate_msg_short error_msg">100长度的字母、数字、汉字和下划线的组合</div> </div> <div class="button_info clearfix"> <input type="button" value="保存" class="btn_save" onclick="showResult();" /> <input type="button" value="取消" class="btn_save" /> </div> </form> </div> <!--主要区域结束--> <div id="footer"> <span>[源自北美的技术,最优秀的师资,最真实的企业环境,最适用的实战项目]</span> <br /> <span>版权所有(C)加拿大达内IT培训集团公司 </span> </div> </body> </html>
增加资费的修改功能,用于修改一条资费数据。本案例中只要求打开修改页面,并将要修改的内容默认显示在修改页面表单的文本框中即可。
打开修改页面逻辑与打开新增页面一致,但同时要查询出要修改的数据并发送给修改页面,在修改页面上将这些数据默认显示在表单上。
对于数据的默认显示,我们可以使用Struts2提供的UI标签来做,UI标签的作用是可以生产框体同时设置其默认值。
实现此案例需要按照如下步骤进行。
步骤一:在DAO中追加根据ID查询资费的方法
在ICostDao中追加根据ID查询资费的方法,代码如下:
package com.netctoss.dao; import java.util.List; import com.netctoss.entity.Cost; /** * 资费DAO接口 */ public interface ICostDao { // 此处略去其他方法的声明... #cold_bold /** #cold_bold * 根据主键查询资费 #cold_bold * @param id 主键 #cold_bold * @return #cold_bold */ #cold_bold Cost findById(int id); }
在CostDaoImpl中实现该方法,代码如下:
package com.netctoss.dao; import java.util.ArrayList; import java.util.List; import com.netctoss.entity.Cost; /** * 当前阶段学习重点是Struts2,对于DAO的实现就模拟实现了。 * 同学们可以使用JDBC/MyBatis自行实现该DAO。 */ public class CostDaoImpl implements ICostDao { // 此处略去其他方法的实现... #cold_bold @Override #cold_bold public Cost findById(int id) { #cold_bold // 模拟根据id查询资费数据 #cold_bold Cost c = new Cost(); #cold_bold c.setId(97); #cold_bold c.setName("tarena"); #cold_bold c.setBaseDuration(99); #cold_bold c.setBaseCost(9.9); #cold_bold c.setUnitCost(0.9); #cold_bold c.setDescr("tarena套餐"); #cold_bold c.setStatus("0"); #cold_bold c.setCostType("2"); #cold_bold return c; #cold_bold } }
步骤二:创建打开修改页面的Action
在com.netctoss.action包下,创建打开修改页面的类ToUpdateCostAction,在该Action下定义输入属性为资费id,输出属性为资费实体对象,并在业务方法中调用DAO根据id查询出资费的实体对象。代码如下:
package com.netctoss.action; import com.netctoss.dao.DAOFactory; import com.netctoss.dao.ICostDao; import com.netctoss.entity.Cost; public class ToUpdateCostAction { // input private int id; // output private Cost cost; public String execute() { ICostDao dao = DAOFactory.getCostDAO(); try { cost = dao.findById(id); } catch (Exception e) { e.printStackTrace(); return "error"; } return "success"; } public int getId() { return id; } public void setId(int id) { this.id = id; } public Cost getCost() { return cost; } public void setCost(Cost cost) { this.cost = cost; } }
步骤三:在struts.xml中配置该action
在struts.xml中,配置打开修改页面的action,代码如下:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN" "http://struts.apache.org/dtds/struts-2.1.7.dtd"> <struts> <!-- 资费模块配置信息: 一般情况下,一个模块的配置单独封装在一个package下, 并且以模块名来命名package的name和namespace。 --> <package name="cost" namespace="/cost" extends="json-default"> <!—此处略去其他Action的配置... --> #cold_bold <!-- 打开修改页面 --> #cold_bold <action name="toUpdateCost" #cold_bold class="com.netctoss.action.ToUpdateCostAction"> #cold_bold <result name="success"> #cold_bold /WEB-INF/cost/update_cost.jsp #cold_bold </result> #cold_bold <result name="error"> #cold_bold /WEB-INF/main/error.jsp #cold_bold </result> #cold_bold </action> </package> <!-- 登录模块 --> <package name="login" namespace="/login" extends="struts-default"> <!—此处略去其他Action的配置... --> </package> </struts>
步骤四:创建资费修改页面
在WEB-INF/cost下,创建资费修改页面update_cost.jsp,并将静态页面代码复制到此JSP中。代码如下:
<%@page pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>达内-NetCTOSS</title> <link type="text/css" rel="stylesheet" media="all" href="../styles/global.css" /> <link type="text/css" rel="stylesheet" media="all" href="../styles/global_color.css" /> <script language="javascript" type="text/javascript"> //保存结果的提示 function showResult() { showResultDiv(true); window.setTimeout("showResultDiv(false);", 3000); } function showResultDiv(flag) { var divResult = document.getElementById("save_result_info"); if (flag) divResult.style.display = "block"; else divResult.style.display = "none"; } //切换资费类型 function feeTypeChange(type) { var inputArray = document.getElementById("main").getElementsByTagName("input"); if (type == 1) { inputArray[5].readonly = true; inputArray[5].value = ""; inputArray[5].className += " readonly"; inputArray[6].readonly = false; inputArray[6].className = "width100"; inputArray[7].readonly = true; inputArray[7].className += " readonly"; inputArray[7].value = ""; } else if (type == 2) { inputArray[5].readonly = false; inputArray[5].className = "width100"; inputArray[6].readonly = false; inputArray[6].className = "width100"; inputArray[7].readonly = false; inputArray[7].className = "width100"; } else if (type == 3) { inputArray[5].readonly = true; inputArray[5].value = ""; inputArray[5].className += " readonly"; inputArray[6].readonly = true; inputArray[6].value = ""; inputArray[6].className += " readonly"; inputArray[7].readonly = false; inputArray[7].className = "width100"; } } </script> </head> <body> <!--Logo区域开始--> <div id="header"> <img src="../images/logo.png" alt="logo" class="left"/> <a href="#">[退出]</a> </div> <!--Logo区域结束--> <!--导航区域开始--> <div id="navi"> <ul id="menu"> <li><a href="../index.html" class="index_off"></a></li> <li><a href="../role/role_list.html" class="role_off"></a></li> <li><a href="../admin/admin_list.html" class="admin_off"></a></li> <li><a href="../fee/fee_list.html" class="fee_on"></a></li> <li><a href="../account/account_list.html" class="account_off"></a></li> <li><a href="../service/service_list.html" class="service_off"></a></li> <li><a href="../bill/bill_list.html" class="bill_off"></a></li> <li><a href="../report/report_list.html" class="report_off"></a></li> <li><a href="../user/user_info.html" class="information_off"></a></li> <li><a href="../user/user_modi_pwd.html" class="password_off"></a></li> </ul> </div> <!--导航区域结束--> <!--主要区域开始--> <div id="main"> <div id="save_result_info" class="save_success">保存成功!</div> <form action="" method="" class="main_form"> <div class="text_info clearfix"><span>资费ID:</span></div> <div class="input_info"><input type="text" class="readonly" readonly value="1" /></div> <div class="text_info clearfix"><span>资费名称:</span></div> <div class="input_info"> <input type="text" class="width300" value="包 20 小时"/> <span class="required">*</span> <div class="validate_msg_short">50长度的字母、数字、汉字和下划线的组合</div> </div> <div class="text_info clearfix"><span>资费类型:</span></div> <div class="input_info fee_type"> <input type="radio" name="radFeeType" id="monthly" onclick="feeTypeChange(1);" /> <label for="monthly">包月</label> <input type="radio" name="radFeeType" checked="checked" id="package" onclick="feeTypeChange(2);" /> <label for="package">套餐</label> <input type="radio" name="radFeeType" id="timeBased" onclick="feeTypeChange(3);" /> <label for="timeBased">计时</label> </div> <div class="text_info clearfix"><span>基本时长:</span></div> <div class="input_info"> <input type="text" value="" class="width100" /> <span class="info">小时</span> <span class="required">*</span> <div class="validate_msg_long">1-600之间的整数</div> </div> <div class="text_info clearfix"><span>基本费用:</span></div> <div class="input_info"> <input type="text" value="" class="width100" /> <span class="info">元</span> <span class="required">*</span> <div class="validate_msg_long">0-99999.99之间的数值</div> </div> <div class="text_info clearfix"><span>单位费用:</span></div> <div class="input_info"> <input type="text" value="" class="width100" /> <span class="info">元/小时</span> <span class="required">*</span> <div class="validate_msg_long">0-99999.99之间的数值</div> </div> <div class="text_info clearfix"><span>资费说明:</span></div> <div class="input_info_high"> <textarea class="width300 height70">没有启用的资费,可以修改除 ID 以外的所有信息 </textarea> <div class="validate_msg_short">100长度的字母、数字、汉字和下划线的组合</div> </div> <div class="button_info clearfix"> <input type="button" value="保存" class="btn_save" onclick="showResult();" /> <input type="button" value="取消" class="btn_save" /> </div> </form> </div> <!--主要区域结束--> <div id="footer"> <span>[源自北美的技术,最优秀的师资,最真实的企业环境,最适用的实战项目]</span> <br /> <span>版权所有(C)加拿大达内IT培训集团公司 </span> </div> </body> </html>
步骤五:设置修改按钮URL
在find_cost.jsp上,设置修改按钮的请求路径为打开修改页面的action,并传入参数id。代码如下:
<%@page pageEncoding="utf-8" isELIgnored="false"%> <%@taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>达内-NetCTOSS</title> <link type="text/css" rel="stylesheet" media="all" href="../styles/global.css" /> <link type="text/css" rel="stylesheet" media="all" href="../styles/global_color.css" /> <script language="javascript" type="text/javascript"> //排序按钮的点击事件 function sort(btnObj) { if (btnObj.className == "sort_desc") btnObj.className = "sort_asc"; else btnObj.className = "sort_desc"; } //启用 function startFee() { var r = window.confirm("确定要启用此资费吗?资费启用后将不能修改和删除。"); document.getElementById("operate_result_info").style.display = "block"; } //删除 function deleteFee(id) { var r = window.confirm("确定要删除此资费吗?"); if(r) { // 如果用户确认,则调用删除资费action window.location.href = "deleteCost?id="+id; } } </script> </head> <body> <!--Logo区域开始--> <div id="header"> <img src="../images/logo.png" alt="logo" class="left"/> <a href="#">[退出]</a> </div> <!--Logo区域结束--> <!--导航区域开始--> <div id="navi"> <ul id="menu"> <li><a href="../index.html" class="index_off"></a></li> <li><a href="../role/role_list.html" class="role_off"></a></li> <li><a href="../admin/admin_list.html" class="admin_off"></a></li> <li><a href="../fee/fee_list.html" class="fee_on"></a></li> <li><a href="../account/account_list.html" class="account_off"></a></li> <li><a href="../service/service_list.html" class="service_off"></a></li> <li><a href="../bill/bill_list.html" class="bill_off"></a></li> <li><a href="../report/report_list.html" class="report_off"></a></li> <li><a href="../user/user_info.html" class="information_off"></a></li> <li><a href="../user/user_modi_pwd.html" class="password_off"></a></li> </ul> </div> <!--导航区域结束--> <!--主要区域开始--> <div id="main"> <form action="" method=""> <!--排序--> <div class="search_add"> <div> <!--<input type="button" value="月租" class="sort_asc" onclick="sort(this);" />--> <input type="button" value="基费" class="sort_asc" onclick="sort(this);" /> <input type="button" value="时长" class="sort_asc" onclick="sort(this);" /> </div> <input type="button" value="增加" class="btn_add" onclick="location.href='toAddCost';" /> </div> <!--启用操作的操作提示--> <div id="operate_result_info" class="operate_success"> <img src="../images/close.png" onclick="this.parentNode.style.display='none';" /> 删除成功! </div> <!--数据区域:用表格展示数据--> <div id="data"> <table id="datalist"> <tr> <th>资费ID</th> <th class="width100">资费名称</th> <th>基本时长</th> <th>基本费用</th> <th>单位费用</th> <th>创建时间</th> <th>开通时间</th> <th class="width50">状态</th> <th class="width200"></th> </tr> <!-- 使用Struts2标签遍历集合,使用OGNL表达式输出内容。 --> <s:iterator value="costs"> <tr> <td><s:property value="id"/></td> <td><a href="fee_detail.html"><s:property value="name"/></a></td> <td><s:property value="baseDuration"/></td> <td><s:property value="baseCost"/></td> <td><s:property value="unitCost"/></td> <td><s:property value="createTime"/></td> <td><s:property value="startTime"/></td> <td> <s:if test="status==0">开通</s:if> <s:else>暂停</s:else> </td> <td> <input type="button" value="启用" class="btn_start" onclick="startFee();" /> #cold_bold <input type="button" value="修改" class="btn_modify" onclick="location.href='toUpdateCost?id=<s:property value="id"/>';" /> <input type="button" value="删除" class="btn_delete" onclick="deleteFee(<s:property value="id"/>);" /> </td> </tr> </s:iterator> </table> <p>业务说明:<br /> 1、创建资费时,状态为暂停,记载创建时间;<br /> 2、暂停状态下,可修改,可删除;<br /> 3、开通后,记载开通时间,且开通后不能修改、不能再停用、也不能删除;<br /> 4、业务账号修改资费时,在下月底统一触发,修改其关联的资费ID(此触发动作由程序处理) </p> </div> <!--分页--> <div id="pages"> <a href="#">上一页</a> <a href="#" class="current_page">1</a> <a href="#">2</a> <a href="#">3</a> <a href="#">4</a> <a href="#">5</a> <a href="#">下一页</a> </div> </form> </div> <!--主要区域结束--> <div id="footer"> <p>[源自北美的技术,最优秀的师资,最真实的企业环境,最适用的实战项目]</p> <p>版权所有(C)加拿大达内IT培训集团公司 </p> </div> </body> </html>
步骤六:阶段测试
重新部署项目并重启tomcat,打开资费列表页面,点击任意的修改按钮,效果如下图:
图-5
步骤七:在修改页面上使用UI标签回显修改数据
在update_cost.jsp上,使用UI标签生成框体并给框体设置默认值。代码如下:
<%@page pageEncoding="utf-8"%> <%@taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>达内-NetCTOSS</title> <link type="text/css" rel="stylesheet" media="all" href="../styles/global.css" /> <link type="text/css" rel="stylesheet" media="all" href="../styles/global_color.css" /> <script language="javascript" type="text/javascript"> //保存结果的提示 function showResult() { showResultDiv(true); window.setTimeout("showResultDiv(false);", 3000); } function showResultDiv(flag) { var divResult = document.getElementById("save_result_info"); if (flag) divResult.style.display = "block"; else divResult.style.display = "none"; } //切换资费类型 function feeTypeChange(type) { var inputArray = document.getElementById("main").getElementsByTagName("input"); if (type == 1) { inputArray[5].readonly = true; inputArray[5].value = ""; inputArray[5].className += " readonly"; inputArray[6].readonly = false; inputArray[6].className = "width100"; inputArray[7].readonly = true; inputArray[7].className += " readonly"; inputArray[7].value = ""; } else if (type == 2) { inputArray[5].readonly = false; inputArray[5].className = "width100"; inputArray[6].readonly = false; inputArray[6].className = "width100"; inputArray[7].readonly = false; inputArray[7].className = "width100"; } else if (type == 3) { inputArray[5].readonly = true; inputArray[5].value = ""; inputArray[5].className += " readonly"; inputArray[6].readonly = true; inputArray[6].value = ""; inputArray[6].className += " readonly"; inputArray[7].readonly = false; inputArray[7].className = "width100"; } } </script> </head> <body> <!--Logo区域开始--> <div id="header"> <img src="../images/logo.png" alt="logo" class="left"/> <a href="#">[退出]</a> </div> <!--Logo区域结束--> <!--导航区域开始--> <div id="navi"> <ul id="menu"> <li><a href="../index.html" class="index_off"></a></li> <li><a href="../role/role_list.html" class="role_off"></a></li> <li><a href="../admin/admin_list.html" class="admin_off"></a></li> <li><a href="../fee/fee_list.html" class="fee_on"></a></li> <li><a href="../account/account_list.html" class="account_off"></a></li> <li><a href="../service/service_list.html" class="service_off"></a></li> <li><a href="../bill/bill_list.html" class="bill_off"></a></li> <li><a href="../report/report_list.html" class="report_off"></a></li> <li><a href="../user/user_info.html" class="information_off"></a></li> <li><a href="../user/user_modi_pwd.html" class="password_off"></a></li> </ul> </div> <!--导航区域结束--> <!--主要区域开始--> <div id="main"> <div id="save_result_info" class="save_success">保存成功!</div> <form action="" method="" class="main_form"> <div class="text_info clearfix"><span>资费ID:</span></div> <div class="input_info"> #cold_bold <s:textfield name="cost.id" cssClass="readonly" readonly="true"/> </div> <div class="text_info clearfix"><span>资费名称:</span></div> <div class="input_info"> #cold_bold <s:textfield name="cost.name" cssClass="width300" /> <span class="required">*</span> <div class="validate_msg_short">50长度的字母、数字、汉字和下划线的组合</div> </div> <div class="text_info clearfix"><span>资费类型:</span></div> <div class="input_info fee_type"> #cold_bold <s:radio name="cost.costType" list="#{'1':'包月','2':'套餐','3':'计时' }" onclick="feeTypeChange(this.value)"/> </div> <div class="text_info clearfix"><span>基本时长:</span></div> <div class="input_info"> #cold_bold <s:textfield name="cost.baseDuration" cssClass="width100"/> <span class="info">小时</span> <span class="required">*</span> <div class="validate_msg_long">1-600之间的整数</div> </div> <div class="text_info clearfix"><span>基本费用:</span></div> <div class="input_info"> #cold_bold <s:textfield name="cost.baseCost" cssClass="width100"/> <span class="info">元</span> <span class="required">*</span> <div class="validate_msg_long">0-99999.99之间的数值</div> </div> <div class="text_info clearfix"><span>单位费用:</span></div> <div class="input_info"> #cold_bold <s:textfield name="cost.unitCost" cssClass="width100"/> <span class="info">元/小时</span> <span class="required">*</span> <div class="validate_msg_long">0-99999.99之间的数值</div> </div> <div class="text_info clearfix"><span>资费说明:</span></div> <div class="input_info_high"> #cold_bold <s:textarea name="cost.descr" cssClass="width300 height70"/> <div class="validate_msg_short">100长度的字母、数字、汉字和下划线的组合</div> </div> <div class="button_info clearfix"> <input type="button" value="保存" class="btn_save" onclick="showResult();" /> <input type="button" value="取消" class="btn_save" /> </div> </form> </div> <!--主要区域结束--> <div id="footer"> <span>[源自北美的技术,最优秀的师资,最真实的企业环境,最适用的实战项目]</span> <br /> <span>版权所有(C)加拿大达内IT培训集团公司 </span> </div> </body> </html>
步骤八:测试
重新访问资费列表页面并点击修改按钮,效果如下图:
图-6
本案例的完整代码如下。
ICostDao完整代码:
package com.netctoss.dao; import java.util.List; import com.netctoss.entity.Cost; /** * 资费DAO接口 */ public interface ICostDao { /** * 查询全部资费数据 */ List<Cost> findAll(); /** * 删除一条资费数据 * @param id 主键 */ void delete(int id); /** * 根据名称查询资费 * @param name 资费名 * @return */ Cost findByName(String name); /** * 根据主键查询资费 * @param id 主键 * @return */ Cost findById(int id); }
CostDaoImpl完整代码:
package com.netctoss.dao; import java.util.ArrayList; import java.util.List; import com.netctoss.entity.Cost; /** * 当前阶段学习重点是Struts2,对于DAO的实现就模拟实现了。 * 同学们可以使用JDBC/MyBatis自行实现该DAO。 */ public class CostDaoImpl implements ICostDao { @Override public List<Cost> findAll() { // 模拟查询全部资费数据 List<Cost> list = new ArrayList<Cost>(); Cost c1 = new Cost(); c1.setId(95); c1.setName("6元套餐"); c1.setBaseDuration(66); c1.setBaseCost(6.6); c1.setUnitCost(0.6); c1.setDescr("6元套餐"); c1.setStatus("0"); c1.setCostType("2"); list.add(c1); Cost c2 = new Cost(); c2.setId(96); c2.setName("8元套餐"); c2.setBaseDuration(88); c2.setBaseCost(8.8); c2.setUnitCost(0.8); c2.setDescr("8元套餐"); c2.setStatus("0"); c2.setCostType("2"); list.add(c2); Cost c3 = new Cost(); c3.setId(97); c3.setName("tarena"); c3.setBaseDuration(99); c3.setBaseCost(9.9); c3.setUnitCost(0.9); c3.setDescr("tarena套餐"); c3.setStatus("0"); c3.setCostType("2"); list.add(c3); return list; } @Override public void delete(int id) { // 模拟根据id删除资费数据 System.out.println("删除ID为[" + id + "]的资费数据."); } @Override public Cost findByName(String name) { // 模拟根据名称查询资费数据,假设资费表中只有一条名为tarena的数据 if("tarena".equals(name)) { Cost c = new Cost(); c.setId(97); c.setName("tarena"); c.setBaseDuration(99); c.setBaseCost(9.9); c.setUnitCost(0.9); c.setDescr("tarena套餐"); c.setStatus("0"); c.setCostType("2"); return c; } return null; } @Override public Cost findById(int id) { // 模拟根据id查询资费数据 Cost c = new Cost(); c.setId(97); c.setName("tarena"); c.setBaseDuration(99); c.setBaseCost(9.9); c.setUnitCost(0.9); c.setDescr("tarena套餐"); c.setStatus("0"); c.setCostType("2"); return c; } }
ToUpdateCostAction完整代码:
package com.netctoss.action; import com.netctoss.dao.DAOFactory; import com.netctoss.dao.ICostDao; import com.netctoss.entity.Cost; public class ToUpdateCostAction { // input private int id; // output private Cost cost; public String execute() { ICostDao dao = DAOFactory.getCostDAO(); try { cost = dao.findById(id); } catch (Exception e) { e.printStackTrace(); return "error"; } return "success"; } public int getId() { return id; } public void setId(int id) { this.id = id; } public Cost getCost() { return cost; } public void setCost(Cost cost) { this.cost = cost; } }
struts.xml完整代码:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN" "http://struts.apache.org/dtds/struts-2.1.7.dtd"> <struts> <!-- 资费模块配置信息: 一般情况下,一个模块的配置单独封装在一个package下, 并且以模块名来命名package的name和namespace。 --> <package name="cost" namespace="/cost" extends="json-default"> <!-- 查询资费数据 --> <action name="findCost" class="com.netctoss.action.FindCostAction"> <!-- 正常情况下跳转到资费列表页面。 一般一个模块的页面要打包在一个文件夹下,并且文件夹以模块名命名。 --> <result name="success"> /WEB-INF/cost/find_cost.jsp </result> <!-- 错误情况下,跳转到错误页面。 错误页面可以被所有模块复用,因此放在main下, 该文件夹用于存放公用的页面。 --> <result name="error"> /WEB-INF/main/error.jsp </result> </action> <!-- 删除资费 --> <action name="deleteCost" class="com.netctoss.action.DeleteCostAction"> <!-- 删除完之后,重定向到查询action --> <result name="success" type="redirectAction"> findCost </result> <result name="error"> /WEB-INF/main/error.jsp </result> </action> <!-- 打开资费新增页 --> <action name="toAddCost"> <result name="success"> /WEB-INF/cost/add_cost.jsp </result> </action> <!-- 资费名唯一性校验 --> <action name="checkCostName" class="com.netctoss.action.CheckCostNameAction"> <!-- 使用json类型的result把结果输出给回调函数 --> <result name="success" type="json"> <param name="root">info</param> </result> </action> <!-- 打开修改页面 --> <action name="toUpdateCost" class="com.netctoss.action.ToUpdateCostAction"> <result name="success"> /WEB-INF/cost/update_cost.jsp </result> <result name="error"> /WEB-INF/main/error.jsp </result> </action> </package> <!-- 登录模块 --> <package name="login" namespace="/login" extends="struts-default"> <!-- 打开登录页面: 1、action的class属性可以省略,省略时Struts2 会自动实例化默认的Action类ActionSupport, 该类中有默认业务方法execute,返回success。 2、action的method属性可以省略,省略时Struts2 会自动调用execute方法。 --> <action name="toLogin"> <result name="success"> /WEB-INF/main/login.jsp </result> </action> <!-- 登录校验 --> <action name="login" class="com.netctoss.action.LoginAction"> <!-- 校验成功,跳转到系统首页 --> <result name="success"> /WEB-INF/main/index.jsp </result> <!-- 登录失败,跳转回登录页面 --> <result name="fail"> /WEB-INF/main/login.jsp </result> <!-- 报错,跳转到错误页面 --> <result name="error"> /WEB-INF/main/error.jsp </result> </action> <!-- 生成验证码 --> <action name="createImage" class="com.netctoss.action.CreateImageAction"> <!-- 使用stream类型的result --> <result name="success" type="stream"> <!-- 指定输出的内容 --> <param name="inputName">imageStream</param> </result> </action> </package> </struts>
find_cost.jsp完整代码:
<%@page pageEncoding="utf-8" isELIgnored="false"%> <%@taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>达内-NetCTOSS</title> <link type="text/css" rel="stylesheet" media="all" href="../styles/global.css" /> <link type="text/css" rel="stylesheet" media="all" href="../styles/global_color.css" /> <script language="javascript" type="text/javascript"> //排序按钮的点击事件 function sort(btnObj) { if (btnObj.className == "sort_desc") btnObj.className = "sort_asc"; else btnObj.className = "sort_desc"; } //启用 function startFee() { var r = window.confirm("确定要启用此资费吗?资费启用后将不能修改和删除。"); document.getElementById("operate_result_info").style.display = "block"; } //删除 function deleteFee(id) { var r = window.confirm("确定要删除此资费吗?"); if(r) { // 如果用户确认,则调用删除资费action window.location.href = "deleteCost?id="+id; } } </script> </head> <body> <!--Logo区域开始--> <div id="header"> <img src="../images/logo.png" alt="logo" class="left"/> <a href="#">[退出]</a> </div> <!--Logo区域结束--> <!--导航区域开始--> <div id="navi"> <ul id="menu"> <li><a href="../index.html" class="index_off"></a></li> <li><a href="../role/role_list.html" class="role_off"></a></li> <li><a href="../admin/admin_list.html" class="admin_off"></a></li> <li><a href="../fee/fee_list.html" class="fee_on"></a></li> <li><a href="../account/account_list.html" class="account_off"></a></li> <li><a href="../service/service_list.html" class="service_off"></a></li> <li><a href="../bill/bill_list.html" class="bill_off"></a></li> <li><a href="../report/report_list.html" class="report_off"></a></li> <li><a href="../user/user_info.html" class="information_off"></a></li> <li><a href="../user/user_modi_pwd.html" class="password_off"></a></li> </ul> </div> <!--导航区域结束--> <!--主要区域开始--> <div id="main"> <form action="" method=""> <!--排序--> <div class="search_add"> <div> <!--<input type="button" value="月租" class="sort_asc" onclick="sort(this);" />--> <input type="button" value="基费" class="sort_asc" onclick="sort(this);" /> <input type="button" value="时长" class="sort_asc" onclick="sort(this);" /> </div> <input type="button" value="增加" class="btn_add" onclick="location.href='toAddCost';" /> </div> <!--启用操作的操作提示--> <div id="operate_result_info" class="operate_success"> <img src="../images/close.png" onclick="this.parentNode.style.display='none';" /> 删除成功! </div> <!--数据区域:用表格展示数据--> <div id="data"> <table id="datalist"> <tr> <th>资费ID</th> <th class="width100">资费名称</th> <th>基本时长</th> <th>基本费用</th> <th>单位费用</th> <th>创建时间</th> <th>开通时间</th> <th class="width50">状态</th> <th class="width200"></th> </tr> <!-- 使用Struts2标签遍历集合,使用OGNL表达式输出内容。 --> <s:iterator value="costs"> <tr> <td><s:property value="id"/></td> <td><a href="fee_detail.html"><s:property value="name"/></a></td> <td><s:property value="baseDuration"/></td> <td><s:property value="baseCost"/></td> <td><s:property value="unitCost"/></td> <td><s:property value="createTime"/></td> <td><s:property value="startTime"/></td> <td> <s:if test="status==0">开通</s:if> <s:else>暂停</s:else> </td> <td> <input type="button" value="启用" class="btn_start" onclick="startFee();" /> <input type="button" value="修改" class="btn_modify" onclick="location.href='toUpdateCost?id=<s:property value="id"/>';" /> <input type="button" value="删除" class="btn_delete" onclick="deleteFee(<s:property value="id"/>);" /> </td> </tr> </s:iterator> </table> <p>业务说明:<br /> 1、创建资费时,状态为暂停,记载创建时间;<br /> 2、暂停状态下,可修改,可删除;<br /> 3、开通后,记载开通时间,且开通后不能修改、不能再停用、也不能删除;<br /> 4、业务账号修改资费时,在下月底统一触发,修改其关联的资费ID(此触发动作由程序处理) </p> </div> <!--分页--> <div id="pages"> <!-- 如果当前页是第一页,则不允许再点上一页。 否则点击上一页时访问page-1页。 --> <s:if test="page==1"> <a href="#">上一页</a> </s:if> <s:else> <a href="findCost?page=<s:property value="page-1"/>">上一页</a> </s:else> <!-- 循环输出页码 --> <s:iterator begin="1" end="totalPage" var="p"> <!-- 1.如果循环页码等于当前页,则给与当前页样式current_page 2.链接findCost是相对路径,相对于当前浏览器地址栏的路径, 如果findCost的路径与地址栏路径的namespace相同, 则可以将namespace及之前的部分省略。 --> <s:if test="#p==page"> <a href="findCost?page=<s:property value="#p"/>" class="current_page"><s:property value="#p"/></a> </s:if> <s:else> <a href="findCost?page=<s:property value="#p"/>"><s:property value="#p"/></a> </s:else> </s:iterator> <!-- 如果当前页是最后一页,则不允许再点下一页。 否则点击下一页时访问page+1页。 --> <s:if test="page==totalPage"> <a href="#">下一页</a> </s:if> <s:else> <a href="findCost?page=<s:property value="page+1"/>">下一页</a> </s:else> </div> </form> </div> <!--主要区域结束--> <div id="footer"> <p>[源自北美的技术,最优秀的师资,最真实的企业环境,最适用的实战项目]</p> <p>版权所有(C)加拿大达内IT培训集团公司 </p> </div> </body> </html>
update_cost.jsp完整代码:
<%@page pageEncoding="utf-8"%> <%@taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>达内-NetCTOSS</title> <link type="text/css" rel="stylesheet" media="all" href="../styles/global.css" /> <link type="text/css" rel="stylesheet" media="all" href="../styles/global_color.css" /> <script language="javascript" type="text/javascript"> //保存结果的提示 function showResult() { showResultDiv(true); window.setTimeout("showResultDiv(false);", 3000); } function showResultDiv(flag) { var divResult = document.getElementById("save_result_info"); if (flag) divResult.style.display = "block"; else divResult.style.display = "none"; } //切换资费类型 function feeTypeChange(type) { var inputArray = document.getElementById("main").getElementsByTagName("input"); if (type == 1) { inputArray[5].readonly = true; inputArray[5].value = ""; inputArray[5].className += " readonly"; inputArray[6].readonly = false; inputArray[6].className = "width100"; inputArray[7].readonly = true; inputArray[7].className += " readonly"; inputArray[7].value = ""; } else if (type == 2) { inputArray[5].readonly = false; inputArray[5].className = "width100"; inputArray[6].readonly = false; inputArray[6].className = "width100"; inputArray[7].readonly = false; inputArray[7].className = "width100"; } else if (type == 3) { inputArray[5].readonly = true; inputArray[5].value = ""; inputArray[5].className += " readonly"; inputArray[6].readonly = true; inputArray[6].value = ""; inputArray[6].className += " readonly"; inputArray[7].readonly = false; inputArray[7].className = "width100"; } } </script> </head> <body> <!--Logo区域开始--> <div id="header"> <img src="../images/logo.png" alt="logo" class="left"/> <a href="#">[退出]</a> </div> <!--Logo区域结束--> <!--导航区域开始--> <div id="navi"> <ul id="menu"> <li><a href="../index.html" class="index_off"></a></li> <li><a href="../role/role_list.html" class="role_off"></a></li> <li><a href="../admin/admin_list.html" class="admin_off"></a></li> <li><a href="../fee/fee_list.html" class="fee_on"></a></li> <li><a href="../account/account_list.html" class="account_off"></a></li> <li><a href="../service/service_list.html" class="service_off"></a></li> <li><a href="../bill/bill_list.html" class="bill_off"></a></li> <li><a href="../report/report_list.html" class="report_off"></a></li> <li><a href="../user/user_info.html" class="information_off"></a></li> <li><a href="../user/user_modi_pwd.html" class="password_off"></a></li> </ul> </div> <!--导航区域结束--> <!--主要区域开始--> <div id="main"> <div id="save_result_info" class="save_success">保存成功!</div> <form action="" method="" class="main_form"> <div class="text_info clearfix"><span>资费ID:</span></div> <div class="input_info"> <s:textfield name="cost.id" cssClass="readonly" readonly="true"/> </div> <div class="text_info clearfix"><span>资费名称:</span></div> <div class="input_info"> <s:textfield name="cost.name" cssClass="width300" /> <span class="required">*</span> <div class="validate_msg_short">50长度的字母、数字、汉字和下划线的组合</div> </div> <div class="text_info clearfix"><span>资费类型:</span></div> <div class="input_info fee_type"> <s:radio name="cost.costType" list="#{'1':'包月','2':'套餐','3':'计时' }" onclick="feeTypeChange(this.value)"/> </div> <div class="text_info clearfix"><span>基本时长:</span></div> <div class="input_info"> <s:textfield name="cost.baseDuration" cssClass="width100"/> <span class="info">小时</span> <span class="required">*</span> <div class="validate_msg_long">1-600之间的整数</div> </div> <div class="text_info clearfix"><span>基本费用:</span></div> <div class="input_info"> <s:textfield name="cost.baseCost" cssClass="width100"/> <span class="info">元</span> <span class="required">*</span> <div class="validate_msg_long">0-99999.99之间的数值</div> </div> <div class="text_info clearfix"><span>单位费用:</span></div> <div class="input_info"> <s:textfield name="cost.unitCost" cssClass="width100"/> <span class="info">元/小时</span> <span class="required">*</span> <div class="validate_msg_long">0-99999.99之间的数值</div> </div> <div class="text_info clearfix"><span>资费说明:</span></div> <div class="input_info_high"> <s:textarea name="cost.descr" cssClass="width300 height70"/> <div class="validate_msg_short">100长度的字母、数字、汉字和下划线的组合</div> </div> <div class="button_info clearfix"> <input type="button" value="保存" class="btn_save" onclick="showResult();" /> <input type="button" value="取消" class="btn_save" /> </div> </form> </div> <!--主要区域结束--> <div id="footer"> <span>[源自北美的技术,最优秀的师资,最真实的企业环境,最适用的实战项目]</span> <br /> <span>版权所有(C)加拿大达内IT培训集团公司 </span> </div> </body> </html>
练习使用简单的UI标签生成框体,并给框体赋默认值,标签包含:
UI标签最核心的功能是用于回显数据,因此往往被使用在修改功能中。为了贴合实际业务,我们模拟修改客户的场景,在修改客户的页面上使用上述标签来回显查询出的客户数据。
由于本案例侧重点在UI标签的使用,因此是模拟修改客户的场景,简化打开修改页面的代码即可,这里我们不需要设计数据库以及查询数据库,仅仅是模拟一份数据即可。
为了保证能够在模拟的场景中使用到每一个UI标签,因此客户实体类中要包含每一类的数据,这样的模拟并不符合真实的业务,而仅仅是为了练习标签做的假设,请同学们注意这一点。
实现此案例需要按照如下步骤进行。
步骤一:创建项目
先创建项目StrutsDay04,然后导入Struts2核心包,接下来在web.xml中配置前端控制器,最后在src下创建struts.xml,即StrutsDay01中的Struts2使用步骤。
步骤二:准备项目
模拟出客户修改的功能,先建包entity,在包下创建客户实体类Customer,代码如下:
package entity; import java.util.List; public class Customer { private String name; // 姓名 private String password; // 密码 private String desc; // 简介 private boolean marry; // 是否已婚 private String sex; // 性别 private List<String> travelCities; // 去过的城市 private String home; // 家乡 public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public boolean isMarry() { return marry; } public void setMarry(boolean marry) { this.marry = marry; } public String getHome() { return home; } public List<String> getTravelCities() { return travelCities; } public void setTravelCities(List<String> travelCities) { this.travelCities = travelCities; } public void setHome(String home) { this.home = home; } }
然后创建客户DAO,并模拟根据id查询客户的方法,代码如下:
package dao; import java.util.ArrayList; import java.util.List; import entity.Customer; /** * 模拟客户DAO */ public class CustomerDAO { /** * 模拟根据ID查询客户 */ public Customer findById() { // 实例化客户实体类 Customer c = new Customer(); // 设置一些默认值 c.setName("Tarena"); c.setPassword("123"); c.setDesc("中华人民共和国公民"); c.setSex("F"); c.setMarry(true); List<String> list = new ArrayList<String>(); list.add("beijing"); list.add("guangzhou"); c.setTravelCities(list); c.setHome("shanghai"); return c; } }
接下来,创建打开修改页面Action类ToUpdateCustomerAction,在此Action中模拟处理打开修改页面,查询客户的请求,代码如下:
package action; import dao.CustomerDAO; import entity.Customer; public class ToUpdateCustomerAction { // output private Customer customer; public String execute() { CustomerDAO dao = new CustomerDAO(); // 模拟查询客户 customer = dao.findById(); return "success"; } public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } }
接下来,在struts.xml中配置打开修改页面action,代码如下:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN" "http://struts.apache.org/dtds/struts-2.1.7.dtd"> <struts> <!-- 客户配置信息 --> <package name="customer" namespace="/customer" extends="struts-default"> <!-- 打开修改页面 --> <action name="toUpdateCustomer" class="action.ToUpdateCustomerAction"> <result name="success"> /WEB-INF/customer/update_customer.jsp </result> </action> </package> </struts>
最后,在WEB-INF下创建customer文件夹,并在此文件夹下创建修改客户的页面update_customer.jsp,该页面简化处理,先输出一句话“模拟修改客户”即可,代码如下:
<%@page pageEncoding="utf-8"%> <%@taglib uri="/struts-tags" prefix="s"%> <html> <head></head> <body> <h1>模拟修改客户</h1> </body> </html>
完成上述模拟修改客户的代码后,项目结构如下图:
图-7
部署项目并启动tomcat,在浏览器中访问修改客户,效果如下图:
图-8
步骤三:表单标签
在update_customer.jsp上,使用表单标签生成form表单,代码如下:
<%@page pageEncoding="utf-8"%> <%@taglib uri="/struts-tags" prefix="s"%> <html> <head></head> <body> <h1>模拟修改客户</h1> #cold_bold <%-- 1.表单标签 --%> #cold_bold <s:form action="#" method="post"> #cold_bold #cold_bold </s:form> </body> </html>
刷新浏览器,修改页面效果如下:
图-9
步骤四:文本框标签
在update_customer.jsp上,使用文本框标签生成文本框,并在框内显示客户名称,代码如下:
<%@page pageEncoding="utf-8"%> <%@taglib uri="/struts-tags" prefix="s"%> <html> <head></head> <body> <h1>模拟修改客户</h1> <%-- 1.表单标签 --%> <s:form action="#" method="post"> #cold_bold <!-- #cold_bold 2.文本框标签 #cold_bold 1)生成文本框 #cold_bold 2)根据OGNL(customer.name)取值给文本框赋值 #cold_bold --> #cold_bold <s:textfield name="customer.name" label="姓名"/> </s:form> </body> </html>
刷新浏览器,修改页面效果如下:
图-10
步骤五:密码框标签
在update_customer.jsp上,使用密码框标签生成密码框,并在框内显示客户密码,代码如下:
<%@page pageEncoding="utf-8"%> <%@taglib uri="/struts-tags" prefix="s"%> <html> <head></head> <body> <h1>模拟修改客户</h1> <%-- 1.表单标签 --%> <s:form action="#" method="post"> <!--此处略去其他标签...--> #cold_bold <!-- #cold_bold 3.密码框标签 #cold_bold 1)生成密码框 #cold_bold 2)根据OGNL(customer.password)取值给密码框赋值 #cold_bold --> #cold_bold <s:password name="customer.password" label="密码" showPassword="true"/> </s:form> </body> </html>
刷新浏览器,修改页面效果如下:
图-11
步骤六:文本域标签
在update_customer.jsp上,使用文本域标签生成文本域,并在框内显示客户简介,代码如下:
<%@page pageEncoding="utf-8"%> <%@taglib uri="/struts-tags" prefix="s"%> <html> <head></head> <body> <h1>模拟修改客户</h1> <%-- 1.表单标签 --%> <s:form action="#" method="post"> <!--此处略去其他标签...--> #cold_bold <!-- #cold_bold 4.文本域标签 #cold_bold 1)生成文本域 #cold_bold 2)根据OGNL(customer.desc)取值给文本域赋值 #cold_bold --> #cold_bold <s:textarea name="customer.desc" cols="30" rows="5" label="简介"/> </s:form> </body> </html>
刷新浏览器,修改页面效果如下:
图-12
步骤七:布尔框标签
在update_customer.jsp上,使用布尔框标签生成选择框,并根据客户是否已婚来决定是否勾选该选择框,代码如下:
<%@page pageEncoding="utf-8"%> <%@taglib uri="/struts-tags" prefix="s"%> <html> <head></head> <body> <h1>模拟修改客户</h1> <%-- 1.表单标签 --%> <s:form action="#" method="post"> <!--此处略去其他标签...--> #cold_bold <!-- #cold_bold 5.布尔标签 #cold_bold 1)生成一个checkbox #cold_bold 2)根据OGNL(customer.marry)取值(布尔型)来确定是否勾选 #cold_bold --> #cold_bold <s:checkbox name="customer.marry" label="是否已婚" labelposition="left"/> </s:form> </body> </html>
刷新浏览器,修改页面效果如下:
图-13
本案例的完整代码如下。
Customer完整代码:
package entity; import java.util.List; public class Customer { private String name; // 姓名 private String password; // 密码 private String desc; // 简介 private boolean marry; // 是否已婚 private String sex; // 性别 private List<String> travelCities; // 去过的城市 private String home; // 家乡 public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public boolean isMarry() { return marry; } public void setMarry(boolean marry) { this.marry = marry; } public String getHome() { return home; } public List<String> getTravelCities() { return travelCities; } public void setTravelCities(List<String> travelCities) { this.travelCities = travelCities; } public void setHome(String home) { this.home = home; } }
CustomerDAO完整代码:
package dao; import java.util.ArrayList; import java.util.List; import entity.Customer; /** * 模拟客户DAO */ public class CustomerDAO { /** * 模拟根据ID查询客户 */ public Customer findById() { // 实例化客户实体类 Customer c = new Customer(); // 设置一些默认值 c.setName("Tarena"); c.setPassword("123"); c.setDesc("中华人民共和国公民"); c.setSex("F"); c.setMarry(true); List<String> list = new ArrayList<String>(); list.add("beijing"); list.add("guangzhou"); c.setTravelCities(list); c.setHome("shanghai"); return c; } }
ToUpdateCustomerAction完整代码:
package action; import dao.CustomerDAO; import entity.Customer; public class ToUpdateCustomerAction { // output private Customer customer; public String execute() { CustomerDAO dao = new CustomerDAO(); // 模拟查询客户 customer = dao.findById(); return "success"; } public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } }
struts.xml完整代码:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN" "http://struts.apache.org/dtds/struts-2.1.7.dtd"> <struts> <!-- 客户配置信息 --> <package name="customer" namespace="/customer" extends="struts-default"> <!-- 打开修改页面 --> <action name="toUpdateCustomer" class="action.ToUpdateCustomerAction"> <result name="success"> /WEB-INF/customer/update_customer.jsp </result> </action> </package> </struts>
update_customer.jsp完整代码:
<%@page pageEncoding="utf-8"%> <%@taglib uri="/struts-tags" prefix="s"%> <html> <head></head> <body> <h1>模拟修改客户</h1> <%-- 1.表单标签 --%> <s:form action="#" method="post"> <!-- 2.文本框标签 1)生成文本框 2)根据OGNL(customer.name)取值给文本框赋值 --> <s:textfield name="customer.name" label="姓名"/> <!-- 3.密码框标签 1)生成密码框 2)根据OGNL(customer.password)取值给密码框赋值 --> <s:password name="customer.password" label="密码" showPassword="true"/> <!-- 4.文本域标签 1)生成文本域 2)根据OGNL(customer.desc)取值给文本域赋值 --> <s:textarea name="customer.desc" cols="30" rows="5" label="简介"/> <!-- 5.布尔标签 1)生成一个checkbox 2)根据OGNL(customer.marry)取值(布尔型)来确定是否勾选 --> <s:checkbox name="customer.marry" label="是否已婚" labelposition="left"/> </s:form> </body> </html>
练习使用简单的UI标签生成框体,并给框体赋默认值,标签包含:
在StrutsDay04案例的模拟修改客户功能基础上,模拟数据,练习使用这3类标签。
实现此案例需要按照如下步骤进行。
步骤一:单选框标签
单选框有2种用法,根据其初始化radio方式的不同,可以分为静态和动态2种方式。首先我们使用静态方式来初始化客户性别选项,并根据客户数据勾选客户性别,需要在update_customer.jsp上使用单选框标签来实现。代码如下:
<%@page pageEncoding="utf-8"%> <%@taglib uri="/struts-tags" prefix="s"%> <html> <head></head> <body> <h1>模拟修改客户</h1> <%-- 1.表单标签 --%> <s:form action="#" method="post"> <!--此处略去其他标签...--> #cold_bold <!-- #cold_bold 6.1单选框标签(静态) #cold_bold 1)根据OGNL(list属性值)创建的Map生成一组radio, #cold_bold 其中Map的可以生成radio的value值,Map的value生成radio的label值。 #cold_bold 2)根据OGNL(customer.marry)取值来与生成radio的value比较, #cold_bold 若与哪个radio的value值一致,则将其勾选。 #cold_bold --> #cold_bold <s:radio name="customer.sex" list="#{'M':'男','F':'女' }" label="性别"/> </s:form> </body> </html>
刷新浏览器,修改页面效果如下:
图-14
静态方式初始化radio时是通过静态代码创建Map来实现的,很多时候这些选项不是固定的,是需要查询数据库得到的,即需要通过动态的方式来进行初始化选项,那么需要采用动态方式来实现。
要实现动态初始化选项,先要创建选项实体类,来封装选项信息,因此这里我们要创建性别的实体类Sex,当然就这个场景而言并不合理,仅是出于练习的目的,大家了解这种用法即可。代码如下:
package entity; public class Sex { private String code; private String name; public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
然后在CustomerDAO中追加查询全部性别的方法,这个方法是模拟的方法,并且不符合真实的业务场景,仅用于练习知识点。代码如下:
package dao; import java.util.ArrayList; import java.util.List; import entity.Customer; import entity.Sex; /** * 模拟客户DAO */ public class CustomerDAO { //此处略去其他方法 ... #cold_bold /** #cold_bold * 模拟查询所有的性别,并不符合真实业务,仅仅是用于练习知识点 #cold_bold */ #cold_bold public List<Sex> findAllSex() { #cold_bold List<Sex> list = new ArrayList<Sex>(); #cold_bold #cold_bold Sex s1 = new Sex(); #cold_bold s1.setCode("M"); #cold_bold s1.setName("男"); #cold_bold list.add(s1); #cold_bold #cold_bold Sex s2 = new Sex(); #cold_bold s2.setCode("F"); #cold_bold s2.setName("女"); #cold_bold list.add(s2); #cold_bold #cold_bold Sex s3 = new Sex(); #cold_bold s3.setCode("O"); #cold_bold s3.setName("其他"); #cold_bold list.add(s3); #cold_bold #cold_bold return list; #cold_bold } }
然后在ToUpdateCustomerAction中模拟查询所有的性别,代码如下:
package action; import java.util.List; import dao.CustomerDAO; import entity.Customer; import entity.Sex; public class ToUpdateCustomerAction { // output private Customer customer; // 客户 #cold_bold private List<Sex> sexes; // 性别 public String execute() { CustomerDAO dao = new CustomerDAO(); // 模拟查询客户 customer = dao.findById(); #cold_bold // 模拟查询全部的性别 #cold_bold sexes = dao.findAllSex(); return "success"; } public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } #cold_bold public List<Sex> getSexes() { #cold_bold return sexes; #cold_bold } #cold_bold #cold_bold public void setSexes(List<Sex> sexes) { #cold_bold this.sexes = sexes; #cold_bold } }
最后,在update_customer.jsp上,使用动态的单选框标签,根据Action中返回的所有性别生成性别选项,并根据客户信息设置默认勾选,代码如下:
<%@page pageEncoding="utf-8"%> <%@taglib uri="/struts-tags" prefix="s"%> <html> <head></head> <body> <h1>模拟修改客户</h1> <%-- 1.表单标签 --%> <s:form action="#" method="post"> <!--此处略去其他标签...--> #cold_bold <!-- #cold_bold 6.2单选框标签(动态) #cold_bold 1)根据OGNL(list属性值)的取值初始化一组radio, #cold_bold 并根据listKey指定的实体类中的属性来生成radio的value值, #cold_bold 根据listValue指定的实体类中的属性来生成radio的label值。 #cold_bold 2)根据OGNL(customer.marry)取值来与生成radio的value比较, #cold_bold 若与哪个radio的value值一致,则将其勾选。 #cold_bold --> <s:radio name="customer.sex" list="sexes" listKey="code" listValue="name" label="性别"/> </s:form> </body> </html>
重新部署项目并重启tomcat,重新访问修改客户,效果如下图:
图-15
步骤二:多选框标签
多选框的用法与单选框用法类似,也分为静态初始化和动态初始化2种,区别在于对checkbox初始化方式的不同。
首先,我们通过静态初始化的方式生成一组城市的复选框,然后根据客户去过的城市来勾选这些城市。代码如下:
<%@page pageEncoding="utf-8"%> <%@taglib uri="/struts-tags" prefix="s"%> <html> <head></head> <body> <h1>模拟修改客户</h1> <%-- 1.表单标签 --%> <s:form action="#" method="post"> <!--此处略去其他标签...--> #cold_bold <!-- #cold_bold 7.1多选框标签(静态) #cold_bold 1)根据OGNL(list属性值)创建的Map生成一组checkbox,其中Map的key #cold_bold 生成checkbox的value值,Map的value生成checkbox的label值。 #cold_bold 2)根据OGNL(customer.travelCities)取值来与生成checkbox的 #cold_bold value比较,若与哪个checkbox的value值一致,则将其勾选。 #cold_bold --> #cold_bold <s:checkboxlistname="customer.travelCities" #cold_bold list="#{'beijing':'北京','shanghai':'上海','guangzhou':'广州','shenzhen':'深圳','chongqing':'重庆','diaoyudao':'钓鱼岛' }" label="旅游过的城市"/> </s:form> </body> </html>
刷新浏览器,效果如下图:
图-16
接下来,我们在看看如何动态的初始化多选框的选项。先创建城市的实体类City,用于封装所有的城市数据,代码如下:
package entity; public class City { private String code; private String name; public City(String code, String name) { super(); this.code = code; this.name = name; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
然后在CustomerDAO中模拟查询全部的城市,代码如下:
package dao; import java.util.ArrayList; import java.util.List; import entity.City; import entity.Customer; import entity.Sex; /** * 模拟客户DAO */ public class CustomerDAO { // 此处略去其他方法... #cold_bold /** #cold_bold * 模拟查询所有的城市 #cold_bold */ #cold_bold public List<City> findAllCities() { #cold_bold List<City> cities = new ArrayList<City>(); #cold_bold City c1 = new City("beijing", "北京"); #cold_bold City c2 = new City("shanghai", "上海"); #cold_bold City c3 = new City("guangzhou", "广州"); #cold_bold City c4 = new City("shenzhen", "深圳"); #cold_bold City c5 = new City("chongqing", "重庆"); #cold_bold City c6 = new City("diaoyudao", "钓鱼岛"); #cold_bold cities.add(c1); #cold_bold cities.add(c2); #cold_bold cities.add(c3); #cold_bold cities.add(c4); #cold_bold cities.add(c5); #cold_bold cities.add(c6); #cold_bold return cities; #cold_bold } }
然后在ToUpdateCustomerAction中查询出全部的城市,代码如下:
package action; import java.util.List; import dao.CustomerDAO; import entity.City; import entity.Customer; import entity.Sex; public class ToUpdateCustomerAction { // output private Customer customer; // 客户 private List<Sex> sexes; // 性别 #cold_bold private List<City> cities; // 城市 public String execute() { CustomerDAO dao = new CustomerDAO(); // 模拟查询客户 customer = dao.findById(); // 模拟查询全部的性别 sexes = dao.findAllSex(); #cold_bold // 模拟查询全部的城市 #cold_bold cities = dao.findAllCities(); return "success"; } public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } public List<Sex> getSexes() { return sexes; } public void setSexes(List<Sex> sexes) { this.sexes = sexes; } #cold_bold public List<City> getCities() { #cold_bold return cities; #cold_bold } #cold_bold #cold_bold public void setCities(List<City> cities) { #cold_bold this.cities = cities; #cold_bold } }
最后,在update_customer.jsp上,使用动态的多选框标签,根据Action中返回的所有城市生成城市选项,并根据客户信息设置默认勾选,代码如下:
<%@page pageEncoding="utf-8"%> <%@taglib uri="/struts-tags" prefix="s"%> <html> <head></head> <body> <h1>模拟修改客户</h1> <%-- 1.表单标签 --%> <s:form action="#" method="post"> <!--此处略去其他标签...--> #cold_bold <!-- #cold_bold 7.2多选框标签(动态) #cold_bold 1)根据OGNL(list属性值)的取值初始化一组checkbox, #cold_bold 并根据listKey指定的实体类中的属性来生成checkbox的value值, #cold_bold 根据listValue指定的实体类中的属性来生成checkbox的label值。 #cold_bold 2)根据OGNL(customer.travelCities)取值来与生成radio的value比较, #cold_bold 若与哪个radio的value值一致,则将其勾选。 #cold_bold --> #cold_bold <s:checkboxlist name="customer.travelCities" list="cities" listKey="code" listValue="name" label="旅游过的城市"/> </s:form> </body> </html>
重新部署项目并重启tomcat,重新访问修改客户页面,效果如下图:
图-17
步骤三:下拉选标签
下拉选标签的用法与单选框标签、多选框标签也类似,分为静态初始化和动态初始化2种方式。首先我们来使用静态的方式来初始化下拉选选项,代码如下:
<%@page pageEncoding="utf-8"%> <%@taglib uri="/struts-tags" prefix="s"%> <html> <head></head> <body> <h1>模拟修改客户</h1> <%-- 1.表单标签 --%> <s:form action="#" method="post"> <!--此处略去其他标签...--> #cold_bold <!-- #cold_bold 8.1下拉选标签(静态) #cold_bold 1)根据OGNL(list属性值)创建的Map生成一组option,其中Map的key #cold_bold 生成option的value值,Map的value生成option的显示值。 #cold_bold 2)根据OGNL(customer.home)取值来与生成option的 #cold_bold value比较,若与哪个option的value值一致,则将其勾选。 #cold_bold --> #cold_bold <s:select name="customer.home" #cold_bold list="#{'beijing':'北京','shanghai':'上海','guangzhou':'广州','shenzhen':'深圳','chongqing':'重庆','diaoyudao':'钓鱼岛' }" #cold_bold label="家乡" headerKey="-1" headerValue="请选择"/> </s:form> </body> </html>
刷新浏览器,显示效果如下图:
图-18
对于动态的初始化的方式,我们还是使用全部的城市来初始化选项,代码如下:
<%@page pageEncoding="utf-8"%> <%@taglib uri="/struts-tags" prefix="s"%> <html> <head></head> <body> <h1>模拟修改客户</h1> <%-- 1.表单标签 --%> <s:form action="#" method="post"> <!--此处略去其他标签...--> #cold_bold <!-- #cold_bold 8.2下拉选标签(动态) #cold_bold 1)根据OGNL(list属性值)的取值初始化一组option, #cold_bold 并根据listKey指定的实体类中的属性来生成option的value值, #cold_bold 根据listValue指定的实体类中的属性来生成option的label值。 #cold_bold 2)根据OGNL(customer.home)取值来与生成option的value比较, #cold_bold 若与哪个option的value值一致,则将其勾选。 #cold_bold --> #cold_bold <s:select name="customer.home" list="cities" listKey="code" listValue="name" #cold_bold label="家乡" headerKey="" headerValue="请选择"/> </s:form> </body> </html>
刷新浏览器,显示效果如下图:
图-19
本案例的完整代码如下。
Customer完整代码:
package entity; import java.util.List; public class Customer { private String name; // 姓名 private String password; // 密码 private String desc; // 简介 private boolean marry; // 是否已婚 private String sex; // 性别 private List<String> travelCities; // 去过的城市 private String home; // 家乡 public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public boolean isMarry() { return marry; } public void setMarry(boolean marry) { this.marry = marry; } public String getHome() { return home; } public List<String> getTravelCities() { return travelCities; } public void setTravelCities(List<String> travelCities) { this.travelCities = travelCities; } public void setHome(String home) { this.home = home; } }
Sex完整代码:
package entity; public class Sex { private String code; private String name; public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
City完整代码:
package entity; public class City { private String code; private String name; public City(String code, String name) { super(); this.code = code; this.name = name; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
CustomerDAO完整代码:
package dao; import java.util.ArrayList; import java.util.List; import entity.City; import entity.Customer; import entity.Sex; /** * 模拟客户DAO */ public class CustomerDAO { /** * 模拟根据ID查询客户 */ public Customer findById() { // 实例化客户实体类 Customer c = new Customer(); // 设置一些默认值 c.setName("Tarena"); c.setPassword("123"); c.setDesc("中华人民共和国公民"); c.setSex("F"); c.setMarry(true); List<String> list = new ArrayList<String>(); list.add("beijing"); list.add("guangzhou"); c.setTravelCities(list); c.setHome("shanghai"); return c; } /** * 模拟查询所有的性别,并不符合真实业务,仅仅是用于练习知识点 */ public List<Sex> findAllSex() { List<Sex> list = new ArrayList<Sex>(); Sex s1 = new Sex(); s1.setCode("M"); s1.setName("男"); list.add(s1); Sex s2 = new Sex(); s2.setCode("F"); s2.setName("女"); list.add(s2); Sex s3 = new Sex(); s3.setCode("O"); s3.setName("其他"); list.add(s3); return list; } /** * 模拟查询所有的城市 */ public List<City> findAllCities() { List<City> cities = new ArrayList<City>(); City c1 = new City("beijing", "北京"); City c2 = new City("shanghai", "上海"); City c3 = new City("guangzhou", "广州"); City c4 = new City("shenzhen", "深圳"); City c5 = new City("chongqing", "重庆"); City c6 = new City("diaoyudao", "钓鱼岛"); cities.add(c1); cities.add(c2); cities.add(c3); cities.add(c4); cities.add(c5); cities.add(c6); return cities; } }
ToUpdateCustomerAction完整代码:
package action; import java.util.List; import dao.CustomerDAO; import entity.City; import entity.Customer; import entity.Sex; public class ToUpdateCustomerAction { // output private Customer customer; // 客户 private List<Sex> sexes; // 性别 private List<City> cities; // 城市 public String execute() { CustomerDAO dao = new CustomerDAO(); // 模拟查询客户 customer = dao.findById(); // 模拟查询全部的性别 sexes = dao.findAllSex(); // 模拟查询全部的城市 cities = dao.findAllCities(); return "success"; } public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } public List<Sex> getSexes() { return sexes; } public void setSexes(List<Sex> sexes) { this.sexes = sexes; } public List<City> getCities() { return cities; } public void setCities(List<City> cities) { this.cities = cities; } }
struts.xml完整代码:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN" "http://struts.apache.org/dtds/struts-2.1.7.dtd"> <struts> <!-- 客户配置信息 --> <package name="customer" namespace="/customer" extends="struts-default"> <!-- 打开修改页面 --> <action name="toUpdateCustomer" class="action.ToUpdateCustomerAction"> <result name="success"> /WEB-INF/customer/update_customer.jsp </result> </action> </package> </struts>
update_customer.jsp完整代码:
<%@page pageEncoding="utf-8"%> <%@taglib uri="/struts-tags" prefix="s"%> <html> <head></head> <body> <h1>模拟修改客户</h1> <%-- 1.表单标签 --%> <s:form action="#" method="post"> <!-- 2.文本框标签 1)生成文本框 2)根据OGNL(customer.name)取值给文本框赋值 --> <s:textfield name="customer.name" label="姓名"/> <!-- 3.密码框标签 1)生成密码框 2)根据OGNL(customer.password)取值给密码框赋值 --> <s:password name="customer.password" label="密码" showPassword="true"/> <!-- 4.文本域标签 1)生成文本域 2)根据OGNL(customer.desc)取值给文本域赋值 --> <s:textarea name="customer.desc" cols="30" rows="5" label="简介"/> <!-- 5.布尔框标签 1)生成一个checkbox 2)根据OGNL(customer.marry)取值(布尔型)来确定是否勾选 --> <s:checkbox name="customer.marry" label="是否已婚" labelposition="left"/> <!-- 6.1单选框标签(静态) 1)根据OGNL(list属性值)创建的Map生成一组radio, 其中Map的可以生成radio的value值,Map的value生成radio的label值。 2)根据OGNL(customer.marry)取值来与生成radio的value比较, 若与哪个radio的value值一致,则将其勾选。 --> <s:radio name="customer.sex" list="#{'M':'男','F':'女' }" label="性别"/> <!-- 6.2单选框标签(动态) 1)根据OGNL(list属性值)的取值初始化一组radio, 并根据listKey指定的实体类中的属性来生成radio的value值, 根据listValue指定的实体类中的属性来生成radio的label值。 2)根据OGNL(customer.marry)取值来与生成radio的value比较, 若与哪个radio的value值一致,则将其勾选。 --> <s:radio name="customer.sex" list="sexes" listKey="code" listValue="name" label="性别"/> <!-- 7.1多选框标签(静态) 1)根据OGNL(list属性值)创建的Map生成一组checkbox,其中Map的key 生成checkbox的value值,Map的value生成checkbox的label值。 2)根据OGNL(customer.travelCities)取值来与生成checkbox的 value比较,若与哪个checkbox的value值一致,则将其勾选。 --> <s:checkboxlist name="customer.travelCities" list="#{'beijing':'北京','shanghai':'上海','guangzhou':'广州','shenzhen':'深圳','chongqing':'重庆','diaoyudao':'钓鱼岛' }" label="旅游过的城市"/> <!-- 7.2多选框标签(动态) 1)根据OGNL(list属性值)的取值初始化一组checkbox, 并根据listKey指定的实体类中的属性来生成checkbox的value值, 根据listValue指定的实体类中的属性来生成checkbox的label值。 2)根据OGNL(customer.travelCities)取值来与生成radio的value比较, 若与哪个radio的value值一致,则将其勾选。 --> <s:checkboxlist name="customer.travelCities" list="cities" listKey="code" listValue="name" label="旅游过的城市"/> <!-- 8.1下拉选标签(静态) 1)根据OGNL(list属性值)创建的Map生成一组option,其中Map的key 生成option的value值,Map的value生成option的显示值。 2)根据OGNL(customer.home)取值来与生成option的 value比较,若与哪个option的value值一致,则将其勾选。 --> <s:select name="customer.home" list="#{'beijing':'北京','shanghai':'上海','guangzhou':'广州','shenzhen':'深圳','chongqing':'重庆','diaoyudao':'钓鱼岛' }" label="家乡" headerKey="-1" headerValue="请选择"/> <!-- 8.2下拉选标签(动态) 1)根据OGNL(list属性值)的取值初始化一组option, 并根据listKey指定的实体类中的属性来生成option的value值, 根据listValue指定的实体类中的属性来生成option的label值。 2)根据OGNL(customer.home)取值来与生成option的value比较, 若与哪个option的value值一致,则将其勾选。 --> <s:select name="customer.home" list="cities" listKey="code" listValue="name" label="家乡" headerKey="" headerValue="请选择"/> </s:form> </body> </html>