Struts2权威指南笔记
1、mvc特点包括:
① 多个视图可以对应一个模型
② 模型返回的数据与显示逻辑分离
③ 应用层被分隔为三层,降低了各层之间的耦合,提供了应用的可扩展性
④ 控制层的概念也很有效,由于它把不通的模型和不同的视图组合在一起,完成不同的请求
⑤ Mvc更符合软件工程化管理的精神
2、Struts2框架的大致处理流程:
① 浏览器发送请求,如请求/mypage.action
② 核心控制器FilterDispatcher根据请求决定调用合适的Action
③ Webwork的拦截器链自动对请求应用通用功能,例如workflow、alidation或文件上传等功能
④ 回调Action的execute方法,该execute方法先获取用户请求参数,然后执行某种数据库操作,如查询、保存数据等。实际上,因为Action只是一个控制器,它会调用业务逻辑组件来处理用户请求
⑤ Action的execute方法处理结果信息将被输出到浏览器中
3、Struts2的配置文件,Struts2的配置文件有2份,配置Action的struts.xml和配置Struts全局属性的struts.properties文件
4、Struts2的控制器由两个部分组成:FilterDispatcher和业务控制器Action,实际上,Struts2应用中起作用的业务控制器不是用户定义的Action,而是系统能够生成的Action代理,但该Action代理以用户定义的Action为目标
5、Action类特点
① Action类完全是一个pojo,因此具有很好的代码复用性
② Action类无需与servlet API耦合,因此进行单元测试非常简单
③ Action类的execute方法仅返回一个字符串作为处理结果,该处理结果可映射到任何的视图,甚至是另一个Action
6、配置过程
① 引入jar,例如struts2-core-2.3.15.1.jar,xwork-core-2.3.15.1.jar,ognl-3.0.6.jar
② web.xml配置
<filter>
<filter-name>struts2</filter-name>
<filter-class>
<!--org.apache.struts2.dispatcher.FilterDispatcher不推荐使用-->
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
这里要注意FilterDispatcher在2.1.3之后就不推荐使用了,应该使用
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter替代
③ 1234
7、获取session,Struts2提供了ActionContext类,该类提供了getSession的方法,但是返回类型是map,不是HttpSession,由Struts2的系列拦截器负责该session与HttpSession之间的转换。ActionContext.getContext().getSession()
8、Action中的成员属性,并不一定用于封装用户的请求参数,也可能是封装了Action需要传入下一个页面显示的值。实际上,这些值将被封装在ValueStack对象中。Struts2将这些属性值全部封装在一个叫做struts.valueStack的请求属性中,可以使用
request.getAttribute(“truts.valueStack”)获取该对象
9、几个常用标签if/else/iterator/property
<s:iterator value="books" status="index">
<s:if test="#index.odd==true">
<tr style="#cccccc">
</s:if>
<s:else>
<tr>
</s:else>
<td>书名:</td>
<td><s:property /></td>
</tr>
</s:iterator>
10、使用native2asciic处理资源文件,Struts2默认加载WEB-INF/classes下的资源文件,如果资源文件在包路径下则要指定到包。
struts.custom.i18n.resources=messageResource
struts.custom.i18n.resources=com.test.messageResource
输出国际化信息:<s:text name=”messageKey”/>或者<s:property value=”%{getText(“messageKey”)}”/>
11、ActionSupport实现了Action接口和Validateable接口,提供了数据校验功能,validate方法会在执行系统的execute方法之前执行,如果fieldErrors中已经包含了数据校验错误,请求将被转发到input逻辑视图处。如果使用配置文件校验,则配置文件与Action位于同一个文件夹中,且命名格式为:ActionName-alidation.xml
12、Struts2框架由3个部分组成:核心控制器FilterDispatcher、业务控制器和业务逻辑组件。Struts2框架提供了核心控制器FilterDispatcher,而用户需要实现业务控制器和业务逻辑组件
Struts2用于处理用户请求的Action实例,并不是用户实现的业务控制器,而是Action代理-因为用户实现的业务控制器并没有与servlet api耦合,无法处理用户请求,而Struts2框架提供了系列拦截器,该系列拦截器负责将HttpServletRequest请求中的参数解析出来,传入到Action中,并回调Action的execute方法来处理用户请求,是典型的AOP处理方式。
13、业务控制器组件就是用户实现Action类的实例,需要配置Action3个部分定义:①Action处理的URL②Action对应的实现类③Action里包含的逻辑视图与物理资源之间的对应关系。
14、业务控制器不会对用户请求进行任何实际处理,用户请求最终由业务逻辑组件负责处理。业务控制器只是中间负责调度的调度器,这也是称Action为控制器的原因。当控制器需要获得业务逻辑组件实例时,通常并不会直接获取业务逻辑组件实例,而是通过工厂模式来获得业务逻辑组件的实例;或者利用其他IoC容器(如spring容器)来管理业务逻辑组件的实例
15、所有的MVC框架都需要web应用加载一个核心控制器,对于Struts2框架而言,需要加载FilterDispatcher,只要web应用负责加载FilterDispatcher,FilterDispatcher会加载应用的Struts2框架
16、Struts2核心配置文件struts.xml,默认放在WEB-INF/classes路径下,可用于模块化配置
<struts>
<!--通过include元素导入其他配置文件-->
<include file=”struts-part1.xml”>
...
</struts>
struts.xml中可以包含的元素:include/constant/bean/package
17、有效的Struts2属性
struts.configuration:该属性指定加载Struts2配置文件的配置文件管理器
struts.locale:指定web应用的默认local
struts.i18n.encoding:指定web应用的默认编码集
struts.objectFactory:指定Struts2默认的objectFactory bean,默认spring
struts.objectFactory.spring.autoWire:指定spring框架的自动装配模式,默认name
struts.objectFactory.spring.useClassCache:指定整合spring时是否缓存bean实例,默认true
struts.objectTypeDeterminer:指定Struts2的类型检测机制,通常支持tiger和notiger两个
struts.multipart.parser:指定处理文件上传请求框架,支持cos、pell和jakarta等属性值
struts.multipart.saveDir:指定上传文件的临时保存路径,默认javax.servlet.context.tempdir
struts.multipart.maxSize:指定上传文件最大字节数
struts.custom.properties:指定Struts2加载用户自定义的属性文件,可多个,用”,”分隔
struts.mapper.class:指定将http请求映射到指定Action的映射器,默认映射器根据请求前缀与Action的name属性完成映射
struts.action.extension:指定需要处理的请求后缀,默认action,多个用”,”分隔
struts.serve.static:设置是否通过jar文件提供静态内容服务,默认true
struts.serve.static.browserCache:设置浏览器是否缓存静态内容。开发时可设为false
struts.enable.DynamicMethodInvocation:设置是否支持动态方法调用,默认true
struts.enable.SlashesInActionNames:设置是否允许在Action名中使用斜线,默认false
struts.tag.altSyntax:指定是否允许在标签中使用表达式语法,通常为true
struts.devMode:设置应用是否使用开发模式,true时显示更多、更友好出错提示
struts.i18n.reload:设置是否每次http请求到达时,系统都重新加载资源文件。开发阶段可为true,发布时应设置为false
struts.ui.theme:指定视图标签默认的视图主题,默认xhtml
struts.ui.templateDir:指定视图主题所需模版文件的位置,默认template,即默认加载template下的模版文件
struts.ui.templateSuffix:指定模版文件后缀,默认值ftl,还允许ftl、vm或jsp
struts.configuration.xml.reload:设置当struts.xml文件改变后,系统是否自动重新加载该文件,默认false
Struts.velocity.configfile:该属性指定velocity框架所需的velocity.properties文件位置,默认velocity.properties
struts.velocity.contexts:指定velocity框架的context位置,多个可用”,”分隔
struts.velocity.toolboxlocation:该属性指定velocity框架的toolbox的位置
struts.url.http.port:该属性指定web应用所在的监听端口。只有当需要生成url时,采提供wen应用默认端口
struts.url.https.port:类似struts.url.http.port作用,只是加密服务端口
struts.url.includeParams:指定生成url时是否包含请求参数,可选none、get、all
struts.custom.i18n.resources:指定国际化资源文件名,多个以”,”分隔
struts.dispatcher.parametersWorkaround:对于某些javaEE服务器(weblogic/orion/oc4j),不支持HttpServletRequest调用getParameterMap()方法,此时设置该属性为true解决该问题,默认为false
struts.freemarker.manager.classname:指定使用FreeMarker管理器
struts.freemarker.wrapper.altMap:默认true,通常无需修改
struts.xslt.nocache:指定XSLT Result是否使用样式表缓存。开发阶段可设为true
struts.configuration.files:指定框架默认加载的配置文件,若需要加载多个用”,”分隔,该属性默认值为struts-default.xml,struts-plugin.xml,struts.xml
18、在struts.xml中定义bean时,有两个作用:①创建该bean的实例,将该实例作为Struts2框架的核心组件使用②bean包含的静态方法需要一个值注入
在第一种用法,因为bean实例往往是作为一个核心组件使用的,因此需要告诉Struts2容器该实例的作用-就是实现了那个接口(一般用于覆盖Struts2默认提供的方法)
第二种用法可以很方便地云逊不创建某个类的实例,却可以接收框架常量。通常要设置static=”true”
对于绝大部分应用而言,无需重新定义Struts2框架的核心组件,也就无需在struts.xml中定义bean。Bean元素有一下几个属性:①class②type③name④scope⑤static⑥optional
19、Struts2配置文件中的常量即可在struts.xml中,也可在struts.properties中配置,加载顺序:struts-default.xml->struts-plugin.xml->struts.xml->struts.properties->web.xml,后一个文件中的配置会覆盖前一个配置值。常量包含两个属性:name,value。若在wen.xml中配置,则可在filter中增加<init-param>,一般常量配置都在struts.xml中配置
20、Struts2框架核心组件就是Action、拦截器等,Struts2框架使用包来管理Action和拦截器等,每个包就是多个Action、多个拦截器引用的集合。Package元素用于定义包配置,有以下几个属性:①name,必填②extends,可选③namespace,可选④abstract,可选,抽象包中不能包含Action定义。注意Struts2的配置文件是从上到下处理的,所以父包要在子包之前定义。
21、当某个包指定了命名空间后,该包下所有的Action处理的url是命名空间+Action,例如:http://localhost:8080/app/namespace/action.action,还可以显示指定根命名空间,通过设置某个包的namespace=”/”来指定根命名空间
22、通常将Struts2的所有配置文件都放在web应用的WEB-INF/classes路径下,struts.xml文件包含了其他的配置文件,Struts2框架自动加载struts.xml文件时,从而完成加载所有配置信息
23、拦截器允许在Action处理之前,或者Action处理结束之后,插入开发者自定义的代码。拦截器可以完成:①进行权限控制②跟踪日志③跟踪系统的性能瓶颈
Struts2允许将多个拦截器组合在一起,形成一个拦截器栈,一个拦截器栈可以包含多个拦截器,拦截器栈对外也表现成一个拦截器。拦截器和拦截器栈都放在<interceptors>中定义
<interceptors>
<interceptor name="authority" class=""></interceptor>
<interceptor name="log" class=""></interceptor>
<interceptor-stack name="authandlog">
<interceptor-ref name="authority"></interceptor-ref>
<interceptor-ref name="log"></interceptor-ref>
</interceptor-stack>
</interceptors>
使用拦截器/拦截器栈
<action name="myAction" class="">
<result name="success">...</result>
<interceptor-ref name="authority"></interceptor-ref>
</action>
注意:package里面的元素顺序是有要求的,分别是
①result-types
②interceprots
③default-action-ref
④default-class-ref
⑤global-result
⑥global-exception-mappings
⑦action(即所有action要放到最后)
24、Struts2通常直接使用Action来封装http请求参数,因此,Action类里还应该包含与请求参数对应的属性,并且为该属性提供对应的setter和getter方法,重要的不是属性而是get/set方法,可在页面使用Struts2标签输出<s:property value=”username”>,系统不会严格区分Action里哪个属性是用于封装请求参数的属性,哪个属性是封装处理结果的属性。
25、Struts2框架提供了ActionContext、ServletContextAware、ServletRequestAware、ServletResponseAware、ServletActionContext类用于访问servlet api
26、必须指出,虽然可以在Action类中获取HttpservletResponse,但如果希望通过HttpServletResponse来生成服务器响应是不可能的,因为Action只是控制器,机如果在Action中写response.getWriter().println(“Hello World”);上面代码在标准servlet中会生成对客户端的输出,但在Struts2的Action中没有任何意义。即不要尝试直接在Action中生成对客户端的输出。
27、Action的name对应url中的前半部分,如果不指定class,则使用系统默认的actionSupport类处理
28、动态方法调用是指表单元素的action并不是直接等于某个Action的名字,而是以如下形式来指定Form的action属性
<!--action属性为actionName!methodName的形式-->
action=”ActionName!methodName.action”
对于使用动态方法调用的方法,该方法声明与系统默认的execute方法的声明只有方法名不同,其他的如方法参数、返回值类型都应该绝对相同。动态方法调用通过设置struts.enable.DynamicMethodInvocation常量完成
29、通过指定method属性,可以将一个Action类定义成多个逻辑Action,Action类的每个处理方法被映射成一个逻辑Action。
30、action定义中的通配符
<action name=”*Action” class=”” method=”{1}”>
Method属性使用了一个表达式{1},该表达式的值就是name属性值中的第一个*的值
<action name=”*Action” class=”com.test.{1}Action”>
表达式也可以出现在class属性中,即Struts2允许将一系列的Action配置成一个<action../>元素
<action name=”*_*” method=”{2}” class=”com.test.{1}Action”>
Struts2允许在class属性和method属性中同时使用表达式
<action name=”*”>
<retult>/{1}.jsp</result>
</action>
Struts2还可以在<result .../>子元素中使用表达式
31、除非请求的url与Action的name属性绝对相同,否则将按先后顺序来决定由那个Action来处理用户请求,因此,应将名为*的Action配置在最后,否则Struts2将使用该Action来处理所有希望使用模式匹配的请求。
32、对于只是简单的超链接的请求,可以通过定义name为*的Action(该Action应该放在最后定义)实现。除此之外,Struts2还允许在容器中定义一个默认的Action,当用户请求的URL在容器中找不到对应的Action时,系统将使用默认的Action来处理用户请求。
配置默认Action通过<default-action-ref.../>元素完成
33、如果配置<result .../>元素时没有指定location参数,系统将会把<result ...>...</result>中间的字符串当成实际视图资源;如果没有指定name属性,则name属性采用默认值:success;如果没有指定type属性,则采用Struts2的默认结果类型(dispatcher)
34、Struts2支持的结果类型在struts-default.xml中定义,常用的结果类型有:dispatcher、redirect、redirect-action、chain、xslt、velocity、freemarker、stream、plaintext等,结果类型要实现com.opensymphony.xwork.Result
35、设置结果类型为plaintext时,可以配置参数”charSet”
设置为redirect时重定向都新的页面,会丢失所有的请求参数、属性和处理结果
设置为redirect-action时,可以配置参数”actionName”,”namespace”
36、使用请求参数决定结果类型,可以使用完全的ognl表达式:${属性名.属性名.属性名}
<action name=”” class=””>
<result name=”input”>/input.jsp</result>
<result type=”redirect”>/edit.action?name=${current.name}</result>
</action>
37、全局结果对包内所有action都有效,当action中含有匹配的结果时,将覆盖全局结果
38、使用模型驱动的action多实现一个ModelDriven的接口,实现该接口并要求实现getModel()方法—该方法用于关联Action和Model之间的关系
39、Struts2的异常处理机制是通过在struts.xml文件中配置<exception-mapping.../>元素完成的,配置该元素时,需要指定两个属性:exception,result
局部异常映射:将<exception-mapping.../>元素作为<action.../>元素的子元素配置
全局异常映射:将<exception-mapping.../>元素作为<global-exception-mappings>元素的子元素
如果局部异常映射和全局异常映射配置了同一个异常类型,在该Action内,局部异常会覆盖全局异常映射
当定义异常映射时,通常:全局异常映射的result属性值通常不要使用局部结果,局部异常映射的result属性值既可以使用全局结果,也可以使用局部结果
输出异常信息:
<s:property value=”exception”/>输出异常对象本身
<s:property value=”exception.message”/>
<s:property value=”exceptionStack”/>输出异常堆栈信息
40、Struts提供了非常强大的类型转换机制,Struts2的类型转换是基于OGNL表达式的,只要我们把html输入项(表单元素和其他GET/POST的参数)命名为合法的OGNL表达式,就可以充分利用Struts2的类型转换机制。
41、Struts2的类型转换器实际上是基于OGNL实现的,在OGNL项目中有一个TypeConverter接口,这个接口就是实现类型转换器必须实现的接口。不过接口里的方法太过复杂,OGNL项目还提供一个该接口的实现类:DefaultTypeConverter,通过继承该类来实现自己的类型转换器,重写convertValue方法
42、文件上传框架需要完成的逻辑:通过分析HttpServletRequest的二进制流,解析出二进制流中所包含的全部表单域,分析出每个表单域的类型(是文件域或者普通表单域),并允许开发者以简单的方式来取得文件域的内容字节、文件名和文件内容等信息,也可以取得其他表单域的值
Struts2默认使用jakarta的common-fileupload的文件上传,也可以使用cos、pell的文件上传支持,对于开发组而言,使用那种文件上传支持,几乎没有任何区别—只需修改struts.multipart/parser常量,并在web应用中增加相应上传项目的类库即可
43、Struts2文件上传Action中,如果表单中包含一个name属性为xxx的文件域,则对应的Action需要使用3个属性来封装该文件域的信息:
类型为File的xxx属性封装了该文件域对应的文件内容
类型为String的xxxFileName属性封装了该文件域对应的文件的文件类型
类型为String的xxxContectType属性封装了该文件域对应的文件的文件类型
除此之外,还可以配置savePath属性,通过配置文件设置该属性的值—这也是典型的依赖注入
<action name=”upload” class=””>
<param name=”savePath”>/upload</param>
<result>/succ.jsp</result>
</action>
44、Struts2中文件上传拦截器是fileUpload,为了让该拦截器起作用,只需要在该Action中配置该拦截器的引用即可。
配置fileUpload拦截器时,可以为其指定两个参数:allowedTypes,maximumSize
当配置fileUpload拦截器时,还必须显示地为该Action配置defaultStack的拦截器引用
如果为了避免文件上传时使用Tomcat的工作 路径作为临时路径,则应该设置struts.multipart.saveDir属性,struts.multipart.maxSize该属性设置整个表单请求内容的最大字节数
45、配置下载的Action时,需要在配置普通Action的基础上,再加上额外的download的拦截器引用。除此之外,需要配置一个类型为stream的结果,配置时需要指定4个属性:contentType,inputName,contentDisposition,bufferSize,因为stream结果类型的逻辑视图是返回给客户端一个输入流,因此无需指定location属性。
46、从代码角度看,拦截器就是一个类,这个类也包含方法,只是这个方法是个特殊的方法,它会在目标方法调用之前”自动”执行。
47、AOP的编程方式中,有三个重要概念:目标对象、被插入的处理方法、代理对象
定义拦截器使用<intercepter .../>元素来定义,最简单格式如下:
<intercepter name=”” class=”” />如果还需要在传入参数,则使用子元素<param .../>
系统为拦截器指定参数有两个时机:①定义拦截器是指定参数值,这种参数值是拦截器这个参数的默认参数值②使用拦截器时指定参数值,这种参数值是当在Action中使用该拦截器时动态分配的参数值
一旦定义了拦截器和拦截器栈后,就可以使用这个拦截器或拦截器栈来拦截Action了,拦截行为将会在Action的execute方法执行前被执行
默认拦截器只有在Action中没有显示指定拦截器是才会起作用,每个包只能指定一个默认拦截器
自定义拦截器需实现Interceptor接口,重写intercept(ActionInvocation invocation)方法,该方法获得ActionInvocation参数,这个参数有可以获得被拦截的Action实例,一旦取得了Action实例,几乎获得了全部的控制权
如果只需要拦截某些方法,则可以使用Struts2拦截器的方法过滤,继承MethodFilterInterceptor类,如果用户需要实现自己的拦截逻辑,则应该重写doIntercept(ActionInvocation invocation)方法
配置在前面的拦截器,在被拦截方法之前的拦截动作,将会先对用户请求起作用;如果是在被拦截方法之后的拦截动作,则会后对用户请求起作用
48、为了精确定义在execute方法执行结束后,在处理Result执行的的动作,Struts2提供了用于拦截结果的监听器,这个监听器是通过手动注册在拦截器内部的,实现拦截结果的监听器必须实现PreResultListener接口。注意不要在PreResultListener监听器的beforeResult方法中通过ActionInvocation参数调用invoke方法,不然会陷入死循环。
49、如果需要在引用拦截器栈时直接覆盖栈内某个拦截器的属性值,则在指定需要被覆盖的属性时,不能只指定该属性的属性名,必须加上该属性属于的拦截器名。即
<l拦截器名>.<参数名>
<interceptor-ref name=””>
<param name=”拦截器名1.name”>改名后的拦截器</param>
</interceptor-ref>
50、Struts2内建拦截器,如果我们定义的package继承了Struts2的默认struts-default包,则可以*使用下面定义的拦截器,否则必须自己定义这些拦截器
alias:实现在不同请求中相似参数别名的转换
autowiring:自动装配拦截器,主要用于当Struts2和Spring整合时,Struts2可以使用自动装配的方式来访问Spring容器中的bean
chain:构建一个Action链,使当前Action可以访问前一个Action的属性,一般和<result type=”chain” .../>一起使用
conversionError:负责处理类型转换错误的拦截器,将类型转换错误从ActionContext中取出,并转换成Action的FieldError错误
createSession:负责创建一个HttpSession对象,主要用于那些需要有HttpSession对象才能正常工作的拦截器中
debuggding:当使用Struts2的开发模式时,这个拦截器会提供更多的调试信息
execAndWait:后台执行Action,负责将等待画面发送给用户
exception:负责处理异常,将异常映射为结果
fileUpload:主要用于文件上传,负责解析表单中文件域的内容
i18n:负责把所选的语言、区域放入用户Session中
logger:负责日志记录,主要是输出Action的名字
model-driven:用于模型驱动的拦截器,当摸个Action类实现了ModelDriven接口时,负责把getModel()方法的结果堆入ValueStack中
scoped-model-driven:如果一个Action实现了一个ScopedModelDriven接口,该拦截器负责从指定生存范围找出指定的Model,并将通过setModel方法将该Model传给Action实例
params:这是一个最基本拦截器,负责解析HTTP请求中的参数,并将参数值设置成Action对应的属性值
prepare:如果Action实现了Preparable接口,将会调用该拦截器的prepare()方法
static-params:负责将xml中<action>标签下<param>标签中的参数传入Action
scope:范围转换拦截器,可以将Action状态信息保存到HttpSession范围,或者ServletContext范围
servlet-config:如果某个Action需要直接访问Servlet API,通过这个拦截器实现
roles:一个JAAS拦截器,只有当浏览者取得合适的授权后,才可以调用被该拦截器拦截的Action
timer:负责输出Action的执行时间,在分析该Action的性能瓶颈时比较有用
token:这个拦截器主要用于阻止重复提交,它检查传到Action中的token,从而防止多次提交
token-session:作用与token拦截器类似,区别是它把token保存在HttpSession中
validation:通过执行在xxxAction-validation.xml中定义的校验器,完成数据校验
workflow:负责调用Action类中的validate方法,如果校验失败,则返回input的逻辑视图
大部分时候,开发者无需手动控制这些拦截器,只要我们定义的包继承了struts-default包,既可以直接使用这些拦截器
51、因为Struts2的struts-default包中指定defaultStarck拦截器栈是默认的拦截器栈,因此如果用户定义的包继承了struts-default包,则也会将defaultStack拦截器栈作为默认的拦截器栈。这意味着:如果系统中的Action配置没有指定拦截器引用,系统会将defaultStack拦截器栈自动作用于该Action。
52、Struts2的标签库大大简化了数据的输出,也提供了大量标签来生成页面效果
Struts2可以将所有标签分成3类:
UI标签:主要用于生成HTML元素的标签
非UI标签:主要用于数据访问、逻辑控制等的标签
Ajax标签:用于Ajax支持的标签
UI标签又可以分为两类:
表单标签:表单标签主要用于生成HTML页面的form元素,以及普通表单元素的标签
非表单标签:非表单标签主要用于生成页面上的树、Tab页等标签
非UI标签,也可以分为两类:
流程控制标签:主要包含用于实现分支、循环等流程控制的标签
数据访问标签:主要包含用于输出ValueStack中的值,完成国际化等功能的标签
53、导入Struts2标签库
<%@taglib prefix=”s” uri=”/struts-tags”%>
54、OGNL中,如果需要访问的属性属于根对象,则可以直接访问该属性;否则必须使用一个命名空间,如#bar
在Struts2中,系统的ValueStack是OGNL的第一个根对象,如果最近的Action存在,则Action上下文是第二个根对象
Struts2不只根据表达式从ValueStack中取得对象,还可以直接从对象中获取属性。Struts2提供了一个特殊的OGNL PropertyAccessory(属性访问器),它可以自动搜寻栈内的所有实体(从上到下),直到找到与求值表达式匹配的属性
Struts2使用标准的Context来进行OGNL表达式求值,OGNL处理的*对象是一个Context,这个Context对象就是一个Map类型实例。在该OGNL的Context中,有一个根对象,这个根对象就是OGNL ValueStack,如果需要访问ValueStack里的属性,直接通过如下方式
#取得ValueStack中的bar属性
${bar}
此外,Struts2还提供了一些命名对象,这些命名对象与根对象无关,它们只是存在于Stack Context中,所以,访问这些对象时需要使用#前缀来指明。
①parametersr,如#parameters[‘foo’]或#parameters.foo②request,如#request[‘foo’]或#request.foo③session,如#session[‘foo’]或#session.foo④application,如#application[‘foo’]或#application.foo⑤attr,如过可以访问到,则访问PageContext,否则将依次搜索request->session->servletCOntext
55、OGNL中的集合操作
直接生成List类型集合的语法为:{e1,e2,e3}
直接生成Map类型集合的语法为:#{key1:value1,key2:value2,key3:value3}
OGNL提供两个元素符:in和not in判断某个元素是否在指定集合中
<s:if test=”’foo’ in {‘foo’,’bar’}”>包含</s:if>
<s:else>不包含</s:else>
此外,OGNL还允许通过某个规则取得集合的子集,有3个操作符支持
①?:取出所有符合条件的元素②^:取出符合条件的第一个元素③$:取出符合条件的最后一个元素
Person.relatives.{? #this.gender == ‘mail’}
直接在集合后紧跟.{}运算符表明用于取出该集合的子集,在{}内使用?表明取出所有符合选择条件的元素,#this代表集合里的元素
56、OGNL支持基本的Lambda表达式,通过这种表达式语法,可以在OGNL中使用一些简单的函数
57、Struts2的非UI标签包括控制标签和数据标签,主要用于完成流程控制,以及对ValueStack的控制。
if:用于控制选择输出的标签
elseIf/elseif:与if标签结合使用,用于控制选择输出的标签
else:与if标签结合使用,用于控制选择输出的标签
append:用于将多个集合拼接成一个新的集合
generator:字符串解析器,用于将一个字符串解析成一个集合
iterator:迭代器,用于将集合迭代输出
merge:将多个集合拼接成一个新的集合,但与append的拼接方式有所不同
sort:用于对集合进行排序
subset:用于截取集合的部分元素,形成新的子集合
58、<s:iterator .../>标签对集合进行迭代输出时,可以指定3个属性:
value:可选,指定被迭代的集合,如果未指定,则使用ValueStack栈顶的集合
id:可选,指定集合里元素的ID
status:可选,指定迭代时IteratorStatus实例,通过该实例即可判断当前迭代元素的属性。例如是否是最后一个,以及当前迭代元素的索引等
59、Sort标签用于对指定的集合元素进行排序,进行排序时,必须提供自己的排序规则,即实现自己的Comparator,自己的Comparator需要实现java.util.COmparator接口,使用时可指定以下属性
①comparator:必填属性,指定进行排序的Comparator实例②source:可选,指定被排序的集合,如果不指定,则对ValueStack栈顶的集合进行排序
60、数据标签主要用于提供各种数据访问相关的功能,包含显示一个Action里的属性,以及生成国际化输出等功能,主要包括如下几个:
action:用于在JSP页面直接调用一个Action,通过指定executeResult参数还可将该Action的处理结果包含到页面中
bean:用于创建一个JavaBean实例。如果指定id属性,则可以将创建的JavaBean实例放入Stack Context中
date:用于格式化输出一个日期,计算指定日期和当前时刻之间的时差
debug:用于在页面省生成一个调试链接,当单击该链接时,可以看到当前ValueStack和Stack Context中的内容
i18n:指定国际化资源文件的baseName
include:在页面中包含其他的jsp或Servlet资源
param:设置参数,通常用作bean、url标签的子标签
push:将某个值放入ValueStack栈顶
set:用于设置一个新变量,并可以将新变量放入指定的范围内
text:用于输出国际化信息
url:用于生成一个URL地址
property:用于生成输出某个值,包括输出ValueStack、Stack Context 和Action Context中值
61、Struts2提供了两种基本的整合策略:一种是将Action实例交给Spring容器来负责生成、管理;另外一种策略是利用Spring插件的自动装配方式,当Spring插件创建Action实例后,立即将Spring容器中对应的业务逻辑组件注入Action实例。
62、Spring为企业应用的开发提供一个轻量级解决方案,该解决方案包括:基于依赖注入的核心机制,基于AOP的声明式事物管理,与多种持久层技术的整合,以及优秀的Web MVC框架等
63、在依赖注入的模式下,创建被调用者的工作不再由调用者来完成,因此称为控制反转;创建被调用者实例的工作通常由Spring容器来完成,然后注入调用者,因此也称为依赖注入
64、每个Struts2的插件jar文件都必须包含一个名为struts-plugin.xml的配置文件,struts-plugin.xml文件的内容与普通的struts.xml文件的内容完全相同
65、Struts2包含3中类型的配置文件,加载顺序为:struts-default.xml->struts-plugin.xml->struts.xml,应用相关的配置文件总是最后才加载的,因为应用可以依赖于插件,每个差价都可以依赖于Struts2的核心,但插件之间不可相互依赖
66、Spring容器初始化
1、利用ContextLoaderListener,要求在WEB-INF路径下有Spring配置文件applicationContext.xml,并且在web.xml中增加如下listener
<listener>
<listener-class>ora.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
如果有多个配置文件需要载入,则应该使用<context-param>元素来确定配置文件的文件名。ContextLoaderListener加载时,会查找名为”contextConfigLocation”的参数,因此,配置context-param时参数名字应该是”contextConfigLocation”,如果应用中的Spring配置文件有多个,则采用如下配置方式
<context-param>
<param-name>contextConfigLoaction</param-name>
<param-value>/WEB-INF/daoContext.xml,/WEB-INF/applicationContext.xml<param-value>
</context-param>
<listener>
<listener-class>ora.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
如果没有contextConfigLocation指定配置文件,Spring自动查找WEBB-INF下的applicationContext.xml,如果有contextConfigLocation,则利用该参数指定的配置文件来创建Spring容器,如果无法找到合适的配置文件,Spring将无法正常初始化
2、采用load-on-startup Servlet创建ApplicationContext
Spring提供了一个特殊的servlet类:ContextLoaderServlet,该servlet在初始化时,会自动查找WEB-INF/下的”applicationContext.xml”文件
<servlet>
<servlet-name>context</servlet-name>
<servlet-class>org.springframework,web.context.ContextLoaderServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
配置该servlet时,配置了load-on-startup子元素,指定该servlet会随web应用的启动而完成初始化,值余下,该servlet越早完成初始化,但不管多小,Listener都比该servlet更早启动
该servlet仅用于提供”后台”服务,负责创建Spring容器,无需响应客户请求,无需配置servlet-mapping,如果有多个配置文件,则同样要指定contextConfigLocation
67、采用工厂模式,将控制器与业务逻辑组件的实现分离,从而提供更好的解耦
68、控制器如何访问到Spring容器中的业务逻辑组件?为了让Action访问Spring的业务逻辑组件,有两种策略:
①Spring管理控制器,并利用依赖注入为控制器注入业务逻辑组件
②控制器定位Spring工厂,也就是Spring容器,从Spring容器中取得所需的业务逻辑组件