Struts2详解(三)

Struts2访问Servlet的API



	 在struts2中,Action并没有直接和ServletAPI进行耦合,也就是说Struts2的Action
不能直接访问ServletAPI。
	虽然解耦能带来很多好处,但是Action完全不访问Servlet API几乎不可能,在实现业务逻辑
的时候,经常要访问Servlet中的对象,如:session、request、application等

	在Struts2中,访问ServletAPI的方式有三种:


第一种:通过ActionContext类访问

ActionContext是Action执行的上下文对象,在ActionContext中保存了Action执行所
需要的所对象。


ActionContext类访问ServletAPI的几个常用的方法:

void put(String key, Object value) : 将key-value键值对放入ActionContext中,
模拟ServletAPI中的HttpServletRequest 的setAttribute()方法

Object get(String key) :通过参数key查找当前ActionContext中的值
Map<String,Object> getApplication() :返回一个Application级的Map对象
static ActionContext getContext() :获取当前线程的ActionContext对象
Map(String,Object) getParameters() :返回一个包含所有HttpServletRequest参数信息的Map对象




代码:
ActionContext context = ActionContext.getContext();
context.put("键","值");


context.getApplication.put("键","值");


//接收请求参数:
Map<String,Object> map = context.getParameters();
for(String key : map.keySet()){
Object value = map.get(key);
System.out.println(value);
}

通过以上方法的调用,分别在request、application中放入了键值对。并从页面中获得表单
传来的参数。


第二种:通过特定的接口访问

ActionContext类可以访问ServletAPI,但是无法直接获得ServletAPI实例,为了让Action中
直接访问servletAPI,Struts2提供了一系列接口:


ServletRequestAware: 实现该接口的Action可以直接访问Web应用的HttpServletRequest实例
ServletResponseAware:
SessionAware:
ServletContextAware:


例如:

public class ActionDemo extends ActionSupport implements SetvletRequestAware{
HttpServletRequest request;


@Override
public void setServletRequest(HttpSetvletRequest request){
this.request = request;
}


@Override
public String execute() throws Exception{
reuqest.setAttribute("message","通过SetvletRequestAware接口实现访问ServletAPI");
return SUCCESS;
}
}

第三种:通过ServletActionContext访问



为了直接访问ServletAPI,Struts2框架提供了ServletActionContext类,该类提供了几个静态方法,如下:


1)static HttpServletRequest getRequest() : 返回web应用的HttpServletRequest对象
2)static HttpServletResponse getResponse() : 返回web应用的HttpServletResponse对象
3)static ServletContext getServletContext() : 返回web应用的ServletContext对象
4) static PageContext getPageContext() : 返回web应用的PageContext对象




代码:
public class ActionDemo extends ActionSupport{

@Override
public String execute() throws Exception{
//获得web应用的HttpServletRequest对象
HttpServletRequest request = ServletActionContext.getRequest();
return SUCCESS;
}
}






结果页面的配置

一、全局结果页面:是指同一个包(package)下配置的Action中返回相同字符串的值,都可以向这个页面来进行跳转



<global-results>
<result name="success">/success.jsp</result>
</global-results>

二、局部结果页面:是指在某个Action中返回的字符串的值,会向这个页面进行跳转

<action name="actionDemo" class="cn.scx.action.ActionDemo" >
<result name="success">/demo.jsp</result>
</action>


Struts2数据封装



页面提交请求到Action---Action接收参数并对请求参数进行数据封装----封装到javaBean中---将javaBean传递给业务层




数据封装分为两大类:


第一类:属性驱动

也可以分为两类:一种只需要提供属性的set方法。另一种通过表达式方式(OGNL)直接封装到对象中


在struts2中,可以直接在Action中定义各种java基本数据类型的字段,使这些字段与表单数据相对应,
并利用这些字段进行数据传递。


1)通过set方法

<form action="#" method="post">
<input type="text" name="name"/>
<input type="text" name="age"/>
<input type="sumbit" name="提交"/>
</form>


