尚硅谷STRUTS2视频学习笔记
上一个月一直在学习STRUTS2,学习的是尚硅谷佟刚老师的视频,因为很喜欢佟刚老师的声音,而且他讲的很细,笔记做的也多,基本上是照着他的视频完整的敲了一遍代码,下面就把学习到的知识梳理一遍,最后把项目分享一下,有需要的可以下载一下。佟刚老师是新建了很多个工程,而我是把所有的内容放在一个工程中的,所以可能有些乱。
工程的结构:


自己也照着所说的笔记自己敲了一遍。所以不但有代码,还有note.txt文件。
想看的话可以去尚硅谷官网去下载一下相关视频。
下面就说一说我印象深刻的一些东西吧。
首先上一张图

这就是处理一个STRUTS2请求的流程
STRUTS2的核心是一个Filter,请求会最先通过这个Filter,然后进行相应处理,首先通过ActionMapper判断请求是否是struts2请求,如果是struts2请求,那么会产生一个action的代理对象,他会与ConfigurationManager进行交互处理struts.xml配置文件,确定请求的是哪一个action,然后还会生成actionInvocation对象,该对象的invoke方法会调用拦截器栈,然后在拦截器中也会调用actionInvocation的invoke方法,最终的结果就是形成如图中间所示的interceptor...action...result...interceptor...这样的一串调用,产生的结果中的数据在页面中的标签中使用,此时也会被解析,然后就会返回给前台页面一个结果。
下面就具体说说STRUTS2的相关内容。
1. OGNL相关标签:
1)通用标签
主要有8个,

可以看项目中的common-tag.jsp文件或百度查看相关用法。
2)表单标签
主要有10个

可以看项目中form-tag.jsp或百度了解相关用法。
可以通过%{xxx}强制进行ognl解析,可以通过加单引号的方式强制使用字符串。可以通过#{key:value,key:value...}的形式构造map,在request,application等非根对象前加#进行调用。
2. 值栈的概念
简单的说:值栈是对应每一个请求对象的轻量级的内存数据中心。
Struts2中一个很激动人心的特性就是引入了值栈,在这里统一管理着数据,供Action、Result、Interceptor等Struts2的其他部分使用,这样一来,数据被集中管理起来而不会凌乱,大大方便了程序编写。
Struts2中关于值栈的另外一个很激动人心的特性就是:大多数情况下,你根本无需关心值栈,你不用管它在哪里,不用管它里面有什么,你只需要去获取自己需要的数据就可以了。也就是说,你可以隐式的使用值栈。
当然,如果编写自定义的Result或拦截器等较复杂功能的时候,还是需要显示访问值栈的,因此,还是需要你掌握值栈的知识。
可以通过<s:debug></debug>标签查看值栈里的信息
值栈分为MAP栈和对象栈,MAP栈如存放application,session,request,parameters的MAP,对象栈存放如action对象中的属性,如果页面上需要一个属性,他会按如下顺序进行查找
page,request,对象栈,session,application,其中在值栈中会先从栈顶依次向下查找。
3. 数据的处理
struts2对前台数据的获取十分简单,如有一个form表单,有很多input元素,他们有不同的name,则在后台只要在相关action设置与name同名的属性值并设置set方法即可获取到前台的数据,而且支持复合类型,
如何支持复合类型呢,只需要实现一个ModelDriven接口,如下

则和employee对象的属性同名的数据就会被赋给employee对象,当然数据类型要一致或可以转换,不可以转换的可以自定义转换器进行数据类型的转换,如果对数据还有进一步的要求,还可以对数据进行校验,分为声明式校验与编程式校验,这些在下面再说。
实现了modelDriven,要重写getModel方法,该方法返回一个Employee的对象,用于接收数据,上面还实现了一个Preparable接口,这个接口的作用是弥补modelDriven接口的不足,同时还定义了一个Employee中已有的属性employeeId,这是开发中常用到的技巧,因为getModel方法返回时employee对象还是空的,所以定义一个employeeId,他的赋值在getModel之前,这样在getModel时可以根据这个employeeId进行一些定制,这时就要用到一个拦截器栈
paramsPrepareParamsStack
其实我们还是没用getModel进行定制,因为我们实现了Preparable,所以通过Preparable结合employeeId进行定制,

