马士兵 struts2 笔记
转自: 马士兵 struts2 笔记
01 Struts2-Action一、Struts作用:将请求与结果分开二、搭建Struts2的运行环境:1、建立Web项目;2、建立Struts2的配置文件(struts.xml); 将Struts2的空项目中的配置文件(struts.xml)复制到项目的src目录下。 配置如下:<!-- struts.devMode : 是否设置为开发模式 true:是开发模式,否则不是 注:在开发模式下,修改Struts的配置文件后不需要重新启动Tomcat服务器即生效。 否则修改Struts配置文件后需要重新启动Tomcat服务器才生效。 --> <constant name="struts.devMode" value="true" /> <!-- namespace :对应与项目名称后面的"/"(例如Struts2_0100_Introduction后面的"/") (http://localhost:8080/Struts2_0100_Introduction/) --> <package name="default" namespace="/" extends="struts-default"> <action name="hello"> <result> /hello.jsp </result> </action></package>3、复制Struts2相应的jar包及第三方包。 将空项目中lib目录中的除junit和spring-test之外的所有文件复制到项目的WebRoot/WEB-INF/lib目录下4、修改对应的web.xml,建立struts2的filter(参考struts自带的项目),添加如下配置: <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> 三、NamespaceNamespace决定了action的访问路径,默认为“”,可以接收所有路径的action,如果没有找到相应的namespace时,则使用namespace为空的actionNamespace可以写为/,或者/xxx,或者/xxx/yyy,对应的action访问路径为/index.action、/xxx/index.action、或者/xxx/yyy/index.action.Namespace最好也用模块来进行命名。namespace :对应与项目名称后面的"/"(例如Struts2_0100_Introduction后面的"/") (http://localhost:8080/Struts2_0100_Introduction/) 四、<package>标签<package>是用来解决重名的问题,例如当系统的前台和后台都有一个action名叫hello,这时就需要用package来区分。 前台<package name="front">后台<package name="back">struts2中的package与java的package是相同的作用的。五、Action具体视图的返回可以由用户自己定义的Action来决定具体的手段是根据返回的字符串找到对应的配置项,来决定视图的内容,有三种手段:<constant name="struts.devMode" value="true" /> <package name="front" extends="struts-default" namespace="/"> <action name="index" />…………注:<base>标签:当前页面中所有连接都会在前面加上base地址。七、Action的动态调用方法Action执行的时候并不一定要执行execute方法,我们可以指定Action执行哪个方法:1、 方法一(通过methed属性指定执行方法):可以在配置文件中配置Action的时候用method=来指定执行哪个方法<action name="userAdd" method="add"> <result>/user_add_success.jsp</result></action> 这样,只要在action的对象中有一个add的方法,并且返回类型为String就可以了。如果没有method属性,则默认执行execute()方法。import com.opensymphony.xwork2.ActionSupport;public class UserAction extends ActionSupport { public String add() { return SUCCESS; } }2、 动态方法调用DMI(推荐)可以在url地址中动态指定action执行那个方法。Url地址如下:http://localhost:8080/Struts2_0500_ActionMethod/user/user!add方法:action + ! + 方法名注:只要Action对象中有这个方法,并且返回类型为String就可以调用。这样Struts.xml配置文件中不需要配置methed属性。代码如下:<action name="user" extends="struts-default" namespace="/actions"> <action name="Student*" method="{1}"> <result>/Student{1}_success.jsp</result> </action> <action name="*_*" method="{2}"> <result>/{1}_{2}_success.jsp</result> <!-- {0}_success.jsp --> </action></package>解释:第一个Action的名称为name=”Student*” method=”{1}”,表示所有Action以Student开始的都会执行这个Action,并且执行Student后字符为方法名的方法,例如:访问的Action为Studentadd,会执行这个Action(Student*),并且执行add的方法.因为{1}在这里代表add,并且返回/Studentadd_success.jsp页面。第二个Action的名称name=”*_*” method=”{2}” class=”…action.{1}Action” 表示所有Action中包含下划线(“_”)都会执行这个Action,例如:Teacher_add,那么会执行这个Action,并且Action对应的类为TeacherAction,且执行Action中的add方法,返回结果页面为/Teacher_add_success.jsp,因为在这里的{1}表示Teacher,{2}表示add3、 匹配顺序当匹配的Action有两个以上时,则会按匹配精确度高的那个Action,当有个相同的匹配精确度时,则按先后顺序进行。 九、Action的属性接收参数Action中三种传递并接受参数:1、 在Action添加成员属性接受参数例如请求的URL地址:http://localhost:8080/Struts2_0700_ActionAttrParamInput/user/user!add?name=a&age=8其中传递了两个参数:name和age,其值分别为:a、8,此Action执行的是add()方法。那我们只要在user这个Action对象中添加这两个成员属性并生成set、get方法。public class UserAction extends ActionSupport { private String name; private int age; public String add() { System.out.println("name=" + name); System.out.println("age=" + age); return SUCCESS; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }2、 域模型(Domain Model)就是利用对象域来进行传递和接受参数例如请求的URL地址:http://localhost:8080/Struts2_0800_DomainModelParamInput/user/user!add?user.name=a&user.age=8其中,访问的是namespace=”/user” action的name=”user” Action所执行的方法method=”add” 利用对象域user来传递参数,为对象的属性赋值(user.name=a user.age=8) 注:需要一个对象user 并且这个对象需要有两个成员属性,且具有get、set方法。 然后在Action中添加一个User对象的成员属性。并且有get、set方法,就可以了。//User对象public class User { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; }} //Action类public class UserAction extends ActionSupport { private User user; //private UserDTO userDTO; public String add() { System.out.println("name=" + user.getName()); System.out.println("age=" + user.getAge()); return SUCCESS; } public User getUser() { return user; } public void setUser(User user) { this.user = user; }}3、 ModelDriven接收参数使Action实现com.opensymphony.xwork2.ModelDriven<User>(在实现接口时需要使用泛型,否则使用时需要转型)中利用其getModel()方法返回对象模型,从而获得传入的参数。例如URL如下:http://localhost:8080/Struts2_0900_ModelDrivenParamInput/user/user!add?name=a&age=8其:访问的是namespace=”/user” action的name=”user” Action所执行的方法method=”add”,其传入了两个参数:name=a,age=8。参数被传入至Action后,会被ModelDriven对象根据参数名自动赋值给User对象相应的属性而生成User对象,并且由getModel()返回。那么我们在Action中就可以利用这个对象了。注意:传入的参数名需要与对象模型中的成员属性一致。对象模型User:public class User { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; }} Action对象import com.opensymphony.xwork2.ActionSupport;import com.opensymphony.xwork2.ModelDriven;public class UserAction extends ActionSupport implements ModelDriven<User>{ private User user = new User(); public String add() { System.out.println("name=" + user.getName()); System.out.println("age=" + user.getAge()); return SUCCESS; } @Override public User getModel() { return user; } } 十、Action属性接收参数中文问题如果表单提交数据中有中文时,尽量使用post方式。需要在Struts.xml配置文件中加入一个常量配置,如下:<struts> <constant name="struts.devMode" value="true" /> <constant name="struts.i18n.encoding" value="GBK" /><!-- internationalization --> <package name="user" extends="struts-default" namespace="/user"> <action name="userAdd" method="add"> <result>/user_add_success.jsp</result> </action> </package></struts>但是,在Struts2 2.7之前,这个配置无效,需要其它方法设置。如下:手动在web.xml中在Struts过滤器之前配置一个过滤器用于解决中文的问题。十一、 简单数据验证使用addFieldError方法和s:fieldError标签简单处理数据校验场景:对一个用户名进行验证,如果用户名不合法,则显示给客户端查看信息。URL请求地址:http://localhost:8080/Struts2_1100_SimpleDataValiation/user/user!add?name=a 分析:访问的Struts2配置,namespace=”/user” action的name=”user” Action所执行的方法method=”add”并且传入了一个参数name=a.如下:<package name="user" extends="struts-default" namespace="/user"> <action name="user" theme="simple"/> <br /> <s:property value="errors.name"/> <s:debug></s:debug></body>注:使用<s:fielderror>标题,需要使用<%@taglib>命令引用Struts2的标签库如下: <%@taglib uri="/struts-tags" prefix="s" %>1、<s:fielderror>标签:获取使用addFieldError()方法添加的信息。 FiledName:指定信息的名称。 Theme: 指定显示的主题。 注:使用此标签获取的错误信息,Struts强制添加了css的修饰。生成的HTML代码如下(不长用):<ul encoding="UTF-8" ?><!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"><struts> <package name="login" extends="struts-default" namespace="/login"> <action name="login*" encoding="UTF-8" ?><!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <constant name="struts.devMode" value="true" /> <include file="login.xml" /></struts> 十四、 默认的Action当用户访问的namespace下一个不存在的Action,则会将使用默认的Action。使用<default-action-ref name=”name”>标签 其中 name属性指向下面已经定义的Action名称了。<struts> <constant name="struts.devMode" value="true" /> <package name="default" namespace="/" extends="struts-default"> <default-action-ref name="index"></default-action-ref> <action name="index"> <result>/default.jsp</result> </action> </package></struts>当前访问namespace=”/”下不存在的Action时,则返回自动转到访问/default.jsp页面。 十五、 Action总结1、 实现一个Action的最常用的方式:从ActionSupport继承2、 DMI动态方式的调用:!3、 通配符配置:* {1} {2}4、 接收参数的方式(一般属性或DomainModel来接收)5、 简单参数验证addFieldErrora) 一般不使用Struts的UI标签6、 访问Web元素a) Map类型 i. IoC ii. 依赖Struts2b) 原始类型 i. IoC ii. 依赖Struts27、 包含文件配置02 Struts2-Result一、Result类型 (type)1、 dispatcher运用服务器跳转 jsp forward不可以是Action,只可以跳转到视图2、 redirect客户端跳转(重定向)-url发生变化不可以是Action,只可以跳转到视图3、 chain跳转到Action (forward action)可以动用到Action在访问Action时,Action前面不要加”/”4、 redirectAction客户端跳转到Action——-url发生变化5、 freemarker6、 httpheader发送一个http头7、 stream下载8、 velocity9、 xslt10、 plaintext返回页面的源码11、 titles把页面分成几块,每个页面都可以动态的指定<struts> <constant name="struts.devMode" value="true" /> <package name="resultTypes" namespace="/r" extends="struts-default"> <action name="r1"> <result type="dispatcher">/r1.jsp</result> </action> <action name="r2"> <result type="redirect">/r2.jsp</result> </action> <action name="r3"> <result type="chain">r1</result> </action> <action name="r4"> <result type="redirectAction">r2</result> </action> </package></struts> 注:当访问不同的namespace下的Action时,则使用如下方式:<result type="chain"> <param name="actionName">dashboard</param>//Action名称 <param name="namespace">/secure</param>//namespace值</result> 二、全局结果集(Globle Result)当有多个Action使用同一个结果集时,则可以使用全局结果集(Globle Result),如下:<package name="user" namespace="/user" extends="struts-default"> <global-results> <result name="mainpage">/main.jsp</result> </global-results> <action name="index"> <result>/index.jsp</result> </action> <action name="user" namespace="/admin" extends="user"> <action name="admin" value="true" /> <package name="user" namespace="/user" extends="struts-default"> <action name="user" namespace="/user" extends="struts-default"> <action name="user" value="true"></constant> 使用一个实例如说明OGNL表达式语言,如下:Cat类package com.wjt276.struts2.ognl;public class Cat { private Dog friend; public Dog getFriend() { return friend; } public void setFriend(Dog friend) { this.friend = friend; } public String miaomiao() { return "miaomiao"; }}Dog类package com. wjt276.struts2.ognl;public class Dog { private String name; public Dog() { } public Dog(String name) { super(); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "dog: " + name; }}S类package com. wjt276.struts2.ognl;public class S { public static String STR = "STATIC STRING"; public static String s() { return "static method"; }} User类package com. wjt276.struts2.ognl;public class User { private int age = 8; public User() {} public User(int age) { super(); this.age = age; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "user" + age; }} OgnlAction类package com. wjt276.struts2.ognl;public class OgnlAction extends ActionSupport { private Cat cat; private Map<String, Dog> dogMap = new HashMap<String, Dog>(); private Set<Dog> dogs = new HashSet<Dog>(); private String password; private User user; private String username; private List<User> users = new ArrayList<User>(); public OgnlAction() { users.add(new User(1)); users.add(new User(2)); users.add(new User(3)); dogs.add(new Dog("dog1")); dogs.add(new Dog("dog2")); dogs.add(new Dog("dog3")); dogMap.put("dog100", new Dog("dog100")); dogMap.put("dog101", new Dog("dog101")); dogMap.put("dog102", new Dog("dog102")); } public String execute() { return SUCCESS; } public Cat getCat() { return cat; } public Map<String, Dog> getDogMap() { return dogMap; } public Set<Dog> getDogs() { return dogs; } public String getPassword() { return password; } public User getUser() { return user; } public String getUsername() { return username; } public List<User> getUsers() { return users; } public String m() { return "hello"; } public void setCat(Cat cat) { this.cat = cat; } public void setDogMap(Map<String, Dog> dogMap) { this.dogMap = dogMap; } public void setDogs(Set<Dog> dogs) { this.dogs = dogs; } public void setPassword(String password) { this.password = password; } public void setUser(User user) { this.user = user; } public void setUsername(String username) { this.username = username; } public void setUsers(List<User> users) { this.users = users; }}Struts2.xml配置文件:<struts> <constant name="struts.enable.DynamicMethodInvocation" value="false" /> <constant name="struts.devMode" value="true" /> <!-- 允许ognl访问静态方法 --> <constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant> <include file="/com/wjt276/struts2/ognl/ognl.xml"/></struts>Com.wjt276.struts2.ognl.ognl.xml配置文件 <package name="ognl" extends="struts-default"> <action name="ognl" /></li> <li>访问值栈中action的普通方法:<s:property value="m()" /></li> <hr /> <li>访问静态方法:<s:property value="@com.wjt276.struts2.ognl.S@s()"/></li> <li>访问静态属性:<s:property value="@com.wjt276.struts2.ognl.S@STR"/></li> <li>访问Math类的静态方法:<s:property value="@@max(2,3)" /></li> <hr /> <li>访问普通类的构造方法:<s:property value="new com.bjsxt.struts2.ognl.User(8)"/></li><%--返回对象的toString()生成的数据--%> <hr /> <li>访问List:<s:property value="users"/></li> <li>访问List中某个元素:<s:property value="users[1]"/></li> <li>访问List中元素某个属性的集合:<s:property value="users.{age}"/></li> <li>访问List中元素某个属性的集合中的特定值:<s:property value="users.{age}[0]"/> | <s:property value="users[0].age"/></li> <li>访问Set:<s:property value="dogs"/></li> <li>访问Set中某个元素:<s:property value="dogs[1]"/></li> <li>访问Map:<s:property value="dogMap"/></li> <li>访问Map中某个元素:<s:property value="dogMap.dog101"/> | <s:property value="dogMap['dog101']"/> | <s:property value="dogMap[/"dog101/"]"/></li> <li>访问Map中所有的key:<s:property value="dogMap.keys"/></li> <li>访问Map中所有的value:<s:property value="dogMap.values"/></li> <li>访问容器的大小:<s:property value="dogMap.size()"/> | <s:property value="users.size"/> </li> <hr /> <li>投影(过滤):<s:property value="users.{?#this.age==1}[0]"/></li> <li>投影:<s:property value="users.{^#this.age>1}.{age}"/></li><%--头一个 --%> <li>投影:<s:property value="users.{$#this.age>1}.{age}"/></li><%--最后一个--%> <li>投影:<s:property value="users.{$#this.age>1}.{age} == null"/></li> <hr /> <li>[]:<s:property value="[0].username"/></li><%--值堆栈中的对象(Object),从上开始的第0个至堆栈底对象 --%> </ol> <s:debug></s:debug>访问后服务器返回给客户端的结果:1. 访问值栈中的action的普通属性: username = u2. 访问值栈中对象的普通属性(get set方法):9 | 9 | 9 | wrong:3. 访问值栈中对象的普通属性(get set方法):4. 访问值栈中对象的普通方法:15. 访问值栈中对象的普通方法:6. 访问值栈中action的普通方法:hello7. 访问静态方法:static method8. 访问静态属性:STATIC STRING9. 访问Math类的静态方法:310. 访问普通类的构造方法:user811. 访问List:[user1, user2, user3]12. 访问List中某个元素:user213. 访问List中元素某个属性的集合:[1, 2, 3]14. 访问List中元素某个属性的集合中的特定值:1 | 115. 访问Set:[dog: dog1, dog: dog2, dog: dog3]16. 访问Set中某个元素: <!—没有显示是因为在Set中没有排序就不存在的用下标访问了-->17. 访问Map:{dog102=dog: dog102, dog101=dog: dog101, dog100=dog: dog100}18. 访问Map中某个元素:dog: dog101 | dog: dog101 | dog: dog10119. 访问Map中所有的key:[dog102, dog101, dog100]20. 访问Map中所有的value:[dog: dog102, dog: dog101, dog: dog100]21. 访问容器的大小:3 | 322. 投影(过滤):user123. 投影:[2]24. 投影:[3]25. 投影:false26. []:u27. [Debug]04 Struts2-TagsStruts2标签目录1、 通用标签a) Propertyb) Set i. 默认为action scope,会将值放入request和ActionContext中 ii. page/request/session/applicationc) beand) include对中文文件支持的问题,不建议使用,如需要包含,改用jsp包含e) paramf) debug2、 控制标签a) If elseif elseb) Iterator i. collections map enumerateon iterator arrayc) subset3、 UI标签a) Theme i. Simple xhtml(默认) css_xhtml ajax4、 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> 七、 Theme1、 css(覆盖Struts2原来的css)2、 覆盖单个文件3、 定义自己的theme4、 实战a) 把所有主题定义为simpleb) Fielderror特殊处理c) 自己控制其他标签的展现 05设计约定(编码规定)1、 原则:简单就是美2、 库名:项目名3、 表的命名:t_model名4、 字段:保持和属性名一致(尽量不要起和数据库命名冲突)5、 用层来划分包com.wjt276.bbs.action model(bean) service dto(vo)6、 Action: xxxAction7、 *.*8、 前台: /9、 后台: /admin10、Package: “action” adminAction 06 项目开发顺序1、 建立界面原型2、 建立Struts.xmla) 确定namespaceb) 确定packgec) 确定Action的名称d) 确定Resulte) 将界面原型页面进行修改,匹配现有设置f) 测试3、 建立数据库(或实体类)4、 建立Model层5、 建立Service层(后面讲hibernate后再完美)a) 此时可以使用Junit进行单元测试了6、 着手开发 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, 如果出现异常,那么它会跳转到reslut="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.propertieswelcome.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.properties1. p(属性名称) = converter ii. 全局:xwork-conversion.properties1. com.xxx.XXX(类名)= converter iii. Annotationb) 如果遇到非常麻烦的映射转换 i. request.setAttribute(); ii. session Struts2总结1. Actiona) namespace(掌握)b) path(掌握)c) DMI(掌握)d) wildcard(掌握)e) 接收参数(掌握前两种)f) 访问request等(掌握Map IOC方式)g) 简单数据验证(掌握addFieldError和<s:fieldError)2. Resulta) 结果类型(掌握四种,重点两种)b) 全局结果(掌握)c) 动态结果(了解)3. OGNL表达式(精通)a) # % $4. Struts标签a) 掌握常用的5. 声明式异常处理(了解)6. I18N(了解)7. CRUD的过程(最重要是设计与规划)(精通)8. Interceptor的原理(掌握)9. 类型转换(掌握默认,了解自定义)?