struts2 开发集锦

来源:互联网 发布:在研究所工作的人 知乎 编辑:程序博客网 时间:2024/05/17 05:00

1. Struts2的开发步骤
1) 在classpath中添加如下包:
    struts2-core-2.1.8.1.jar, xwork-core-2.1.6.jar, ognl-2.7.3.jar, freemarker-2.3.15.jar, common-fileupload-1.2.1.jar, common-io-1.3.2.jar
2) 在web.xml中添加过滤器:
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
3) 在classpath中添加Struts2的配置文件struts.xml:
4) 编写Action类。
=======================================================================================
1. Struts2整合Spring
1) 添加Struts2和Spring需要的Jar包到classpath中。
2) 在应用的classpath路径下添加strut2配置文件(struts.xml)和spring配置文件 (applicationContext.xml)。
3) 把struts2-spring-plugin-xxx.jar插件包添加到应用的classpath路径下。
4) 把strut2框架的对象工厂设置为Spring提供:在struts.xml配置文件中添加常量配置
    <constant name="struts.objectFactory" value="spring" />
5) 在web.xml中配置监听器来初始化Spring的ApplicationContext:具体配置参见Spring应用
6) 把需要由Spring管理的Action类等配置到Spring配置文件中。
    struts.xml中Action的配置如下:
    <action name="login" class="accountAction">
<result name="success">/success.jsp</result>
<result name="error">/error.jsp</result>
</action>
那么在Spring配置文件中需要添加如下bean的配置:
<bean name="accountAction" class="com.qiujy.web.action.AccountAction">
<property name="accountService" ref="accountService"/>
</bean>
==============================================================================================
1. Struts2中基于注解的Action配置
  1) @ParentPackage 指定父包
  2) @Namespace 指定命名空间
  3) @Results 一组结果的数组
  4) @Result(name="success",location="/msg.jsp") 一个结果的映射
  5) @Action(value="login") 指定某个请求处理方法的请求URL。注意,它不能添加在Action类上,要添加到方法上。
  6) @ExceptionMappings 一级声明异常的数组
  7) @ExceptionMapping 映射一个声明异常
==============================================================================================
1. Struts2中的OGNL的使用。
2. OGNL:对象图导航语言。通过OGNL表达式可以获取对象的属性,调用对象的方法,或构造出对象。
  1) OGNL上下文中有一个根对象。这个根对象可以直接获取。不需要#。
  2)支持常量:
         字符串常量、字符常量、
         数值常量:int、long、float、double
         布尔常量:true、false
    Null常量 : null
         支持操作符:支持Java的所有操作符,还支持特有的操作符: , {}、in、not in;
3. Struts2中的OGNL:
  1) Struts2将ActionContext设置为OGNL上下文,并将值栈(ValueStack)作为OGNL的根对象放置到 ActionContext中。
  2) Struts2总是把当前Action实例放置在值栈的栈顶。所以,在OGNL中引用Action中的属性也可以省略“#”。
4. 常用标签
1) <s:property value="OGNL"/>
2) <s:date name="OGNL" format=""/>
3) <s:if test="OGNL"></s:if><s:elseif test="OGNL"></s:elseif><s:else></s:else>
★4) <s:iterator value="OGNL" status="vs">...</s:iterator>
5) <s:debug/>
==============================================================================================================
1. Struts2中的类型转换器
  1) Struts2中内置了一些常用的类型转换器:可以把客户端提交的String数据转换成对应类型的数据。
     a) 基本类型
     b) java.util.Date:
     c) 数组和列表
  2) 自定义类型转换器:
     a) 继承自org.apache.struts2.util.StrutsTypeConverter类
  public abstract Object convertFromString(Map context, String[] values, Class toClass);
        context:OGNL上下文的Map对象
        values :需要转换的字符串数组
        toClass:要转换的目标类型
  public abstract String convertToString(Map context, Object o);
         context:OGNL上下文的Map对象
         o:需要转换的对象
     b) 注册:以全局方式
                    在应用程序的classpath下创建一属性文件,名为:xwork-conversion.properties
                    文件内容:待转换类型的全限定名=类型转换器类的全限定名
  3) 转换Set:
     0) Action中的Set属性需要进行初始化:如:
        private Set<User> userSet = new HashSet<User>();
     a) 添加针对某个Action的转换器配置文件:ActionName-conversion.properties 如:
        UserAction-conversion.properties
     b) 在这个文件中添加:Action的Set属性的相关配置
        Element_属性名=Set中的元素类型的全限定名                 #指定Set中的元素类型
        KeyProperty_属性名=Set中的元素类型中的某个属性  #指定Set的索引字段
                   如下示例:
        Element_userSet=com.qiujy.domain.User
        KeyProperty_userSet=id
     c) JSP页面: <input type="text" name="Set属性名.makeNew[0].属性名"/>
                    如:<input type="text" name="userSet.makeNew[0].loginname"/>
