首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

《研磨struts2》第十二章 CRUD综合应用 之 12.3 使用Struts2来实现表现层

2012-08-13 
《研磨struts2》第十二章 CRUD综合运用 之 12.3 使用Struts2来实现表现层2.3??使用Struts2来实现表现层12.3.

《研磨struts2》第十二章 CRUD综合运用 之 12.3 使用Struts2来实现表现层

2.3??使用Struts2来实现表现层

12.3.1??将一组相关的Action类合成一个

在前面学习的时候,每个Action类都只对应一个单独的web请求,那么,这样做会带来什么问题呢?

?????? 先想一下,用户在添加页面上点击添加按钮之后,会发生什么事呢?Struts2会提交到负责添加的Action中,这个Action只是接收前一个页面传过来的数据,然后把它填入数据库就可以了,所以,可以这样写:

?

java代码:查看复制到剪贴板打印
  1. public?class?UserAddAction?extends?ActionSupport{??
  2. ????private?UserModel?user;??
  3. ????public?UserModel?getUser()?{??
  4. ????????return?user;??
  5. ????}??
  6. ????public?void?setUser(UserModel?user)?{??
  7. ????????this.user?=?user;??
  8. ????}??
  9. ????public?String?execute()?throws?Exception{??
  10. ????????UserJDBCDAO?dao?=?new?UserJDBCDAO();??
  11. ????????//把接收到的数据添加到数据库里??
  12. ????????dao.create(user);??
  13. ????????return?this.toList();??
  14. ????}??
  15. ????//其它的省略了??
  16. }??

这个Action用自己的一个user属性接收了上一个页面上传过来的数据,然后新建了一个dao,用dao把这个UserModel放入了数据库。看起来没有什么问题,它做了它该做的事情。

?????? 再想一想其他Action呢?如果用户在修改页面上点击了修改按钮之后,Action要做什么呢?

同样也是接收页面传过来的数据,然后用dao把这个UserModel放入数据库吧,大致的写法会是这样:

?

java代码:查看复制到剪贴板打印
  1. public?class?UserUpdateAction?extends?ActionSupport{??
  2. ????private?UserModel?user;??
  3. ????public?UserModel?getUser()?{??
  4. ????????return?user;??
  5. ????}??
  6. ????public?void?setUser(UserModel?user)?{??
  7. ????????this.user?=?user;??
  8. ????}??
  9. ????public?String?execute()?throws?Exception{??
  10. ????????UserJDBCDAO?dao?=?new?UserJDBCDAO();??
  11. ????????//把接收到的数据更新到数据库里??
  12. ????????dao.update(user);??
  13. ????????return?this.toList();??
  14. ????}??
  15. ????//其它的省略了??
  16. }??

对比这两个类,会发现几乎是相同的,只是UserAddAction调用了dao的create方法,而UserUpdateAction调用了dao的update方法。

?????? 因此,在实际的开发中,并不会用一个Action来对应一个web请求的功能,而是把一组相关的web请求的功能,比如说都是处理UserModel的功能,放到一起,用一个Action来实现。

在struts.xml的配置中,仍然可以使用多份不同的配置,也就是一个Action对应多个<action>标签。这样做,既可以消除很多细粒度的类,又可以消除这些类之间的重复代码,比如说UserAddAction和UserUpdateAction都有的user属性及其getter/setter等。

在接下来的实现中,我们将使用一个Action,来完成对用户的增、删、改、查功能。

12.3.2??显示全部用户

首先来实现显示全部用户的功能。要显示全部数据,通常是先进入一个Action来检索出所有数据,然后跳转到负责显示数据的页面,把数据展示出来。

1:准备Action

?????? 在上一个小节中,已经说过,真正的开发中往往把一些列相关的web请求的功能放到一起,由一个Action响应。那么,怎么用一个Action来响应多个web请求的功能呢?

可以采用第四章学到的给Action起别名的方法:在struts.xml中,一个Action类对应多个<action>元素,每一个<action>元素都可以指定一个方法名(method属性),使得响应的时候可以不调用execute方法,而是调用指定方法。

?????? 因此,可以写出Action的代码,示例如下:

?

