Struts2框架学习
第一讲:回顾
- Web开发的进程有两种模式,model1开发模式和model2开发模式。
- Model1模式
- 优点:执行效率高,开发效率高,适合中小型项目。
- 缺点:逻辑比较混乱,页面混乱,维护困难,扩展不容易。
- Model2
- 优点:解耦,将试图层和业务层分离。结构清晰,分工明确,维护方便,适合中大型项目。
- 缺点:执行效率相对Model1低,代码量大,重复代码比较多。
- Model2又称为MVC设计模式。
- M:model模型
- V:view试图
- C:controller控制
- 使用Servlet的MVC存在一些问题,有重复的代码—通过MVC框架来解决。
- Servlet解决了什么问题
- Java学习路线
- 基础语法—->方法(目的:减少代码,代码重复利用)—->类(目的:代码复用,OOP:面向对象)—-> jar包(多个类封装为jar包。目的:代码复用)—-> 框架(一个或多个jar包。目的:代码重用)
- 从中体现最多的思想是:封装
- 什么是框架?
- framework
- 框架是模板,模型,模子。
- 专业语言描述:框架是一个可重用的半成品。
- 为什么要学框架?
- 提高开发效率,降低学习难度。
- 如何学习框架?
- 框架是别人提供的,那么使用框架时,要遵守框架提供的规。
- 学习框架就是学习框架的规则。
- 框架有两个部分组成:可变的部分和不可变的部分。
- 常见的框架有哪些
- 什么是struts?
- Apache Struts is a free, open-source, MVC framework for creating elegant, modern Java web applications. It favors convention over configuration, is extensible using a plugin architecture, and ships with plugins to support REST, AJAX and JSON.
- Struts2是一个开源、免费、轻量级的
mvc框架- 轻量级:如果一个框架没有侵入性,就说该框架是轻量级的。
- 侵入性:如果使用一个框架必须实现框架提供的接口,或者继承框架提供的类。
- 在Struts2之前是Struts1。Struts1出现很早,市场占有率比较高,所以不支持一些新的试图层展示技术,逐渐被淘汰。Struts2=Struts1+webwork
- Struts2是基于请求的mvc框架。
- Struts2的目录结构
- apps:应用案例。
- docs:文档。
- lib:使用的库包。
- src:源码。
- Struts2的Hello World案例
- 新建web项目
- 导入jar包
- 编写web.xml文件–配置struts2的前端控制器(分发器)
1
2
3
4
5
6
7
8
9<!-- 配置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>*.action</url-pattern>
</filter-mapping>
- 编写业务处理类
1 | package demo; |
- 在src下,添加strut2的配置文件,名称为为struts.xml,该配置文件名不能更改,并进行配置。
1 |
|
- 编写hello.jsp页面
1 | <%@ page language="java" contentType="text/html; charset=UTF-8" |
- 发布项目并进行测试。
第四讲 配置讲解
web.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<!--
配置struts2的前端控制器
struts2框架开始工作的入口
接管请求
-->
<filter>
<!-- 名称自定义 -->
<filter-name>struts2</filter-name>
<!-- Struts2提供的控制器类 -->
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>struts2.xml 该配置文件的文件名固定,并且只能放在src目录下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38<struts>
<!--
package 分模块管理
name属性属性值自定义但是不能重复,在一个项目中是唯一的
namespace属性命名空间与url请求路径直接相关
如:“/” 请求为 /hello.action;
如:"/user",则请求路径为/user/hello.action
extends 继承 必须直接或间接继承struts-default
result的请求路径是相对namespace的属性值
-->
<package name="default" namespace="/" extends="struts-default">
<!--
配置action
配置url和处理类的方法进行映射
name为请求名称 不加后缀
class 处理类的完全限定名称 包名+类名,如果不配置,由默认类来处理
com.opensymphony.xwork2.ActionSupport
method指定处理请求的方法,默认是execute()方法
-->
<action name="hello" class="demo.HelloWorld" method="hello">
<!--
result结果集配置
name 结果集名称,和处理方法的返回之匹配 默认为success,可以自定义。
Struts2提供了5个返回结果:
Action.SUCCESS: 执行成功,跳转到下一个试图
Action.NONE:执行成功,不需要试图展示
Action.ERRPR:执行失败,显示失败页面
Action.INPUT:要执行该Action需要更多的输入条件
Action.LOGIN:需要登陆后才能执行
type指定响应结果类型
dispatcher 请求转发,默认使用
redirect 请求重定向
redirectAction 重定向到另一个action
result的值为跳转页面 不加"/"为相对namespace路径,建议使用绝对路径
-->
<result name="" type="">/hello.jsp</result>
</action>
</package>
第五讲 Struts2的执行流程
- 浏览器发起请求 –> 服务器接收请求并交给
Struts2的前端控制器 —–> 根据请求的url查看struts.xml中的namespace+actionName是否存在 –> 执行action所对应的类的对应方法 —> 根据方法的执行结果到action的结果集进行匹配 –> 响应结果。
- Struts2
.png)
第六讲 Struts2的数据处理一
- 在struts2中,对表单数据的处理有三种:属性驱动,对象驱动,模型驱动
- 使用Strut2获取表达数据:只需要表单域数据名称和Action处理类的属性名称一致,并且提供属性的set方法,那么在Action处理类中即可获取表单数据。这种获取数据的方式称为
属性驱动。- 处理类:
1 | package demo; |
1 | <%@ page language="java" contentType="text/html; charset=UTF-8" |
1 |
|
- 如果数据需要显示在页面上,那么该数据可以作为处理类的数据,处理方法后该属性有值,并且有该属性的get方法,那么在页面上可以直接通过el表达式获取。
1 | package demo; |
1 | <%@ page language="java" contentType="text/html; charset=utf-8"%> |
第七讲 数据处理二
IOC:控制反转
- 对象驱动方式获取属性:(重点)
- 在action的处理类中,属性以对象的形式存在,该属性对象只需声明并为其提供get方法和set方法即可,需要保证该属性对象有无参构造方法。
- 在表单域中的表单域名称以属性对象.属性对象的属性来命名。 这种方式比较重要
1 | //User类 |
1 | <!--显示成功页面--> |
- 模式驱动:在对象驱动中,页面的表单域名称比较复杂,如果对象属性比较多的情况下,代码量比较大。通过模式驱动可以解决这个问题。
- 模式驱动需要实现ModelDriver接口,并且主动将对象创建好。
1 | //处理类 |
1 | <!--登录页面--> |
第七讲 数据处理二
IOC:控制反转
- 对象驱动方式获取属性:(重点)
- 在action的处理类中,属性以对象的形式存在,该属性对象只需声明并为其提供get方法和set方法即可,需要保证该属性对象有无参构造方法。
- 在表单域中的表单域名称以属性对象.属性对象的属性来命名。 这种方式比较重要
1 | //User类 |
1 | <!--显示成功页面--> |
第八讲 action的几种创建方式
- 在
Struts2中有三种方式来创建action处理类
- 实现
action接口的方式来创建处理类,好处:
- 可以直接使用Action类提供的常量
- 必须重写默认的处理方法。
- 这种方法使用比较少。
1 | package com.zhuchuli.action; |
- 通过继承
ActionSupport类来创建Action的处理类,Strut2推荐使用这种方式。
1 | package com.zhuchuli.action; |
- 无侵入性的实现方式
1 | package com.zhuchuli.action; |
第九讲 Struts2配置讲解2
constant标签
1 | <!-- strut2的常量配置 --> |
include标签:引入其他的配置文件,在团队开发中使用
1 |
|
第十讲 action的优化配置
- 在Struts2中,随着业务的增加,
action的配置文件会急剧增加,导致了配置文件膨胀的问题。struts2中提供了三种方式来解决这个问题。
- 通过动态方法调用来解决。
- 通过通配符来解决。
- 通过注解来解决。
- 传统的action方式,配置文件会变得很庞大
1 |
|
1 | package com.zhuchuli.action; |
- 通过动态方法解决该问题
- 在常量中开启动态方法调用。
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>- 配置
action,一个Action处理类,只需配置一次。不需要配置处理方法。
1 | <action name="userAction" class="com.zhuchuli.action.UserAction"> |
- 调用处理方法,
ActionName!method.action,例如:http://localhost:8080/Struts_study02/userAction!delete.action- 注意:使用动态方法调用需要不同处理方法的返回值是否一致问题。会配置多个结果集。这种方式不推荐使用,不安全。
1 | <!-- *表示一个或多个字符 --> |
- 注意如果使用通配符配置,那么需要注意不同处理方法的返回值的问题。
- 使用注解来解决。
- 使用注解需要导入
struts2-convention-plugin-2.3.37.jar、asm-3.3.jar、asm-commons-3.3.jar、asm-tree-3.3.jar- 在处理类上填写相关注解
1 | package com.zhuchuli.action; |
第十一讲 ThreadLocal和ActionContext
ThreadLocal是一个容器,存放在容器中的数据是线程安全的。
1 | package threadlocal; |
ActionContext:是Struts2的上下文对象,它的本质是一个容器,也是一个Map结构的对象。ActionContext贯穿于整个Action生命周期,每次接受请求后都会新建一个ActionContext对象,将ServletAPI中的数据存入到ActionContext中,实现了struts2和Servlet的解耦,使得测试可以不依赖容器。而且ActionContext是线程安全的。由于每次请求都会重新创建ActionContext,导致执行效率比Servlet低。ActionContext有六个对象:
request:存放的是HttpServletRequest域中的数据。session:存放的是HttpSession域中的数据。application:存放的是ServletContext域中的数据。parameters:存放的是请求参数attr:存放的是request、session、application中的数据。ValueStacke:业务处理类的相关数据。
1 | // helpers to get access to request/session/application scope |
ServletContext:是一个容器,是一个对象,相当于map。
第十二讲 ognl
ognl:Object graph navigation language,对象导航图语言。- 在
Struts2中,ognl完成数据设置和类型转换两个功能。- 在
struts2中是通过ognl来设值和取值的。ActionContext作为ognl的上下文,ValueStack作为ognl的root对象- 在
struts2中使用ognl表达式获取数据需要使用struts2的标签库,使用struts2的标签库,需要注意一定是通过过滤器后才能解析struts2的标签
1 | package demo; |
1 | <%@ page language="java" contentType="text/html; charset=utf-8"%> |
- ognl获取各种域中的数据如下:
application:#application.username、#application['username'];session:#session.username、#session['username'];request:#request.username、#request['username'];parameters:#parameters.username、#parameter['username'];attr:#attr.username、#attr['username'],按pageContext、request、session、application顺序查找。
第十三讲 ServletAPI
- 在
Struts2的开发中,依然需要使用到ServletAPI,比如用户登录之后,需要将用户信息保存到session中.在Struts2中有两种方式可以获取ServletAPI,一种解耦方式,一种是耦合方式。
- 解耦的实现方式
1 | package com.zhuchuli.action; |
- 耦合的方式
- 直接通过
ServletContext获取
1 | public String login() { |
- 通过
ActionContext获取
1 | public String login() { |
- 通过
IOC方式直接获取到ServletAPI
1 | public class LoginAction03 implements ServletRequestAware{ |
第十四讲 类型转换
- 在
Struts2中,对常用的数据类型已经自动进行了类型装换工作。但是对于自定义类型,Struts2没法去做类型转换工作。需要自定义类型转换器来实现类型的转换。- 类型转换的实现步骤:
- 新建一个类型转换并继承
StrutsTypeConverter
1 | package cn.zhuchuli.pointconverter; |
- 在
src下添加xwork-conversion.properties配置文件
# be converted type=convertercn.zhuchuli.vo.Point = cn.zhuchuli.pointconverter.PointConverter
第十五讲 数据校验一 (硬编码实现)
- 数据校验分为2类,一类是前端的数据校验,一般通过js实现,一类是后端的数据验证。在对一些安全级别较高项目都需要对其进行后台验证。Struts2提供了两种后台校验方法,一种是硬编码实现,一种是校验框架实现。
- 如果要使用
struts2的数据校验功能,action需要继承ActionSupport类。在该类中提供了validate方法,可以将验证规则写在该方法中,只有方法执行通过之后,才会执行业务方法。- 实现步骤
- 业务处理类
1 | package com.zhuchuli.action; |
- 在配置文件中配置input结果集
1 | <action name="user" class="com.zhuchuli.action.UserAction"> |
- 在页面中添加struts2的标签库,并且添加错误标签
1 | <%@ page language="java" contentType="text/html; charset=UTF-8" |
- 通过上述方法来实现数据校验会有一个问题。一个业务类中有多个业务方法,并且每个业务方法的验证规则可能不一致,但是所有的业务方法都会通过
validate。导致功能不能实现。在struts2中,如果一个业务类中有多个业务方法,那么需要为每个业务方法添加自己的验证方法。验证方法的命名规则为validate+业务方法名(首字母大写)。这样执行业务方法时,执行顺序为validateXxxx ---> validate ---> xxxx。这样的话,validate方法中填写的公共的验证方法。
1 | package com.zhuchuli.action; |
第十五讲 数据校验二(使用Struts2提供的校验框架实现数据校验)
- 实现步骤
- 创建
jsp页面
1 | <%@ page language="java" contentType="text/html; charset=UTF-8" |
- 创建
Action类
1 | package com.zhuchuli.action; |
- 在
Action类所在包下,添加校验规则文件以ActionClassName-validation.xml命名
1 |
|
- 配置
Struts.xml文件
1 |
|
第十七讲 Struts2拦截器
struts2中的所有功能都是由拦截器来实现的。拦截器是Struts2的核心。拦截器和过滤器非常相似,过滤器过滤的是所有的请求,拦截器纸过滤action,并且在struts2中所有的功能都是可插拔的。在struts2中还可以自定义拦截器来实现一些struts2没有提供的功能。在struts2中拦截器的实现是通过代理来实现的。(AOP)在Struts2中拦截器都是单列的,所有的action共享相同的拦截器,所以在拦截器定义常量时要注意线程安全问题。Struts2中提供很多拦截器来实现各种功能,在开发中可以根据不同的应用选择不同的拦截器来实现功能。Struts2提供了一系列默认的拦截器(拦截器栈)来实现功能。- 默认拦截器说明
alias:对于HTTP请求包含的参数设置别名autowiring:将某些JavaBean实例自动绑定到其他Bean对应的属性中。有点类似Spring的自动绑定,在Spring部分会详细说明。Chain:在Web项目开发中,以前使用Struts开发时候经常碰到两个Action互相传递参数或属性的情况。该拦截器就是让前一Action的参数可以在现有Action中使用。conversionError:从ActionContext中将转化类型时候发生的错误添加到Action的值域错误中,在校验时候经常被使用到来显示类型转化错误的信息。cookie:从Struts< xmlnamespace prefix="ST1" >2.0.7版本开始,可以把cookie注入Action中可设置的名字或值中。createSession:自动创建一个HTTP的Session,尤其是对需要HTTP的Session的拦截器特别有用。比如下面介绍的TokenInterceptor。debugging:用来对在视图间传递的数据进行调试。ExecAndWait:不显式执行Action,在视图上显示给用户的是一个正在等待的页面,但是Action其实是在“背后”正在执行着。该拦截器尤其在对进度条进行开发的时候特别有用。exception:将异常和Action返回的result相映射。fileUpload:支持文件上传功能的拦截器。i18n:支持国际化的拦截器。logger:拥有日志功能的拦截器。modelDriven:Action执行该拦截器时候,可以将getModel方法得到的result值放入值栈中scopedModelDriven:执行该拦截器时候,它可以从一个scope范围检索和存储model值,通过调用setModel方法去设置model值。params:将HTTP请求中包含的参数值设置到Action中。prepare:假如Action继承了Preparable接口,则会调用prepare方法。staticParams:对于在struts.xml文件中Action中设置的参数设置到对应的Action中。scope:在session或者application范围中设置Action的状态servletConfig:该拦截器提供访问包含HttpServletResquest和HttpServletResponse对象的Map的方法。timer:输出Action的执行时间。token:避免重复提交的校验拦截器tokenSession:和token拦截器类似,但它还能存储提交的数据到session里。validation:运行在action-validation.xml(校验章节将介绍)文件中定义的校验规则。workflow:在Action中调用validate校验方法。如果Action有错误则返回到input视图。store:执行校验功能时候,该拦截器提供存储和检索Action的所有错误和正确信息的功能。checkbox:视图中如果有checkbox存在的情况,该拦截器自动将unchecked的checkbox当作一个参数(通常值为“false”)记录下来。这样可以用一个隐藏的表单值来记录所有未提交的checkbox,而且缺省unchecked的checkbox值是布尔类型的,如果视图中checkbox的值设置的不是布尔类型,它就会被覆盖成布尔类型的值。profiling:通过参数来激活或不激活分析检测功能,前提是Web项目是在开发模式下。(涉及到调试和性能检验时使用)roles:进行权限配置的拦截器,如果登录用户拥有相应权限才去执行某一特定Action。Struts2中的默认拦截器是定义在struts-default.xml中。这些拦截器都是定义在struts-default包下的。所以在使用struts2时定义的package要直接或间接继承struts-default- 常见内置拦截器的使用,使用内置拦截器是需要引用拦截器。
Timer拦截器的使用
- 创建
action类
1 | package com.zhuchuli.interceptor; |
- 在配置文件中进行配置
1 |
|
token拦截器的使用
- 创建
Action类
1 | package com.zhuchuli.interceptor; |
- 在页面中添加
token标签
1 | <%@ page language="java" contentType="text/html; charset=UTF-8" |
- 在
action中引用token
1 | <action name="save" class="com.zhuchuli.interceptor.UserAction" method="save"> |
- 编写失效页面。
1 | <%@ page language="java" contentType="text/html; charset=UTF-8" |
第十八讲 自定义拦截器
- 在开发中,经常会使用到struts2中没有提供的一些功能,这时需要我们自定义拦截器来实现。当引用自定义拦截器后,struts2提供的默认拦截器将不起作用,需要重新引入。
- 自定义拦截器的实现步骤:
- 定义拦截器
1 | package com.zhuchuli.myinterceptor; |
- 在
package中配置拦截器
1 | <!-- 拦截器的配置 --> |
- 在使用action中引用拦截器
1 | <action name="timer" class="com.zhuchuli.interceptor.TimerAction"> |
- 登录拦截器的实现
1 | package com.zhuchuli.myinterceptor; |
1 | <package name="default" namespace="/" extends="struts-default"> |
1 | package com.zhuchuli.interceptor; |
1 | package com.zhuchuuli.vo; |
1 | <%@ page language="java" contentType="text/html; charset=UTF-8" |
第十九讲 拦截器栈和方法拦截器
- 拦截器栈:就是一组拦截器,放在一个配置中,在拦截器栈中可以引用多个拦截器,在真正需要调用时只需要一个栈即可,方便引用,拦截器中可以引用另外一个拦截器栈,
1 | <!-- 拦截器的配置 --> |
- 拦截器栈的引用,与拦截器引用一致,可以将拦截器栈当做拦截器来使用
1 | <interceptor-ref name="myStack"></interceptor-ref> |
- 设置默认拦截器栈
1 | <!-- 设置默认拦截器--> |
- Struts2定义了默认的拦截器栈是defaultStack,里面有默认的18个拦截器。
- 拦截器拦截的是整个action,action中的所有业务方法都会被拦截。比较粗粒度。有时只需拦截action中某个方法或某几个方法就能实现功能,那么拦截器就会造成效率降低。这时可以通过方法拦截器来解决这个问题。
- 方法拦截器的实现
1 | package com.zhuchuli.myinterceptor; |
1 | <interceptors> |
第二十讲 内置拦截器的使用情况。
第二十一讲 struts 文件上传(使用默认的内置拦截器)
- 在大部分应用中都有文件上传的功能。servlet中可以使用第三方插件来实现文件上传:
smartfileupload、commons-fileuoload- 文件上传步骤
- 添加jsp页面,注意表单提交必须是post提交,并且设置`enctype=”multipart/form-data”
1 | <%@ page language="java" contentType="text/html; charset=UTF-8" |
- 添加文件上传处理类
1 | package com.zhuchuli.action; |
- 添加配置文件
1 |
|
第二十二讲 批量文件上传
- 批量文件下载
- Jsp页面
1 | <%@ page language="java" contentType="text/html; charset=UTF-8" |
1 | package com.zhuchuli.action; |
struts.xml配置文件
1 | <action name="batch" class="com.zhuchuli.action.BatchUploadAction" method="upload"> |
第二十三讲 文件下载
- 文件下载可以通过超链接直接实现,但是通过超链接直接下载的文件不安全。任何用户得到超链接都可以下载,没法权限的控制。浏览器如果能打开文件,那么浏览会直接将文件打开。
- 通过流的方式来实现文件下载
- 业务处理方法
1 | package com.zhuchuli.action; |
- 配置文件
1 | <action name="download" class="com.zhuchuli.action.DownloadAction"> |
- jsp页面
1 | <%@ page language="java" contentType="text/html; charset=UTF-8" |
第二十四讲 ajax
- 在
Struts2中依然可以使用Servlet中的ajax
1 | package com.zhuchuli.ajax; |
- Struts2对ajax也提供了异步支持,使用步骤
- 导入相关jar包
- 编写jsp页面
1 | <%@ page language="java" contentType="text/html; charset=UTF-8" |
- 编写业务处理方法
1 | package com.zhuchuli.ajax; |
- 配置文件
1 |
|
第二十五讲 异常处理
- 异常处理在实际的应用开发中必不可少。比如:开发中不能直接将错误信息展示给用户看,需要对其进行处理,给用户一个更友好的提示。
- 异常处理类
1 | package com.zhuchuli.action; |
- 配置文件
1 | <action name="delete" class="com.zhuchuli.action.UserAction" method="delete"> |