关闭

struts2知识

标签: strutsactioniteratorstringclasslogin
960人阅读 评论(0) 收藏 举报
分类:

一、struts2概述
  struts2是在webwork2基础发展而来的。和struts1一样,也属于MVC框架。
  尽管struts2和struts1在名字上差别不大,但是在代码编写风格上几乎是不一样的。struts2有如下优点:
  1>在软件设计上,struts1属于侵入式设计,而struts2属于无侵入式设计。struts2没有像struts1那样跟servlet api和struts api有着紧密的耦合,struts2的应用可以不依赖于servlet api和struts api。
  2>struts2提供了拦截器,利用拦截器可以进行AOP编程,实现如拦截器等功能。
  3>struts2提供了类型转化器,可以把特殊的请求参数转换成需要的类型。
  4>struts2提供支持多种表现层技术,如:jsp,freemark,velocity等。
  5>struts2输入校验可以对指定方法进行校验,解决了struts1长久之痛。
  6>提供了全局范围、包范围、action范围的国际化资源文件管理实现。
 
二、搭建struts2开发环境:
1、找到开发struts2应用需要使用到的jar文件。
  开发struts2应用程序最少需要的jar包包括如下六个:
  1>struts2-core-2.x.x.jar:struts2框架的核心类库;
  2>xwork-2.x.x.jar:xwork类库,struts2在其上构建;
  3>ognl-2.6.x.jar:对象图导航语言,struts2框架通过其读写对象的属性;
  4>freemark-2.3.x.jar:struts2的UI标签的模板使用freemark编写;
  5>commons-logging-1.1.x.jar:ASF出品的日志包,struts2框架通过这个日志包来支持log4j和JDK1.4+的日志记录;
  6>commons-fileload-1.2.1.jar:文件上传组件,struts2.1.6版本后必须加入此包。
2、编写struts2配置文件。
  struts2默认配置文件为struts.xml,该文件需要存放在WEB-INF/classes下,该文件的配置模板如下:
  <?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>
   </struts>
3、在web.xml中是struts2 MVC框架启动配置。
  在struts1.x中,struts框架是通过servlet启动的,在struts2中,struts框架是通过filter启动。在web.xml中的配置如下:
  <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
        <!--自从struts2.1.3以后,下面的FilterDispatch已标注为过时
        <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>-->
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    在StrutsPrepareAndExecuteFilter的init()方法中将会读取类路径下默认的配置文件struts.xml完成初始化操作。
    注意:struts2读取到struts.xml的内容后,将会以javabean形式存放在内存中,以后struts2对用户的每次处理请求都将使用内存中的数据,而不是每次都读取struts.xml文件。

三、struts.xml配置中的包介绍
 <package name="itcast" namespace="/test" extends="struts-default">
  <action name="helloworld" class="cn.itcast.action.HelloWorldAction" method="execute">
   <result name="success">/WEB-INF/page/hello.jsp</result>
  </action>
 </package>
 在struts2框架中使用包来管理action,包的作用和java中的类包作用非常类似,它主要用来管理一组业务功能相关的action。
 配置包时必须制定name属性,该name属性可以任意取名,但必须唯一,他不对应java的类包,如果其他包要继承该包,必须通过该属性进行引用。
 包的namespace属性用于定义该包的命名空间,命名空间作为访问该包下action的路径的一部分,namespace可以不配置,默认为"",及空字符串。
  通常每个包都应该继承struts-default包,因为struts2很多核心的功能都是由拦截器来实现,例如请求中把请求参数封装到action、文件上传、数据验证等都是通过拦截器实现的。struts-default定义了这些拦截器和result类型,当包继承了struts-default时才能使用struts2提供的核心功能。struts-default是在struts2-core-2.x.x.jar文件中的struts-default.xml中定义。struts-default.xml也是struts2默认配置文件,struts每次都会自动加载此文件。
  包还可以通过abstract="true"定义为抽象包,抽象包中不能包含action。
 
四、action名称的搜索顺序
 步骤1.获得请求路径的URL,例如Url是:http://cn.itcast.struts2/path1/path2/login
 步骤2.首先会寻找namespace 为/path1/path2的package,如果不存在则会执行步骤3;如果存在这个namespace为/path1/path2的package,则在这个package下寻找名字为login的action,当在该package下寻找不到名卫login的action时,则会直接去默认的命名空间的package里寻找(默认命名空间卫空字符串“”),如果在默认namespace的package里寻找不到该action,页面提示找不到action。
 步骤3.寻找namespace为/path1的package,如果不存在则会执行步骤4;如果存在这个namespace为/path1的package,则在这个package下寻找名字为login的action,当在该package下寻找不到名为login的action时,则会直接去默认的命名空间的package里寻找(默认命名空间卫空字符串“”),如果在默认namespace的package里寻找不到该action,页面提示找不到action。
 步骤4.寻找namespace为/的package,如果存在这个namespace为/的package,则在这个package下寻找名字为login的action,当在该package下寻找不到名为login的action时或者不存在该package时,都会去默认的namespace的package里寻找(默认命名空间卫空字符串“”),如果还是找不到,页面提示找不到action。