public class ActionDemo extends ActionSupport{
//接收参数
private String name;
private String age;
public void setName(String name){
this.name =name;
}
public void setAge(String age){
this.age =age;
}


@Override
public String execute() throws Exception{
System.out.println(age);
return SUCCESS;
}
}
注:这种方式需要在Action中定义很多属性,并提供set方法。会使Action代码臃肿。
可以把属性和set方法提取出来,放进一个对象中,这个对象就是封装数据的,一般用javaBean来实现。
javaBean就是数据传递的载体。

2)页面提供表达式方式(OGNL)

<form action="#" method="post">
<input type="text" name="user.name"/>
<input type="text" name="user.age"/>
<input type="sumbit" name="提交"/>
</form>


public class ActionDemo extends ActionSupport{
//接收参数
private User user;
//必须提供对象的get方法
public User getUser(){
return user;
}
public void setUser(User user){
this.user =user;
}


@Override
public String execute() throws Exception{
System.out.println(user);
return SUCCESS;
}
}
注:这种方式需要提供user的get方法,如果没有,struts2底层就没有办法得到user对象
那么在user中只会有一个属性被封装进去,而其他属性都是null。

第二类:模型驱动

通过实现ModelDriven接口来接收请求参数,Action必须实现这个接口,并重写getModel()方法,这个方法
返回的就是Action所使用的数据模型对象。


模型驱动通过javaBean模型进行数据传递


代码:
<form action="#" method="post">
<input type="text" name="name"/>
<input type="text" name="age"/>
<input type="sumbit" name="提交"/>
</form>


public class ActionDemo extends ActionSupport implements ModelDriven<User>{
//手动构建对象
private User user = new User();
//必须提供对象的get方法
public User getModel(){
return user;
}


@Override
public String execute() throws Exception{
System.out.println(user);
return SUCCESS;
}
}


注:如果传递的数据为单个对象的属性时,优先使用这种方式。



封装集合类型的数据:

第一种:封装到List集合中:

<form action="#" method="post">
<input type="text" name="list[0].name"/>
<input type="text" name="list[0].age"/>


<input type="text" name="list[1].name"/>
<input type="text" name="list[1].age"/>
<input type="sumbit" name="提交"/>
</form>


public class ActionDemo extends ActionSupport{
//接收参数
private List list<User>;
//必须提供对象的get方法
public List<User> getList(){
return list;
}
public void setList(List<User> listr){
this.list =list;
}


@Override
public String execute() throws Exception{
for(User user : list){
System.out.println(user);
}
return SUCCESS;
}
}

第二种:封装到Map集合中:

<form action="#" method="post">
<input type="text" name="map["one"].name"/>
<input type="text" name="map["one"].age"/>


<input type="text" name="map["two"].name"/>
<input type="text" name="map["two"].age"/>
<input type="sumbit" name="提交"/>
</form>


public class ActionDemo extends ActionSupport{
//接收参数
private Map map<String,User>;
//必须提供对象的get方法
public Map<String,User> getMap(){
return map;
}
public void setMap(Map<String,User> map){
this.map =map;
}


@Override
public String execute() throws Exception{
for(String key : map.keySet()){
User user = map.get(key);
System.out.println(key + "----"+ user);
}
return SUCCESS;
}
}




Struts2的默认表达式语言 OGNL(对象图导航语言)

使用OGNL,可以通过某种表达式语法,存取Java对象的任意属性,调用Java对象的方法,同时能够自动实现
必要的类型转换。


特点:
1)支持对象方法的调用:objName.methodName();
2)支持类静态方法调用和值的访问,格式为:
@[类全名]@[方法名 | 值名] @java.lang.String@format('foo %s', 'bar');
3)支持赋值操作和表达式串联
4)访问OGNL上下文 和 ActionContext
5)操作集合对象


OGNL结构:
1、表达式
带有语法含义的字符串,表达“要做什么操作”
2、根对象
可以理解为OBNL的操作对象,表达“对谁操作”
3、context对象
根对象所在的环境就是OGNL上下文环境,表达“在哪里进行操作”
上下文环境Context是一个Map类型的对象,
在表达式中访问Context中的对象,需要使用“#”号加上对象名称。


