struts2 复习

好久没用struts2 一年多了吧。好多东西已经模糊忘记了。转篇博客恢复下记忆吧!



●开发准备
  1.引入类库 直接从struts/apps/struts2-blank/WEB-INF/lib下拷贝
  除junit和spring-test之外的所有jar包
  2.复制一个struts.xml
  直接从struts/apps/struts2-blank/WEB-INF/classes下拷贝struts.xml
  3.对web.xml配置 同样从
  struts/apps/struts2-blank/WEB-INF/web.xml中拷贝
  <filter></filter>和<filter-mapping></filter-mapping>以及其中的全部内容

●Action
1.struts2的作用就是让用户请求和返回视图(servlet api)分离。

2.namespace决定了action的访问路径,默认为"",可以接收所有路径的action
namespace可以写为/,或者/xxx,或者/xxx/yyy,对应的action访问路径为/xxx.action
/xxx/xxx.action,或者/xxx/yyy/xxx.action
namespace最好也用模块来进行命名 比如用户模块 就用user

3.具体视图的返回可以由用户自己定义的Action来决定
具体的手段是根据返回的字符串找到对应的配置项,来决定视图的内容
具体Action的实现可以是一个普通的java类,里面有public String execute方法即可
或者实现Action接口
不过最常用的是从ActionSupport继承,好处在于可以直接使用Struts2封装好的方法

4.struts2中的路径问题是根据action的路径而不是jsp路径来确定,所以尽量不要使用相对路径。
虽然可以用redirect方式解决,但redirect方式并非必要。
解决办法非常简单,统一使用绝对路径。(在jsp中用request.getContextRoot方式来拿到webapp的路径)
或者使用myeclipse经常用的,指定basePath

5.Action执行的时候并不一定要执行execute方法
可以在配置文件中配置Action的时候用method=来指定执行哪个方法
也可以在url地址中动态指定(动态方法调用DMI)(推荐)
前者会产生太多的action,所以不推荐使用

6.使用通配符,将配置量降到最低
不过,一定要遵守"约定优于配置"的原则,即命名规则统一。

[xhtml]  view plain copy print ?
  1. <action name="Student*" class="com.bjsxt.struts2.action.StudentAction" method="{1}">  
  2. <result>/Student{1}_success.jsp</result>  

*代替字符串,{1}代表第一个*所匹配的字符串。
[c-sharp]  view plain copy print ?
  1. <action name="*_*" class="com.bjsxt.struts2.action.{1}Action" method="{2}">  
  2. <result>/{1}_{2}_success.jsp</result>  


7.使用action属性接收参数,在URL地址中传的参数和action里的成员变量可以是一一对应的,
action初始化时,会自动将成员变量的值初始化成参数的值。(struts调set方法,所以set方法名
和url参数的名必须匹配而真正的成员变量名不一定非要匹配)

8.使用Domainmodel(领域模型)接收参数 action类中可以不写具体的属性而将其写入领域模型中,
然后action类中持有一个领域模型的对象的引用,在url中同样可以传参数直接对领域模型对象的属性赋值,
写法为 namespace/actionname!method?domainmodel.parameter=XXX&domainmodel.parameter=XXX,
(也可能是method?domainmodel.parameter.parameter.parameter=XXX,此时domainmodel成员变量为另一个对象,
另一个对象的成员变量为另另一个对象)
当领域模型与实际参数的属性不同时,如,password往往有确认password,则新建一个dataTransferObject类来接收参数并判断,再初始化领域模型。此时action类中持有的则是DTO的引用。

9.我们也可以使action类实现ModelDriven<User>接口,使用接口中的getmodle方法来使action自动获得领域模型,这样即使在action类中包含了领域模型的引用,同样可以在url中直接写 namespace/actionname!method?parameter=XXX&parameter=XXX.使用这个方法时,在action中要自己new一个模型。

10.
[c-sharp]  view plain copy print ?
  1. <constant name="struts.i18n.encoding" value="GBK" />  
  struts.xml解决中文问题的标签,这些标签可以在struts2-core-2.1.6.jar中的org.apache.struts2中的default.properties中查询默认值。
在2.1.6之前,中文问题是个BUG,在2.1.7中已修正。

11.使用struts的标签来将程序中对用户的提示信息打印到前台页面:
在后台 使用
[java]  view plain copy print ?
  1. this.addFieldError("name","name is error");  

其中name为action中的属性,"name is error"为错误信息的提示

[c-sharp]  view plain copy print ?
  1. <s:fielderror fieldName="name" />  

