一、简介
Struts2是Apache发行的MVC开源框架(它只是表现层(MVC)框架)。
Struts2的来历
(1)Struts1:也是apache开发的一套mvc的开源框架。在2005年之前非常流行。
弊端:Struts1的核心控制器就是一个Servlet。随着使用者的增多,弊端开始出现。
(2)Struts2:在long long ago,有一个设计超前的框架XWork,后来推出了XWork1和WebWork2。Struts2就是apache和OpenSymphony组织合并开发出来。
里面包含了WebWork2的核心及Struts的一些特性和功能。除此之外,和Struts1没有任何关系了。
核心功能
(1)允许POJO(Plain Old Java Objects)对象 作为Action
(2)Action的execute 方法不再与Servlet API耦合,更易测试
(3)支持更多视图技术(JSP、FreeMarker、Velocity)
(4)基于Spring AOP思想的拦截器机制,更易扩展
(5)更强大、更易用输入校验功能
二、搭建开发坏境
1、开发包目录结构

2、开发步骤
(1)拷贝jar包:struts-blank的war包,在它的WEB-INFlib目录下的全部jar包
(2)在最顶层的构建路径,建立一个默认名称为struts.xml的配置文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE struts PUBLIC 3 "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" 4 "http://struts.apache.org/dtds/struts-2.3.dtd"> 5 <struts> 6 </struts>
(3)配置前端控制器(核心)
在web.xml中,在struts2已经写好了的一个过滤器。
struts2比struts1优秀的一个体现就是,它用了更为强大的过滤器作为控制器了。
1 <filter> 2 <filter-name>struts2</filter-name> 3 <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> 4 </filter> 5 6 <filter-mapping> 7 <filter-name>struts2</filter-name> 8 <url-pattern>/*</url-pattern> 9 </filter-mapping>
三、开发案例
1、建立一个jsp文件
1 <html> 2 <head> 3 <title>My JSP 'index.jsp' starting page</title> 4 </head> 5 <body> 6 <%--在Struts中,控制器会默认拦截扩展名为.action的请求(以.action为后缀的url) --%> 7 <a href="${pageContext.request.contextPath }/hello.action">访问Struts2的第一个案例</a> 8 <a href="${pageContext.request.contextPath }/hello">访问Struts2的第一个案例,没有.action</a> 9 </body> 10 </html>
2、在structs.xml中配置
1 <struts> 2 <package name="p1" extends="struts-default"> 3 <action name="hello" class="cn.guojie.web.action.HelloAction" method="sayHello"> 4 <result name="success">/success.jsp</result> 5 </action> 6 </package> 7 </struts>
3、建立动作类和动作方法
1 public class HelloAction { 2 3 /** 4 * 在动作中指定的方法 5 * 要求 6 * 1、必须public 7 * 2、返回值必须是一个String 8 * 3、必须没有参数 9 */ 10 public String sayHello() { 11 System.out.println("HelloAction中的sayHello方法执行了"); 12 return "success"; 13 } 14 }
4、结果视图页面success.jsp
1 <head> 2 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 3 <title>Insert title here</title> 4 </head> 5 <body> 6 操作成功 7 </body> 8 </html>
四、执行过程
servlet执行过程:客户浏览器 --> Tomcat服务器 -- > web.xml --> Servlet
Struts2执行过程:客户浏览器 --> Tomcat服务器 --> web.xml --> struts.xml --> HelloAction --> success.jsp
过滤器(web.xml)在服务器一启动就执行初始化
servlet只实例化一次,有线程安全问题;Structs实例化多次,无线程安全问题
内部执行过程
五、Struts2配置文件
当应用被 tomcat 加载的时候, struts2的配置文件就已经被加载过了
加载顺序
(1)default.properties 保存在 struts2-core-2.3.7.jar 中 org.apache.struts2包里面(常量)
(2)struts-default.xml 保存在 struts2-core-2.3.7.jar(核心,拦截器、常用结果视图、默认动作类)
(3)struts-plugin.xml 保存在struts-Xxx-2.3.7.jar(插件)
(4)struts.xml 是web应用默认的struts配置文件(自己应用中,要修改,推荐)
(5)struts.properties 是Struts的默认配置文件(自己应用中,不推荐)
(6)web.xml 是Web应用的配置文件(修改)
如果多个文件配置了同一个struts2 常量,则后一个文件中配置的常量值会覆盖前面文件配置的常量值
Struts2 提供了两种配置的方式:一种是 key=value 的方式,即使用 .properties文件。另一种是 xml 文件配置,我们推荐使用 xml 文件(它能描述层级关系)
六、Struts2 提供的常量
1、常用的常量
常量定义在了 default.properties 配置文件中,体现形式都是 key=value 。所有的struts2 应用都会用到这些常量