public void demo() throws OgnlException{
OgnlContext context = new OgnlContext();
Object obj = Ognl.getValue("'helloworld'.length()", context, context.getRoot());


System.out.println(obj); //结果为10
}

值栈(ValueStack):

ValueStack是Struts的一个接口,字面意义为值栈,OgnlValueStack是ValueStack的实现类,客户端发起一个请求struts2会创建
一个Action实例,并且同时创建一个OgnlValueStack值栈实例,OgnlValueStack贯穿Action的生命周期。struts2将Action的请求参数
封装为对象存储在值栈中,并通过OGNL表达式读取值栈中对象的属性值。


值栈的内部结构:

1.Root栈(list)
CompoundRoot:继承AraryList 实现压栈和出栈功能。存储Action实例和请求参数等
拥有先进后出,后进先出特点,最后压进栈的数据在栈顶,成为对象栈。


使用OgnlValueStack的findValue()方法可以在CompoundRoot中从栈顶向栈底查找对象的属性值
2.map(ognl上下文)栈
存储了一些引用,parameters、request、session、application等,上下文的Root为CompoundRoot



ActionContext 和 ValueStack 的关系

1.在创建ActionContext 的时候,创建ValueStack对象,将ValueStack对象给 ActionContext
2.ActionContext中有ValueStack的引用,ValueStack中也有ActionContext的引用
3.ActionContext获取ServletAPI的时候,依赖的是值栈



获取值栈对象:
1.通过ActionContext对象获取值栈
ValueStack vs = ActionContext.getContext().getValueStack();
2.通过Request域获取值栈
ValueStack vs = ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);


值栈的问题

1.什么是值栈 ValueStack ?

本质:数据的中转站,值栈ValueStack是struts2的一个接口规范,其作用就是存储Action在访问过程中
的一些数据


一次访问对应一个Action对象,一个Action对象对应一个ActionContext对象,一个ActionContext对应一个
ValueStack对象,可以认为值栈对象的生命周期与Action同步

2.值栈的内部结构 ?

对象栈/Root栈 ---本质List
Context栈/map栈 ---本质Map

3.如何获得值栈对象 ?

1.通过ActionContext对象获取值栈
ValueStack vs = ActionContext.getContext().getValueStack();
2.通过Request域获取值栈
ValueStack vs = ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);

4.如何向值栈保存数据

值栈的内部结构:Root 和 Context


1.向Root栈保存数据
/**
* 手动保存
*/
ValueStack vs = ActionContext.getContext().getValueStack(); //得到值栈对象


CompoundRoot root = vs.getRoot(); //得到Root栈

//使用List方法存储
root.add("a"); //这种方式存储到Root栈(List)的栈底


//使用原始方法向栈顶放置数据
root.add(0,"b");


//使用Root封装好的方法向栈顶存储数据---压栈
root.push("c");


root.peek();//取出栈顶数据
root.pop();//弹出栈顶数据


注:struts2自动向Root栈保存数据,保存的数据有 ---当前Action对象   ---当前Model对象(传递的参数)


2.向Context栈保存数据
ValueStack vs = ActionContext.getContext().getValueStack(); //得到值栈对象


Map<String,Object> context = ValueStack.getContext();


向map中存储数据。。。


注:struts2自动向Context栈保存数据保存的数据有
---request对象
---response对象
---servletContext对象
---request域数据
---application域数据
---session域数据
---paramters提交的参数
---attr所有域数据

5.如何取值栈的数据 ?

主要是jsp中如何取数据-------------->struts标签 + ognl表达式


1.从Root栈中取  ---List
<s:property value="root栈中propertyName" />
2.从Context栈中取  ---Map
<s:property value="#context栈中的key" />


6.为什么EL也能访问值栈中的数据 ?

实质:EL其实是从request域中取到的数据
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值