JavaEE--------Struts2框架

一. Struts2框架的概述

    Struts2 是一种基于MVC模式的轻量级Web框架,它自问世以来,就受到了广大Web 开发者的关注,并广泛应用于各种企业系统的开发中。目前掌握Struts2 框架几乎成为Web开发者的必备技能之一。接下来将针对Struts2 的特点、安装以及执行流程等内容进行详细的讲解。

1.1 Struts2 简介

    Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个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 其它WEB层框架

那么,除了Strut2之外,还有哪些优秀的Web层框架呢?常见的WEB层的框架还有Struts1、Webwork、SpringMVC。WEB层框架都有一个特点,就是基于前端控制器模式实现的。

二. Struts2 快速入门

2.1 搭建Struts2 框架

先搭建一个简单的Struts2 框架,具体步骤如下:

2.1.1 导包

1)下载Struts2 的开发包

Struts2 的官网:https://struts.apache.org/  链接

2)解压Struts2 的开发包

3) 创建一个WEB工程,引入相关jar 包

导包,最简单的方法,是找到apps文件夹下后缀为 .war的例子,它们是Struts2的例子,肯定包含Struts2需要的jar 包。比如,将struts2-blank解压,打开解压之后的文件夹找到WEB-INF/lib ,这里面的所有的jar 包就是我们需要导入的包。直接将它们全部复制到我们自己新建的web工程下的lib 目录下就可以了。

2.1.2 书写Action类

在src 下创建一个包cn.itcast.struts2.action,在该包下创建一个Action类,名称为HelloAction 。在这个类中编写一个公有的,返回值为String类型的方法,这个方法的名称叫做execute(),且该方法没有任何参数,因为这个方法最终要被反射执行

public class HelloAction {
	/**
	* 提供一个默认的执行方法:execute()
	*/
    public String execute(){
        System.out.println("hello world!");
        return "success";
    }
}

对于execute()方法,先任意给其一个字符串返回值,比如返回一个success的字符串。这个字符串就作为一个逻辑视图名称

Action类编写好之后,Struts2 框架需要识别出这个类是一个Action,就需要对Action类进行配置。比如上面步骤中的execute()方法返回一个字符串,这个success字符串又怎么能够代表一个页面呢?这时候就需要配置struts.xml对Action进行配置。

2.1.3 在src/struts.xml中配置Action类

接下来,我们需要观察apps 中的示例代码,在WEB-INF的classes 中,有一个名称为struts.xml的文件,这个文件就是Struts2的配置文件。开发中我们需要将struts.xml 文件引入到工程的 src 下,因为 src 下的内容发布到web 服务器中的就是WEB-INF 下的classes 中。将struts.xml 中原有的内容删除掉,再配置上自己编写的Action类就可以了。也可以自己在src下新建一个struts.xml文件,需要自己手动导入约束。导入约束:打开Web App libraries下的strut2-core-2_3_24.jar包,找到dtd后缀的文件,即为约束。打开dtd后缀的文件,比如struts-2.3.dtd,把里面的内容复制到记事本中,再将记事本重命名为struts-2.3.dtd。再在Eclipse中复制一下导包的路径,具体步骤如下面三张图片所示。

需要注意的是,到了Action之后,只会在控制台中输出Action中的内容,而没有实现页面的跳转。而在实际的开发中是需要实现页面跳转的,Action类中的execute()方法中返回了一个字符串类型的返回值,它是一个逻辑视图(逻辑视图:相当于一个真实的页面,只是取了一个别名而已)。所以在配置Action类的时候,也需要对页面的跳转进行配置。然后在相关位置新建一个.jsp页面。代码如下所示,里面具体的标签,会在后面的章节中做具体介绍。

<?xml version="1.0" encoding="UTF-8"
<!DOCTYPE struts PUBLIC
	"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
	"htttp://struts.apache.org/dtds/struts-2.3.dtd"
