struts2第三天( 响应 涉及的是数据的存储(值栈)与页面上数据显示(ognl+struts2标签))


Struts2ServletAPI的访问

* 解耦合的方式:通过ActionContext对象

* 实现特定接口的方式:实现ServletRequestAwareServletContextAwareServletResponseAware

* 通过ServletActionContext获取

Struts2的结果页面的配置

* 结果页面的分类:

* 全局结果页面:针对一个包下的所有的action都生效

* 局部结果页面:针对一个action生效

* 结果页面的类型

* 通过type属性进行配置:

* dispatcher

* chain

* redirect

* redirectAction

* stream

Struts2的数据封装

* 属性驱动

* 提供属性的set的方法

* 提供页面OGNL表达式的方式

* 模型驱动

* 采用模型驱动实现

1.2 案例:CRM的客户查询操作

1.2.1 案例需求

CRM的管理系统中的客户管理:

查询客户:对查询进行优化.

l 添加客户

l 修改客户

l 删除客户

1.3 相关知识点

1.3.1 OGNL的表达式

1.3.1.1 什么是OGNL

OGNL:对象图导航语言,是一门功能强大的表达式语言(功能比EL强大很多倍)。Struts2OGNL引入到自身,作为Struts2的表达式语言。

1.3.1.2 OGNL的作用

1.3.1.3 OGNL的要素:

l 表达式:

l 跟对象:

l Context对象:

1.3.2 OGNL的入门

1.3.2.1 Java环境中使用

public class OgnlDemo1 {

 

@Test

/**

 * OGNL调用对象的方法:

 */

public void demo1() throws OgnlException{

OgnlContext context = new OgnlContext();

Object value = Ognl.getValue("'helloworld'.length()", context, context.getRoot());

System.out.println(value);

}

@Test

/**

 * OGNL调用对象的静态方法:

 * @包名.类名@属性/方法

 */

public void demo2() throws OgnlException{

OgnlContext context = new OgnlContext();

Object value = Ognl.getValue("@java.lang.Math@random()", context, context.getRoot());

System.out.println(value);

}

@Test

/**

 * 获得Root中的数据获取root中的数据不需要加#

 */

public void demo3() throws OgnlException{

OgnlContext context = new OgnlContext();

User user = new User();

user.setUsername("aaa");

user.setPassword("123");

// root中存入数据

context.setRoot(user);

// 获取root中的数据:

Object username = Ognl.getValue("username", context, context.getRoot());

Object password = Ognl.getValue("password", context, context.getRoot());

System.out.println(username +"   "+password);

}

@Test

/**

 * 获取context中的数据:获取context中的数据需要加#

 */

public void demo4() throws OgnlException{

OgnlContext context = new OgnlContext();

context.put("name", "张三");

Object value = Ognl.getValue("#name", context, context.getRoot());

System.out.println(value);

}

}

1.3.2.2 Struts2环境中使用

<h1>OGNLStruts2环境中使用</h1>

<h3>访问对象的方法</h3>

<s:property value="'helloworld'.length()"/>

<h3>访问对象的静态方法</h3>

<s:property value="@java.lang.Math@random()"/>

1.3.3 Struts2ValueStack

1.3.3.1 什么是ValueStack值栈

ValueStackStruts2框架中的接口,实现类OgnlValueStack的类。ValueStack(值栈)实质就是一个Struts2的数据的中转站ValueStack对象贯穿了Action的整个的生命周期。从客户端发送一个请求到ActionStruts2就会创建一个Action的实例,同时为这个Action的实例创建一个ValueStack对象。在执行Action过程中,Struts2框架将ValueStack存入到request域中一份。Struts2通过OGNL访问值栈的数据

1.3.3.2 值栈的内部结构

1.3.3.3 ActionContext与值栈关系

为什么可以通过ActionContext获得值栈?

