Struts 2.0全面分析

2019-04-13 22:16发布

                                                                 Struts 2.0                                                                                                   struts 1---前端控制+应用控制+命令模式
webwork ---控制器+拦截器+代理 Struts 2.0 继承了WebWork的设计理念,并没有继承struts 1,所以与struts 1是截然不同的~!
-------------------------------------------------------
Struts 2.0的简单实例:
web.xml中
   struts2
   org.apache.struts2.dispatcher.FilterDispatcher


   struts2 
   /*

------------------------------
action类继承 Action接口或者ActionSupport接口
如:public class LoginAction implements Action{
   private String name=null; 然后提供set,get方法    //封装参数名为name的值,对应前台的参数
   private String password=null; 然后提供set,get方法//封装参数名为password的值,对应前台的参数
   private UserVo user=null; 然后提供set,get方法// 用对象的方式,封装对象UserVo的值
   public String execute() throws Exception{
     System.out.println(name+"  "+password);
     System.out.println(user.name+user.password);//那么在前台jsp页面中要写成这样前台和action之中的属性保持一致!
     return Action.SUCCESS;
   }
 
} ------------------------------------------------------------
struts.xml 不同以往,写在src目录下~!
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">

   --用于组织拦截器,action对象,返回类配置的一套逻辑单位
       -name 标识名称
       -namespace  package映射的url地址(可有可无,倘若配置上名为girl,那么工程要加入girl这一层目录
       -abstruct:若为true时,struts2 框架不会使用该配置生成配置封装信息
      --用于定义返回值类型,struts2的执行结果可以生成哪些响应格式
      --在action的执行中,需加入的拦截器对象
     
            -name action的组件标识名 //前台页面请求action="…….action"  不再是…….do
            -class action类名
            -method 讲请求转发到指定的方法中
            要返回的类型,或路径
                -name 返回名称(success  error  input  login 这些是默认的,是跟着execute方法返回值) 补充:Struts2 中通配符在struts.xml的使用!        
       /jsp/result{1}.jsp      
  若一个action中多个方法 调用其中一个方法可以用 login!method1.action 这样他会自我调用method1方法 --------------------------------------------------------------------------------------------
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">

    继承struts的默认包,里面有大量的配置信息
    //前台页面请求action="login.action"  不再是login.do
    index.jsp
    login.jsp //这个是验证失败的话
   

 


----------------------------------------------------- 1 若是请求出现错误,为了友好化,可以这样设定!  
         /jsp/AllErros.jsp
 
    2 全局结果,无论什么方法,只要返回结果一致,都会转向指定的页面!    /jsp/error.jsp 若是...中也出现error  那么他的优先级大于全局的!!!!! ------------------------------------------
总结下简单的体系:
  前端控制 : FilterDispatcher .接受请求,调用组建--->通过ActionProxyFactory(action代理工厂)获得代理,然后-->interceptor(拦截器)-->分解请求,封装到指定对象上~!
                 |
               execute()--->interceptor--->转发重定向,或者直接响应
-------------------------------------------------------------------------------------------------
struts2  action的验证: //validate方法
@Override
 public void validate() {
  if(userName == null || "".equals(userName))
   this.addFieldError("userName", "用户名不能为空");
  if(userPassword == null || "".equals(userPassword))
   this.addFieldError("userPassword", "密码必须填写");
 } this.addFieldError("username","用户名不能为空");
this.addActionMessage("欢迎登陆论坛");
this.addActionError("用户名或密码错误!请重新尝试!!");
一般来说验证信息就是以上3种形式! s标签的导入 :<%@taglib uri="/struts-tags" prefix="s"%> userName


-----------------------------------------------------------------
ajax,json的返回结构在struts2中的应用
action类没有任何变化,还是将数据保存在list中,在struts.xml中可以将list转换成json格式!
//引用json默认包
  
   //返回类型装换成json类型
  

在jsp页面中,这是通过jquery得到json对象

   
------------------------------------------------------------
session,request,application等拦截器,通过 implements struts2自带的它们接口,获得它们的map形式 public class LoginAction extends ActionSupport implements RequestAware, SessionAware ,ApplicationAware{
    private Map request = null;
 
    private Map session = null;
 
    private Map application = null;
   
    public void setRequest(Map request) {
  this.request = request;
 }     public void setSession(Map session) {
  this.session = session;
 }     public void setApplication(Map application) {
  this.application = application;
 }
   
    public String execute() throws Exception {
       session.put("userInfo","获取了对象");//另外两种略,这样无论在其他action类中还是jsp页面中都可以通过session得到数据
    } 
}
当然也可以通过ServletActionContext引用它们的API,得到session,request,application对象
import org.apache.struts2.ServletActionContext; ServletActionContext.getRequest().getSession();
ServletActionContext.getRequest()
-----------------------------------------------------------------------------------------------------------------------------------------------                                                                               Struts2的类型转换器                                                                       Struts2的类型转换器:(开发的实际意义不大,但是可以让你理解和更好的使用Struts2的类型转换机制
转换器--在struts2的框架内部,实现请求参数--》Action属性的自动封装和类型转换。
        都是来自ognl.TypeConverter
        请求通过struts2的组件,转发到action之前, struts会获取该action的所用属性的信息,然后检测该属性是否有对应的类型转换器,如果有,则会进行类型转换。若没有,则会调用默认的类型转换器。 1 局部转换器:针对某一个Action的属性值转换提供实现。(Action类名-conversion.properties放在与action同一个包下)
例如:RegAction-conversion.properties里
user=cn.com.csuinfosoft.converter.MyConverter 页面上属性名都用user: 2 全局转换器:对当前所有的工程下,所有指定类型的属性进行转换。(xwork-conversion.properties放在classes目录)
例如:xwork-conversion.properties
cn.com.csuinfosoft.vo.User=cn.com.csuinfosoft.converter.MyConverter   以上两个转换器,转换类基本写法一样,只是配置文档不同,这就导致了一个局部,一个全局。
转换类 实现 ognl.TypeConverter接口
public Object convertValue(Map map,Object arg1,Member arg2,String arg3,Object arg4,Class arg5){
}
map--ognlContext---OGML上下文
arg1---所对应的action实例
arg2---Member成员类型,所需调用的属性设置方法(反射对象)
arg3---对应的请求参数或者属性名
arg4---参数值
arg5---需要转换的属性类型
代码如下:
public class MyConverter implements TypeConverter {  public Object convertValue(Map map, Object arg1, Member arg2, String arg3,
   Object arg4, Class arg5) {
  if(arg5 == User.class) {
   User user = new User();
   String[] param = (String[])arg4;
   user.setUserName(param[0]);
   user.setUserAge(Integer.parseInt(param[1]));
   user.setUserTel(param[2]);
   return user;
  }
  return null;
 } } 还是很容易理解的。。。。 ----------------------------------------------------------------------------------------------------------------------------------------------                                                                        Struts2的拦截器和文件上传                                                                        Struts2的拦截器:
拦截器---在struts调用Action执行过程中,提供辅助的请求处理操作。
Struts2的包中有大量的拦截器。
Interceptor
    -intercept(ActionInvocation invocation)
                          --Action的执行引用
拦截器类 实现 Interceptor接口
public void destory(){
}
public void init(){
}
public String intercept(ActionInvocation actionInvocation) throws Exception {
  
  System.out.println("intercept----begin----");
  String result = actionInvocation.invoke();
  System.out.println("result === " + result);
  System.out.println("intercept----end----");
  return result;
}
启用拦截器要在struts.xml中加入配置:


  //拦截器的单独定义,如果不用栈的话,那么这个拦截器用了,其他的拦截器就失效
 
 
   //拦截器 name属性可以是已有的拦截器名称,也可以是拦截器栈的名称
   //拦截器默认栈 ,如果不加上这个,很多默认的拦截器就不会再实现了。
 



 


例子代码:

 
   
 
 
 
 
 

   

  
       
 reg.html
  

 

  自定义拦截器中,在一个action中有些方法需要拦截,有些方法不需要,可以用includeMethods和excludeMethods 这两个参数来设置 1 首先在拦截器类中extends MethodFilterInterceptor 2 includeMethods 优先级高于 excludeMethods  
            method1,method2             method1,method2  
  对于较长时间需要等待的,可以给出execAndWait拦截器,这样可以给用户一个友好的等待提示,当然也可以自己设计友好的提示内容! /jsp/wait.jsp
         execute
 
  避免重复提交用到的拦截器 1 TokenInterceptor 这个拦截器会查出是否重复提交,若是则可以转向错误页面!  /jsp/error.jsp     除了在struts.xml中设定外,还要在请求jsp页面标记该拦截器
           这里标记该form
       
       
       
       
  2 TokenSession  这个拦截器会查出是否重复提交,若是则转向第一次正确登录的 页面,无需设定错误页面!    除了在struts.xml中设定外,还要在请求jsp页面标记该拦截器
           这里标记该form
       
       
       
       
  -----------------------------------------------------------------------------------------------
Struts2的文件上传功能:
Struts2的文件上传是基于拦截器来实现的。
还有要加入两个文件上传的包!
页面:

  
   
    
    
   
   
    
    
   
   
    
    
   
   
    
      
  

    
     文件:
    

     
    

     文件:
    

     
    

     文件:
    

     
    

    

Action类:
-----------------------------------------------------
public class UploadAction implements Action {  /**
  * 封装上传文件信息
  */
 private File[] photo = null;
 
 
 /*FileUpload拦截器会根据上传文件的信息,自动填充一下两个属性
  *
  * photoContentType,photoFileName
  * */
 private String[] photoContentType = null;
 
 private String[] photoFileName = null;
 
 private String[] title = null;
 
 public String execute() throws Exception {
  
  File file = null;
  for(int i = 0; i < photo.length; i++) {
   file = photo[i];
   
   System.out.println("title === " + title[i]);
   System.out.println("file.name === " + photoFileName[i]);
   System.out.println("file.type === " + photoContentType[i]);
   System.out.println("file === " + file);
   System.out.println("######################################");
  }
  return this.SUCCESS;
 }  public void setPhoto(File[] photo) {
  this.photo = photo;
 }  public void setPhotoContentType(String[] photoContentType) {
  this.photoContentType = photoContentType;
 }  public void setPhotoFileName(String[] photoFileName) {
  this.photoFileName = photoFileName;
 }  public void setTitle(String[] title) {
  this.title = title;
 } }