将带有简单格式的提示信息打印到前台
首先,在前台页面中包含

[xhtml]  view plain copy print ?
  1. <%@taglib uri="/struts-tags" prefix="s" %>  

在META-INF下struts-tag.tld中有标签详细信息 页面中使用<s:debug></s:debug>
可以观察ValueStack里保存的action中的属性。
属性都是存在map中的,有值,有名,而 值,是个数组,
所以我们用<s:property value="errors.name[0]">可以取到错误信息的具体字符串。

12.
一、
后台程序可以通过ActionSupport中的方法
[java]  view plain copy print ?
  1. request = (Map)ActionContext.getContext().get("request");  
  2. session = ActionContext.getContext().getSession();  
  3. application = ActionContext.getContext().getApplication();  

得到map类型的 request,session,application.
还可以通过put方法对这些名值对进行赋值。
在前台页面,可以通过
[xhtml]  view plain copy print ?
  1. <s:property value="#request.r1"/> | <%=request.getAttribute("r1") %> <br />  
  2. <s:property value="#session.s1"/> | <%=session.getAttribute("s1") %> <br />  
  3. <s:property value="#application.a1"/> | <%=application.getAttribute("a1") %> <br />  

来拿到所设置的request、session、application.既用#key来访问或者用最原始的jsp语言来访问。

二(常用)、
同样设置三个成员变量 但使用范型
[java]  view plain copy print ?
  1. private Map<String, Object> request;  
  2. private Map<String, Object> session;  
  3. private Map<String, Object> application;  

然后设置set方法,由struts将页面元素对象自动设置进去(实现RequestAware,SessionAware,ApplicationAware),
然后调用put方法,往进写东西。

三、
同样设置三个成员变量 但类型不同
[java]  view plain copy print ?
  1. private HttpServletRequest request;  
  2. private HttpSession session;  
  3. private ServletContext application;  

然后初始化
[java]  view plain copy print ?
  1. request = ServletActionContext.getRequest();  
  2. session = request.getSession();  
  3. application = session.getServletContext();  

然后由request.setAttribute("r1", "r1")往进设置值。

四、
同样设置三个成员变量
[java]  view plain copy print ?
  1. private HttpServletRequest request;  
  2. private HttpSession session;  
  3. private ServletContext application;  
  4. //初始化  
  5. public void setServletRequest(HttpServletRequest request) {  
  6.     this.request = request;  
  7.     this.session = request.getSession();  
  8.     this.application = session.getServletContext();  
  9. }  
  10. //然后由request.setAttribute("r1", "r1")设值。  


13.模块包含
在struts.xml中可以将其他xml文档包含
[xhtml]  view plain copy print ?
  1. <include file="XXXX.xml" />  

这样的好处是,多个模块可以同时开发,然后包含就可以协作工作。

14.默认action
在url的namespace后什么都不敲入或敲入不存在的action时,访问默认的action
[xhtml]  view plain copy print ?
  1. <default-action-ref name="index"></default-action-ref>  

然后再jsp中使用
[xhtml]  view plain copy print ?
  1. <s:property value="r"/>  

接受参数。
●result
15.result的type(类型)属性
·默认为dispatcher 运用jsp跳转(forward)到结果页面 不能跳转到action
·redirect 重定向到结果页面 不能跳转到action
·chain forward跳转到一个action
·redirectAction 重定向到一个action
·freemarker
·httpheader 发一个http的头信息
·stream 下载
·velocity
·xslt xml的修饰
·plaintext 页面源码
·tiles 页面分块后动态指定
假如chain forward跳转的action在某包内

[xhtml]  view plain copy print ?
  1. <result type="chain">  
  2.        <param name="actionName">adfadf</param>  
  3.        <param name="namespace">/XXXXXX</param>  
  4. </reuslt>  

在struts-2.2.1.1-docs/struts-2.2.1.1/docs/chain-result.html可查

16.global-results全局结果集在,同一个package中大家可以共用的结果视图
[xhtml]  view plain copy print ?
  1. <global-results>  
  2.     <result name="mainpage">/main.jsp</result>  
  3. </global-results>  

其他package中也想使用此package的result,则extends="packagename"
[xhtml]  view plain copy print ?
  1. <package name="admin" namespace="/admin" extends="user">  

则此包内拥有user包的action

17.动态结果集 即<result>${r}</result>,此时r为action的成员变量 xml中${}可以读取valuestack里的内容
r的值可以动态指定为一个字符串,例如"/user_success.jsp"。

