struts2框架是一个非常优秀的mvc框架,时至今日已有很多公司采用其作为表示层的控制转发工具,我非常喜欢struts2的拦截器特性和一整套的自定义标签。在这根据个人使用struts2的经验,与大家分享一些常用的struts2标签,希望对大家有所帮助。
•实例场景
假设有这样一个网站:需要用户填写个人的信息,包括:编号、姓名、密码、生日、性别、城市、爱好。其中编号需要填入整数,姓名是字符串,密码在页面中必须以密码框的形式显示,生日必须是日期格式,性别单选,城市用下拉列表选择,爱好复选框可以多选。那么用户填写完信息以后,点击“提交”按钮,到下一个页面显示用户填写的信息。
•需求分析
这是一个非常常见的需求,里面囊括了整形、字符串和日期类型等处理,另外用到了文本框、密码框、单选、复选和下拉列表等控件。
如果采用servlet/jsp的开发模式是可以实现该功能的,但是很多地方可能需要一些复杂处理,比如用户点击提交到后台需要通过request.getParameter的形式把页面的字段逐个取出来解析;单选、复选和下拉列表中的数据需要使用jsp代码逐个迭代显示;如果加上表单验证的话,这又需要花费更大的精力。
struts2提供了一整套的自定义标签解决方案,其功能在原生html标签基础上做了很大的改进:控件的name属性可以采用对象图的形式定义,点击提交按钮通过拦截器自动封装属性,这样在后台就不需要用request获取每个属性字段了;struts2对的单选、复选和下拉列表等控件进行了改进,开发人员只需要用一行代码设置集合数据和key/value即可显示出与html同样功能的组件;同时它提供了独有的错误显示标签,用于显示验证不通过的错误信息,非常方便。
•实例效果
按照我的习惯,我首先把运行的效果展示出来,再根据效果分析每个功能的具体实现。
【表单数据填写页面】
【验证不通过显示的错误消息】
【提交成功后的页面】
•后台java代码
为了减少大家看代码的疲惫感,我尽量将每个类的核心内容展示出来,具体的代码实现在此就省略掉,如果需要全部代码,可在附件中下载。
首先创建一个UserBean存放用户信息,这是一个javabean:
Java代码
1.public class UserBean implements Serializable{
2. private static final long serialVersionUID = -5808037703808170288L;
3.
4. private int userId; //编号
5. private String userName; //姓名
6. private String password; //密码
7. private Date birthday = new Date(); //生日:格式yyyy-MM-dd,默认为当前时间
8. private int sex; //性别:0男,1女
9. private int[] hobby; //爱好,数组
10. private int city; //所属 城市
11.
12. getter、setter...
13.}
public class UserBean implements Serializable{
private static final long serialVersionUID = -5808037703808170288L;
private int userId; //编号
private String userName; //姓名
private String password; //密码
private Date birthday = new Date(); //生日:格式yyyy-MM-dd,默认为当前时间
private int sex; //性别:0男,1女
private int[] hobby; //爱好,数组
private int city; //所属 城市
getter、setter...
}
UserBean中的性别、爱好和所属城市均使用int表示,但是在页面中,需要用字符串来展示每个int对应的内容(key/value),所以需要分别创建它们对应的javabean,下面以SexBean为例,其它与此完全类似:
Java代码
1.public class CityBean implements Serializable{
2. private static final long serialVersionUID = -6562852059776509594L;
3.
4. private int cityId;
5. private String cityValue;
6.
7. public CityBean(int cityId, String cityValue) {
8. super();
9. this.cityId = cityId;
10. this.cityValue = cityValue;
11. }
12.
13. getter、setter
14.}
public class CityBean implements Serializable{
private static final long serialVersionUID = -6562852059776509594L;
private int cityId;
private String cityValue;
public CityBean(int cityId, String cityValue) {
super();
this.cityId = cityId;
this.cityValue = cityValue;
}
getter、setter
}
然后编写一个TagsService,用于处理业务逻辑,供action调用:
Java代码
1.public class TagsService {
2.
3. /**
4. * Function : 获取城市的集合
5. */
6. public List<CityBean> getCitys()
7.
8. /**
9. * Function : 获取兴趣的集合
10. */
11. public List<HobbyBean> getHobbis()
12.
13. /**
14. * Function : 获取性别的集合
15. */
16. public List<SexBean> getSexs()
17.
18. /**
19. * Function : 获取被选中的兴趣爱好集合
20. */
21. public List<HobbyBean> getCheckedHobbies(int hobbies[])
22.
23. /**
24. * Function : 获取被选择的城市集合
25. */
26. public CityBean getSelectedCity(int cityId)
27.}
public class TagsService {
/**
* Function : 获取城市的集合
*/
public List<CityBean> getCitys()
/**
* Function : 获取兴趣的集合
*/
public List<HobbyBean> getHobbis()
/**
* Function : 获取性别的集合
*/
public List<SexBean> getSexs()
/**
* Function : 获取被选中的兴趣爱好集合
*/
public List<HobbyBean> getCheckedHobbies(int hobbies[])
/**
* Function : 获取被选择的城市集合
*/
public CityBean getSelectedCity(int cityId)
}
最后是mvc的核心Controller-TagsAction,有经验的人看了下面代码或许会觉得有些地方不合理,因为相同功能会有多种实现,我这是做例子,随后会告诉大家哪种方式会更好。
Java代码
1.public class TagsAction extends ActionSupport {
2. private static final long serialVersionUID = 4361410156958515185L;
3. private TagsService tagsService = new TagsService();
4.
5. //****formbean*****
6. private List<CityBean> lstCityBean;
7. private List<HobbyBean> lstHobbyBean;
8. private UserBean userBean;
9.
10. //*******action method***********
11. /**
12. * 进入表单填写页面
13. */
14. public String goIndex(){
15. userBean = new UserBean();
16. HttpServletRequest request = (HttpServletRequest) ActionContext.getContext().get(ServletActionContext.HTTP_REQUEST);
17. request.setAttribute("lstSexBean", tagsService.getSexs());
18. return SUCCESS;
19. }
20. /**
21. * Function : 提交表单
22. */
23. public String doSubmit(){
24. HttpServletRequest request = (HttpServletRequest) ActionContext.getContext().get(ServletActionContext.HTTP_REQUEST);
25. request.setAttribute("lstHobby", tagsService.getCheckedHobbies(userBean.getHobby()));
26. request.setAttribute("cityBean", tagsService.getSelectedCity(userBean.getCity()));
27. return SUCCESS;
28. }
29. /**
30. * Function : 验证表单数据
31. */
32. public void validateDoSubmit(){
33. if(userBean.getCity()<1){
34. this.addFieldError("userBean.city", "请选择城市!");
35. return;
36. }
37. }
38.
39. public List<CityBean> getLstCityBean() {
40. return tagsService.getCitys();
41. }
42.
43. public List<HobbyBean> getLstHobbyBean() {
44. return tagsService.getHobbis();
45. }
46.
47. gettter、setter........
48.}
public class TagsAction extends ActionSupport {
private static final long serialVersionUID = 4361410156958515185L;
private TagsService tagsService = new TagsService();
//****formbean*****
private List<CityBean> lstCityBean;
private List<HobbyBean> lstHobbyBean;
private UserBean userBean;
//*******action method***********
/**
* 进入表单填写页面
*/
public String goIndex(){
userBean = new UserBean();
HttpServletRequest request = (HttpServletRequest) ActionContext.getContext().get(ServletActionContext.HTTP_REQUEST);
request.setAttribute("lstSexBean", tagsService.getSexs());
return SUCCESS;
}
/**
* Function : 提交表单
*/
public String doSubmit(){
HttpServletRequest request = (HttpServletRequest) ActionContext.getContext().get(ServletActionContext.HTTP_REQUEST);
request.setAttribute("lstHobby", tagsService.getCheckedHobbies(userBean.getHobby()));
request.setAttribute("cityBean", tagsService.getSelectedCity(userBean.getCity()));
return SUCCESS;
}
/**
* Function : 验证表单数据
*/
public void validateDoSubmit(){
if(userBean.getCity()<1){
this.addFieldError("userBean.city", "请选择城市!");
return;
}
}
public List<CityBean> getLstCityBean() {
return tagsService.getCitys();
}
public List<HobbyBean> getLstHobbyBean() {
return tagsService.getHobbis();
}
gettter、setter........
}
•表单数据填写页面代码分析
要使用struts2标签,必须引用struts2的taglib
Java代码
1.<%@ taglib prefix="s" uri="/struts-tags"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
【表单数据填写页面】
Html代码
1.<body>
2. <h3>Debug标签</h3>
3. <s:debug></s:debug>
4. <hr/>
5. <h3>表单标签</h3>
6. <form action="<%=root%>/doSubmit.action" method="post">
7. <s:fielderror cssStyle="color:red"></s:fielderror>
8. <table>
9. <tr>
10. <td>编号:</td>
11. <td><s:textfield name="userBean.userId"/></td>
12. </tr>
13. <tr>
14. <td>姓名:</td>
15. <td><s:textfield name="userBean.userName"></s:textfield></td>
16. </tr>
17. <tr>
18. <td>密码:</td>
19. <td><s:password name="userBean.password"></s:password></td>
20. </tr>
21. <tr>
22. <td>生日:</td>
23. <td>
24. <s:textfield name="userBean.birthday">
25. <s:param name="value">
26. <s:date name="userBean.birthday" format="yyyy-MM-dd hh:MM:ss" />
27. </s:param>
28. </s:textfield>
29. </td>
30. </tr>
31. <tr>
32. <td>性别:</td>
33. <td><s:radio name="userBean.sex" list="#request.lstSexBean" listKey="sexId" listValue="sexValue"></s:radio></td>
34. </tr>
35. <tr>
36. <td>城市:</td>
37. <td><s:select name="userBean.city" list="lstCityBean" listKey="cityId" listValue="cityValue" headerKey="0" headerValue="--请选择--"></s:select></td>
38. </tr>
39. <tr>
40. <td>爱好:</td>
41. <td><s:checkboxlist name="userBean.hobby" list="lstHobbyBean" listKey="hobbyId" listValue="hobbyValue"></s:checkboxlist></td>
42. </tr>
43. <tr>
44. <s:hidden></s:hidden>
45. <td><s:submit value="提交"/></td>
46. <td><s:reset value="重置"/></td>
47. </tr>
48. </table>
49. </form>
50.
51.</body>
<body>
<h3>Debug标签</h3>
<s:debug></s:debug>
<hr/>
<h3>表单标签</h3>
<form action="<%=root%>/doSubmit.action" method="post">
<s:fielderror cssStyle="color:red"></s:fielderror>
<table>
<tr>
<td>编号:</td>
<td><s:textfield name="userBean.userId"/></td>
</tr>
<tr>
<td>姓名:</td>
<td><s:textfield name="userBean.userName"></s:textfield></td>
</tr>
<tr>
<td>密码:</td>
<td><s:password name="userBean.password"></s:password></td>
</tr>
<tr>
<td>生日:</td>
<td>
<s:textfield name="userBean.birthday">
<s:param name="value">
<s:date name="userBean.birthday" format="yyyy-MM-dd hh:MM:ss" />
</s:param>
</s:textfield>
</td>
</tr>
<tr>
<td>性别:</td>
<td><s:radio name="userBean.sex" list="#request.lstSexBean" listKey="sexId" listValue="sexValue"></s:radio></td>
</tr>
<tr>
<td>城市:</td>
<td><s:select name="userBean.city" list="lstCityBean" listKey="cityId" listValue="cityValue" headerKey="0" headerValue="--请选择--"></s:select></td>
</tr>
<tr>
<td>爱好:</td>
<td><s:checkboxlist name="userBean.hobby" list="lstHobbyBean" listKey="hobbyId" listValue="hobbyValue"></s:checkboxlist></td>
</tr>
<tr>
<s:hidden></s:hidden>
<td><s:submit value="提交"/></td>
<td><s:reset value="重置"/></td>
</tr>
</table>
</form>
</body>
<s:textfield>标签:文本框标签,可填写文本内容,同时该标签含有很多有用的属性:
readonly 只读属性
disabled 可用/不可用属性,如果设置为不可用在提交表单的时候该文本框的值不会传到后台
cssClass 指定css的class
cssStyle 自定义css样式
maxlength 文本框可输入的文字个数
tooltip 冒泡提示
上面只是一小部分属性,另外还有各种事件属性:
<s:password>标签:密码框标签,其附带的属性与textfield相似
<s:textarea>标签:定义多行的文本输入控件,其核心属性cols和rows分别指定文本域的宽度和高度
<s:date>标签:时间显示标签,用于显示指定格式的时间对象,很多人不知道如何在文本框中显示指定日期格式,大家可以参考通过<s:textfield>+<s:date>的形式:
Java代码
1.<s:textfield name="userBean.birthday">
2. <s:param name="value">
3. <s:date name="userBean.birthday" format="yyyy-MM-dd hh:MM:ss" />
4. </s:param>
5.</s:textfield>
<s:textfield name="userBean.birthday">
<s:param name="value">
<s:date name="userBean.birthday" format="yyyy-MM-dd hh:MM:ss" />
</s:param>
</s:textfield> <s:radio>标签:单选按钮,该控件依然采用key/value的形式处理数据,即key值传到后台,value值显示给用户,结合上面的例子,我们知道性别男的key=0,value="男",性别女的key=1,value="女",这就是为什么在后台将性别以SexBean这种javabean的形式来存储。开发用struts2的<s:radio>标签展示单选按钮完全是傻瓜式的操作:设置需要显示的数据集合(collection或array),设置key和value,如下面的代码:
Html代码
1.<s:radio name="userBean.sex" list="#request.lstSexBean" listKey="sexId" listValue="sexValue"></s:radio>
<s:radio name="userBean.sex" list="#request.lstSexBean" listKey="sexId" listValue="sexValue"></s:radio> 注意list就是从后台获取的集合数据,listKey的值最终会赋给name="userBean.sex",listValue用于显示给用户。
从后台向页面传list数据有多种方式,第一种方法是通过request.setAttribut的形式:
Java代码
1.request.setAttribute("lstSexBean", tagsService.getSexs());
request.setAttribute("lstSexBean", tagsService.getSexs()); 第二种更加好些,这也是个人推荐的:首先在action中定义一个集合formbean,设置formbean的get方法,然后重写get方法,返回集合数据:
Java代码
1.private List<SexBean> lstSexBean;
2. public List<SexBean> getLstSexBean(){
3. return tagsService.getSexs();
4. }
private List<SexBean> lstSexBean;
public List<SexBean> getLstSexBean(){
return tagsService.getSexs();
} 其实<s:radio>最后还是转换成html的radio标签显示内容,我们可以看看通过<s:radio>转换后的代码:
Html代码
1.<input type="radio" name="userBean.sex" id="userBean_sex0" checked="checked" value="0"/><label for="userBean_sex0">男</label>
2.<input type="radio" name="userBean.sex" id="userBean_sex1" value="1"/><label for="userBean_sex1">女</label>
<input type="radio" name="userBean.sex" id="userBean_sex0" checked="checked" value="0"/><label for="userBean_sex0">男</label>
<input type="radio" name="userBean.sex" id="userBean_sex1" value="1"/><label for="userBean_sex1">女</label> <s:select>标签:下拉列表,该标签的使用方法跟<s:radio>标签完全类似,另外可以通过headerKey和headerValue属性设置下拉列表默认值和显示的内容
<s:select>转换成普通html后的代码:
Html代码
1.<select name="userBean.city" id="userBean_city">
2. <option value="0"
3. selected="selected"
4. >--请选择--</option>
5. <option value="1">北京</option>
6. <option value="2">上海</option>
7. <option value="3">广州</option>
8. <option value="4">成都</option>
9. <option value="5">深圳</option>
10.</select>
<select name="userBean.city" id="userBean_city">
<option value="0"
selected="selected"
>--请选择--</option>
<option value="1">北京</option>
<option value="2">上海</option>
<option value="3">广州</option>
<option value="4">成都</option>
<option value="5">深圳</option>
</select> <s:checkboxlist>标签:复选标签,该标签的使用方法跟<s:radio>标签完全类似
<s:checkboxlist>转换成普通html后的代码:
Html代码
1.<input type="checkbox" name="userBean.hobby" value="1" id="userBean.hobby-1"/>
2.<label for="userBean.hobby-1" class="checkboxLabel">唱歌</label>
3.<input type="checkbox" name="userBean.hobby" value="2" id="userBean.hobby-2"/>
4.<label for="userBean.hobby-2" class="checkboxLabel">跳舞</label>
5.<input type="checkbox" name="userBean.hobby" value="3" id="userBean.hobby-3"/>
6.<label for="userBean.hobby-3" class="checkboxLabel">运动</label>
7.<input type="checkbox" name="userBean.hobby" value="4" id="userBean.hobby-4"/>
8.<label for="userBean.hobby-4" class="checkboxLabel">旅游</label>
9.<input type="checkbox" name="userBean.hobby" value="5" id="userBean.hobby-5"/>
10.<label for="userBean.hobby-5" class="checkboxLabel">宅神</label>
11.<input type="hidden" id="__multiselect_userBean_hobby" name="__multiselect_userBean.hobby" value="" />
<input type="checkbox" name="userBean.hobby" value="1" id="userBean.hobby-1"/>
<label for="userBean.hobby-1" class="checkboxLabel">唱歌</label>
<input type="checkbox" name="userBean.hobby" value="2" id="userBean.hobby-2"/>
<label for="userBean.hobby-2" class="checkboxLabel">跳舞</label>
<input type="checkbox" name="userBean.hobby" value="3" id="userBean.hobby-3"/>
<label for="userBean.hobby-3" class="checkboxLabel">运动</label>
<input type="checkbox" name="userBean.hobby" value="4" id="userBean.hobby-4"/>
<label for="userBean.hobby-4" class="checkboxLabel">旅游</label>
<input type="checkbox" name="userBean.hobby" value="5" id="userBean.hobby-5"/>
<label for="userBean.hobby-5" class="checkboxLabel">宅神</label>
<input type="hidden" id="__multiselect_userBean_hobby" name="__multiselect_userBean.hobby" value="" /> <s:hidden>标签:隐藏标签,可以设置变量值,但是不在页面显示
<s:submit>标签:表单提交按钮
<s:reset>标签:表单重置按钮
<s:debug>标签:struts2独有的调试标签,在开发中使用,可以在页面看到值栈中的所有信息,方便调试。
•提交后显示的页面
点击提交按钮后,经过后台处理,数据传到另一个jsp显示:
Html代码
1.<body>
2. <table>
3. <tr>
4. <td>编号:</td>
5. <td><s:property value="userBean.userId"></s:property></td>
6. </tr>
7. <tr>
8. <td>姓名:</td>
9. <td><s:property value="userBean.userName"></s:property></td>
10. </tr>
11. <tr>
12. <td>密码:</td>
13. <td><s:property value="userBean.password"></s:property></td>
14. </tr>
15. <tr>
16. <td>生日:</td>
17. <td><s:date name="userBean.birthday" format="yyyy-MM-dd hh:MM:ss" /></td>
18. </tr>
19. <tr>
20. <td>性别:</td>
21. <td>
22. <s:if test="userBean.sex==0">
23. 男
24. </s:if>
25. <s:else>
26. 女
27. </s:else>
28. </td>
29. </tr>
30. <tr>
31. <td>城市:</td>
32. <td>
33. <s:property value="#request.cityBean.cityValue"/>
34. </td>
35. </tr>
36. <tr>
37. <td>爱好:</td>
38. <td>
39. <s:if test="#request.lstHobby!=null">
40. <s:iterator value="#request.lstHobby" var="hobby" status="index" begin="0" end="#request.lstHobby.length-1">
41. 第[<s:property value="%{#attr.index.index+1}"/>]条爱好:<s:property value="%{#attr.hobby.hobbyValue}"/><br/>
42. </s:iterator>
43. </s:if>
44. </td>
45. </tr>
46. </table>
47.</body>
<body>
<table>
<tr>
<td>编号:</td>
<td><s:property value="userBean.userId"></s:property></td>
</tr>
<tr>
<td>姓名:</td>
<td><s:property value="userBean.userName"></s:property></td>
</tr>
<tr>
<td>密码:</td>
<td><s:property value="userBean.password"></s:property></td>
</tr>
<tr>
<td>生日:</td>
<td><s:date name="userBean.birthday" format="yyyy-MM-dd hh:MM:ss" /></td>
</tr>
<tr>
<td>性别:</td>
<td>
<s:if test="userBean.sex==0">
男
</s:if>
<s:else>
女
</s:else>
</td>
</tr>
<tr>
<td>城市:</td>
<td>
<s:property value="#request.cityBean.cityValue"/>
</td>
</tr>
<tr>
<td>爱好:</td>
<td>
<s:if test="#request.lstHobby!=null">
<s:iterator value="#request.lstHobby" var="hobby" status="index" begin="0" end="#request.lstHobby.length-1">
第[<s:property value="%{#attr.index.index+1}"/>]条爱好:<s:property value="%{#attr.hobby.hobbyValue}"/><br/>
</s:iterator>
</s:if>
</td>
</tr>
</table>
</body> <s:property>标签:用于显示变量值的标签,没有什么可说的
<s:if><s:elseif><s:else>标签:这三个标签结合使用就能实现java的if...elseif...else的逻辑操作,标签中的test属性用于分之条件判断。
<s:iterator>标签:迭代标签,这个标签的功能类似于java的for循环操作,value属性装的是集合对象,var属性是集合中的某一对象,status表示迭代的次数,begin和end表示循环开始位置和结束位置。最后看上面例子的代码:
Html代码
1.<s:iterator value="#request.lstHobby" var="hobby" status="index" begin="0" end="#request.lstHobby.length-1">
2.<SPAN style="WHITE-SPACE: pre"> </SPAN>第[<s:property value="%{#attr.index.index+1}"/>]条爱好:<s:property value="%{#attr.hobby.hobbyValue}"/><br/>
3.</s:iterator>
<s:iterator value="#request.lstHobby" var="hobby" status="index" begin="0" end="#request.lstHobby.length-1">
第[<s:property value="%{#attr.index.index+1}"/>]条爱好:<s:property value="%{#attr.hobby.hobbyValue}"/><br/>
</s:iterator>
•OGNL简介
OGNL是一个功能强大的EL,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能,它使用相同的表达式去存取对象的属性。
之所以命名为OGNL,就是因为它处理对象很给力,struts能够将对象层层解析,把各个对象的关系以图的样式展示出来。比如userBean.userId,之所以能找到这个对象,就是因为OGNL会先找userBean对象,然后再找userBean对象里的userId属性。假设UserBean这个类还包含了名为Role的javabean的实例,Role里面包含字段roleName,我们要找到roleName就可以直接写<s:property value="user.role.roleName">,OGNL通过对象逐级导航找到子对象。
•实例场景
假设有这样一个网站:需要用户填写个人的信息,包括:编号、姓名、密码、生日、性别、城市、爱好。其中编号需要填入整数,姓名是字符串,密码在页面中必须以密码框的形式显示,生日必须是日期格式,性别单选,城市用下拉列表选择,爱好复选框可以多选。那么用户填写完信息以后,点击“提交”按钮,到下一个页面显示用户填写的信息。
•需求分析
这是一个非常常见的需求,里面囊括了整形、字符串和日期类型等处理,另外用到了文本框、密码框、单选、复选和下拉列表等控件。
如果采用servlet/jsp的开发模式是可以实现该功能的,但是很多地方可能需要一些复杂处理,比如用户点击提交到后台需要通过request.getParameter的形式把页面的字段逐个取出来解析;单选、复选和下拉列表中的数据需要使用jsp代码逐个迭代显示;如果加上表单验证的话,这又需要花费更大的精力。
struts2提供了一整套的自定义标签解决方案,其功能在原生html标签基础上做了很大的改进:控件的name属性可以采用对象图的形式定义,点击提交按钮通过拦截器自动封装属性,这样在后台就不需要用request获取每个属性字段了;struts2对的单选、复选和下拉列表等控件进行了改进,开发人员只需要用一行代码设置集合数据和key/value即可显示出与html同样功能的组件;同时它提供了独有的错误显示标签,用于显示验证不通过的错误信息,非常方便。
•实例效果
按照我的习惯,我首先把运行的效果展示出来,再根据效果分析每个功能的具体实现。
【表单数据填写页面】
【验证不通过显示的错误消息】
【提交成功后的页面】
•后台java代码
为了减少大家看代码的疲惫感,我尽量将每个类的核心内容展示出来,具体的代码实现在此就省略掉,如果需要全部代码,可在附件中下载。
首先创建一个UserBean存放用户信息,这是一个javabean:
Java代码
1.public class UserBean implements Serializable{
2. private static final long serialVersionUID = -5808037703808170288L;
3.
4. private int userId; //编号
5. private String userName; //姓名
6. private String password; //密码
7. private Date birthday = new Date(); //生日:格式yyyy-MM-dd,默认为当前时间
8. private int sex; //性别:0男,1女
9. private int[] hobby; //爱好,数组
10. private int city; //所属 城市
11.
12. getter、setter...
13.}
public class UserBean implements Serializable{
private static final long serialVersionUID = -5808037703808170288L;
private int userId; //编号
private String userName; //姓名
private String password; //密码
private Date birthday = new Date(); //生日:格式yyyy-MM-dd,默认为当前时间
private int sex; //性别:0男,1女
private int[] hobby; //爱好,数组
private int city; //所属 城市
getter、setter...
}
UserBean中的性别、爱好和所属城市均使用int表示,但是在页面中,需要用字符串来展示每个int对应的内容(key/value),所以需要分别创建它们对应的javabean,下面以SexBean为例,其它与此完全类似:
Java代码
1.public class CityBean implements Serializable{
2. private static final long serialVersionUID = -6562852059776509594L;
3.
4. private int cityId;
5. private String cityValue;
6.
7. public CityBean(int cityId, String cityValue) {
8. super();
9. this.cityId = cityId;
10. this.cityValue = cityValue;
11. }
12.
13. getter、setter
14.}
public class CityBean implements Serializable{
private static final long serialVersionUID = -6562852059776509594L;
private int cityId;
private String cityValue;
public CityBean(int cityId, String cityValue) {
super();
this.cityId = cityId;
this.cityValue = cityValue;
}
getter、setter
}
然后编写一个TagsService,用于处理业务逻辑,供action调用:
Java代码
1.public class TagsService {
2.
3. /**
4. * Function : 获取城市的集合
5. */
6. public List<CityBean> getCitys()
7.
8. /**
9. * Function : 获取兴趣的集合
10. */
11. public List<HobbyBean> getHobbis()
12.
13. /**
14. * Function : 获取性别的集合
15. */
16. public List<SexBean> getSexs()
17.
18. /**
19. * Function : 获取被选中的兴趣爱好集合
20. */
21. public List<HobbyBean> getCheckedHobbies(int hobbies[])
22.
23. /**
24. * Function : 获取被选择的城市集合
25. */
26. public CityBean getSelectedCity(int cityId)
27.}
public class TagsService {
/**
* Function : 获取城市的集合
*/
public List<CityBean> getCitys()
/**
* Function : 获取兴趣的集合
*/
public List<HobbyBean> getHobbis()
/**
* Function : 获取性别的集合
*/
public List<SexBean> getSexs()
/**
* Function : 获取被选中的兴趣爱好集合
*/
public List<HobbyBean> getCheckedHobbies(int hobbies[])
/**
* Function : 获取被选择的城市集合
*/
public CityBean getSelectedCity(int cityId)
}
最后是mvc的核心Controller-TagsAction,有经验的人看了下面代码或许会觉得有些地方不合理,因为相同功能会有多种实现,我这是做例子,随后会告诉大家哪种方式会更好。
Java代码
1.public class TagsAction extends ActionSupport {
2. private static final long serialVersionUID = 4361410156958515185L;
3. private TagsService tagsService = new TagsService();
4.
5. //****formbean*****
6. private List<CityBean> lstCityBean;
7. private List<HobbyBean> lstHobbyBean;
8. private UserBean userBean;
9.
10. //*******action method***********
11. /**
12. * 进入表单填写页面
13. */
14. public String goIndex(){
15. userBean = new UserBean();
16. HttpServletRequest request = (HttpServletRequest) ActionContext.getContext().get(ServletActionContext.HTTP_REQUEST);
17. request.setAttribute("lstSexBean", tagsService.getSexs());
18. return SUCCESS;
19. }
20. /**
21. * Function : 提交表单
22. */
23. public String doSubmit(){
24. HttpServletRequest request = (HttpServletRequest) ActionContext.getContext().get(ServletActionContext.HTTP_REQUEST);
25. request.setAttribute("lstHobby", tagsService.getCheckedHobbies(userBean.getHobby()));
26. request.setAttribute("cityBean", tagsService.getSelectedCity(userBean.getCity()));
27. return SUCCESS;
28. }
29. /**
30. * Function : 验证表单数据
31. */
32. public void validateDoSubmit(){
33. if(userBean.getCity()<1){
34. this.addFieldError("userBean.city", "请选择城市!");
35. return;
36. }
37. }
38.
39. public List<CityBean> getLstCityBean() {
40. return tagsService.getCitys();
41. }
42.
43. public List<HobbyBean> getLstHobbyBean() {
44. return tagsService.getHobbis();
45. }
46.
47. gettter、setter........
48.}
public class TagsAction extends ActionSupport {
private static final long serialVersionUID = 4361410156958515185L;
private TagsService tagsService = new TagsService();
//****formbean*****
private List<CityBean> lstCityBean;
private List<HobbyBean> lstHobbyBean;
private UserBean userBean;
//*******action method***********
/**
* 进入表单填写页面
*/
public String goIndex(){
userBean = new UserBean();
HttpServletRequest request = (HttpServletRequest) ActionContext.getContext().get(ServletActionContext.HTTP_REQUEST);
request.setAttribute("lstSexBean", tagsService.getSexs());
return SUCCESS;
}
/**
* Function : 提交表单
*/
public String doSubmit(){
HttpServletRequest request = (HttpServletRequest) ActionContext.getContext().get(ServletActionContext.HTTP_REQUEST);
request.setAttribute("lstHobby", tagsService.getCheckedHobbies(userBean.getHobby()));
request.setAttribute("cityBean", tagsService.getSelectedCity(userBean.getCity()));
return SUCCESS;
}
/**
* Function : 验证表单数据
*/
public void validateDoSubmit(){
if(userBean.getCity()<1){
this.addFieldError("userBean.city", "请选择城市!");
return;
}
}
public List<CityBean> getLstCityBean() {
return tagsService.getCitys();
}
public List<HobbyBean> getLstHobbyBean() {
return tagsService.getHobbis();
}
gettter、setter........
}
•表单数据填写页面代码分析
要使用struts2标签,必须引用struts2的taglib
Java代码
1.<%@ taglib prefix="s" uri="/struts-tags"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
【表单数据填写页面】
Html代码
1.<body>
2. <h3>Debug标签</h3>
3. <s:debug></s:debug>
4. <hr/>
5. <h3>表单标签</h3>
6. <form action="<%=root%>/doSubmit.action" method="post">
7. <s:fielderror cssStyle="color:red"></s:fielderror>
8. <table>
9. <tr>
10. <td>编号:</td>
11. <td><s:textfield name="userBean.userId"/></td>
12. </tr>
13. <tr>
14. <td>姓名:</td>
15. <td><s:textfield name="userBean.userName"></s:textfield></td>
16. </tr>
17. <tr>
18. <td>密码:</td>
19. <td><s:password name="userBean.password"></s:password></td>
20. </tr>
21. <tr>
22. <td>生日:</td>
23. <td>
24. <s:textfield name="userBean.birthday">
25. <s:param name="value">
26. <s:date name="userBean.birthday" format="yyyy-MM-dd hh:MM:ss" />
27. </s:param>
28. </s:textfield>
29. </td>
30. </tr>
31. <tr>
32. <td>性别:</td>
33. <td><s:radio name="userBean.sex" list="#request.lstSexBean" listKey="sexId" listValue="sexValue"></s:radio></td>
34. </tr>
35. <tr>
36. <td>城市:</td>
37. <td><s:select name="userBean.city" list="lstCityBean" listKey="cityId" listValue="cityValue" headerKey="0" headerValue="--请选择--"></s:select></td>
38. </tr>
39. <tr>
40. <td>爱好:</td>
41. <td><s:checkboxlist name="userBean.hobby" list="lstHobbyBean" listKey="hobbyId" listValue="hobbyValue"></s:checkboxlist></td>
42. </tr>
43. <tr>
44. <s:hidden></s:hidden>
45. <td><s:submit value="提交"/></td>
46. <td><s:reset value="重置"/></td>
47. </tr>
48. </table>
49. </form>
50.
51.</body>
<body>
<h3>Debug标签</h3>
<s:debug></s:debug>
<hr/>
<h3>表单标签</h3>
<form action="<%=root%>/doSubmit.action" method="post">
<s:fielderror cssStyle="color:red"></s:fielderror>
<table>
<tr>
<td>编号:</td>
<td><s:textfield name="userBean.userId"/></td>
</tr>
<tr>
<td>姓名:</td>
<td><s:textfield name="userBean.userName"></s:textfield></td>
</tr>
<tr>
<td>密码:</td>
<td><s:password name="userBean.password"></s:password></td>
</tr>
<tr>
<td>生日:</td>
<td>
<s:textfield name="userBean.birthday">
<s:param name="value">
<s:date name="userBean.birthday" format="yyyy-MM-dd hh:MM:ss" />
</s:param>
</s:textfield>
</td>
</tr>
<tr>
<td>性别:</td>
<td><s:radio name="userBean.sex" list="#request.lstSexBean" listKey="sexId" listValue="sexValue"></s:radio></td>
</tr>
<tr>
<td>城市:</td>
<td><s:select name="userBean.city" list="lstCityBean" listKey="cityId" listValue="cityValue" headerKey="0" headerValue="--请选择--"></s:select></td>
</tr>
<tr>
<td>爱好:</td>
<td><s:checkboxlist name="userBean.hobby" list="lstHobbyBean" listKey="hobbyId" listValue="hobbyValue"></s:checkboxlist></td>
</tr>
<tr>
<s:hidden></s:hidden>
<td><s:submit value="提交"/></td>
<td><s:reset value="重置"/></td>
</tr>
</table>
</form>
</body>
<s:textfield>标签:文本框标签,可填写文本内容,同时该标签含有很多有用的属性:
readonly 只读属性
disabled 可用/不可用属性,如果设置为不可用在提交表单的时候该文本框的值不会传到后台
cssClass 指定css的class
cssStyle 自定义css样式
maxlength 文本框可输入的文字个数
tooltip 冒泡提示
上面只是一小部分属性,另外还有各种事件属性:
<s:password>标签:密码框标签,其附带的属性与textfield相似
<s:textarea>标签:定义多行的文本输入控件,其核心属性cols和rows分别指定文本域的宽度和高度
<s:date>标签:时间显示标签,用于显示指定格式的时间对象,很多人不知道如何在文本框中显示指定日期格式,大家可以参考通过<s:textfield>+<s:date>的形式:
Java代码
1.<s:textfield name="userBean.birthday">
2. <s:param name="value">
3. <s:date name="userBean.birthday" format="yyyy-MM-dd hh:MM:ss" />
4. </s:param>
5.</s:textfield>
<s:textfield name="userBean.birthday">
<s:param name="value">
<s:date name="userBean.birthday" format="yyyy-MM-dd hh:MM:ss" />
</s:param>
</s:textfield> <s:radio>标签:单选按钮,该控件依然采用key/value的形式处理数据,即key值传到后台,value值显示给用户,结合上面的例子,我们知道性别男的key=0,value="男",性别女的key=1,value="女",这就是为什么在后台将性别以SexBean这种javabean的形式来存储。开发用struts2的<s:radio>标签展示单选按钮完全是傻瓜式的操作:设置需要显示的数据集合(collection或array),设置key和value,如下面的代码:
Html代码
1.<s:radio name="userBean.sex" list="#request.lstSexBean" listKey="sexId" listValue="sexValue"></s:radio>
<s:radio name="userBean.sex" list="#request.lstSexBean" listKey="sexId" listValue="sexValue"></s:radio> 注意list就是从后台获取的集合数据,listKey的值最终会赋给name="userBean.sex",listValue用于显示给用户。
从后台向页面传list数据有多种方式,第一种方法是通过request.setAttribut的形式:
Java代码
1.request.setAttribute("lstSexBean", tagsService.getSexs());
request.setAttribute("lstSexBean", tagsService.getSexs()); 第二种更加好些,这也是个人推荐的:首先在action中定义一个集合formbean,设置formbean的get方法,然后重写get方法,返回集合数据:
Java代码
1.private List<SexBean> lstSexBean;
2. public List<SexBean> getLstSexBean(){
3. return tagsService.getSexs();
4. }
private List<SexBean> lstSexBean;
public List<SexBean> getLstSexBean(){
return tagsService.getSexs();
} 其实<s:radio>最后还是转换成html的radio标签显示内容,我们可以看看通过<s:radio>转换后的代码:
Html代码
1.<input type="radio" name="userBean.sex" id="userBean_sex0" checked="checked" value="0"/><label for="userBean_sex0">男</label>
2.<input type="radio" name="userBean.sex" id="userBean_sex1" value="1"/><label for="userBean_sex1">女</label>
<input type="radio" name="userBean.sex" id="userBean_sex0" checked="checked" value="0"/><label for="userBean_sex0">男</label>
<input type="radio" name="userBean.sex" id="userBean_sex1" value="1"/><label for="userBean_sex1">女</label> <s:select>标签:下拉列表,该标签的使用方法跟<s:radio>标签完全类似,另外可以通过headerKey和headerValue属性设置下拉列表默认值和显示的内容
<s:select>转换成普通html后的代码:
Html代码
1.<select name="userBean.city" id="userBean_city">
2. <option value="0"
3. selected="selected"
4. >--请选择--</option>
5. <option value="1">北京</option>
6. <option value="2">上海</option>
7. <option value="3">广州</option>
8. <option value="4">成都</option>
9. <option value="5">深圳</option>
10.</select>
<select name="userBean.city" id="userBean_city">
<option value="0"
selected="selected"
>--请选择--</option>
<option value="1">北京</option>
<option value="2">上海</option>
<option value="3">广州</option>
<option value="4">成都</option>
<option value="5">深圳</option>
</select> <s:checkboxlist>标签:复选标签,该标签的使用方法跟<s:radio>标签完全类似
<s:checkboxlist>转换成普通html后的代码:
Html代码
1.<input type="checkbox" name="userBean.hobby" value="1" id="userBean.hobby-1"/>
2.<label for="userBean.hobby-1" class="checkboxLabel">唱歌</label>
3.<input type="checkbox" name="userBean.hobby" value="2" id="userBean.hobby-2"/>
4.<label for="userBean.hobby-2" class="checkboxLabel">跳舞</label>
5.<input type="checkbox" name="userBean.hobby" value="3" id="userBean.hobby-3"/>
6.<label for="userBean.hobby-3" class="checkboxLabel">运动</label>
7.<input type="checkbox" name="userBean.hobby" value="4" id="userBean.hobby-4"/>
8.<label for="userBean.hobby-4" class="checkboxLabel">旅游</label>
9.<input type="checkbox" name="userBean.hobby" value="5" id="userBean.hobby-5"/>
10.<label for="userBean.hobby-5" class="checkboxLabel">宅神</label>
11.<input type="hidden" id="__multiselect_userBean_hobby" name="__multiselect_userBean.hobby" value="" />
<input type="checkbox" name="userBean.hobby" value="1" id="userBean.hobby-1"/>
<label for="userBean.hobby-1" class="checkboxLabel">唱歌</label>
<input type="checkbox" name="userBean.hobby" value="2" id="userBean.hobby-2"/>
<label for="userBean.hobby-2" class="checkboxLabel">跳舞</label>
<input type="checkbox" name="userBean.hobby" value="3" id="userBean.hobby-3"/>
<label for="userBean.hobby-3" class="checkboxLabel">运动</label>
<input type="checkbox" name="userBean.hobby" value="4" id="userBean.hobby-4"/>
<label for="userBean.hobby-4" class="checkboxLabel">旅游</label>
<input type="checkbox" name="userBean.hobby" value="5" id="userBean.hobby-5"/>
<label for="userBean.hobby-5" class="checkboxLabel">宅神</label>
<input type="hidden" id="__multiselect_userBean_hobby" name="__multiselect_userBean.hobby" value="" /> <s:hidden>标签:隐藏标签,可以设置变量值,但是不在页面显示
<s:submit>标签:表单提交按钮
<s:reset>标签:表单重置按钮
<s:debug>标签:struts2独有的调试标签,在开发中使用,可以在页面看到值栈中的所有信息,方便调试。
•提交后显示的页面
点击提交按钮后,经过后台处理,数据传到另一个jsp显示:
Html代码
1.<body>
2. <table>
3. <tr>
4. <td>编号:</td>
5. <td><s:property value="userBean.userId"></s:property></td>
6. </tr>
7. <tr>
8. <td>姓名:</td>
9. <td><s:property value="userBean.userName"></s:property></td>
10. </tr>
11. <tr>
12. <td>密码:</td>
13. <td><s:property value="userBean.password"></s:property></td>
14. </tr>
15. <tr>
16. <td>生日:</td>
17. <td><s:date name="userBean.birthday" format="yyyy-MM-dd hh:MM:ss" /></td>
18. </tr>
19. <tr>
20. <td>性别:</td>
21. <td>
22. <s:if test="userBean.sex==0">
23. 男
24. </s:if>
25. <s:else>
26. 女
27. </s:else>
28. </td>
29. </tr>
30. <tr>
31. <td>城市:</td>
32. <td>
33. <s:property value="#request.cityBean.cityValue"/>
34. </td>
35. </tr>
36. <tr>
37. <td>爱好:</td>
38. <td>
39. <s:if test="#request.lstHobby!=null">
40. <s:iterator value="#request.lstHobby" var="hobby" status="index" begin="0" end="#request.lstHobby.length-1">
41. 第[<s:property value="%{#attr.index.index+1}"/>]条爱好:<s:property value="%{#attr.hobby.hobbyValue}"/><br/>
42. </s:iterator>
43. </s:if>
44. </td>
45. </tr>
46. </table>
47.</body>
<body>
<table>
<tr>
<td>编号:</td>
<td><s:property value="userBean.userId"></s:property></td>
</tr>
<tr>
<td>姓名:</td>
<td><s:property value="userBean.userName"></s:property></td>
</tr>
<tr>
<td>密码:</td>
<td><s:property value="userBean.password"></s:property></td>
</tr>
<tr>
<td>生日:</td>
<td><s:date name="userBean.birthday" format="yyyy-MM-dd hh:MM:ss" /></td>
</tr>
<tr>
<td>性别:</td>
<td>
<s:if test="userBean.sex==0">
男
</s:if>
<s:else>
女
</s:else>
</td>
</tr>
<tr>
<td>城市:</td>
<td>
<s:property value="#request.cityBean.cityValue"/>
</td>
</tr>
<tr>
<td>爱好:</td>
<td>
<s:if test="#request.lstHobby!=null">
<s:iterator value="#request.lstHobby" var="hobby" status="index" begin="0" end="#request.lstHobby.length-1">
第[<s:property value="%{#attr.index.index+1}"/>]条爱好:<s:property value="%{#attr.hobby.hobbyValue}"/><br/>
</s:iterator>
</s:if>
</td>
</tr>
</table>
</body> <s:property>标签:用于显示变量值的标签,没有什么可说的
<s:if><s:elseif><s:else>标签:这三个标签结合使用就能实现java的if...elseif...else的逻辑操作,标签中的test属性用于分之条件判断。
<s:iterator>标签:迭代标签,这个标签的功能类似于java的for循环操作,value属性装的是集合对象,var属性是集合中的某一对象,status表示迭代的次数,begin和end表示循环开始位置和结束位置。最后看上面例子的代码:
Html代码
1.<s:iterator value="#request.lstHobby" var="hobby" status="index" begin="0" end="#request.lstHobby.length-1">
2.<SPAN style="WHITE-SPACE: pre"> </SPAN>第[<s:property value="%{#attr.index.index+1}"/>]条爱好:<s:property value="%{#attr.hobby.hobbyValue}"/><br/>
3.</s:iterator>
<s:iterator value="#request.lstHobby" var="hobby" status="index" begin="0" end="#request.lstHobby.length-1">
第[<s:property value="%{#attr.index.index+1}"/>]条爱好:<s:property value="%{#attr.hobby.hobbyValue}"/><br/>
</s:iterator>
•OGNL简介
OGNL是一个功能强大的EL,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能,它使用相同的表达式去存取对象的属性。
之所以命名为OGNL,就是因为它处理对象很给力,struts能够将对象层层解析,把各个对象的关系以图的样式展示出来。比如userBean.userId,之所以能找到这个对象,就是因为OGNL会先找userBean对象,然后再找userBean对象里的userId属性。假设UserBean这个类还包含了名为Role的javabean的实例,Role里面包含字段roleName,我们要找到roleName就可以直接写<s:property value="user.role.roleName">,OGNL通过对象逐级导航找到子对象。
相关推荐
在Struts2框架中,标签库是其一大特色,它提供了丰富的自定义标签,使得开发者能够更加便捷地创建动态页面。这些标签极大地简化了JSP页面的编写,提高了代码的可读性和可维护性。 1. **Struts2核心标签库**: - `s...
Struts2 标签库详解 Struts2 提供了一个强大的标签库,用于简化 Web 应用程序的开发过程。这些标签可以分为两类:通用标签和 UI 标签。下面,我们将详细介绍 Struts2 标签库的使用。 4.1 通用标签 通用标签用来...
Struts2标签是Java开发中一个非常重要的工具,它极大地简化了MVC框架下的视图层构建,使得开发者能够更加高效地实现动态网页。在Struts2框架中,标签库是一系列预定义的JSP标签,它们提供了丰富的功能,如数据绑定、...
Struts 2 标签的使用注意事项 Struts 2 是一个基于MVC架构的Java Web应用程序框架,它提供了一系列的标签来简化Web开发。然而,在使用Struts 2标签时,需要注意一些重要的事项。 首先,在使用Struts 2标签之前,...
"Struts2标签库详解" Struts2标签库是Struts2框架中的一个重要组件,它提供了一系列的标签,帮助开发者快速构建Web应用程序。在Struts2标签库中,标签可以分为UI标签和非UI标签两大类。UI标签用于生成HTML控件,如...
在Struts2框架中,标签库是其重要组成部分,它提供了丰富的标签来帮助开发者更方便地构建用户界面。下面我们将深入探讨Struts2标签的使用及其API文档。 1. **Struts2标签的分类与功能** - **控制标签**:如`s:if`,...
在Struts2中,标签库是其核心特性之一,它提供了一系列预定义的JSP标签,用于简化视图层的编码,提高代码的可读性和可维护性。下面我们将详细探讨Struts2标签的使用方法以及EL(Expression Language)表达式。 1. *...
2. **Struts2标签**:Struts2提供了一系列自定义标签来简化视图层的开发。例如,我们可以使用`<s:textfield>`标签来创建输入框,`<s:password>`标签用于密码输入,`<s:submit>`标签则用于提交表单。 ```jsp ...
在Struts2框架中,标签库是其核心特性之一,它提供了丰富的UI组件和控制逻辑,使得开发者可以更加便捷地进行页面渲染和交互处理。本文将深入探讨Struts2标签的中文文档,以及如何利用这些文档进行有效开发。 首先,...
Struts2标签库的组成 Struts2框架的标签库可以分为以下三类: 用户界面标签(UI标签):主要用来生成HTML元素的标签。 表单标签:主要用于生成HTML页面的FORM元素,以及普通表单元素的标签。 非表单标签:主要用于生成...
本文将深入探讨Struts2标签和Tiles库的使用,以及它们在实际开发中的应用。 1. **Struts2标签** Struts2提供了丰富的标签库,这些标签使得开发者能够在JSP页面中方便地实现业务逻辑和控制流程。例如: - `s:...
首先,Struts2标签库分为两大类:核心标签库和展示标签库。核心标签库提供了一组基础功能,如表单处理、控制流程、消息显示等,而展示标签库则包含更具体的UI元素,如数据展示、分页等。了解这些标签库的使用,可以...
参考文档是开发者理解和使用Struts2标签的关键资源,它详细阐述了每个标签的功能、属性、用法及示例,有助于快速学习和掌握Struts2的视图层开发。 通过深入学习和实践Struts2的标签API,开发者可以有效地提升Web...
利用Struts 2标签创建ex3.jsp页面,此页面提交给tag.action,在structs.xml中配置这个action的转发视图为result.jsp在result.jsp页面中显示ex3.jsp页面控件的值。(源代码和实验报告)
Struts2标签库是Java Web开发中非常重要的一个部分,它是Apache Struts框架的一部分,用于简化JSP页面的编写,提高代码的可读性和可维护性。本资源包含了一个PDF和Word格式的文档,旨在详细介绍如何使用Struts2的...
Struts2标签详解与实例 在Java Web开发中,Struts2框架因其强大的MVC(模型-视图-控制器)架构而备受青睐。Struts2提供了丰富的标签库,简化了视图层的开发,使开发者可以更加专注于业务逻辑。本文将深入探讨Struts...
struts2 标签 Taglib (Struts2标签库)
第五章:struts2标签库