paramsPrepareParamsStack如图
在1时给employeeId赋值,在2时调用preparable的相关方法,3时调用modelDriven的getModel方法,然后employee对象相关属性就可以被使用或赋值
我们要实现preparable的prepare方法,通过阅读源码可知,preparable还会调用尝试调用(prepare+方法名)或(prepareDo+方法名)的方法,所以在某个action调某个方法时,可以定义如上命名的一个方法,使用在1阶段被赋值了的属性,进行相应定制employee等复合对象操作,而在getModel中不做其它操作, 直接返回employee等复合对象。
这样我们通过使用paramsPrepareParamsStack拦截器栈中的1,2,3,实现了对action的定制,
这有什么用,举个代码里的例子,如我们想编辑某一个employee,前台只传了一个employeeId过来(后台对应方法为edit()),那么我们可以增加一个prepareEdit()方法,在获得employeeId之后,在prepareEdit中通过id查询数据库获得该employee的完整信息,将信息传给employee对象,然后在edit方法中就可以使用employee对象返回给前台编辑页面。
再如新增时(add()方法),可以通过prepareAdd给employee对象new一个对象,然后通过getModel返回employee对象,在add方法中employee对象就会有前台新增的数据,从而可以进行新增的操作。


这里面为了定制并没有使用prepare方法,这个方法一般情况下调用每个方法都会执行,要让他不执行,需要在STRUTS.XML文件中配置一个属性,如下图

按图中红框处使用
这就讲到了struts2的配置文件。
4. struts2.xml文件

文件以包为单位进行组织,包可以有命名空间,到页面上也就是一段路径
要继承一个struts-default包以使用继承的包里的相应功能。
可以定义一些constant常量以配置一些内容。这些constant常量可以从struts2-core-2.3.15.3.jar中的default.properties中查看。
还可以在包中定义一些全局的异常以及异常转向的页面。
struts.xml中主要就是包及包中的action

如果一个action不定义class那么会有一个默认的class叫做ActionSupport,如果不定义method会有一个默认的method叫做execute,如果result不定义name会有一个默认的name叫做success,如果result不定义type会有一个默认的type叫做dispatcher(转发)。action中还可以使用通配符,如上图,使用通配符后可以在method,result及返回的页面中通过{1}{2}...来获取通配符代替的内容。

如果我们想修改某个拦截器栈的内容可以通过上图的方式,即自己定义一个拦截器栈,在我们自定义的拦截器栈中对原拦截器栈进行修改,最后使用我们新定义的拦截器栈即达到了对原有拦截器栈的修改使用。

那如何在原有拦截器栈的基础上使用其它的拦截器呢,可以通过上图的方式,即通过interceptor-ref引用要使用的拦截器,不要忘了加上defaultStack默认拦截器栈。

,
result的类型常用的有上面几种,dispatcher是默认的转发到页面,redirectAction是重定向到action,也可以通过redirect实现,redirect是重定向,chain是转发到action,stream用于文件下载。
5. 获取struts或原生的作用域的对象application, session, request, parameter
1)获取struts的相关对象,有两种方法,
1. 通过ActionContext。
如下

2. 通过实现相应的xxxAware接口。

上面以application作为示例。
2)获取原生对象的方法
1. 通过ServletActionContext

session和parameter可以从request中获取
2)通过实现ServletxxxAware接口

6)i18n国际化

可以对Action或Model中的属性进行国际化配置,有三种方式,只对某个ACTION进行配置,对整个包下的ACTION进行配置,对整个项目进行配置。需要实现ActionSupport接口。
1)对某个ACTION进行配置:
如图中2:在ACTION中可以通过getText()方法获取相关国际化数据,命名规则为actionName_language_country.properties
2)对整个包进行配置:
如图中1所示,命名规则为package_language_country.properties
3)对整个项目进行配置
命名规则:name_language_country.properties
然后要在struts.xml文件中进行配置:


文件中可以使用OGNL表达式或者占位符,占位符在页面上进行填充

除了request_locale之外,还有一个request_only_locale,顾名思义,它的作用范围只限在当前页面。
7.自定义拦截器

可以实现AbstractInterceptor抽象类或Interceptor接口,继承抽象类的好处是抽象类中的大部分方法已经有了默认的实现,我们自己只需要实现某个核心的接口就可以了。而实现某个接口则要实现其中的所有的方法。
实现的方式如上图,中间要调用一下invocation.invoke()方法,使可以调用拦截器栈中的其它拦截器,然后在之前和之后可以写自己的代码,之前的代码会在调用ACTION之前调用,之后的代码会在调用ACTION之后调用。
光写好了类还不行,还要进行相关的配置才可以使用。

如图,先声明一下这个拦截器,然后就可以进行使用啦!
8.自定义转换器