----------------------------------------------------------------
struts.xml中配置文件上传的拦截器:
       
      
    
    
     image/jpeg,image/gif //这个是用来判断文件类型是否符合要求
    

    
 



   
   

   upload.jsp
  --------------------------------------------------------------------- 文字脏话过滤~!
1 写好interceptor类
public String intercept(ActionInvocation arg0) throws Exception {
     Object o=arg0.getAction();
     if (o instanceof charAction){
      charAction action=(charAction) o;
      System.out.println(action);
     if (action!=null){
      String content=action.getContent();
      System.out.println(content+"-----------------");
      String[] str={"TMD","tmd","GM","gm","cao"};
      for(int i=0;i      if (content.contains(str[i])){
       content=content.replaceAll(str[i],"***");
      }
      }
      System.out.println(content+"=====================");
      action.setContent(content);
   return arg0.invoke(); 
     }else{
      return "input";
      
     }
     }
     return "input";
 }
2 在struts.xml配置对应的文件 3 特别注意:
 
      
      
      
        
 

defaultStack要写在我们拦截器前面,因为是顺序加载,先加载defaultStack ,这样action中才能得到请求页面的值~
否贼,先我们的拦截器类,那么在方法中的action得到对应的属性值为null~! 切记:defaultStack" 写在 我们的定义拦截器类前面 ---------------------------------------------- 拦截器在action中可以设定哪些方法拦截,哪些方法不被拦截 1 首先需要拦截器类 extends MethodFilterInterceptor 2 配置中写:               execute1,execute2 设定哪些方法不被拦截        execute 设定哪些方法被拦截       ----------------------------------------- 拦截器拦截顺序 假设在一个action中有3个拦截器,配置顺序分别为拦截器1,拦截器2,拦截器3 则执行顺序为: 拦截器1 执行 拦截器2 执行 拦截器3 执行 execute方法实现 拦截器3 执行完毕 拦截器2 执行完毕 拦截器1 执行完毕   这类似一个递归的顺序! ---------------------------------------- 拦截器结果监听器 拦截器监听类实现 implements PreResultListener{   public void beforeResult(ActionInvocation ai,String result){        这里对执行的结果进行监听    } }   在interceptor类中,ai.addPreResultListener(new 我们定义监听类); --------------------------------------- 拦截器也包括参数的覆盖,这个不难,不懂得网上可以查到的 struts2.0中大量使用了内置拦截器和内置拦截器栈,有些还是需要了解的 如: 查看运行耗时的拦截器 ------------------------------------- 权限,判断是否登陆,通过session的到用户对象 public String interceptor(ActionInvocation ai) throws Exception{    ActionContext ac=ai.getInvocationContext();    Map session=ac.getSession();    String username=(String)session.get("username");    if (username!=null && username.length()>0){       return ai.invoke();    } else{       return Action.LOGIN;    } } ================================================================================================= ------------------------------------------------------------Struts2 效验器--------------------------------------------------
1 普通的效验代码  基于正则表达式(相对全面的注册页面) 3步!
该效验代码出现在validate方法中 1 首先 jsp页面!
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>


 
 

     My JSP 'regist.jsp' starting page   
  
  
  
  
      
  

   


    注册新用户(带*项为必填信息)
   


   
    

    
    
     
     
     
     
     

      
     
     
     
     
      
         
    
   

       

      

  

 