<struts>
    <!-- 配置一个包: package -->
    <package name="demo1" namespace="/hello" extends="struts-default" >
 	<!-- 配置Action -->
        <action name="HelloAction" class="cn.itcast.struts2.action.HelloAction">
		<!-- 配置结果页面的跳转-->
		<resulet name="success">/hello.jsp</resulet>
        </action>
    </package>
</struts>

这时,需要手动在WEB-INF下新建一个hello.jsp。代码如下:

Action类就已经配置好了。配置好之后还是不能执行的,因为之前我们介绍过,WEB 层的框架都有一个特点就是基于前端控制器的模式,这个前端控制器是由过滤器来实现的,所以我们需要配饰Struts2 的核心过滤器。这个核心过滤器的名称是StrutsPrepareAndExecuteFilter。

2.1.4 将Struts2核心过滤器配置到web.xml

Struts2框架要想执行,所有的请求都需要经过这个前端控制器(核心过滤器),所以需要配置这个核心过滤器。因为这个过滤器完成了框架的部分功能。打开web.xml,在web.xml 中进行如配置,代码如下:

<!-- 配置Struts2 的核心过滤器:前端控制器 -->
<filter>
	<filter-name>struts2</filter-name>
	<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
	
<filter-mapping>
	<filter-name>struts2</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>

那么到这,完成了以上的步骤之后,程序就可以执行了。

2.1.5 测试

在地址栏中输入http://localhost8080/struts2_day01/hello/HelloAction,其中前面部分http://localhost8080/是tomcat默认的地址信息,.../struts2_day01是web工程名,.../hello是struts.xml中的namespace值,.../HelloAction是struts.xml中的Action name值

从结果我们可以看到,在下面的打印台上输出了 hello world! 说明Action已经执行到了。上面也输出了页面的信息,说明成功跳转到了hello.jsp页面 。

2.2 Struts2 的访问流程

当服务器启动,加载web.xml 文件,就会加载一个过滤器Filter,StrutsPrepareAndExecuteFilter这个过滤器加载后,Struts2框架就可以使用。StrutsPrepareAndExecuteFilter这个过滤器会拦截所有请求,我们的/hello访问请求也会被拦截下来,会使用/hello,去struts.xml 文件中查找指定的Action类。

三. Struts2 工作原理

下面是Struts2官网上给出的全图:

  

其中,橙色蓝色的StrutsPrepareAndExecuteFilter、ActionMapper、ActionProxy、ConfigurationManager、Result,是Struts2已经定义好而不需要我们程序员去处理的部分。绿色的Interceptor拦截器,可以用Struts2中现成的,也可以我们程序员自己重新自定义。黄色的struts.xml、Template中的JSP等、Action,是需要我们程序员自己动手的。

一个请求在Struts2框架中的处理大概分为以下几个步骤:

1) struts2的整个生命周期开始于来自客户端的request请求, 客户端初始化一个指向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的execute()方法,该execute()方法先获取用户请求参数,然后它会调用业务逻辑组件来处理用户的请求。在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。
8) 一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以使用Struts2 框架中继承的标签。在这个过程中需要涉及到ActionMapper。

上述过程中所有的对象(Action,Results,Interceptors,等)都是通过ObjectFactory来创建的。

 

  1) 客户端(Client)向服务器发送一个请求(request) 
  2) 客器(Container)通过web.xml映射请求,并获得控制器(Controller)的名字。 
 3) 容器(Container)调用过滤器(StrutsPrepareAndExecuteFilter或FilterDispatcher)。在Struts2.1以前调用FilterDispatcher,Struts2.1之后调用StrutsPrepareAndExecuteFilter。 
 4) 控制器(Controller)通过ActionMapper获得Action的信息。 
 5) 控制器(Controller)调用ActionProxy。 
 6) ActionProxy读取struts.xml文件读取相应的action和interceptor stack的信息。 
 7) ActionProxy把request请求传递给ActionInvocation。 
 8) ActionInvocation依次调用interceptor拦截器和action。 
 9) 根据action执行结果,产生result。 