java代码:查看复制到剪贴板打印
  1. public?class?UserAction?extends?ActionSupport{??
  2. ????private?List<UserModel>?list;??
  3. ????public?List<UserModel>?getList()?{??
  4. ????????return?list;??
  5. ????}??
  6. ????public?void?setList(List<UserModel>?list)?{??
  7. ????????this.list?=?list;??
  8. ????}??
  9. ????public?String?toList()?throws?Exception{??
  10. ????????UserJDBCDAO?dao?=?new?UserJDBCDAO();??
  11. ????????//从数据库里检索出所有的数据,并赋给Action的属性list??
  12. ????????list?=?dao.getAll();??
  13. ????????return?"toList";??
  14. ????}??
  15. }??

在这里,代码本身并不难,只是需要注意,现在的响应方法不是execute方法了,而是写的toList方法。

2:准备JSP

?????? 在Action中,将从数据库里检索出来的数据放到了一个叫list的属性里,所以,列表页面(list.jsp)上只要循环的显示这个list属性里的所有东西就可以了。

这会用到<s:iterator/>标签,注意,这个标签会把当前正在循环的对象放到值栈的栈顶,所以,在引用正在循环对象的某个属性的时候,在<s:iterator/>标签范围内的<s:property/>标签里的OGNL表达式只需要写属性名就可以了。

示例代码如下:

?

java代码:查看复制到剪贴板打印
  1. <%@?page?language="java"?contentType="text/html;?charset=gb2312"??
  2. ????pageEncoding="gb2312"%>??
  3. <%@taglib?prefix="s"?uri="/struts-tags"?%>??
  4. <!DOCTYPE?html?PUBLIC?"-//W3C//DTD?HTML?4.01?Transitional//EN"???
  5. "http://www.w3.org/TR/html4/loose.dtd">??
  6. <html>??
  7. <head>??
  8. <meta?http-equiv="Content-Type"?content="text/html;?charset=gb2312">??
  9. <title>显示用户信息</title>??
  10. </head>??
  11. <body>??
  12. <hr>??
  13. <table?border="1"?cellpadding="1"?cellspacing="0"?align="center">??
  14. ????<tr>??
  15. ????????<td>编号</td>??
  16. ????????<td>姓名</td>??
  17. ????????<td>性别</td>??
  18. ????????<td>年龄</td>??
  19. ????????<td>操作</td>??
  20. ????</tr>??
  21. <s:iterator?value="list">??
  22. ????<tr>??
  23. ????????<td><s:property?value="userId"/>?</td>??
  24. ????????<td><s:property?value="name"/>?</td>??
  25. ????????<td><s:property?value="sex"/>?</td>??
  26. ????????<td><s:property?value="age"/>?</td>??
  27. ????????<td>??
  28. ????????????操作??
  29. ????????</td>??
  30. ????</tr>??
  31. </s:iterator>??
  32. </table>??
  33. </body>??
  34. </html>??

3:struts.xml配置

在struts.xml中需要进行配置,才能让UserAction的toList方法被执行后,跳转到指定的list.jsp。

?

java代码:查看复制到剪贴板打印
  1. <package?name="crud1"?namespace="/crud1"?extends="struts-default">??
  2. <action?name="userToList"?class="cn.javass.crud1.action.UserAction"?method="toList">??
  3. ????????<result?name="toList">/jsp/list.jsp</result>??
  4. ????</action>??
  5. </package>??

在这里,唯一要注意的就是<action>标签的method属性,指明了在访问名为userToList的Action时,要调用的不是execute方法,而是指定的toList方法。

?????? 启动数据库和Tomcat服务器,访问“http://localhost:9080/crud1/crud1/userToList.action”就可以看到全部数据了。当然,建完表之后还没有数据,可以先手工向数据库里加几条,看一下结果。

《研磨struts2》第十二章 CRUD综合应用 之 12.3 使用Struts2来实现表现层

图12.1 显示全部用户页面

12.3.3??添加用户

做完显示全部用户之后,接下来开始实现添加用户的功能。

添加用户的操作要分两个阶段:首先,要跳入一个“添加页面”,在这个页面上可以填入想添的数据;然后,点击添加按钮时,提交这个页面,进行真正的数据库操作。

1:准备跳转到添加页面的链接

先要在list.jsp页面上添加一个转到“添加用户”页面的链接:

?

java代码:查看复制到剪贴板打印
  1. <a?href="/crud1/crud1/userToAdd.action">添加用户</a>??

点击这个链接,访问名为userToAdd的Action。

2:准备跳转到添加页面之前的Action

?????? 在添加页面上,需要收集用户的输入:分别用三个普通的文本框收集用户的编号、姓名、年龄;用一个下拉框来收集用户的性别,下拉框有两个选项,分别是男和女。因此,在跳转到添加页面之前的Action中,只需要准备一个字符串数组设定两个选项“男”和“女”。