五、action配置中的各项默认值
 <package name="itcast" namespace="/test" extends="struts-default">
  <action name="helloworld" class="cn.itcast.action.HelloWorldAction" method="execute">
   <result name="success">/WEB-INF/page/hello.jsp</result>
  </action>
 </package>
 1、如果没有为action指定class,默认是ActionSupport。
 2、如果没有为action指定method,默认执行action中的execute()方法。
 3、如果没有指定result的name属性,默认值为success。

六、action中result的转发类型
 result配置类似于struts1中的forward,但struts2中提供了多种结果类型,常用的类型有:dispatcher(默认值),redirect,redirectAction,plainText。
 1、在result中可以使用${属性名}表达式访问action中的属性,表达式里的属性名对应action中getXXX的xxx属性。如:
 <result type="redirect">/employeeAdd.jsp?username=${username}</result>
 2、redirectAction用于重定向action,如果重定向的action在同一个包下,则如下配置:
 <result type="redirectAction">helloworld</result>
 如果重定向的action在其他命名空间,则如下配置:
 <result type="redirectAction">
    <param name="namespace">/control/department</param>
    <param name="actionName">otherRedirectAction</param>
 </result>
 3、plainText用于显示原始文件内容,当我们需要原样显示jsp文件源代码的时候,我们可以使用此类型,配置如下:
 <result type="plainText">
    <param name="location">/index.jsp</param>
    <param name="charSet">UTF-8</param><!--指定读取文件的编码-->
 </result>
 
七、为action的属性注入值
 struts2为action的属性提供了依赖注入功能,在struts配置文件中,可以很方便的为action的属性注入值,注意:属性必须提供setter方法。
 public class helloWorldAction{
  private String savePath;
 
  public String getSavePath() {
   return savePath;
  }
 
  public void setSavePath(String savePath) {
   this.savePath = savePath;
  }
  ......
 }
 <package name="itcast" namespace="/test" extends="struts-default">
  <action name="setFiled" class="cn.itcast.action.HelloWorldAction" method="execute">
    <param name="savePath">/images</param>
    <result name="success">/WEB-INF/page/setFiled.jsp</result>
  </action>
 </package
 以上代码通过<param>节点为action的savePath属性注入值“/images”,此注入功能适用于某属性不能再action中固定,需要手动配置。
 
八、指定需要struts2处理的请求后缀
 通过常量struts.action.extension进行修改,多个后缀之间用英文逗号隔开,配置如下:
 <struts>
  <constant name="struts.action.extension" value="do,action"></constant>
 </struts>
 
九、常量定义
 常量可以在struts.xml或struts.properties中配置,建议在struts.xml中配置,两种配置方式如下:
 1、在struts.xml中配置常量:
 <struts>
  <constant name="struts.action.extension" value="do,action"></constant>
 </struts>
 2、在struts.properties中配置常量:
 struts.action.extension=do
 3、常量可以再下面多个配置文件中进行定义,struts2加载常量的搜索顺序如下:
 struts-default.xml
 struts-plugin.xml
 struts.xml
 struts.properties
 web.xml
 如果在多个文件中配置了同一个常量,则后一个文件中配置的常量值会覆盖前面文件中配置的常量值。
 