2 struts.xml 中
 
         /jsp/registSuccess.jsp
         /jsp/regist.jsp
 
3 action类中
package cn.com.action; import java.util.regex.Pattern; import com.opensymphony.xwork2.ActionSupport; public class registAction extends ActionSupport {
 private String username;
 private String password1;
 private String password2;
 private String email;
 private int age;
 private String sex;
 private String dateValue; //   set/get 方法略!  @Override
 public String execute() throws Exception {
  System.out.println(username);
  System.out.println(password1);
  System.out.println(password2);
  System.out.println(email);
  System.out.println(sex);
  System.out.println(dateValue);
  System.out.println(age);
  if (hasErrors()) {
   return INPUT;
  }
  return SUCCESS;
 }  /**
  * Pattern.matches正则表达式的方法 import java.util.regex.Pattern; /w表示字母和数字或下划线的组合
  * 4,15 表示长度范围 更多表达式自己查
  */
 @Override
 public void validate() {
  if (username.equals("")) {
   addFieldError("username", "必须输入用户名");
  } else if (!Pattern.matches("//w{4,15}", username)) {
   addFieldError("username", "用户名必须是字母和数字或下划线的组合且长度在(4-15)范围内");
  }
  if (username.equals("")) {
   addFieldError("password1", "必须输入密码");
  } else if (!Pattern.matches("//w{6,15}", password1)) {
   addFieldError("password1", "密码必须是字母和数字或下划线的组合且长度在(6-15)范围内");
  }
  if (username.equals("")) {
   addFieldError("password2", "必须重复输入密码");
  } else if (!password2.equals(password1)) {
   addFieldError("password2", "重复输入密码必须与第一次输入密码一致");
  }   if (username.equals("")) {
   addFieldError("email", "必须输入邮编");
  } else if (!Pattern.matches(
    "^//w+(//.|//w+)*//w+(//.//w+)*@//w+//w+//.//w+$", email)) {
   addFieldError("email", "邮编的格式不正确或者输入的邮编不存在");
  }   if (age < 1 || age > 99) {
   addFieldError("age", "年龄必须为整数且在(1-99)范围内");
  }  } } -------------------------------------------------
