使用Logic标签库 1)Logic标签库主要用于完成基本的流程控制,如循环,选择等.在jsp面面输出中,logic标签库 是使用最频繁的,也是相对比较复杂的标签库 2)要使用Logic标签库必须要加入标签库的声明 <%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %> 3)logic标签库中的提供的大多数功能完全可以用jstl来替代。一般在logic标签库用得最多的标签 就是<logic:iterator>标签 <logic:equal>用于比较两个值是否相等 A:格式:<logic:equal name="在四种范围内的变量的值" value="用于比较的值" > <% String uid="chen"; request.setAttribute("uid",uid); %> <logic:equal name="uid" value="chen"> //用于比较 相等 </logic:equal> B:比较javabean的属性值 <% worker d=new worker(); d.setId("W1"); request.setAttribute("uid",d); %> <logic:equal name="uid" property="id" value="W1" > equal </logic:equal> 表示把request范围内的uid的JavaBean的属性值与W1进行比较 其它的用于比较的标签,用法与<logic:equal>一样 A:<logic:greaterEqual>大于或等于 B:<logic:greaterThan>大于 C:<logic:lessEqual>小于或等于 D:<logic:lessThan>小于 应用举例: 1)让用户输入一个职工的编号从数据库查找出对应的部门,如果该部门是销售部 则显示是销售部,否则显示不是销售部 思路:input.jsp--->Action--->调用JavaBean进行计算得出部门--->转到show.jsp 页面进行判断(比较的过程在show.jsp,得出结果在Action中) 2)我们完全可以使用jstl标签。 <c:choose> <c:when test="${depart=='销售部'}"> <h1>is sales</h1> </c:when> <c:otherwise> <h1>not is</h1> </c:otherwise> </c:choose> <logic:iterator>标签.相当于jstl中的<c:forEatch> 1)用于循环输出数据项 2)格式: <logic:iterator id="存入page范围内变量" name="从四种范围变量中取出的集合名"> ${} </logic:iterator> 3)原理:每次从name指定的集合中检索出一个元素,然后把它放在page范围内 并以id属性指定的名字来命名这个元素 ========================================================== <% ArrayList list=new ArrayList(); list.add("chen"); list.add("yuan"); list.add("haung"); request.setAttribute("list",list); %> <logic:iterate id="workerName" name="list"> <bean:write name="workerName"/><br> </logic:iterate> ================================================================ 3)把JavaBean集合进行输出 <% ArrayList users=new ArrayList(); users.add(new Person("tomcat",12)); users.add(new Person("Mysql",120)); users.add(new Person("oracle",16)); request.setAttribute("users",users) %> <logic:iterate id="user" name="users"> <bean:write name="user" property="name"/><br>相当于${user.name} <bean:write name="user" property="age"/><br> 相当于${user.age} </logic:iterate> <c:set var="orderList" value="<%=orderDao.getAllOrder()%>" scope="request"/> 4)<logic:iterate>还可以访问map中的元素 <% Map personMap=new HashMap(); personMap.put("W1","张三"); personMap.put("W2","李四"); personMap.put("W3","王五"); personMap.put("W4","赵六"); %> <c:set var="personMap" value="<%=personMap %>"/> <logic:iterate id="person" name="personMap"> <bean:write name="person" property="key"/> 相当于${person.key} <bean:write name="person" property="value"/>相当于${person.value} </logic:iterate> 5)设置被访问的变量: A:设置name属性,name属性指定要遍历的集合或map, B:设置name属性和property属性,name属性指定一个javaBean,property属性指定java的 一个属性,这个属性做为遍历的集合或map.比如: <% String love[]={"dance","jump","read"}; person personInstance=new person("p1","zhang",love); request.setAttribute("personInstance",personInstance); %> <logic:iterate id="elementLove" name="personInstance" property="love"> ${elementLove } </logic:iterate> 改为: <% ArrayList persons=new ArrayList(); person personInstance1=new person("p1","zhang",new String[] {"dance1","jump1","read1"}); person personInstance2=new person("p1","zhang",new String[] {"dance2","jump2","read2"}); person personInstance3=new person("p1","zhang",new String[] {"dance3","jump3","read3"}); persons.add(personInstance1); persons.add(personInstance2); persons.add(personInstance3); request.setAttribute("persons",persons); %> <logic:iterate id="elementPerson" name="persons"> <br>=========${elementPerson.id} ${elementPerson.name}======<br> <logic:iterate id="elementLove" name="elementPerson" property="love"> ${elementLove } </logic:iterate> </logic:iterate> 举例: 1)从数据库中查询结果用<logic:iterate>标签进行输出(注意indexId的使用 <logic:iterate id="empList" name="emps" indexId="index"> <c:choose> <c:when test="${index%2==0}"> <tr align="center" bgcolor="#FFFFFF"> </c:when> <c:otherwise> <tr align="center" bgcolor="yellow"> </c:otherwise> </c:choose> <td><bean:write name="empList" property="id"/></td> <td><bean:write name="empList" property="name"/></td> <td><bean:write name="empList" property="job"/></td> </tr> </logic:iterate> 2)定义一个部门类,里面有一个属性为该部门的员工集合,输出部门信息与该部门员 工信息,depts里面包含多个dept,一个dept里面包含多个emp 以分组报表有形式进行输出 =====================================dept部门类===================================== public class dept { private String id; private String name; public ArrayList getEmps() //说明对于"只读属性"可以直接写get方法,没有必要 //定义私有变量,也就是说该javaBean自动会有emps属性 { ArrayList empsList=new ArrayList(); String sql="select empno,ename from emp where deptno="+this.id; ResultSet rs=db.runSql(sql); while(rs.next()) { emp empInstance=new emp(rs.getString(1),rs.getString(2)); empsList.add(empInstance); } return empsList; } ................... } =====================================depts所有部门类================================ public static ArrayList queryAll() { ArrayList deptsList=new ArrayList(); String sql="select deptno,dname from dept"; ResultSet rs=db.runSql(sql); while(rs.next()) { dept deptInstance=new dept(); deptInstance.setId(rs.getString(1)); deptInstance.setName(rs.getString(2)); deptsList.add(deptInstance); } return deptsList; } 3)通过订单表查看订单明细表.可以定义一个类得到所有订单,定义一个订单类,里面有 多个订单明细类,定义订单明细类。(在定义订单类中通过超链接显示所有订单明细表) 2)实现分页(创建一个用于分页的类,使用单例模式) =====================================分页类============================================ public class emps { private int currentPage=1; private final int pageSize=4; private static emps demo=null; private emps() { } public static emps newInstance() { if (demo==null) { demo=new emps(); } return demo; } public List getCurrentPageList() { List list=new ArrayList(); String sql=String.format("select * from (select * from emp where empno not in (select empno from emp where rownum<=(%d-1)*%d)) where rownum<=% d", this.currentPage,this.pageSize,pageSize); ResultSet rs=dbManager.RunHasResultSql(sql); while(rs.next()) { emp empInstance=new emp(); empInstance.setId(rs.getString(1)); empInstance.setName(rs.getString(2)); empInstance.setJob(rs.getString(3)); list.add(empInstance); } return list; } public int getCurrentPage() { return this.currentPage; } public void setCurrentPage(int currentPage) { switch(currentPage) { case 0://表示首页 this.currentPage=1; break; case 1://表示上一页 if (this.currentPage>1) { this.currentPage--; } break; case 2: //表示下一页 if (this.currentPage<this.getTotalPage()) { this.currentPage++; } break; case 3: //表示末页 this.currentPage=this.getTotalPage(); System.out.print(this.getTotalPage()); break; } } public int getTotalPage() { int rowCount=0,totalPages=0; String sql="select count(*) from emp"; ResultSet rs=dbManager.RunHasResultSql(sql); if (rs.next()) { rowCount=rs.getInt(1); } if (rowCount%this.pageSize==0) { totalPages=rowCount/this.pageSize; } else { totalPages=rowCount/this.pageSize+1; } return totalPages; } public int getPageSize() { return pageSize; }=============================================jsp页面========================================== <logic:notPresent name="emps"> <c:set var="emps" value="<%=emps.newInstance().getCurrentPageList()%>" scope="request"/> </logic:notPresent> //注意使用<c:set>标签 <logic:iterate id="empList" name="emps" indexId="index">============================================================================================= <logic:Present>判断四种范围内的变量是否不存在 格式: <logic:Present name="要判断的四种范围内的变量名"> 做一些事件 </logic:Present> <logic:redirect/>重定向 格式:<logic:redirect href="要重定向的页面"/> 相当于 response.sendRedirect(),会丢失请求中的数据 <logic:forward/>转发请求 格式:<logic:forward name="msg"/> 说明: 1)name必须是在struts-config.xml文件中定义的全局forward 2)<jsp:forward page="msg.jsp">也相当于转发,但它没有全局forward的限制 第五章 struts动态ActionForm,struts数据校检,stuts中的Token(令牌) struts动态ActionForm 1)什么是动态ActionForm 动态ActionForm是struts从1.1版本开始引入一项新的技术,即在创建ActionForm时 可以不用通过编程的方式而只要通过struts-config.xml文件中进行配置,以后在 struts运行时,会自动根据struts-config.xml中配置的DynaActionform来生成一个 Action实例 2)为什么要使用DynaActionform 很显然随着应用程序的变大,数百个ActionForm 这样不仅编程起来麻烦,以后维护 起来也麻烦,比如:某个属性变化了,则需要修改源代码,然后重新编译,但是如果 使用DynaActionform则只需要修改struts-config.xml配置文件就行了。这样提高了 应用程序的开发效率与应用程序的可维护性 3)如何使用DynaActionform 1)在struts-config.xml中创建一个DynaActionform <form-beans > <form-bean name="dynaActionForm" type="org.apache.struts.action.DynaActionForm"> <form-property name="num1" type="java.lang.String"/> <form-property name="num2" type="java.lang.String"/> </form-bean> </form-beans> 2)从上面的配置可以看出,动态ActionForm的配置必须增加forms-property元素 且每个forms-property包含两个属性 A:name 属性的名字,该属性必须与jsp页面的表单元素的名字一致 B:type 属性的类型。强烈建议把类型都设置为String,以后在Action中再去转换 C:类型不能直接写String一定要写上java.lang.String D:动态ActionForm的type必须要写org.apache.struts.action.DynaActionForm 它是struts中内置的一个用于创建动态ActionForm的一个父类 3)如何使用DynaActionForm 在与之对应的Action中的Excute中写上代码,然后通过其get方法就行了 DynaActionForm frm=(DynaActionForm)form; //取出动态ActionForm frm.get("在struts-config.xml为动态Action配置的属性名"); 比如: int num1=Integer.parseInt(frm.get("num1").toString()); String userName=frm.get("userName").toString(); double price=Double.parseDouble(frm.get("price").toString()); 4)通过"initial"给DynaActionForm增加默认值: <form-bean name="dynaActionForm" type="org.apache.struts.action.DynaActionForm"> <form-property initial="1" name="num1" type="java.lang.String"/> <form-property initial="2" name="num2" type="java.lang.String"/> </form-bean> 5)如何在DynaActionForm中配合checkBox使用数组属性: A:配置: <form-bean name="dynaActionForm" type="org.apache.struts.action.DynaActionForm"> <form-property name="love" type="java.lang.String[]"/>在String后面加上"[]" </form-bean> B:使用: DynaActionForm frm=(DynaActionForm)form; String love[]=frm.getStrings("love");//通过getStrings方法会返回一个数组 6)什么时候用动态ActionForm。实事上配置动态ActionForm的工作量与通过MyEclipse去生 成一个ActionForm的工作量相当。所以如果一个表单中只有一到两个元素需要传值则考虑 DynaActionForm,但是如果超过两个以上时,建议还是使用ActionForm 举例: 1)使用动态ActionForm来求出让用户输入两个数与一个操作符来求出运算结果 注意在同一个页面中显示结果,注意操作符使用单选按钮,并提供默认值. 2)使用动态ActionForm实现商品的添加功能。注意使用oracle中触发器与sequences 实现自动编号功能 CREATE TABLE table1 (id NUMBER PRIMARY KEY, username VARCHAR2(50) ); --建序列 CREATE SEQUENCE table1_seq START WITH 1 INCREMENT BY 1 --建触発器 CREATE OR REPLACE TRIGGER table1_tg BEFORE INSERT ON table1 FOR EACH ROW BEGIN SELECT table1_seq.NEXTVAL INTO :NEW.id FROM DUAL; END; --執行 INSERT INTO table1 (username) VALUES ('張三'); 3)使用dynaActionForm配合checkbox实现让用户选择商品类型,查询出对应的 商品,然后用户选择商品,求出应付款 struts数据校检 1)struts数据的检验分成客户端检验与服务器检验。客户端检验是避免用户输入非法的的数据 而服务器端检验通常是把用户输入的正确数据与数据库的数据进行对比,然后依然业务逻辑 进行检验 2)如果要进行服务器商检验可以在Action中进行,如果要进行客户端检验则可以利用 js或struts中的commons-validator的检验框架进行检验 通过stuts中的Token(令牌)阻止页面重复提交 1)原理: 当客户端每次请求一个页面之前,服务器端会产生一个令牌,同时把这个令牌传给客户端 之后再进行处理。处理完毕之后,马上更新旧的令牌,同时传送旧的令牌给客户端。 这样如果客户端提交表单一次之后,按IE上的后退按钮再次提交时,就会发出客户端的 令牌(因为是以前的令牌)与现在服务器的令牌不一致。通过这个就能判断是否重复提交 表单 2)步骤: 1.jsp页面放一个超链接.<a href="prepareAction.do">发表留言</a> 2)点击超链接之后跳转到prepareAction,在prepareAction里面去添加一个令牌 public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { this.saveToken(request); return mapping.findForward("2");//跳到2.jsp页面 } prepareAction实际上过度作用的一个Action目的是为了添加令牌 3)在2.jsp里面一般是一个表单用来填写数据,并提交到另外一个insertTalkAction里面 实现真正的插入 <html:form action="insertTalkAction.do"> 留言id<html:text property="uid"/><br> 内容<html:text property="content"/><br> <html:submit>提交</html:submit> </html:form> 4)在insertTalkAction里面的代码是关键代码 ====================================================================================== public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { if (this.isTokenValid(request,true)) //没有重复提交 { Random rnd=new Random(); int n=rnd.nextInt(2000)+900; request.setAttribute("msg", "没有重复提交,将插入数据.."); String sql=String.format("insert into emp(empno,ename) values(%d,'小上')", n); dbManager.RunNoneResultSql(sql); } else //重复提交了 { request.setAttribute("msg", "重复提交!!!!"); this.saveToken(request); } return mapping.findForward("msg"); } ==================================一般的格式=============================================== if (isTokenValid(request, true)) //表单不是重复提交 { 这里是保存数据的代码 } else //表单重复提交 { saveToken(request); 其它的处理代码 } ============================================================================================= 让dw支持struts 1)正常情况下,在dw中不存在,也不会显示struts标签 2)可以下载一个插件,让dw能够编辑并显示struts标签。 3)配置步骤如下: 1)下载插件:ast-03.mxp 2)直接双击打开,此时dw会自动用扩展管理器打开,按照提示安装即可 3)导入struts的标签库。 编辑-->标签库-->添加-->jsp-->从文件中导入tld-->选择struts-html.tld与 struts-logic.tld等标签库 4)新建一个jsp页面。在里面直接键入<html:link>会看到语法提示 5)但是dw没有属性可以修改,要修改属性必须通过代码进行修改

评论