10) Result信息,经过interceptor拦截器返回给ActionInvocation。 
11) 产生一个HttpServletResponse响应。 

12) 将产生的响应返回给客户端。 

Struts2 六大核心组件

AOP思想,面向切面编程

四. Strut2 详解

4.1 Action类详解

4.2 Strut2 配置详解

通过前面的学习,我们已经对Struts2 框架有了一定的了解,但是对于各知识点的细节,还需要进一步地学习。接下来,将针对Struts2中struts.xml 文件的配置等内容进行详细的讲解。在学习具体详细的配置之前,要对Struts2的配置文件的加载顺序有一定的了解,这样对后面学习Struts2 的配置都是有帮助的。

4.2.1 配置文件的加载顺序

每次从客户端发送请求到服务器端都要先经过Struts2的核心过滤器StrutsPrepareAndExecuteFilter,这个过滤器有两个功能:预处理执行预处理中主要是加载配置文件,对应的是过滤器中的init()方法;而执行是用来执行一组拦截器完成部分功能,对应的是过滤器的doFilter()方法所以我们如果想要了解Struts2的配置文件的加载顺序,就要查询过滤器的init()方法。

4.2.2 Action的配置中各个元素与属性

4.2.3 Struts2常量配置

在企业开发中,还有一个问题,就是如果一个团队协同开发一个项目,而团队中的很多人都需要去修改struts.xml,那么最后在项目整合的时候就会很麻烦。所以Struts2 中也支持分模块开发的配置。

4.2.4 分模块开发的配置

其中,每一个被包含的配置文件必须是标准的Struts2 配置文件,一样包含DTD信息、Struts2 配置文件的根元素等信息。

4.2.5 动态方法调用

方式一,配置动态方法是否开启的常量

1) 创建一个Action类,此类中包含了不止一个方法。

2) 通过设置动态方法调用是否开启的常量,
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
实现动态配置上面Action中四个方法。

3) 在地址栏中输入:
http://localhost8080/struts2_day01/dynamic/Demo1Action!delete.action

进行访问。其中调用方法的访问格式是  !方法名因为在此案例中指定了访问action时的后缀名常量<constant name="struts.action.extension" value="action"></constant>,所以要加 .action后缀。

重启服务器后,在地址栏中输入访问路径,结果如下图所示:

方式二,通配符  * 方法

1) 创建一个Action类,此类中包含了不止一个方法。

  

2) 使用 * 通配符,<action name="Demo1Action_*" class="cn.itheima.b_dynamic.Demo1Action" method="{1}">

3) 在地址栏中输入

http://localhost8080/struts2_day01/dynamic/Demo1Action_add.action

  

4.2.6 Struts2 中的默认方法配置

4.3 页面结果的配置(结果跳转方式)

4.4  Struts2访问servlet的API 

前面已经对Struts2的流程执行完成了,但是如果表单中有参数,如何进行接收?又或者我们需要向页面保存一些数据,又要如何完成?我们可以通过学习Struts2 访问Servlet的API 来实现这样的功能。【 Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet 

在Struts2中,Action 并没有直接和Servlet API 进行耦合,也就是说在Struts2的Action中不能直接访问Servlet API。虽然Struts2中的Action访问Servlet API 麻烦一些,但是这却是Struts2中Action的重要改良之一,方便Action进行单元测试。

尽管Action和Servlet API 解耦会带来很多的好处,然而在Action中完全不访问Servlet API  几乎是不可能的,在实现业务逻辑是,经常要访问Servlet 中的对象,如 session、 request 、application 等。

Struts2访问Servlet的API,就是要了解Struts2如何从 ActionContext 中取值。原理如下图:

  

Struts2访问servlet的API 的方式有 3 种,通过ActionContext 类访问Servlet的API,具体如下:

4.4.1 通过ActionContext 类访问Servlet的API

建议:在开发中优先使用方式一,通过ActionContext 类访问Servlet的API 。

4.4.2 通过ServletActionContext 类访问Servlet的API

  

4.4.3 通过特定接口访问Servlet的API

4.5 封装Struts2中的数据 

在很多的实际开发场景中,页面提交请求到Action,在Action中接收参数并且需要对请求参数进行数据的封装。封装到一个JavaBean中,然后将JavaBean 传递给业务层。那么这些操作,Struts2 已经替我们都想好的。Struts2 将数据的封装分成两大类:一类被称为属性驱动,一类被称为模型驱动。

4.5.1 属性驱动

4.5.2 模型驱动

 

4.6  Struts2 中封装复杂类型的数据

在实际开发中,有些时候我们需要批量插入用户或批量插入其它的对象,在Action中需要接收到这多个Action 中封装的对象,然后传递给业务层。那么这个时候就需要将表单的数据封装到集合中。一般我们通常使用的集合无非是List或Map集合,下面就以这两种集合进行数据的封装示例演示。

4.6.1 封装到List 集合中

4.6.2 封装到Map 集合中

××××××××××××××××××××××××××看到这×××××××××××××××××××

五. OGNL 

5.1 OGNL 概念

OGNL是Object-Graph Navigation Language的缩写,对象视图导航语言。它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。如果把表达式看作是一个带有语义的字符串,那么OGNL 无疑成为了这个语义字符串与Java对象之间沟通的桥梁

OGNL:对象视图导航语言。${user.addr.name},这种写法就叫做对象视图导航。OGNL不仅仅可以视图导航,还支持比EL表达式更加丰富的功能。

5.2 OGNL 的作用

 

5.3 OGNL 的要素

5.4 OGNL 案例

下面结合具体的例子,熟悉OGNL 是如何进行代码编码的。

六. OGNL 和Struts2框架 的结合

6.1 结合的原理

6.2 值栈

6.2.1 值栈相关概念

 扩展知识:

request.getAttribute() 方法的查找顺序
1. 原生request 域
2. 查找ValueStack的栈(Root)部分

3. 查找ValueStack的Context部分(ActionContext)

6.3 Struts2 和 OGNL 结合的体现

6.3.1 Struts2参数接收时,所体现出的OGNL

 获得值栈,代码如下:

 

6.3.2 Struts2配置文件中,所体现出的OGNL

6.3.3 Struts2 的标签,所体现出的OGNL(了解即可)

标签体系:

Struts2 的标签的使用

 

七. Struts2 的拦截器

7.1 拦截器的相关概念

7.2 拦截器的创建方式 

拦截器的创建,有3 中常见方式:

7.3 自定义拦截器与拦截器的配置

注意:自定义拦截器要放在默认拦截器之前。

  

其中,指定哪些方法拦截与哪些方法不拦截不能同时出现

7.4 拦截器和过滤器的区别

过滤器包裹住servlet,servlet包裹住拦截器。如下图所示:

1.过滤器和拦截器“触发时机(触发时间和地点)”不一样:
过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。
2.过滤器的触发时机是容器后,servlet之前,所以过滤器的doFilter(ServletRequest request, ServletResponse response, FilterChain chain)的入参是ServletRequest ,而不是httpservletrequest。因为过滤器是在httpservlet之前。

过滤器和拦截器的区别:
  ①拦截器是基于Java的反射机制的,而过滤器是基于函数回调。
  ②拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
  ③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
  ④拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
  ⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。

  ⑥拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service(),可以调用业务逻辑。

---------------------------------------------------------------------- 我是低调的分隔线  --------------------------------------------------------------------------


                                                                                                                                     吾欲之南海,一瓶一钵足矣...

                         

易百教程:https://www.yiibai.com/struts_2/ 链接

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值