一、Action类定义的三种方式
第一种:使用公共的pojo【Java类】作为Action,提供无参数的Action方法(不推荐使用)。
缺点:
没有一种方式约束Action方法必须是公共的无参数。
Action 方法的返回逻辑视图可以自定义指定,有时起名不规范。
第二种:定义一个类,实现com.opensymphony.cwork2.Action接口,并覆写 execute 方法即可.(不推荐)
缺点:
不支持国际化,数据校验,消息机制。
第三种:定义一个类,继承com.opensymphony.cwork2.ActionSupport类。(推荐)
比如:定义BaseAction类继承ActionSupport 类,其他的Action类继承BaseAction。
二、Action中的多方法调用方式
第一种:DMI :动态方法调用:官方不推荐
格式:action名 ! 方法名
比如:user!save
在struts2新版本中,默认关闭了DMI。若我们使用DML需要在xml中配置常量,启动动态方法调用,例如:
<constant name = "struts.enable.DynamicMethodInvocation" value="true" />
第二种:使用通配的方式来调用 ,通配符:* 【常用的方式】
语法格式:<action name="user_*" class="xxx.xxxx.xx" method="{1}"></action>
{1}:对应表示当前action配置中的第一个*
{2}:对应表示当前action配置中的第二个*
{n}:对应表示当前action配置中的第二n个*
比如:user_save 那么第一个值:save
user_update 那么第一个值:update
两个通配符:*_*
语法格式:<action name="*_*" class="xxx.xxxx.{1}x" method="{2}"></action>
1:是第一个星号类空间 2:是第二星号表示的动作
代码如下:
<action name="*_*" class="com.web.{1}" method="{2}"></action>
三、访问Servlet API的三种方式
Action 访问 Servlet API
1) 让Action类实现感知接口 【不推荐使用】
继承 ServletRequestAware 感知:HttpRequest 对象
继承 ServletResponsetAware 感知:HttpResponse 对象
继承 ServletSessionAware 感知:HttpSession 对象
运行流程:
当客户端发起请求,访问XXXActrion 对象,服务器会创建Action对象,判断当前对象是否实现了ServletRequestAware 感知接口,如果实现了会调用setServletRequest 这个重写的方法,这样就可以获取到ServletAPI,例如:
存在的问题:和ServletAPI耦合严重
2)可以通过ServletActionContext工具类
可以通过ServletActionContext类中的静态方法,得到Servlet相关的API
getRequest () getResponse ()
这种方式直接通过ServletActionContext的静态方法可以获取到Servlet的API对象,操作和理解相对简单。
ServletActionContext.getRequest().getParameter("参数名");
问题:依然是Action和ServleAPI存在耦合。
3)通过ActionContext 工具类
Struts2将作用域对象重新使用Map集合进行了封装,所以现在操作作用域中的共享数据就是直接操作对应的Map集合。
ActionContext 表示Action上下文对象,ActionContext 封装了每一次请求的信息。
可以使用ActionContext 中的非静态方法来获取Servlet相关的API,所需要的获取到ActionContext 对象。
请求参数语法:
ActionContext ac = ActionContext .getContext();
Map<String,Object> map= ac.getParameters(); --Map集合
这value :Object是个数组 ((String [])map.get("name"))[0];
Session的语法:
Map<String,Object> map= ac.getParameters();
session.put(key, value)
session.get(key)
四、请求参数的接收与封装
Action获取请求参数的三种方式,归功于拦截器(ParametersIntercepter)
第一种:Action本身作为Model对象,通过setter方法注入封装(属性注入)
例如:请求地址:http://localhost:8080/WebDemo/IndexAction_Save?name=12131&age=1
框架会调用setName方法将参数中名称为name的数据设置给name字段,框架帮我们做了类型装换。
private String name;
private int age;
public void setName(String name) {this.name = name;}
public void setAge(int age) {this.age = age;}
第二种:创建独立的Model对象,页面通过ognl表达式封装(属性注入)
将参数封装到指定的对象中。
例如:请求地址:http://localhost:8080/WebDemo/IndexAction_Save?u.name=new&u.age=11
1、新建个实体类 UserEntity 包含 name 和 age 字段和 set get方法
2、在action中定义UserEntity 变量
private UserEntity u; 同时给u设置get和set方法 。
public void setU(UserEntity u) {this.u = u;}
public UserEntity getU() {return u;}
第三种:使用ModelDrien接口,对数据进行封装(模型驱动 )【了解即可】
Action类继承 ModelDrien 接口,ModelDrien 为泛型。