首页 > 代码库 > struts2学习笔记(一)—— 知识点扫描

struts2学习笔记(一)—— 知识点扫描

一、struts2的核心部件

(1)Configuration

(2)Action

(3)Interceptor

(4)Value Stack / OGNL

(5)Result Types

(6)Results / View Technology


二、architectural goals:

(1)separation  of concerns

(2)loose coupling

(3)testability

(4)modularization

(5)convention over configuration


1.在Action中访问Web资源:

(1)什么是WEB资源?

        HttpServletRequest 、HttpSession 、ServletContext 等原生的 Servlet API

(2)为什么访问WEB资源?

        B/S 的应用的 Controller 必须要访问 WEB 资源:向域对象中读写属性,读写 Cookie,获取 realPath。。。

(4)如何访问?

        I.和 Servlet API 解耦的方式:只能访问有限的 Servlet API对象,且只能访问其有限的方法(读取请求参数,读写域对象的属性,使 Session 失效。。。)

        > 使用 ActionContext

        > 实现 XXXAware 接口

        > 选用建议:若一个 Action 类中有多个 action 方法,且多个方法都需要使用域对象的 Map 或 parameters,则建议使用 Aware 接口的方式

        > session 对应的 Map 实际上是 SessionMap 类型

       II.和 Servlet API 耦合的方式:可以访问更多的 Servlet API 对象,且可以调用其原生的方法

        > 使用 ServletActionContext
        > 使用 ServletXXXAware 接口

2.struts.properties
    struts.xml主要负责管理应用中的Action映射,以及该Action包含的Result定义等。除此之外,还包含一个struts.properties文件:定义struts2框架的大量属性,开发者可以通过改变这些属性来满足应用的需求。
    struts.properties文件通常放在WEB-INF/classes路径下,其实,它的内容均可以在struts.xml中以<constant name="" value=http://www.mamicode.com/"">加载,或者在web.xml中以标签加载。

3.struts.xml
    在其中的action结点(请求与Action类的映射),可以通过 annotation 、web.xml startup parameters 和 alternate URL mapping schemes来代替。
    但是如果需要解决global results,exception handling和自定义拦截器栈,则必须要用strusts.xml
    struts-default.xml和strut.plugin.xml被自动包含进来。前者提供strust2框架的核心配置,后者提供特殊插件的配置。每一个plug-in jar文件都应该包含一个struts-plugin.xml文件
 (1)<struts>标签:包含其他所有的标签
 (2)<include>标签:引用一个其他的配置文件
 (3)<package>标签:属性abstract为true时,该标签内不能配置action;继承自struts-default package

4.Result Types
 (1)dispatcher类型 最常用 后台使用HttpServletRequest的RequestDispatcher来转发请求
          > 实现类:org.apache.struts2.dispatcher.ServletDispatcherResult
          > 两个属性
             <result name="success" type="dispacther">
                    <param name="location">/success.jsp</param>   //指定Action执行完毕后要转向的目标资源
                    <param name="parse">true</param>                    //true:解析location参数中的OGNL表达式;反之则不解析
             </result>


(2)redirect类型 后台使用HttpServletResponse的sendRedirect方法来请求重定向到指定的URL
         > 实现类:org.apache.struts2.dispatcher.ServletRedirectResult
         > 两个属性:同上
         > 适用场合:用户注册、在线调查等,不会造成刷新导致的重复提交问题
(3)redirectAction类型
         > 实现类:org.apache.struts2.dispatcher.ServletActionRedirectResult(继承自ServletRedirectResult)
         > 工作原理同redirect一样,区别是重新定向到另外一个action
(4)plainText类型
         > 实现类:org.apache.struts2.dispatcher.PlainTextResult
         > 可以输出JSP或HTML源代码
         > struts2框架自动完成对标记到实体引用或者字符引用的转换
         > 两个属性:location和charSet,后者代表输出页面内容时使用的字符编码
(5)全局结果
         > 在<global-results>标签内使用
(6)动态结果
         > 配置的时候不知道要执行哪一个结果,配置结果时使用了表达式,运行时框架解析表达式,根据表达式的值来确定要执行的结果
         > 在结果映射中,使用${...}语法访问的属性一定要在Action中存在,提供对应的JavaBean风格的getter方法。在JavaBean中实例变量名和属性名可以不同,使用${...}访问的是属性名

5.Interceptors
(1)要使某个拦截器能被需要它的Action使用,有两种配置方法:
        > 该方法没有拦截器配置的数量限制,唯一要求的是,拦截器的执行顺序就是在Action中配置的顺序
     
      <interceptors>
                    …
             <interceptor name="autowiring"
              class="interceptor.ActionAutowiringInterceptor"/>
     </interceptors>
     <action name="my" class="com.fdar.infoq.MyAction" >
          <result>view.jsp</result>
          <interceptor-ref name="autowiring"/>
     </action>


        > 在</package>之前使用<default-interceptor-ref name="autowiring"/>,但是只有一个拦截器才能被定义为默认的拦截器
(2)拦截器栈的表示和使用
<interceptor-stack name="basicStack">
    <interceptor-ref name="exception"/>
    <interceptor-ref name="servlet-config"/>
    <interceptor-ref name="prepare"/>
    <interceptor-ref name="checkbox"/>
    <interceptor-ref name="params"/>
    <interceptor-ref name="conversionError"/>
