struts2知识点

1,Struts1和Struts2的区别和对比 

1 Struts1要求Action类继承一个抽象基类。Strut1的一个普遍问题是使用抽象类编程而不是接口。 

2 Struts 2 Action类可以实现一个Action接口,也可实现其他接口,使可选和定制的服务成为可能。

  Struts2提供一个ActionSupport基类去 实现 常用的接口。Action接口不是必须的,

  任何有execute标识的POJO(javabean)对象都可以用作Struts2的Action对象。 

 

3 线程模式: 

 Struts1 Action是单例模式并且必须是线程安全的,因为仅有Action的一个实例来处理所有的请求。单例策略限制了Struts1 Action能作的事,

 并且要在开发时特别小心。Action资源必须是线程安全的或同步的。 

 Struts2 Action对象为每一个请求产生一个实例,因此没有线程安全问题。(实际上,servlet容器给每个请求产生许多可丢弃的对象,

 并且不会导致性能和垃圾回收问题) 

 

4 Servlet 依赖: 

  Struts1 Action 依赖于Servlet API ,因为当一个Action被调用时HttpServletRequest 和 HttpServletResponse 被传递给execute方法。 

  Struts 2 Action不依赖于容器,允许Action脱离容器单独被测试。如果需要,Struts2 Action仍然可以访问初始的request和response。

  但是,其他的元素减少或者消除了直接访问HttpServetRequest 和 HttpServletResponse的必要性。 

 

5 可测性: 

  测试Struts1 Action的一个主要问题是execute方法暴露了servlet API(这使得测试要依赖于容器)。

   一个第三方扩展--Struts TestCase--提供了一套Struts1的模拟对象(来进行测试)。 

  Struts 2 Action可以通过初始化、设置属性、调用方法来测试,"依赖注入"支持也使测试更容易。 

 

6 捕获输入: 

  Struts1 使用ActionForm对象捕获输入。所有的ActionForm必须继承一个基类。

  因为其他JavaBean不能用作ActionForm,开发者经 常创建多余的类捕获输入。

  动态Bean(DynaBeans)可以作为创建传统ActionForm的选择,但是,

  开发者可能是在重新描述(创建)已经存 在的JavaBean(仍然会导致有冗余的javabean)。 

  Struts 2直接使用Action属性作为输入属性,消除了对第二个输入对象的需求。

  输入属性可能是有自己(子)属性的rich对象类型。Action属性能够通过 web页面上的taglibs访问。

  Struts2也支持ActionForm模式。rich对象类型,包括业务对象,能够用作输入/输出对象。

  这种 ModelDriven 特性简化了taglib对POJO输入对象的引用。 

 

7  表达式语言: 

  Struts1 整合了JSTL,因此使用JSTL EL。这种EL有基本对象图遍历,但是对集合和索引属性的支持很弱。 

  Struts2可以使用JSTL,但是也支持一个更强大和灵活的表达式语言--"Object Graph Notation Language" (OGNL). 

 

8  绑定值到页面(view): 

  Struts 1使用标准JSP机制把对象绑定到页面中来访问。 

  Struts 2 使用 "ValueStack"技术,使taglib能够访问值而不需要把你的页面(view)和对象绑定起来。

  ValueStack策略允许通过一系列名称相同但类型不同的属性重用页面(view)。 

 

9  类型转换: 

  Struts 1 ActionForm 属性通常都是String类型。Struts1使用Commons-Beanutils进行类型转换。每个类一个转换器,对每一个实例来说是不可配置的。 

  Struts2 使用OGNL进行类型转换。提供基本和常用对象的转换器。 

 

10 校验: 

  Struts 1支持在ActionForm的validate方法中手动校验,或者通过Commons Validator的扩展来校验。同一个类可以有不同的校验内容,但不能校验子对象。 

  Struts2支持通过validate方法和XWork校验框架来进行校验。XWork校验框架使用为属性类类型定义的校验和内容校验,来支持chain校验子属性 

 

11 Action执行的控制: 

 Struts1支持每一个模块有单独的Request Processors(生命周期),但是模块中的所有Action必须共享相同的生命周期。 

 Struts2支持通过拦截器堆栈(Interceptor Stacks)为每一个Action创建不同的生命周期。堆栈能够根据需要和不同的Action一起使用。

 

2 Struts2请求流程 

