通知 网站从因情语写改为晴雨,这个网站的模板也从calmlog_ex改为 whimurmur

尚硅谷STRUTS2视频学习笔记

1000人浏览 / 0人评论 / | 作者:因情语写  | 分类: struts  | 标签: struts2  | 

作者:因情语写

链接:https://www.proprogrammar.com/article/374

声明:请尊重原作者的劳动,如需转载请注明出处


  上一个月一直在学习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有一个了解,可以初步使用的样子。

我的项目代码如下:

项目代码


亲爱的读者:有时间可以点赞评论一下

点赞(0) 打赏

全部评论

还没有评论!
广告位-帮帮忙点下广告