`

《研磨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”就可以看到全部数据了。当然,建完表之后还没有数据,可以先手工向数据库里加几条,看一下结果。

图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请求所对应的功能。

图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:运行测试一下

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

图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上点击查询用户的超链接,将会跳转到查询页面,运行如下:

图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获取更多内容

3
4
分享到:
评论
1 楼 on_rain 2012-05-29  
你是在说一个struts的通配符搞定的事吧?
<action name="user_*" class="cn.javass.crud1.action.UserAction" method="{1}">
</action>

相关推荐

Global site tag (gtag.js) - Google Analytics