struts2总结

 

Action:struts2的Action可以是一个普通java类,但必须包含有execute()方法,这样我们可以自己在一个类里面写一个execute方

法,也可以extends ActionSupport,或者是implements Action接口,这三种方法都可以创建一个我们自己的Action类,implements

Action 接口和继承ActionSupport 还是有差别的  例如:继承ActionSupport就支撑国际化等,实现Action接口没有的功能,所以建

议使用extends ActionSupport。

Action中获得request,session,application的方法:
有两种:一种是解耦的;
我们可以通过implements:RequestAware、SessionAware、ApplicationAware 这三个交织接口(这三个接口是不支持泛型的),在

struts2启动时,struts2容器会自动调用public void setRequest(Map<String, Object> request)等方法帮你织入,这样 ,你的程

序就可以使用这三个作用域了,同时也达到了解耦的目的;
还有就是,我们可以在Action中execute方法内,掉用ActionContext(Action的上下文)的静态方法,getContext()获得一个

ActionContext对象;有了这个对象,我们就可以:
                        // 获取 RequestMap 实例
   Map<String, Object> request = (Map<String, Object>) context.get("request");
   // 获取 SessionMap 实例
   Map<String, Object> session = context.getSession();
   // 获取 ApplicationMap 实例
   Map<String, Object> application = context.getApplication();
由于这三实例是AcitonContext中拿到的,不依赖于HttpServletRequest,这也是一种解耦的方法;


另一种就是:耦合的,
我们一样可以通过实现接口ServletRequestAware,ServletContextAware来获得这三个对象,由于这三个对象,依赖于http请求,故

我们说他是耦合的,一样struts会调用public void setServletRequest(HttpServletRequest request)帮我们织入这三个对象,所

以Action里就可以获得HttpServletRequest等三个对象了
另一种方法 就是:我们可以通过ServletActionContext来获取
                      // 获取 HttpServletRequest 实例
   HttpServletRequest request = ServletActionContext.getRequest();
   // 获取 HttpSession 实例
   HttpSession session = request.getSession();
   // 获取 ServletContext 实例
   ServletContext context = ServletActionContext.getServletContext();
耦合的Action,使我们的单元测试工作很难实现,使我们被迫要通过Http请求来测试我们写的Aciton,大大增加了工作量,解耦的话

,我们可以把一个Map<String,Object>集合传进去,这样好像真的有Http请求一样,达到了测试的目的。


Action的配置:<!-- action 元素用于对 action 进行配置。
   name 指定的就是用户访问的 URL,
   class 属性指定 action 的完整类名。
  -->
  <action name="helloWorld" class="demo.first.hello.HelloWorldAction2" method="login">
   <!--
    说明:用户访问任意资源名为 HelloWorld.action 的 URL 时,都将交给
    demo.first.HelloWorldAction 处理,当 execute() 方法返回 "success" 时, 给用户的
    View 为 "/helloworld.jsp",可以指定某一个方法进行处理,通过method指定或者,通过url
                                helloWorld!login.action进行指定使用login方法处理请求
   -->
   <result>/WEB-INF/pages/helloworld.jsp</result>
                        <!-- result 有两个属性,一个是name,另一个是type; name没有配置时,默认是success;
                              tytp 没有配置时,默认是dispather,如果需要其他的配置项,要显性写出-->
  </action>
 这里值得注意的是:
        <!--
      Struts配置的查找次序:
  struts-default.xml > struts-plugin.xml >
  struts.xml > struts.properties > web.xml
 -->
所以一些配置除了写在struts.xml文件还可以写在struts.propertites 或web.xml 都是可以的
如一些配置有利于我们调试的使用:
        <!-- 打开调试模式 -->
 <constant name="struts.devMode" value="true" />
 <!-- 使I18N资源文件可自动重新加载 -->
 <constant name="struts.i18n.reload" value="true" />
 <!-- 使Struts配置文件可自动重新加载 -->
 <constant name="struts.configuration.xml.reload" value="true" />
 <!-- 禁用浏览器缓存 -->
 <constant name="struts.serve.static.browserCache" value="false" />
        <!-- 允许action的名称使用"/"  -->
        <constant name="struts.enable.SlashesInActionNames" value="true"/>
