struts2 基于OGNL的类型转换【转载】
使用过struts2的都应该会深深地喜欢它为我们提供的这种转换方式,为我们对于表单提交的处理变得更加的简单
借助内置的类型转换,struts2可以完成字符串和基本类型之间的转换,只需要提供属性对应的set方法即可,而不需要像在servlet中一样使用request.getParameter("xx");
来获取表单提交的信息
更加完美的是:借助于ONGL表达式的支持,struts2还可以经过简单的处理来将请求参数转化为复合类型,这对于属性众多的复合对象真是天助;看下面的实例:
注册的表单:register.jsp
<s:form action ="douserreg" method ="POST" name="regesiter" enctype="multipart/form-data" id="registerForm" onsubmit="return checkReg(this);"> <div id = "sign" class="mDiv"></div> <input type = "hidden" name = "examId" id = "examId" value = <s:property value = "examId"/>> <table class="regist_table" style="width:600px;"> <col class="regist_table_fir"/> <col class="regist_table_sed"/> <col class="regist_table_thi"/> <tr> <td>当前正在注册的考试:</td> <td colspan="3"> <font color = "red"><%=session.getAttribute("examName")%></font> </td> </tr> <tr> <td>用 户 名:</td> <td> <s:textfield name="users.uname" id="inputName" cssClass="regist_input" value = "手机长号" disabled="true"/> </td> <td>真实姓名:</td> <td><s:textfield name = "users.ucnName" cssClass = "regist_input" id = "realName"/> </td> </tr> <tr> <td>密 码:</td> <td><s:password name="users.upsw" cssClass="regist_input" id = "upsw"/></td> <td>密码校验:</td> <td><s:password name="repeatPass" cssClass="regist_input" id = "repeatPass"/></td> </tr> <tr> <td>性 别:</td> <td align="left"> <s:radio name="users.ssex" list="{'男','女'}" id = "sex"/> </td> <td>是否省优<br>毕业生:</td> <td align="left"> <s:radio name="users.sfsybys" list="{'是','否'}" id = "great"/> </td> </tr> <tr> <td>学 位:</td> <td><s:select label="学位" list="ehDegreeList" name="users.stuDegree" emptyOption="false" headerKey="" headerValue="--请选择--" listKey="formValue" listValue="formValue" cssClass="regist_input" id = "degree"/> </td> <td>学 历:</td> <td><s:select label="学历" list="eduBakList" name="users.eduBak" emptyOption="false" headerKey="" headerValue="--请选择--" listKey="formValue" listValue="formValue" cssClass="regist_input" id = "edubak"/> </td> </tr> <tr> <td>外语等级:</td> <td><s:select label="外语等级" list="wydjLists" name="users.wydj" emptyOption="false" headerKey="" headerValue="--请选择--" listKey="formValue" listValue="formValue" cssClass="regist_input" id = "foreignDegree"/> </td> <td>身 份 证:</td><td><s:textfield name="users.certificate" id="inputCerti" onblur="validateRegCertificate();" cssClass="regist_input"/></td> </tr> <tr> <td>毕业时间:</td><td><input type = "text" name="users.bysj" id = "time" onFocus="WdatePicker()"></td> <td>毕业院校:</td><td> <s:textfield name="users.byyx" cssClass="regist_input" id = "college"/></td> </tr> <tr> <td>专 业:</td><td><s:textfield name="users.specials" cssClass="regist_input" id = "major"/></td> <td>政治面貌:</td><td><s:textfield name="users.zzmm" cssClass="regist_input" id = "polity"/></td> </tr> <tr><td>民 族:</td><td><s:textfield name="users.nation" cssClass="regist_input" id = "nation"/></td> <td>固定电话:</td><td><s:textfield name="users.gddh" cssClass="regist_input" id = "phone"/></td> </tr> <tr> <td>手机长号:</td> <td><s:textfield name="users.yddh" cssClass="regist_input" id = "telephone" onblur="validateRegTelephone();"/></td> <td>户口所在地:</td> <td><s:textfield name="users.hkszd" cssClass="regist_input" id = "hkszd"/></td> </tr> <tr> <td>邮 箱:</td><td> <s:textfield name="users.zcyx" cssClass="regist_address" id = "email"/></td> <td>联系地址:</td><td> <s:textfield name="users.lxdz" cssClass="regist_address" id = "address"/></td> </tr> <tr> <td>在校荣获奖励:</td> <td colspan="3"><s:textarea name="users.zxrhjl" rows="5" cols="40" id = "honour"/></td> </tr> <tr> <td>个人简历:</td> <td colspan="3"><s:textarea name="users.grjl" rows="5" cols="40" id = "resume"/></td> </tr> <tr> <td>个人照片:</td><td colspan="3"><input type="file" name="upload" id = "photo"/></td> </tr> <tr> <td><s:token/></td> <td colspan="3"><input type = "submit" name="submit" style="background:url(index_update/images/zhuce.jpg) no-repeat;height:22px; width:50px;border:none" value=""/> <input name="reset" type="reset" value="" style="background:url(index_update/images/resetbut.jpg); border:none; height:22px; width:50px;"/></td> </tr> </table> </s:form>
上面标签中的name值都是使用 对象.属性 的标准OGNL表达式,这样struts2标签就可以获得该标签提交的值
后台代码很简单:只要提供复合对象users的set方法,然后在复合对象users的内部对所有的属性提供set方法即可(users内部属性与对象持久化这里不讨论)
public class UserBasicAction extends ActionSupport{ protected StuUsers users; public StuUsers getUsers() { return users; } public void setUsers(StuUsers users) { this.users = users; } }
看着后台代码的简洁性我们不得不喜欢struts2提供了这种方式
这里有几个注意点:
1.因为struts2将通过反射来创建一个复合类(StuUsers)的实例,因此系统必须为该复合类提供一个无参数的构造方法。
如:
public class StuUsers implements java.io.Serializable { // Fields private Integer uid; private String uname; private String upsw; private String ucnName; private String ssex; private String eduBak; private String bysj; private String byyx; private String stuDegree; private String specials; private String certificate; private String zzmm; private String nation; private String sfsybys; private String wydj; private String lxdz; private String gddh; private String yddh; private String zxrhjl; private String grjl; private String userPhoto; private String djbz; private String hkszd; private String zcyx; private Exams exams; private String applySign; private String state; private String vercode; private String registerTime; private String activateTime; private Set examUsers = new HashSet(0); // Constructors /** default constructor */ public StuUsers() { } /** minimal constructor */ public StuUsers(String uname, String upsw, String ucnName, String ssex) { this.uname = uname; this.upsw = upsw; this.ucnName = ucnName; this.ssex = ssex; } //省略get,set方法......
2.为了能给复合对象users的属性以这种方式进赋值,我们必须为复合对象需要赋值的属性提供set方法,在Action类中提供users的get方法;
讲到这里应该够用了,但以前看书还看到了更加难度高的赋值,还是要分享下,就是直接生成Collection,或者Map实例
这个就直接给实例了 大家慢慢体会:
Map:Action类:
package xidian.sl.action.user; import java.util.Map; import xidian.sl.entity.StuInfor; import com.opensymphony.xwork2.ActionSupport; @SuppressWarnings("serial") public class Test extends ActionSupport{ private Map<String, StuInfor> stuMap; @Override public String execute() throws Exception { System.out.println("进来了"); //输出组合后的复杂对象 System.out.println("第一个用户名:"+stuMap.get("one").getStuNum()+" <br/>第一个密码:"+stuMap.get("one").getPassword() +" <br/>第二个用户名:"+stuMap.get("two").getStuNum()+" <br/>第二个密码:"+stuMap.get("two").getPassword()); return SUCCESS; } public Map<String, StuInfor> getStuMap() { return stuMap; } public void setStuMap(Map<String, StuInfor> stuMap) { this.stuMap = stuMap; } }
页面提交端:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="s" uri="/struts-tags" %> <!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>测试</title> </head> <body> <s:form action = "testAction.action"> <s:textfield name = "stuMap['one'].stuNum" label = "第一个用户名"/> <s:password name = "stuMap['one'].password" label = "第一个密码"></s:password> <s:textfield name = "stuMap['two'].stuNum" label = "第二个用户名"/> <s:password name = "stuMap['two'].password" label = "第二个密码"></s:password> <s:submit name = "send" value = "提交" theme = "simple"></s:submit> </s:form> </body> </html>
页面显示段:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="s" uri="/struts-tags" %> <!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>测试2</title> </head> <body> 第一个用户名为:<s:property value = "stuMap['one'].stuNum"></s:property><br/> 第一个密码为:<s:property value = "stuMap['one'].password"></s:property><br/> 第二个用户名为:<s:property value = "stuMap['two'].stuNum"></s:property><br/> 第一个密码为:<s:property value = "stuMap['two'].password"></s:property><br/> </body> </html>
List与Map的处理基本一致:只是Map是“Action属性名[‘key 值’] 属性名” 而List是“Action属性名[‘索引 值’] 属性名”
这里还需要注意一个问题就是在申明集合类事最好使用泛型来明确集合类的元素类,这样struts2才能知道,否则就需要我们自己写局部类型转换文件来指定集合元素的类型