十、struts2常用的常量介绍
 在struts 2中,配置文件需要配置不少常量,其中常用的如下:
 1、<constant name="struts.i18n.encoding" value="UTF-8"/>
 struts.i18n.encoding:这个常量会作用于setCharacterEncoding方法和freemarker,velocity(这两种为模板技术)的输出,POST方式提交的数据,可以交由这个常量去设置它的编码格式。
 2、<constant name="struts.configuration.xml.reload" value="true" />
 struts.configuration.xml.reload:当struts的配置文件修改后,系统是否自动重新加载该文件,默认值为false,开发阶段最好打开,开发完后再关闭。
 3、<constant name="struts.serve.static.browserCache" value="false"/>
 truts.serve.static.browserCache:设置浏览器是否缓存,默认值为true,开发阶段最好关闭。
 4、<constant name="struts.devMode" value="true" />
 struts.devMode:打印出更详细的错误信息,用于排错,主要用于开发模式,做好了再关闭,在copy sturts-blank中的stuts.xml中,里面有这常量。
 5、<constant name="struts.ui.theme" value="simple" />
 struts.ui.theme:标签所使用的额外的自定义样式,不太实用,最好设置成simple,且一般都不用到struts 2的标签库。
 6、<constant name="struts.objectFactory" value="spring"/>
 struts.objectFactory:与spring继承时,指定由spring负责action对象的创建,在继承spring时,会用到这个常量.
 7、<constant name="struts.enable.DynamicMethodInvocation" value="true" />
 struts.enable.DynamicMethodInvocation:该属性设置struts2是否支持动态方法调用,该属性的默认值是true,如果需要关闭动态方法调用,则可设置该属性为false, 
 注意:DMI的调用方式Struts2的文档不建议使用,且下载的struts2-2-X.jar中,它的struts-blank中struts.xml有这常量,并设其值为false。
 8、<constant name="struts.multipart.maxSize" value="20971520" />
 struts.multipart.maxSize:设置上传文件的总大小限制。
 注意:用HTML方式来上传是无法上传太大的文件,很不稳定,可以说失败率超高。解决方法是用socket编个插件用于上传,而不能直接依赖。
 9、<constant name="struts.action.extension" value="do,go" />
 struts.action.extension:修改后缀名,默认是action,可以修改。若值有多个,可用逗号隔开,这对于常量的值都通用。
 10、<constant name="struts.custom.i18n.resources" value="baseName" />
 struts.custom.i18n.resources:用于配置国际化全局XML资源文件,须在指明该全局资源文件的基础名。
 11、<constant name="struts.ognl.allowStaticMethodAccess" value="true" />
 struts.ognl.allowStaticMethodAccess:如其名,用于设置OGNL是否允许静态方法访问,默认为false。
 
十一、struts2的处理流程
 用户请求--->StrutsPrepareAndExecuteFilter--->Interceptor(struts2内置的拦截器或用户自定义的拦截器)--->Action(用户编写的action类)--->Result--->Jsp/html--->响应。
 StrutsPrepareAndExecuteFilter是struts2框架的核心控制器,它负责拦截由<url-pattern></url-pattern>指定的所有用户请求,如果用户请求的路径不带后缀或后缀以action结尾,这时请求将被转到struts2框架处理,否则struts2框架将略过该请求的处理,当请求转入struts2框架处理时会经过一系列拦截器,然后再到action。
 注意:与struts1不同,struts2对用户每一次请求都会创建一个action,所以struts2中的action是线程安全的。
 
十二、为应用指定多个struts配置文件
 在大部分应用中,随着应用规模的增加,系统中action的数量也会大量增加,导致struts.xml配置文件变得非常臃肿。为了避免struts.xml文件过于庞大臃肿,提高struts.xml文件的可读性,可以将一个struts.xml配置文件分解为多个配置文件,然后在struts.xml文件中包含其他配置文件,配置如下:
 <struts>
  <include file="struts-user.xml"/>
  <include file="struts-order.xml"/>
 </struts>
 
十三、动态方法调用
 如果action存在多个方法,可使用!+方法名调用指定方法。
 public class HelloWorldAction
 {
  public String execute()
  {
   this.message = "我的第一个struts2应用";
   return "success";
  }
  
  public String other()
  {
   this.message = "第二个方法";
   return "success";
  }
 }
 <package name="itcast" namespace="/test" extends="struts-default">
  <action name="helloworld" class="cn.itcast.action.HelloWorldAction">
   <result name="success">/WEB-INF/page/hello.jsp</result>
  </action>
 </package>
 假设访问上面的action的url路径为:/struts/test/helloworld.action
 要访问action的other方法,可以调用:
 /struts/test/helloworld!other.action。
 如果不想使用动态方法调用,可以通过配置如下常量关闭:
 <constant name="struts.enable.DynamicMethodInvocation" value="true" />
 
十四、使用通配符定义action
 public class HelloWorldAction
 {
  public String execute()
  {
   this.message = "我的第一个struts2应用";
   return "success";
  }
  
  public String other()
  {
   this.message = "第二个方法";
   return "success";
  }
 }
 <package name="itcast" namespace="/test" extends="struts-default">
  <action name="helloworld_*" class="cn.itcast.action.HelloWorldAction" method="{1}">
   <result name="success">/WEB-INF/page/hello.jsp</result>
  </action>
 </package>
 要访问other()方法,可通过如下url访问:
 /test/helloworld_other.action
 注意:action配置中所有method,result路径中都可只用通配符。
 
