面试题:struts 值栈 有用
一、 核心部分
1. 【核心试题】完成当天课堂练习
2. 【多选题】 阅读如下代码中,下列哪种方式可以在页面正确迭代获取集合中的数据 (ABC)
public String add(){
ValueStack vs = ActionContext.getContext().getValueStack();
// 压入List集合
List<User> ulist = new ArrayList<User>();
ulist.add(new User("小明",20));
ulist.add(new User("小红",30));
ulist.add(new User("小张",40));
vs.set("ulist", ulist);
return SUCCESS;
}
public class User {
private String name;
private Integer age;
public User() {
}
public User(String name, Integer age) {
this.name = name;
this.age = age;
}......
}
A、 <c:forEach items="${ ulist }" var="user"> ${ user.name } -- ${ user.age } </c:forEach>
B、 <s:iterator value="ulist"> <s:property value="name"/> <s:property value="age"/> </s:iterator>
C、 <s:iterator value="ulist" var="u"> <s:property value="#u.name"/> <s:property value="#u.age"/> </s:iterator>
D、 <s:iterator value="ulist"> <s:property value="#ulist.name"/> <s:property value="#ulist.age"/> </s:iterator>
3. 【多选题】 ValueStack结构是由哪两部分组成的 (AD)
A、 CompoundRoot
B、 Arraylist
C、 Map
D、 OgnlContext
4. 【多选题】 下列有关值栈组成部分的表述中错误的是 (CD)
A、 通常情况下,值栈由两部分组成root和context,默认情况下Struts会把 动作和相关对象压入 ObjectStack中,会把各种各样的映射关系压入 Context 中。
B、 在ValueStack中存在root属性、context 属性,其中root属性代指的就是ArrayList, context属性代指的就是Map
C、 OGNL表达式访问值栈中的数据必须使用#才能实现访问。
D、 当我们操作值栈内容时,默认操作的就是map中的元素。
5. 【多选题】 下列有关ValueStack 和 ActionContext对象的相关理解中正确的是 (ABCD)
A、 ActionContext是绑定到当前的线程上,那么在每个拦截器或者Action中获取到的ActionContext是同一个。
B、 值栈对象是当请求时才会被创建的。
C、 ActionContext中存在一个Map集合,该Map集合和ValueStack的context是同一个地址。
D、 ActionContext中可以获取到ValueStack的引用,我们可以使用ActionContext来获取到值栈对象。
6. 【多选题】 下列选项中有关OGNL(对象图导航语言)的表述正确的是 (AB)
A、 当我们以任意的一个对象为根,我们通过OGNL可以访问与这个对象关联的其它对象。
B、 通过ognl简单一致的表达式语法,我们可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。
C、 表现层框架都默认使用OGNL作为表达式语言。
D、 OGNL通常支持对象方法调用、类静态的方法调用和值访问,但是不支持集合对象的相关操作。
7. 【多选题】 当我们向值栈的root属性中保存数据时,如下哪些方式是正确的 (AC)
A、 valueStack.push(Object obj);
B、 valueStack.push(String key, Object obj);
C、 valueStack.set(String key, Object obj);
D、 valueStack.set(Object obj);
8. 【多选题】 下列选项中有关值栈的相关概念表述正确的是 (ABD)
A、 值栈就相当于一个数据的中转站,我们可以向值栈存入一些数据,同样也可以从值栈中获取到数据。
B、 ValueStack是struts2框架提供一个接口,具体的实现类是ognlValueStack。
C、 默认情况下struts2框架下Action是单例的,当请求一访问,就会创建一个Action实例,同时也会创建一个ActionContext对象,代表的是Action的上下文对象,最后还会创建一个ValueStack对象。
D、 通常情况下每一个Action实例都有一个ValueStack对象。
9. 【编程题】在jsp页面使用迭代标签迭代集合值
需求:写一个Action,初始化List集合数据,存储在值栈的root(根元素)对象中,再在jsp页面使用迭代标签迭代集合值。
操作步骤
- 新建action,继承ActionSupport
- 新建对象:User.java
- 在action的成员变量中定义list(集合的元素为User对象)
- 重写execute()方法, 给集合对象赋值
- 写jsp页面,迭代显示集合值
Action代码: |
public class TagTestAction extends ActionSupport{
// 数据存储到根元素中! private List<User> list; public List<User> getList() { return list; }
@Override public String execute() throws Exception {
list = new ArrayList<User>();
// 初始化 for (int i=1; i<6; i++) { User user = new User("Kobe"+i,"999"); list.add(user); }
return super.execute(); }
}
|
注:答案在答案\编程题9
二、 晋级部分
需求:使用struts的<s:property>标签,结合OGNL表达式获取值栈中Map数据,也是ValueStack值栈对象中context中数据。
需求详述:
通过ActionContext获取表示request、session、application域的map, 再往map中设置值,最后再在jsp页面通过struts2的标签获取值 (<s:property>)
操作步骤
(1) 新建action类
(2) 在action类的方法中,通过ActionContext 获取表示request、session、 applicatoin域对象的map集合,再设置map值。
(3) 配置struts.xml
(4) 通过jsp页面获取map集合值
注:答案在答案\晋级题1
三、 面试题部分
1. 值栈对象的创建 ,ValueStack 和 ActionContext 是什么关系 ?
答案:
值栈对象是请求时创建的
doFilter中 prepare.createActionContext(request, response);
* 创建ActionContext对象过程中,创建值栈对象ValueStack
* ActionContext对象对ValueStack对象有引用的(在程序中通过 ActionContext 获得值栈对象 )
Dispatcher类 serviceAction 方法中将值栈对象保存到request范围
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());
2. 如何获得值栈对象?
答案:
1、ActionContext.getContext().get(ActionContext.VALUE_STACK); 2、ActionContext.getContext().getValueStack(); 3、ServletActionContext.getRequest().getAttribute("struts.valueStack");
3. 什么是值栈?值栈的内部结构?
答案:
ValueStack 是 struts2 提供一个接口,实现类 OgnlValueStack ---- 值栈对象 (OGNL是从值栈中获取数据的 )每个Action实例都有一个ValueStack对象 (一个请求对应 一个ValueStack对象 )在其中保存当前Action 对象和其他相关对象 (值栈中是有Action引用的 )Struts 框架把 ValueStack 对象保存在名为“struts.valueStack” 的请求属性中,request中(值栈对象是request一个属性)
值栈由两部分组成,ObjectStack(root)和ContextMap(context)
ObjectStack: Struts 把动作和相关对象压入 ObjectStack 中--List
ContextMap: Struts 把各种各样的映射关系(一些 Map 类型的对象) 压入ContextMap中,Struts 会把下面这些映射压入 ContextMap 中
parameters: 该 Map 中包含当前请求的请求参数
request: 该 Map 中包含当前 request 对象中的所有属性
session: 该 Map 中包含当前 session 对象中的所有属性
application:该 Map 中包含当前 application 对象中的所有属性
attr: 该 Map 按如下顺序来检索某个属性: request, session, application
VaValueStack中 存在root属性 (CompoundRoot) 、 context 属性 (OgnlContext )
* CompoundRoot 就是ArrayList
* OgnlContext 就是 Map
cncontext 对应Map 引入 root对象
* context中还存在 request、 session、application、 attr、 parameters 对象引用
* OGNL表达式,访问root中数据时 不需要 #, 访问 request、 session、application、 attr、 parameters 对象数据 必须写 #
* 操作值栈 默认指 操作 root 元素
- 什么是OGNL表达式.
OGNL的全称是对象图导航语言, 可以通过某种表达式语法,存取Java对象的任意属性,调用Java对象的方法,同时能够自动实现必要的类型转换.
- OGNL表达式的使用要求是什么
要想使用ognl表达式,一般情况下都得需要使用struts2的标签库。
- 怎样用s标签把value属性取值所对应的内容输出到浏览器。
<s:property value=""/>
- 阐述一下 s:property的作用。
把value属性取值所对应的内容输出到浏览器上。注意:它不是把value的值输出到浏览器上。
- 用<s:property/>写一段代码把一个 ”OGNL表达式” 看成是字符串
<s:property value="%{'OGNL表达式’}"/> <s:property value='%{"OGNL表达式"}'/> |
简化的表现形式:'OGNL表达式'或者是"OGNL表达式",单引号还是双引号由外层决定。
- 用<s:property/>写一段代码,怎样把一个字符串”OGNL表达式”看成OGNL表达式?
把一个字符串看成是OGNL表达式的方式是: %{字符串}
<s:property value='%{OGNL表达式}'/> |
- OGNL表达式可以访问普通的方法,写一段代码用<s:property>标签完成下面的需求:
- 计算字符串”OGNLExpression”的长度 ,并输出
- 字符串”OGNLExpression”转成大写,并输出
- 用字符’e’分割字符串”OGNLExpression”,并输出
代码如下:
<s:property value='"OGNLExpression".length()'/><br/> <s:property value='"OGNLExpression".toUpperCase()'/><br/> <s:property value='"OGNLExpression".split("E")'/><br/> |
- OGNL表达式可以访问静态属性,访问静态属性,必须按照规则写:@包名.包名....类名@静态属性名称,请用<s:property> 输出Integer的最大值。
<s:property value="@java.lang.Integer@MAX_VALUE"/> |
- OGNL表达式可以访问静态方法,访问静态方法必须按照规则写:@包名.包名....类名@静态方法名称,struts2默认不允许OGNL访问静态方法,要想使用需要配置文件中开启,请在jsp中用<s:property>输出Math类调用random()方法产生的随机数。
struts2框架默认不支持OGNL表达式的静态方法调用,开启的方式如下: <constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant> --%> 随机数:<s:property value="@java.lang.Math@random()"/>
|
- HTML标签在浏览器输出一套性别的单选按钮:
<input type="radio" name="gender" value="男">男
<input type="radio" name="gender" value="女">女
<br/>
Struts2标签也有一个radio,也是用于在浏览器上输出一套性别单选按钮,list属性的取值是一个OGNL表达式,可以使用{}来创建一个List集合,请用在页面写出代码?
<s:radio name="gender" list="{'男','女'}" label="性别"/>
|
- 用HTML在浏览器上输出一个单选性别:
<input type="radio" name="gender" value="male"/>男
<input type="radio" name="gender" value="female"/>女
<br/>
用Struts2标签的radio,list属性的取值是一个OGNL表达式,可以使用#{key:value,key:value}来创建一个Map集合,请用代码完成。
<s:radio name="gender" list="#{'male':'男','female':'女'}" label="性别"/>
|
- 请简述一下ContextMap,并画出ContextMap的结构图
ContextMap是ognl上下文对象,结构map<String,Object>封装了一次请求的所有数据。
结构图如下:
- 用自己的话请阐述ActionContext对象。
它是一个工具类,是struts2框架提供给我们的,可以让我们调用其中的方法,快速的操作ContextMap。用它操作OGNL上下文对象
- ActionContext对象以及和ContextMap(context)的关系
ActionContext就相当于对ContextMap进行了一次再封装。
- 框架是怎么保证ActionContext的线程安全的?
java的web工程是多线程的,那么每个线程在访问Action时,都会创建自己的ActionContext,每次创建ActionContext时,把对象绑定到当前线程上。
- 怎样获取一个ActionContext对象?
获取ActionContext对象:ActionContext context = ActionContext.getContext();
- 请按下面的需求完成对ActionContext设置值和取值的练习。
1.获取ActionContext对象,并且存入数据key是字符串 "contextMap", value是字符串 "hello context map ",在jsp页面用<s:property value="#contextMap"/>取值并显示。
2. 获取ActionContext对象,然后获取key为application的Map,并且存入数据key是字符串 " applicationMap ", value是字符串 " hello application map ",在jsp页面用<s:property value="#application.applicationMap"/>取值并显示。
3. 获取ActionContext对象,然后获取key为session的Map,并且存入数据key是字符串 "sessionMap", value是字符串 "hello session map",在jsp页面用<s:property value="#session.sessionMap"/>取值并显示。
- 请阐述一下ValueStack对象
ValueStack是Struts的一个接口,字面意义为值栈,OgnlValueStack是ValueStack的实现类,客户端发起一个请求struts2架构会创建一个action实例同时创建一个OgnlValueStack值栈实例,OgnlValueStack贯穿整个 Action 的生命周期。
它是ContextMap中的一部分,里面的结构是一个List,是我们可以快速访问数据一个容器。它的封装是由struts2框架完成的。
通常情况下我们是从页面上获取数据。
- 请阐述一下ValueStack的内部结构
在 OnglValueStack 中包含了一个CompoundRoot的对象,该对象继承了ArrayList,并且提供了只能操作集合第一个元素的方法,所以我们说它实现了栈的特性。同时,它里面定义了一个ContextMap的引用,也就是说,我们有值栈对象,也可以通过值栈来获取ContextMap。
- 根据下面需求完成对ValueStack的操作练习。
1.获取ActionContext对象,然后获取ValueStack对象,然后创建一个User对象,User对象有name和age属性,压入栈中,然后通过<s:property value="name"/>获取里面name的值。
2.在Demo2Action中定义一个成员变量name=”张三”,在页面中通过<s:property value="[1].name"/>获取值,并在页面显示。
- 如下图,完成下面需求
在ContextMap 中放入一个name属性,在request域中放入一个name属性,session放入一个name属性,并且在Demo3Action中加一个name的成员变量,然后通过页面el表达式取name的值,然后总结一下el表达式的取值顺序。
1.先编写代码去实现,然后总结规律。
2.规律总结如下:
Struts2框架中对EL表达式做了如下改变:
EL表达式原来的搜素顺序:
page Scope——>request Scope——>sessionScope——>application Scope
EL表达式改变后的搜索顺序:
page Scope—>request Scope—>valueStack—>contextMap—>sessionScope
—>application Scope
它是如何做到的呢?答案就是,struts2框架对request对象进行了包装,并且对getAttribute方法进行了增强
- 对#号,%号,$号做一下总结
#:
1、获取ContextMap中数据,把后面的内容看成是key。
2、在使用struts2标签,创建Map对象时使用。<s:radio list="#{}">
%:
1、使用%{''}把OGNL表达式强制看成是普通字符串
2、使用%{}把普通字符串强制看成是OGNL表达式
$:
1、使用EL表达式的标识
2、在struts的配置文件中使用OGNL表达式
- 编程题,优化struts2的查询客户案例,在CustomerAction中定义一个成员变量private List<Customer> customers,然后提供get和set方法,然后页面集合遍历集合修改为<s:iterator value="customers" var="cust">和<s:iterator value="customers">