18.带参数的结果集。
由于forward服务器内跳转共享一个值栈,所以参数也共享,即没有必要传。
而再redirect客户端重定向的时候,值栈不共享,是两次request过程,
此时希望action向新定向到的页面传参数需要使用?paramname=${paramname}
[xhtml]  view plain copy print ?
  1. <result type="redirect">/user_success.jsp?t=${type}</result>  

此时如果在user_success.jsp使用struts的<s:property value="t">
标签取值取不出,因为不是action没有值栈actionstack。
只能用<s:property value="#parameters.t">从actioncontext中取。

●ognl表达式
1.action中的成员变量为domainmodel对象引用时,可以在前台传参数来初始化这个对象,不传不构造,
也可以自己new。但是,如果要使用传参来初始化的时候domainmodel必须有一个空的构造方法。。

2.
访问值栈中的action的普通属性 <s:property value="username"/>  直接写属性名
访问值栈中对象的普通属性<s:property value="cat.friend.name"/>  对象名.成员变量名(是对象).成员变量名
访问值栈中对象的普通方法<s:property value="password.length()"/>  对象名.方法名()
访问值栈中action的普通方法<s:property value="m()"/>  直接写方法名()

3.
访问静态方法 <s:property value="@com.bjsxt.struts.ognl.S@s()"/> @类名@方法名()
在struts中要有一个设置<constant name="struts.ognl.allowStaticMethodAccess" value="true"><constant>
设置后才允许静态方法访问,这些在default.properties配置文件中可以查到
访问静态属性 <s:property value="@com.bjsxt.struts.ognl.S@STR"/> @类名@属性名
访问Math类的静态方法:<s:property value="@@max(2,3)" />  @@方法名

4.
访问普通类的构造方法:<s:property value="new com.bjsxt.struts2.ognl.User(8)"/>  new 全类名(参数)
访问List中某个元素:<s:property value="users[1]"/> List名[下标]
访问List中元素某个属性的集合:<s:property value="users.{age}"/> 把users中每个user拿出来,
再把每个user的age拿出来组成一个新的List。  list名.{属性名}
访问List中元素某个属性的集合中的特定值:<s:property value="users.{age}[0]"/> 把users中每个user拿出来,
再把每个user的age拿出来组成一个新的List,取第0个。 list名.{属性名}[下标]
访问Set:<s:property value="dogs"/>
访问Set中某个元素:<s:property value="dogs[1]"/> 由于set是无序的所以取不到
访问Map:<s:property value="dogMap"/>
访问Map中某个元素:<s:property value="dogMap.dog101"/> map名.key名 或者dogMap['dog101']或者dogMap[/"dog101/"]
访问Map中所有的key:<s:property value="dogMap.keys"/> 拿到了key的集合
访问Map中所有的value:<s:property value="dogMap.values"/> 拿到了value的集合
访问容器的大小:<s:property value="dogMap.size()"/> | <s:property value="users.size"/>不加()也可以,
ognl认为它是个属性。

5.
投影(过滤):<s:property value="users.{?#this.age==1}[0]"/>
从users(list)中拿出age为1的user并将其放入集合,取第0个。
投影:<s:property value="users.{^#this.age>1}.{age}"/> 
从users中拿出age大于1的  取开头那个 把年龄输出
投影:<s:property value="users.{$#this.age>1}.{age}"/>
从users中拿出age大于1的  取结尾那个 把年龄输出
投影:<s:property value="users.{$#this.age>1}.{age} == null"/>
从users中拿出age大于1的  取结尾那个的年龄 看是否为空

6.
用[]访问valuestack里面的元素 action永远在栈顶
[]:<s:property value="[0].username"/> 此时访问的是从0位置开始也就是从action的位置
开始往下的元素直到栈底。如果用到服务器端跳转,用到的action会挨个被压入valuestack中。

●Struts标签
首先,在前台页面中包含<%@taglib uri="/struts-tags" prefix="s" %>
1.property
[xhtml]  view plain copy print ?
  1. <s:property value="username"/>   

将username属性的值打印出来
[xhtml]  view plain copy print ?
  1. <s:property value="'username'"/>   

将username字符串打印出来
[xhtml]  view plain copy print ?
  1. <s:property value="admin" default="管理员"/>   

为admin属性设置默认值,如果valuestack中没有则打印默认值
[xhtml]  view plain copy print ?
  1. <s:property value="'<hr/>'" escape="false"/>  

默认为true,将标签转译成字符显示,而不是直接显示标签。
false时,不转译,即浏览器直接显示标签样式。