遗留问题
1. Map类型怎么转换?
2. 类型转换错误处理时,怎么不跳转到input结果页?
================================================================================
1. Struts2中的输入校验
2. 编码方式校验
  1) Action一定要继承自ActionSupport
  2) 针对某个要进行校验的请求处理方法编写一个 public void validateXxx()方法,在方法内部进行表单数据校验.
  3) 也可针对所有的请求处理方法编写public void validate()方法。
  4) 在校验方法中,可以通过addFieldError()方法来添加字段校验错误消息。
  5) 当校验失败时,Struts框架会自动跳转到name为input的Result页面。在校验失败页面中,可以使用<s:fielderror/>来显示错误消息
  6) 简单,灵活。但重用性不高。
3. XML配置方式校验。在编码方式之前被执行。
  1) 针对要校验的Action类,在同包下编写一个名为:Action类名-validation.xml校验规则文件。
  2) 在校验规则文件中添加校验规则:具体的校验器名,参数可参看Struts2的reference或Struts2的API。
     a) Field校验:针对Action类中每个非自定义类型的Field进行校验的规则。
    <field name="要校验的Field名">
   <field-validator type="校验规则器名" short-circuit="是否要短路径校验(默认是false)">
       <param name="校验器要使用的参数名">值</param>
            <message>校验失败时的提示消息</message>
</field-validator>
<!-- 还可添加其它的校验规则 -->
</field>
     b) 非Field校验:针对Action类的某些Field使用OGNL表达进行组合校验。
    <validator type="fieldexpression">
<param name="fieldName">pwd</param>
     <param name="fieldName">pwd2</param>
     <param name="expression"><![CDATA[pwd==pwd2]]></param><!-- OGNL表达式 -->
     <message>确认密码和密码输入不一致</message>
</validator>
     c) visitor校验:主要是用来校验Action类中的自定义类型Field。(针对使用模型驱动方式时)
       i) 在Action类的的校验规则文件中针对自定义类型Field使用visitor校验规则。
    <!-- 针对自定义Field使用visitor校验 -->
<field name="user">
<field-validator type="required" short-circuit="true">
            <message>用户的信息必填</message><!-- 消息前缀 -->
</field-validator>
<field-validator type="visitor"><!-- 指定为visitor校验规则 -->
<param name="context">userContext</param><!-- 指定本visitor校验的上下文名 -->
            <param name="appendPrefix">true</param><!-- 是否要添加校验失败消息的前缀 -->
            <message>用户的</message><!-- 消息前缀 -->
</field-validator>
</field>
  ii) 针对visitor的Field编写一个校验规则文件.文件名为: visitor字段类型名[-visitor校验的上下文名]-validation.xml. 例如: 本例中的文件名为User-userContext-validation.xml
                注意: 此文件要存放到visitor字段类型所在的包下.
  iii) 在visitor的Field校验规则文件中针对要校验的Field添加校验规则.
   3) 在校验失败页面(名为input的result页面)中,可以使用<s:fielderror/>来显示错误消息。
   4) 默认情况下,XML的校验规则对Action中所有的请求处理方法生效.此时应该只针对每个要校验的请求处理方法指定校验。有两种方式:
      i) 只为Action中的指定方法指定校验规则文件,配置文件命名为:Action类型名-别名-validation.xml,
                      别名是要校验的方法对应的Action标签的name属性值。
                      如:UserAction在struts2.xml的配置为:
    <package name="my" extends="struts-default" namespace="/">