n ActionContextAction的上下文。创建Action实例的时候,创建值栈对象,将值栈对象存入到ActionContext中。

    public ActionContext createActionContext(HttpServletRequest request, HttpServletResponse response) {

        ActionContext ctx;

        Integer counter = 1;

        Integer oldCounter = (Integer) request.getAttribute(CLEANUP_RECURSION_COUNTER);

        if (oldCounter != null) {

            counter = oldCounter + 1;

        }

        

        ActionContext oldContext = ActionContext.getContext();

        if (oldContext != null) {

            // detected existing context, so we are probably in a forward

            ctx = new ActionContext(new HashMap<String, Object>(oldContext.getContextMap()));

        } else {

            ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();

            stack.getContext().putAll(dispatcher.createContextMap(request, response, null));

            ctx = new ActionContext(stack.getContext());

        }

        request.setAttribute(CLEANUP_RECURSION_COUNTER, counter);

        ActionContext.setContext(ctx);

        return ctx;

    }

ActionContext为什么访问ServletAPI

上次课用ActionContext访问ServletAPI:

ActionContext act = ActionContext.getContext();

Map<String,Object> sessionMap = act.getSession();

sessionMap.put();

***** 这种访问ServletAPI的方式,只能操作域中数据的,不能获得真实的对象。

ActionContext中能够访问ServletAPI基于ValueStack来实现的。

1.3.3.4 获得ValueStack

通过ActionContext对象获取:

// 获取值栈的方式一:通过ActionContext获取:

ValueStack valueStack1 = ActionContext.getContext().getValueStack();

通过request域获取:

执行Action的过程中,将ValueStack存入到request域中,keystruts.valueStack。相当于request.setAttribute(“struts.valueStack”,valueStack);

// 获取值栈的方式二:通过request对象获取:

ValueStack valueStack2 = (ValueStack) ServletActionContext.getRequest()

.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);

1.3.3.5 操作ValueStack

操作root

通过值栈中的方法操作值栈

调用ValueStack中的方法:setpush

public class ValueStack3Action extends ActionSupport{

 

@Override

public String execute() throws Exception {

// 获得值栈:

ValueStack valueStack = ActionContext.getContext().getValueStack();

/**

 * ValueStack中的方法:

 * * void set(String key,Object value);  -- 创建一个Map集合,将Map集合存入到值栈(root)中。

 * * void push(Object obj);  -- 将对象存入到值栈(root)中。

 * * 栈的特点:先进后出.

 */

valueStack.set("name", "王强勇");// 一般list集合使用set

User user = new User();

user.setUsername("aaa");

valueStack.push(user); // 一般Object使用push

return SUCCESS;

}

}

通过Action中提供成员属性的方式

Action类默认是在栈中,而且默认情况下(没有手动向值栈存值,没有实现模型驱动)是在栈顶的位置。Action已经在值栈中了,现在提供了一个Action的属性,Action的属性也是会在栈中。

public class ValueStack3Action extends ActionSupport{

 

private Integer age;

public Integer getAge() {

return age;

}

..

}

操作context区(了解)

<s:debug></s:debug>

<s:property value="#request.name"/>

<s:property value="#session.name"/>

<s:property value="#application.name"/>

<s:property value="#parameters.id"/>

<s:property value="#attr.name"/>

1.3.3.6 获取ValueStack中的数据

<h1>获取数据</h1>

<h3>获取push的数据</h3>

<s:property value="username"/>

<s:property value="password"/>

<h3>获取set的数据</h3>

<s:property value="user.username"/>

<s:property value="user.password"/>

<h3>获取list集合中的数据</h3>

<s:property value="list[0].username"/>

<s:property value="list[0].password"/>

<s:property value="list[1].username"/>

<s:property value="list[1].password"/>

<s:property value="list[2].username"/>

<s:property value="list[2].password"/>

<br/>

1.3.3.7 EL访问ValueStack

EL获取的数据来源都是四个作用域还有提供11操作web常用的对象。

11web常用对象:

requestScope

sessionScope

pageScope

applicationScope

param

paramValues

header

headerValue

cookie

initparams

pageContext

因为Struts2底层对request对象进行包装:

public class StrutsRequestWrapper extends HttpServletRequestWrapper {

 

    private static final String REQUEST_WRAPPER_GET_ATTRIBUTE = "__requestWrapper.getAttribute";

    private final boolean disableRequestAttributeValueStackLookup;

 