可以继承StrutsTypeConvertor,重写其中的convertFromString,convertToString,或者实现TypeConverter
图中convertFromString中的arg0是上下文对象,可以获取一些上下文参数,arg1是要转换的字符数组,arg2是后台对应的数据类型
convertToString中的arg1是前台所需的对象,因为前台展示的是字符串,所以要进行类型转换或定制显示的内容。
写好了类当然要进行相关配置才可以使用啦。
也有两种配置方式,如果是针对某一个action,可以在同包下建立一个actionName-conversion.properties文件,如果是针对整个项目,可以在项目的根路径下新建一个名为xwork-conversion.properties的文件
两种文件的内容如下
java.util.Date=atguigu.type.convertor.DateConvertor
大致定义了对某种类型使用某种转换器。
还有自定义错误消息与错误消息的显示格式可以参看项目中的相关内容。
大致自定义错误消息就是在MODEL或ACTION的同一个包下新建一个actionName.properties的文件,内容为invalid.fieldvalue.xxxx=xxxx,第一个xxxx是字段名,第二个xxxx是字段转换出错时显示的错误消息。
9. 校验器
校验器分为声明式校验器与自定义的校验器,声明式校验器又分为字段校验与非字段校验,
声明式校验的相关内容可以参见:struts-2.3.16.1/docs/WW/docs/validation.html

如图是一个字段校验,如果一个ACTION类的不同方法对应的不同ACTION有不同校验规则,那么可以如图定义多个配置文件,配置文件的命名规则为actionClassName-actionName-valudation.xml,这样相关的action请求就会使用相关的校验规则,如果还有一个actionClassName-validation.xml的配置文件,那么该ACTION类的所有action请求都会使用该校验规则。


上图应用了一个非字段验证和一个自定义的验证
关于自定义验证:
首先新建一个类继承FieldValidatorSupport或ValidatorSupport,


其中format属性对应配置文件中的format参数,只要提供一个set方法,就可以进行使用,
validate方法的写法可以参照其它校验器,如何找到其它校验器呢?在xwork-core-2.3.15.3.jar中包com.opensymphony.xwork2.validator.validators下default.xml文件定义了默认的校验器。
主要是获取字段名,通过字段名获取字段值,对字段值进行校验,校验不通过时调用方法增加字段错误。
类写好了使用前要先配置,
在工程根目录下新建一个validators.xml,内容如下

然后就可以在相关的validation配置文件中使用我们定义的校验器了。如上面对idCard校验器的使用。
10. 文件的上传下载
1)文件的上传
以上传多个文件为例

这一组文件标签使用同一个name,然后在java文件中

使用一个List接收,同时还定义了两个新的属性,nameContentType,nameFileName,它俩会自动获取上传文件的内容类型和文件名,因为上传多个文件,所以用的List,
然后就可以把File对象的列表给保存起来啦。
STRUTS2的文件上传实际上使用的是APACHE COMMONS的Fileupdoad组件。
我们可以通过修改FileUploadInterceptor拦截器修改文件上传的配置,maximumSize,allowedTypes,allowedExtensions,还可以配置一次允许上传的最大大小,
配置方式如下:

当上传文件出错时,我们还可以自定义国际化的错误消息

在国际化文件中配置上面的内容,后面的占位符会显示出错文件的相关信息。
2)文件的下载
文件的下载要用到结果类型stream,文件下载时要配置一些参数,这些参数可以在struts.xml文件中进行配置,也可以在下载的action中通过属性的方式进行配置,只需要提供属性的get方法,


上面就通过在类文件中获取一部分配置项,在配置文件中配置一部分配置项的方式进行的下载操作。

上面是可以进行配置的七项内容。
11.防止表单的重复提交
重复提交有下面三种情况
1)多次点击提交按钮
2)已经提交成功,按回退之后,再点击提交按钮
3)在控制器响应页面的形式为转发情况下,若已经提交成功,然后点击”刷新(F5)“
下面两种情况不算重复提交
1)若刷新表单页面,再提交表单不算重复提交
2)若使用的是redirect的响应类型,已经提交成功后,再点击刷新不会重复提交
解决表单重复提交可以使用token或者sessionToken拦截器。
需要在页面上表单中使用s:token标签,具体的原理可以看相关视频,
然后在struts.xml中使用相关的拦截器,

