浅析 struts2
Posted Zempty笔记
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅析 struts2相关的知识,希望对你有一定的参考价值。
导语
查阅了很多资料去了解和学习 struts2 ,本文是对自己学习 struts2 的一个总结,以便淡忘的时候拿来回味一番。
struts2 的初印象
struts2 是一个用来同 web 端页面和后端数据进行交互的一个框架,在 MVC 中更多的是担任 C 的角色。相较于 servlet ,struts2 框架的优势就是写很少的代码,做到想做的事(框架的底层代码可能帮我们实现了部分需求)。
在 Java 的编程中 ,struts2 有着很重要的地位。找工作可能明确要求要会 struts2,因此在接触她之前,我对她有着很多的期待,可以说是迫不及待,想早点拥有她,当我细细品味之后发现她其实跟 servlet 长的很像。长的比 servlet 好看,有点难追!
开追 struts2
工欲善其事,必先利其器。学习 struts2 的最好方法我认为是去 strut2 的官网,了解一下应该怎么开始 struts2 。首先第一步是准备 struts2 的工具( struts2 需要的一些jar 包 ),官方网站的介绍是通过 Maven 来构建 struts2 的 jar 包的,这样做方便快捷,但是如果你对 Maven 不是很了解,我建议下载 struts2 的文件,然后根据文件提供的例子,拷贝所需要的 jar 包即可。如图所示:
这是官方下载下来的文件 :
打开文件找到apps 点击打开 :
解压缩其中的一个例子 :
我是通过修改例子的后缀名为.zip ,然后拷贝需要的 jar 包
如上图所示:在解压缩的 WEN-INF 文件夹里面找到 lib 文件夹 ,在 lib 文件夹里面拷贝所需要的 jar 包到新建的 web 工程中。这里需要特别强调一下:切记不要拷贝所有的 jar 包,这样容易导致你的工程执行 action 时出现 404 错误。下面是工程需要的 jar 包 :如图所示:
第二步编写一个 Java 类 ,其中包含方法名为 execute 和返回值为 String 的方法,编写完成后,在 classpath 路径下面配置一个名称为 struts.xml 文件(其实就是在 src 下面配置 struts.xml ,如果要是使用 Maven 的话,就在 src/main/resources 下面配置 struts.xml 文件)。
关于这两张图片做一下稍微的解析:strut2 会默认执行类中的 execute 方法 ,而且会根据方法的返回值做出相应的处理,比如说 :转发、跳转等。在 struts.xml 文件中首行定义了 XML 文件的版本和编码方式,下面一行则是引入 struts2 的 .dtd 文件,它定义了 struts2 的 XML 文件特有的格式,节点构成。所有的节点都在根节点<struts></struts>标签中,<package>标签是一个包,里面装着不同的 action ,它有常用的三个属性 name 用来表示这个包的名称,namespace 是一个路径,在浏览器中用来定位 action ,extends 表示该包继承的父包名称,一般都是继承 struts-default 。包中的 action 用来表示定位你写的哪一个类,要做什么处理,action 中的 name 属性用来给你所定义的类起个名字,用来在浏览器中定位资源,class 则是只能指名你所要操作的是哪个类。result 标签中 name 表示方法的返回值,同 execute 方法的返回值一致。result 标签中的文本标签 /index.jsp 表示执行完这个 action 要转发到的页面是 index.jsp 。
第三步配置 web.xml ,如图所示:
新建一个 index.jsp 用来测试 action 的效果
前面所述都是在你建立的 web 项目中操作的。下面把我的工程截图如下:
下面启动服务器运行第一个 action 。
浏览器路径中输入你要操作的 action 名称 ,最好加上 .action 后缀,如上图所示。
如果你经过操作看到了上面的页面,那么恭喜你!你的 struts2 的征程正式开启了 !
struts2 编写 action 类
上文提到的一个类 HelloStruts2 就是一个 action 类,上文强调方法中需要有 execute 方法 ,因为 struts2 框架中默认执行 action 中的 execute 方法。
下面就来分析如何编写 action 类:
第一种方法:编写一个 Java 常规类,类中的方法返回值为 String 类型,这样方便根据返回值 ,进行页面的转发、跳转等。然后在 struts2 .xml 文件中进行 action 的配置。具体配置上文有提到,可参考。
第二种方法:编写一个 Java 常规类继承框架中的 Action 接口,并实现 Action 中的execute 方法,然后配置 struts2.xml 文件。如图所示:
第三种方法:编写一个 Java 常规类,让该类继承 struts2 中的 ActionSupport 。 分析ActionSupport 类就可以知道它也是实现了 Action 接口,继承类的好处是不需要去重写跟需求无关的的方法,既可以拓展父类父类中的方法,又可以把父类中的东西直接拿来用。我认为最大的一个好处是让人一目了然,一看就知道这是一个 action 类,所以建议使用第三种方法创建 action 类。如图所示:
解析 struts.xml
分析上面的情况:有这样一种情景:有一个工程,有多个人去负责开发,A 开发的时候去配置一个 struts.xml ,B 也去配置一个 struts.xml ,C 也如此,。。。,那么请问应该用谁的 xml 呢?可以汇总,整合,这样可以实现但是太麻烦,针对这种情景,有一个普遍的做法就是 A 去定义一个自己的 .xml 文件,同上文提到的 struts2 配置相同,最好是类名.xml ,B 呢也去自己定义一个,依次类推。然后在定义一个 struts.xml 文件,把所有人定义的 .xml 文件都引入进来就可以了,如图所示:图中的 struts-one.xml 就是我自己定义的一个,引入 struts.xml 就可以使用了。
下面在分析一个情景,上文提到了 action 创建的时候默认执行 execute 方法,如果我的action 类中有多个方法呢?我想要执行我需要的方法总么办呢?下面给出两种解决的办法,都是配置文件来解决的:
如上图 ,我想执行图中的 testMethod1 方法或者 testMethod2 方法,需要在配置文件中做如图所示的配置:
打开服务器,浏览器中输入相应的 action 就会执行对应的方法:
将会执行 testMethod1 方法。
将会执行 testMethod2 方法。
上面的问题解决了,但是如果一个 action 类中的方法很多,配置文件就会配置很多的action。于是可以通过通配符去解决这个问题。如图所示:
在浏览器中输入如下路径就会访问 test_Method1 方法 :
但是上面的配置方式在 struts 2.5 的版本中是行不通的,输入相应的路径会报 404 的错误 ,应该采用如下的方法配置,在配置文件中列出允许执行的方法:
下面在说明一个场景,如果多个方法返回同一个值,转发到同一个页面,配置文件的 result 标签就会大量的重复,如何解决呢?配置全局变量。如图所示:
struts2 获取表单数据
一、普通方式获取表单数据
在 servlet 中获取表单的数据主要是通过 HttpServletRequest 获取。同样在 action 类中可以通过类似的方法获取:下面介绍如下:
(1)通过 ActionContext 获表单请求数据:
ActionContext context = ActionContext.getContext();
Map<String, Parameter> map = context.getParameters();
介绍一下 map 中的 key 是表单中的 name 值 ,value 是表单中的 value 值
(2)通过 ServletActionContext 获取 HttpServletRequest ,然后获取表单中的数据
HttpServletRequest request=ServletActionContext.getRequest();
ServletActionContext 可以得到 servlet 中的三个域对象。
二、通过属性封装
(1)、在 action 类中封装同表单名称一样的属性。
(2)、生成属性的 setter和getter方法。
如图所示:
三、表达式封装
(1)、在 action 中声明一个实体类。
(2)、创建实体类的 set 、get 方法。
(3)、在请求表单中使用 实体类 . 属性 的方式。
当使用表达式封装的时候,一定要注意表达属性的命名,要使用 action 中定义的实体类引用.实体类的属性名。
四、模型封装
(1)、定义的 action 要实现 ModelDriven 接口。
(2)、实现 getModel 方法。
模型驱动封装需要注意一定要把定义的实体类实例化。这样数据才能封装进去。
上述的五种方式,模型驱动经常用到,有时候可能需要用到其他几种进行对数据的封装,可以根据自己的需求进行合理的应用。
struts2 的值栈
struts2 值栈主要分为两部分 一部分叫 root 是个 list 集合,一部分是context 是个 map 集合 。通过 struts2 的 debug 标签可以很清晰的看到值栈中的内存结构(<s:debug />)。
一、向值栈中放入数据通常有三种方法:
(1)、调用值栈中的 set 方法。
(2)、调用值栈中的 push 方法。
(3)、在 action 中定义变量 ,生成 get 方法。
(4)、通过上述的模型封装,数据也会进入值栈。
二、从值栈中取出数据
通过 struts2 标签和 ognl 表达式一起使用来获取值栈的数据。
(1)、取出通过 set 方法放进值栈的数据。
(2)、取出通过 push 方法放进值栈的数据。
通过标签 <s:property value="[0].top" 获取的是值栈栈顶的数据,一般 push 都把数据推到栈顶。
(3)、取出通过 action 放进值栈的数据。下面在 action 中定义一个 List 属性,然后通过 struts 标签遍历 List 集合取出数据。
关于上图遍历 list 的集合的时候一定要注意有两种遍历方法,需要注意自己采取哪种方法进行遍历,下面是通过第二种方法获取遍历的 list 集合,一定要注意下图标识的 # 标识符必须使用:
(4)、通过模型封装的方法获取值栈。
通过模型驱动不单单可以从表单获取数据封装到实体类中,还可以把实体类的数据输出到页面当中。
struts2 的拦截器
拦截器是在 action 对象创建之后,action 的方法执行之前执行的。
拦截器实现原理:
(1)、AOP :就是面向切面编程。用我的理解就是:不改变原来方法的代码,就可以拓展其功用。
(2)、责任链模式:就像 servlet 中的过滤器,多个过滤器按顺序执行,然后执行目标代码,然后在依次经过过滤器一一返回。责任链模式跟过滤器的过滤链模式功用相同。
如何去定义一个过滤器呢?
查看 struts2 的源代码你会发现有这样一个抽象类叫 AbstractInterceptor ,它是实现的是 Interceptor 的接口。因此我们可以有两种方式定义一个拦截器,继承 AbstractInterceptor 或者实现
Interceptor 接口。
通常的做法是继承接口,这样我们不用去复写不必要的方法,只关心主要的功能即可。下图是继承 AbstractInterceptor 的一个自定义拦截器。
定义完一个拦截器,应该如何使用呢?去配置文件配置拦截器。如图所示:
如上图红线框标注的是配置一个拦截器,在配置拦截器的过程中最好把默认的拦截器给引用进来,否则,struts2 默认的拦截器将不会执行,如上图红线标注是引用的默认拦截器。
有可能你的某些方法并不需要执行拦截器,那么应该怎么去做处理呢?
有这样一个类叫 MethodFilterInterceptor 它是继承了 AbstractInterceptor 。我们定义一个类去继承它就可以去解决上述问题。如下图所示:
重要的是我们自定义拦截器的时候通常都是继承 MethodFilterInterceptor 这个类,因为它用起来更方便,更实用。
如上图所示配置,就可以不让 action 类中的 test 方法执行拦截器。
总结:
本文浅析了什么是struts2、struts2 中 action 的定义和使用、struts.xml 文件的解析、struts2 的数据封装,、struts2 的值栈、struts2 的拦截器。
记忆力很差,有时候用到相关知识点的时候总是不那么流畅,因此总结记录一下,以便随时阅读回味。
推荐阅读
Zempty 笔记
生活|写作|程序员代码
以上是关于浅析 struts2的主要内容,如果未能解决你的问题,请参考以下文章