interview-strust2
Struts是什么?
Struts是流行和成熟的基于MVC设计模式的Web应用程序框架。

优点
快速开发
- 自动封装表单提交数据
- 便捷的实现上传文件
- 国际化
- 通过配置完成表单验证
- 强大的标签库
安全
- 安全的线程机制:每个action都是独立的——根据每个请求生成单独的实例。(Jsp的Servlet是单例模式,导致线程不安全)
- 防止数据重复提交:token令牌机制
- 异常处理机制
先进的思路
- 面向切面编程:拦截器
Struts2工作原理及核心文件
工作原理一张图搞定

Struts2核心文件
WEB.xml
任何MVC框架都需要与Web应用整合,这就得依靠一个配置文件。在Struts中,只有配置在web.xml文件中Servlet才会被应用加载。
通常,所有的MVC框架都需要Web应用加载一个核心控制器,对于Struts2而言,需要加载StrutsPrepareAndExecuteFilter,只要Web应用负责加载StrutsPrepareAndExecuteFilter,StrutsPrepareAndExecuteFilter将会加载Struts2框架。
StrutsPrepareAndExecuteFilter 是什么?
来一张图。
那么为什么它被取代了?顾名思义:Struts的准备和执行之间——它能在执行Action之前进行过滤。
struts.xml
该文件包含的内容:
- 全局属性
- 用户请求和相应Action之间的对应关系
- Action可能用到的参数和返回结果
- 各种拦截器的配置
demo:
<!-- include节点是struts2中组件化的方式 可以将每个功能模块独立到一个xml配置文件中 然后用include节点引用-->
<include file="struts-default.xml"></include>
<!-- package提供了将多个Action组织为一个模块的方式
package的名字必须是唯一的package,允许扩展
当一个package扩展自另一个package时候该package会在本身配置的基础上加入扩展的package的配置
父package必须在子package前配置
常见属性:
name:package名称
extends:继承的父package名称
abstract:设置package的属性为抽象的,抽象的package不能定义action值。true:false
namespace:定义package命名空间。该命名空间影响到url的地址,例如此命名空间为/test那么访问的是localhost:8080/projectname/test/xx.action
-->
<package name="com.kay.struts2" extends="struts-default" namespace="/test">
<interceptors>
<!--定义拦截器
name:拦截器名称
class:拦截器类路径
-->
<interceptor name="timer" class="com.kay.timber"></interceptor>
<interceptor name="logger" class="com.kay.logger"></interceptor>
<!--定义拦截器栈-->
<interceptor-stack name="mystack">
<interceptor-ref name="timber"></interceptor-ref>
<interceptor-ref name="logger"></interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 定义默认的拦截器 每个Action都会自动引用。如果Action中引用了其他的拦截器 默认的拦截器将无效-->
<default-interceptor-ref name="mystack"></default-interceptor-ref>
<!--全局results配置-->
<global-results>
<results name="input">/error.jsp</results>
</global-results>
<!--Action配置 一个Action可以被多次映射(只要action配置中的name不同)
name:action名称
class:对应的类的路径
method:调用Action中的方法名
-->
<action name="hello" class="com.kay.struts2.Action.LoginAction">
<!--引用拦截器
name:拦截器名称或拦截器栈名称
-->
<interceptor-ref name="timer"></interceptor-ref>
<!-- 节点配置
name:result名称和Action中返回的值相同
type:result类型。struts-default.xml中默认的dispatcher,用于支持JSP视图技术。你也可以选择别的视图技术。
-->
<result name="success" type="dispatcher">/talk.jsp</result>
<!--子标签设置
name:对应Action中的get/set方法
location:该属性对应了该视图对应的实际视图资源
parse:该参数指定是否可以在实际视图名字中使用OGNL表达式。OGNL全名:Object-Graph Navigation Language。用于获取作用域内的值,可以写在JSP和struts.xml里。
-->
<param name="url">http://www.sina.com</param>
</action>
</package>
你说你的头都看大了?那来个简洁版吧。
<!--引入文件,方便管理-->
<include file="otherXML.xml"></include>
<package name="your.package.yourClass" extends="struts-default" namespace="/test">
<!--定义拦截器。你也可以组成一个拦截器栈-->
<interceptor name="timerName" class="your.package.yourTimerClass"></interceptor>
<!-- 定义默认的拦截器 每个Action都会自动引用。如果Action中引用了其他的拦截器 默认的拦截器将无效-->
<default-interceptor-ref name="mystack"></default-interceptor-ref>
<!--全局results配置。一般写个错误页面什么的-->
<global-results>
<results name="input">/error.jsp</results>
</global-results>
<!--action--定义>
<action name="hello" class="com.kay.struts2.Action.LoginAction">
<!--拦截器引用-->
<interceptor-ref name="timer"></interceptor-ref>
<!-- 节点配置-->
<result name="success" type="dispatcher">/talk.jsp</result>
<!--子标签设置-->
<param name="url">http://www.sina.com</param>
</action>
</package>
struts.properties
struts2框架的全局属性文件,自动加载。该文件包含很多key-value对。该文件完全可以配置在struts.xml文件中,使用constant元素。
#指定默认编码集,对于请求参数带有中文的情况应该设置成GBK或GB2312.默认UTF-8
struts.i18n.encoding=GB2312
#是否每次HTTP请求到达时,都重新加载国际化资源文件,默认值false
struts.i18n.reload=true
#但struts.xml改动后,是否重新加载该文件。在开发阶段建议将该属性设置为"true",提高开发效率,默认值为false
struts.configuration.xml.reload=true
#是否使用Struts2的开发模式,可以获得更多报错信息,便于调试。在开发阶段设置为ture,默认值为false
struts.devMode=true
#设置浏览器是否缓存静态页面,开发阶段设置为false,以后的服务器的最新响应,默认值true
struts.serve.static.browserCache=true
#指定后缀为.action形式的请求可被Struts2处理,可配置多个请求后缀。比如.do .struts2等。配置多个后缀名用逗号隔开
struts.action.extension=action,do,struts2,
#配置服务器运行时的端口号,一般情况下该属性不修改,如果端口号占用则重新分配,默认80
struts.url.http.port = 8080
拦截器
- Struts2大多数核心功能是通过拦截器实现的,每个拦截器完成某项功能。
- 拦截器方法在Action执行之前或者之后执行。
- 拦截器的工作方式和过滤器非常像。可以说是控制器般的存在。
你问我什么是过滤器?呃。。
拦截器栈
- 从结构上看,拦截器相当于多个拦截器的组合。
- 从功能上看,拦截器栈也是拦截器。
如何自定义拦截器
有两种方法
1、实现Interceptor接口
-void init( ):初始化拦截器所需资源
-void destory( ):释放在init( )中分配的资源
-String intercept(ActionInvocation ai)throws Exception
- 实现拦截器功能
- 利用ActionInvocation参数获取Action状态
- 返回result字符串作为逻辑视图
2、继承AbstractInterceptor类
- 提供了init( )和destory( )方法的空实现
- 只需要实现intercept方法即可
Struts2内建拦截器
- params:负责将请求的参数设置为Action属性
- staticParams:将配置文件中action元素的子元素param参数设置为Action属性
- servletConfig:将源于Servlet API的各种对象注入到Action,必须实现对应接口
- fileUpload:对文件上传提供支持,将文件和元数据设置到对应的Action属性
- exception:捕获异常,并且将异常映射到用户自定义的错误页面
- validation:调用验证框架进行数据验证。
我们在没有手工指定拦截器时,已经用了defaultStack拦截器栈。
默认拦截器栈
- 在struts-default.xml中定义一个defaultStack拦截器栈,并将其指定为默认拦截器。
- 只要在定义包的过程中继承struts-default包,那么defaultStack将是默认的拦截器。
- 当为包中的某个action显式指定了某个拦截器,则默认拦截器不会起作用。
- 拦截器栈中的各个拦截器的顺序很重要。
简单操作指南
访问Servlet API
- ActionContext
- 实现***Aware接口
- ServletActionContext
Action的搜索顺序
现有该URL:http://localhost:8080/struts2/path1/path2/path3/dad.action
- 判断package是否存在,如:path1/path2/path3/
- 存在的话。判断action是否存在,如果不存在则去默认namespace的package里面寻找action。如果没有,则报错。
- 不存在的话。检查上一级路径的package是否存在(直到默认namespace),重复第一步。如果没有,则报错。
动态方法调用
解决一个Action对应多个请求的处理,防止Action过多。你可以理解为同一个URL下有不同的方法
- 指定method属性——在action的method指定属性。
- 感叹号方式——在action里面添加多个result。用name指定,访问usr时:localhost/actionName!name.action
- 通配符方式——属于推荐方法。在action的name里添加_*,method中设置通配符。
<action name="dad_* method="{1}" class="your.package.yourAction>
<result>/result.jsp</result>
<result name="add">/{1}.jsp{/result}
<result name="update">/{1}.jsp{/result}
</action>
接受参数
- action属性就是实现javaBean。然后自动提交上去就会被获取——在表单中指定了action"yourActionClassName.action" method="post"
- 面向对象。就是在action里new一个JavaBean。然后getJavaBean、setJavaBean。在表单里得指定JavaBean.属性名。
- 是推荐方法。要在该action里实现一个接口——ModelDriven<T>。不需要get和set方法了。里面的成员变量也直接实例化。
处理结果类型
还记得之前那张struts2工作原理的图吗?在第7步会返回一个String对象。这些String对象来自于com.opensymphony.xwork2.Action
- SUCCESS:Action正确的执行完成,返回相应的视图,success是name属性的默认值
- NONE:表示Action正确的执行完成,但不返回任何试图
- ERROR:表示Action执行失败,返回到错误处理视图
- LOGIN:Action因为用户没有登录的原因没有正确执行,将返回该登录视图,要求用户进行登录验证
- INPUT:Action的执行,需要从前端界面获取参数,INPUT就是代表这个参数输入的界面,一般应用中,会对这些参数进行验证,如果验证没有通过,将自动返回到该视图。
<result name="success">/success.jsp</result>
小Tips
- result元素中name就是result元素的逻辑视图名称。
- 如果省略了name属性,系统将采用默认的name属性值,默认的name值是success。
- 如果省略了斜杠,就是action里的namespace。
网友评论