<action name="user_*" class="com.qiujy.web.action.UserAction" method="{1}">
<result name="success">/info.jsp</result>
<result name="input">/user_{1}.jsp</result>
</action>
    </package>             
                ● UserAction中有registe方法和login方法,要对registe方法进行校验,则它的校验规则文件名为:UserAction- user_registe-validation.xml。
                 ● 如果使用visitor校验器,必需指定visitor校验的上下文名。
      ii) 在校验拦截器中指定要验证的方法。不太实用。
   <action name="user_*" class="com.qiujy.web.action.UserAction" method="{1}">
    <result name="success">/info.jsp</result>
    <result name="input">/user_{1}.jsp</result>
     <interceptor-ref name="defaultStack">
        <!-- 给校验拦截器指定不进行校验的方法列表:用逗号隔开 -->
        <param name="validation.excludeMethods">*</param>
        <!-- 给校验拦截器指定要进行校验的方法列表:用逗号隔开 -->
        <param name="validation.includeMethods">regist</param>
      </interceptor-ref>
   </action>
   5) 同时使用客户端校验和服务器端校验
      i) 设置<s:form>标签的validate属性:
         false:默认值。校验框架只执行服务器端校验。
         true:先执行客户端校验,然后再执行服务器端校验。
         form标签会根据你在服务器端配置的验证规则生成对应的JavaScript验证代码。
                      目前支持的内置校验器:required、requiredstring、stringlength、regex validator、email、url、int、double
      ii) 不太好用,不建议使用。建议使用jQuery进行页面表单校验。
   6) 自定义校验器:
      i) 继承自FieldValidatorSupport抽象类。重写validate(Object obj)方法
      ii) 注册校验器类. 在应用程序的classpath下新建一校验器注册文件。名为validators.xml,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
        "-//OpenSymphony Group//XWork Validator Config 1.0//EN"
        "http://www.opensymphony.com/xwork/xwork-validator-config-1.0.dtd">
<validators>
  <validator name="校验器名" class="校验器类的全限定名"/>
</validators>
4. Annotation方式校验: Struts2提供了注解的方式校验
  1) @Validation 指明这个类或者接口将使用基于注解的校验。Struts2.1中已被标识为过时。
  2) @Validations() 在同一个方法上要使用多个注解校验时。
  3) @SkipValidation 指定某个方法不需要校验。否则所有方法都会使用校验。也可以在检验拦截器中使用validateAnnotatedMethodOnly
  4) 13个内置校验器的注解版本:(注:这些注解都只能用在方法级别上) 具体参数参见Struts2的API或Reference。
