Struct总结:
Struts2总结
1. Action
a) namespace(掌握)
b) path(掌握)
c) DMI(掌握)
d) wildcard(掌握)
e) 接收参数(掌握前两种)
f) 访问request等(掌握Map IOC方式)
g) 简单数据验证(掌握addFieldError和<s:fieldError)
1. Result
a) 结果类型(掌握四种,重点两种)
b) 全局结果(掌握)
c) 动态结果(了解)
1. OGNL表达式(精通)
a) # % $
2. Struts标签
a) 掌握常用的
3. 声明式异常处理(了解)
4. I18N(了解)
5. CRUD的过程(最重要是设计与规划)(精通)
6. Interceptor的原理(掌握)
7. 类型转换(掌握默认,了解自定义)
Struct 1 Action
每次请求时,都只会用原先那个Action类生成的实例
Struct 2 Action
每次请求时,都会重新生成Action类的实例
实际上主流的开发有两个方向:
1. 轻量级、开源框架:以Spring+Hibernate为基础的。
2. Sun公司提供的Java EE规范:以EJB 3+JPA为基础的。
Struts 2是由WebWork发展而来的,WebWork是以XWork为基础的。
所以Struts 2也是以XWork为基础的。
安装struts 2
(2) 修改web.xml文件,增加Struts2支持。 DEMO
需要在web.xml文件中增加一个核心Filter。以前是FilterDispatcher,
现在改为使用StrutsPrepareAndExecuteFilter。
但实际上,2.1.6中依然不能使用StrutsPrepareAndExecuteFilter,因为它在处理中文问题时有乱码。
(3) 在WEB-INF/classes目录增加一个struts.xml文件,它负责管理Struts 2的配置。
struts.xml是开发过程中一个非常重要的配置文件。
1. 注册(插入一条记录) 2.登录(查看指定记录是否存在) 3. 查看/修改用户。(查询全部记录)
struts2-core-2.1.8.1.jar
xwork-core-2.1.6.jar
freemarker-2.3.15.jar
ognl-2.7.3.jar
commons-fileupload-1.2.1.jar
commons-logging-1.0.4.jar
与传统MVC开发的差别:
1. 传统的MVC开发,每次用户请求,通常会定义一个Servlet进行处理。
用了Struts 2之后,定义一个Action进行处理。
2. 传统的MVC开发,Servlet开发完成之后,需要在web.xml文件中配置Servlet
用了Struts 2之后,需要在struts.xml文件中配置Action
Struts 2的Action的要求:
1. 实现Action接口,或者继承ActionSupport基类[X1]
2. 为所有的请求参数定义Field,并提供getter和setter方法。
以后就可通过该Field来获取请求参数,无需搞request.getParameter[X2] !!!!
3. 定义一个处理用户请求的方法。该方法的签名是:
public String xxx() execute
{
}
在Action类中,无需通过getParameter来获取请求参数。
也不需要调用request.setAttribute将需要显示的数据传到JSP页面。
<!-- 配置列出Web应用根路径下所有文件的Action -->
<action name="">
<result>.</result>
虽然action的命名空间非常灵活,但如果name用带.或-的值,则可能引发其他异常
原则:约定优于配置
常量配置:
它就是一些简单的key-value对!
通常就是一个常量名、一个常量值。
为struts 2配置常量有3种方式:
↗ 在web.xml文件中为PrepareAndExecuteFilter指定初始化参数。
每个<init-param.../>元素配置一个常量。
↗ 增加一个struts.properties文件(放在WEB-INF/classes)。
struts.i18n.encoding=UTF-8 指定默认编码集
struts.action.extension= 扩展名 默认是action
structs.i18n.reload = 是否每次HTTP请求到达时,系统自动加载资源文件
structs.configuratin.xml.reload 当XML文件改变后,系统是否自动重新加载此文件。
structs. i18n.resources 所需要的国际第资源文件,如果有多个资源文件则用,分开
struts.devMode=true 是否使用开发模式。如果为true则可以在应用出错时显示更多、更友好的出错提示。
通常开发阶段设为true,开发阶段设为false
↗ 在struts.xml文件中使用<constant.../>元素进行配置。
<constant name="struts.i18n.encoding" value="GBK"/>
<constant name="struts.action.extension" value="html"/>
包含其他配置文件:
默认情况下,Struct2会自动加载类加载路径下的structs.xml default.xml stuts-plugin.xml三类文件[X1]
通常,structs2框架按如下顺序加载Struct2常量:
Structs-default.xml (保存在struts2-core-2.1.2文件中)
Structs-plugin.xml (保存在struts2-Xxxx-2.1.2等struct2插件JAR文件中)
Structs.xml
Structs.properties (stucts2默认的配置文件)
Web.xml
<include file=”struts-part1.xml > DEMO
包,抽象包不能用action (包和命名空间)(“” 默认命名空间可以处理任何命名空间的请求)
Struct2 还可以显示指定根命名空间,通过设置某个包的namespace=”/”来指定根命名空间。
如果请求为/barspace/bar.action,系统首先查找/barspace空间下的bar.action请求,如果在此命名空间里找不到,则到默认的命名空间里找,都找不到的就出错。
如果请求为/login.action ,系统会在根命名空间下(“/”)查找名为login的Action,找到了就处理此请求,否则到默认的命名空间里找,都长不到的就出错。
命名空间只有一个级别。如果请求的URL是/bookservice/search/get.action,系统将先在/bookservice/search的命名空间下查找名为get的Action,没有的就到默认的空间找,而不会到//bookservice的命名空间下查找。。。。
Struts 2不允许为单独的Action配置命名空间,只能为一个package整体配置命名空间。
Struts 2的核心JAR包里包含了一个struts-default.xml文件,
该文件中定义了一个名为struts-default的抽象包。
设置默认的Action
为了让Struct2的Action可以接管用户请求,我们可以配置 name=”*” 的Action,
除此之外,Struct2还支持配置默认Action ,当用户请求找不到对应的Action时,系统默认的Action即将处理用户请求
<default-action-ref name=”simpleCddfsdf”>
<action name="simpleCddfsdf" class="lee.simpleCddfsdf" >
<result ... />
</action>
实现Action:
Struct2 2 的Action优势:
低侵入式设计。代码的保值性很好;
与Servlet API分离,便于测试
Web应用中通常访问的API是:HttpServletRequest 、HttpSession 、ServletContext(代表application对象)
既可以彻底与Servlet Api分离,从而允许此Action脱离Web容器运行,也就可以脱离Web容器来测试Action,又允许用简单的方式操作各范围内属性
两种方式:
1 借助ActionContext实现伪访问 DEMO jsp
2 借助ServletActionContext实现真实访问
借助ServletContextAware:实现此接口可以直接访问ServletContext实例 DEMO
借助ServletRequestAware:直接访问HttpRequest实例
DMI 动态方法调用: ! 好像用处不大 跟method差不多 在浏览器URL里可以用..!..
使用动态方法调用前必须设置 struts.enable.DynamicMethodInvocation = true
指定Method属性及使用通配符:
如果省略了method属性,则默认采用execute方法处理请求
<action name="*Action" class="lee.LoginRegistAction" method="{1}">
<action name="*-*" class="action.{1}" method="{2}">
<!—通用的Action -->
<action name=”*”> <result>/{1}.jsp</result> </action>
<action name=””>
<result>.</result>
</action>
<!—浏览器 列出当前目录-->
配置处理结果:
Action的处理方法的签名必须为如下格式:
public String xxx()
{
}
局部结果:将<result.../>元素作为<action.../>元素的子元素定义。
全局结果:将<result.../>元素作为<global-results..../>元素的子元素定义。
<gloabl-results>
<result name="success">/WEB-INF/jsp/{1}Succ.jsp</result>
</gloabl-results>
Result默认的name属性名是sussecc,可以省略的
局部结果只对当前<action.../>配置起作用。
全局结果则对所有的<action.../>配置都起作用。
当局部结果和全局结果冲突时,局部结果生效!!!!
配置结果的完整语法为:
<result name="Action处理方法所返回的字符串" type="视图类型">
<!-- location参数指定视图资源的位置 -->
<param name="locatioin">/视图资源的位置</param>
<param .../>
</result>
-name属性指定Action处理方法所返回的字符串,该属性的默认值是"success"
-type指定将要使用的视图资源的类型,该属性的默认值是"dispatcher"
如果配置<result.../>时,只需要一个<param.../>子元素,
而且该<param.../>元素所配置的参数名为location,那么可以简写为如下形式:
<result name="Action处理方法所返回的字符串" type="视图类型">/视图资源的位置</result>
Struts 2支持的结果类型:
chain :使用两个Action作为链来处理。一个用户请求,需要先后经过两个或更多的Action处理。
就要用到这种chain处理结果。
dispatcher:默认的处理结果。(转发)
freemarker
httpheader
redirect:重定向另一个URL。 Jsp (重定向[X1] )
<result name="success" type="redirect">
<param name="location">foo.jsp</param>
<param name="parse">false</param>
</result>
<!—parse 是否允许在location参数中使用表达式
-->
stream:做文件下载的。
velocity
xslt
plainText :使用普通文本作为视图。 (主要用于显示实际视图资源的源代码[X1] )
动态结果: *
“零配置” the Convention Plugin is bundled with Struts since 2.1 and replaces the Codebehind Plugin and Zero Config plugins. It provides the following features: (代替了零配置插件)
------------------------------------
用Annotation来代替了XML配置。
Rails框架,“CoC” Convention Over Configuration
使用XML配置的优势是:
管理信息从Java源代码中分离出来。因此降低了耦合,从提高了可扩展性。
使用XML配置的劣势是:
a. 重写编写XML工作量大,开发效率低。
b. XML文件越来越多,维护XML文档也变得很难。
Rails说:有一个约定。
Convention Over Configuration 约定优于配置。
Struts 2的工具插件:
struts2-config-browser-plugin-2.1.8.1.jar
configBrowser插件的用法:
1. 将插件的JAR包复制到Web应用WEB-INF/lib下。
2. 访问主机名:端口/项目名/config-browser/index
这个插件的作用是帮助你调试的。
Convention插件。 (约定插件,不叫零配置)
<constant name="struts.convention.result.path" value="/WEB-INF/jsp/"/> //XML文件
@ResultPath("/WEB-INF/jsps") //放在Actin类前面
<!-- 系统自动搜索的Action类的后缀 -->
<constant name="struts.convention.action.suffix" value="Action"/>
<!-- 系统自动搜索的Action类所在的子包 -->
<constant name="struts.convention.action.packages" value="actions"/>
<!-- 指定是否自动搜索所有匹配的action -->
<constant name="struts.convention.action.mapAllMatches" value="true"/>
1. Action类必须满足一定的规则。
2. Action类通常应该放在actions子包下。
这样Convention插件会自动搜索所有匹配的Action,并将其进行“配置”
将Action的类名的后缀去掉,并将原来的“camerl”写法,改为中划线写法,
作为<action.../>的name
在struts-defult.xml里已经配置了开启异常映射功能
<interceptors> <interceptor name=”exception” class=” ”
局部异常映射:<exception-mappting>作为<action>子元素配置[X2]
<action><exception-mappting exception=”java.sql.SQLException” result=”sql” /><action>
全局异常映射:<exception-mappting>作为<global-exception-mapping>子元素配置
<global-exception-mapping><exception-mappting exception=”java.sql.SQLException” result=”sql” /><global-exception-mapping>
输出异常信息: (可直接放在JSP页面中) 要先导入标签库<%@ taglib prefix=”s” uri=”/struts-tags” %>
<s:property value=”exception”> 输出异常对象本身
<s:property value=”exceptionStack”> 输出异常堆栈信息
<s:property value=”exception.message”>
<s:property value=”exceptionStack”> 使用Structs2标签输出异常跟踪栈信息
全局异常映射的result属性值通常不要使用局部结果,局部映射的result属性值既可以使用全局结果集,也可以使用局部结果集
Struts2国际化:
Sruts.custom.i18n.resource = messageResource 使用native2ascii工具[X1]
访问国际化信息: messageResouce.properties _zh_CN.properties _en_US.properties
JSP页面,<s:text name=”” /> name指定了国际化资源文件中的key DEMO
Action类,使用ActionSupport类的getText 方法 name属性 name指定了国际化资源文件中的key
在此表单元素的Label里输出国际化信息,可以为此表单标签指定一个key属性,此key指定了国际化资源文件中的key <s:textfield name="username" key="user"/>
输出带占位符的国际化消息: DEMO
JSP页面,<s:text ../>标签中 使用多个<s:param ../> 依此类推的
Action类,getText 来自于ActionSuport
加载资源文件的方式:
1. 全局资源 需要显式加载 利用这个常量Sruts.custom.i18n.resource
2. 包范围的国际化资源(资源文件放在此包;命名PackageName_language_country.properties)
3. Action范围内国际化资源(资源文件与Action类放在一起;命名ActionName_language_country.properties)
4. 页面范围(局部)国际化资源 (临时[X2] ) <s:i18n >作为父标签,通过这个标签显式加载 DEMO
页面上使用<s:text>标签来输出国际化消息,
当此标签在资源文件找不到对应的key,它将直接输出默认消息,如果默认消息也没有,它将输出key
Struts标签库:
OGNL表达式
Stack Context中有两个对象,foo和bar,其中foo是根。
#foo.abc -输出foo.getAbc()
#bar.abc -输出bar.getAbc()
OGNL规定,如果省略对象,那么默认就是访问根的属性。
abc - 输出foo.getAbc()
如果Stack Context有2个根:foo,bar(根之间有顺序)
#foo.abc -输出foo.getAbc()
#bar.abc -输出bar.getAbc()
abc - 优先输出foo.getAbc(),如果foo对象没有getAbc(),尝试输出bar.getAbc()
Struts 2的OGNL求值是基于Stack Context
在Struts 2中,Stack Context的第一个根对象是Value Stack,Value Stack里又包含大量对象。
如果需要访问ValueStack里的属性,只需通过以下方式即可:
${bar}
Struts还提供了一些命名对象,这些命名对象与根对象无关,它们只是存在于StackContext中。所以访问这些对象时需要使用#前缀来指明:
Parameters #Parameters["foo"] 或 #Parameters.foo
Request #request["ddd"] 或 #request.ddd
Session
Application
Attr 此对象将依次搜索如下对象:PageContext HttpServlet HttpSession ServletyContext中的属性
Debuger调试标签 <s:debug />
OGNL中的集合操作
创建List集合 {e2 , e2 , ...}
创建Map类型集合 #{key1:value1 , key2:value2 , ....}
取得子集时有如下3个操作符:
? 取出所有符合选择逻辑的元素 person.relatives.{ ? #this.gender == ‘male’ }
^ 取出符合选择逻辑的第一个元素
$ 取出符合选择逻辑的最后一个元素
对于集合类型,OGNL表达式可以使用in和not in两个元素符号。其中,in表达式用来判断某个元素是否在指定的集合对象中;not in判断某个元素是否不在指定的集合对象中,
%”符号的用途是在标志的属性为字符串类型时,计算OGNL表达式的值。例如在Ognl.jsp中加入以下代码:
<hr />
<h3>%的用途</h3>
<p><s:url value="#foobar['foo1']" /></p>
<p><s:url value="%{#foobar['foo1']}" /></p>
清单6 演示%用途的代码片段
刷新页面,结果如下所示:
清单7 示例运行结果2
“$”有两个主要的用途
用于在国际化资源文件中,引用OGNL表达式,例子请参考《在Struts 2.0中国际化(i18n)您的应用程序》
在Struts 2配置文件中,引用OGNL表达式,如
<action name="AddPhoto" class="addPhoto">
<interceptor-ref name="fileUploadStack" />
<result type="redirect">ListPhotos.action?albumId=${albumId}</result>
</action>
清单8 演示$用途的代码片段
If elseif else append generator iterator merge sort subset
Append元素与merge元素拼合的方式不同:
Append:a.1 a.2 a.3 b.1 b.2 b.3 c.1 c.2
Merge: a.1 b.1 c.1 a.2 b.2 c.2 a.3 b.3 c.3
数据标签 DEMO
Action 在JSP页面直接调用Action
Date 格式化输出一个日期(nice指定是否输出其时差)
Debug
I18n 指定国际化资源文件的basename
Include 用于在JSP页面中包含其他的JSP或servlet资源
Param 设置一个参数,通常是用做bean标签、url标签的子标签
Push 将某个值放入ValueStack的栈顶
Set 设置一个新变量,并可以将新变量放入指定的范围:applicatin,session
Text 输出国际化消息
url 生成一个url地址
property 输出某个值,包括输出ValueStack、Stack Context、Action Context中的值
UI标签
不用尝试自己加载模板,开发者只要指定主题就够了,主题会负责去加载模板[X2]
需要掌握的知识点:
1. 为struts2标签指定theme的方式(7种)
2. Struts2常用的主题及其特性 simple(不会有额外的布局功能) css_xhtml xhtml(默认的,非常方便,两列布局,输出检验错误提示,出处客户端校验提示)
主题是模板的组织形式,模板被包装在主题里面,;
设置主题的方法:
1. 通过设定特定UI标签上的theme属性来指定主题;
2. 设定特定UI标签外围的Form标签的theme属性
3. 取得Page会话范围的内以theme为名称的属性来确定主题;
4. 取得Request会话范围的内以theme为名称的属性来确定主题;
5. 取得Session会话范围的内以theme为名称的属性来确定主题;
6. 取得application会话范围的内以theme为名称的属性来确定主题;
7. 通过设置名为struts.ui.theme的常量(默认值是xhtml)来确定默认主题,此常量可以在struts.properties文件或者struts.xml文件确定
Struts可以选择自己的模板技术,通过修改struts.ui.templateSuffix常量的值就可以改变struts2默认的模板技术。
Ftl:(缺省) 基于Freemaker的模板技术;
Vm:基于Velocity的模板技术;
Jsp:基于JSP的模板技术
<action name=””>
<result>.</result>
</action>
<!—浏览器 列出当前目录-->
表单标签:
分两类:form标签本身;单个表单元素的标签
Form标签的行为不同于表单元素标签。Struts2的表单元素标签都包含了非常多的属性,但有很多属性
完全是通用的。
所有表单标签处理类都继承了UIBean类,UIBean包含了一些通用属性,这些通用属性分为了3类:
模板相关属性
Javascript相关属性
通用属性
doubleselect doubleselect02 [W1] 级联
Head标签
生成一个隐藏域,生成的参数是随机的。
防止重复提交:
1.进入表单页面时,系统会生成一个随机字符串,并将其放入session,并放入页面中的一个隐藏域
2.提交请求时,系统会将sessin中的随机参数与隐藏域的随机参数进行对比,如果相同,即判断为有效请求,系统要清空session中的..
3.如果刷新,隐藏域对应的请求参数没变,但session中随机字符串已经没了,此时隐藏域的与session的不pi配,判断为无效请求。
非表单标签:
Actionerror actionmessgae component fielderror
内建类型转换器:
boolean和Boolean:完成字符串与布尔值之间的转换
char和Character
int和Integer
long和Long
float和Float
double和Double
Date:完成字符串与日期类型之间的转换日期格式使用用户请求所在Locale的SHORT格式
数组:在默认情况下,数组元素是字符串,如果用户提供了自定义类型转换器,也可以是其他复合类型的数组。[W1]
集合:在默认情况下,假定集合元素类型为String,并创建一个新的ArrayList封闭所有的字符串
对于数组的类型转换将按照数组元素的类型来单独转换每个元素,但对于其他的类型转换,如果转转换无法完成,系统将出现类型转换
基于OGNL的类型转换:
指定集合对象的类型 DEMO
ActinName-converesion.properties文件放到Action所在的目录下
通过局部类型转换文件指定如下 key-value对
Element_users=lee.user (List类型的做法[W1] )
如果是Map类型的,则需要同时指定Map类型的key类型和value类型:
Key_<MapPropName>=<keyType>
Element_<MapPropName>=<valueType>
自定义类型转换: DEMO
1) 实现TypeConverter接口,意味着要完成类型转换的全部工作
2) 实现TypeConverter接口比较复杂,可继承DefultTypeConver [W1]
3) 更简单的是继承StrutsTypeConverter 上课实例DEMO UserVoConverter.java
重写convertFromString( string到自定义类型 疯狂JAVA实例DEMO
重写convertToString( 自定义类型到string
注册类型转换器:
全局:在类加载路径下指定xwork-conversion.properties DEMO
自定义类型=转换器类
局部:指定对特定的Action的特定的属性使用指定的转换器 DEMO
局部类型的转换的文件放到Action相同的路径下,文件名为AcitonName-conversion.properties
Action属性名=转换器类
#指定user属性需要使用lee.UserConverter类来完成类型转换
user=lee.UserConverter
使用JDK1.5的注释来注册类型转换器。
全局类型转换器是根据目标类来起作用的--只有你的Aciton类里有指定类型的属性,
那么自定义类型转换器就会起作用。
局部类型转换器是根据指定Action的指定属性来起作用的,--此类型转换器只对特定Acitn类的特定属性起作用
struts2的ActionSupport基类负责收集类型转换错误、输入检验错误,并将它们封闭成FieldError对象,添加到ActionContext中。
转换失败时,系统会跳到input Result ,因此需要配置name="input"的result;
struts全局使用key为Xwork.default.invalid.fieldvalue的消息作为提示信息。
Xwork.default.invalid.fieldvalue={0}字段类型转换失败
需要对特定字段指定特别的提示信息,通过学习Action的局部资源文件来实现,
invalid.fieldvalue.<propName>=<tipMsg>
在页面上显示错误提示:
1.使用xhtml主题的struts 2标签
2.使用<s:fieldError />来输出
错误提示的国际化
全局 在全局的国际化文件里添加key为Xwork.default.invalid.fieldvalue={0}字段类型转换失败
局部 在局部的国际化文件里添加key为invalid.fieldvalue.<propName>=<tipMsg>
处理集合类型的错误处理:
struts2提供了一个名为conversionError的拦载器,这个拦载器被注册在默认的拦载器栈中。此拦载器负责将对应错误封闭成表单域错误(FieldError)
输入检验: DEMO
服务端检验:防止非法数据进入程序,导致程序异常、底层数据库异常。服务器端校验是保证程序有效运行及数据完整的手段
1.编写校验规则文件
a) 校验规则文件与Aciton的类文件放在同一路径
b) 校验规则文件名 就是 Aciton的类名-validatin.xml
2.页面上使用 表单标签,会输出验证错误 。或使用<s:fielderror />也可以输出
3.错误提示国际化输出 <s:message key=/>
客户端检验:拒绝误操作输入提交到服务器处理,降低服务器负担,异常 DEMO
1.应该用<s:form ../>生成表单
2.为<s:form ../>增加validate="true"
3.[W3] 如果希望国际化,应该把错误信息放到全局国际化资源中。并用${getText("key")}的方式来加载国际化消息
如果希望类型转换还有输入检验可以正常工作,记住你的Action应该继承ActinSupport
转换失败时,系统会跳到input Result ,因此需要配置name="input"的result;