?????? 把关于UserModel的一组操作都放到UserAction中,各个方法之间是互不影响的,UserAction中已经有了toList方法,那么,只要新添加的方法不叫toList就可以了。所以,在UserAction中添加以下内容,注意,这里的添加不要影响原有的内容,是在已有的内容上添加的,示例代码如下:

?

java代码:查看复制到剪贴板打印
  1. public?class?UserAction?extends?ActionSupport{??
  2. ????private?String[]?sexs?=?new?String[]{"男","女"};??
  3. ????public?String[]?getSexs()?{??
  4. ????????return?sexs;??
  5. ????}??
  6. ????public?void?setSexs(String[]?sexs)?{??
  7. ????????this.sexs?=?sexs;??
  8. ????}??
  9. ????public?String?toAdd()?throws?Exception{??
  10. ????????return?"toAdd";??
  11. ????}??
  12. ????//原有代码请参见实现toList方法的UserAction??
  13. }??

在这里,新建了一个toAdd方法,它什么也没做,只是返回了toAdd这个字符串。还新建了一个String数组,定义了“男”和“女”,这样,在下一个页面上就可以引用这个数组来生成下拉框了。

2:准备添加页面

?????? 添加页面,也就是add.jsp页面,示例代码如下:

?

java代码:查看复制到剪贴板打印
  1. <%@?page?language="java"?contentType="text/html;?charset=gb2312"??
  2. ????pageEncoding="gb2312"%>??
  3. <%@taglib?prefix="s"?uri="/struts-tags"?%>??
  4. <!DOCTYPE?html?PUBLIC?"-//W3C//DTD?HTML?4.01?Transitional//EN"??
  5. ?"http://www.w3.org/TR/html4/loose.dtd">??
  6. <html>??
  7. <head>??
  8. <meta?http-equiv="Content-Type"?content="text/html;?charset=gb2312">??
  9. <title>添加用户信息</title>??
  10. </head>??
  11. <body>??
  12. <s:form?action="userAdd"?method="post">??
  13. ????<s:textfield?name="user.userId"?label="编号"/>??
  14. ????<s:textfield?name="user.name"?label="姓名"/>??
  15. ????<s:select?list="sexs"?name="user.sex"?label="性别"/>??
  16. ????<s:textfield?name="user.age"?label="年龄"/>??
  17. ????<s:submit?value="添加"/>??
  18. </s:form>??
  19. </body>??
  20. </html>??

在这个页面上,<s:form>标签,没有设置namespace属性,说明要提交到同包内的名为userAdd的Action去,没有指定theme属性,说明使用默认的xhtml主题。

<s:textfield>标签很简单,其label属性为文本框前面显示的文字,name属性指定了提交的参数名。

<s:select>标签的list属性指定了生成选项的数据源为上一个Action的sexs属性,正是建立的String数组,没有指定listKey属性和listValue属性说明生成<option>的时候value和<option>标签中间的文本都使用String数组中的字符串即可,所以,在页面上看到的选项是“男”、“女”,将来在下一个Action中接到的值也将是“男”或“女”。

3:struts.xml配置

?????? 那么,下一步是让UserAction的toAdd方法运行完之后,跳转到add.jsp页面,而进入这个页面是在list.jsp上跳转到名为userToAdd的Action,所以在配置的时候采取以下方式:

?

java代码:查看复制到剪贴板打印
  1. <action?name="userToAdd"?class="cn.javass.crud1.action.UserAction"?method="toAdd">??
  2. ????<result?name="toAdd">/jsp/add.jsp</result>??
  3. </action>??

注意,这个<action>元素与上一个<action>名为userToList的元素的关系是:同一个包内的两个<action>元素,因此,这里就体现了解决问题的思路:同一个Action类通过取不同别名的方法,在struts.xml中配置为多个<action>元素,来执行一组相关的web请求所对应的功能。

《研磨struts2》第十二章 CRUD综合应用 之 12.3 使用Struts2来实现表现层

图12.2 添加用户页面

4:提交Action

?????? 添加页面的初始化完成之后,可以来实现点击“添加按钮”后如何向数据库里提交了。在add.jsp上,点击“添加按钮”提交到名为userAdd的Action中。仍然使用UserAction,这时,UserAction的add方法只需要接收add.jsp传过来的参数,并把它添加到数据库即可,在向数据库添加完之后,只需要跳转到显示所有用户的页面,示例代码如下:

?

