Struts2
一、struts2的执行流程
先来了解一下struts1的执行流程:
Struts1运行原理:(了解)
Struts1运行原理:Struts1工作流程:
(1)客户端向Web应用发送请求,请求被核心控制器ActionServlet拦截;
(2)ActionServlet根据请求决定是调用业务逻辑控制器还是将请求转发给相应JSP页面;
(3)若调用业务逻辑控制器,则业务逻辑控制器再调用相应的模型来处理用户的请求;
(4)处理的结果再通过JSP呈现给用户
Struts1缺点:
(1)Struts1仅支持JSP作为表现层技术
(2)在Model2的基础上发展得来,完全基于Servlet API,与Servlet API严重耦合,一旦脱离Web服务器,Action的测试将变得非常困难
(3)Action类必须继承其提供的Action基类,实现处理方法时又必须使用Struts1的专有API,这种入侵式设计的最大弱点在于:一旦系统需要重构,这些Action类将没有价值。
Struts2结合Webwork的优势:
(1)Struts2支持更多表现层技术,有更好的适应性。
(2)Action无须跟Servlet API耦合,使得测试更加容易,同时提高代码重用性;而且不耦合任何Servlet API(拦截器机制)
(3)Struts2具有更好的模块化和可扩展性(插件机制)。
Struts2的工作流程:
Struts2是以WebWork为核心,采用拦截器机制对用户的请求进行处理
工作流程:
Struts2执行流程图(1)客户端浏览器发送HTTP请求到Web应用
(2)Web容器将请求传递到标准ActionContextCleanUp过滤器以消除属性,而不让后续过滤器清楚,以延长Action中属性(包括自定义属性)的生命周期。
(3)再经过如stimesh等其他过滤器后,请求传递给StrutsPrepareAndExecuteFilter核心控制器
(4)StrutsPrepareAndExecuteFilter调用ActionMapper(Action映射器)确定调用哪个Action,再将控制权转移给ActionProxy代理
(5)ActionProxy代理调用配置管理器ConfigurationManager从配置文件struts.xml中读取配置信息,然后创建ActionInvocation对象
(6)ActionInvocation在调用拦截器链中的拦截器后再调用Action,根据Action返回的结果字符串查找对应的Result
(7)Result调用视图模板,再以相反的顺序执行拦截器链,返回HTTP响应
(8)HTTP响应以相反的顺序返回给核心控制器StrutsPrepareAndExecuteFilter以及其他web.xml中定义的过滤器,最终返回给客户端
或:
(1)客户端初始化一个指向Servlet容器(例如Tomcat)的请求
(2)这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin);
(3)接着StrutsPrepareAndExecuteFilter被调用,StrutsPrepareAndExecuteFilter询问ActionMapper来决定这个请求是否需要调用某个Action;
(4)如果ActionMapper决定需要调用某个Action,StrutsPrepareAndExecuteFilter把请求的处理交给ActionProxy;
(5)ActionProxy通过ConfigurationManager询问框架的配置文件,找到需要调用的Action类;
(6)ActionProxy创建一个ActionInvocation的实例。
(7)ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。
(8)一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以使用Struts2框架中继承的标签。在这个过程中需要涉及到ActionMapper。
Struts2核心组件介绍:
ActionMapper:通过method参数将请求转发到具体的action
ActionProxy代理:是Action的一个代理类,也就是说Action的调用是通过ActionProxy实现的,其实就是调用了ActionProxy.execute()方法,而该方法又调用了ActionInvocation.invoke()方法。归根到底,最后调用的是DefaultActionInvocation.invokeAction()方法。
ActionInvocation:就是Action的调用者。ActionInvocation在Action的执行过程中,负责Interceptor、Action和Result等一系列元素的调度。
Interceptor拦截器:是Struts 2的一个强有力的工具,有许多功能(feature)都是构建于它之上,如国际化、校验等。
二、介绍一下struts2(扯皮)
Struts2是一个基于MVC设计模式的Web应用框架(Apache公司的,Apache公司的还有Tomcat),它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。Struts 2是Struts的下一代产品,是在 struts 1和WebWork的技术基础上进行了合并的全新的Struts 2框架。其全新的Struts 2的体系结构与Struts 1的体系结构差别巨大。Struts 2以WebWork为核心,采用拦截器的机制来处理用户的请求,这样的设计也使得业务逻辑控制器能够与ServletAPI完全脱离开,所以Struts 2可以理解为WebWork的更新产品。虽然从Struts 1到Struts 2有着太大的变化,但是相对于WebWork,Struts 2的变化很小。
优势:
1.自动封装参数
2.参数的校验(配置)
3.结果的处理(转发|重定向)
4.国际化
5.解耦servlet
6.更好的支持MVC
7.防止表单的重复提交
三、使用struts2的准备工作
1、导入相对应的jar包 (struts2中的lib下的jar包);
2、在web.xml内进行配置filter(只有配置了filter才可以使用struts2框架)进行配置 StrutsPrepareAndExecuteFilter;所有的请求都被过滤器过滤到struts的配置文件中去。
web.xml文件3、配置我们的struts.xml文件 (放于根目录下) (可以在struts的zip包中 抽出出来struts.xml文件 然后自己进行修改)
struts.xml文件4、创建相应的action进行操作;
Action类流程:当我们发送请求的时候,会被我们在web.xml中配置的拦截器进行拦截 会根据请求的路径在struts.xml中进行判断,在根据所对应的method执行性对应的方法.
四、struts.xml的配置信息
struts.xml文件配置剖析:
package:
name : 包名, 必须唯一
namespace: 主要去action中的name属性进行联合,来确定一个action的访问路径
extend:指定继承于哪个包,一般都是 struts-default(当是ajax返回一个json数据的时候,就是json-default包)
abstruct:代表当前包是一个抽象包
action:
name: 与package中的namespace进行联合
class:指示当前的action类
method:指示当前类中的指定执行方法的执行方案
result:
name:与action中的返回值进行匹配 来确定要跳转的路径
type:指定我们当前的要跳转的跳转方式
result的name属性默认值是success,
默认的跳转方式是请求转发 dispatcher
五、在struts2中定义常量的方式
方式一:通过struts.xml配置文件,直接在struts.xml文件中配置(推荐)
方式一注:后加载的配置常量会将先加载的配置常量进行覆盖
方式二:通过struts.properties文件。新建一个struts.properties文件,与struts.xml同级,会自动加载这个文件,里面的key,value能够修改常量,但是struts加载这些文件的顺序一定:通常,Struts2框架按照如下搜索顺序加载Struts2常量。
⑴ struts-default.xml
⑵ struts-plugin.xml
⑶ struts.xml
⑷ struts.properties
⑸ web.xml
方式三:通过Web应用的web.xml文件。
当我们在web.xml文件中配置StrutsPrepareAndExecuteFilter时也可配置Struts2常量,此时采用为StrutsPrepareAndExecuteFilter配置初始化参数的方式来配置Struts2常量,如下所示:
六、Action的创建
1、创建Action的方式:
(1)、创建POJO
(2)、实现Action接口
(3)、继承ActionSupport(一般使用这个)//具有丰富的功能,不过耦合性比较高
七、Struts2的封装数据
1.属性驱动 :在Action里面建立属性,写上get,set,属性名对应表单提交的字段名 支持类型:支持我们基本的八大数据类型以及其包装类和特定字符的转String
2.对象驱动 :创建对象属性,写上get,set,属性对应实体,表单里的字段要为属性.字段
3.模型驱动 :action要实现ModelDriven 接口,创建对象属性的实例,并在getModel方法里返回,表单中保持原有提交字段名(//缺点:只能对一个模型进行实例化
步骤1.action实现modelDriven<类名> 接口
步骤2.实例化模型(new )
步骤3.重写getModel方法,并将我们实例的对象进行返回
)
附图解释:
三种封装数据的图解八、struts2中获取servletAPI
1.ServletActionContext进行获取
一般使用这个2.采用注入方式 :
ServletRequestAware,实现这个接口可以获取HttpServletRequest
ServletResponseAware ,实现这个接口可以获取HttpServletResponse
ServletContextAware实现这个接口可以获取ServletContext
九、OGNL表达式
OGNL作用:
(1)、支持对象的操作,调用对象的方法
(2)、支持静态成员访问
(3)、支持赋值操作与表达串联
(4)、访问OGNL上下文,访问ActionContext
(5)、操作集合对象
三要素:
(1)、表达式
(2)、ognlContext上下文new OgnlContext()
(3)、root根
获取数据
在root根中获取数据时 ,ognl表达式前不需要加 #, 如果不是在root根中进行获取数据,则需要添加 #
使用ognl
在struts2中可以使用ognl+valueStack可以实现在页面上获取数据
在页面中进行配置
<%@ taglib prefix="s" uri=" /struts-tags" %>
<s:property value=”表达式”>来使用
十、valueStack
valuestack的使用的主要目的是为了将action中产生的数据传递到页面上
struts2中的action是多例的,每一次请求都会创建一个action,一个valuestack对应一个action,valuesta贯穿整个action的生命周期
struts2框架将valuestack保存在 request中
主要由两部分组成:
CompoundRoot: 是一个list 主要存储的是action的相关数据
Map<String,Object> context: 是一个map集合 主要引用web开发中的相关信息
获取valuestack中的数据
根据ognl表达式进行获取数据 如果前面添加# 在context中进行查找,如果没有添加# ,代表在CompoundRoot中进行获取数据,也就是所说的root中.
1.直接通过request对象进行获取 //因为valuestack存于request中
servletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY)
2.使用actionContext进行获取
ActionContext.getContext().getValueStack();
ActionContext是action的上下文,struts2框架使用actionContext进行保存action在执行过程中所需要的一些对象
Struts2会根据每一次的http请求来创建对应的ActionContext,它是与当前线程绑定的。
每一次请求,就是一个线程,对应着一个request,每一次请求,会创建一个Action,每一个action对应一个ActionContext.每一次请求也对应着一个valueStack.
request---ActionContext----Action-----ValueStaci它们都对应着一次请求(一个线程).
valueStack与ActionContext本质上是可以获取
存储数据
//主要向root中进行存储
1.手动存储
valueStack.set("key","value")
valueStack.push()
2.自动存储
3.声明成员变量 提供get方法 为了使用属性封装也提供set方法
获取数据
在标签中可以通过 value="key" 或 value="[index].top"
底层是栈. 先进后出
在action中的属性的get方法中 也可以将数据返回
使用模型驱动
在访问路径添加属性的赋值
使用el表达式也可以获取数据 struts2 对 request 里面的 getattribute方法进行了增强
//个人理解: 如果对数据提供了get/set方法 那么就相当于属性存储,要使用ognl进行获取时,应该使用 对象名.属性名 进行获取
传递数据前提:继承了actionsupport
struts.xml文件中,用来传递数据 (在重定向中) : 错误显示标签
在struts2中处理简单的信息 (字符串)this.addActionError
this.addFieldErrorthis.addActionMessage
十一、Interceptor拦截器
主要的作用是为了拦截 action 的操作,在action的执行前后进行一些我们想要做的操作
自定义拦截器
1.在配置文件中 声明 interceptor
2.创建一个类实现 interceptor接口
3.在action中使用interceptor ,action必须继承actionsupport
4.在action的配置中,引入自定义 interceptor
interceptor指定拦截action
Interceptor的放行: return invocation.invoke();
在我们的配置文件中的interceptor里面
<param name="includeMethods">方法名
<param name="encludeMethods">方法名
十二、文件上传
单文件上传:
多文件上传:
jsp页面 web.xml文件 struts.xml文件 Action类详细见:https://www.cnblogs.com/wkrbky/p/5904787.html
www.cnblogs.com/solverpeng/p/5613727.html
十三、文件下载
http://www.cnblogs.com/solverpeng/p/5613738.html
十四、表单的重复提交