validate*(validate方法名)的存在  它可以针对指定的方法进行效验!
例如我们的action中有多个方法!如Test1 和Test2
当请求通过struts.xml中调用Test1 时,该action中的validateTest1() 效验方法会被调用! 
当请求通过struts.xml中调用Test2 时,该action中的validateTest2() 效验方法会被调用!  各求所需,合理致用~!
-----------------------------------------------------------
在struts2内部有许多内置的效验器,我们也可以通过默认的Struts2默认效验框架来实现对程序的效验工作!!! 由于struts-default 默认拦截器,则效验的拦截器自然被包括,所以无需对效验器再进行拦截了
1, action 中只是很简单的!
package cn.com.action; import com.opensymphony.xwork2.ActionSupport; public class registAction extends ActionSupport {
 private String username;
 private String password1;
 private String password2;
 private String email;
 private int age;
 private String sex;
 private String dateValue; //   set/get 方法略!  @Override
 public String execute() throws Exception {
  System.out.println(username);
  System.out.println(password1);
  System.out.println(password2);
  System.out.println(email);
  System.out.println(sex);
  System.out.println(dateValue);
  System.out.println(age);
  if (hasErrors()) {
   return INPUT;
  }
  return SUCCESS;
 }
} 2  jsp页面,struts.xml保持不变 ~! 类似于前面的~! 3 编写效验action类名-validation.xml文件 该文件与action类文件必需放在同一目录下
例如:registAction-validation.xml

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

   
       
     
     
         必需输入用户名
     

     
     
     
     
      用户名必须是字母和数字或下划线的组合且长度在(4-15)范围内
     
     
  

  
    
       
     
     
         必需输入密码
     

     
     
     
     
      密码必须是字母和数字或下划线的组合且长度在(6-15)范围内
     
     
  

  
    
       
     
     
         必需重复输入密码
     

     
     
     
     
      两次输入的密码不一致
     
     
  

  
    
       
     
     
         必需输入邮箱
     

     
     
     
      邮编的格式不正确或者输入的邮编不存在
     
     
  

  
  
    
           
     
     
      1
      99
      年龄必须是在(1-99)范围内
     
     
  

 