java代码:查看复制到剪贴板打印
  1. public?class?UserAction?extends?ActionSupport{??
  2. ????private?UserModel?user;??
  3. ????public?UserModel?getUser()?{??
  4. ????????return?user;??
  5. ????}??
  6. ????public?void?setUser(UserModel?user)?{??
  7. ????????this.user?=?user;??
  8. ????}??
  9. ????public?String?add()?throws?Exception{??
  10. ????????UserJDBCDAO?dao?=?new?UserJDBCDAO();??
  11. ????????//把接收到的数据添加到数据库??
  12. ????????dao.create(user);??
  13. ????????//调用toList方法,在添加到数据库之后??
  14. //把所有的数据检索出来,然后跳转到显示所有用户的页面??
  15. ????????return?this.toList();??
  16. ????}??
  17. ????//原有代码请参见实现toAdd方法的UserAction??
  18. }??

由于add方法最后调用了toList方法,而且add方法以toList方法的返回值作为自己的返回值,所以add方法的返回值实际上是toList。而且,添加用户最终要跳转到显示所有用户的页面。所以在配置struts.xml的时候要注意,这个<action>元素的<result>子元素应该以toList为名,最终指向到list.jsp。

6:struts.xml配置


java代码:查看复制到剪贴板打印
  1. <action?name="userAdd"?class="cn.javass.crud1.action.UserAction"?method="add">??
  2. ????<result?name="toList">/jsp/list.jsp</result>??
  3. </action>??

去运行测试一下看看,现在的新增和列表功能是否好用。

12.3.4??修改用户

做完显示所有用户和添加用户的功能之后,接下来实现修改用户的功能。

修改用户要分两个阶段:首先,要跳转到一个“修改页面”,在这个页面上展示需要修改的数据,用户在此基础上可以修改要改的数据,然后点击修改按钮时,提交这个页面,进行真正的数据库操作。

1:准备跳转到修改页面的链接

先要在list.jsp页面上为每条用户数据准备一个跳转到修改页面的链接,这个链接自然应该放到table中,每一行都有一个,而且每行都把自己这行显示的用户的userId数据传给后续处理的Action,示例代码如下:

?

java代码:查看复制到剪贴板打印
  1. <hr>??
  2. <table?border="1"?cellpadding="1"?cellspacing="0"?align="center">??
  3. ????<tr>??
  4. ????????<td>编号</td>??
  5. ????????<td>姓名</td>??
  6. ????????<td>性别</td>??
  7. ????????<td>年龄</td>??
  8. ????????<td>操作</td>??
  9. ????</tr>??
  10. <s:iterator?value="list">??
  11. ????<tr>??
  12. ????????<td><s:property?value="userId"/>?</td>??
  13. ????????<td><s:property?value="name"/>?</td>??
  14. ????????<td><s:property?value="sex"/>?</td>??
  15. ????????<td><s:property?value="age"/>?</td>??
  16. ????????<td>??
  17. ????????????<a?href="/crud1/crud1/userToUpdate.action?user.userId=<s:property?value='userId'/>">修改</a>??
  18. ????????</td>??
  19. ????</tr>??
  20. </s:iterator>??
  21. </table>??

在上面的代码中,加粗的代码就是跳转到名为userToUpdate的Action的链接,需要以user.userId的名字传入当前行显示的用户的userId,而且整个这一行在<s:iterator/>标签中,所以,使用<s:property value=”userId”/>即可引用当前行显示的用户的userId。

2:准备跳转到修改页面之前的Action

?????? 修改页面先要展示需要修改的数据,通常的做法是在转向修改页面之前的Action里面,就把这条数据检索出来并放到值栈里,等待修改页面去引用,示例代码如下:

?

java代码:查看复制到剪贴板打印
  1. public?class?UserAction?extends?ActionSupport{????
  2. ????public?String?toUpdate()?throws?Exception{??
  3. ????????UserJDBCDAO?dao?=?new?UserJDBCDAO();??
  4. ????????//按照接收到的userid,检索出对应记录??
  5. ????????user?=?dao.getSingle(user.getUserid());??
  6. ????????return?"toUpdate";??
  7. ????}??
  8. ????//原有代码请参见实现add方法的UserAction??
  9. }??

在这个Action里,toUpdate方法操作了user属性,由于各个操作都共用这个UserAction,所以,在做add方法时,已经为UserAction增添了user属性,这里就不要再声明了。

