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技术 画图技术