1、struts2工做原理(网友总结,千遍一概)java
1 客户端初始化一个指向Servlet容器(例如Tomcat)的请求
2 这个请求通过一系列的过滤器(Filter)(这些过滤器中有一个叫作ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其余框架的集成颇有帮助,例如:SiteMesh Plugin)
3 接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请是否须要调用某个Action
4 若是ActionMapper决定须要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy
5 ActionProxy经过Configuration Manager询问框架的配置文件,找到须要调用的Action类
6 ActionProxy建立一个ActionInvocation的实例。
7 ActionInvocation实例使用命名模式来调用,在调用Action的过程先后,涉及到相关拦截器(Intercepter)的调用。
8 一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果一般是(但不老是,也可 能是另外的一个Action链)一个须要被表示的JSP或者FreeMarker的模版。在表示的过程当中可使用Struts2 框架中继承的标签。在这个过程当中须要涉及到ActionMapper
在上述过程当中全部的对象(Action,Results,Interceptors,等)都是经过ObjectFactory来建立的。程序员
2、struts2基本配置web
2.1 struts.xml配置文件详解spring
<struts> <!-- 开发模式下使用,打印更多详细错误信息 --> <constant name="struts.devMode" value="true" /> <!-- 国际化 --> <constant name="struts.i18n.encoding" value="UTF-8"/> <!-- 容许ognl访问静态方法 --> <constant name="struts.ognl.allowStaticMethodAccess" value="true" /> <!-- 该属性指定须要struts2处理的请求后缀,默认值是action,即,全部匹配*.action的请求 都由struts2处理,若是用户须要指定多个请求后缀,则多个后缀之间以英文逗号","隔开 --> <constant name="struts.action.extension" value="action"/> <!-- 设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭 --> <constant name="struts.serve.static.browserCache" value="false"/> <!-- 当struts的配置文件修改后,系统是否自动从新加载该文件,默认值false:不从新加载 --> <constant name="struts.configuration.xml.reload" value="true"/> <!-- 默认的视图主题 --> <constant name="struts.ui.theme" value="simple"/> <!-- 与spring集成时,指定由spring负责管理action对象的建立 --> <constant name="struts.objectFactory" value="spring"/> <!-- 该属性设置struts2是否支持动态方法调用,默认值true:支持 --> <constant name="struts.enable.DynamicMethodInvocation" value="false"/> <!-- 上传文件的大小限制 --> <constant name="struts.multipart.maxSize" value="10701096"/> <!-- 引入文件 --> <include file="cn/qjc/action/login/login.xml"></include> <include file="cn/qjc/action/demo/demo01.xml"></include> <include file="cn/qjc/interceptor/interceptor.xml"></include> </struts>
struts2配置文件加载顺序apache
a、default.properties:struts2-core**.jar org.apache.struts包中(程序员只能看)浏览器
b、struts-default.xml:struts2-core**.jar中(程序员只能看)缓存
c、struts-plugin.xml:在插件的jar包中(程序员只能看)安全
d、struts.xml:在应用的构建路径顶端。本身定义的Struts配置文件(推荐)app
e、struts.properties:在应用的构建路径顶端。程序员能够编写(不推荐)框架
f、web.xml:配置过滤器时,指定参数。程序员能够编写(不推荐)
特别注意:顺序是固定的。后面的配置会覆盖前面的同名配置信息。
加载struts.xml过程
说明:
一、 在启动的时候加载了三个配置文件 struts-default.xml、struts-plugin.xml、struts.xml
二、 若是这三个文件有相同的项,后面覆盖前面的。
三、 struts.xml文件必须放在src下才能找到。
2.2 package元素
意义:分模块开发
属性:
name:必须的。配置文件中要惟一。就是一个名字。
extends:指定父包。会把父包中的配置内容继承下来。通常须要直接或间接的继承一个叫作“struts-default”的包(在struts-default.xml配置文件中)。
若是不继承该包,那么Struts2中的核心功能将没法使用。
abstract:是不是抽象包。没有任何action子元素的package能够声明为抽象包。
namespace:指定名称空间。通常以”/”开头。该包中的动做访问路径:namesapce+动做名称。若是namespace=””,这是默认名称空间,和不写该属性是同样的。
2.3 action配置
做用:定义一个动做。
属性:
name:必须的。动做名称。用户用于发起请求。在包中要惟一。
class:指定动做类的全名。框架会经过反射机制实例化。默认是:com.opensymphony.xwork2.ActionSupport。
method:指定动做类中的动做方法。框架会执行该方法。默认是execute()。
<!-- 配置全局视图:访问动做时没有局部视图,则找全局视图 --> <package name="default" extends="struts-default" abstract="true"> <global-results> <result name="success">/WEB-INF/login/success.jsp</result> </global-results> </package> <package name="login" namespace="/user" extends="default"> <action name="login" class="cn.qjc.action.login.Login" method="login"> <!-- type默认dispatcher 表示请求转发 --> <result name="success" type="dispatcher">/WEB-INF/login/success.jsp</result> <result name="error">/WEB-INF/login/error.jsp</result> </action> </package>
3、动做类(Action类)
3.1 编写动做类的三种方式:
a、POJO(Plain Old Java Object)普通的JavaBean。
/** * 编写动做类方式一:普通javaBean * @author qjc */ public class Demo1Action { public String seyHello(){ System.out.println("动做类执行了"); return "success"; } }
b、实现com.opensymphony.xwork2.Action接口
/** * 编写动做类方式二:实现Aaction接口 * @author qjc */ public class Demo2Action implements Action{ @Override public String execute() throws Exception { System.out.println("动做类执行了"); return SUCCESS; } }
c、继承com.opensymphony.xwork2.ActionSupport(推荐)
意义:提供了一些基本的功能。好比验证和国际化消息提示等。
/** * 编写动做类方式三:继承ActionSupport类 * @author qjc */ public class Demo3Action extends ActionSupport{ }
3.2 ActionSupport用法
在struts框架中,准备了一个ActionSupport类,源码分析:
代码段一:
public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable {
代码段二:
/** * A default implementation that does nothing an returns "success". * <p/> ActionSupport是一个默认的Action实现,可是只返回了一个字符串success * Subclasses should override this method to provide their business logic. * <p/>子类须要从新覆盖整个方法,在这个方法中写相应的逻辑 * See also {@link com.opensymphony.xwork2.Action#execute()}. * * @return returns {@link #SUCCESS} * @throws Exception can be thrown by subclasses. */ public String execute() throws Exception { return SUCCESS; }
代码段三:
public static final String SUCCESS = "success";
说明:
一、代码段一说明了ActionSupport也实现了Action接口(之前写的类实现了Action接口)
二、代码段二说明若是程序员写本身的action继承了ActionSupport,须要从新覆盖execute方法便可。
三、这个方法默认的返回的是success;
因此在配置文件中也能够这样写:
<action name="actionSupprotAction"> <result name="success">/baseconfig/successActionSupport.jsp</result> </action>
能够看到action标签中没有class属性,在struts-default.xml中,
<default-class-ref class="com.opensymphony.xwork2.ActionSupport" />
说明:
若是在action标签中没有写class属性。那么根据上述的配置文件,struts2会启用ActionSupport这个类。因此action标签中的class属性能够不写。
4、结果类型
一、 每一个action方法都返回一个String类型的值,struts一次请求返回什么值是由这个值肯定的。
二、 在配置文件中,每个action元素的配置都必须有result元素,每个result对应一个action的返回值。
三、 Result有两个属性:
name:结果的名字,和action中的返回值同样,默认值为success;
type:响应结果类型,默认值为dispatcher.
在struts-default.xml文件中,以下面所示
<result-types> <result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/> <result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/> <result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/> <result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/> <result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/> <result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/> <result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/> <result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/> <result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/> <result-type name="plainText"
说明:
一、 从上述能够看出总共10种类型
二、 默认类型为ServletDispatcherResult即转发。
三、 结果类型能够是这10种结果类型的任意一种。
4.1 dispatcher类型:
dispatcher类型是最经常使用的结果类型,也是struts框架默认的结果类型。
在配置文件中,能够有两种写法:
第一种写法: <result name="success">/resulttype/successDispatcher.jsp</result> 第二种写法: <result name="success"> <param name="location">/resulttype/successDispatcher.jsp</param> </result>
下面的图说明了location的来历:
4.2 redirect类型:
这种结果类型与dispatcher类型相对,dispatcher结果类型是将请求forwsrd(转发)到指定的JSP资源;而redirect结果类型,则意味着将请求redirect(重定向)到指定的视图资源。
redirect与dispatcher差异主要是转发和重定向的差异:重定向会丢失全部的请求参数、请求属性,固然也丢失Action处理结果。
注意:
使用redirect类型的结果时,不能重定向到/WEB-INF/路径下任何资源,由于重定向至关于从新发送请求,而Web应用的WEB-INF/路径是受保护的。
4.3 redirectAction类型:
这种结果类型与redirect类型很是类似,同样是从新生成一个全新请求,但与redirect区别在于:redirectAction使用ActionMapperFactory提供的ActionMapper来重定向求情。
即:把结果类型从新定向到action。
能够接受两种参数
a) actionName: action的名字
b) namespace:命名空间
第一种方式
<result name="success" type="redirectAction">resulttype/redirectactionAction.action</result>
第二种方式
<result name="success" type="redirectAction"> <!-- actionName: 请求的action的路径 namespace: 若是不写,默认就是请求的action的路径,若是写,路径将被从新赋值 --> <param name="actionName"> resulttype/redirectactionAction.action </param> </result>
4.4 其余类型
freemarker:用于转发到另一个freemarker模板。(页面静态化)
velocity:用于转发到另一个velocity模板。
httpheader:用于输出http协议的消息头。
xslt:XML有关的样式
redirect:用于重定向到另一个JSP页面。
redirectAction:用于重定向到另一个动做。
stream:用于文件下载(往后再讲。文件上传和下载)
plainText:以纯文本的形式展示页面。输出源码。
4.5 自定义类型
自定义结果类型步骤
以随机验证码图片为例
a、编写一个类,直接或间接实现com.opensymphony.xwork2.Result接口。通常继承org.apache.struts2.dispatcher.StrutsResultSupport类
/** * 使用自定义结果集加载验证码 * @author qjc */ public class Demo02 extends StrutsResultSupport{ private int width=120; private int height=80; private int codeCount=4; private int lineCount=100; @Override protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception { //输出结果便可 ValidateCode vc = new ValidateCode(width, height, codeCount, lineCount); BufferedImage image = vc.getBuffImg(); //输出便可 HttpServletResponse response = ServletActionContext.getResponse(); ImageIO.write(image, "jpeg", response.getOutputStream()); } //此处省略getter and setter ...
}
b、声明结果类型,而后才能使用
<!--
自定义结果集
--> <package name="p3" extends="struts-default"> <result-types> <!-- 结果类型定义 --> <result-type name="captcha" class="cn.qjc.action.demo.Demo02"></result-type> </result-types> </package>
c、使用
<action name="captcha"> <!--使用自定义结果类型:captcha --> <result name="success" type="captcha"> <param name="width">200</param> </result> </action>
页面编写
<body> <form action="${pageContext.request.contextPath }/user/login.action"> 用户名:<input name="username"><br> 密 码:<input type="password" name="password"><br> 验证码:<input name="code" size="4"> <img src="${pageContext.request.contextPath}/captcha.action"><br> <input type="submit" value="登陆"> </form> </body>
5、Action原型模式
在servlet中,一个servlet只有一个对象,也就是说servlet是单例模式。若是把一个集合写在servlet属性中,则要考虑线程安全的问题。
可是在struts2的框架中,并不存在这种状况,action是多例的。也就是说struts2中的action,只要访问一次就要实例化一个对象。这样就不存在线程安全的问题。这也是struts2框架的一个好处。
能够写一个类,以下:
package cn.qjc.struts2.action.moreinstance; import com.opensymphony.xwork2.ActionSupport; @SuppressWarnings("serial") public class MoreInstanceAction extends ActionSupport{ public MoreInstanceAction(){ System.out.println("create new action"); } public String execute(){ System.out.println("more instance action"); return SUCCESS; } }
配置文件为:
<struts> <package name="moreinstance" namespace="/moreinstance"> <action name="moreinstanceAction" class="cn.qjc.struts2.action.moreinstance.MoreInstanceAction"> </action> </package> </struts>
请求两次http://localhost:8080/struts2/moreinstance/moreinstanceAction.action路径,若是构造函数中的”create new action”输出两次,说明建立了两次对象。