1.Struts2介绍
- Struts2是一个MVC层的框架
- 是Struts1+Webwork两个框架结合而成的,大部分的功能都采用的是webwork的组件
- Struts2框架采用了非侵入式设计
- POJO:纯的java对象
2.hello Struts2
- 导包
- 配置web.xml文件
- 编写Action类,这是我们的逻辑控制器
- 配置src/struts.xml,核心配置文件中配置action
3.StrutsPreparedAndExecuteFilter
- 为Struts2的前端控制器,需要在xml文件中配置
4.Action
- 后端控制器:
- 程序开发的核心
- Action的配置:
- package包:
- 一个包中可以包含多个action
- package中常用的属性:
- name必填,package的名,其他package通过此名找到这个包
- namespace 命名空间(很有用),这个包中的所有Action的请求路径必须在此命名空间下
- extends 父包
- Action:配置action
- name:action的请求名
- class:Action的类名(全称)
- method:方法名,比如save
- package包:
5.Result标记
- 这个标记是action的子标记,用来设置action的跳转资源的路径及方式
<result name=”success”>/success.jsp</result>
- name:资源名
- success.jsp:资源地址
6.Action如何访问Servlet的API
- struts2中
- 注入的方法(通过IOC方式将servlet对象注入到Action中)
- 为当前Action提供对session的支持
- Action实现一个接口:SessionAware
- 实现setSession方法,这个方法由struts2来调用,并传递一个代表session的map
- 为当前Action提供对session的支持
- 利用上下文(由Struts2提供)方法
- 使用解耦的方式访问ServletAPI
- 只需要通过一个ActionContext对象即可
ActionContext ctx=ActionContext.getContext();
ctx=ActionContext.getContext();
ctx.getSession();
ctx.getApplication();
ctx.get(“request”);
ctx.getParameters();
- 只需要通过一个ActionContext对象即可
- 使用解耦的方式访问ServletAPI
- 注入的方法(通过IOC方式将servlet对象注入到Action中)
- 原生的ServletAPI访问方法
- 注入方式:实现ServletRequestAware接口
- 上下文:ServletActionContext.getRequest()等方法
7.Action返回Result的类型
- dispatcher:
- 相当于forward,但只能转发到固定的资源,比如jsp,而不能转给另一个action
- chain:
- 可以将请求转给另一个action
- redirect:
- 重定向到任何资源,包括action
参数有location
- 重定向到任何资源,包括action
- redirectAction:
- 重定向到另一个action,甚至是其他包
- 参数有actionName,namespace
8.相对于Struts1配置简单,utf-8不需要转码
9.Struts1封装Servlet,Struts2封装过滤器
10.Servlet整个过程创建一个对象,而Struts2每提交一次创建一个新对象
11.debug调试方法
- 设置断点(在代码左侧的边框上双击鼠标左键)
- F6单步执行
- F5进入方法体
- F7从方法中返回
- F8进入下一个断点,如没有则正常运行
12.Action的配置
- 通配符的使用:
- Action中的name属性可以使用*作为通配符,只要匹配到name的格式,就会找到对应的方法,在method属性中可以使用{0}和{1}.数字表示*的序数
- 配置exception-mapping
- 当action出现异常的时候,将会将请求转发给对应的result。
13.动态方法调用
- 可以简化action的配置,但不建议使用,因为不够安全,默认Struts2对此功能禁用
- 如果使用,则需要修改配置
vaue设置为true。动态方法调用时,需要在url中包含方法,格式是actionName.action<constant name="" value="true"></constant>
14.ActionSupport类
- 这个类实现了很多Action都需要实现的功能,一般来说,我们在定义一个Action时,最好是继承此类
- 如果我们配置Action时不指定class,那么这个action将会实例一个ActionSupport对象
15.参数组装的方式
- 直接组装Action的属性
- 组装到action中的一个实体对象中;要求表单的组件名应该是 对象名.属性名
- 通过ModelDriven接口返回一个对象;(接口上最好加上泛型)
16.类型转换
- 内置的转换器:
- 自定义转换器:(不常用)
17.内置转换的类型
- 8种基本数据类型及它们的包装类
- String
- Date
- 数组
- List集合:可以通过[ ]来确定list中的元素位置
18.ognl
- 对象图导航语言,是一个表达式语言:是el表达式的增强版,是一个独立的组件
- Struts2集成了ognl,在Struts2中可直接使用ognl表达式
19.ognl的基础
- ognl上下文 map
- 表达式
- 根元素
20.struts2中的ognl上下文
- Struts2的ognl上下文中包含很多作用域对象,例如,request,session,application等,根元素是valueStack
- Struts2会自动向valueStack中压入textProvider对象和当前的Action对象
- 如果想向valuestack中增加新的元素,可以通过ActionContext.getContext().getValueStack()得到值栈,并向值栈中添加元素
- 访问值栈的表达式
- [n] :从某个位置的元素开始取
- [n].top:只取某个位置元素的某属性
21.ognl中常用的符号
- #:获取非根的元素
- %:计算ognl表达式
- $:在配置文件中使用ognl
22.拦截器
- 这是struts2最重要的一个组件,Struts2的大多数功能都是通过拦截器来实现的;例如,文件上传,参数组装,重复提交,modelDriven等功能;
23.Struts2的拦截器分为两种
- 预定义的
- 自定义的
24.代理模式
- 解决:
- 我们不能直接访问一个对象
- 抽象角色
- 代理角色
- 真实角色
- 我们不能直接访问一个对象
25.Struts2拦截器的工作原理
- Struts2会根据struts.xml配置文件,动态的创建一个代理对象,这个代理对象的名字是ActionProxy,它里面包含了n个拦截器以及Action
26.配置拦截器
- 例子:实现表单重复提交
- 自定义Action,配置在action里,需要在Action节点中增加token拦截器
- 在表单中增加标记
27.自定义拦截器
- 定义一个实现了Interceptor接口的拦截器
- 在struts.xml文件中配置拦截器
28.struts2的配置文件
- 配置常量可以在5类配置文件中进行配置
- 它们的顺序如下,如果有重复的配置,后面的配置将会覆盖之前的配置
- struts-default.xml
- struts-pluging.xml
- struts.xml
- struts.properties
- Web.xml
29.文件上传
- 编写jsp上传页面,form表单的enctype属性=multipart/form-data;还需要增加一个file组件;
- 编写Action时,每个上传文件应该对应三个属性
- 例如上传组件的名字是pic,那么,三个属性分别是:
- File pic; //文件本身
- String picFileName; //文件名
- String picContentType; //文件内容类型
- 例如上传组件的名字是pic,那么,三个属性分别是:
- 如果想改变上传文件的最大字节数,可以在struts.properties中修改struts.multipart.maxSize的值
-
若要防止上传文件名重复而被覆盖,并把文件放到工程中,可以如下操作:
//获取pic的真实路径 String path = ServletActionContext.getServletContext().getRealPath("/pics"); String[] names = picFileName.split("\\."); String extend = names[names.length-1]; //生成一个随机文件名 String name = UUID.randomUUID().toString()+"."+extend; System.out.println(name); //上传之后存在服务器的硬盘上; try { FileUtils.copyFile(pic, new File(path+"/"+name)); } catch (IOException e) { e.printStackTrace(); }
30.多文件上传
- 可以通过数组或List集合来实现多文件上传
31.文件下载
- 实现原理:
- 通过result来实现,type的值是stream
- 实现步骤
- 在Action中返回一个type=stream的result;
- 配置result,为它添加两个属性,分别是:
- inputName
- contentDisposition
其中inputName代表返回给浏览器的一个字节流,因此需要在action中定义一个返回字节流的方法;例如
<param name="inputName">image</param>
那么,struts2将会调用action中的getImage方法,并且将返回的字节流写到浏览器中,完成下载
32.Struts1与Struts2的区别
- Action实现类方面:
- Struts1要求Action继承一个抽象基类
- Struts2中Action类既可以实现一个Action接口,也可以实现其他接口
- Servlet依赖方面:
- Struts1 Action依赖于Servlet API,因为Struts1 Action的execute()方法中有HttpServletRequest和HttpServletResponse方法
- Struts2 Action不再依赖于Servlet API,因为Struts2的Action是由POJO组成,在Struts2中,Servlet上下文以简单Map的形式表现出来,这使得Action可以进行独立的测试
- 可测试方面:
- Struts1中Action的测试依赖于Web容器或借助第三方扩展:Struts TestCase
- Struts2中Action可通过初始化、设置属性、调用方法来测试
- 封装请求参数:
- Struts1使用ActionForm对象封装用户的请求参数,所有的ActionForm必须继承一个基类——ActionForm。开发人员需要创建大量的ActionForm类封装用户请求参数
- Struts2直接使用Action属性来封装用户请求参数,避免了大量开发ActionForm类的繁琐。可使用ModelDriven模式
- 表达式语言方面:
- Struts1使用jstl
- Struts2可以使用jstl,但有更强大的ognl
- 绑定值到视图:
- Struts1使用标准JSP机制把对象绑定到视图页面
- Struts2使用ValueStack技术,使标签库能够访问值,而不需要把对象和视图页面绑定在一起
- 类型转换:
- Struts1中ActionForm属性通常是String类型。Struts1使用Commons-Beanutils进行类型转换,转换器不可配置
- Struts2使用ognl进行类型转换,支持基本数据类型和常用对象之间的转换
- 数据校验:
- Struts1和Struts2都支持通过validate()方法的手动验证
- Struts1支持在ActionForm重写validate()方法中手动校验或者通过整合Commons alidator框架完成数据校验
- Struts2支持通过重写validate()方法进行校验,也支持整合XWork校验框架进行校验
- Action执行控制:
- Struts1支持每一个模块对应一个请求处理(即生命周期的概念),但是模块中的所有Action必须共享相同的生命周期。
- Struts2支持通过拦截器堆栈为每一个Action创建不同的生命周期
- 捕获输入
- Struts1使用ActionForm对象捕获输入
- Struts2直接使用Action属性作为输入属性,消除了对第二个输入对象的需求