@RequiredFieldValidator
@RequiredStringValidator
@StringLengthFieldValidator
@IntRangeFieldValidator
@DoubleRangeFieldValidator
@DateRangeFieldValidator
@ExpressionValidator
@FieldExpressionValidator
@RegexFieldValidator
@EmailValidator
@UrlValidator
@VisitorFieldValidator
@ConversionErrorFieldValidator
======================================================================
5.Java对国际化的支持:java内部使用unicode编码方式:
1)java.util.Locale 表示了特定的的地理,政治和文化地区,环境信息的对象
有语言代码和区域代码组成;
语言代码小写字母:en,zh
区域代码大写字母:US,CH ,TW,HK
2)java.util.Resourcebundle 用于绑定特定语言环境的资源对象;
资源文件的命名规范:基本名_语言代码[_区域代码].properties
默认资源文件名:基本名.properties;
3)  java.util.MessageFormat 用于对含有占位符的字符进行格式化输出;
4)编码方式
Locale locale =Locale.CHINA;
ResourceBundle rb =ResourceBundle.getBundle("资源文件的基本名",locale);
String value=rb.getstring("key");
String str=messageFormat.format(value,Object... arguments);
=====================================================================
在struts2中国际化的原理:
1 ) 在classpath中天际正对特定语言环境中的配置文件
2 ) 在struts.xml中通过常量配置注册资源文件的基本名:
<constant name="struts.custom.i18n.resources" value="msg"/>
3 ) 在jsp页面中 用<s:text value="资源文件中key"/>
4 ) 在Aciotn中,可以使用ActionSupport 类提供的getText("")
=====================================================
------------------------------------------------------文件上传 ------------------------------------
struts2 中的文件上传
1. 在文本应用使用common-fileupload.jar实现文件上传
2.struts2 中文件上传:
在jsp页面中 在Form表单中 要指定type="multpart/-data"
在Action 中
      File upFile; String contentType , String fileName , 提供getter,setter的方法;
      public void copy(File srcfile,File destFile) throws IOException{
     BufferedInputStream bis = null;
     BufferedOutputStream bos =null;
     try{
      bis =new BufferedInputStream(new FileInputStream(srcfile));
      bos =new BufferedOutputStream(new FileOutputStream(destFile));
      byte[] buf =new byte[8192];
      for(int count=-1;(count=bis.read(buf))!=-1){
      bos.write(b,0,count);
      bos.flush();
      }
    }catch(IOException ie){
     throw ie;
    }finally{
     if(bis!=null){
      bis.close();
     }
      if(bos!=null){
      bos.close();
     } 
      }
    同时也可以使用批量上传  
      ---------------------------
  在struts.xml
  public Boolean isallowtype(String type)
  {
   List<String>types= new ArrayList<String>();
   types.add("image/pjpeg");
   types.add(text/plain);
   types.add(application/msword);
   if(types.contains(type)){
   token.wu
   }
  }======================================
  1)页面要求;
   Form 表单  method="post"  enctype="multipart/form-data"
   要有file域:<input type="file" name="up"/>
  2) 在Action中:
   添加一个名与页面file域同名的file属性;
   添加一个以file域名开头,后面名为ContentType 的字符串属性,这个由struts的文件传拦截器赋问价类型值。
  添加一个以file域名开头,后面名为FileName 的字符串属性,这个有strusts2的文件上传蓝假期赋文件名的值。
3)Io流操作,把文件的上传写到指定的目录中。
4)批量文件上传: 在Action中添加一个List<File>类型的与页面file域同名的属性。
通过IO流循环操作,完成文件的读写。
====================================
  token 防止重复提交表单
   1) 在页面的表单中添加<s:token/>
   2) 在使用token 的Action配置中添加token 或tokensession拦截器
================================================================
4.FreeMarker页面模板技术: 模板+数据模型=输出
  1)FreeMarker 模板: 一个普通文本文件,其中使用了一些FreeMarker的特别标记。
  2)数据模型: 存放了数据的数据结构,通常是一个Hash存储结构(如:hashMap)
  3)FreeMarker 框架负责间隔一个数据模型中的书籍合并到模板中,从而生成输出
  2.配置是使用环境,下载并把freemarker-x.x.jar 放置到应用程序中的classpath下。
  3.java应用
  1)创建数据模型:Map<String,Object> root=.....
  2)创建模板:xxx.ftl
  3)合并