有一点需要注意,如果使用的是token拦截器,则重复提交时会跳转到一个错误页面,所以要配置一个name为invalid.token的result,而如果使用tokenSession,则重复提交不会有任何结果,就像什么都没有发生过一样。
以上就是我学习的主要内容,但不是全部,视频中还有大量对源码的讲解和其它细节,可以参看视频了解。讲得没什么新意,就是把视频里的东西复述了一下,因为所知有限,也没有什么延伸,新学习STRUTS2,仅做一个记录,给同样是新手的人看一下大致对STRUTS2有一个了解,可以初步使用的样子。
我的项目代码如下:
尚硅谷STRUTS2视频学习笔记的更多相关文章
- 尚硅谷MySQL高级学习笔记
目录 数据库MySQL学习笔记高级篇 写在前面 1. mysql的架构介绍 mysql简介 mysqlLinux版的安装 mysql配置文件 mysql逻辑架构介绍 mysql存储引擎 2. 索引优化 ...
- 尚硅谷MySQL基础学习笔记
目录 写在前面 MySQL引入 数据库的好处 数据库的相关概念 数据库存储数据的特点 MySQL服务的启动和停止 MySQL服务端的登录和退出 MySQL的常用命令 MySQL语法规范 DQL(Dat ...
- struts2视频学习笔记 29-30(Struts 2常用标签,防止表单重复提交)
课时28 Struts 2常用标签解说 property标签 property标签用于输出指定值: <s:set name="name" value="'kk'&q ...
- struts2视频学习笔记 28(OGNL表达式)
课时28 OGNL表达式 OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目. Struts 2框架使用OGNL作为默认的表达式语 ...
- struts2视频学习笔记 24-27(国际化)
课时24 配置国际化全局资源文件.输出国际化信息 1.准备资源文件,添加到src目录下,资源文件的命名格式如下:baseName_language_country.propertiesbaseName ...
- struts2视频学习笔记 22-23(基于XML配置方式实现对action的所有方法及部分方法进行校验)
课时22 基于XML配置方式实现对action的所有方法进行校验 使用基于XML配置方式实现输入校验时,Action也需要继承ActionSupport,并且提供校验文件,校验文件和action类 ...
- struts2视频学习笔记 19-20(手工编写代码实现所有方法和指定方法校验)
课时19 对Action中所有方法进行输入校验 1.手工编写代码实现对action中所有方法输入校验 通过重写validate() 方法实现, validate()方法会校验action中所有与exe ...
- struts2视频学习笔记 18(自定义拦截器)
课时18 自定义拦截 因为struts2中如文件上传,数据验证,封装请求参数到action等功能都是由系统默认的defaultStack中的拦截器实现的,所以我们定义的拦截器需要引用系统默认的defa ...
- struts2视频学习笔记 15-17 (访问或添加request属性,文件上传)
课时15 访问或添加request/session/application属性 1.简单说 page指当前页面.在一个jsp页面里有效 2.request 指从http请求到服务器处理结束,返回响应的 ...
随机推荐
- MySql初试
初次使用MySql感觉有点不方便,习惯了使用MS Sql Server带来的便利,话不多说直接进入主题. 第一步.下载MySQL Community Server,下载地址:https://dev.m ...
- mysql 事务隔离级别详解
事物的 隔离级别,说简单非常简单(新手也能说出 是个隔离级别 和 影响),说男也非常难.(很多 有几年编程 经验的程序员依旧搞不清楚) 废话不多少 直接开始: 事务的隔离级别 是用来描述 事务的读关系 ...
- C# ObjectArx AutoCAD二次开发(转帖)
http://www.cnblogs.com/houlinbo/p/3325898.html 1.开发基本资料准备 用Vs2010进行Autocad 2010开发,首先下载ObjectArx 2010 ...
- react-router4.0的使用
近来很忙,学了一波react,特来记一笔,分享下react-router的使用方式 第一步引入内部组件 import {Route,BrowserRouter as Router,Switch,Lin ...
- [原]System.IO.Path.Combine 路径合并
使用 ILSpy 工具查看了 System.IO.Path 类中的 Combine 方法 对它的功能有点不放心,原方法实现如下: // System.IO.Path /// <summary&g ...
- Centos 6.5 升级python到版本2.7.12
查看python版本: python --version 1.下载Python-2.7.12 wget https://www.python.org/ftp/python/2.7.12/Python- ...
- post 中文数据到elasticsearch restful接口报json_parse_exception 问题
我们的客户端程序直接调用es 的restful接口, 通过post json数据去查询, 但post数据有中文的时候,有些中文会报异常,有些中文不会 {"error":{" ...
- chapter1 初识Go语言
1.1 语言简史 1.2 语言特性 I:自动垃圾回收 II:更丰富的内置类型 数组切片(Slice):是一种动态增长的数组. III:函数多返回值 func getName()(firstName, ...
- 学习MongoDB 一:MongoDB 入门(安装与配置)
一.简介 MongoDB一种非关系型数据库(NoSql),是一种强大.灵活.可扩展的数据存储方式,因为MongoDB是文档模型,自由灵活很高,可以让你在开发过程中畅顺无比,对于大数据量.高并发.弱事务 ...
- Where is virtualenvwrapper.sh after pip install?
I'm trying to setup virtualenvwrapper on OSX, and all the instructions and tutorials I've found te ...