1、客户端发送请求 (客户端初始化一个指向Servlet容器(如Tomcat)的请求)

2、请求经过一系列过滤器(如ActionContextCleanUp、SiteMesh等),ActionContextCleanUp-->FilterDispatcher 

3、FilterDispatcher通过ActionMapper来决定这个Request需要调用哪个Action 

4、如果ActionMapper决定调用某个Action,FilterDispatcher把请求的处理交给ActionProxy,

5、ActionProxy通过Configuration Manager询问Struts配置文件(Struts.xml),找到需要调用的Action类。

6、ActionProxy创建一个ActionInvocation的实例 

7、ActionInvocation调用真正的Action,当然这涉及到相关拦截器的调用 

8、Action执行完毕,ActionInvocation创建Result并返回,返回结果

 

 

3步骤

 

 

一 导包

二 web.xml  配置过滤器

  

        struts2

        org.apache.struts2.dispatcher.FilterDispatcher

 

  

 

  

        struts2

        /*

  

 

 

 

三   src目录下建立 struts.xml

    

        "http://struts.apache.org/dtds/struts-2.0.dtd">

 

/xxx.jsp

    

 

4一些常识:

   可以有多个包,每个包有一个命名空间

   一个包里有多个action,一个action里有多个result

   访问action时先以命名空间查找

  开发模式的常量设置:将中的value值改为true。  

 

 

     .action 

    不带类名与包名  逐层访问路径  默认 result  success  继承extends="struts-default"(为什么呢,后面拦截器会有说明)

    包名 命名空间  寻找顺序(最精确匹配)

    先找命名空间,如果在该命名空间不存在该action则报错[unknown location]

   ,当命名空间存在该action时,则可以在该命名空间下后面紧跟其它路径逐层访问 当逐层访问路径与有命名空间冲突时,以有命名空间的为主。

     修改后缀名的常量

 

  5

   原因: struts 2   使用 filter 实现, 的机制是 servlet 

   目前解决办法是: 

      1、用form表单提交

      2、; 

      3、 

      4、通过过滤器改变请求地址。 

        配置web.xml 

 

  struts2 

  /* 

  REQUEST 

  FORWARD   

    

 

       5、可以用s:url标签 

 

   6  类名 

     实现Action与不实现action接口

     不extends ActionSupport   重写execute方法 

     extends ActionSupport     重写execute方法

      ?传值注意  method=post

       表单提交  用 method=post

 

    7  struts2 中 Actionsupport 的作用 

      (1)实现Action接口 具备5个常量

      (2)数据校验,Action接口的基础上还定义了一个validate()方法

      (3)国际化

 

   8    Action 跟 Actionsupport 的区别 

    当我们在写action的时候,可以实现Action接口,也可以继承Actionsupport这个类.到底这两个有什么区别呢? 

Action接口有: 

public static final java.lang.String SUCCESS = "success"; 

public static final java.lang.String NONE = "none"; 

public static final java.lang.String ERROR = "error"; 

public static final java.lang.String INPUT = "input"; 

public static final java.lang.String LOGIN = "login"; 

public abstract java.lang.String execute() throws java.lang.Exception; 

而Actionsupport这个工具类在实现了Action接口的基础上还定义了一个validate()方法,

重写该方法,它会在execute()方法之前执行,如校验失败,会转入input处,必须在配置该Action时配置input属性。 

另外,Actionsupport还提供了一个getText(String key)方法还实现国际化,该方法从资源文件上获取国际化信息. 


  9从  action属性到页面的传值  bean list  bena中bean  bean中list  list中bean map 
      action属性必须提供get方法




字符串判断
数字类型判断

10动态方法
   1感叹号定位方法  action名!方法名.action
   2 method定位方法   配置多个action 
   3 通配符匹配法(action中的name  class  method都支持通配符 result也支持)

  action的匹配顺序 先找最精确匹配 当用通配符匹配时 配置在前面的优先匹配

11

  全局结果与局部结果 ----- 全局异常与局部异常
  /ggg.jsp
  全局结果 所有的action共用   局部结果 自己的action用 当两者重名时,优先选择局部结果


全局异常与局部异常(附件 struts1.x中的异常处理.txt)
 
exception="异常类型如java.lang.Exception" >
 

如假设有result中配置/geror.jsp

则在geror.jsp页面可以使用Struts2的标签来输出异常信息
全局异常 所有的action共用  局部异常 自己的action用 当两者重名时,优先选择局部异常


12类型转换
     1 内建类型转换器   
     
        常规类型的转换:
      比如表单提交的信息有 用户名,生日, 年龄, Action中对应的数据类型分别是 String, Date, int. Struts2会自动完成.
      Struts2内建了常用的类型转换器,如String ,boolean,char,int,long,float,double,Date, 
        数组(假定元素是String类型), 集合(假定元素是String类型,用ArrayList封装)


        利用ognl的内建支持  
      <1>直接把页面属性转换成action中的bean属性,页面属性分开,假设action中bean属性名为user  则如下
        
        
       在页面输入值后  action中bean属性名为user可以直接拿到值
      <2>直接把页面属性转换成action中的集合属性,不需要转换器
       map版
         第一个用户名:
         第一个密码:
         第二个用户名:
         第二个密码:
       list或数组版本
         第一个用户名:
         第一个密码:
         第二个用户名:
         第二个密码:




    2 自定义
      从范围来讲 有局部转换器和全局转换器  从实现的角度而言有基于ognl的转换和基于strut2转换
        
        
       (1) 写自定义类型转换类 

      ognl的转换   extends DefaultTypeConverter 重写convertValue方法

         举例 把字符串转换成bean对象 bean作为action中的一个属性 bean名为User,action中的bean属性名为user
         假设把页面上的用户名和密码,用户名和密码在同一个文本框输入,用,好隔开, 代码如下
         public Object convertValue(Map context, Object value, Class toType)
{
        if (toType == User.class )
{
String[] params = (String[])value;
User user = new User();
String[] userValues = params[0].split(",");
user.setName(userValues[0]);
user.setPass(userValues[1]);
return user;

        }
else if (toType == String.class )
{
User user = (User) value;
return "<" + user.getName() + "," + user.getPass() + ">";
        } 
        return null ;
      } 


       基于struts2的转换  extends StrutsTypeConverter  编写convertFromString与convertToString方法

         public Object convertFromString(Map context, String[] values, Class toClass)
{
User user = new User();
String[] userValues = values[0].split(",");
user.setName(userValues[0]);
user.setPass(userValues[1]);
return user;
    }

        @Override
        public String convertToString(Map context, Object o)
{
User user = (User)o;
return "<" + user.getName() + "," + user.getPass() + ">";

        }



         
      (2) 配置类型转换(局部配置与全局配置)
          局部类型转换器只在本action内有效,全局类型转换器在所有action内有效
         如果是配置局部类型转换器,则在与Action类同包目录下建立Action类名-conversion.properties文件,里面配置
            action中的bean属性名=包名.转换器类名
        如果是配置全局类型转换器,则在src目录下建立xwork-conversion.properties,里面配置
             包名.被转换的类名(action中的bean属性类名)=包名.转换器类名


     
      
   

     
        把页面属性转换成action中的集合属性   有2种实现方式
        (1 action中集合属性使用泛型指定里面元素类型 2 在局部配置文件配置Element_action中的集合属性名=包名.集合元素里的类名)
        页面信息
        请输入用户1信息:
        请输入用户2信息:
    
       


    3 错误处理
       当类型转换出现错误,自动转发到input页面,  在页面用显示全部错误
       在资源文件修改默认的错误显示信息
       xwork.default.invalid.fieldvalue={0}字段类型转换失败!
      
13 校验
1 继承Actionsupport 重写validate方法
             this.addFieldError("username", this.getText("xxx"));
 this.addFieldError("username1", "yyy");

     在页面用显示全部错误
     显示某个错误
      
      
      
  2 validateXxx方法
  3 strut2的校验流程
    
  4 校验框架
    每个Action类有一个校验文件,命名 Action类名-validation.xml,且与Action类同目录,
 当校验文件的取名为ActionClassName-validation.xml时,会对 action中的所有处理方法实施输入验证。
 如果你只需要对action中的某个action方法实施校验,那么,校验文件的取名应为:ActionClassName-ActionName-validation.xml,
 其中ActionName为struts.xml中action的名称。例如:在实际应用中,常有以下配置: 
  /WEB-INF/page/message.jsp 
   /WEB-INF/page/addUser.jsp 
    
   UserAction中有以下两个处理方法: 
    public String add() throws Exception{ 
     .... 
   } 
    public String update() throws Exception{ 
    .... 
   }  
要对add()方法实施验证,校验文件的取名为: UserAction-user_add-validation.xml 
要对update()方法实施验证,校验文件的取名为: UserAction-user_update-validation.xml ld> 

   客户端校验:功能不咋的  不建议使用
     1,form的主题(theme)一定不能设定为simple
     2,将form的validate属性设置为true

字段校验  字段用什么校验器来校验  
非字段校验是用校验器校验什么字段  
通俗点讲: 字段校验:校验谁,用什么方法 非字段校验:用什么校验,校验谁 



     字段校验   
        举例  

   内建的校验器在 xwork  lib包中  如 xwork-2.0.7\com\opensymphony\xwork2\validator\validators\default.xml  文件中


        
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">

true
必须输入名字
您输入的用户名只能是字母和数组,且长度必须在4到25之间
true
必须输入密码
您输入的密码只能是字母和数组,且长度必须在4到25之间
1
150
年纪必须在1到150之间
    
1900-01-01
2050-02-21
年纪必须在${min}到${max}之间

    非字段校验 
  
  需要被检验的字段
  参数值
  校验错误信息
 


举例
    

name
true
${getText("name.requried")}
name
true
${getText("name.regex")}
pass
true
${getText("pass.requried")}
pass
true
${getText("pass.regex")}
age
1
150
${getText("age.range")}
birth
1900-01-01
2050-02-21
${getText("birth.range")}


      
  校验国际化配置 如该种方式出错,则采用${getText("key名")} 
  向资源文件传递参数 ${getText("key名",{'aa','bb'})}

  
   模型驱动的校验 
   模型驱动的配置 需要为模型驱动的action中bean提供get方法,当然喜欢加上set方法也可以
   配置
    
模型驱动用户的:





    visitor校验   2个校验文件  当属性为javabean时的校验  区别于模型驱动
     
     第一个校验文件  Action类名-validation.xml中的配置如下
      
userContext
true
用户的:
  
     jsp页面输入框示例
    
     

     第2个校验文件 bean类名-第一个校验文件context参数值-validation.xml 如User-userContext-validation.xml,
     该文件中就可以写校验bean中的属性,如同前面的校验
       
 

14访问 servletapi
    1.  非IoC方式

   要获得上述对象,关键Struts 2.0中com.opensymphony.xwork2.ActionContext类。我们可以通过它的静态方法getContext()获取当前Action的上下文对象。 
   另外,org.apache.struts2.ServletActionContext作为辅助类(Helper Class),可以帮助您快捷地获得这几个对象。 
                             HttpServletRequest request = ServletActionContext.getRequest(); 
                             HttpServletResponse response = ServletActionContext.getResponse(); 
                             HttpSession session = request.getSession();

   如果你只是想访问session的属性(Attribute),你也可以通过ActionContext.getContext().getSession()获取或添加session范围(Scoped)的对象。

    2. IoC方式
       要使用IoC方式,我们首先要告诉IoC容器(Container)想取得某个对象的意愿,通过实现相应的接口做到这点
       实现相关接口SessionAware, ServletRequestAware, ServletResponseAware
      private Map att;
      private HttpServletRequest request;
      private HttpServletResponse response;    
   
  publicvoid setSession(Map att) {
      this.att = att;
  }
  
  publicvoid setServletRequest(HttpServletRequest request) {
      this.request = request;
  }
  
  publicvoid setServletResponse(HttpServletResponse response) {
      this.response = response;
  }

 
15 struts2  中的ognl 以及标签语法
   
   两个栈  第一个是值栈ognl上下文(value stack)  第2个是ActionContext 栈 访问里面的数据ActionContext 栈通过前面加上 #号实现  
   
 Struts 2中的表达式语言

Struts 2支持以下几种表达式语言:

1.      OGNL(Object-Graph Navigation Language),可以方便地操作对象属性的开源表达式语言; 

2.      JSTL(JSP Standard Tag Library),JSP 2.0集成的标准的表达式语言; 

3.      Groovy,基于Java平台的动态语言,它具有时下比较流行的动态语言(如Python、Ruby和Smarttalk等)的一些起特性; 

4.      Velocity,严格来说不是表达式语言,它是一种基于Java的模板匹配引擎,具说其性能要比JSP好。 

Struts 2默认的表达式语言是OGNL,原因是它相对其它表达式语言具有下面几大优势:

1.      支持对象方法调用,如xxx.doSomeSpecial(); 

2.      支持类静态的方法调用和值访问,表达式的格式为@[类全名(包括包路径)]@[方法名 |  值名],例如:@java.lang.String@format('foo %s', 'bar')或@tutorial.MyConstant@APP_NAME; 


3.      支持赋值操作和表达式串联,如price=100, discount=0.8, calculatePrice(),这个表达式会返回80; 

4.      访问OGNL上下文(OGNL context)和ActionContext; 

5.      操作集合对象。 


  “#”主要有三种用途:  
    1.      访问OGNL上下文和Action上下文,#相当于ActionContext.getContext();下面有几个ActionContext中有用的属性: 

 parameters
 包含当前HTTP请求参数的Map
 #parameters.id[0]作用相当于request.getParameter("id")
 
request
 包含当前HttpServletRequest的属性(attribute)的Map
 #request.userName相当于request.getAttribute("userName")
 
session
 包含当前HttpSession的属性(attribute)的Map
 #session.userName相当于session.getAttribute("userName")
 
application
 包含当前应用的ServletContext的属性(attribute)的Map
 #application.userName相当于application.getAttribute("userName")
 
attr
 用于按request > session > application顺序访问其属性(attribute)
 #attr.userName相当于按顺序在以上三个范围(scope)内读取userName属性,直到找到为止
 
2.      用于过滤和投影(projecting)集合,如books.{?#this.price<100}; 
      
            
  • - $
  •         
        

      问题:?#this的多个判断问题  &&


    3.      构造Map,如#{'foo1':'bar1', 'foo2':'bar2'}。  之前讲过
     

     %的特性  计算表达式   类似javascript中的eval函数  可用s:url举例说明%用法  
    “%”符号的用途是在标志的属性为字符串类型时,计算OGNL表达式的值

      
       计算boolean值(带有转义符的):
     
      带有属性的:
     
     既带有转义符又带有属性的:
     

    表示式语言符号
      1.在Freemarker、Velocity或者JSTL的表达式语言的JavaBean对象的标准文本
      

    Username: ${user.username}

      2.在值栈中的一个username属性
     
      3. 引用值栈中的属性的另一种方式
     
     
        es
     
    Espanol
      4. 在Session Context中获得user对象的userName属性
     
      5. 在一个静态map中,像("username","trillian")一样
      

      
    $”有两个主要的用途
    1.      用于在国际化资源文件中,引用OGNL表达式,参考前面的国际化校验配置
    2.      在Struts 2配置文件中,引用OGNL表达式,如 
                            
                ListPhotos.action?albumId=${albumId}
            


    16拦截器
        拦截器,用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。
        拦截器是AOP(Aspect-Oriented Programming 面向方面编程)中的一种实现策略。
        1 用代理模式与动态代理编写拦截器
          

           所谓Dynamic Proxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,
           然后该class就宣称它实现了这些interface。你当然可以把该class的实例当作这些interface中的任何一个来用。
           当然啦,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,
           在生成它的实例时你必须提供一个handler,由它接管实际的工作
            那么如何实现动态代理呢
    1 写一个动态代理,implements InvocationHandler接口,实现方法
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
     
      method.invoke(sub,args);
    return null;
    }
    2 调用 ,
    真实实现类名 xxx = new 真实实现类名(); // 在这里指定被代理类
    InvocationHandler ds = new DynamicSubject(xxx); // 初始化代理类
    接口  接口变量= (接口) Proxy.newProxyInstance(xxx.getClass().getClassLoader(), xxx.getClass().getInterfaces(), ds);
                           接口变量.方法
     
                   /**
    * 从以上可以看出,动态代理可以任意指定被代理的类,即真实对象类,而代理模式则无法实现该功能,
    * 因为他把真实对象的写死在代理类里,如果要按照上述的方法使用代理模式,那么真实角色必须是事先已经存在的,并将其作为代理对象的内部属性。但是
    * 实际使用时,一个真实角色或其接口必须对应一个代理角色,如果大量使用会导致类的急剧膨胀
    */

          
        2  struts2拦截器
          解压strut2的核心包,根目录下struts-default.xml中有struts2的拦截器配置
        

           拦截器几乎完成了Struts2框架70%的工作,包括解析请求参数、将请求参数赋值给Action属性、执行数据校验、
           文件上传……,Struts2设计的灵巧性,更大程度地得益于拦截器设计,当需要扩展Struts2功能时,只需要提供对应拦截器,
           并将它配置在Struts2容器中即可;如果不需要该功能时,也只需要取消该拦截器的配置即可。
           这种可插拔式的设计,正是软件设计领域一直孜孜以求的目标。
    实际上,Struts2的精髓就在于拦截器,掌握了Struts2的拦截器机制,你就可以说精通了Struts2。
    从某个角度来看,我们可以把Struts2框架理解成一个空壳,而这些拦截器像一个一个抽屉,随时可以
    插进入,也可以拔出来——这是软件产品一直追求的目标。
    如果你喜欢,你可以把Struts2的全部插件拔出,那么Struts2就成了一个空容器——
    而这种空,正是 Struts2的魅力,你可以把任何自己想要的东西填入进去,甚至包括自己完全实现这个框架。

    另一方面,因为Struts2的插件机制,Struts2提供了无限扩展的可能性,你可以把自己想要的任何
    东西做成插件,然后填入Struts2——这样的结果是:一个企业,一个团队,可以把自己业务相关的东西
    做成插件,随时随地地复用。
    也就是说:如果你想要,你可以把Struts2改造成属于自己的框架。

    当然,Struts2也内建了大量的拦截器,这些拦截器以name-class对的形式配置在struts-default. xml文件中,其中name是拦截器的名字,就是以后使用该拦截器的唯一标识;class则指定了该拦截器的实现类,如果我们定义的package继承了Struts2的默认struts-default包,则可以自由使用下面定义的拦截器,否则必须自己定义这些拦截器。
     3  自定义拦截器
         (1)编写拦截器类,继承AbstractInterceptor类 重写intercept(ActionInvocation arg0)方法
              调用用参数类ActionInvocation的invoke方法,即 String result= arg0.invoke();  返回该result=
              invoke就是回调使用了该拦截器的action得相应方法,此时可在该方法执行前后加入我们想要的代码,达到我们拦截action的目的
     利用 arg0.getAction()方法还可以得到拦截器拦截的action实例 
    public String intercept(ActionInvocation arg0) throws Exception {
    //  LoginAction loginaction=LoginAction(arg0.getAction());
      System.out.println("执行ction之前");
     String result= arg0.invoke();
      System.out.println("执行ction之后");
    return result;
    }
        、(2)在struts.xml配置拦截器
            
       
      属性值
    /welcome.jsp
    /error.jsp

         多个拦截器在一起组成一个拦截器栈
              
                    
                    
                    
                

        使用拦截器栈 与 使用拦截器一样语法

         当配置一个包时,可以为其指定默认的拦截器,每个包只能有一个默认的拦截器,一旦为某个包指定了默认的拦截器,
         如果该包中的action没有指定
         自己的拦截器,则action使用包指定的默认拦截器,但是一旦为action指定了自己拦截器,
         则包的默认拦截器将会失效,如果还想
         使用包的默认拦截器,则必须显示的指定,我们的包继承另一个包时,也继承了另一个包的默认拦截器,
         当然我们可以定义自己包的默认拦截器覆盖之
         从这里可以解释为什么我们刚刚开始学struts2的时候老是extends="struts-default" 
         因为struts-default包中的默认拦截器是个好东东

         配置默认拦截器 在 包package中 放后面
          
         
            上面拦截器会拦截action中的所有方法 要想拦截某个方法怎么办  拦截指定方法  
     编写拦截器类,extends MethodFilterInterceptor   MethodFilterInterceptor是AbstractInterceptor的子类
     重写doIntercept方法
        public String doIntercept(ActionInvocation invocation)
    throws Exception
    {
    //  LoginAction loginaction=LoginAction(arg0.getAction());
          System.out.println("执行action方法之前");
          String result= arg0.invoke();
         System.out.println("执行action方法之后");
    return result;
    }
         
           使用配置指定拦截的方法
            
    execute,haha        
    execute              


          可以重复使用一个拦截器,拦截器的执行顺序是在方法执行前,先配先执行,在方法执行后,后配先执行


          拦截结果的监听 是在action结束后,返回result之前的一个监听器,可以在该监听器里写我们的代码,以便在返回结果前执行,
          这个监听器通过手动注册在拦截器内部的
          监听器示例代码  implements PreResultListener
            public class MyPreResultListener implements PreResultListener
             {
    public void beforeResult(ActionInvocation invocation,String resultCode)
    {
    System.out.println("返回的逻辑视图为:" + resultCode);
    }
          }

             拦截器示例代码
       public class BeforeResultInterceptor extends AbstractInterceptor
               {
       public String intercept(ActionInvocation invocation) throws Exception
    {
    invocation.addPreResultListener(new MyPreResultListener()); //注册监听器
    System.out.println("execute方法执行之前的拦截...");
    String result = invocation.invoke();
    System.out.println("execute方法执行之后的拦截......");
    return result;

         }
               }

         监听器代码在action结束后,返回结果前执行,和在action结束后在拦截器内部写的代码相比, 监听器代码把action结束后的代码
         放到监听器似乎更精确和清晰些

           

         给拦截器栈传递参数时会出现一个问题,当拦截器栈中拦截器类中的属性名相同时,不知道这个参数到底要传给那个拦截器,为了
         解决这个问题,可作如下配置
            
    属性值



    17 struts2的四个主题
    simple,xhtml(默认主题),css_xhtml和ajax,这4个主题的模板文件放在Struts2的核心类库里(struts2-core.jar包)。template目录下
          也可以自定义自己的主题,建议继承它的已有主题
          simple主题是最简单的主题,它是最底层的结构,主要用于构建附加的功能或者行为(例如在此主题基础上进行扩展),
          使用simple主题时,每个UI标签只生成一个简单的HTML元素,不会生成其他额外的内容。

    Struts2的xhtml, css_xhtml主题都是对simple主题的包装和扩展。

    xhtml主题是Struts2的默认主题,它对simple主题进行扩展,在该主题的基础上增加了如下附加的特性:

    1,针对HTML标签(如textfield和select标签)使用标准的两列表格布局。

    2,每个HTML标签的Label,即可以出现在HTML元素的左边,也可以出现在上边,这取决于labelposition属性的设置。

    3,自动输出校验错误信息。

    4,输出JavaScript的客户端校验。

    css_xhtml主题则对原有的xhtml主题进行了扩展,在xhtml主题基础上加入了CSS样式控制。

    ajax主题目对xhtml主题目进行了扩展,在xhtml主题上为每个标签提供了额外的Ajax支持。
    ajax主题的Ajax支持是以Dojo和DWR为基础的。ajax主题在xhtml主题基础上增加了如下特性:

    1,支持Ajax方式的客户端校验。

    2,支持远程表单的异步提交(最好和submit标签一起使用)。

    3,提供高级的div标签,允许实现局部更新部分HTML的功能。

    4,提供高级的a标签,允许动态加载并执行远端的javaScript代码。

    5,提供支持ajax的tabbedPanel。

    6,提供"富客户端"模型的pub-sub事件模型。

    5,Struts2的表单标签

    18零配置
        零配置  约定大于配置原则 使用注解编程替代xml配置     首先要澄清一点,这里说的零配置并不是一点配置都没有,只是说配置很少而已
         
          2.0的零配置
          web.xml配置加载的action所在的包名,在过滤器中作如下修改
          
    struts2
    org.apache.struts2.dispatcher.FilterDispatcher
    actionPackages
    com

      表名要加载com包下的aciton   命名空间默认为"/"

      
       在action类中配置
            @Namespace("/aaa")
            @Results({
            @Result(name="success", type=NullResult.class, value="/success.jsp")
    })

         例如
           @Results({
    @Result(name="success",type=NullResult.class,value="/xxx.jsp")
          })
        public class Test extends ActionSupport {
    public String execute() throws Exception {
    return super.execute();
    }

       直接访问http://localhost:8080/struts20zero/类名(首字母小写).action
        
        当类名以Action结尾时候,则Action可以省略

        如类名XxxAction,则访问 直接访问http://localhost:8080/struts20zero/xxx.action
        如果有Xxx类的action。如果实在同一命名空间下,前面的应该会得到匹配
        如果是早不同的包名下,则与包名的字母排列顺序有关,后面的一半会执行


         

      19Convention Plugin插件
       
            包命名习惯来指定Action位置
    " 命名习惯制定结果(支持JSP,FreeMarker等)路径
    " 类名到URL的约定转换
    " 包名到命名空间(namespace)的约定转换
    " 遵循SEO规范

    你可能感兴趣的:(Java,web开发)