-----------------------------------------------------------
//创建个configuation实例来出示FreeMarker的配置// 也可以在classpath下添加一个freemarker.properties
Configuarion config =new Configuration();
String basePath =Thread.currentThrad().getContextClassLoader().getResource("").getPath();
Config.setDirectoryForTemplateLoading(new file(basePath+"/templates"));
Temlate template =config.getTmplate("first.txt");
//输出控制台
template.process(getDateModel(), new OutputStreamWriter(System.out));
//输出到文件
BufferedWriter bw =new bufferedWriter( new FileWriter(new File(path+"/abc.txt")));
template.process(getDataMoedl(), bw);
bw.flush();
<#setting number_formate="#,###.00">
<#setting datetime_formate="yyyy年MM月dd日 HH:mm:ss">
${"<a href=/"#/">xxx</a>"?html}
${true?string("男","女")}
==================== Teachers Code=======================
  1. FreeMarker模板引擎的使用: 模板 + 数据模型 = 输出
  1) FreeMarker模板:一个普通文本文件,其中使用了一些FreeMarker的特别标记。
  2) 数据模型:存放了数据的数据结构,通常是一个Hash存储结构(如:HashMap)
  3) FreeMarker框架负责将一个数据模型中的数据合并到模板中,从而生成输出
2. 配置使用环境: 下载并把freemarker-2.x.x.jar放置到应用程序的classpath下。
3. Java应用:
   1) 创建数据模型: Map<String, Object> root = ....
   2) 创建模板: xxx.ftl
   3) 合并:
//创建一个Configuration实例来初始freeMarker的配置 //在classpath下添加一个名为freemarker.properties
Configuration cfg = new Configuration();
//设置模板文件的存放目录
cfg.setDirectoryForTemplateLoading(new File("templates"));
//加载指定的模板
Template t = cfg.getTemplate("first.ftl");
//处理合并
t.process(root, new OutputStreamWriter(System.out));
4. web应用中直接使用FreeMarker: 在Servlet的请求处理方法中:
//创建一个Configuration实例来初始freeMarker的配置
Configuration cfg = new Configuration();
//设置模板文件的存放目录
cfg.setServletContextForTemplateLoading(getServletContext(),"/templates");
//加载指定的模板
Template t = cfg.getTemplate("first.ftl", "UTF-8");
//处理合并
t.process(getDataModel(), response.getWriter());
★5. FTL(FreeMarker模板语言)语法:
1) 模板文件由4部分组成:
   a) 文本:直接输出的部分
   b) 注释:<#--  注释内容 -->  不会输出
   c) 插值(interpolation):${表达式} 或 #{表达式} ,将使用数据模型中的数据替换后再输出
   d) FTL指令:
                内置(预定义)指令:<#指令名 属性名="值">主体</#指令名>  如:<#if user??>${user.loginname}</#if>
                自定义指令: <@指令名 属性名="值">主体</@指令名>
2) 插值规则
a) 表达式放置在插值语法${}之中,用于输出表达式的值。
b) 表达式的值的类型可以是:字符串、 数字、布尔、日期时间、序列、Hash结构
c) 表达式支持Java中的所有运算符:
    算术运算符:+、-、*、/、%
    比较运算符:==(eq)、!=(ne)、>(gt)、>=(gte)、<(lt)、<=(lte)
    逻辑运算符:&&(and)、||(or)、!(not)
    三目运算符:? :
d) 内置函数:
    Ⅰ) 使用方式:表达式?函数名[(实参)]
    Ⅱ) 字符串的内置函数: substring(from[, to])、html、length、trim、url
             示例:<#setting url_escaping_charset="UTF-8"> 、exp?url[("UTF-8")]
    Ⅲ) 数字的内置函数:c、string[(数字模式串)]、
    Ⅳ) 布尔的内置函数:string[("男", "女")]
    Ⅴ) 内置的日期时间函数:string[("格式模式串")]、datetime、date、time
e) 序列:
         在FTL中定义的序列:由方括号包括,各元素用英文逗号分隔如:<#assign seq=["winter", "spring", "summer", "autumn"]>
         也可以用数字范围(递增、反递增)定义数字序列: <#assign nums=101..105>  或 <#assign nums=105..101>
         在数据模型中:可以是List对象、Set对象
         序列的内置函数:size、sort[("指定字段作排序依据")]