2.set 往指定或非指定范围内设定变量并指定值
常用于给actioncontext中的param中的变量命名

[xhtml]  view plain copy print ?
  1. <s:set var="adminName" value="username" />   

将名为adminName的变量设置到request和ActionContext中
值为username的值,此时
[xhtml]  view plain copy print ?
  1. <s:property value="#request.adminName" />  
  2. <s:property value="#adminName" />  

都可以将adminName的值显示
[xhtml]  view plain copy print ?
  1. <s:set name="adminPassword" value="password" scope="page"/>  

为adminPassword变量设定范围,name=这种写法已经被废弃
[xhtml]  view plain copy print ?
  1. <s:set var="adminPassword" value="password" scope="session"/>  

上面代码显示,
当scope(范围)为session时,
在debug标签中看到actionContext中的session有值,
[xhtml]  view plain copy print ?
  1. <s:property value="#session.adminPassword"/>  

所以必须从session中取而不能直接取值。

3.bean 创建name指定的类的对象并用var命名
不用var命名,会只在值栈中压入创建的对象,
标签结束时消除对象,所以标签外访问不到。
反之,则在stackcontext中,标签结束后同样可以取到。
[xhtml]  view plain copy print ?
  1. <s:bean name="com.bjsxt.struts2.tags.Dog" var="myDog">  
  2.     <s:param name="name" value="'oudy'"></s:param>  
  3. </s:bean>  

param属性为对象的成员变量设置值,name为名,value为值。
注意value为ognl所以字符串要加单引号。

4.include  包含英文文件(中文会出问题)
[xhtml]  view plain copy print ?
  1. <s:include value="/_include1.html"></s:include>  

或者
[xhtml]  view plain copy print ?
  1. <s:set var="incPage" value="'/_include1.html'" />  
  2. <s:include value="%{#incPage}"></s:include>  

 %{}的意思为将大括号中的内容强制当成ognl表达式

5.if elseif
url传参数后在actionContext中的parameters中会有对应参数和值
[xhtml]  view plain copy print ?
  1. <s:property value="#parameters.age[0]" /><!--可以查看参数age的值-->  
  2. <s:if test="#parameters.age[0] < 0">wrong age!</s:if>  
  3. <s:elseif test="#parameters.age[0] < 20">too young!</s:elseif>  
  4. <s:else>yeah!</s:else>  

6.iterator
[xhtml]  view plain copy print ?
  1. <s:iterator value="{1,2,3}">  
  2.     <s:property/>|  
  3. </s:iterator>  

ognl{}内为集合,iterator标签将集合中的内容遍历
由<s:property/>依次打印出来
[xhtml]  view plain copy print ?
  1. <s:iterator value="{'aaa', 'bbb', 'ccc'}" var="x">  
  2.     <s:property value="#x.toUpperCase()"/> |  
  3. </s:iterator>  

每次遍历将集合的元素赋予x,
在property标签中调用其转换大写方法转换为大写
[xhtml]  view plain copy print ?
  1. <s:iterator value="{'aaa', 'bbb', 'ccc'}" status="status">  
  2.     <s:property/> |  
  3.     遍历过的元素总数:<s:property value="#status.count"/> |  
  4.     遍历过的元素索引:<s:property value="#status.index"/> |  
  5.     当前是偶数?:<s:property value="#status.even"/> |  
  6.     当前是奇数?:<s:property value="#status.odd"/> |  
  7.     是第一个元素吗?:<s:property value="#status.first"/> |  
  8.     是最后一个元素吗?:<s:property value="#status.last"/>  
  9. </s:iterator>  

在iterator中有个状态标签status,有许多属性,如元素总数,索引,奇偶等,
[xhtml]  view plain copy print ?
  1. <s:iterator value="#{1:'a', 2:'b', 3:'c'}" >  
  2.     <s:property value="key"/> | <s:property value="value"/>  
  3. </s:iterator>  

ognl中的map写法为 键:值 
用<s:property value="key">取键,value="value"取值
[xhtml]  view plain copy print ?
  1. <s:iterator value="#{1:'a', 2:'b', 3:'c'}" var="x">  
  2.     <s:property value="#x.key"/> | <s:property value="#x.value"/>  
  3. </s:iterator>  

用var=x代表其中一个条目,value=#x.key取这个条目的键,#x.value取这个条目的值

7.fielderror当action类中    
this.addFieldError("fielderror.test", "wrong!");
前台可以用fielderror将其显示
[xhtml]  view plain copy print ?
  1. <s:fielderror fieldName="fielderror.test" theme="simple"></s:fielderror>  