result 的type 常用类型有: dispather(默认),redirect,redirectaction,chain;
dispather 相当于Servlet的请求分发
redirect  就相当于重定向;
redirectaction  重定向到一个action
chain  链式传递到下以个action

特殊列:     
                <action name="*">
   <result type="redirectAction">list</result>
  </action>

这个action没有配置到class,name="*",Struts2中,没有配置class的,struts认为是extends
ActionSupport ,name="*",*是通配符,整个action的意思是:当user使用的url访问不到其他action时
都可以到这个action来,默认返回一个”success“,后转到list.action,这样配置的作用就是,如果user乱输入一个访问action的

url地址,也不会出现不友好的页面,一样可以被这个action处理,返回一个默认的处理页面;
 
                <action name="*">
   <result>/WEB-INF/pages/wildcard/{1}.jsp</result>
  </action>
struts支持使用占位符,引用通配符的值,上面result的意思是:把通配符的值放在result中,这样就是返回view的一个url;
当在action里定义一个<param name="pk">{3}</param>,这样就必须使用到<interceptor-ref name="staticParams"/>这个拦截器

ognl=========》的使用

使用struts2的一大优势就是可以使用强大的ognl表达式,在ognl表达式中,可以调用方法,引用属性等等,更重要的是,ognl不但

可以读数据,而且可以写数据;使用ognl必须明白stack,在struts2的值栈中 request,session,application、action本身

parameters都在栈体下,使用ongl可以拿到他们,例如:#request.department.id,这样就可以拿到reqeustScope中的的department