由于在list.jsp页面上写链接传值的时候,用户的userId以名为user.userId属性传入这个Action,因此,自然要调用其user属性的getUserId()方法来获得。

3:准备修改页面

?????? 修改页面与添加页面的布局完全一样,只是要展示需要修改的数据,示例代码如下:

?

java代码:查看复制到剪贴板打印
  1. <%@?page?language="java"?contentType="text/html;?charset=gb2312"??
  2. ????pageEncoding="gb2312"%>??
  3. <%@taglib?prefix="s"?uri="/struts-tags"?%>??
  4. <!DOCTYPE?html?PUBLIC?"-//W3C//DTD?HTML?4.01?Transitional//EN"??
  5. ?"http://www.w3.org/TR/html4/loose.dtd">??
  6. <html>??
  7. <head>??
  8. <meta?http-equiv="Content-Type"?content="text/html;?charset=gb2312">??
  9. <title>修改用户信息</title>??
  10. </head>??
  11. <body>??
  12. <s:form?action="userUpdate"?method="post">??
  13. ????<s:textfield?name="user.userId"?label="编号"/>??
  14. ????<s:textfield?name="user.name"?label="姓名"/>??
  15. ????<s:select?list="sexs"?name="user.sex"?label="性别"/>??
  16. ????<s:textfield?name="user.age"?label="年龄"/>??
  17. ????<s:submit?value="修改"/>??
  18. </s:form>??
  19. </body>??
  20. </html>??

请读者比较一下这个update.jsp和原来的add.jsp,发现除了<title>不同,<s:form>要提交的目标不同,<s:submit/>显示的文字不同之外,别的都与add.jsp一模一样,不是要展示数据吗?怎么没有赋值呢?

请大家回忆一下前面学过的知识:<s:textfield/>标签的name属性,不仅仅指定了这个文本框在提交的时候的参数名;在没有指定value属性的时候,name属性还可以当作OGNL表达式来向值栈请求值,作为这个文本框的初始值。

?????? 因此,在update.jsp上的<s:textfield name=”user.userid”/>,由于在Action(userToUpdate)中初始化了其user属性,而这个属性的值被放到了值栈中,所以页面能够自动获取道这些值,并展示在相应的表单域里面。

3:struts.xml配置

?????? 首先是在list.jsp上跳转到名为userToUpdate的Action,然后让UserAction的toUpdate方法运行完之后,跳转到update.jsp页面,所以在配置的时候采取以下方式:

?

java代码:查看复制到剪贴板打印
  1. <action?name="userToUpdate"?class="cn.javass.crud1.action.UserAction"??
  2. method="toUpdate">??
  3. ????<result?name="toUpdate">/jsp/update.jsp</result>??
  4. </action>??

4:运行测试一下

?????? 先跳转到修改页面,如下图所示:

《研磨struts2》第十二章 CRUD综合应用 之 12.3 使用Struts2来实现表现层

图12.3 修改用户页面

5:处理修改提交的Action

?????? 修改页面的初始化完成之后,用户将值修改成需要的数据,然后点击“修改按钮”向后台提交修改信息。在update.jsp上,点击“修改按钮”提交到名为userUpdate的Action去进行处理。

这时,UserAction的update方法只需要接收update.jsp传过来的参数,并把它更新到数据库即可,在向数据库更新完之后,仍然跳转到显示所有用户的页面,示例代码如下:

?

java代码:查看复制到剪贴板打印
  1. public?class?UserAction?extends?ActionSupport{??
  2. ????public?String?update()?throws?Exception{??
  3. ????????UserJDBCDAO?dao?=?new?UserJDBCDAO();??
  4. ????????//把接收到的数据更新到数据库??
  5. ????????dao.update(user);??
  6. ????????return?this.toList();??
  7. ????}??
  8. ????//原有代码请参见实现toUpdate方法的UserAction??
  9. }??

6:struts.xml配置

由于update方法最后调用了toList方法,而且update方法以toList方法的返回值作为自己的返回值,所以update方法的返回值实际上是“toList”。所以在配置struts.xml的时候要注意,这个<action>元素的<result>子元素应该以toList为名,最终指向到list.jsp。

?

java代码:查看复制到剪贴板打印
  1. <action?name="userUpdate"?class="cn.javass.crud1.action.UserAction"?method="update">??
  2. ????<result?name="toList">/jsp/list.jsp</result>??
  3. </action>??

12.3.5??删除用户