    /**

     * The constructor

     * @param req The request

     */

    public StrutsRequestWrapper(HttpServletRequest req) {

        this(req, false);

    }

 

    /**

     * The constructor

     * @param req The request

     * @param disableRequestAttributeValueStackLookup flag for disabling request attribute value stack lookup (JSTL accessibility)

     */

    public StrutsRequestWrapper(HttpServletRequest req, boolean disableRequestAttributeValueStackLookup) {

        super(req);

        this.disableRequestAttributeValueStackLookup = disableRequestAttributeValueStackLookup;

    }

 

    /**

     * Gets the object, looking in the value stack if not found

     *

     * @param key The attribute key

     */

    public Object getAttribute(String key) {

        if (key == null) {

            throw new NullPointerException("You must specify a key value");

        }

 

        if (disableRequestAttributeValueStackLookup || key.startsWith("javax.servlet")) {

            // don't bother with the standard javax.servlet attributes, we can short-circuit this

            // see WW-953 and the forums post linked in that issue for more info

            return super.getAttribute(key);

        }

 

        ActionContext ctx = ActionContext.getContext();

        Object attribute = super.getAttribute(key);

 

        if (ctx != null && attribute == null) {

            boolean alreadyIn = isTrue((Boolean) ctx.get(REQUEST_WRAPPER_GET_ATTRIBUTE));

 

            // note: we don't let # come through or else a request for

            // #attr.foo or #request.foo could cause an endless loop

            if (!alreadyIn && !key.contains("#")) {

                try {

                    // If not found, then try the ValueStack

                    ctx.put(REQUEST_WRAPPER_GET_ATTRIBUTE, Boolean.TRUE);

                    ValueStack stack = ctx.getValueStack();

                    if (stack != null) {

                        attribute = stack.findValue(key);

                    }

                } finally {

                    ctx.put(REQUEST_WRAPPER_GET_ATTRIBUTE, Boolean.FALSE);

                }

            }

        }

        return attribute;

    }

}

1.3.4 OGNL中特殊符号的使用:

1.3.4.1 #

获取context中的数据

<s:property value="#request.name"/>

<s:property value="#session.name"/>

<s:property value="#application.name"/>

<s:property value="#parameters.id"/>

<s:property value="#attr.name"/>

OGNL中手动构建一个Map集合

<h1>#号构建一个Map集合</h1>

<h3>遍历List集合</h3>

<s:iterator var="i" value="{'aa','bb','cc'}">

<s:property value="#i"/><br/>

</s:iterator>

<h3>遍历Map集合</h3>

<s:iterator var="entry" value="#{'aa':'11','bb':'22','cc':'33'}">

<s:property value="key"/>--<s:property value="value"/><br/>

<s:property value="#entry.key"/>--<s:property value="#entry.value"/><br/>

</s:iterator>

<h3>使用Struts2UI标签构建Map集合的地方</h3>

传统方式:<br/>

性别:<input type="radio" name="sex" value=""/><input type="radio" name="sex" value=""/><br/>

性别:<input type="radio" name="sex" value="1"/><input type="radio" name="sex" value="2"/><br/>

Struts2UI标签的方式:<br/>

<s:radio list="{'',''}" name="sex" label="性别"/>

<s:radio list="#{'1':'','2':'' }" name="sex" label="性别"/>

1.3.4.2 %

强制解析OGNL表达式:

<s:property value=”ognl”/> 一定会执行的。

<%

request.setAttribute("name", "王强勇");

%>

<input type="text" name="name" value="<s:property value="#request.name"/>"/>

<s:textfield name="name" value="%{#request.name}"/>

1.3.4.3 $

Struts2的配置文件中使用OGNL表达式

n 文件下载

<action name=”download” class=””>

<result name=”” type=”stream”>

<param name=”Content-Dispostion”>attachment;filename=${fileName}</param>

</result>

</action>

n 国际化

message_zh_CN.properties

welcome=您好:${#session.user.name}

message_en_US.properties

welcome=Hello:${#session.user.name}

猜你喜欢

转载自blog.csdn.net/wuqianjing/article/details/80886018
今日推荐