本文主要是介绍strtus2之核心原理和constant详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 1 strtus2核心概念
- 1.1 FilterDispatcher
- 1.2 Action
- 1.3 Result
- 1.4 Interceptor
- 1.5 ActionContext、值栈与OGNL
- 1.6 Struts2标签
- 1.7 自动类型转换
- 1.8 国际化
- 1.9 验证框架
- 2 struts2系统架构
- 2.1 各模块说明
- 3 struts2运行流程
- 3.1 前提条件
- 3.2 运行流程
- 4 constant详解
1 strtus2核心概念
1.1 FilterDispatcher
FilterDispatcher
是Struts2
的前端控制器,也是Struts2
的MVC
中的控制器部分。在实际开发中,只需要在web.xml
中配置一次即可,如下所示:
<filter><filter-name>Struts2</filter-name><filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class></filter><filter-mapping><filter-name>Struts2</filter-name><url-pattern>/*</url-pattern></filter-mapping>
但是一定要注意,如果还有其他的过滤器,那么FilterDispatcher
的配置通常要出现在最后。
1.2 Action
Action
动作类,作为MVC
中的模型部分,既封装业务数据,也负责处理用户的请求,execute
方法就是默认的动作处理方法。
1.3 Result
结果,代表Action
运行之后要转向的下一个页面。Struts2
本身支持多种结果类型,如jsp
、velocity
、freemarker
、jasperreports
等,在同一个web
应用中,各种结果类型还能混用。
1.4 Interceptor
拦截器是Struts2
中一个重要的概念。每一个Struts2
工程都使用了拦截器,只是使用了Struts2
自带的内建拦截器与默认拦截器配置而已。
Struts2
的许多功能都是由拦截器完成的,比如:
- 帮你把request参数设置到Action的属性中。
- 实现上传文件
- 防止重复提交
- 实现验证框架
- 通用错误处理
- 程序国际化
1.5 ActionContext、值栈与OGNL
Struts2
在每个Action
刚开始运行的时候,都会单独为它建立一个ActionContext
,把所有能访问的数据,包括请求参数(request
的parameter
)、请求的属性(request
的Attribute
)、会话(session
)信息等等,都放到ActionContext
中。这样一来,在以后取值、赋值的时候,就只需要访问ActionContext
就可以了,所以说ActionContext
可以被认为是每个Action
拥有的一个独立的内存数据中心
对象图导航语言OGNL
是Object-Graph Navigation Language
的缩写,它是一种功能强大的表达式语言(Expression Language
,简称为EL
)。它通过简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。
值栈
可以用来容纳多个对象,主要用来存放一些临时对象。当使用OGNL
访问值栈中对象的属性的时候,指定属性的引用会引用更靠近值栈栈顶方向对象,晚进栈的对象会覆盖早进栈的对象。简单点说,Struts2
用值栈为我们使用Struts2
做了很多引用上的简化,主要是缩短了OGNL
表达式的长度。另外,值栈也可以作为一个内存数据中心,来存放一些Struts2
标签临时定义的数据。
1.6 Struts2标签
Struts2
的标签库功能强大,使用简单,大大简化了视图开发的工作。而且,它与框架的其他部分也非常自然的结合,如国际化、验证等等。
1.7 自动类型转换
在Action
中可以有多种方式来对应页面的数据,从而自动获取页面的值。但是,从request
里面接收的值都是String
类型的,而Action
的属性可以是各种类型的。这就需要Struts2
的类型转换机制来支持,它节省了我们大量的手工进行类型转换的开发时间。
Struts2已经内置了大量的类型转换方式:
- 各种私有类型及其包装类
- 常见的各种数据类型,如String、Date、BigDecimal等等
- 各种集合概念,包括数组、Set、List、Map
- 甚至可以是枚举
Struts2
提供的这些就已经够用了,还可以自己实现特殊的类型转换器,以满足特殊的功能需要。
1.8 国际化
i18n
通常作为国际化
的简称,其来源是英文单词internationalization
的首末字符i和n
,18
为中间的字符数。
web
应用通常应该支持多国语言,可以根据客户端请求所来自的国家和语言显示不同语种的用户界面。这样,当需要在应用程序中添加对一种新语言的支持时,就无需修改应用程序的代码了。
Struts2
非常自然的实现了国际化,我们不需要考虑更多的事情,只是按照Struts2
的要求,把不同语言的信息,放到对应的位置即可。
1.9 验证框架
作为一个成熟、稳定的web
应用,无论如何服务器端验证是少不了的。通常情况下,我们不会完全相信客户端传递过来的数据,应该在真正调用业务逻辑之前对数据进行校验,如果用户提交的数据不符合要求,就不会去调用业务逻辑。
Struts2
为我们提供了一套完整、严密,可扩展的验证框架,保证在Action
运行之前会判断用户提交的信息是否完整、符合条件。
2 struts2系统架构
Struts2
的官方文档里附带了Struts2
的架构图,下面这张图上展示了Struts2
的内部模块,以及它们的运行流程。
这张图上分了好多块,彼此之间相互联系,先浏览一下各块的名字,再留心一下运行图最下面的图例,分为四种颜色:
- 橙色是
Servlet Filters
,过滤器链,所有的请求都要经过Filter
链的处理。 - 浅蓝色是
Struts Core
,Struts2
的核心部分,Struts2
中已经做好的功能,在实际开发中不需要动它们。 - 浅绿色是
Interceptors
,Struts2
的拦截器。Struts2
提供了很多默认的拦截器,可以完成日常开发的绝大部分工作;当然,也可以自定义拦截器,用来实现具体业务需要的功能。 - 浅黄色是
User Created
,由开发人员创建的,包括struts.xml
、Action
、Template
,是每个使用Struts2
来进行开发的人员都必须会的。
2.1 各模块说明
架构图上有好多东西,接下来逐个击破。首先看看它们各自是做什么的,跟着图上的箭头一个一个来看:
FilterDispatcher
是整个Struts2
的调度中心,根据ActionMapper
的结果来决定是否处理请求,如果ActionMapper
指出该URL
应该被Struts2
处理,那么它将会执行Action
处理,并停止过滤器链上还没有执行的过滤器。(补充: 先过dispatcher
dispatcher
持有actionmapper
,actionmapper
决定走哪个action
,filterdispatcher
里面持有actionmapper
)ActionMapper
提供了HTTP
请求与action
执行之间的映射,简单点说,ActionMapper
会判断这个请求是否应该被Struts2
处理,如果需要Struts2
处理,ActionMapper
会返回一个对象来描述请求对应的ActionInvocation
的信息。ActionProxy
是一个特别的中间层,位于Action
和xwork
之间,使得我们在将来有机会引入更多的实现方式,比如通过WebService
来实现等。ConfigurationManager
是xwork
配置的管理中心,通俗的讲,可以把它看做struts.xml
这个配置文件在内存中的对应。struts.xml
是Struts2
的应用配置文件,负责诸如URL
与Action
之间映射的配置、以及执行后页面跳转的Result
配置等。ActionInvocation
:真正调用并执行Action
,它拥有一个Action
实例和这个Action
所依赖的拦截器实例。ActionInvocation
会执行这些拦截器、Action
以及相应的Result
。Interceptor
(拦截器):拦截器是一些无状态的类,拦截器可以自动拦截Action
,它们给开发者提供了在Action
运行之前或Result
运行之后来执行一些功能代码的机会。类似于我们熟悉的javax.servlet.Filter
Action
:动作类是Struts2
中的动作执行单元。用来处理用户请求,并封装业务所需要的数据。Result
:Result
就是不同视图类型的抽象封装模型,不同的视图类型会对应不同的Result
实现,Struts2
中支持多种视图类型,比如Jsp
,FreeMarker
等。Templates
:各种视图类型的页面模板,比如JSP
就是一种模板页面技术。Tag Subsystem
:Struts2
的标签库,它抽象了三种不同的视图技术JSP
、velocity
、freemarker
,可以在不同的视图技术中,几乎没有差别的使用这些标签。
3 struts2运行流程
3.1 前提条件
在讲解流程之前,假设已经建立了的一个名为strutsDeepen
的web
工程,该工程仅仅实现了简单的用户登陆与欢迎界面。具体的实现为:
- 在
web.xml
中配置了Struts2
的过滤器 - 写了一个
Action
类,名称为loginAction
- 在
struts.xml
中配置了这个Action
类 - 写了两个页面,一个是登录页面,一个是欢迎页面
只做了这么点事情,就可以在Struts2
的帮助下顺利完成功能调用,那么Struts2
内部是怎么运行的呢?逐步来根据系统架构图进行分析。
3.2 运行流程
当用户提交登录请求后,请求的URL
为:/strutsDeepen/loginAction.action
,请求会被Tomcat
服务器接收到,Tomcat
服务器会根据请求URL
中的web
上下文,也就是/strutsDeepen
,来选择处理这个请求的Web
应用,那就是由strutsDeepen
这个web
工程来处理这个请求。
Web
容器会去读取strutsDeepen
这个工程的web.xml
,在web.xml
中进行匹配,发现后缀为.action
的请求,由struts2
这个过滤器来进行处理,根据Filter
的配置,找到实际的类为FilterDispatcher
。
Web
容器会获取FilterDispatcher
这个类的实例,然后回调doFilter
方法,进行真正的处理。FilterDispatcher
作为前端控制器,是整个Struts2
的调度中心。
注意
:在架构图上,可以看到有三个过滤器层次,分别是ActionContextCleanUp
、SiteMesh
等其他过滤器和FilterDispatcher
。这三个层次中,ActionContextCleanUp
和FilterDispatcher
是Struts2
的过滤器,而SiteMeshSiteMesh
等其他过滤器不是。
FilterDispatcher
是任何一个Struts2
应用都需要配置的,一般出现在过滤器链的最后;如果在FilterDispatcher
前出现了如SiteMesh
这种特殊的过滤器,还必须在SiteMesh
前引用Struts2
的ActionContextCleanUp
过滤器。
在前面的strutsDeepen
中,并没有出现SiteMesh
这种特殊的过滤器,所以只需要引用FilterDispatcher
就可以了。
(补充:先过dispatcher
dispatcher
持有actionmapper
,actionmapper
决定走哪个action
,filterdispatcher
里面持有actionmapper
)
FilterDispatcher
将请求转发给ActionMapper
。ActionMapper
负责识别当前的请求是否需要Struts2
做出处理。
ActionMapper
告诉FilterDispatcher
,需要处理这个请求,FilterDispatcher
会停止过滤器链以后的部分,所以通常情况下:FilterDispatcher
应该出现在过滤器链的最后。然后建立一个ActionProxy
对象,这个对象作为Action
与xwork
之间的中间层,会代理Action
的运行过程。
ActionProxy
对象刚被创建出来的时候,并不知道要运行哪个Action
,它手里只有从FilterDispatcher
中拿到的请求的URL
。这时候,它去向ConfigurationManager
询问到底要运行哪个Action
。某个特定的URL
由哪个Action
响应由谁负责,定义在什么地方呢?没错,在struts.xml
里面。而ConfigurationManager
就是负责读取并管理struts.xml
的,可以简单的理解为ConfigurationManager
是struts.xml
在内存中的映像。在服务器启动的时候,ConfigurationManager
会一次性的把struts.xml
中的所有信息读到内存里,并缓存起来,以保证ActionProxy
拿着来访的URL
向他询问要运行哪个Action
的时候,就可以直接匹配、查找并回答了。
ActionProxy
拿到了运行哪个Action
、相关的拦截器以及所有可能使用的result
信息,就可以着手建立ActionInvocation
对象了,ActionInvocation
对象描述了Action
运行的整个过程。
注意
:Action
运行绝不仅仅只是运行Action
的execute
方法这么简单,还包括其他部分,完整的调用过程由ActionInvocation
对象负责。
回忆一下,strutsDeepen
中Action
的execute
方法运行的时候,是不是它的属性就已经有了请求中的参数呢?这说明,在execute
方法之前,有人偷偷的帮我们做了这件事,把请求中的参数赋值到了Action
的属性上,这个有人
就是刚刚说的拦截器
。拦截器的运行被分成两部分,一部分在Action
之前运行,一部分在Result
之后运行,而且顺序是刚好反过来的。也就是在Action
执行前的顺序,比如是拦截器1、拦截器2、拦截器3,那么运行Result
之后,再次运行拦截器的时候,顺序就变成拦截器3、拦截器2、拦截器1了。
总之ActionInvocation
对象执行的时候比较复杂,会做很多事:
- 首先,按照拦截器的引用顺序依次执行各个拦截器的前置部分;
- 然后,执行
Action
的execute
方法; - 然后,根据
execute
方法返回的结果,也就是Result
,在struts.xml
中匹配选择下一个页面; - 找到页面后,由于现在的页面一般都是模板页面,在页面上,可以通过
Struts2
自带的标签库来访问需要的数据,并生成最终页面; - 最后,
ActionInvocation
对象再按照拦截器的引用顺序的倒序依次执行各个拦截器的后置部分。 ActionInvocation
对象执行完毕后,实际上就已经得到响应对象了,也就是HttpServletResponse
对象,最后按与过滤器器配置定义相反的顺序依次经过过滤器,向用户展示出响应的结果。
4 constant详解
<constant name="struts.i18n.encoding" value="UTF-8" />
:指定Web
应用的默认编码集,相当于调用HttpServletRequest``setCharacterEncoding
方法
<constant name="struts.action.extension" value="do" />
:该 属性指定需要Struts 2
处理的请求后缀,该属性的默认值是action
,即 所有匹配*.action
的请求都由Struts 2
处理。如 果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,
)隔开
<constant name="struts.serve.static.browserCache " value="false" />
:设置浏览器是否缓存静态内容,默认值为true
(生产环境下使用),开发阶段最好关闭,当应用处于开发阶段时,我们希望每次请求都获得服务器的最新响应,则可设置该属性为false
<constant name="struts.configuration.xml.reload" value="true" />
:当struts
的配置文件修改后,系统是否自动重新加载该文件,默认值为false
(生 产环境下使用),开发阶段最好打开
<constant name="struts.devMode" value="true" />
:开发模式下使用,这样可以打印出更详细的错误信息
<constant name="struts.ui.theme" value="simple" />
:默认的视图主题
<constant name="struts.objectFactory" value="spring" />
:该 属性指定Struts2
中的action
由Spring
容器创建
struts.enable.DynamicMethodInvocation
:该属性设置Struts 2
是否支持动态方法调用,该属性的默认值是true
。如果需要关闭动态方法调用,则可设置该属性为false
。
struts.enable.SlashesInActionNames
:该属性设置Struts 2
是否允许在Action
名中使用斜线,该属性的默认值是false
。如果开发者希望允许在Action
名中使用斜线,则可设置该属性为true
。
struts.tag.altSyntax
:该属性指定是否允许在Struts 2
标签中使用表达式语法,因为通常都需要在标签中使用表达式语法,故此属性应该设置为true
,该属性的默认值是true
。
struts.i18n.reload
:该属性设置是否每次HTTP
请求到达时,系统都重新加载资源文件。该属性默认值是false
。在开发阶段将该属性设置为true
会更有利于开发, 但在产品发布阶段应将该属性设置为false
。
提示 开发阶段将该属性设置了true
,将可以在每次请求时都重新加载国际化资源文件,从而可以让开发者看到实时开发效果;产品发布阶段应该将该属性设置为 false
,是为了提供响应性能,每次请求都需要重新加载资源文件会大大降低应用的性能。
struts.ui.templateDir
:该属性指定视图主题所需要模板文件的位置,该属性的默认值是template
,即默认加载template
路径下的模板文件。
struts.ui.templateSuffix
:该属性指定模板文件的后缀,该属性的默认属性值是ftl
。该属性还允许使用ftl
、vm
或jsp
,分别对应FreeMarker
、 Velocity
和JSP
模板。
struts.velocity.configfile
:该属性指定Velocity
框架所需的velocity.properties
文件的位置。该属性的默认值为velocity.properties
struts.velocity.contexts
:该属性指定Velocity
框架的Context
位置,如果该框架有多个Context
,则多个Context
之间以英文逗号(,
)隔开。
struts.velocity.toolboxlocation
:该属性指定Velocity
框架的toolbox
的位置。
struts.url.http.port
:该属性指定Web
应用所在的监听端口。该属性通常没有太大的用户,只是当Struts 2
需要生成URL
时(例如Url
标签),该属性才提供Web
应用的默认端口。
struts.url.https.port
:该属性类似于struts.url.http.port
属性的作用,区别是该属性指定的是Web
应用的加密服务端口。
struts.url.includeParams
:该属性指定Struts 2
生成URL
时是否包含请求参数。该属性接受none
、get
和all
三个属性值,分别对应于不包含、仅包含GET
类型请求参数和包含全部请求参数。
struts.custom.i18n.resources
:该属性指定Struts 2
应用所需要的国际化资源文件,如果有多份国际化资源文件,则多个资源文件的文件名以英文逗号(,
)隔开。
struts.dispatcher.parametersWorkaround
:对 于某些Java EE
服务器,不支持HttpServlet Request
调用getParameterMap()
方法,此时可以设置该属性值为true
来解决该问题。该属性的默认值是false
。对于WebLogic
、Orion
和OC4J
服务器,通常应该设置该属性为true
。
struts.freemarker.manager.classname
:该属性指定Struts 2
使用的FreeMarker
管理器。该属性的默认值org.apache.struts2.views.freemarker.FreemarkerManager
,这是 Struts 2
内建的FreeMarker
管理器。
struts.freemarker.wrapper.altMap
:该属性只支持true
和false
两个属性值,默认值是true
。通常无需修改该属性值。
struts.xslt.nocache
:该属性指定XSLT Result
是否使用样式表缓存。当应用处于开发阶段时,该属性通常被设置为true
;当应用处于产品使用阶段时,该属性通常被设置为false
。
struts.configuration.files
:该属性指定Struts 2
框架默认加载的配置文件,如果需要指定默认加载多个配置文件,则多个配置文件的文件名之间以英文逗号(,
)隔开。该属性的默认值为struts-default.xml,struts-plugin.xml,struts.xml
,看到该属性值,读者应该明白为什么Struts 2
框架默认加载struts.xml
文件了。
struts.objectFactory
:该属性指定Struts 2
中的action
由哪个容器创建
struts.convention.default.parent.package
:这个常量表示缺省的包名是什么,因为在实际应用中,我们常常定义一个缺省的包,这个包中定义了一大堆的拦截器等等,然后其他的包继承自这个包。这个常量可以配也可以不配
struts.convention.package.locators
:这个常量表示你的action
类的java
包的包名的后缀是啥:比如action
。这个常量也可以不配;
struts.convention.package.locators.basePackage
:这个常量表示你的action
类的java
包package
的名字是啥;这个常量也可以不配;
这篇关于strtus2之核心原理和constant详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!