现在,该考虑如何删除用户了。在做任何企业级应用软件时,在删除之前都必须进行询问,决不能让用户点击了删除按钮之后就马上删除,实现的方式很多,其中一种简单的方式就是使用javascript中的询问框confirm来完成这个功能。当用户选择确认删除之后,就真的执行删除并跳回到显示所有用户的页面就可以了。

1:准备删除的链接

在list.jsp页面上为每个用户准备一个删除的链接,这个链接自然也像修改一样应该放到table中,每一行都有一个,而且每行都把自己这行显示的用户的userid传给下一个Action:

?

java代码:查看复制到剪贴板打印
  1. <hr>??
  2. <table?border="1"?cellpadding="1"?cellspacing="0"?align="center">??
  3. ????<tr>??
  4. ????????<td>编号</td>??
  5. ????????<td>姓名</td>??
  6. ????????<td>性别</td>??
  7. ????????<td>年龄</td>??
  8. ????????<td>操作</td>??
  9. ????</tr>??
  10. <s:iterator?value="list">??
  11. ????<tr>??
  12. ????????<td><s:property?value="userId"/>?</td>??
  13. ????????<td><s:property?value="name"/>?</td>??
  14. ????????<td><s:property?value="sex"/>?</td>??
  15. ????????<td><s:property?value="age"/>?</td>??
  16. ????????<td>??
  17. ????????????<a?href="/crud1/crud1/userToUpdate.action?user.userId=<s:property?value='userId'/>">修改</a>|??
  18. ????????????<a?href="javascript:if?(confirm('确认删除吗?'))?window.location.href='/crud1/crud1/userDelete.action?user.userId=<s:property?value='userId'/>'">删除</a>??
  19. ????????</td>??
  20. ????</tr>??
  21. </s:iterator>??
  22. </table>??