f) Hash结构:
         在FTL文件中直接定义时:由大括号包括,由逗号分隔键/值列表,键和值之间用冒号分隔。键必须是字符串。<#assign scores={"语文":78, "数学":89, "英语":87}>${scores.语文}
         在数据模型中:可以是Map对象
    Hash的内置函数:size、keys、values
3) FreeMarker中的空值判断
  a) 判断是否为空值:用??(?if_exists,?exists) 如果不为空返回true,否则返回false。
  b) 通过Configuration设置:Configuration cfg = new Configuration(); cfg.setClassicCompatible(true);
  c) 属性配置方式:在freemarker.properties文件中classic_compatible=true
  d) 通过ftl设置:在ftl文件头前加入<#setting classic_compatible=true>
  e) 在FTL中遍历序列、Hash结构时:<#if userList??><#list userList as user>....</#list></#if>
4) 常用内置指令:
  a) if/else
<#if condition>
  ...
<#elseif condition2>
  ...
<#elseif condition3>
  ...
...
<#else>
  ...
</#if>
  b) switch/case
<#switch value>
  <#case refValue1>
    ...
    <#break>
  <#case refValue2>
    ...
    <#break>
  ...
  <#case refValueN>
    ...
    <#break>
  <#default>
    ...
</#switch>
  c) list
<#list sequence as item>  <#-- item_index 当前迭代项的索引 -->
    ...
</#list>
  d) include 包含指定文件。类似于JSP中的include标准动作
<#include "文件路径" [encoding="charset"] [parse=true|false]>
  e) import 导入指定模板中的所有变量。
<#import "文件路径"  as hash>
  f) noparse 不处理该指令中包含的内容
<#noparse>
  …
</#noparse>
  g) assign: 为当前模板页面创建或替换一个顶层变量
<#assign name=value>
<#assign name1=value1 name2=value2 ... nameN=valueN>
  h) global:创建或替换一个命名空间全局范围作用域的顶层变量
  i) local:创建或替换一个局部作用域的顶层变量
  j)setting 设置FreeMarker运行时的属性.语法:<#setting name=value>
name常用的有:
locale:该模板所使用的语言环境选项。en,zh,zh_CN,zh_TW
number_format:数字格式化输出的格式
boolean_format:布尔值格式化输出的格式
date_format,time_format,datetime_format:日期时间格式化输出的格式
time_zone:格式化输出日期时间所使用的时区。
url_escaping_charset:URL编码的字符集。
  k) 自定义指令:<#macro 指令名 属性名...>...</#macro>
6. Web应用中整合FreeMarker:FreeMarker提供了FreemarkerServlet类来整合模板到Web应用中:
  1) 这个Servlet在数据模型中放置了三个Hash结构:Request, Session, Application,分别用来访问请求,会话,应用上下文中的属性。
             访问作用域中的属性时,没有指定Hash结构名,它会依次按Request,Session,Application顺序搜索。
  2) 它还提供了一个名为RequestParameters的Hash结构,用来访问HTTP请求中的参数数据。
7. Struts2中整合FreeMarker: Struts2默认就是使用FreeMarker来产生所有UI标签的HTML标记。
  1) 对提供了FreeMarkerResult来支持FTL页面。
     <result type="freemarker">/templates/info.ftl</result>
  2) FreeMarker针对Struts2提供了以下内置Hash结构:
     a) stack: 代表ValueStack本身,可通过如下方式来访问其中的变量"${stack.findString('ognl expr')}"
     b) action: 代表刚刚执行过的Action实例
     c) response: 代表HpptServletResponse实例
     d) res: 代表HpptServletResponse实例
     e) request: 代表HpptServletRequest实例
     f) req: 代表HpptServletRequest实例
     g) session: 代表HpptSession实例
     h) application: 代表ServletContext实例
     i) base: 代表用户请求的上下文路径.
8. 使用FreeMarker完成页面的静态化:
-----------------------------------------------------------------------------------------------------------------
  =============================================================================
5. JFreeChar技术 画图技术
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/kekeyifan/archive/2009/12/07 /4958716.aspx

原创粉丝点击