(封装完成!)
------------------------------------------------------------------------------
补充(中的validate="true" 默认为false 
若是true 先在客户端进行校验,然后在服务端再进行校验  客户端所支持的效验器不够全面,没有服务器的多,有些校验不出结果!)
若为false 只在服务器端进行校验
-------------------------------------------------------------------
自定义校验框架也是不错的,但是基本上默认的已经比较全面够用了.
--------------------------------------------------------------------
visitor 效验器在校验中的作用 例如 登录需要用户名和密码的校验     注册也需要用户名和密码的校验 这些可以用同一个校验文件 ,通过visitor就可以互相访问!
这样的会,虽然代码少了,但是程序的可读性变差了, 阅读程序时较为复杂!
-----------------------------------------------------------------
校验框架的短路现象理解就好了~! 其实际作用一般! ========================================================================================================================================== Struts2 标签:
导入struts标签库
<%@taglib uri="/struts-tags" prefix="s"%> 
_____________________________________________________
1 迭代标签+ognl表达式
     
             
       
       
       
     

value="……"  就是ognl表达式(对象导航语言,提供了一组数据结构和表达式,通过表达式可以访问该数据结构上的任意对象或者对象属性)
ognl上下文--用于存放一次请求处理过程,所对应各级会话内容和值栈内容的map结构对象(OgnlContext)
            可以访问:request,session,application,值栈,param