的id属性,this是一个特殊对象存在于栈底,employees.{?#this.salary > 2000}。


coc==========》零配置
使用Struts2你就知道了,每个action都要写一堆配置,如果很多action的话 起不是要写很多的配置,自从java5的Annocation出来

后,就很多人想用annocation来代替xml的配置,但真的可以代替吗?是代替不了。但特定的开发环境,使用annocation还是带来很

大的便利的,如果我们的写的包名和类名符合规定的话 我们不需要再配置struts.xml文件了,struts提供了默认;
使用annocation要使用struts的struts2-convention-plugin-2.1.8.1.jar,这个jar包
首先可以在web.xml指定当前包:
<init-param>
 <param-name>struts.convention.package.locators.basePackage</param-name>
 <!-- 多个包间以逗号分隔 -->
 <param-value>demo.crud.actions</param-value>
</init-param>
这样的话,
struts会在所有包中检索包含actions或action结尾的包
包里面的类如:ListAction 或默认映射为/list.action
返回success的页面是/WEB-INF/content/list.jsp
如果你的项目就是这样的话 就不用写配置文件了
但我们还是可以通过如:@Result(name = "success", type = "redirect", location = "/list.action")
改变其默认设置的
@Action(value = "edit", results = {
  @Result(name="success", type="redirectAction", location="../list")
 })

同时可以利用@Action把一个方法声明为Action

@Result(name = Action.SUCCESS, type = "chain",
  params = {"actionName", "list", "namespace", "/"})

通过params可以设置actionName 和namespace的值通过这样的配置,这个action映射为/list.action

Interceptor=====================================》

Struts2的拦截器,比我的感觉,它很像一个Filter,功能是实现到达action前的url拦截处理,可以看出Interceptor是一个接口,

如果直接实现它,我们就要实现很多方法,所以建议extends它的抽象类AbstractInterceptor,这样我们就可以就可以创建一个我们
的拦截器了,自己创建的拦截器要在struts加上申明:如:<!-- 声明拦截器 --><interceptor name="authInterceptor" 

class="demo.interceptor.AuthInterceptor" />,这样我们定义的拦截堆就可以使用了,建议一般使用自己定义的拦截器和默认的拦

截堆  这样就可以使用defaultStack的功能;

同时xwork2也提供了一种标记可以实现拦截器同样的功能
 com.opensymphony.xwork2.interceptor.annotations.After;
 com.opensymphony.xwork2.interceptor.annotations.Before;
 com.opensymphony.xwork2.interceptor.annotations.BeforeResult;
这样拦截的代码可以和Action书写在一起,方便程序员的检查
使用时必须使用<interceptor-ref name="annotationWorkflow" />这个拦截器才可以使用@After、@Before、@BeforeResult;其功能

和拦截器一样

coc配置Interceptor
@InterceptorRefs({
 @InterceptorRef("defaultStack"),
 @InterceptorRef("annotationWorkflow")
})
这样声明就声明了拦截器,其他的coc同action之前讲的一样


struts2的i18n========================>

寻找资源的顺序  查找以当前类名相同的资源文件==》查找实现接口同名的资源文件==》查找父类,把父类设置为当前类重复第一步

的步骤==》看是否实现了ModleDriven如果实现了,就查找以返回类型的同名的资源文件==》查找当前包以package(**).properites

的资源文件。。。。。。

我们可以通过s标签生成url,带有参数,设置浏览器当前的语言,已达到国际化
生成的url:
<s:url id="chinese_url" action="user-list">
 <s:param name="request_locale" value="%{@java.util.Locale@CHINESE}" />
</s:url>
<s:url id="english_url" action="user-list">
 <s:param name="request_locale" value="@java.util.Locale@ENGLISH" />
</s:url>

再使用生成的url:
<s:a href="%{chinese_url}"><s:text name="user-list.lang.chinese" /></s:a>
&nbsp;
<s:a href="%{english_url}"><s:text name="user-list.lang.english" /></s:a>
这里,<s:text/>是用来读取资源文件的value值的。


struts2的文件上传:================================》

struts2的文件上传要使用到struts标签,其中提交方法必须为post enctype="multipart/form-data"
在处理上传的action中,有三个属性是确定的,file(上传的文件),fileContentType(文件的类型) fileFileName(文件名称,包括

格式),struts上传文件后 是保存在一个临时文件里,可以在struts文件通过:<constant name="struts.multipart.saveDir"

value="c:\\temp" />设置临时保存的文件路径;同时,也可以在上传文件的action的Interceptor设置参数来设置上传信息:
<interceptor-ref name="defaultStack">
 <!-- 设置可接受的最大字节数 -->
      <param name="fileUpload.maximumSize">256000</param>
 <!-- 设置可接受的文件类型 
      <param name="fileUpload.allowedTypes">
  image/gif,image/jpeg,image/pjpeg
     </param>
 -->
</interceptor-ref>
最后可以通过FileUtils.copyFile()方法把那个临时文件保存到你要求的路径,就完成了文件的上传。

struts的token验证======================》

1.在你需要token验证的页面添加<s:token />标签,
2.然后在处理这个页面数据的action配置里,增加一个Interceptor:
<interceptor-ref name="token">
   <param name="includeMethods">create</param>
</interceptor-ref>
param是指明那个方法需要token验证,
3.配置一个type:<result name="invalid.token" type="redirectAction">message</result>
name 属性是规定的,如果有看这个token拦截器源代码就知道,当token验证不通过时 回返回一个“invalid.token”的字符串。
所以必须有这么一个type
需要注意的是,你的action配置了一个拦截器,如果你还想使用defaultstack就必须加上这个引用
<interceptor-ref name="defaultStack" />
4完成


struts的===================validate验证:
1.使用框架验证:
struts2框架验证读取文件的顺序:验证框架首先在根目录下找validators.xml文件,没找到validators.xml文件,验证框架将调用默

认的验证设置,即default.xml里面的配置信息
设置验证策略时,规定采用的文件名为:ActionName-validation.xml
在这个文件上写上你要求的验证:如
<validators>
 <!-- 声明针对 user.account 属性的验证规则 -->
 <field name="user.account">
            <!-- field-validator type 是在validators.xml文件里的-->
  <field-validator type="requiredstring">
   <message key="error.user.account.empty">账号名不能为空</message>
  </field-validator>
 
  <field-validator type="stringlength">
   <param name="minLength">3</param>
   <param name="maxLength">10</param>
   <message key="error.user.account.length">账号名不能小于3个字符大于10个字符</message>
  </field-validator>
 </field>
 
 <field name="user.name">
  <field-validator type="requiredstring">
   <message key="error.user.name.empty">名称不能为空</message>
  </field-validator>
 </field>
</validators>
2.代码验证:
进行代码验证时:首先调用validate***()进行验证,再调用validate()方法进行验证;当验证不通过时 返回一个input;
故你的result type 要有input;

 

posted on 2011-06-14 14:36  唐朝  阅读(350)  评论(0编辑  收藏  举报