• Struts 2.0全面分析


      Struts 2.0                                                                                                  
    
    struts 1---前端控制+应用控制+命令模式
    webwork ---控制器+拦截器+代理
    
    Struts 2.0 继承了WebWork的设计理念,并没有继承struts 1,所以与struts 1是截然不同的~!
    -------------------------------------------------------
    Struts 2.0的简单实例:
    web.xml中
    
    <filter>
       <filter-name>struts2</filter-name>
       <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
    </filter>
    <filter-mapping>
       <filter-name>struts2</filter-name>  
       <url-pattern>/*</url-pattern>
    </filter-mapping>
    ------------------------------
    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页面中要写成<input type="text" name="user.name"/> 和<input type="password" name="user.password"/>这样前台和action之中的属性保持一致!
         return Action.SUCCESS;
       }
      
    }
    
    ------------------------------------------------------------
    struts.xml 不同以往,写在src目录下~!
    
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE struts PUBLIC
            "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
            "http://struts.apache.org/dtds/struts-2.0.dtd">
    <struts>
       <package>--用于组织拦截器,action对象,返回类配置的一套逻辑单位
           -name 标识名称
           -namespace  package映射的url地址(可有可无,倘若配置上名为girl,那么工程要加入girl这一层目录
           -abstruct:若为true时,struts2 框架不会使用该配置生成配置封装信息
          <result-types>--用于定义返回值类型,struts2的执行结果可以生成哪些响应格式
          <interceptor>--在action的执行中,需加入的拦截器对象
          <action> 
                -name action的组件标识名 //前台页面请求action="…….action"  不再是…….do 
                -class action类名
                -method 讲请求转发到指定的方法中
                <result>要返回的类型,或路径
                    -name 返回名称(success  error  input  login 这些是默认的,是跟着execute方法返回值)
    
    补充:Struts2 中通配符在struts.xml的使用!
    
            <action name="test*" class="cn.com.action.loginAction" method="test{1}">
           <result name="result{1}">/jsp/result{1}.jsp</result>
    
          </action>
    
     
    
    若一个action中多个方法 调用其中一个方法可以用 login!method1.action 这样他会自我调用method1方法
    
    --------------------------------------------------------------------------------------------
    
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE struts PUBLIC
            "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
            "http://struts.apache.org/dtds/struts-2.0.dtd">
    <struts>
      <package name="shushine" extends="struts-default">  继承struts的默认包,里面有大量的配置信息
        <action name="login" class="cn.com.action.LoginAction"> //前台页面请求action="login.action"  不再是login.do
        <result name="success">index.jsp</result> 
        <result name="input">login.jsp</result> //这个是验证失败的话
        </action>
      </package>
    </struts>
    -----------------------------------------------------
    
    1 若是请求出现错误,为了友好化,可以这样设定!
    
    <default-action-ref name="actionError"></default-action-ref>
    
    <action name="actionError">  
             <result>/jsp/AllErros.jsp</result>
     </action> 
    
     
    
    2 全局结果,无论什么方法,只要返回结果一致,都会转向指定的页面!
    
    <global-results>
    
       <result name="error">/jsp/error.jsp</result>
    
    </global-results>
    
    若是<action >...</action>中也出现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"%>
    
    <s:fielderror><s:param>userName</s:param></s:fielderror>
    <s:actionmessage/>
    <s:actionerror/>
    -----------------------------------------------------------------
    ajax,json的返回结构在struts2中的应用
    action类没有任何变化,还是将数据保存在list中,在struts.xml中可以将list转换成json格式!
    <package name="testAjax" extends="json-default">//引用json默认包
      <action name="json" class="cn.com.csuinfosoft.action.JsonAction">
       <result type="json"></result>//返回类型装换成json类型
      </action>
    </package>
    
    在jsp页面中,这是通过jQuery得到json对象
    <script type="text/JavaScript" src="js/jquery-1.2.6.js"></script>
      <script>
       function testAjax() {
        $.ajax({
         type: "POST",
         url:"json.action",
         dataType:"json",
         success:function(msg) {
          alert('msg === ' + msg.cityList);
          var selectObj = $("#city");
          selectObj.empty(); 
          for(i = 0; i < msg.cityList.length; i++) {
           selectObj.append("<option value='"+msg.cityList[i].id+"'>"+msg.cityList[i].name+"</option>");
          }           
         }
        });
       }
      </script> 
    
    
    ------------------------------------------------------------
    session,request,application等拦截器,通过 implements struts2自带的它们接口,获得它们的map形式
    
    public class LoginAction extends ActionSupport implements RequestAware, SessionAware ,ApplicationAware{
        private Map<String,Object> request = null; 
     
        private Map<String,Object> session = null;
     
        private Map<String,Object> 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中加入配置:
    <package>
    <interceptors>
      <interceptor class="cn.com.interceptor.MyInterceptor" name="myInterceptor"></interceptor>//拦截器的单独定义,如果不用栈的话,那么这个拦截器用了,其他的拦截器就失效
      <!--拦截器栈-->
      <interceptor-stack name="mydefault">
       <interceptor-ref name="myInterceptor"/>//拦截器 name属性可以是已有的拦截器名称,也可以是拦截器栈的名称
       <interceptor-ref name="defaultStack"/>//拦截器默认栈 ,如果不加上这个,很多默认的拦截器就不会再实现了。
      </interceptor-stack>
    </interceptors>
    <action ......>
      <interceptor-ref name="myInterceptor"/>
    </action>
    </package>
    例子代码:
    <struts>
      <package name="shushine" extends="struts-default">
        <interceptors>
     <interceptor class="cn.com.csuinfosoft.interceptor.MyInterceptor" name="myInterceptor"></interceptor>
     <interceptor-stack name="myInterceptorStack">
     <interceptor-ref name="myInterceptor"></interceptor-ref>
     <interceptor-ref name="defaultStack"></interceptor-ref>
     </interceptor-stack>
        </interceptors>
       <action name="regAction" class="cn.com.csuinfosoft.action.RegAction">
            <interceptor-ref name="myInterceptorStack"></interceptor-ref>
     <result name="success">reg.html</result>
       </action>
      </package>
    </struts>
    
     
    
    自定义拦截器中,在一个action中有些方法需要拦截,有些方法不需要,可以用includeMethods和excludeMethods 这两个参数来设置
    
    1 首先在拦截器类中extends MethodFilterInterceptor
    
    2 includeMethods 优先级高于 excludeMethods
    
     <interceptor-ref name="test">
                <param name="excludeMethods">method1,method2</param>
    
                <param name="includeMethods">method1,method2</param>
    
      </interceptor-ref>
    
     
    
    对于较长时间需要等待的,可以给出execAndWait拦截器,这样可以给用户一个友好的等待提示,当然也可以自己设计友好的提示内容!
    
    <result name="wait">/jsp/wait.jsp</result>
    
    <interceptor-ref name="execAndWait">
             <param name="excludeMethods">execute</param>
     </interceptor-ref>
    
     
    
    避免重复提交用到的拦截器
    
    1 TokenInterceptor 这个拦截器会查出是否重复提交,若是则可以转向错误页面!
    
     <result name="invalid.token">/jsp/error.jsp</result>
    
     <interceptor-ref name="token"></interceptor-ref>
    
     
    
    除了在struts.xml中设定外,还要在请求jsp页面标记该拦截器
    
    <s:form action="login" method="post">
          <s:token></s:token>     这里标记该form
            <s:textfield name="username" label="用户名"></s:textfield>
            <s:textfield name="password" label="密  码"></s:textfield>
            <s:submit value="Submit"></s:submit>
            <s:reset value="Reset"></s:reset>
    
    </s:form>
    
     
    
    2 TokenSession  这个拦截器会查出是否重复提交,若是则转向第一次正确登录的 页面,无需设定错误页面!
    
       <interceptor-ref name="tokenSession"></interceptor-ref>
    
    除了在struts.xml中设定外,还要在请求jsp页面标记该拦截器
    
    <s:form action="login" method="post">
          <s:token></s:token>     这里标记该form
            <s:textfield name="username" label="用户名"></s:textfield>
            <s:textfield name="password" label="密  码"></s:textfield>
            <s:submit value="Submit"></s:submit>
            <s:reset value="Reset"></s:reset>
    
    </s:form>
    
     
    
    -----------------------------------------------------------------------------------------------
    Struts2的文件上传功能:
    Struts2的文件上传是基于拦截器来实现的。
    还有要加入两个文件上传的包!
    页面:
    <form action="uploadAction.action" method="POST" enctype="multipart/form-data">
      <table align="center" border="1">
       <tr>
        <td>
        
         文件:<input type="text" name="title"/>
        </td>
        <td>
         <input type="file" name="photo"/>
        </td>
       </tr>
       <tr>
        <td>
         文件:<input type="text" name="title"/>
        </td>
        <td>
         <input type="file" name="photo"/>
        </td>
       </tr>
       <tr>
        <td>
         文件:<input type="text" name="title"/>
        </td>
        <td>
         <input type="file" name="photo"/>
        </td>
       </tr>
       <tr>
        <td align="center" colspan="2"><input type="submit" name="s1" value="上传"/>
        </td>
       </tr>   
      </table>
    </form>
    
    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中配置文件上传的拦截器:
    <interceptors>        
           <interceptor-stack name="MyfileUploadStack">
        <interceptor-ref name="defaultStack"></interceptor-ref>
        <interceptor-ref name="fileUpload">
         <param name="allowedTypes">image/jpeg,image/gif</param> //这个是用来判断文件类型是否符合要求
        </interceptor-ref>
        <interceptor-ref name="myInterceptor"></interceptor-ref>
     </interceptor-stack>
    </interceptors>
    <action name="uploadAction" class="cn.com.csuinfosoft.action.UploadAction">
       <interceptor-ref name="MyfileUploadStack">
       </interceptor-ref>
       <result name="success">upload.jsp</result>
    </action>
    
     
    
    ---------------------------------------------------------------------
    
    文字脏话过滤~!
    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<str.length;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 特别注意:
      <interceptors>
           <interceptor name="contentInterceptor" class="cn.com.interceptor.ContentInterceptor"></interceptor>
           <interceptor-stack name="contentstack">
           <interceptor-ref name="defaultStack"></interceptor-ref>
             <interceptor-ref name="contentInterceptor"></interceptor-ref>
      </interceptor-stack>
    defaultStack要写在我们拦截器前面,因为是顺序加载,先加载defaultStack ,这样action中才能得到请求页面的值~
    否贼,先我们的拦截器类,那么在方法中的action得到对应的属性值为null~!
    
    切记:defaultStack" 写在 我们的定义拦截器类前面
    
    ----------------------------------------------
    
    拦截器在action中可以设定哪些方法拦截,哪些方法不被拦截
    
    1 首先需要拦截器类 extends MethodFilterInterceptor
    
    2 配置中写:
    
          <interceptor-ref name="contentInterceptor">
    
           <param name="excludeMethods">execute1,execute2</param> 设定哪些方法不被拦截
    
           <param name="includeMethods">execute</param> 设定哪些方法被拦截
    
          </interceptor-ref>
    
    -----------------------------------------
    
    拦截器拦截顺序
    
    假设在一个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中大量使用了内置拦截器和内置拦截器栈,有些还是需要了解的
    
    如:<interceptor-ref name="timer"/> 查看运行耗时的拦截器
    
    -------------------------------------
    
    权限,判断是否登陆,通过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"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
     <head>
     <s:head theme="ajax"/> 
    <!--在以前的struts2版本中s:datetimepicker只需要在head标签处设置 
    <s:head theme="ajax"/>, 
    就可以直接使用s:datetimepicker的标签了。 
    而在2.1.6版本中不能直接这样使用了,将datetimepicker移除了。 
    原因是此标签调用了dojo的datetimepicker的库。 
    所以现在使用的时候首先要导入一个库。 
    struts2-dojo-plugin-2.1.6.jar。
    
    然后还要设置dojo的taglib 详见http://blog.csdn.net/javakeikei/archive/2009/10/19/4700352.aspx#1262867 -->
      <style type="text/css">
    body {
     background-color: #CCCCCC;
    }
    </style>
    
      <title>My JSP 'regist.jsp' starting page</title>
    
      <meta http-equiv="pragma" content="no-cache">
      <meta http-equiv="cache-control" content="no-cache">
      <meta http-equiv="expires" content="0">
      <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
      <meta http-equiv="description" content="This is my page">
      <!--
     <link rel="stylesheet" type="text/css" href="styles.css">
     -->
    
     </head>
    
     <body>
      <center>
       <h2>
        注册新用户(带*项为必填信息)
       </h2>
       <table>
        <hr>
        <s:form action="validate1">
        
         <s:textfield name="username" label="用户名" required="true"></s:textfield>
         <s:textfield name="password1" label="输入密码" required="true"></s:textfield>
         <s:textfield name="password2" label="重复密码" required="true"></s:textfield>
         <s:textfield name="email" label="邮箱" required="true"></s:textfield>
         <tr>
          <td>
           <hr color="red">
          </td>
         </tr>
         <s:textfield name="age" label="年龄"></s:textfield>
         <s:radio list="#{'男':'男','女':'女'}" name="sex" label="性别" />
         <s:datetimepicker id="dateDemo" name="dateValue" value="today" toggleType="explode" label="出生日期"></s:datetimepicker>
         <s:submit value="提交" align="center"></s:submit><s:reset value="重置" align="center"></s:reset> 
             
        </s:form>
       </table>
      </center>
     </body>
    </html>
    
    
    2 struts.xml 中
     <action name="validate1" class="cn.com.action.registAction">
             <result name="success">/jsp/registSuccess.jsp</result>
             <result name="input">/jsp/regist.jsp</result>
     </action>
    
    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
    <?xml version="1.0" encoding="GBK"?> 
    <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" 
    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd"> 
    <validators>
        <!-- 效验用户名区域 -->
       <field name="username">     
          <!-- 效验用户名不能为空 --> 
          <field-validator type="requiredstring">
             <message>必需输入用户名</message>
          </field-validator> 
          
          <!-- 效验用户名格式问题 -->
          <field-validator type="regex">
          <param name="expression"><![CDATA[(/w{4,15})]]></param> 
          <message>用户名必须是字母和数字或下划线的组合且长度在(4-15)范围内</message>
          </field-validator>      
       </field>
       
         <!-- 效验密码区域 -->
       <field name="password1">     
          <!-- 效验密码不能为空 --> 
          <field-validator type="requiredstring">
             <message>必需输入密码</message>
          </field-validator> 
          
          <!-- 效验用户名格式问题 -->
          <field-validator type="regex">
          <param name="expression"><![CDATA[(/w{6,15})]]></param> 
          <message>密码必须是字母和数字或下划线的组合且长度在(6-15)范围内</message>
          </field-validator>      
       </field>
       
         <!-- 效验重复密码区域 -->
       <field name="password2">     
          <!-- 效验重复密码不能为空 --> 
          <field-validator type="requiredstring">
             <message>必需重复输入密码</message>
          </field-validator> 
          
          <!-- 效验重复密码一致性问题 -->
          <field-validator type="fieldexpression">
          <param name="expression"><![CDATA[(password2.equals(password1))]]></param> 
          <message>两次输入的密码不一致</message>
          </field-validator>      
       </field>
       
         <!-- 效验邮箱区域 -->
       <field name="email">     
          <!-- 效验邮箱不能为空 --> 
          <field-validator type="requiredstring">
             <message>必需输入邮箱</message>
          </field-validator> 
          
          <!-- 效验邮箱格式问题 -->
          <field-validator type="email">
          <message>邮编的格式不正确或者输入的邮编不存在</message>
          </field-validator>      
       </field>
       
       
         <!-- 效验年龄区域 -->
       <field name="age">         
          <!-- 效验年龄格式问题 -->
          <field-validator type="int">
          <param name="min">1</param>
          <param name="max">99</param>
          <message>年龄必须是在(1-99)范围内</message>
          </field-validator>      
       </field>
     
    </validators>
    (封装完成!)
    ------------------------------------------------------------------------------
    补充(<s:form action="validate1" validate="true">中的validate="true" 默认为false  
    若是true 先在客户端进行校验,然后在服务端再进行校验  客户端所支持的效验器不够全面,没有服务器的多,有些校验不出结果!)
    若为false 只在服务器端进行校验
    -------------------------------------------------------------------
    自定义校验框架也是不错的,但是基本上默认的已经比较全面够用了.
    --------------------------------------------------------------------
    visitor 效验器在校验中的作用
    
    例如 登录需要用户名和密码的校验     注册也需要用户名和密码的校验 这些可以用同一个校验文件 ,通过visitor就可以互相访问!
    这样的会,虽然代码少了,但是程序的可读性变差了, 阅读程序时较为复杂!
    -----------------------------------------------------------------
    校验框架的短路现象理解就好了~! 其实际作用一般!
    
    ==========================================================================================================================================
    
    Struts2 标签:
    导入struts标签库
    <%@taglib uri="/struts-tags" prefix="s"%>  
    _____________________________________________________
    1 迭代标签+ognl表达式
    <s:iterator value="list">      
          <tr>        
            <td><s:property value="name"/></td>
            <td><s:property value="record"/></td>
            <td><s:property value="date"/></td>
          </tr>
    </s:iterator>
    value="……"  就是ognl表达式(对象导航语言,提供了一组数据结构和表达式,通过表达式可以访问该数据结构上的任意对象或者对象属性)
    ognl上下文--用于存放一次请求处理过程,所对应各级会话内容和值栈内容的map结构对象(OgnlContext)
                可以访问:request,session,application,值栈,param
    ognl表达式--"#对象名.属性 "  #application  #session #request #this
              --"对象名.{?#this.属性=='值'}"
    <s:iterator value="list.{?#this.age>20 && #this.sal>1000}">      
    顺序是:值栈,request,session.application...
    
    <s:proprety value="#session.userInfo"/>
    <s:if test="sal>1500">如果怎么样</s:if><s:else>否则怎么样</s:else>
    
    ____________________________________________________
    Js效果标签(Js+Ajax+htm)
    <head>
      <s:head theme="ajax"/>   //导入 ajax 模式
    </head>
    <s:div>-->生成div元素
    <s:head>
         -theme="ajax"--在页面导入struts2的Ajax环境(Dojo--Js框架),启用 ajax 功能
         -href:通过功能访问的资源路径
         -loadingText:等待加载时的提示信息
         -实时的访问:
            -autoStart:boolean 是否循环加载
            -updateFreq:int类型  循环访问的间隔时间
            -delay:integer 设置延迟多长时间开始加载div标签内容 
    Ajax模式:基于请求对象的响应结果生成div内容
    --------------------
    <s:autocompleter>可以实现搜索引擎,打1个字,就可以动态生成下拉菜单显示相关内容(如google,百度)
    <div align="center">
    动态列表生成技术</br>
    
    1 这个是静态list:
    <s:autocompleter id="select" list="{'PengPeng','penpen','Peijing','PangPang'}"
       showDownArrow="false" loadOnTextChange="true" loadMinimumCount="1"></s:autocompleter>
    
    2 json生成的list..配置中可以设置不包含那些属性
    <s:autocompleter id="input" name="selectParam" theme="ajax" href="completerAction.action" 
     showDownArrow="false" loadOnTextChange="true" loadMinimumCount="1"></s:autocompleter>
    </div>
    
    
    loadOnTextChange是否在文本内容改变时进行匹配内容的加载
    showDownArrow 是否采用select下拉菜单功能
    loadMinimumCount 文本框内有几位字符时才进行这种内容匹配的操作。
    ----------------------------------------------------------------------------------------
    --tab
    <s:tabbedPanel id="mytab"
       theme="ajax"
       labelposition="top"
       selectedTab="d2"
       closeButton="true"  
     >
    <s:div id="d1" label="魏" theme="ajax">  曹操</br>司马懿</br>张辽</br> </s:div>
    <s:div id="d2" label="蜀" theme="ajax">   春哥</br>曾哥</br>飞哥</br> </s:div>
    <s:div id="d3" label="吴" theme="ajax">   曹操</br>司马懿</br>张辽</br> </s:div>
    </s:tabbedPanel>
    -------------------------------------------------------------
    ------------------------------------------------------日期  struts2上提供自带的时间组件--------------------------------------------------
    <s:datetimepicker id="dateDemo" name="dateValue"  value="today" toggleType="explode"></s:datetimepicker>
    
     
    
    在以前的struts2版本中s:datetimepicker只需要在head标签处设置 
    <s:head theme="ajax"/>, 
    就可以直接使用s:datetimepicker的标签了。 
    而在2.1.6版本中不能直接这样使用了,将datetimepicker移除了。 
    原因是此标签调用了dojo的datetimepicker的库。 
    所以现在使用的时候首先要导入一个库。
    struts2-dojo-plugin-2.1.6.jar。
    
    然后还要设置dojo的taglib
    

      然后还要设置dojo的taglib

    <%@ taglib prefix="sd" uri="/struts-dojo-tags" %> 
    

      同样也需要对theme进行设置

    <s:head theme="xhtml"/>   
    <sd:head parseContent="true"/>

    上面的设置在head标签中。 
    然后使用sd:datetimepocker就可以实现了。 

    设置formatLength为long的datetimepicker标签

     <s:datetimepicker toggleType="explode" value="today" formatLength="long" />  

    设置displayFormat参数为“yyyy年MM月dd日” 
    displayWeeks参数为2的datetimepicker标签

    <s:datetimepicker displayFormat="yyyy年MM月dd日" displayWeeks="2" />  
    

     设置weekStartsOn参数为1,toggleType参数为fade的datetimepicker标签

     <s:datetimepicker weekStartsOn="1" toggleType="fade" />  

    设置显示时间datetimepicker标签

    <s:datetimepicker type="time" value="8:30" />
    

     另外 
    displayFormat这个参数好像不能格式化yyyy-MM-dd hh:mm:ss 有待解决

    <s:datetimepicker name="date" toggleType="explode" toggleDuration="400" displayFormat="yyyy-MM-dd hh:mm:ss" id="object_createdate" value="today">
    </s:datetimepicker>
    --树 action类+ js上的组件
    <s:tree id="myTree"  theme="ajax" rootNode="rootNode" nodeTitleProperty="nodeName" nodeIdProperty="nodeId"
    childCollectionProperty="nodes">
    </s:tree>
    
    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中
      <filter>
      <filter-name>struts2</filter-name>
      <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
             //这以下是加入<init-param>:
      <init-param>
       <param-name>encoding</param-name>
       <param-value>UTF-8</param-value>
      </init-param>
     </filter>
    2:在struts.xml中
    <constant name="struts.local" value="zh_CN"></constant>
    <constant name="struts.i18n.encoding" value="UTF-8"></constant>
    
     
    
    ------------------------------------------------------------------------------------------------------------------------------------------------
    
                                                                        Struts 2.0+spring                                                                                                   
    整合还需要一个扩展包:struts2-spring-plugin-2.0.14.jar
    在web.xml中
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/action-spring.xml</param-value>//当然也可以写在applicationContext.xml
    </context-param>
    
    在action-spring.xml中
    <bean id="loginAction" class="cn.com.csuinfosoft.action.LoginAction" scope="prototype">
    </bean>//scope="prototype"一定要配置成多例
    ----------------------------------------------------------
    如果没有配置scope=prototype则操作的时候不会新建一个action,他任然会保留上次访问的过记录的信息。以前错的,它同样会报错 ,它会一直停留在上次的访问记录不变
    
    ----------------------------------------------------------
    struts.xml中的配置
    <constant name="objectFactory" value="spring"></constant>//全局的参数,告诉struts框架对象的创建由
    
    spring创建
    
    <action name="login" class="loginAction">  class对应action-spring.xml  <bean id="loginAction"...
       <result name="success">index.jsp</result>
       <result name="input">login.jsp</result>
    </action> 
    
    ----------------------------------------------------------
    
    错误情况:
    
    配置时,出现的错误:
    
    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类的方法也会被视为返回数据,造成错误的产生!

    -----------------------------------------------------------------------------------------------------------------------------------【转】

      

  • 相关阅读:
    P1962 斐波那契数列(矩阵加速DP)
    P1939 【模板】矩阵加速(数列)
    剑指04.重建二叉树
    剑指03.从尾到头打印链表
    剑指02.替换空格
    剑指01.二维数组中的查找
    Python绘图学习笔记(待完善)
    时间观念 目标观念
    购房交税
    可以不做会计,但是不能不懂会计
  • 原文地址:https://www.cnblogs.com/tk55/p/6079207.html
Copyright © 2020-2023  润新知