ognl表达式--"#对象名.属性 "  #application  #session #request #this
          --"对象名.{?#this.属性=='值'}"
     
顺序是:值栈,request,session.application...
如果怎么样否则怎么样 ____________________________________________________
Js效果标签(Js+Ajax+htm)

     //导入 ajax 模式

-->生成div元素

     -theme="ajax"--在页面导入struts2的Ajax环境(Dojo--Js框架),启用 ajax 功能
     -href:通过功能访问的资源路径
     -loadingText:等待加载时的提示信息
     -实时的访问:
        -autoStart:boolean 是否循环加载
        -updateFreq:int类型  循环访问的间隔时间
        -delay:integer 设置延迟多长时间开始加载div标签内容
Ajax模式:基于请求对象的响应结果生成div内容
--------------------
可以实现搜索引擎,打1个字,就可以动态生成下拉菜单显示相关内容(如google,百度)

动态列表生成技术
1 这个是静态list:
   showDownArrow="false" loadOnTextChange="true" loadMinimumCount="1"> 2 json生成的list..配置中可以设置不包含那些属性
 showDownArrow="false" loadOnTextChange="true" loadMinimumCount="1">

loadOnTextChange是否在文本内容改变时进行匹配内容的加载
showDownArrow 是否采用select下拉菜单功能
loadMinimumCount 文本框内有几位字符时才进行这种内容匹配的操作。
----------------------------------------------------------------------------------------
--tab
   theme="ajax"
   labelposition="top"
   selectedTab="d2"
   closeButton="true" 
 >
  曹操
司马懿
张辽

   春哥
曾哥
飞哥

   曹操
司马懿
张辽


-------------------------------------------------------------
------------------------------------------------------日期  struts2上提供自带的时间组件--------------------------------------------------  

在以前的struts2版本中s:datetimepicker只需要在head标签处设置

就可以直接使用s:datetimepicker的标签了。
而在2.1.6版本中不能直接这样使用了,将datetimepicker移除了。
原因是此标签调用了dojo的datetimepicker的库。
所以现在使用的时候首先要导入一个库。

  • struts2-dojo-plugin-2.1.6.jar。

然后还要设置dojo的taglib Java代码
  1. <%@ taglib prefix="sd" uri="/struts-dojo-tags" %>   
<%@ taglib prefix="sd" uri="/struts-dojo-tags" %> 同样也需要对theme进行设置 Java代码
  1. "xhtml"/>   
  2. "true"/>  
上面的设置在head标签中。
然后使用sd:datetimepocker就可以实现了。

设置formatLength为long的datetimepicker标签 Java代码
  1. "explode" value="today" formatLength="long" />  

设置displayFormat参数为“yyyy年MM月dd日”
displayWeeks参数为2的datetimepicker标签 Java代码
  1. "yyyy年MM月dd日" displayWeeks="2" />  


设置weekStartsOn参数为1,toggleType参数为fade的datetimepicker标签 Java代码
  1. "1" toggleType="fade" />  

设置显示时间datetimepicker标签 Java代码
  1. "time" value="8:30" />  