8.ui
疑问 struts.xml中的constant标签有哪些属性
[xhtml]  view plain copy print ?
  1. <constant name="struts.devMode" value="true"></constant> 开启热部署(开发模式)  
  2. <constant name="struts.ognl.allowStaticMethodAccess" value="true"><constant> 允许访问静态方法  
  3. <constant name="struts.i18n.encoding" value="GBK" />  

解决中文问题
[xhtml]  view plain copy print ?
  1. <constant name="struts.custom.i18n.resource" value="XXXX">  
  2.    </constant>  

国际化全局配置

9.struts Exception handling—声明式异常处理
在struts中 class中的方法可以在捕获异常后将其抛出,
这样可以支持struts的声明式处理任何异常。
在struts.xml中
[xhtml]  view plain copy print ?
  1. <global-results>  
  2.     <result name="error">/error.jsp</result>  
  3. </global-results>  
  4. <global-exception-mappings>  
  5.     <exception-mapping result="error"exception="java.lang.Exception">  
  6.     </exception-mapping>  
  7. </global-exception-mappings>  

必须把results写前面!
对异常做出映射,当发生java.lang.Exception时,返回error这个result.

10.struts <default-action-ref >的bug问题
该设置不会解析action的方法只会简单的将result返回BUG。

要想设置首页,目前只能在web.xml中配置
[xhtml]  view plain copy print ?
  1. <welcome-file-list>  
  2.    <welcome-file>index</welcome-file>  
  3. </welcome-file-list>  


11.i18n:支持程序国际化
 1.i18n原理
  a)ResourceBundle和Locale的概念
 
[java]  view plain copy print ?
  1. ResourceBundle res = ResourceBundle.getBundle("app", Locale.CHINA);  
  2. System.out.println(res.getString("welcome.msg" ));  

  b)资源文件
    app_en_US.properties  app_英语缩写_美国.properties
        内容: welcome.msg=hello,sir
    app_zh_CH.properties  app_中华缩写_中国.properties
  c)native2ascii jdk/bin/native2ascii 可以将中文转换成iso8859-1    
 2.Struts的资源文件
  a)app级 见原理
 
  b)propertiesEditor插件
   i. 解压
  ii. features plugin 覆盖到myeclipse中的eclipse目录里
 3.Action级别国际化
   a)jsp中
 
[xhtml]  view plain copy print ?
  1. <s:property value="getText('login.username')"/>  

   这里可以直接调用方法说明action中有这个方法
   这个方法其实是Actionsupport中的方法
   b)LoginAction_en_US.properties中
   login.username=username:
   login.password=password:
   login.login=login
 4.package级别国际化 在包内
   package_en_US.propertiesss
 5.全局级别国际化  (常用)
   XXXX_en_US.properties 在src目录内
   在struts.xml中配
  
[xhtml]  view plain copy print ?
  1. <constant name="struts.custom.i18n.resource" value="XXXX">  
  2.    </constant>  

 6.动态字符的国际化
   properties中
   welcome.msg=welcome:{0}
   jsp文件中
  
[xhtml]  view plain copy print ?
  1. <s:text name="welcome.msg">  
  2.     <s:param value="username"></s:param>  
  3.    </s:text>   

 7.动态语言切换
   struts中可以直接在url后传参数实现动态语言切换
   "admin/lang?request_locale=en_US"

12.自定义拦截器
[xhtml]  view plain copy print ?
  1. <package name="test" namespace="/" extends="struts-default">  
  2.     <interceptors>  
  3.         <interceptor name="my" class="com.bjsxt.interceptor.MyInterceptor">            </interceptor>  
  4.     </interceptors>  
  5.   
  6.     <action name="test" class="com.bjsxt.action.TestAction">  
  7.         <result>/test.jsp</result>  
  8.         <interceptor-ref name="my"></interceptor-ref>  
  9.         <interceptor-ref name="defaultStack"></interceptor-ref><!--这句话必须写否则没有系统子代的interceptor -->  
  10.     </action>  
  11. </package>  


13.使用struts的token拦截器
[xhtml]  view plain copy print ?
  1. <interceptor-ref name="defaultStack">  
  2.     </interceptor-ref>  
  3.     <interceptor-ref name="token">  
  4. </interceptor-ref>  
  5. <result name="invalid.token">/error.jsp</result>  

最后一句写明当返回为invalid.token时的结果页面

你可能感兴趣的:(struts2 复习)