</interceptor-stack>
<action name="my" class="com.fdar.infoq.MyAction" >
    <result>view.jsp</result>
    <interceptor-ref name="basicStack"/>
</action>


(3)ActionInvocation提供了可以访问运行环境的权限
(4)struts2将它的核心功能放到拦截器中实现,而不是分散到Action中实现,有利于系统的解耦,使得功能的实现类似于个人电脑的组装,变成了可插拔的:需要某个功能就插入一个拦截器,不需要某个功能就拔出一个拦截器。你可以任意组合拦截器来为Action提供附加功能,而不需要修改Action
(5)实现Interceptor接口:
        >init
        >destroy
        >intercept:在Action执行前被调用,拦截器为Action提供的附加功能在这里实现。 利用invocation参数可以获取Action执行的状态。如果要继续执行后续部分(余下的拦截器、Action、Result)可以调用invocation.invoke();如果要终止后续的执行,可以直接返回一个结果码,框架将根据这个结果码来呈现对应的结果视图
(6)拦截器执行顺序:
我们可以以invocation.invoke()为界,将拦截器中的代码分成2个部分,在invocation.invoke()之前的代码,将会在Action之前被依次执行,而在invocation.invoke()之后的代码,将会在Action之后被逆序执行。
        【计算Action执行时间的实例】:
 public String intercept(ActionInvocation invocation){
         long startTime=System.currentTimeMillis();
         String result=invocation.invoke(); //拦截点
         long executionTime=System.currentTimeMillis()-startTime;
         System.out.println("Action的执行花费的毫秒数是:"+exexutionTime);
         return result;
}


(7)MethodFilterInterceptor可以指定要拦截或者排除的方法列表,通过指定included和excluded方法列表来实现,例如:
 public String intercept(ActionInvocation invocation){
         long startTime=System.currentTimeMillis();
         String result=invocation.invoke(); //拦截点
         long executionTime=System.currentTimeMillis()-startTime;
         System.out.println("Action的执行花费的毫秒数是:"+exexutionTime);
         return result;
}

(8)拦截器必须是无状态的,换句话说,在拦截器类中不能有实例变量。
(9)如果包继承自struts-default包,那么defaultStack拦截器栈将是默认的拦截器引用
(10)PreResultListener接口
           >在Action执行之后、Result执行之前得到通知,从而在视图呈现给用户之前做一些处理
           >实例需要手工注册,在拦截器调用invocation.invoke()方法之前调用invocation.addPreResultListener()方法注册PreResultListener

6.Value Stack/ OGNL 
  > Value Stack : a stack of objects
  > OGNL:access objects within the value stack
 (1)Value Stack中Object的种类及顺序
  > Temporary Objects
  > The Model Object
  > The Action Object:the action being executed
  > The Named Objects:#application #request #session #attr #parameters
(2)strust2的值栈允许存在许多虚拟根对象:将OGNL上下文设置为ActionContext,并将值栈作为OGNL的根对象
(3)top 结合 [N].xx语法可以访问栈中的任意对象
(4)struts2框架总是把Action实例放置在栈顶,因为在Action在值栈中,而值栈又是OGNL的根,所以引用Action的属性可以省略#标记
(5)struts2中的命名对象
        > #parameters.XX 或者 #parameters[‘XX]]:用于访问请求参数,本质上parameters是一个Map对象,用HttpServletRequest对象中的请求参数构造的,一旦对象创建好了(在Action实例之前就创建好了),它和HttpServletRequest就没有关系了,所以只读不可写(写了没有效果)
        > #request
        > #session
        > #application
        > #attr:PageContext
(6)值栈能够线程安全地为每个请求提供公共的数据存取服务
        > 当有请求到达时,struts2会为每个请求创建一个新的值栈,也就是说,值栈和请求是一一对应的,不同的请求,值栈也不一样,而值栈封装了一次请求所有需要操作的相关数据
(7)怎么讲struts2值栈中的对象删除?
        > ValueStack 对象。这个对象贯穿整个 Action 的生命周期(每个 Action 类的对象实例会拥有一个 ValueStack 对象)。当 Struts 2 接收到一个 .action 的请求后,会先建立 Action 类的对象实例,但并不会调用 Action 方法,而是先将 Action 类的相应属性放到 ValueStack 对象的顶层节点( ValueStack 对象相当于一个栈)。 
          所以删除操作不了。


7.OGNL
(1)为什么使用OGNL?
         > 取代Java代码
         > 简化数据访问的方式
         > 提供更清晰的视图层实现
(2)OGNL表达式的计算都是围绕OGNL上下文来进行的,OGNL上下文实际上是一个Map对象,它可以包含许多JavaBean对象,这些对象中有一个特殊的根对象。
(3)表达式的基础单元:导航链
(4)OGNL提供调用任何方法的能力
(5)调用静态方法:@class@method
(6)调用构造方法:new ,必须使用完整的限定类名
(7)投影、选择

8.标签
(1)通用标签
         >数据标签
         >控制标签
(2)UI标签
         >表单标签
         >非表单标签
         >Ajax标签