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

多文件上传:

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

十四、表单的重复提交

www.cnblogs.com/solverpeng/p/5633360.html

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,393评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,790评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,391评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,703评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,613评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,003评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,507评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,158评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,300评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,256评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,274评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,984评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,569评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,662评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,899评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,268评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,840评论 2 339

推荐阅读更多精彩内容