2、在 struts.xml中覆盖常量
使用 <constant name="" value=""></constant> 元素进行覆盖

3 、创建struts.properties 文件覆盖
在应用的构建路径中创建一个 struts.properties 的文件

4 、在web.xml 中配置过滤器参数
七、xml 配置文件的主要元素
1 、 package元素
1.1 、作用:
在 struts2的配置文件中引入了面向对象思想,使用了分包管理,易于管理动作类,便于模块化开发动作类。
1.2 、属性:
name :包的名称,必须写,且必须唯一。
extends :一般情况下需要继承 struts-default 包,但不是必须的。不过如果不继承的话,将无法使用 struts2 提供的核心功能。struts-default.xml 中定义着 struts-default 这个包。而struts-default.xml 是在我们的 struts.xml 加载之前加载。
abstract :把包声明为抽象包,抽象包就是用来被继承的。只要是没有 <action> 元素的包,就可以声明为抽象包。
namespace :名称空间。指定了名称空间之后,访问路径=名称空间 + 动作名称,当不指定该属性时,该属性有默认值“ ”,不是“/”,不写namespace就是默认
名称空间搜索顺序
第一步:找对应的名称空间
在指定的名称空间下找到了就执行第二步,在指定的名称空间下没找到,按名称空间结构向上一级查找,一直到根名称空间,只要在任何一级找到了就执行第二步
第二步:找动作名称
在指定的名称空间下,搜索对应的动作名称,找到了就执行动作类的动作方法
在指定的名称空间下没找到对应的动作名称,前往默认的名称空间下找动作名称,注意,只招动作名称,名称空间在第一步已经执行
2 、 action元素
2.1 、作用:
配置动作,用于定义动作名称,动作类和动作方法的映射,以及当前出现不同情况时前往指定的结果视图
过滤器过滤动作名称,通过动作类的字节码文件反射,拿到getter执行方法
2.2 、属性:
name :动作名称
class :动作类全名。默认的动作类是: com.opensymphony.xwork2.ActionSupport
是在 struts-default.xml中定义的
要想替换默认动作类:
在应用的 struts.xml 中,package 中加入:

method:动作类中的方法名称。默认是 public String execute(){}
要求:
1.public 的
2. 返回值必须是 String
3. 没有参数
2.3 、动作类
方式一:动作类就是一个 POJO (Plain Old Java Object 原始的 java 对象),非常简单的 javabean。
无侵入式,与struts2看不出来有关系
方式二:动作类实现 com.opensymphony.xwork2.Action接口。
常量:给动作方法返回值用的。用常量可以使你的应用规范和统一。
SUCCESS "success" 执行成功后,前往指定位置
NONE "none" 不返回任何结果视图,和return null作用一样
ERROR "error" 当执行动作方法出现异常后前往指定位置
INPUT "input" 数据回显
LOGIN "login" 一般用于返回登录页面
方式三:动作类继承 com.opensymphony.xwork2.ActionSupport接口实现类(推荐使用 )
什么都不写时,有一个默认动作方法execute()
默认动作类ActionSupport,在struts-default.xml的配置文件中定义着
<default-class-ref class="com.opensymphony.xwork2.ActionSupport" />,一般不修改
2.4 、动作方法的访问
(1)使用通配符:
*表示动作的名称,当有和动作名称相匹配的时候可以用{出现的位置}来代替

优先级:绝对匹配优先。使用通配符的按照在配置文件中的先后顺序进行匹配的
(2)动态方法调用(不安全)
八、结果类型视图 ( 逻辑结果视图 )
该部分内容指的就是 struts 配置文件中的 result元素的使用
1 、 result元素
作用:
为动作指定结果视图
属性:
name :逻辑视图的名称,对应着动作方法的返回值,当一致时前往指定的jsp。默认值是 success

