struts2笔记(六)
04 Struts2-Tags
Struts2标签目录
1、通用标签
a)Property
b)Set
i.默认为action scope,会将值放入request和ActionContext中
ii.page/request/session/application
c)bean
d)include对中文文件支持的问题,不建议使用,如需要包含,改用jsp包含
e)param
f)debug
2、控制标签
a)If elseif else
b)Iterator
i.collections map enumerateon iterator array
c)subset
3、UI标签
a)Theme
i.Simple xhtml(默认) css_xhtml ajax
4、AJAX标签
a)补充
5、$ # % 的区别
a)$ 用于i18n和Struts配置文件
b)# 取得ActionContext的值
c)% 将原本的文本属性解析为ognl,对于本来就是ognl的属性不起作用
i.参考<s:property>和<s:include>
一、property标签
格式:<s:property value=””default=”” escape=”true|false”/>
如果value中的内容为object,则Struts2都会把它解析成ognl表达式
如果里面需要表示为字符串,则需要将内容用单引号括起来
1、利用ognl表达式取值(例如:取值堆栈中的username值)
<s:property value="username"/>
2、取值为字符串
需要将内容用单引号括起来
<s:property value="’username’"/>
3、设置默认值-default
如果一个对象值取不到,则可以使用default设置一个默认值。
<s:property value="admin" default=”管理员”/>
4、设定HTML-escape
是否设置返回值为HTML原代码样式
true:解析返回值的html代码 false:原封不动返回值
<s:property value="'<hr/>'" escape="false"/>
二、set标签
注:var 用于设定变量名
value 变量值(可以是ognl表达式),也可以是字符串
scope 就是的作用范围 request session page application action(默认)
<li>set 设定adminName值(默认为request 和 ActionContext): <s:set var="adminName" value="username" /></li>
<li>set 从request取值: <s:property value="#request.adminName" /></li>
<li>set 从ActionContext取值: <s:property value="#adminName" /></li>
<%--<li>set 设定范围: <s:set name="adminPassword" value="password" scope="page"/></li>
<li>set 从相应范围取值: <%=pageContext.getAttribute("adminPassword") %></li>
--%>
<li>set 设定var,范围为ActionContext: <s:set var="adminPassword" value="password" scope="session"/></li>
<li>set 使用#取值: <s:property value="#adminPassword"/> </li>
<li>set 从相应范围取值: <s:property value="#session.adminPassword"/> </li>
三、bean标签
定义bean,并使用param来设定新的属性值
<s:bean name="com.bjsxt.struts2.tags.Dog" >
<s:param name="name" value="'pp'"></s:param>
</s:bean>
定义bean,并使用一个变量(var)来接受创建的这个bean,取出值来
<s:bean name="com.bjsxt.struts2.tags.Dog" var="myDog">
<s:param name="name" value="'oudy'"></s:param>
</s:bean>
拿出值:因为在actionContext中,所以使用#
<s:property value="#myDog.name"/>
当<s:bean>不指定var时,则对象相关属性会在值栈中。如果需要访问,则只能在<s:bean>标签内访问。
当<s:bean>标签结束后,则值栈就不存在这个对象了。
<s:bean name="com.bjsxt.struts2.tags.Dog" >
<s:param name="name" value="'pp'"></s:param>
<s:property value="name"/>
</s:bean>
四、<include>标签-少使用
包含文件
<li>include _include1.html 包含静态英文文件
<s:include value="/_include1.html"></s:include>
</li>
<li>include _include2.html 包含静态中文文件
<s:include value="/_include2.html"></s:include>
</li>
<li>include _include1.html 包含静态英文文件,说明%用法
<s:set var="incPage" value="%{'/_include1.html'}" />
<s:include value="%{#incPage}"></s:include>
</li>
%{xxx} 强制将xxx内容转换成OGNL表达式
<-- One: -->
<s:include value="myJsp.jsp" />
<-- Two: -->
<s:include value="myJsp.jsp">
<s:param name="param1" value="value2" />
<s:param name="param2" value="value2" />
</s:include>
<-- Three: -->
<s:include value="myJsp.jsp">
<s:param name="param1">value1</s:param>
<s:param name="param2">value2</s:param>
</s:include>
五、If elseif else
<li>if elseif else:
age = <s:property value="#parameters.age[0]" /> <br />
<s:set var="age" value="#parameters.age[0]" />
<s:if test="#age < 0">wrong age!</s:if>
<s:elseif test="#parameters.age[0] < 20">too young!</s:elseif>
<s:else>yeah!</s:else><br />
<s:if test="#parameters.aaa == null">null</s:if>
</li>
<s:if test="%{false}">
<div>Will Not Be Executed</div>
</s:if>
<s:elseif test="%{true}">
<div>Will Be Executed</div>
</s:elseif>
<s:else>
<div>Will Not Be Executed</div>
</s:else>
六、Iterator标签
<li>遍历集合:<br />
<s:iterator value="{1, 2, 3}" >
<s:property/> |<!—不需要写其它的,就可以输出数组内的值-->
</s:iterator>
</li>
<li>自定义变量:<br />
<s:iterator value="{'aaa', 'bbb', 'ccc'}" var="x">
<s:property value="#x.toUpperCase()"/> |
</s:iterator>
</li>
<li>使用status:<br />
<s:iterator value="{'aaa', 'bbb', 'ccc'}" status="status">
<s:property/> |
遍历过的元素总数:<s:property value="#status.count"/> |
遍历过的元素索引:<s:property value="#status.index"/> |
当前是偶数?:<s:property value="#status.even"/> |
当前是奇数?:<s:property value="#status.odd"/> |
是第一个元素吗?:<s:property value="#status.first"/> |
是最后一个元素吗?:<s:property value="#status.last"/>
<br />
</s:iterator>
</li>
<li>
<s:iterator value="#{1:'a', 2:'b', 3:'c'}" >
<s:property value="key"/> | <s:property value="value"/> <br />
</s:iterator>
</li>
<li>
<s:iterator value="#{1:'a', 2:'b', 3:'c'}" var="x">
<s:property value="#x.key"/> | <s:property value="#x.value"/> <br />
</s:iterator>
</li>
七、Theme
1、css(覆盖Struts2原来的css)
2、覆盖单个文件
3、定义自己的theme
4、实战
a)把所有主题定义为simple
b)Fielderror特殊处理
c)自己控制其他标签的展现
07 声明式异常处理
注:Struts2支持声明式异常处理。
Struts2是通过拦截器(interceptor)来处理声明式异常处理。
要求在DAO、Service、Action层都需要抛出导演就可以了。其它的让Struts2来处理。详细过程如下:
实例:
如果在列表时出现错误,则方法如下:
public List<Category> list() throws SQLException{
Connection conn = DB.createConn();
String sql = "select * from _category";
List<Category> categories = new ArrayList<Category>();
PreparedStatement ps = DB.prepare(conn, sql);
ResultSet rs = null;
try {
rs = ps.executeQuery();
Category c = null;
while(rs.next()){
c = new Category();
…………
}
} catch (SQLException e) {
e.printStackTrace();
throw(e);//此处向外抛出异常,让调用它的方法知道
} finally{
DB.close(rs);
DB.close(ps);
DB.close(conn);
}
return categories;
}
然后在调用它的Action也向上抛出异常
public String list() throws SQLException{
categories = categoryService.list();
return SUCCESS;
}
注意重点:我们需要在Struts.xml配置文件中配置需要处理的异常就可以了。
<action name="*-*" method="{2}">
<result>/admin/{1}-{2}.jsp</result>
<result name="input">/admin/{1}-{2}.jsp</result>
<!--<exception-mapping>标签是映射异常处理。表示映射哪种异常,此处是java.lang.Exception, 如果出现异常,那么它会跳转到result="error"的结果集,也就是/error.jsp -->
<exception-mapping result="error" exception="java.lang.Exception"/>
<result name="error">/error.jsp</result>
</action>
当然,我们也可以将所有的异常使用同一个异常映射,那就是<global-exception-mappings>,需要映射的packge只需要继承此package就可以了。如下:
<package name="bbs2009-deafult" extends="struts-default">
<global-results>
<result name="error">/error.jsp</result>
</global-results>
<global-exception-mappings>
<exception-mapping result="error" exception="java.lang.Exception"/>
</global-exception-mappings>
</package>
<!-- 后台Action的配置区 -->
<package name="admin" namespace="/admin" extends="bbs2009-default">
<default-action-ref name="index"></default-action-ref>
<action name="index">
<result>index.html</result>
</action>
<action name="*-*" method="{2}">
<result>/admin/{1}-{2}.jsp</result>
<result name="input">/admin/{1}-{2}.jsp</result>
<result name="error">/error.jsp</result>
</action>
</package>
注意:如果使用全局异常映射(<global-exception-mappings>)和全局结果集(<global-results>)则需要全局结果集(<global-results>)在前。
如果局部(当前)Action、和全局结果集存在相同的<result>,则使用最近的那个结果。
总结:
1、在Action中进行异常映射
2、在package中进行全局异常映射
3、使用继承共用异常映射
4、Struts2中异常处理由拦截器实现(观察struts-default.xml)
a)实际上Struts2的大多数功能都由拦截器实现。
08 国际化
一、 国际化资源文件
命名格式:xxx_语言_国家.properties
例如:app_en_US.properties表示美国 英语
app_zh_CN.properties表示中国 汉语
资源文件的编码是使用UTF-8的编码,这样中文也必需是UTF-8的格式,则需要将中文转换成UTF-8的,你可以使用propertiesEditor插件来进行输入中文。
app_en_US.properties文件内容
welcome.msg=hello world!
app_zh_CN.properties
welcome.msg=欢迎您!
二、 Java国际化
要求:资源文件要求存放在classpath的根目录下(src下)。
然后再建立一个Java类和一个main方法如下:这样就可以进行国际化处理了。
public static void main(String[] args) {
ResourceBundle res = ResourceBundle.getBundle("app",Locale.CHINA);
System.out.println(res.getString("welcome.msg"));
}
注:java.util.ResourceBundle是加载国际化资源文件的类。利用此类的getBundle()方法加载classpath下的指定开头的文件名的国际化资源文件。并且在加载时需要指定加载哪个国家的国际人资源文件。
此实例中的ResourceBundle.getBundle("app",Locale.CHINA);表示加载以"app"开头的国际化资源文件,并且是中国的(对应的zh_CN)的。
一但国际化资源文件加载上来后,就可以使用ResourceBundle类的getSring("welcome.msg")方法获取当前内容。
三、Struts2国际化
Struts2国际化分为:Action级别、package级别、Application级别
1、 Action级别
条件:要求国际化资源文件名的前缀同相应的Action名,并且国际化资源文件需要与相应的Action在同一个包中
例如:我们需要国际化登录页面。如下
原始代码:<body>
Login_input <br>
<form action="admin/Login_login">
username:<input name="username" type="text"/><br/>
password:<input name="password" type="password"/>
<input type="submit" value="login">
</form> </body>
这里需要对"Login_input"、"username"、"password"、"login"进行国际化。因为登录页面的请求URL为
http://localhost:8080/struts2_3200_bbs2009_08/admin/Login-input
根据Struts2.xml的配置文件可知对应的Action为LoginAction.java.因为国际化资源文件名应是LoginAction_开头(此处为LoginAction_zh_CN.properties、LoginAction_en_US.properties)如下
注意:要求国际化资源文件需要与相应的Action在同一包中(见上第三个图),这样Struts2就可以保证当访问这个LoginAction时国际化资源文件会自动加载。我们在相应的文件中可以直接访问(利用ActionSupport类中的getText()方法。)了。
我们现在只需要将登录页面代码修改就可以了。
<body>
<s:property value="getText('login.title')"/><br>
<form action="admin/Login-login" method="post">
<s:property value="getText('login.username')"/><input name="username" type="text"/><br/>
<s:property value="getText('login.password')"/><input name="password" type="password"/>
<input type="submit" value="<s:property value='getText("login.login")'/>">
</form>
<s:debug></s:debug>
</body>
注意:Struts2国际化是使用<s:property value=”getText()”/>来获取信息的。
格式:
<s:property value="getText('login.title',defaultValue)"/>
其中:getText()是ActionSuppot类中的方法。因为<s:property>标签只可以直接使用Action的方法。方法中的参数一:表示国际化资源文件中的标签,因为要求是字符串,所以使用单引号括起来。
参数二:当没有取出数据时,则使用这个默认的值,可以省略此参数。
总结:国际化资源文件建立完、使用标签取值后,其它都将由Struts2来完成。
2、Package级别
Package级别的只是将国际化资源文件建立在package(包)下,要求资源文件名前缀同包名就可以了。
其它的使用同Action级别的一样。
例如:如果在com.wjt276.bbs2009.action包下建立国际化资源文件,则文件名必须以package开头
package_en_US.properties 及 package_zh_CN.properties
总结:1、包级别的资源文件名,必须以package开头
2、包级别的资源文件可以给此包中的所有Action类使用。
3、Application级别
Application级别也只是资源文件存放的位置不同,相同的所使用的范围也不一样。
资源文件要求存放在classpath的根目录下。
国际化资源文件以任何名称开头都可以,只是需要在Struts2.xml配置文件中告诉Struts2资源文件是以什么开头的。
例如:现在以项目名为前缀:bbs2009
bbs2009_en_US.properties 及 bbs2009_en_US.properties
告诉Struts2资源文件是以什么开头的
<constant name="struts.custom.i18n.resources" value="bbs2009"/>
四、资源文件中的参数处理
场景:如果一个登录系统,用户登录后页面提示“欢迎您,xxxx”,如果是英文:”Welcome,xxx”
正常应该如下处理:先取值欢迎信息 + 再显示登录的用户名。
<s:property value="getText('welcome.msg')"/><s:property value="username"/>
注意:但是这要就需要两个Struts2的标签来完成这件事。
资源文件中welcome.msg的值如下:
welcome.msg=欢迎您, 或 welcome.msg=Welcome,
我们还有别外一种方式解决它,只需要一个Struts2标签,只是加入一个参数,这个标签是<s:text>。具体方式如下:
首先是资源文件需要修改,如下
注意:需要在资源文件中使用{index}来表示传入参数是哪一个。这个index是从0开始
文件中的欢迎您,{0}或Welcome,{0}, 如果第一个参数传入值为wjt276,那么页面将显示欢迎您,wjt276或Welcome,wjt276
其次需要使用<s:text>标签是获取信息。如下:
<s:text name="welcome.msg">
<s:param value="username"></s:param>
</s:text>
注意:<s:text>标签中的name中的值不需要单引号括起来,因为是OGNL表达式,而<s:property>标签中value=”getText(‘welcome.msg’)”中的值需要用单引号括起来。因为需要传一个字符串
五、国际化-动态语言切换
在某些网站中,会发现页面中有国家语言的选择,如:中文、英语、日语等语言供您选择。
Struts2也可以实现这种动态语言切换的功能,方法非常的简单。
方法:只需要传入一个参数(参数名必需为request_locale),参数值为”语言_国家”(也就是资源文件的后缀,如zh_CN、en_US)就可以了。例:如果当前访问的页面为中文并且URL为
http://localhost:8080/struts2_3200_bbs2009_08/admin/Login-input
如果需要切换成英文,则只需要传入一个参数request_locale=en_US就可以了。URL如下
http://localhost:8080/struts2_3200_bbs2009_08/admin/Login-input?request_locale=en_US
这样当前进程的浏览器就可以访问这个网站的所有页面为英文,至到这个进程结束,因为Struts2向session中写入locale值
WW_TRANS_I18N_LOCALE=en_US
09 自定义拦截器
一般99.9%用不上
10 类型转换
public class MyPointConverter extends DefaultTypeConverter{
@Override
public Object convertValue(Object value, Class toType) {
if(toType == Point.class) {
Point p = new Point();
String[] strs = (String[])value;
String[] xy = strs[0].split(",");
p.x = Integer.parseInt(xy[0]);
p.y = Integer.parseInt(xy[1]);
return p;
}
if(toType == String.class) {
return value.toString();
}
return super.convertValue(value, toType);
}
}
public class MyPointConverter extends StrutsTypeConverter{
@Override
public Object convertFromString(Map context, String[] values, Class toClass) {
Point p = new Point();
String[] strs = (String[])values;
String[] xy = strs[0].split(",");
p.x = Integer.parseInt(xy[0]);
p.y = Integer.parseInt(xy[1]);
return p;
}
@Override
public String convertToString(Map context, Object o) {
// TODO Auto-generated method stub
return o.toString();
}
}
a)三种注册方式:
i.局部:XXXAction-conversion.properties
1.p(属性名称) = converter
ii.全局:xwork-conversion.properties
1.com.xxx.XXX(类名)= converter
iii.Annotation
b)如果遇到非常麻烦的映射转换
i.request.setAttribute();
ii.session