1. Action 使用Servlet相关API
Action是对Servlet的封装, 实现了与Servlet相关的API解耦, 简化开发. 但有时又需要使用我们熟悉的Servlet API.
1.1 通过ActionContext类调用ServletAPI
ActionContext类的对象表示Action的上下文对象, 常用方法如下:
(1) ActionContext.getContext().get("request"): 返回值是Map, 需要强转, 相当于是一个解耦之后的HttpServletRequest
(2) ActionContext.getContext().getSession(): 返回值是Map, 相当于解耦之后的HttpSession
(3) ActionContext.getContext().getApplication(): 返回值是Map, 相当于解耦之后的ServletContext
(4) ActionContext.getContext().getParamerter(): 返回值是Map, 存储的是所有参数信息, 键是参数名, 值是具体的参数值, 类型是数组类型
1.2 通过实现一些Aware接口调用Servlet API
(1) Action类实现了RequestAware接口, 框架会把HttpServletRequest对象解耦成Map, 注入到Action类中
(2) Action类实现了SessionAware接口, 框架会把HttpSession对象解耦成Map, 注入到Action类中
(3) Action类实现了ApplicationAware接口, 框架会把ServletContext对象解耦成Map, 注入到Action类中
(4) Action类实现了ParameterAware接口, 框架会把请求中所有的参数信息封装成Map, 注入到Action类中
1.3 通过ServletActionContext类调用 ServletAPI
(1) ServletActionContext.getRequest(): 获取HttpServletRequest对象
(2) ServletActionContext.getResponse(): 获取HttpServletResponse对象
(3) ServletActionContext.getRequest.getSession(): 获取HttpSession对象
(4) ServletActionContext.getServletContext(): 获取ServletContext对象
总结:
ActionContext 和 Aware 这两种方式为间接调用Servlet API (解耦)
ServletActionContext的方式为直接方法(非解耦)
推荐使用ActionContext 和 Aware 这两种方式, 因为是解耦形式. 但是有些地方必须使用ServletActionContext. 比如文件下载里, 需要获取文件类型, 就要使用ServletActionContext
2. 请求参数的接收
请求参数的接收分为两大类 : 属性驱动, 模型驱动
2.1 属性驱动方式接收
(1)简单属性驱动方式接收
注意:
类中属性的名字要与页面参数名一致.
提供对应的setter方法
原理:
拦截器拦截用户请求, 调用Action类里属性的setter方法, 把参数值设置到对应的属性里面去
优势: 当参数比较少的时候, 采用这种方式接受简单.
弊端: 当参数比较多时, Action类里定义很多个属性及setter方法, 不便于向业务层传递参数, 比较麻烦
(2) 对象属性驱动方式接收
注意:
jsp页面中的参数名: (对象名.属性名)
因为在Action中需要用一个对象来接收, 所以说需要封装一个实体类(属性名要和页面中参数名对应, 提供属性对应的set方法)
在Action类里提供对象属性并提供对象属性对应的setter和getter方法
原理:
请求被拦截器拦截, 对参数名进行截取, 寻找Action里对应的属性名, 调用get方法, 获取到对象, 如果对象为null, 则调用实体类里的默认的构造方法实例化, 再调用对象属性的set方法把对象设置进去, 再把参数值通过对象的set方法把参数值设置到对象里. 当第二次设置参数时, 调用get方法获取对象, 但此时对象不为null, 调用对象set方法把参数值设置到对象里去
优势: 把参数封装到Action的对象属性里, Action类没必要提供很多的简单属相及set方法, 代码量少; 向业务层传递参数可以直接传递对象, 方便
弊端: 需要在页面中, 参数名前面加上对象, 写起来有点麻烦
2.2 模型驱动方式接收
注意:
创建Action类, 并让Action类实现ModelDriven<实体类>接口, 重写getModel方法, 返回对象属性
原理:
拦截器拦截请求(modelDriven, params), 判断该Action是否实现了ModelDriven接口, 如果实现了ModelDriven接口, 调用getModel方法, 获取对象, 把参数封装到对象的属性里去(调用对象的set方法)
优势:
(1)当参数比较多时, 会自动封装到对象属性里, 传递参数也简单
(2)页面上参数名字的书写简单, 不需要写成"对象.属性名"形式
三种方式总结:
如果参数比较少(一到两个) , 可以使用第一种
如果参数比较多, 建议采用第二种或者第三种
多种方式优先级问题: 先采用模型驱动方式接收, 再采用属性驱动方式接收
原因: 与值栈相关, 模型对象在栈顶, 在当前Action的实例前, 注入参数时, 优先找到的是模型对象
3.1 result结果集的配置
name 属性 : 结果集的名字, 与Action的方法的返回值对应, 一个Action节点可以对应多个结果集
注意: result的name属性默认是success, 如果想定义一个名字是success的result, 可以不加name
3.2 全局结果集和局部结果集
Struts2结果集按照作用范围不同, 分为两种结果: 局部结果和全局结果
局部结果集: 只针对某个Action有效.
全局结果集: 针对某个包下所有的action都有效
注意: global-results 节点必须放在所有action节点前, 并放在default节点后
3.3 结果集类型
在struts2-core.jar包中的sturts0default.xml文件中, 可以查看strut2所有的结果集类型
常用的结果集类型有:
(1) dispatcher: 转发到另一个页面, 地址栏不会发生变化.result节点type属性的默认就是dispatcher
(2)redirect: 重定向到一个页面, 地址栏会发生变化
(3) chain: 转发到另一个action, 地址栏不会发生变化
(4) redirectAction: 重定向到另一个Action, 地址栏会发生变化
(5) stream: 以流的形式响应一个请求, 文件下载时会用到
在struts.xml中, 通过result节点的type属性来指定跳转类型
4. Action是多例的
Action是多例的, 每请求一次Action类, 框架都会实例化一个Action对象