type :结果类型,指的就是用什么方式转到定义的页面。默认是 dispatcher
2 、 result元素中 type 的取值
type 属性的取值在 struts-default.xml中定义
常用结果类型介绍
(1) dispatcher : (默认值 )
使用请求转发,转向一个页面。
(2)redirect :
使用重定向,转向一个页面

(3)redirectAction :注意:使用的是重定向。
1. 重定向到相同名称空间的另一个动作。
<result name="success" type="redirectAction">action2</result>

2.重定向到不同名称空间的动作
<result name="success" type="redirectAction">
使用注入的思想,在执行重定向之前,会先获得这两个参数的值,调用的就是setNamespace("/n2")和setActionName("action3")的方法
<param name="namespace">/n2</param>
<param name="actionName">action3</param>
</result>

(4)chain :注意: 使用的是请求转发。
1. 转发到相同名称空间的另一个动作。
<result name="success" type="chain">action2</result>

2.请求转发到不同名称空间的动作
<result name="success" type="chain">
使用的是注入的思想,在执行之重定向之前,会先获取这两个参数的值
调用的就是setNamespace("/n2")和setActionName("action3")
<param name="namespace">/n2</param>
<param name="actionName">action3</param>
</result>

3 、 result元素中 param 子元素
在转发或者重定向到不同包下的动作时,都用到了 result 元素的子元素 param。
param 元素的作用: 依赖注入 (Dependence Injection) 思想
我们通过 struts-default.xml 中的resultTypes 元素中配置可以看出,每个结果类型视图其实都是靠一个类来实现的。而 param 元素就是将配置的参数,注入到该类中。
调用的是对应类的 setter 方法进行注入的。
redirectAction结果视图

该类中肯定会有对 actionName 和namespace 属性的注入方法( setter 方法)
默认结果视图 dispatcher
4、自定义结果类型
通过前面的内容,我们看出,其实结果类型就是一个类,这些类都实现了com.opensymphony.xwork2.Result接口。
或者继承自该接口的实现类org.apache.struts2.dispatcher.StrutsResultSupport。
这些类都有一个doExecute方法,用于执行结果视图。
综上:我们也可以自己写一个结果视图。
输出CAPTCHA图像的结果类型
CAPTCHA(Completely Automated Public Turing Test to Tell Computers and Humans Apart 全自动区分计算机和人类的图灵测试)————>简称:验证码。
第一步:写一个类,实现接口或者继承接口的实现类

第二步:在 struts.xml 文件中配置结果类型
第三步:在 action 配置时引用
通过可配置的参数,实现图像大小的调整
5、全局视图和局部视图
5.1、局部视图
写在action内部的结果视图,只能当前动作类使用

5.2、全局视图
查找顺序,先找当前动作类的自己的,没有再去全局结果视图中查找

九、在动作类中访问Servlet的API
第一种方式:使用ServletActionContext类(推荐)

第二种方式:使用实现接口的方式
使用的是依赖注入的形式,把想要的对象注入进来,有拦截器做的

十、分文件编写框架配置文件
1、不分文件开发可能产生的问题
就类似于我们在写java类时,所有代码都写在一个类里,甚至写在一个方法里。
当3个人都checkout了struts.xml文件时,第一个人提交了,后面的人在没有更新就提交时,第一个人写的可能就白写了。
2、分文件编写Struts2的配置文件
约定优于配置
约定优于配置(convention over configuration),也称作按约定编程,是一种软件设计范式,旨在减少软件开发人员需做决定的数量,获得简单的好处,而又不失灵活性。
本质是说,开发人员仅需规定应用中不符约定的部分。例如,如果模型中有个名为Sale的类,那么数据库中对应的表就会默认命名为sales。只有在偏离这一约定时,例如将该表命名为”products_sold”,才需写有关这个名字的配置。
如果您所用工具的约定与你的期待相符,便可省去配置;反之,你可以配置来达到你所期待的方式。
转发和重定向
转发:一次请求,一次响应。地址栏的url不会改变。在服务器端执行,所以必须在同一台服务器上。转发速度快。
重定向:两次请求。地址栏的url会随之改变为定向后的那个url。在客户端执行,所以可以在不同的服务器上。重定向速度慢。
复制完项目之后需要改
