struts2
struts2发展历史
经过很多年发展,Struts1已经成为了高度成熟的框架,但随着时间的发展,Struts1的局限性和缺点不断的暴露出来。
现在Struts已经分化成了两个框架
-第一个是在Struts1的基础上,融合了另一个web框架Webwork的Struts2.Struts2实质上是以Webwork为核心的,和Struts1有很大区别。
-第二个是Shale,与原有Struts1关联很少,使用了全新的设计思想。
MVC思想概述
java web动态编程技术,经历了Model和Model2时代。
Model1时代:整个Web应用几乎全部由jsp页面组成,jsp页面接收处理客户端请求,对请求处理后直接做出响应,用少量的JavaBean来处理数据库连接访问等操作。Model1的局限性非常明显,jsp页面同时担任View和Controller两种角色,将页面表现和逻辑处理混杂在一起,代码重用性极低,增加了扩展和维护难度。
Model2时代:已经采用了MVC的设计。在Model 2架构中,Servlet作为Controller,负责接收用户请求,只包含控制逻辑,然后调用后端来进行具体的逻辑处理。最后转发到相应的jsp页面负责显示。
MVC由Model(模型),View(视图),Controller(控制器)组成。
javaWeb中的三层架构
表现层:MVC,struts2框架其实是对表现层的MVC作了优化
业务层:service
持久层:dao
Struts2环境的搭建
(1)下载Struts2
<span style="color:#000000"><code> 目录结构
apps:该文件夹下包含了基于Struts2的示例应用
docs:包含了Struts2的相关文档
lib:包含了Struts2的核心类库,以及Struts2的第三方类库
src:包含了Struts框架的所有源代码
</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
(2)创建web项目,导入struts2所需jar包,lib中有struts2的所有jar包,但是我们不需要那么多。
我们只把必需的添加到项目即可。将apps目录下struts2-blank.war压缩包中的lib目录下的jar包添加到我们项目中即可。这是struts2必需的jar包。
Struts2架构
struts使用拦截器作为增强处理,以用户的逻辑控制器为目标,创建一个控制器代理,控制器代理回调业务控制器的execute方法处理用户请求,该方法的返回值决定struts2将怎样的视图资源呈现给用户
struts2大致处理流程:
(1)浏览器发送请求
(2)核心控制器根据请求决定是否调用相应的Action
(3)struts2内置的拦截器链会自动对请求进行一些操作
(4)回调Action的execute方法,执行操作。
(5)Action会将处理结果存入stack Context中,并返回字符串,核心控制器根据字符串跳转到指定的视图资源。
(6)视图资源会读取Stack Context中的信息,向浏览器生成响应数据。
Struts2入门案例
只需跟着做即可,先不必了解为何这样做。
(1)编辑web应用的web.xml配置文件,配置struts2的核心拦截器。
<span style="color:#000000"><code>
<<span style="color:#4f4f4f">filter</span>>
<<span style="color:#4f4f4f">filter</span>-name>struts2</<span style="color:#4f4f4f">filter</span>-name>
<<span style="color:#4f4f4f">filter</span>-<span style="color:#000088">class</span>>org.apache.struts2.dispatcher.ng.<span style="color:#4f4f4f">filter</span>.StrutsPrepareAndExecuteFilter</<span style="color:#4f4f4f">filter</span>-<span style="color:#000088">class</span>>
</<span style="color:#4f4f4f">filter</span>>
<<span style="color:#4f4f4f">filter</span>-mapping>
<<span style="color:#4f4f4f">filter</span>-name>struts2</<span style="color:#4f4f4f">filter</span>-name>
<url-pattern>/*</url-pattern>
</<span style="color:#4f4f4f">filter</span>-mapping> </code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
(2)从用户请求开始,我们实现一个登陆表单
<span style="color:#000000"><code> 这里的action属性比较特殊,不是普通的servlet。
当表单提交给login时,struts的拦截器会起作用,调用用户开发的Action处理用户请求
<span style="color:#006666"><<span style="color:#4f4f4f">body</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">form</span> <span style="color:#4f4f4f">action</span>=<span style="color:#009900">"login"</span> <span style="color:#4f4f4f">method</span>=<span style="color:#009900">"post"</span>></span>
用户名:<span style="color:#006666"><<span style="color:#4f4f4f">input</span> <span style="color:#4f4f4f">type</span>=<span style="color:#009900">"text"</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"username"</span>></span><span style="color:#006666"><<span style="color:#4f4f4f">br</span>></span>
密 码:<span style="color:#006666"><<span style="color:#4f4f4f">input</span> <span style="color:#4f4f4f">type</span>=<span style="color:#009900">"password"</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"password"</span>></span><span style="color:#006666"><<span style="color:#4f4f4f">br</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">input</span> <span style="color:#4f4f4f">type</span>=<span style="color:#009900">"submit"</span> <span style="color:#4f4f4f">value</span>=<span style="color:#009900">"登录"</span>></span>
<span style="color:#006666"></<span style="color:#4f4f4f">form</span>></span>
<span style="color:#006666"></<span style="color:#4f4f4f">body</span>></span> </code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
(3)实现控制器Action类处理用户请求
我们已经指出,MVC框架的核心就是控制器,控制器处理具体用户请求。
<span style="color:#000000"><code> 这个类实现Action接口,并实现接口的execute方法。
该类包含的多个属性用于封装用户的请求参数。 我们可能现在很难理解,我们请求的参数是怎么赋值给这个类的。
我们说过,在调用Action方法之前,struts2的内置拦截器会自动负责解析用户请求参数,并赋值给Action相应的参数
<span style="color:#000088">public</span> <span style="color:#000088">class</span> <span style="color:#4f4f4f">LoginAction</span> <span style="color:#000088">extends</span> <span style="color:#4f4f4f">Action</span>{
<span style="color:#000088">private</span> String username; <span style="color:#880000">//用户名</span>
<span style="color:#000088">private</span> String password; <span style="color:#880000">//密码</span>
<span style="color:#000088">public</span> String <span style="color:#009900">getUsername</span>() {
<span style="color:#000088">return</span> username;
}
<span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">setUsername</span>(String username) {
<span style="color:#000088">this</span>.username = username;
}
<span style="color:#000088">public</span> String <span style="color:#009900">getPassword</span>() {
<span style="color:#000088">return</span> password;
}
<span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">setPassword</span>(String password) {
<span style="color:#000088">this</span>.password = password;
}
<span style="color:#880000">//判断用户名和密码是否相同</span>
<span style="color:#000088">public</span> String <span style="color:#009900">execute</span>(){
<span style="color:#000088">if</span>(getUsername().equals(<span style="color:#009900">"cad"</span>)&&getPassword().equals(<span style="color:#009900">"123456"</span>)){
<span style="color:#000088">return</span> <span style="color:#009900">"success"</span>;
}<span style="color:#000088">else</span>
{
<span style="color:#000088">return</span> <span style="color:#009900">"error"</span>;
}
}
}
</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
(4)配置Action
我们用户发送login请求,那么如果根据login请求去调用相应的Action实现类呢?这就需要我们去配置Action。
<span style="color:#000000"><code>配置struts.xml ,struts.xml应该放在src的classes路径下
<span style="color:#006666"><?xml version="1.0" encoding="UTF-8"?></span> //直接复制
<span style="color:#4f4f4f"><!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd"></span>
<span style="color:#006666"><<span style="color:#4f4f4f">struts</span>></span> //根元素
<span style="color:#006666"><<span style="color:#4f4f4f">package</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"demo"</span> <span style="color:#4f4f4f">extends</span>=<span style="color:#009900">"struts-default"</span>></span> //包 name随便取,extends照写就ok
<span style="color:#006666"><<span style="color:#4f4f4f">action</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"login"</span> <span style="color:#4f4f4f">class</span>=<span style="color:#009900">"com.cad.struts2.LoginAction"</span>></span> //action name为login,即为负责处理login的请求,action默认调用自身的execute方法处理请求
<span style="color:#006666"><<span style="color:#4f4f4f">result</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"success"</span>></span>/welcome.jsp<span style="color:#006666"></<span style="color:#4f4f4f">result</span>></span> //根据返回的字符串转发到相应页面
<span style="color:#006666"><<span style="color:#4f4f4f">result</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"error"</span>></span>/error.jsp<span style="color:#006666"></<span style="color:#4f4f4f">result</span>></span>
<span style="color:#006666"></<span style="color:#4f4f4f">action</span>></span>
<span style="color:#006666"></<span style="color:#4f4f4f">package</span>></span>
<span style="color:#006666"></<span style="color:#4f4f4f">struts</span>></span> </code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
Struts2两个重要组成部分
struts2核心就是核心控制器和业务控制器。
核心控制器StrutsPrepareAndExecuteFilter
<span style="color:#000000"><code>StrutsPrepareAndExecuteFilter作为一个filter运行在web应用中,负责拦截所有用户请求,该filter 会过滤用户请求,然
后将请求都交给struts2框架处理。拦截器会默认拦截扩展名为.action的请求,什么后缀名都不写也可以。例如
hello.action或者hello都会进行拦截。xxx.jsp就不会进行拦截,直接放行。
</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
(1)启动Tomcat,tomcat加载web.xml文件。同时加载和初始化核心过滤器,查看struts2源码,发现核心过滤器的初始化方法中会加载struts.xml等struts2配置文件。
(2)当用户请求到达时,核心过滤器拦截用户请求,将请求交给struts2框架来处理,即去匹配struts.xml的内容。
struts2框架获取用户请求后,根据请求的名字来决定调用哪个业务逻辑组件,实例化相应的类。例如,对于login请求,调用名为login的Action处理。
(3)struts2的所有Action都被定义在struts.xml文件中,Action有name和class属性,name决定了该Action处理哪个用户请求,class决定了该Action的实现类。
(4)Struts2用户处理用户请求的Action实例,并不是用户实现的业务控制器,而是Action代理,他会回调用户的处理方法,因为用户实现的业务控制器没有与Servlet API有任何关系,所以根本没办法进行获取参数等请求处理,而struts2定义了一系列拦截器,会对请求参数解析,传入到Action中,回调execute方法。
我们每次请求都会实例化相应的类,所以不会出现线程不安全的情况。而Servlet为单例,会出现线程不安全。
业务控制器:
<span style="color:#000000"><code>业务控制器就是用户实现的Action类,Action类中通常包含一个execute方法,该方法返回一个字符串,字符串与struts.xml中的result的name相对应,跳转到不同页面。
</code></span>
- 1
- 2
struts2内部运行流程
(1)客户端发出HTTP请求
(2)然后请求被核心过滤器StrutsPrepareAndExecuteFilter拦截
(3)核心过滤器将请求转发到Action映射器,Action映射器负责识别当前的请求是否需要交由Struts2处理。
(4)Action映射器返回需要struts2处理的信息,StrutsPrepareAndExecuteFilter会创建一个Action代理
(5)Action代理并不知道执行哪一个Action,它会向配置管理器询问调用哪一个Action,配置管理器会从struts.xml读取我们配置的Action信息。
(6)Action代理创建相关请求的Action对象,调用相关的方法之前,struts2的一系列拦截器会帮我们做一些操作,例如获取请求参数等。
(7)然后调用execute方法根据返回的字符串去匹配相应的页面,
(8)页面可以获取一些页面模板,然后生成最终页面,再倒序的执行拦截器的后续操作
(9)最后生成HTTP响应内容
Struts2配置文件
<span style="color:#000000"><code>Struts2核心配置文件是struts.xml,该文件主要负责管理业务控制器Action。
struts2有很多配置文件,按照以下顺序加载配置
(在服务器开启时,加载web.xml文件,然后初始化核心过滤器,核心过滤器的init初始化方法中,
提供了加载配置文件的方法。所以服务器一启动,这些配置文件就已经加载到内存中了。 )
default.properties:该文件保存在struts2-core-2.3.32.jar中的org.apache.struts2包里面
里面保存一些常量。
struts-default.xml :该文件保存在struts2-core-2.3.32.jar中
定义了一些struts2的基础Bean和struts2内建支持的结果类型,还有struts2内建的拦截器(拦截器有很多,分为一系列的拦截器块,我们默认使用defaultStack拦截器块)
struts-plugin.xml :该文件保存在struts-xxx-2.3.32.jar等struts2插件jar包中
我们整合spring等框架时,都需要这种插件的jar包。
struts.xml:是web应用默认的自己的struts2配置文件
struts.properties :是struts2的默认配置文件
web.xml:web应用的配置文件
如果多个文件配置了同一个struts2常量,则后一个文件中配置的常量值会覆盖前面文件中配置的常量值。
</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
配置文件中常用的常量
<span style="color:#000000"><code> struts.i18n.encoding:该常量指定struts2应用默认使用的字符集。
struts.objectFactory.spring.autoWire:和spring框架整合有关。
struts.multipart.parser:指定文件上传用的组件。默认为jakarta(即common-fileupload上传组件)
struts.multipart.saveDir:指定上传文件的临时保存路径
struts.multipart.maxSize:指定上传中整个请求所允许上传的最大字节数。
struts.action.extension:指定struts2需要处理的请求后缀。默认值为.action或者什么都不写
struts.serve.static.browserCache:设置浏览器是否缓存静态内容,当应用处于开发阶段时,我们希望不缓存,可设置为false
struts.enable.DynamicMethodInvocation:设置struts2是否支持动态方法调用,默认值为true
struts.devMode:设置struts2是否使用开发模式。如果设置为true,为开发模式,修改struts.xml配置文件不需要重启服务器,会显示更多更友好的错误提示。
struts.ui.theme:指定视图主题。
struts.url.includeParams:指定struts2生成url时是否包含请求参数。有none,get和all三个值。分别对应不包含,仅包含get类型请求参数和包含全部请求参数。
</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
struts.xml文件中配置和修改常量
<span style="color:#000000"><code>在struts.xml文件中配置,使用<constant .../>配置常量。
name:常量名
value:常量值
<constant name="" value=""/>
</code></span>
- 1
- 2
- 3
- 4
- 5
<span style="color:#000000"><code> 例子:我们修改请求后缀为.abc
在struts.xml文件中配置
<span style="color:#006666"><<span style="color:#4f4f4f">package</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"demo"</span> <span style="color:#4f4f4f">extends</span>=<span style="color:#009900">"struts-default"</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">action</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"hello"</span> <span style="color:#4f4f4f">class</span>=<span style="color:#009900">"com.cad.struts2.Hello"</span> <span style="color:#4f4f4f">method</span>=<span style="color:#009900">"sayHello"</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">result</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"success"</span>></span>/welcome.jsp<span style="color:#006666"></<span style="color:#4f4f4f">result</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">result</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"error"</span>></span>/error.jsp<span style="color:#006666"></<span style="color:#4f4f4f">result</span>></span>
<span style="color:#006666"></<span style="color:#4f4f4f">action</span>></span>
<span style="color:#006666"></<span style="color:#4f4f4f">package</span>></span>
//修改请求后缀为abc
<span style="color:#006666"><<span style="color:#4f4f4f">constant</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"struts.action.extension"</span> <span style="color:#4f4f4f">value</span>=<span style="color:#009900">"abc"</span>></span><span style="color:#006666"></<span style="color:#4f4f4f">constant</span>></span> </code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
<span style="color:#000000"><code>
编写jsp页面
<span style="color:#006666"><<span style="color:#4f4f4f">body</span>></span>
//使用默认请求后缀
<span style="color:#006666"><<span style="color:#4f4f4f">a</span> <span style="color:#4f4f4f">href</span>=<span style="color:#009900">"${pageContext.request.contextPath }/hello.action"</span>></span>后缀为.action<span style="color:#006666"></<span style="color:#4f4f4f">a</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">a</span> <span style="color:#4f4f4f">href</span>=<span style="color:#009900">"${pageContext.request.contextPath }/hello"</span>></span>没有后缀<span style="color:#006666"></<span style="color:#4f4f4f">a</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">a</span> <span style="color:#4f4f4f">href</span>=<span style="color:#009900">"${pageContext.request.contextPath }/hello.abc"</span>></span>后缀为.abc<span style="color:#006666"></<span style="color:#4f4f4f">a</span>></span>
<span style="color:#006666"></<span style="color:#4f4f4f">body</span>></span>
结果为前两个都出现404
最后一个超链接访问成功
</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
在web.xml文件中配置常量
<span style="color:#000000"><code> <span style="color:#880000"> //修改请求后缀为do</span>
<init-<span style="color:#4f4f4f">param</span>>
<<span style="color:#4f4f4f">param</span>-name>struts.action.extension</<span style="color:#4f4f4f">param</span>-name>
<<span style="color:#4f4f4f">param</span>-<span style="color:#4f4f4f">value</span>><span style="color:#4f4f4f">do</span></<span style="color:#4f4f4f">param</span>-<span style="color:#4f4f4f">value</span>>
</init-<span style="color:#4f4f4f">param</span>>
jsp页面
<body>
<a href=<span style="color:#009900">"${pageContext.request.contextPath }/hello.action"</span>>后缀为.action</a>
<a href=<span style="color:#009900">"${pageContext.request.contextPath }/hello"</span>>没有后缀</a>
<a href=<span style="color:#009900">"${pageContext.request.contextPath }/hello.abc"</span>>后缀为.abc</a>
<a href=<span style="color:#009900">"${pageContext.request.contextPath }/hello.do"</span>>后缀为.<span style="color:#4f4f4f">do</span></a>
</body>
前三个都请求失败,最后.<span style="color:#4f4f4f">do</span>结尾的请求成功。这也验证了我们说的配置文件的加载顺序。
</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
深入struts2配置文件
Bean配置
<span style="color:#000000"><code>struts2是一个高度可扩展的框架。框架的大部分核心组件,并不是硬编码写在代码中,而是以自己的IOC容器管理框架的核心组件。
struts2以可配置的方式来管理核心组件,从而允许开发者很方便的扩展该框架的核心组件,当开发者需要扩展,替换核心组件时,只需要提供自己组件的实现类,将其部署在struts2的IoC容器中即可。
struts-default.xml文件中配置了大量的struts2框架的内置Bean。
我们在struts.xml中定义Bean时,通常有两个作用
-创建该Bean的实例,将该实例作为struts2框架的核心组件使用。
-Bean包含的静态方法需要注入一个值。可以很方便地允许不创建某个类的实例,却可以接受框架常量。
这个部分只需要了解即可,百分之九十九的struts2应用都不用我们去定义核心组件和去配置Bean。
使用<bean />元素在struts.xml定义Bean
属性:
class:必填属性。指定了Bean实例的实现类
type:可选属性,制定了Bean实例实现的struts2规范,该规范通过某个接口实现。
name:可选属性。Bean实例的名字
scope:可选属性。指定Bean实例的作用域
static:可选属性。指定Bean是否使用静态方法注入。
optional:可选属性。指定该Bean是否是一个可选Bean。
例如
使用自定义的ObjectFactory,实现了ObjectFactory接口。实现类是MyObjectFactory
<bean type="com.opensymphony.xwork2.ObjectFactory" name="myfactory" class="com.my.MyObjectFactory"/>
</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
了解即可,不需要深入。
package包配置
<span style="color:#000000"><code> struts2框架的核心组件就是Action,拦截器等。struts2使用包来管理Action,拦截器等。
属性
name:配置包时,必须指定name属性,是包的唯一标识。
extends:属性值必须是另一个包的name属性。指定extends属性表示继承其他包。子包可以集成一个或多个父包中的拦截器,拦截器栈,action等配置。
例如我们前面项目中定义的 <package name="demo" extends="struts-default"> ,就继承struts-default.xml中的struts-default包。
abstract:可选属性。指定该包是否是抽象包,抽象包不能包含Action定义。
namespace:该属性是一个可选属性,定义该包的命名空间。一个web应用中可能出现同名Action。同一个命名空间中不能有同名Action
某个包指定命名空间后,该包下的所有action的url地址必须是 命名空间+action
例如我们加一个命名空间,则访问这个动作的时候必须加上命名空间。例如 http://localhost:8080/Struts2Demo/user/hello.action
<package name="demo" extends="struts-default" namespace="/user">
<action name="hello" class="com.cad.struts2.Hello" method="sayHello">
<result name="success">/welcome.jsp</result>
<result name="error">/error.jsp</result>
</action>
</package>
如果包没有指定命名空间,则默认的命名空间为""
根命名空间为"/"
</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
包的执行顺序
例如http://localhost:8080/Struts2Demo/user/my/hello.action
<span style="color:#000000"><code> (1)搜索配置文件所有package的namespace
(2)先去匹配命名空间/user/my,如果匹配到,就查找Action,查找到就执行,没查找到会到默认命名空间查找Action,查找到执行,没找到报错。
(3)如果没匹配到该命名空间,就接着匹配命名空间/user,如果匹配到,就查找Action,查找到就执行,没查找到会到默认命名空间查找Action,查找到执行,没找到报错。
(4)没匹配到就去根命名空间(”/“)查找action,没查找到会到默认命名空间查找Action,查找到执行,没找到报错。
(5)没匹配到任何命名空间直接报错。
</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Struts2的Action
开发者需要提供大量的Action,并在struts.xml中配置Action.Action类里包含了对用户请求的处理逻辑,因为我们也称Action为业务控制器。
编写Action处理类
第一种创建处理类方法 :
<span style="color:#000000"><code> struts2采用了低侵入式的设计,struts2不要求Action类继承任何的struts基类,也不需要实现任何接口。Action类只是一个普通的POJO(Plain Ordinary Java Object简单的java对象)
</code></span>
- 1
- 2
第二种:创建一个类实现Action接口,该接口定义了五个字符串常量。还包含一个String execute()方法
<span style="color:#000000"><code> public interface Action{
五个字符串常量
public static final String ERROR="errror";
public static final String INPUT="input";
public static final String LOGIN="login";
public static final String NONE="none";
public static final String SUCCESS="success";
//处理用户请求的execute方法
public String execute()throws Exception;
}
</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
第三种:继承Action接口的实现类ActionSupport,该类提供了很多的默认方法,包括获取国际化信息,数据校验的方法等。大大简化了Action的开发。我们开发中选择第三种
配置Action
<span style="color:#000000"><code> 在struts.xml文件中配置。struts2使用包来组织action。所以action定义放在包定义的下面 。
<action.../>
属性
name:action的名字
class:指定该action的实现类,class属性并不是必须的,如果我们不指定class属性,系统默认使用ActionSupport类
配置Action的默认处理类
如果我们不指定<action>中的class属性,默认使用ActionSupport类。
我们可以使用<default-class-ref class=""></default-class-ref>来指定默认的动作处理类。
</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
Action的方法调用
我们继承的ActionSupport,当我们执行Action的时候,默认执行他的execute方法,现在我们来执行自己的方法。< action >中有一个method属性,可以指定用户调用哪个方法。
<span style="color:#000000"><code>例子:
我们写一个Action类,类里有四个方法。
<span style="color:#000088">public</span> <span style="color:#000088">class</span> <span style="color:#4f4f4f">Hello</span> <span style="color:#000088">extends</span> <span style="color:#4f4f4f">ActionSupport</span>{
<span style="color:#000088">public</span> String <span style="color:#009900">addUser</span>(){
System.out.println(<span style="color:#009900">"添加用户"</span>);
<span style="color:#000088">return</span> SUCCESS;
}
<span style="color:#000088">public</span> String <span style="color:#009900">updateUser</span>(){
System.out.println(<span style="color:#009900">"修改用户"</span>);
<span style="color:#000088">return</span> SUCCESS;
}
<span style="color:#000088">public</span> String <span style="color:#009900">selectUser</span>(){
System.out.println(<span style="color:#009900">"查询用户"</span>);
<span style="color:#000088">return</span> SUCCESS;
}
<span style="color:#000088">public</span> String <span style="color:#009900">deleteUser</span>(){
System.out.println(<span style="color:#009900">"删除用户"</span>);
<span style="color:#000088">return</span> SUCCESS;
}
} </code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
<span style="color:#000000"><code>我们在struts.xml中配置我们的action
<package name=<span style="color:#009900">"demo"</span> extends=<span style="color:#009900">"struts-default"</span>>
<action name=<span style="color:#009900">"addUser"</span> class=<span style="color:#009900">"com.cad.struts2.Hello"</span> method=<span style="color:#009900">"addUser"</span>>
<<span style="color:#009900">result</span> name=<span style="color:#009900">"success"</span>>/welcome.jsp</<span style="color:#009900">result</span>>
<<span style="color:#009900">result</span> name=<span style="color:#009900">"error"</span>>/<span style="color:#000088">error</span>.jsp</<span style="color:#009900">result</span>>
</action>
<action name=<span style="color:#009900">"updateUser"</span> class=<span style="color:#009900">"com.cad.struts2.Hello"</span> method=<span style="color:#009900">"updateUser"</span>>
<<span style="color:#009900">result</span> name=<span style="color:#009900">"success"</span>>/welcome.jsp</<span style="color:#009900">result</span>>
<<span style="color:#009900">result</span> name=<span style="color:#009900">"error"</span>>/<span style="color:#000088">error</span>.jsp</<span style="color:#009900">result</span>>
</action>
<action name=<span style="color:#009900">"selectUser"</span> class=<span style="color:#009900">"com.cad.struts2.Hello"</span> method=<span style="color:#009900">"selectUser"</span>>
<<span style="color:#009900">result</span> name=<span style="color:#009900">"success"</span>>/welcome.jsp</<span style="color:#009900">result</span>>
<<span style="color:#009900">result</span> name=<span style="color:#009900">"error"</span>>/<span style="color:#000088">error</span>.jsp</<span style="color:#009900">result</span>>
</action>
<action name=<span style="color:#009900">"deleteUser"</span> class=<span style="color:#009900">"com.cad.struts2.Hello"</span> method=<span style="color:#009900">"deleteUser"</span>>
<<span style="color:#009900">result</span> name=<span style="color:#009900">"success"</span>>/welcome.jsp</<span style="color:#009900">result</span>>
<<span style="color:#009900">result</span> name=<span style="color:#009900">"error"</span>>/<span style="color:#000088">error</span>.jsp</<span style="color:#009900">result</span>>
</action>
</package> </code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
<span style="color:#000000"><code>在jsp页面中请求action
<span style="color:#006666"><<span style="color:#4f4f4f">body</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">a</span> <span style="color:#4f4f4f">href</span>=<span style="color:#009900">"${pageContext.request.contextPath }/addUser"</span>></span>添加用户<span style="color:#006666"></<span style="color:#4f4f4f">a</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">a</span> <span style="color:#4f4f4f">href</span>=<span style="color:#009900">"${pageContext.request.contextPath }/updateUser"</span>></span>修改用户<span style="color:#006666"></<span style="color:#4f4f4f">a</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">a</span> <span style="color:#4f4f4f">href</span>=<span style="color:#009900">"${pageContext.request.contextPath }/selectUser"</span>></span>查看用户<span style="color:#006666"></<span style="color:#4f4f4f">a</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">a</span> <span style="color:#4f4f4f">href</span>=<span style="color:#009900">"${pageContext.request.contextPath }/deleteUser"</span>></span>删除用户<span style="color:#006666"></<span style="color:#4f4f4f">a</span>></span>
<span style="color:#006666"></<span style="color:#4f4f4f">body</span>></span> </code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
我们发现这种方式写的很多代码类似,相当冗余,为了解决这个问题,struts2提供了通配符的配置方式帮我们解决这个问题。
使用通配符
<span style="color:#000000"><code> 我们在struts.xml文件中配置
<package name=<span style="color:#009900">"demo"</span> extends=<span style="color:#009900">"struts-default"</span>>
<action name=<span style="color:#009900">"*"</span> class=<span style="color:#009900">"com.cad.struts2.Hello"</span> method=<span style="color:#009900">"{1}"</span>>
<<span style="color:#009900">result</span> name=<span style="color:#009900">"success"</span>>/{<span style="color:#006666">1</span>}.jsp</<span style="color:#009900">result</span>>
<<span style="color:#009900">result</span> name=<span style="color:#009900">"error"</span>>/<span style="color:#000088">error</span>.jsp</<span style="color:#009900">result</span>>
</action>
</package> </code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
action的name中可以使用通配符 * , * 可以匹配所有的action, * 的值为传入的action名字,例如传入了addUser.action,那么 * 的值就为addUser。method属性中可以使用表达式来获取 * 的值,{第几个*}
例如 ” * _ * “,我们传递add_User,那么{1}的值就是add,{2}的值就是User。
动态方法调用
<span style="color:#000000"><code>使用动态调用前要先将动态调用的常量更改成<span style="color:#009900">true</span>,动态调用默认是<span style="color:#009900">false</span>,因为不安全。
<<span style="color:#4f4f4f">constant</span> name=<span style="color:#009900">"struts.enable.DynamicMethodInvocation"</span> <span style="color:#4f4f4f">value</span>=<span style="color:#009900">"true"</span>></<span style="color:#4f4f4f">constant</span>>
我们使用动态方法调用我们需要的方法。
格式 :动作名称!方法名称</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
<span style="color:#000000"><code>我们配置struts.xml文件 ,不写method值,也不用通配符
<package name=<span style="color:#009900">"demo"</span> extends=<span style="color:#009900">"struts-default"</span>>
<action name=<span style="color:#009900">"user"</span> class=<span style="color:#009900">"com.cad.struts2.Hello"</span> >
<<span style="color:#009900">result</span> name=<span style="color:#009900">"success"</span>>/welcome.jsp</<span style="color:#009900">result</span>>
<<span style="color:#009900">result</span> name=<span style="color:#009900">"error"</span>>/<span style="color:#000088">error</span>.jsp</<span style="color:#009900">result</span>>
</action>
</package> </code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
<span style="color:#000000"><code>我们更改jsp页面按照动态方法调用的格式,就可以调用相关的方法。
<span style="color:#006666"><<span style="color:#4f4f4f">body</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">a</span> <span style="color:#4f4f4f">href</span>=<span style="color:#009900">"${pageContext.request.contextPath }/user!addUser"</span>></span>添加用户<span style="color:#006666"></<span style="color:#4f4f4f">a</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">a</span> <span style="color:#4f4f4f">href</span>=<span style="color:#009900">"${pageContext.request.contextPath }/user!updateUser"</span>></span>修改用户<span style="color:#006666"></<span style="color:#4f4f4f">a</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">a</span> <span style="color:#4f4f4f">href</span>=<span style="color:#009900">"${pageContext.request.contextPath }/user!selectUser"</span>></span>查看用户<span style="color:#006666"></<span style="color:#4f4f4f">a</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">a</span> <span style="color:#4f4f4f">href</span>=<span style="color:#009900">"${pageContext.request.contextPath }/user!deleteUser"</span>></span>删除用户<span style="color:#006666"></<span style="color:#4f4f4f">a</span>></span>
<span style="color:#006666"></<span style="color:#4f4f4f">body</span>></span> </code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
管理处理结果
<span style="color:#000000"><code>当Action处理完用户请求时,处理结果应该通过视图资源实现,但将哪个视图呈现给浏览者呢。由<result.../>来决定
Action处理完用户请求后,返回一个普通字符串。整个普通字符串就是一个逻辑视图名。
通过配置文件将逻辑视图和物理视图联系起来。一旦系统收到Action返回的逻辑视图名,就把对应的物理视图呈现给浏览者。
struts2支持多种视图技术。当一个Action处理用户请求后,仅仅返回一个字符串,这个字符串只是逻辑视图名
逻辑视图名可以和很多视图资源关联。例如 JSP,FreeMarker等
</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
结果类型。
比如我们逻辑视图名是success,对应success.jsp,那么我们是请求转发到该页面还是重定向呢。这就需要我们指定结果类型。struts2提供了一系列的内置结果类型,在struts-default.xml中能看到。
<span style="color:#000000"><code><result../>属性
name:逻辑视图名称,应该与Action返回的字符串相同,如果不填写,默认为success
type:结果视图类型,不写的时候默认值为dispatcher(请求转发)
name是去哪里,type是怎么去。
</code></span>
- 1
- 2
- 3
- 4
- 5
struts内建支持的常用结果类型
<span style="color:#000000"><code> -chain:Action链式处理。当一个Action处理完成之后,系统并不想转发到视图资源,而是希望下一个Action进行处理,此时就需要这个类型。
-dispatcher:请求转发
-redirect:重定向
-redirectAction:重定向到其他Action
-stream:向浏览器返回一个InputStream的结果类型(一般用于文件下载)
</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Chain例子
<span style="color:#000000"><code>struts.xml文件配置
当发送请求demo1时,返回的结果转发到demo2的Action处理
<package name=<span style="color:#009900">"demo"</span> extends=<span style="color:#009900">"struts-default"</span>>
<action name=<span style="color:#009900">"demo1"</span> class=<span style="color:#009900">"com.cad.struts2.Hello"</span> >
<<span style="color:#009900">result</span> type=<span style="color:#009900">"chain"</span>>demo2</<span style="color:#009900">result</span>>
</action>
<action name=<span style="color:#009900">"demo2"</span> >
<<span style="color:#009900">result</span> name=<span style="color:#009900">"success"</span> >/welcome.jsp</<span style="color:#009900">result</span>>
<<span style="color:#009900">result</span> name=<span style="color:#009900">"error"</span>>/<span style="color:#000088">error</span>.jsp</<span style="color:#009900">result</span>>
</action>
</package> </code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
不同包之间的请求转发
<span style="color:#000000"><code><span style="color:#006666"><<span style="color:#4f4f4f">package</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"demo"</span> <span style="color:#4f4f4f">extends</span>=<span style="color:#009900">"struts-default"</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">action</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"demo1"</span> <span style="color:#4f4f4f">class</span>=<span style="color:#009900">"com.cad.struts2.Hello"</span> ></span>
<span style="color:#006666"><<span style="color:#4f4f4f">result</span> <span style="color:#4f4f4f">type</span>=<span style="color:#009900">"chain"</span>></span>
//因为结果类型都有对应的实现类,我们到请求转发的实现类中发现,有actionName和namespace两个参数,并提供了get和set方法
//使用的是注入的思想,在请求转发之前,先调用setNamespace和setActionName赋值
<span style="color:#006666"><<span style="color:#4f4f4f">param</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"actionName"</span>></span>demo2<span style="color:#006666"></<span style="color:#4f4f4f">param</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">param</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"namespace"</span>></span>/user<span style="color:#006666"></<span style="color:#4f4f4f">param</span>></span>
<span style="color:#006666"></<span style="color:#4f4f4f">result</span>></span>
<span style="color:#006666"></<span style="color:#4f4f4f">action</span>></span>
<span style="color:#006666"></<span style="color:#4f4f4f">package</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">package</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"demo1"</span> <span style="color:#4f4f4f">extends</span>=<span style="color:#009900">"struts-default"</span> <span style="color:#4f4f4f">namespace</span>=<span style="color:#009900">"/user"</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">action</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"demo2"</span> ></span>
<span style="color:#006666"><<span style="color:#4f4f4f">result</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"success"</span> ></span>/welcome.jsp<span style="color:#006666"></<span style="color:#4f4f4f">result</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">result</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"error"</span>></span>/error.jsp<span style="color:#006666"></<span style="color:#4f4f4f">result</span>></span>
<span style="color:#006666"></<span style="color:#4f4f4f">action</span>></span>
<span style="color:#006666"></<span style="color:#4f4f4f">package</span>></span>
重定向也是一样。 </code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
自定义结果类型
<span style="color:#000000"><code>需要实现一个结果类型类,继承StrutsResultSupport类
我们这里面使用我们的验证码小工具,输出一个验证码
至于这个验证码小工具,以前的文章中有详细的说明。
<span style="color:#000088">public</span> <span style="color:#000088">class</span> <span style="color:#4f4f4f">VcodeResult</span> <span style="color:#000088">extends</span> <span style="color:#4f4f4f">StrutsResultSupport</span> {
<span style="color:#9b859d">@Override</span>
<span style="color:#000088">protected</span> <span style="color:#000088">void</span> <span style="color:#009900">doExecute</span>(String arg0, ActionInvocation arg1) <span style="color:#000088">throws</span> Exception {
VerifiCode v=<span style="color:#000088">new</span> VerifiCode();
HttpServletResponse response=ServletActionContext.getResponse();
BufferedImage b=v.getImage();
v.output(b, response.getOutputStream());
}
}</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
<span style="color:#000000"><code> 然后再创建一个Action类 ,什么都不用写
<span style="color:#000088">public</span> <span style="color:#000088">class</span> <span style="color:#4f4f4f">VcodeAction</span> <span style="color:#000088">extends</span> <span style="color:#4f4f4f">ActionSupport</span> {
} </code></span>
- 1
- 2
- 3
- 4
<span style="color:#000000"><code>
在struts.xml中进行配置
<span style="color:#006666"><<span style="color:#4f4f4f">package</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"vcode"</span> <span style="color:#4f4f4f">extends</span>=<span style="color:#009900">"struts-default"</span> ></span>
//配置我们自定义的结果类型
<span style="color:#006666"><<span style="color:#4f4f4f">result-types</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">result-type</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"vcode"</span> <span style="color:#4f4f4f">class</span>=<span style="color:#009900">"com.cad.struts2.VcodeResult"</span>></span><span style="color:#006666"></<span style="color:#4f4f4f">result-type</span>></span>
<span style="color:#006666"></<span style="color:#4f4f4f">result-types</span>></span>
//我们还是在我们的原页面,所以不需要指定其他页面,type即为我们的自定义结果类型
<span style="color:#006666"><<span style="color:#4f4f4f">action</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"vcode"</span> <span style="color:#4f4f4f">class</span>=<span style="color:#009900">"com.cad.struts2.VcodeAction"</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">result</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"success"</span> <span style="color:#4f4f4f">type</span>=<span style="color:#009900">"vcode"</span>></span><span style="color:#006666"></<span style="color:#4f4f4f">result</span>></span>
<span style="color:#006666"></<span style="color:#4f4f4f">action</span>></span>
<span style="color:#006666"></<span style="color:#4f4f4f">package</span>></span> </code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
<span style="color:#000000"><code> 我们可以在自定义的结果类型类中添加<span style="color:#000088">get</span>和<span style="color:#000088">set</span>方法,来方便我们的一些参数自定义。
例如我们添加了weight,height的<span style="color:#000088">get</span>和<span style="color:#000088">set</span>方法。
<action name=<span style="color:#009900">"vcode"</span> class=<span style="color:#009900">"com.cad.struts2.VcodeAction"</span>>
<<span style="color:#009900">result</span> name=<span style="color:#009900">"success"</span> type=<span style="color:#009900">"vcode"</span>>
<param name=<span style="color:#009900">"weight"</span>><span style="color:#006666">100</span></param>
<param name=<span style="color:#009900">"height"</span>><span style="color:#006666">100</span></param>
</<span style="color:#009900">result</span>>
</action>
我们就可以自定义验证码的长宽等。这也又体现了我们的注入思想。
我们前面请求转发前设置nameSpace和actionName和我们做的其实是相同的操作。</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
全局结果视图和局部结果视图
<span style="color:#000000"><code>我们在包中定义了自己的结果类型,只有在自己的包或者子包中才能使用,在别的包中还是无法使用这个结果类型,为了所有的Action都能使用,我们需要将其变为全局。
我们只需要定义一个包,继承struts2的默认配置文件
<span style="color:#006666"><<span style="color:#4f4f4f">package</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"myresult"</span> <span style="color:#4f4f4f">extends</span>=<span style="color:#009900">"struts-default"</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">result-types</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">result-type</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"vcode"</span> <span style="color:#4f4f4f">class</span>=<span style="color:#009900">"com.cad.struts2.VcodeResult"</span>></span><span style="color:#006666"></<span style="color:#4f4f4f">result-type</span>></span>
<span style="color:#006666"></<span style="color:#4f4f4f">result-types</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">global-results</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">result</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">param</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"weight"</span>></span>500<span style="color:#006666"></<span style="color:#4f4f4f">param</span>></span>
<span style="color:#006666"><<span style="color:#4f4f4f">param</span> <span style="color:#4f4f4f">name</span>=<span style="color:#009900">"height"</span>></span>1000<span style="color:#006666"></<span style="color:#4f4f4f">param</span>></span>
<span style="color:#006666"></<span style="color:#4f4f4f">result</span>></span>
<span style="color:#006666"></<span style="color:#4f4f4f">global-results</span>></span>
<span style="color:#006666"></<span style="color:#4f4f4f">package</span>></span>
然后如果我们需要这个结果类型,只需要我们的包继承这个包即可。
在<span style="color:#006666"><<span style="color:#4f4f4f">global-results</span>></span>中配置全局参数,所有的action使用这个类型生成的验证码尺寸都一样。
</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
Action访问Servlet API
<span style="color:#000000"><code>第一种方式
Struts2提供了一个ServletActionContext对象可以访问ServletAPI。
例如
HttpServletRequest request=ServletActionContext<span style="color:#009900">.getRequest</span>()<span style="color:#880000">;</span>
HttpServletResponse response=ServletActionContext<span style="color:#009900">.getResponse</span>()<span style="color:#880000">;</span>
ServletContext context=ServletActionContext<span style="color:#009900">.getServletContext</span>()<span style="color:#880000">;</span>
HttpSession session=request<span style="color:#009900">.getSession</span>()<span style="color:#880000">; </span>
</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
<span style="color:#000000"><code>第二种方式,实现ServletContextAware,ServletRequestAware,ServletResponseAware三个接口
<span style="color:#000088">public</span> <span style="color:#000088">class</span> <span style="color:#4f4f4f">VcodeAction</span> <span style="color:#000088">extends</span> <span style="color:#4f4f4f">ActionSupport</span> <span style="color:#000088">implements</span> <span style="color:#4f4f4f">ServletContextAware</span>,<span style="color:#4f4f4f">ServletRequestAware</span>,<span style="color:#4f4f4f">ServletResponseAware</span> {
<span style="color:#880000">//定义三个参数</span>
<span style="color:#000088">private</span> HttpServletRequest request;
<span style="color:#000088">private</span> HttpServletResponse response;
<span style="color:#000088">private</span> ServletContext context;
<span style="color:#000088">public</span> String <span style="color:#009900">execute</span>() <span style="color:#000088">throws</span> Exception {
<span style="color:#000088">return</span> <span style="color:#000088">null</span>;
}
<span style="color:#880000">//实现接口中设置参数的方法</span>
<span style="color:#9b859d">@Override</span>
<span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">setServletResponse</span>(HttpServletResponse response) {
<span style="color:#000088">this</span>.response=response;
}
<span style="color:#9b859d">@Override</span>
<span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">setServletRequest</span>(HttpServletRequest request) {
<span style="color:#000088">this</span>.request=request;
}
<span style="color:#9b859d">@Override</span>
<span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">setServletContext</span>(ServletContext context) {
<span style="color:#000088">this</span>.context=context;
}
}
执行流程是什么,谁调用了set方法?
struts的内建拦截器有一个ServletConfig的拦截器。
它会先得到我们的动作类的引用,
然后通过<span style="color:#000088">instanceof</span>方法判断我们动作类是否属于ServletContextAware,ServletRequestAware,ServletResponseAware类型
因为我们实现了这个接口,当然属于这个类型
然后获取request,response等
然后调用我们动作类实现的接口方法 setServletResponse,setServletRequest,setServletContext等为我们的request,response赋值。
</code></span>