另外
displayFormat这个参数好像不能格式化yyyy-MM-dd hh:mm:ss 有待解决 Java代码 "date" toggleType="explode" toggleDuration="400" displayFormat="yyyy-MM-dd hh:mm:ss" id="object_createdate" value="today">   
------------------------------------------------------------------------------------------------------------------- --树 action类+ js上的组件
childCollectionProperty="nodes">
action类上:
public String execute() throws Exception {
  rootNode = new Nodes();//创建根元素
  rootNode.setNodeId(1);
  rootNode.setNodeName("中信软件教育");
  Nodes[] rootChild = new Nodes[2];
  Nodes node = null;
  
  //二级节点
  node = new Nodes();
  node.setNodeId(2);
  node.setNodeName("教学部");
  Nodes[] childNodes = new Nodes[2];
  
  //三级节点
  Nodes child = new Nodes();
  child.setNodeId(4);
  child.setNodeName("马凯");
  childNodes[0] = child;
  
  child = new Nodes();
  child.setNodeId(5);
  child.setNodeName("DragLong");
  childNodes[1] = child;
  node.setNodes(childNodes);
  rootChild[0] = node;
  
  node = new Nodes();
  node.setNodeId(3);
  node.setNodeName("教务部");
  childNodes = new Nodes[2];
  
  //三级节点
  child = new Nodes();
  child.setNodeId(6);
  child.setNodeName("刘姥姥");
  childNodes[0] = child;
  
  child = new Nodes();
  child.setNodeId(7);
  child.setNodeName("邓艾接");
  childNodes[1] = child;
  node.setNodes(childNodes);
  rootChild[1] = node;
  rootNode.setNodes(rootChild);
  
  return this.SUCCESS;
 }
------------------------------------------------------------------
JS获取s标签的值:
JS获取s:autocompleter的值
使用了s:autocompleter标签,然后用js的方式获取它的值 普通获取值的方法 有些是
document.getElementById("name").value//输入框
或者
document.getElementById("name").innerText //文本
或者
document.getElementById("name").text //下拉框 s:autocomplete为DOJO对象 所以用
dojo.widget.byId('name');
   
var autoCompleter = dojo.widget.byId("name");
得到值:dojo.widget.byId("name").getValue();
设置值:dojo.widget.byId("name").setValue("值"); ===============================================================
struts2 配置中文
1:在web.xml中
 
  struts2
  org.apache.struts2.dispatcher.FilterDispatcher
         //这以下是加入
  
   encoding
   UTF-8
  

 

2:在struts.xml中

  ------------------------------------------------------------------------------------------------------------------------------------------------                                                                     Struts 2.0+Spring                                                                                                   
整合还需要一个扩展包:struts2-spring-plugin-2.0.14.jar
在web.xml中

    contextConfigLocation
    /WEB-INF/action-spring.xml//当然也可以写在applicationContext.xml
在action-spring.xml中

//scope="prototype"一定要配置成多例
----------------------------------------------------------
如果没有配置scope=prototype则操作的时候不会新建一个action,他任然会保留上次访问的过记录的信息。以前错的,它同样会报错 ,它会一直停留在上次的访问记录不变 ----------------------------------------------------------
struts.xml中的配置
//全局的参数,告诉struts框架对象的创建由 spring创建   class对应action-spring.xml     index.jsp
   login.jsp
  ---------------------------------------------------------- 错误情况: 配置时,出现的错误: Unable to load bean: type: class:com.opensymphony.xwork2.ObjectFactory - bean - jar:file:/。。。。 出现这种错误时,就要注意了,是否是struts2-core-2.0.14.jar 包的冲突~! 可能tomcat lib中有struts2-core-2.0.14.jar 和webapps项目中的 ib中的此包冲突。 或者是tomcat webapps 目录下,有多个项目,可能有项目中的lib中包含有相同的struts2-core-2.0.14.jar,这样也会报冲突的~!   去掉其他,只剩下你的项目lib中含有struts2-core-2.0.14.jar  即可~! ---------------------------------------------------------------------------------------------------------------------- 错误情况: 我们都知道~Spring中实现dao方法都是要,在action中提供set方法。有时我们也会带上get方法,因为有时它的出现无所谓,不会影响什么。。
可是,当你在改action中通过struts2的json方法返回时,会发现报:
java.sql.SQLException: 访问层需要具体实施: getConnectionPoolInfo
…… 原因是:该json返回是视action的里的get方法的。。getdao类的方法也会被视为返回数据,造成错误的产生! -----------------------------------------------------------------------------------------------------------------------------------