在上面的代码中,“<a href="javascript:if (confirm('确认删除吗?')) window.location.href='/crud1/crud1/userDelete.action?user.userId=<s:property value='userId'/>'">删除</a>”这句话就是要进行删除的链接。虽然看着比较长,不要着急,一点一点来分析,对这个链接的href属性:

  • javascript:这说明了后面是javascript语句。而观察这一整句javascript,实际上就是一个if语句,这一整句if分成条件部分和执行部分,其中条件部分就是一个confirm,而执行部分是window.location.href。
  • confirm:询问框,返回一个boolean,询问是否进行删除。观察if的结构可知,决定删除的时候会调用后面的部分,而决定不删除的时候什么都不做
  • window.location.href :控制页面跳转,如果决定删除,将跳转到/crud1/crud1/userDelete.action?user.userId=<s:property value='userId'/>。

    2:实现删除功能的Action

    ?????? 实现删除功能的Action,只需要接收list.jsp页面传过来的用户的userId,然后在数据库里把这个用户删除即可,删除后仍然跳转到显示全部用户的页面。示例代码如下:

    ?

    java代码:查看复制到剪贴板打印
    1. public?class?UserAction?extends?ActionSupport{????
    2. ????public?String?delete()?throws?Exception{??
    3. ????????UserJDBCDAO?dao?=?new?UserJDBCDAO();??
    4. //用接收到的数据从数据库里删除??
    5. ????????dao.delete(user.getUserid());??
    6. ????????return?this.toList();??
    7. ????}??
    8. ????//原有代码请参见实现update方法的UserAction??
    9. }??

    3:struts.xml配置

    由于delete方法最后调用了toList方法,而且delete方法以toList方法的返回值作为自己的返回值,所以delete方法的返回值实际上是“toList”。所以在配置struts.xml的时候要注意,这个<action>元素的<result>子元素应该以toList为名,最终指向到list.jsp。

    ?

    java代码:查看复制到剪贴板打印
    1. <action?name="userDelete"?class="cn.javass.crud1.action.UserAction"?method="delete">??
    2. ????<result?name="toList">/jsp/list.jsp</result>??
    3. </action>??

    12.3.6??按条件查询

    在显示全部用户信息的list.jsp上放置一个转到查询页面的链接,点击这个链接可以跳转到输入查询条件页面。

    1:准备跳转到查询页面的链接

    先要在list.jsp页面上添加一个转到“查询用户”页面的链接:

    ?

    java代码:查看复制到剪贴板打印
    1. <a?href="/crud1/crud1/userToQuery.action">查询用户</a>??

    点击这个链接,访问名为userToQuery的Action。

    2:准备跳转到查询页面之前的Action

    ?????? 查询页面用一个下拉框来收集用户的性别。但它与添加页面和修改页面不同,添加页面和修改页面上的下拉框只需要“男”和“女”两个选项;但是查询页面上,可以不用性别作为条件,因此还要添加“请选择”这一项代表不以性别作为选项。

    ?????? 在之前准备添加页面时,已经用一个字符串数组sexs,存入了“男”和“女”,因此,现在的Action里面其实什么都不用做,示例代码如下:

    ?

    java代码:查看复制到剪贴板打印
    1. public?class?UserAction?extends?ActionSupport{????
    2. ????public?String?toQuery()?throws?Exception{??
    3. ????????return?"toQuery";??
    4. ????}??
    5. ????//原有代码请参见实现delete方法的UserAction??
    6. }??

    3:准备查询页面

    ?????? 查询页面需要在性别下拉框中添上一项“请选择”,这一项传到下一个页面的值使用空字符串就可以了。

    可是前面并没有在Action的字符串数组sexs上加上请选择这一项,那么页面上该怎么实现呢?很简单,使用select标签的headerKey和headerValue属性就可以了。

    示例代码如下:

    ?

    java代码:查看复制到剪贴板打印
    1. <%@?page?language="java"?contentType="text/html;?charset=gb2312"??
    2. ????pageEncoding="gb2312"%>??
    3. <%@taglib?prefix="s"?uri="/struts-tags"?%>??
    4. <!DOCTYPE?html?PUBLIC?"-//W3C//DTD?HTML?4.01?Transitional//EN"??
    5. ?"http://www.w3.org/TR/html4/loose.dtd">??
    6. <html>??
    7. <head>??
    8. <meta?http-equiv="Content-Type"?content="text/html;?charset=gb2312">??
    9. <title>查询用户信息</title>??
    10. </head>??
    11. <body>??
    12. <s:form?action="userQuery"?method="post">??
    13. ????<s:textfield?name="uqm.userId"?label="编号"?value="0"/>??
    14. ????<s:textfield?name="uqm.name"?label="姓名"/>??
    15. ????<s:select?list="sexs"?name="uqm.sex"?label="性别"???
    16. headerKey=""?headerValue="请选择"/>??
    17. ????<s:textfield?name="uqm.age"?label="年龄最小值"?value="0"/>??
    18. ????<s:textfield?name="uqm.age2"?label="年龄最大值"?value="0"/>??
    19. ????<s:submit?value="查询"/>??
    20. </s:form>??
    21. </body>??
    22. </html>??

    仔细的你肯定会发现,这里使用的标签写法跟以前不太一样,这里给userId、age和age2三个输入框设置了初始值0,这又是为何呢?

    这是因为这几个值在Model中对应的都是int类型的数据,对于查询页面,这几个输入框都可以不填写任何值,那么提交到Action的时候就应该是“null”或者是空字符串,不管是哪一个值,Struts2都无法把它转换成Model需要的int类型的数据,从而导致报错,错误信息示例如下:

    ?

    java代码:查看复制到剪贴板打印
    1. 警告:?Error?setting?expression?'uqm.userId'?with?value?'[Ljava.lang.String;@67cd84'??
    2. ognl.MethodFailedException:?Method?"setUserId"?failed?for?object?cn.javass.crud1.model.UserQueryModel@1f?[java.lang.NoSuchMethodException:?cn.javass.crud1.model.UserQueryModel.setUserId([Ljava.lang.String;)]??
    3. ????at?ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1265)??
    4. ????at?ognl.OgnlRuntime.setMethodValue(OgnlRuntime.java:1454)??
    5. ????……??
    6. Caused?by:?java.lang.NoSuchMethodException:?cn.javass.crud1.model.UserQueryModel.setUserId([Ljava.lang.String;)??
    7. ????at?ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1206)??
    8. ????...?69?more??
    9. /--?Encapsulated?exception?------------\??
    10. java.lang.NoSuchMethodException:?cn.javass.crud1.model.UserQueryModel.setUserId([Ljava.lang.String;)??
    11. ????at?ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1206)??
    12. ????……??
    13. ????at?java.lang.Thread.run(Thread.java:662)??
    14. \--------------------------------------/??

    怎么处理这种情况呢?

    ?????? 其实,不处理都行,这个例外信息只是一个警告信息,程序照样能正常运行。如果不想看到这个警告信息,就可以采用上面添加初始值的方式。

    在使用<s:select/>标签时,如果同时使用headerKey属性和headerValue属性,则会在第一项的位置添加一项<option>,其value就是headerKey属性的值,而显示的文字就是headerValue属性的值。

    ?????? 在检索页面上,要把所有的操作组合成一个UserQueryModel传给后一个Action,其中不仅包括UserModel原有的属性,还包括了表示年龄最大值的age2属性。

    4:struts.xml配置


    java代码:查看复制到剪贴板打印
    1. <action?name="userToQuery"?class="cn.javass.crud1.action.UserAction"?method="toQuery">??
    2. ????<result?name="toQuery">/jsp/query.jsp</result>??
    3. </action>??

    5:运行测试一下

    ?????? 在list.jsp上点击查询用户的超链接,将会跳转到查询页面,运行如下:

    《研磨struts2》第十二章 CRUD综合应用 之 12.3 使用Struts2来实现表现层

    图12.4 查询用户页面

    6:实现查询功能的Action

    ?????? 在实现查询功能的Action中,需要接收前一个页面传过来的组合查询条件数据,把这些数据组合称为一个UserQueryModel,然后把这个对象传给DAO,查询出合适的数据来,然后跳转到list.jsp,把这些数据展示出来即可。

    ?????? 注意:显示全部用户和显示符合查询条件的用户,可以共用list.jsp,list.jsp上只是把值栈中“list”(由<s:iterator/>标签引用的)的内容显示在页面上。所以,在查询之后,把查询结果放到Action的list属性就可以了。

    Action现在需要接收用户查询条件的数据,因此只需要新建立UserQueryModel类型的uqm属性及其getter/setter即可。示例代码如下:

    ?

    java代码:查看复制到剪贴板打印
    1. public?class?UserAction?extends?ActionSupport{??
    2. ????private?UserQueryModel?uqm;??
    3. ????public?UserQueryModel?getUqm()?{??
    4. ????????return?uqm;??
    5. ????}??
    6. ????public?void?setUqm(UserQueryModel?uqm)?{??
    7. ????????this.uqm?=?uqm;??
    8. ????}??
    9. ????public?String?query()?throws?Exception{??
    10. ????????UserJDBCDAO?dao?=?new?UserJDBCDAO();??
    11. ????????//接收用户输入的查询条件,到数据库中查询??
    12. ????????list?=?dao.getByCondition(uqm);??
    13. ????????//注意:只是返回toList这个字符串,而不是调用toList方法??
    14. ????????return?"toList";??
    15. ????}??
    16. ????//原有代码请参见实现toQuery方法的UserAction??
    17. }??

    7:struts.xml配置

    ?

    java代码:查看复制到剪贴板打印
    1. <action?name="userQuery"?class="cn.javass.crud1.action.UserAction"?method="query">??
    2. ????<result?name="toList">/jsp/list.jsp</result>??
    3. </action>??

    12.3.7??小结

    在以前的学习中都是简单的就知识而知识的学习,在本节中真正体会了如何综合使用所学的这些Struts2的核心知识。在这里,有两点要注意:

    1:一组与同一个域对象相关的Action会有好多重复的代码,比如多个Action会拥有域对象类型的属性及其getter/setter。那么,可以把这一组Action实现为一个类,根据不同的配置别名去访问不同的方法,这样就减少了类的数量,同时减少了冗余代码。

    注意:在本小节中多次出现的UserAction代码是以累加的方式逐步演化的,每步的UserAction里面只是列出新加的代码。因而完整的UserAction有好多方法,toList、toAdd、add、toUpdate、udpate、delete、toQuery、Query。

    虽然一组Action合在一起了,但是struts.xml中的<action>标签仍然可以分开来配置的,它们之间也可能由相似的代码,比如<result name="toList">/jsp/list.jsp</result>就出现了好多次。那么,可不可以把它们也合在一起呢?合起来之后会有什么副作用呢?这个以后再说。

    2:Struts2表单标签提供了良好的帮助,它的name属性还可以在页面初始化时取值,因此add.jsp与update.jsp之间的差别很小了。

    要是使用普通的<input>标签,写法大致如下:

    ?

    java代码:查看复制到剪贴板打印
    1. add.jsp上<input?type=”text”?name=”user.userId”>??
    2. update.jsp上<input?type=”text”?name=”user.userId”?value=”${user.userId}”>???

    可以看出,使用普通的<input>标签,修改页面上还需要自己手动设置初始值。

    ?

    私塾在线网站原创《研磨struts2》系列

    转自请注明出处:【http://sishuok.com/forum/blogPost/list/4111.html】

    欢迎访问http://sishuok.com获取更多内容

    </action>

热点排行