Struts2

Struts2:

Struts 2是一个MVC框架,以WebWork框架的设计思想为核心,吸收了Struts 1的部分优点,Struts 2拥有更加广阔的前景,自身功能强大
Struts2的核心:拦截器
Struts2的核心功能由内置拦截器实现:

params拦截器:参数在页面和action之间的传递、国际化

fileUpload拦截器:文件上传

.......

核心过滤器:(StrutsPrepareAndExecuteFilter):以前为:filterDispatcher。将Servlet的请求和响应过滤封装后通过Struts2拦截器实现Struts2的基本功能。

Struts 2官方地址:
http://struts.apache.org

Struts2目录结构:
apps:Struts2示例应用程序

docs:Struts2指南、向导、API文档

lib:Struts2的发行包及依赖包

src:Struts2项目源代码
Struts 2中的符号:

1、“#”符号:相当于ActionContext.getContext();

①、访问非根对象(struts中值栈为根对象)

如:#parameters.id[0] 相当于 request.getParameter("id")    

②、用于过滤和投影(projecting)集合。

如: books.{?#this.price>35}、books.{?#this.price>35} 

③、构造Map,如: #{'foo1':'bar1', 'foo2':'bar2'}

这种方式常用在给radio或select、checkbox等标签赋值上。
<--! 页面中获取一个map的值可以这样写 -->  
<s:property value="#myMap['foo1']"/>     
<s:property value="#myMap['foo1']"/>   

2、“%”符号:

在标签的属性值是为字符串类型时,告诉执行环境%{}里的是OGNL表达式。
<s:set name="myMap" value="#{'key1':'value1','key2':'value2'}"/>
<!-- -->
<!-- 在页面上输出“value1” -->
<s:property value="#myMap['key1']"/>   
<!-- 输出"#myMap['key1']"这么一个字符串 -->
<s:url value="#myMap['key1']" />   

property标签中,value之后的字符串会自动被解析为OGNL表达式
URL标签在被struts解析的时候默认当做字符串
正确代码如下:
<s:url value="%{#myMap['key1']}"/>  

3、“$”符号:

①、在国际化资源文件中,引用OGNL表达式。   

②、在Struts 2配置文件中,引用OGNL表达式: 
<action name="saveUser" class="userAction" method="save">  
    <!-- 这里的${}不是EL表达式,而是OGNL表达式,他只是在不同的地方定义的解析字符不一样而已 -->
    <result type="redirect">listUser.action?msg=${msg}</result>   
</action>
Struts 2文件上传下载:

http://blog.csdn.net/zjl16/article/details/50516364

Struts 2访问Servlet API的两种方式:(如何使用session保存用户信息?)

1、与Servlet API解耦的访问方式

Action可以摆脱Servlet容器的束缚,可以直接访问所需要的对象。而这些对象被定义成了Map类型,以key-value的形式进行读取。
//action中进行保存到Map集合中
public String execute() {
    if("jason".equals(username) && "2010".equals(password)) {
        Map<String, Object> session = null;
        //从actionContext中获取session
        session = ActionContext.getContext().getSession();

        if(session.containsKey(CURRENT_USER)) {             
            session.remove(CURRENT_USER);
        }

        //以key/value形式保存数据
        session.put(CURRENT_USER, username);
        return "success";
    } else {
        return "error";
    }
}
<!-- 页面显示用EL表达式显示数据 -->
<body>
    <h1>读取Session中保存的用户名</h1>
    <div>欢迎您,${sessionScope.CURRENT_USER}!</div>
</body>

2、与Servlet API耦合的访问方式

public class LoginAction implements Action {
    private static final String CURRENT_USER = "CURRENT_USER";  
    … //省略username、password属性及其setter和getter方法
    public String execute() {           
        if("jason".equals(username) && "2010".equals(password)) {   
            //获取session
            HttpSession session = null;
            session = ServletActionContext.getRequest().getSession();   

            if(session.getAttribute(CURRENT_USER) != null) {
                session.removeAttribute(CURRENT_USER);
            }
            //以setAttribute的方式保存数据
            session.setAttribute(CURRENT_USER, username);   
            return "success";
        } else {            
            return "error";
        }
    }
}
Struts2服务器端数据校验

1、Struts 2提供了数据验证机制

继承ActionSupport类来完成Action开发

ActionSupport类不仅对Action接口进行简单实现,同时增加了验证、本地化等支持 

2、valid方法可以进行数据验证

//1、让action继承ActionSupport
//2、分情况用addFieldError方法添加错误信息
public class LoginAction extends ActionSupport{
    //......省略代码
    public void validate() {    
        if(this.getUsername().length()==0){
            //通过addField方法添加的错误信息显示到页面
            addFieldError("name","用户名不能为空");
        }
        if(this.getPassword().length()==0){
            addFieldError("pwd", "用户密码不能为空");
        }
    }   
    //......省略代码
}
<!-- 在页面中用struts标签显示错误信息 -->
<s:fielderror/>
Struts 2标签

Struts 2迭代标签输出数据
1、在页面中引入strurs2标签库

<%@ taglib prefix="s" uri="/struts-tags"%>

2、struts2标签分为UI标签和通用标签

UI标签
标 签说 明
<s:form></s:form>表单标签
<s:textfield>…</s: textfield>文本输入框
<s:password>…</s: password>密码输入框
<s:textarea>…</s: textarea>文本域输入框
<s:radio>…</s: radio>单选按钮
<s:checkbox>…</s: checkbox>多选框
<s:submit/>提交标签
<s:reset/>重置标签
<s:hidden/>隐藏域标签
非表单标签
标 签说 明
<s:actionerror/>显示Action错误
<s:actionmessage/>显示Action消息
<s:fielderror/>显示字段错误
<s:property value="user.name" />标签用于输出指定对象的属性值
<s:set>标签将一个值赋给指定范围的变量
条件判断标签
标 签说 明
<s:if>……</s:if>根据表达式的值,判断将要执行的内容
<s:elseif>……</s:elseif>
<s:else>……</s:else>
<s:if test="表达式">
    <!-- 需要执行的代码 -->
</s:if>

<s:elseif test="表达式">
    <!-- 需要执行的代码 -->
</s:elseif>

<s:else>
    <!-- 需要执行的代码 -->
</s:else>
迭代标签
标 签说 明
<s:iterator>……</s:iterator>用于遍历集合
<s:iterator value="集合对象" status="status" id="name">
    <!-- 读取集合对象并输出显示 -->
</s:iterator>

<!-- value属性:需要进行遍历的集合对象 -->
<!-- status属性:当前迭代元素的IteratorStatus实例 -->
<!-- id属性:当前迭代元素的id,可直接访问元素,该参数可选 -->
URL标签
<s:url value="url" />
    <s:param name="parname"  value="parvalue" />
</s:url>

<!-- value属性:表示指定生成URL的地址 -->
<!-- <s:param />表示需要传递的参数信息 -->
<!-- name属性:表示传递的参数名称 -->
<!-- value属性:表示传递参数所具有的值 -->
日期标签
<s:date format="format"  nice="true|false"  name="name" id="id">
    ……
</s:date>

<!-- format属性:指定格式进行日期格式化 -->
<!-- nice属性:该属性只有true和false两个值,用于指定是否输出指定日期与当前时间的时差,默认是false -->
<!-- name属性:表示当前需要格式化的日期 -->
<!-- id属性:表示引用该元素的id值 -->

Struts 2的执行流程

1、加载Struts 2 类库(导入jar包)
文件名说 明
struts2-core-xxx.jarStruts 2框架的核心类库
xwork-core-xxx.jarXWork类库,Struts 2的构建基础,现已并到Struts2-core中
ognl-xxx.jarStruts 2使用的一种表达式语言类库
freemarker-xxx.jarStruts 2的标签模板使用类库
javassist-xxx.GA.jar对字节码进行处理
commons-fileupload-xxx.jar文件上传时需要使用
commons-io-xxx.jarJava IO扩展
commons-lang-xxx.jar包含了一些数据类型的工具类
2、配置web.xml文件
<filter>
    <filter-name>struts2</filter-name>
    <filter-class></filter-class>
</filter>

<filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern></url-pattern>
</filter-mapping>

注解:

①、org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter
   //Struts 2的核心控制器,对框架进行初始化,以及处理所有的请求


②、/* 所有文件
3、开发视图层页面
4、开发控制层Action
创建Action类

实现Action接口

继承ActionSupport类

配置Action

Action的作用

①、封装工作单元

②、数据转移的场所 

③、返回结果字符串 

在struts.xml文件中配置默认Action

默认Action作用:没有Action匹配请求时,默认Action将被执行

<!-- 通过<default-action-ref name="defaultAction"/ >元素配置默认Action -->

<struts>
    <default-action-ref name="defaultAction"/ >
    <package name="default" extends="struts-default">
        <action name="defaultAction">
            <!-- 如果请求的action不存在,页面跳转到error.jsp -->
            <result>error.jsp</result>          
        </action>
    </package>
</struts>
5、配置struts.xml文件

Struts.xml:核心配置文件,主要负责Action,通常放在src目录下,可以被自动加载

<?xml version="1.0" encoding="UTF-8" ?>

<!-- 在struts2 core的jar包中可以找到对应的语句 -->
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
    <!-- 默认的视图主题 -->
    <constant name="struts.ui.theme" value="simple" />
    <!-- 指定Web应用的默认编码集,相当于调用HttpServletRequest的setCharacterEncoding方法 --> 
    <constant name="struts.i18n.encoding" value="UTF-8" />
    <!-- 当struts的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下使用),开发阶段最好打开--> 
    <constant name="struts.configuration.xml.reload" value="true" />
    <package name="default" namespace="/" extends="struts-default">
        <!-- name值与显示页面的表单中的action对应 -->
        <action name="helloWorld" class="cn.strutsdemo.HelloWorldAction">    
            <result name="success">helloWorld.jsp</result>
        </action>
    </package>
</struts>

constant标签:配置常量,可以改变Struts 2框架的一些行为

name属性:表示常量名称;

value属性:表示常量值 
<!-- 默认的视图主题 -->
<constant name="struts.ui.theme" value="simple" />
<!-- 指定Web应用的默认编码集,相当于调用HttpServletRequest的setCharacterEncoding方法 --> 
<constant name="struts.i18n.encoding" value="UTF-8" />
<!-- 当struts的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下使用),开发阶段最好打开--> 
<constant name="struts.configuration.xml.reload" value="true" />

package标签

包的作用:简化维护工作,提高重用性(包可以“继承”已定义的包,并可以添加自己包的配置)

name属性:为必需的且唯一,用于指定包的名称

extends属性:指定要扩展的包

namespace属性:定义该包中action的命名空间 ,可选

固定格式:<package name="default" namespace="/" extends="struts-default"></package>

struts-default.xml :Struts 2默认配置文件,会自动加载

注意点:struts-default 包 在 struts-default.xml 文件中定义

struts-plugin.xml :Struts 2插件使用的配置文件

运行加载顺序:struts-default.xml ---->struts-plugin.xml----->struts.xml

action标签:一个action对应一个Action类的请求;

action动态方法调用 :解决一个Action对应多个请求的处理,以免Action太多

第一种方式:指定method属性

JSP调用一个方法,便需要在配置文件中配置一个action标签;
这种方式是以方法为单位进行配置,调用多少个方法,便需要配置多少个action,而指向的action类全是一个。
不可避免的增加了不必要的重复配置,笨拙繁琐。

method属性:实现Action中不同方法的调用,

特点:
    ①、避免动态方法调用的安全隐患

    ②、导致大量的Action配置 

第二种方式:通配符

1、首先得关闭开关:

<constant name="struts.enable.DynamicMethodInvocation" value="false" /> 


2、主要看URL里写的是XXXUser 则* === XXX

<action name= "*User" class="cn.houserent.action.UserAction" method="{1}">
    <result>/page/{1}_success.jsp</result>
    <result name="input">/page/{1}.jsp</result>
</action>

在地址栏中输入:/loginUser.action    //通配符为:login
method="login"
/page/login_success.jsp
/page/login.jsp 

在地址栏中输入:/registerUser.action     //通配符为:regist
method="register"
/page/register_success.jsp
/page/register.jsp

//{1}、{2}表示第一第二个占位符 、*为通配符 
<action name="*_*" class="com.bjsxt.struts2.action.{1}Action" method="{2}">  
    <result>/{1}_{2}_success.jsp</result>  
</action>  

第三种方式:DMI(Dynamic Method Invocation) 不推荐使用

调用aciton时不直接等同于调用某个action的名字,而是通过“actionname !methodname”的形式,调用指定到action中具体方法执行。
//action类:
package chapter3.action;

public class Chapter3Action {
    public String result1(){
       return "result1";
    }

    public String result2(){
       return "result2";
    }
}

①、设置struts.xml 文件DMI常量启动动态方法调用:

<constant name="struts. enable. DynamicMethodInvocation" value="true"/>    

②、配置好action result值跳转页面<不同方法的返回值均配置到一个action标签中>

<package name="chapter3" namespace="/chapter3" extends="struts-default">
    <action name="chapter3Action" class="chapter3.action.Chapter3Action">
        <result name="result1">/WEB-INF/JspPage/chapter3/result1.jsp</result>
        <result name="result2">/WEB-INF/JspPage/chapter3/result2.jsp</result>
        <result name="chapter3">/WEB-INF/JspPage/chapter3/chapter3.jsp</result>
   </action>
</package>

③、JSP中通过“actionname !methodname”的形式调用指定action中指定方法

<body>
    <a href="basePath/chapter3/chapter3Action!result1">result1</a><br>
    <a href="{basePath}/chapter3/chapter3Action!result2">result2</a><br>
</body> 

Result标签:实现对结果的调用

result元素的值指定对应的实际资源位置

name属性:表示result逻辑名

常用结果类型

dispatcher类型:默认结果类型,后台使用RequestDispatcher转发请求 

redirect类型:后台使用的sendRedirect()将请求重定向至指定的URL 

redirectAction类型:主要用于重定向到Action 

全局结果:实现同一个包中多个action共享一个结果

<!-- 全局结果位于package元素内 -->
<global-results>
    <result name="error">/page/error.jsp</result>
    <result name="login" type="redirect">/page/login.jsp</result>
</global-results>   

动态结果:动态结果集可以在action中指定要跳转的页面(${}是OGNL表达式,不是EL表达式)

<package name="resultTypes" namespace="/r" extends="struts-default">  
    <action name="result_mul" class="cn.edu.hpu.action.ResultAction">  
        <!-- 这种写法代表在配置文件中可以用这种方法去读值栈里面的内容 -->  
        <result>${r}</result>
    </action>
</package>
//ResultAction.java
package cn.edu.hpu.action;  

import com.opensymphony.xwork2.ActionSupport;  

public class ResultAction extends ActionSupport {  

    private int type;  

    private String r="/Hello.jsp";  

    public int getType() {  
        return type;  
    }  


    public void setType(int type) {  
        this.type = type;  
    }  


    public String getR() {  
        return r;  
    }  


    public void setR(String r) {  
        this.r = r;  
    }  

    public String execute() throws Exception {  
        //因为r是后来保存在值栈中的,所以能被配置文件以${r}  
        //的形式读到  
        if(type==1) r="/User_Add_success.jsp";  
        else if(type==2) r="/User_Add_error.jsp";  
        return SUCCESS;  
    }  
}  
//index.jsp:
<a href="<%=basePath %>/r/result_mul?type=1">动态结果集1</a>  
<a href="<%=basePath %>/r/result_mul?type=2">动态结果集2</a>  
<a href="<%=basePath %>/r/result_mul?type=3">动态结果集3</a>  
6、部署、运行项目

Struts 2类型转换

进行类型转换的原因:

①、基于HTTP协议的Web应用中客户端请求的所有内容都以 文本编码 方式传输到服务器端,服务器端的编程语言却有着丰富的数据类型:

②、Servlet中,类型转换工作由开发者自己完成:

String agestr = request.getParameter("age");
int age = Integer.parseInt(agestr);

struts2提供多种内置类型转换器(自动对客户端传来的数据进行类型转换);

内置类型转换器说 明
String将int、long、double、boolean、String类型的数组或者java.util.Date类型转换为字符串
boolean/Boolean在字符串和布尔值之间进行转换
char/Character在字符串和字符之间进行转换
int、float、long、double在字符串和数值型数据之间进行转换
Integer、Float、Long、Double在字符串和数值型数据之间进行转换
Date在字符串和日期类型之间进行转换。具体输入输出格式与当前的Locale相关
数组和集合在字符串数组和数组对象、集合对象间进行转换
自定义类型转换器

类型转换:由拦截器实现,将表单中获取的String类型转为Action中所需要的类型

特定类型转换为字符串类型:重写toString()方法;

字符串类型转换为特定类型:一般的特定类型struts2都已经解决,特殊的特定类型需要自定义类型转换器,

如:
    Date传值时必须写成1999-01-01才会自动转换类型,若写为19990101则不转
    Point传参应该是p.x=1&p.y=2,但写成p=1,2则不转

1、局部类型转换器:

过程:找不到特殊类型的转换之后,struts2会找action对应的包下面的转换文件,查看里面的成员变量里有没有对应的转换器,如果找到,就会尝试把接收到的参数传给转换器“转换方法(convertValue)”中的形参value,把要转换的类型传给toType。最后“转换方法”执行得到一个结果Object,结果就是一个new出来的Point。

//TypeCoverter接口
public interface TypeConberter{
    public Object convertValue(Map context,Object target,Member member,String 
                    propertyName,Object value, Class toType);
}

//DefaultTypeConverter实现类
public class UserTypeConvert extends DefaultTypeConverter {

    //context 是类型转换环境的上下文
    //value 是需要转换的参数
    //toType 是转换后的目标类型。
    @Override 
    public Object convertValue(Map<String, Object> context, Object value, Class
                 toType) { 
        return null;
    }
}
步骤
第一步:实现自定义转换器
①、实现TypeCoverter接口或者继承DefaultTypeConverter实现类(实现TypeCoverter)来实现自己的类型转换器
②、重写convertValue方法
第二步 配置文件
①、在需要生效的Action类的包下放置ActionName-conversion.properties文件
ActionName是需要转换生效的Action的类名;-conversion固定。如: LoginAction-conversion.properties
文件中的内容:待转换的类型 = 类型转换器的全类名 birthday =convert.UserTypeConvert
//Date类型输入"yyyyMMdd"的自定义转化
public class LoginAction {
    private Date birthday;
    public Date getBirthday() {
        return birthday;
    } 
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    } 
    public String execute() throws UnsupportedEncodingException{
        return "success";
    }
}
//转换器继承类:DefaultTypeConverter类
//(由com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter包提供)。
//重写里面的convertValue方法,这个方法会被struts调用。代码如下:

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter;
public class UserTypeConvert extends DefaultTypeConverter{
    @Override
    public Object convertValue(Map<String, Object> context, Object value, Class toType){
        SimpleDateFormat dateformat = new SimpleDateFormat("yyyyMMdd"); 
        try{
            if(toType == Date.class) { 
                String [] datevalue = (String [])value; 
                return dateformat.parse(datevalue[0]); 
            } else if(toType == String.class) { 
                Date datevalue = (Date)value;
                return dateformat.format(datevalue); 
            } 
        } catch (java.text.ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null; 
    }
}

2、全局类型转换器:对所有action转换类型起作用

配置文件
Src下放置xwork-conversion.properties文件,文件名固定。
文件中的内容:待转换的类型 = 类型转换器的全类名。如:java.util.Date = convert.UserTypeConvert
类型转换器注册的方式有三种(配置文件):
1、注册局部类型转换器:局部类型转换器仅仅对某个Action的属性起作用。

2、注册全局类型转换器:全局类型转换器对所有Action的特定类型的属性都会生效。

3、使用JDK1.5的Annotation来注册类型转换器
向用户输出类型转换错误的前提条件
1、启动StrutsConversionErrorInterceptor拦截器,包含在defaultStack拦截器栈中 

2、Action继承ActionSupport类,并实现ValidationAware接口 

3、配置input结果映射,页面使用Struts 2表单标签或<s:fielderror>标签
所有类型的转换错误信息
1、在struts.xml中指定资源文件的基名
<constant name="struts.custom.i18n.resources" value="message"/> 
2、在src目录下创建资源文件message.properties并修改键值
xwork.default.invalid.fieldvalue=字段“{0}”的值无效
定制特定字段的类型转换错误信息
在Action包下创建RegisterAction.properties,指定键值
invalid.fieldvalue.birthday=生日转换错误
Struts2中文乱码
<!-- 指定Web应用的默认编码集,相当于调用HttpServletRequest的setCharacterEncoding方法 --> 
<constant name="struts.i18n.encoding" value="UTF-8" />

OGNL(Object Graph Navigation Language) 对象图导航语言

1、Ognl是一个开源项目,取代页面中Java脚本,简化数据访问,和EL同属于表达式语言,但功能更为强大 

2、 OGNL表达式的解析都是围绕OGNL上下文进行的,OGNL表达式是一个map对象,其中包含多个java对象,其中有一个对象十分的特殊,这个对象称为根对象!

    a.一个OGNL表达式若没有指定目标对象,默认就是从根对象开始查找!

    b.若要访问非根对象中的属性,就要在访问根对象的前面需加#前缀!

struts2框架在解析OGNL表达式的时候,OGNL上下文就是ActionContext,而根对象就是Action对象!

OGNL在框架中的作用

表达式语言

将表单或Struts 2标签与特定的Java数据绑定起来,用来将数据移入、移出框架 

类型转换

数据进入和流出框架,在页面数据的字符串类型和Java数据类型之间进行转换

执行过程:

表单数据提交时,首先会被装入对应的Java对象,并赋值给相应的属性,在这个过程中会自动执行类型转换。

然后这个对象又会作为Action对象属性而存在,Action位置在值栈中,值栈的位于运行环境中。这部分对应的就是数据流入。

对于数据流出而言,当请求处理完毕后,使用OGNL结合Struts 2标签又可以方便的在页面中访问数据。

OGNL访问值栈

OGNL访问值栈时的顺序,自上而下,如果存在相同名称属性则位于栈顶的属性会被读取。

使用OGNL访问数据

访问Bean的属性
    1、Bean的类型必须遵循JavaBean规范
    2、必须具有无参构造
    3、setter/getter方法符合JavaBean规范

访问集合对象
    可以使用属性名[index]的方式访问

列表、数组
    可以使用属性名[key]的方式访问

Map对象
    使用size或者length获取集合长度

访问JavaBean

public class Address { // 家庭地址
    private String country; // 国家
    private String city; // 城市
    private String street; // 街道
    ...  //省略各个属性的setter和getter方法
}

public class User { //用户类
    private String name; //姓名
    private int age;     //年龄
    private Address address; //家庭地址
    ...  //省略各个属性的setter和getter方法
}
//User对象作为Action的属性,其键名为user
//访问name属性:user.name;
//访问country属性:user.address.country;

访问集合

<s:set name="list" value="{'jason','tom','jack'}"/>
<s:property value="#list[0]"/>
<s:property value="#list.size"/>

数组的访问

//定义数组:
new int[]{1,2,3,4}
/*
访问数组:
访问已创建的数组,对象名为array

访问第一个元素:array[0] 
获取数组长度:array.length
*/

Map的访问

<--! 定义Map -->
<s:set name="map" value="#{'cn':'China','us':'the United States','fr':'France','jp':'Japan'}" />

<--! 访问已创建的Map,对象名为map 访问“China-->
<--! 第一种方式:-->
#map["cn"] 
<--! 第二种方式:-->
#map.cn

注意: 值栈中内容可以直接访问,访问非值栈对象需添加#前缀

Struts 2将OGNL上下文设置为ActionContext

Struts 2将值栈作为OGNL上下文根对象

ActionContext对象包括:application、session、ValueStack、request、attr、parameters

非值栈对象访问方式等价访问方式
application#application.username#application['username']application.getAttribute("username")
session#session.username#session['username']session.getAttribute("userName")
request#request.username#request['username']request.getAttribute("username")
parameters#parameters.username#parameters['username']request.getParameterValues(“username”)
attr#attr.username#attr['username']pageContext–>request–>session–>application顺序查找

例子:

<s:set name="age" value="10" scope="request"/>
<s:set name="username" value="'Jason'" scope="session"/>
<s:set name="count" value="5" scope="application"/>     
#request.age:<s:property value="#request.age"/><br/>
#session.username:<s:property value="#session.username"/><br/>
#application.count:<s:property value="#application.count"/><br/>
#attr.count:<s:property value="#attr.count" /><br />    

<s:set name="country1" value="China"/>  
<s:set name="country2" value="'China'"/>
#country1:<s:property value="#country1"/><br/>
#country2:<s:property value="#country2"/><br/>  
#request.country2:<s:property value="#request.country2"/><br/>  

值栈(ValueStack):

由 Struts 2 框架创建的存储区域,具有栈的特点(先进先出),Action的实例会被存放到值栈中

1、valueStack是值栈的对外接口,实际对应的类是OgnlValueStack,OgnlValueStack对象中包含了一个ArrayList集合来作为栈,默认action对象位置值栈的栈顶位置。

a.void push(Objext o) 可用来将一个对象数据压入栈顶.

b.set(String key,Objext obj) 则是将数据放入Map对象当中,并将Map对象压入栈顶位置!

2、 OGNL表达式在取数据的时候,其规则是先从栈的栈顶(action对象)中开始查找,先判断是否有Map对象,根据key取值;不是Map对象,则寻找该对象的getKey()方法,得到其值,若没有方法,则查找key变量(要求必须是public修饰)均为找到,就去第二个对象中向下查找!

ActionContext

重要的文字,写三遍;

struts2框架在解析OGNL表达式的时候,OGNL上下文就是ActionContext,而根对象就是Action对象!

ActionContext的组成:值栈-ValueStack、非值栈-Stack Context

    客户端发送的每一次请求,struts2框架都会自动的创建一个ActionContext和值栈对象,请求处理完毕以后这两个对象会自动的销毁!

ActionContext对象相当于一个大大的容器,里面包含了application、session、parameters、valueSatck、attr属性。(其中valueStack对象就是值栈对象)

注意:

1、ActionContext中的application、session、parameters等对象都是非根对象,在OGNL表达式中要访问他们,需要在表达式前面加上#前缀!

2、<s:debug/>标签可以查看ActionContext对象

总结:

Struts 2提供了非常强大的类型转换功能,提供了多种内置类型转换器,也支持开发自定义类型转换器
Struts 2框架使用OGNL作为默认的表达式语言
ActionContext中包含多个对象。如果使用OGNL访问根对象,可直接书写对象的属性,而要使用其他对象必须使用“#key”前缀来访问
使用Struts 2日期标签可以实现日期输出的格式化显示,使用URL标签可以构建一个超链接
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值