十五、接受请求参数
 1、采用基本类型接受请求参数(get/post)
 在action类中定义与请求参数同名的属性,struts2便能自动接收请求参数并赋予给同名属性。
 请求路径:http://localhost:8080/test/view.action?id=10
 public class productAction {
  private Integer id;
  public void setId(Integer id) {//通过反射技术调用与请求参数同名的属性的setter方法来获取请求参数值
   this.id = id;
  }
 }
 2、采用复合类型接收请求参数
 请求路径:http://localhost:8080/test/view.action?product.id=10
 public class productAction {
  private Product product;
 
  public Product getProduct() {
   return product;
  }
  public void setProduct(Product product) {
   this.product = product;
  }
 struts2首先通过反射技术调用Product的默认构造器创建product对象,然后再通过反射技术调用product中与请求参数同名的属性的setter方法来获取请求参数值。
 
十六、自定义类型转换器
 public class DateTypeConverter extends DefaultTypeConverter {
  @Override
  public Object convertValue(Map<String, Object> context, Object value,
    Class toType) {
   SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
   try {
    if (toType == Date.class) {
     String[] params = (String[]) value;
     return dateFormat.parse(params[0]);
    } else if (toType == String.class) {
     Date date = (Date) value;
     return dateFormat.format(date);
    }
   } catch (ParseException e) {
    e.printStackTrace();
   }
   return null;
  }
 }
 1、将上面的类型转换器注册为局部类型转换器,步骤如下:
 1>在action类所在包下放置ActionClassName-conversion.properties文件,ActionClassName是Action类名,后面的-conversion.properties是固定写法。
 2>在properties文件中的内容为:
 属性名称=类型转换器的全类名,如:birthday=cn.itcast.converter.DateTypeConverter。
 2、将上面的类型转换器注册为全局类型转换器,步骤如下:
 1>在WEB-INF/class下放置xwork-conversion.properties文件。
 2>在properties文件中的内容为:
 待转化的类型=类型转换器的全类名,如:java.util.Date=cn.itcast.converter.DateTypeConverter。
 
十七、添加或访问request/session/application范围的属性
 java代码:
 public String scope()
 {
  ActionContext ctx = ActionContext.getContext();
  ctx.getApplication().put("app", "application范围");
  ctx.getSession().put("sess", "session范围");
  ctx.put("req", "request范围");
  ctx.put("names", Arrays.asList("张三","李四","王五"));
  return "success";
 }
 jsp页面代码:
 <body>
     应用范围:${applicationScope.app}<br>
     会话范围:${sessionScope.sess}<br>
     请求范围:${request.req}<br>
     <c:forEach items="${names}" var="name">
      ${name}<br/>
     </c:forEach>
  </body>
 
十八、获取HttpServletRequest/HttpSession/ServletContext/HttpServletResponse对象
 方法一,通过ServletActionContext对象直接获取:
 public String rsa()
 {
  HttpServletRequest request = ServletActionContext.getRequest();
  ServletContext servletContext = ServletActionContext.getServletContext();
  request.setAttribute("req", "request范围属性");
  request.getSession().setAttribute("sess", "session范围属性");
  servletContext.setAttribute("app", "application范围属性");
  HttpServletResponse response = ServletActionContext.getResponse();
  return "success";
 }
 方法二,实现指定接口,由struts框架运行时注入:
 public class ScopeObject implements ServletRequestAware, ServletResponseAware,
  ServletContextAware {
  private HttpServletRequest request;
  private HttpServletResponse response;
  private ServletContext servletContext;
 
  public void setServletRequest(HttpServletRequest req) {
   this.request = req;
  }
 
  public void setServletResponse(HttpServletResponse res) {
   this.response = res;
  }
 
  public void setServletContext(ServletContext ser) {
   this.servletContext = ser;
  }
 }
 
十九、文件上传
 第一步,在WEB-INF/lib下加入commons-fileupload-1.2.1.jar、commons-io-1.3.2.jar(FileUtils工具类)。
 第二步,把form表单的enctype设置为:"multipart/form-data"
 <form
   action="${pageContext.request.contextPath}/control/employee/fileUpload.action"
   enctype="multipart/form-data" method="post">
   请选择上传文件:<input type="file" name="uploadFile"/>
   <input type="submit" value="上传"/>
 </form>
 第三步,在action类中添加以下属性:
 public class FileUploadAction {
  private File uploadFile; //上传文件
  private String  uploadFileContentType; //上传文件类型,此属性名固定为上传文件属性名+ContentType
  private String uploadFileFileName; //上传文件名称,此属性名固定为上传文件属性名+FileName
 
  //此处省略getter,setter方法
  
  public String uploadFile() throws IOException
  {
   String realPath = ServletActionContext.getServletContext().getRealPath("/uploadFile");
   if(null != uploadFile)
   {
    File saveFile = new File(new File(realPath), uploadFileFileName);
    if(!saveFile.getParentFile().exists())
    {
     saveFile.getParentFile().mkdirs();
    }
    FileUtils.copyFile(uploadFile, saveFile);
    ActionContext.getContext().put("uploadInfo", "上传成功");
   }
   return "success";
  }
 }
 注意:struts默认上传文件大小限制为:2097152kb,如下配置可修改上传文件的总大小限制:
 <constant name="struts.multipart.maxSize" value="100000000"></constant>
 大文件一般不用web实现,而是安装插件,类似迅雷的软件,集成在浏览器,通过socket连接到服务器,往服务器的某端口发送数据,实现断点续传,多线程功能。
 
二十、多文件上传
 第一步,在WEB-INF/lib下加入commons-fileupload-1.2.1.jar、commons-io-1.3.2.jar(FileUtils工具类)。
 第二步,把form表单的enctype设置为:"multipart/form-data"
 <form
   action="${pageContext.request.contextPath}/control/employee/filesUpload.action"
   enctype="multipart/form-data" method="post">
   请选择上传文件:<br/>
   文件1:<input type="file" name="uploadFile"/><br/>
   文件2:<input type="file" name="uploadFile"/><br/>
   文件3:<input type="file" name="uploadFile"/><br/>
   <input type="submit" value="上传"/>
 </form>
 第三步,在action类中添加以下属性:
 public class FilesUploadAction {
  private File[] uploadFile; //上传文件,数组或list集合接受上传文件
  private String[]  uploadFileContentType; //上传文件类型
  private String[] uploadFileFileName; //上传文件名称
 
  //此处省略getter,setter方法
 
  public String uploadFiles() throws IOException
  {
   String realPath = ServletActionContext.getServletContext().getRealPath("/uploadFile");
   if(null != uploadFile)
   {
    File saveDir = new File(realPath);
    if(!saveDir.exists())
    {
     saveDir.mkdirs();
    }
    for(int i=0; i<uploadFile.length; i++)
    {
     File saveFile = new File(saveDir, uploadFileFileName[i]);
     FileUtils.copyFile(uploadFile[i], saveFile);
    }
    ActionContext.getContext().put("uploadInfo", "上传成功");
   }
   return "success";
  }
 }
 
二十一、自定义拦截器
 <package name="itcast" namespace="/test" extends="struts-default"> 
  <interceptors>
    <interceptor name="permissionInterceptor" class="cn.itcast.interceptor.PermissionInterceptor"></interceptor>
    <interceptor-stack name="permissionStack">
     <interceptor-ref name="defaultStack"></interceptor-ref>
     <interceptor-ref name="permissionInterceptor"></interceptor-ref>
    </interceptor-stack>
  </interceptors>
  <action name="login_*" class="cn.itcast.action.LoginAction" method="{1}">
    <result name="success">/WEB-INF/page/login.jsp</result>
    <interceptor-ref name="permissionStack"></interceptor-ref>
  </action>
 </package
 因为struts2中文件上传、数据校验、封装请求参数到action等功能都是由系统默认的defaultStack中的拦截器实现的,所以我们实现的拦截器需要引用系统默认的defaultStack,这样才可以使用struts2框架提供的众多功能。
 如果希望包下的所有action都使用自定义拦截器,可以通过<default-interceptor-ref name="permissionStack"/>把拦截器定义为默认拦截器。
 注意:每个包只能指定一个默认拦截器,一旦为该包中的某个action显示指定了某个拦截器,则默认拦截器不会起作用,如果需要让默认拦截器起作用,必须在action中再显示指定一遍。
 
二十二、输入校验方法
 在struts2中,我们可以实现对action的所有方法或指定方法进行校验。
 struts2提供两种实现输入校验的方法:
 1、采用手工编写代码实现,会对所有方法进行校验。
  两种校验方法:
  一是通过重写validate()方法实现,validate()方法会校验action中所有与execute方法签名相同的方法;
  二是通过重写validateXxx()方法实现,validate()方法会校验action中xxx()方法;
  当某个数据校验失败时,我们应该调用addFiledError()方法往系统的filedErrors添加校验失败信息,为了使用addFiledError()方法,action可以继承ActionSupport类。如果系统的filedErrors包含校验失败信息,struts2会将请求转发到input的result,在input视图中可以通过<s:filederror/>显示失败信息。
  1>重写validate()方法:
  public void validate() {
   if(null == this.mobile || "".equals(this.mobile.trim()))
   {
    this.addFieldError("mobile", "手机号码不能为空");
   }
   else
   {
    if(!Pattern.compile("^1[358]\\d{9}$").matcher(mobile).matches())
    {
     this.addFieldError("mobile", "手机号码格式不正确");
    }
   }
  }
  2>校验失败后,请求转发到input视图:
  <result name="input">/login.jsp</result>
  3>在login.jsp页面使用<s:fieldError/>显示失败信息。
 2、基于XML配置方式实现。
  使用基于xml配置方式实现输入校验时,Action也需要继承ActionSupport,并且提供校验文件,校验文件和action类放在同一包下,文件取名有一下两种情况:
  1>文件的取名格式为:ActionClassName-validation.xml,会对action中的所有方法进行输入校验,其中ActionClassName为action的简单类名,-validation.xml为固定写法。
  2>文件的取名格式为:ActionClassName-ActionName-validation.xml,会对action中的某个action方法进行输入校验,其中ActionClassName为action的简单类名,ActionName为struts.xml中action的名称,-validation.xml为固定写法。
  校验文件的模板配置如下:
  <!DOCTYPE validators PUBLIC
        "-//OpenSymphony Group//XWork Validator 1.0.3//EN"
        "http://www.opensymphony.com/xwork/xwork-validator-1.0.3.dtd">
  <validators>
      <field name="username">
          <field-validator type="requiredstring">
           <param name="trim">true</param>
              <message>用户名不能为空!</message>
          </field-validator>
      </field>
      <field name="mobile">
          <field-validator type="requiredstring">
              <param name="trim">true</param>
              <message>手机号码不能为空!</message>
          </field-validator>
      </field>
      <field name="mobile">
          <field-validator type="regex">
           <param name="expression"><![CDATA[^1[358]\d{9}$]]></param>
           <message>手机号码格式不正确</message>
          </field-validator>
      </field>
  </validators>
 各属性说明如下:
 <field>指定action中要校验的属性;
 <field-validator>指定校验器,struts2提供了能满足大部分验证需求的校验器,这些校验器定义可以在xwork-2.x.jar中的com.opensymphony.xwork2.validator.validators下的default.xml中找到。
 <message>为校验失败后的提示信息,如果需要国际化,可以为message指定key属性,key的值为资源文件中的key。
 
二十三、输入校验流程
 1、类型转换器对请求参数执行类型转换,并把转换后的值赋给action中的属性。
 2、如果在执行类型转换的过程中出现异常,系统会将异常信息保存到ActionContext,conversionError拦截器会将异常信息添加到fieldErrors里。不管类型转换器是否出现异常,都会进入第2步。
 3、系统通过反射技术先调用action中的validateXxx()方法,Xxx为方法名。
 4、调用action中的validate()方法。
 5、如果系统中的filedErrors存在错误信息,系统自动将请求转发至名称为input的视图,如果系统中filedErrors没有任何错误信息,系统将执行action中的处理方法。
 
二十四、基于xml校验的特点:
 当sonAction继承了另外一个baseAction,父类baseAction的校验文件会先被搜索到。系统按如下顺序校验文件:
 1、BaseAction-validation.xml
 2、BaseAction-ActionName-validation.xml
 3、sonAction-validation.xml
 4、sonAction-ActionName-validation.xml
 系统寻找到第一个校验文件时还会继续搜索后面的校验文件,当搜索到所有校验文件时,会把校验文件里的所有校验规则汇总,然后全部应用于action方法的校验。如果两个校验文件中指定的校验规则冲突,则只使用后面文件的校验规则。
 
二十五、国际化---输出带占位符的国际化信息
 1、资源文件包括中文资源文件login_zh_CN.properties和英文资源文件login_en_US.properties。
 login_zh_CN.properties配置如下:
 welcome={0},欢迎光临{1}!
 login_en_US.properties配置如下:
 welcome={0},welcome to {1}!
 2、准备好资源文件之后,在struts.xml中通过struts.custom.i18n.resource常量把资源文件定义为全局资源文件,例如:
 <constant name="struts.custom.i18n.resource" value="itcast"></constant>
 itcast为资源文件的基本名称。
 3、在action类中获取带占位符的国际化信息,可以使用getText(String key,String[] args)或getText(String aTextName,List args)方法,例如:
 ActionContext.getContext().put("message", this.getText("welcome", new String[]{"zhangsan","study"}));
 4、在jsp页面输出带占位符的国际化信息:
 <s:text name="welcome">
     <s:param>zhangsan</s:param>
     <s:param>itcast</s:param>
  </s:text>
  name属性为资源文件中的key。
  5、在表单标签中,通过key属性指定资源文件中的key,例如:
  <s:textfield name="realname" key="user"/>

二十六、国际化---包范围资源文件
 在大型应用中,有大量的内容需要国际化,为便于维护,可针对不同模块,使用包范围来组织国际化资源文件。
 方法如下:
 在java包下放置package_language_country.properties资源文件,package为固定写法,处于该包及子包下的action都可以访问该资源。
 当查找指定key时,系统会先从指定package资源文件查找,当找不到对应key时,才会从常量struts.custom.i18n.resource指定的资源文件中查找。
 
二十七、国际化---action范围资源文件
 为某个action单独指定资源文件,方法如下:
 在action所在的路径,放置ActionClasName_language_country.properties资源文件,ActionClassName就是action类的简单名称。
 struts2查找指定key的搜素顺序:
 1、ActionClasName_language_country.properties
 2、如果未找到,则查找package_language_country.properties,从当前包往上查找基本名为package的资源文件,一直找到最顶层包。
 3、如果未找到,则查找struts.custom.i18n.resource指定的资源文件。

二十八、国际化---jsp中直接访问某个资源文件
 struts2提供了<s:i18n>标签,使用此标签可以再类路径下直接从某个资源文件中获取国际化数据,而无需任何配置:
 <s:i18n name="itcast">
  <s:text name="welcome"/>
 </s:i18n>
 itcast为类路径下的资源文件的基本名。
 如果要访问的资源文件在类路径的某个包下,可以这样访问:
 <s:i18n name="cn/itcast/action/package">
  <s:text name="welcome"/>
 </s:i18n>
 如果要访问某action名称为ActionclassName对应的资源文件,可以这样访问:
 <s:i18n name="cn/itcast/action/ActionclassName">
  <s:text name="welcome"/>
 </s:i18n>

二十九、OGNL表达式语言
 OGNL是object graphic navigation language,对象图导航语言,是一个开源项目,struts2框架使用ognl作为默认的表达式语言。
 相对el表达式,ognl提供了平时我们需要的一些功能,例如:
 1、支持对象方法调用,如xxx.sayHello()。
 2、支持类静态方法调用和值访问,表达式的格式为:@[类全名]@[方法名|值名],如:@java.lang.String@format('foo %s','bar')或@cn.itcast.Constant@APP_NAME。
 3、操作集合对象。
 struts2中的ognl Context实现为ActionContext,ognl Context包括valueStack(根对象),parameters,request,session,application,attr。当struts2接受一个请求时,会迅速创建ActionContext,valueStack,action,然后把action存放进valueStack,所以action的实例变量可以被ognl访问。
 由于valuestack是struts2中ognl的根对象,如果用户需要访问valueStack中的对象,在jsp页面可以直接通过el表达式访问valueStack中对象的属性。
 如果访问其他context中的对象,由于他们不是根对象,所以在访问时,需要添加#前缀。
 1、application对象:用于访问ServletContext,例如#application.userName或者#application['username'],相当于调用ServletContext.getAttribute('username');
 2、session对象:用于访问HttpSession,例如#session.userName或者#session['username'],相当于调用session.getAttribute('username');
 3、request对象:用于访问HttpServletRequest,例如#request.userName或者#request['username'],相当于调用request.getAttribute('username');
 4、parameters对象:用于访问http的请求参数,例如#parameters.userName或者#parameters['username'],相当于调用request.getParameter('username');
 5、attr对象:用于按page->request->session->application顺序访问其属性。
 使用el表达式能够访问valueStack中对象的属性,是因为:struts2对httpServletRequest做了进一步的封装,先从request中获取属性值,如果没有找到,会从值栈中查找对象的属性值。
 采用ognl表达式创建list/map集合对象:
 如果需要一个集合元素的时候,可以使用ognl中同集合相关的表达式,使用如下代码直接生成一个list对象或map对象。
 <s:set name="list" value="{'first','second','third'}" scope=""></s:set>
  <s:iterator value="#list">
     <s:property/><br/>
  </s:iterator>
  <s:set name="map" value="#{'key1':100,'key2':'value2'}"></s:set>
  <s:iterator value="#map">
     <s:property value="key"/>:<s:property value="value"/><br/>
  </s:iterator>
  set标签用于将某个值放入指定范围。
  scope:指定变量被放置的范围,该属性可以接受application、session、request、page、action,如果没有设置该属性,则默认放置在ognl context中。
  value:赋给变量的值,如果没有设置该属性,则将valueStack栈顶的值赋给变量。
  property标签用于输出指定值,value属性指定需要输出的属性值,如果没有指定该属性,则默认输出valuestack栈顶的值。
  对于集合类型,ognl表达式可以使用in和not in两个元素符号,用于判断某个元素是否在或者不在指定的集合对象中,例如:
  <s:if test="'foo' in {'foo','bar'}">
     foo在集合中
  </s:if>
  <s:else>
     foo不在集合中
  </s:else>
  ognl还允许使用某个规则获得集合对象的子集,常用的有以下3个相关操作符:
  ?:获得所有符合逻辑的元素。
  ^:获得符合逻辑的第一个元素。
  $:获得符合逻辑的最后一个元素。
  例如:
  <s:iterator value="books.{?#this.price>60}">
     bookName:<s:property value="name"/>,price:<s:property value="price"/><br/>
  </s:iterator>
 在上面代码中,直接在集合后紧跟.{}运算符表明用于取出该集合的子集,{}内的表达式用于获取符合条件的元素,this指的是为了从大集合books筛选数据到小集合,需要对大集合books进行迭代,this代表当前迭代的元素。
 
三十、struts2标签
 1、property标签
 property标签用于输出指定值
 <s:set name="username" value="zhangsan"/>
 <s:property value="#name"/>
 default:可选属性,如果需要输出的属性值为null,则显示该属性指定的值。
 escape:可选属性,指定是否格式化HTML代码。
 value:可选属性,指定需要输出的属性值,如果没有指定该属性,则默认输出valuestack栈顶的值。
 id:可选属性,指定该元素的表示。
 2、iterator标签
 iterator标签用于对集合进行迭代,这里的集合包含List,Set和数组。
 <s:set name="list" value="{'first','second','third'}" scope=""></s:set>
  <s:iterator value="#list" status="st">
     <font color="<s:if test="#st.odd">red</s:if><s:else>blue</s:else>">
      <s:property/>
     </font><br/>
  </s:iterator>
  value:可选属性,指定被迭代的集合,如果没有设置该属性,则使用valuestack栈顶的集合。
  status:可选属性,该属性指定迭代时的Iteratorstatus实例。
 3、if/elseif/esle标签
 用于条件判断,例如:
 <s:set name="age" value="20" scope="request"></s:set>
  <s:if test="#request.age==10">
   10
  </s:if>
  <s:elseif test="#request.age==20">
   20
  </s:elseif>
  <s:else>
   都不相等
  </s:else>
  scope:指定获取属性值的范围。
  4、url标签
  <s:url action="ognl_test" namespace="test">
    <s:param name="username" value="'zhangsan'"></s:param>
  </s:url>
  生成路径为:/xxx/test/ognl_test.action?username=zhangsan。
  当标签的属性值作为字符串类型处理时,“%”符号的用途是计算ognl表达式的值。
  <s:set name="myurl" value="'www.baidu.com'"></s:set>
  <s:url  value="#myurl"></s:url>
  <s:url  value="%{#myurl}"></s:url>
 输出结果:
 #myurl
 www.baidu.com
 5、表单标签——checkboxlist复选框,radio单选框,select下拉列表应用相似。
 1>集合为list
 <s:checkboxlist name="checkList" list="{'first','second','third'}" value="{'first','third'}"></s:checkboxlist>
 生成代码如下:
 <tr>
    <td class="tdLabel"></td>
    <td>
   <input type="checkbox" name="checkList" value="first" id="checkList-1" checked="checked"/>
   <label for="checkList-1" class="checkboxLabel">first</label>
   <input type="checkbox" name="checkList" value="second" id="checkList-2"/>
   <label for="checkList-2" class="checkboxLabel">second</label>
   <input type="checkbox" name="checkList" value="third" id="checkList-3" checked="checked"/>
   <label for="checkList-3" class="checkboxLabel">third</label>
   <input type="hidden" id="__multiselect_checkList" name="__multiselect_checkList" value="" />    
  </td>
 </tr>
 注意:<tr><td>标签是struts2自动生成的主题样式,可在struts.xml配置如下常量进行关闭。
 <constant name="struts.ui.theme" value="simple" />
 关闭之后,生成代码如下:
 <input type="checkbox" name="checkList" value="first" id="checkList-1" checked="checked"/>
 <label for="checkList-1" class="checkboxLabel">first</label>
 <input type="checkbox" name="checkList" value="second" id="checkList-2"/>
 <label for="checkList-2" class="checkboxLabel">second</label>
 <input type="checkbox" name="checkList" value="third" id="checkList-3" checked="checked"/>
 <label for="checkList-3" class="checkboxLabel">third</label>
 <input type="hidden" id="__multiselect_checkList" name="__multiselect_checkList" value="" />
 2>集合为map:
 <s:checkboxlist name="checkMap" list="#{1:'first',2:'second',3:'third'}" listKey="key" listValue="value" value="{1,2}"></s:checkboxlist>
 其中listKey指定checkbox的value值,listValue指定页面显示的值。
 生成代码如下:
 <input type="checkbox" name="checkMap" value="1" id="checkMap-1" checked="checked"/>
 <label for="checkMap-1" class="checkboxLabel">first</label>
 <input type="checkbox" name="checkMap" value="2" id="checkMap-2" checked="checked"/>
 <label for="checkMap-2" class="checkboxLabel">second</label>
 <input type="checkbox" name="checkMap" value="3" id="checkMap-3"/>
 <label for="checkMap-3" class="checkboxLabel">third</label>
 <input type="hidden" id="__multiselect_checkMap" name="__multiselect_checkMap" value="" />

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:203887次
    • 积分:2239
    • 等级:
    • 排名:第16759名
    • 原创:63篇
    • 转载:17篇
    • 译文:0篇
    • 评论:26条
    最新评论