Struts2学习-3 : OGNL表达式详解

OGNL表达式详解
1,OGNL:Object Graph Navigation Language
2,OGNL不仅可以调用属性,还可以调用普通方法
<!-- 表达式可以调get和set,可以调方法,可以按索引取数组内容 (打印a)-->
<s:property value='"abcdefg".toCharArray()[0]'/><br/>
<!-- ognl表达式中:context代表contextMap (打印对应的value)-->
<s:property value="#context['com.opensymphony.xwork2.ActionContext.locale']"/>
<!-- 打印11111111111111111,直接量,直接写的值,H表示大数据? -->
<s:property value="11111111111111111H"/><br/>
111B  表示BigDecimal类型    1111H表示BigInteger
 
3:OGNL获取属性等
<%
request.setAttribute("str"new String[]{"a","b","c"});
%>
<s:debug></s:debug>
<!-- OGNL中可以使用伪属性  .length(以下打印3) -->
<s:property value="#request.str.length"/><br/>
<s:property value="#request.str['length']"/><br/>
<s:property value="#request.str['len'+'gth']"/><br/>
 
4.1链式表达式(Chained Subexpressions):
<!-- 链式表达式,#this表示前面的110H.intValue() -->
<s:property value="110H.intValue().(#this<112?#this*2:#this/2)"/><br/>
 
*4.2访问静态资源:
取得静态常量,用@进行间隔,加小括号表示静态方法,不加小括号就是代表取get方法
<!-- 使用静态资源,需要打开静态常量开关struts.ognl.allowStaticMethodAccess -->
<!-- 表示Integer中的MAX_VALUE常量 -->
<s:property value="@java.lang.Integer@MAX_VALUE"/><br/>
<!-- 表示使用System类中的currentTimeMillis()静态方法 -->
<s:property value="@java.lang.System@currentTimeMillis()"/><hr/>
*4.3集合对象的操作
  创建集合并迭代:
  a、表达式:{'a','b','c'}用于创建List集合
<!--{'a','b','c'} 创建了一个List集合  -->
<s:iterator value="{'a','b','c'}">
    <s:property/><br/><!-- value省略,打印a b c -->
</s:iterator>
<!-- 打印class java.util.ArrayList -->
<s:property value="{'a','b','c'}.class"/><br/>
  b、表达式:#{'a':'aa','b':'bb','c':'cc'}用于创建Map集合
<s:iterator value="#{'a':'aa','b':'bb'}">
<!-- 打印a:aa  b:bb -->
    <s:property value="key"/>:<s:property value="value"/><br/>
</s:iterator>
  c、in表达式:注意复杂程度
选项有eat,sleep,study,key包含(in表达式)其中的sleep,study。
<!-- EL表达式在Struts2中已经被改写了:原有功能保持不变。只是在四大域范围内找不到的话,EL表达式就变成了OGNL表达式 -->
<s:iterator value="#{'eat':'吃饭','sleep':'睡觉','study':'学习'}">
    <input type="checkbox" name="hobby" <s:property value="key in {'java','sleep','study'}?'checked=\"checked\"':''"/> value="${key}"/>${value}
</s:iterator><br/>
 
4.4投影查询:Projecting Across Collections PPT第27页
<!-- 打印fengjie=fengjie -->
${name}=<s:property value="name"/><br/>
<!-- 打印[10, 6, 4, 0] -->
<s:property value="{5,3,2,0}.{#this*2}"/>
<!-- 打印[5, 3, 2] -->
<s:property value="{5,3,2,0}.{?#this*2}"/>
<!-- 打印 [5] -->
<s:property value="{5,3,2,0}.{^#this*2}"/>
<!-- 打印 [2] -->
<s:property value="{5,3,2,0}.{$#this*2}"/><br/>
 
5:类型的转换
  <s:property value=”(5).{#this*2}”/>--->[0, 2, 4, 6, 8]
<!-- 打印[0, 2, 4, 6, 8] -->
<s:property value="(5).{#this*2}"/><br/>
  <s:property value=”#{'name':'wzt','age':30,'gender':'male'}.{#key}”/>发现什么都没有输出
  <s:property value="#{'name':'wzt','age':30,'gender':'male'}.{#this}"/>有输出。把Map转为了Value
<!-- 打印 [wzt, 30, male]-->
<s:property value="#{'name':'wzt','age':30,'gender':'male'}.{#this}"/><br/>
<!-- 打印当前日期 -->
<s:property value="new java.util.Date()"/>
ONGL国际化

2.1、配置全局的国际消息资源包,并在JSP中进行获取

2.1在类路径或包中建立一个资源包:msg_zh_CN.properties msg_en_US.properties


2.2struts.xml中配置全局资源包:

<!-- 配置全局国际化消息资源包,value写资源包的基名,多个资源包之间用逗号,分隔-->
<constant name="struts.custom.i18n.resources" value="com.itheima.resources.msg"></constant>

2.3JSP中使用<s:text value=”key”/>的形式进行访问

<s:text name="hello"></s:text><br/> <!-- 下面这个也能访问,是调用根栈中DefaultTextProvider的方法,第一种方法其实就是调用这个方法 -->
<s:property value="getText('hello')"/><br/>
<!-- 没有hello1,则直接打印hello1 -->
<s:text name="hello1"></s:text><br/>

 

3.1、配置动作类的资源消息报,并在JSP中进行获取

动作类名_zh_CN.properties,放在与动作类相同的包中。


注意:如果动作类没有继承ActionSupport,则会从全局资源包中读取消息;如果继承了ActionSupport,则动作消息资源包的优先级要高。

原理就是在根栈中动作类在TextProvider的前面,因此先调用动作类的getText方法,如果动作类没有继承ActionSupport,就没有getText方法了。

 

4.1、配置包级别的资源消息,并在JSP中进行获取

package_zh_CN.properties  package是固定写法


5.1、其他知识因时间关系不在深究,具体参考官方文档:Guides-->Localization的说明

V2.1.8..\struts-2.1.8.1\docs\docs\localization.html

V2.3.14..\Users\wzhting\Desktop\struts-2.3.14.2\docs\WW\localization.html

 

包级别的资源包(在动作类继承actionsupport)
action动作消息资源包优先级最高
package消息资源包级别优先级次之
(package无论在哪里,优先级仍旧是次之)
全局优先级最低
 
原理:
a先自己的包,再找所有的父类的,一层层往上找
例如如下,就找到Int1的资源包

b找所有的包中,包级别的资源包
c找全局的资源文件
d打印本身(在这个列子里打印Hello1)
 
动作属性的设置
1、演示给动作类的属性赋值的三种方式(在执行动作的时候,会把当前这个动作类压入栈顶)
  2.1在动作类中直接给字段赋初始值,并提供getter和setter方法。
private String name = "fengjie";
 
  2.2(静态参数值)在struts.xml
<action name="test1" class="com.itheima.action.HelloAction1" method="test1">
    <param name="name">任敏</param><!-- 给动作类属性设置值:setter -->
    <result>/1.jsp</result>
</action>
 
  2.3(动态参数值)在请求动作时以get方式传递参数name=什么,就显示什么

 
  动作属性的设置,2.1 2.2 2.3 优先级逐步增高,就是说2.3动态参数值优先级最高。
  Tips:
  静态参数值的获取是由staticParams拦截器实现的。
  动态参数值的获取是由params拦截器实现的。
动态参数值优先值最高,因为先进行静态拦截staticParams拦截器实现,再进行动态拦截params拦截器实现,动态拦截把静态覆盖了
中文也支持,因为struts的编码常量设置默认为UTF-8
 
2、查阅staticParams和params拦截器的源代码帮助理解
查看源码,进行试验,发现如果那么重名,那么两个值都会显示

 
用户注册案例
1、先分析页面的请求再下手做。由动作开始。
2、编写配置文件(user.xml,包含到struts.xml中),动作类,JSP页面(使用UI标签)
<!-- 更改strutsUI标签的显示样式模板,参考struts2-core-*.jar中的template -->
<constant name="struts.ui.theme" value="xhtml"></constant>
<package name="p1" namespace="/user" extends="struts-default">
    <action name="RegUserUI" class="com.itheima.action.UserAction" method="RegUserUI">
        <result type="dispatcher" name="success">/WEB-INF/pages/regist.jsp</result>
    </action>
    <action name="RegUser" class="com.itheima.action.UserAction" method="RegUser">
        <result type="dispatcher" name="success">/WEB-INF/pages/main.jsp</result>
        <result type="dispatcher" name="error">/WEB-INF/pages/commons/error.jsp</result>
    </action>
</package>
写一个User的JavaBean,有username,nick和password三个变量
写动作类UserAction,继承ActionSupport。
public class UserAction extends  ActionSupport{
    private User user = new User();
    public User getUser() {
        System.out.println("getUser");
        return user;
    }
    public void setUser(User user) {
        System.out.println("setUser");
        this.user = user;
    }
    public String RegUserUI(){
        return SUCCESS;
    }
    public String RegUser(){
        try{
            System.out.println(user);
            //调用service,保存数据
            System.out.println("调用后台service,保存数据到数据库中");
            return SUCCESS;
        }catch(Exception e){
            e.printStackTrace();
            return ERROR;
        }
    }
}
写一个注册页面regist.jsp(注意name应该为user.nick这个格式)
注意,在第一个form表单中,submit不要加 name=”submit“ 因为动作类里面没有getsubmit,后台会报错.(struts-2.3.15.1已解决这个问题);
使用OGNL表达式后,只需要写action=”RegUser“就可以了。会自动得到访问地址。
此时action里面的RegUser根据struts里的常量值来,例如设置为do,那这个值自动在后面加do
不需要加冒号,会自己加,如果没有label,那么key就会使用国际化的资源包,如果有label,那么就使用label的值
    <!-- 
    <form action="${pageContext.request.contextPath}/user/RegUser.action" method="post">
        用户名:<input type="text" name="user.username"/><br/>
        昵称:<input type="text" name="user.nick"/><br/>
        密码:<input type="password" name="user.password"/><br/>
        <input type="submit" value="注册"/>
    </form>
     -->
     <s:form action="RegUser" namespace="/user">
         <s:textfield key="hello" label="用户名" name="user.username" ></s:textfield>
         <s:textfield label="昵称" name="user.nick"></s:textfield>
         <s:password label="密码" name="user.password"></s:password>
         <s:submit value="注册"></s:submit>
     </s:form>
建立index.jsp(注意要设置 escapeAmp="false",否则&会转义)
要使用s:a不要使用html的<a>好处是:动作的扩展名不定;支持中文参数值URL编码
还有一个s:url是同理的,功能类似JSTL中的c:url
s:param的value属性是一个OGNL表达式,因此字符串直接量要使用value=”'你好'”
注意,这里的地址会被重写,防止用户禁用cookie;
<s:a namespace="/user" action="RegUserUI" escapeAmp="false">注册
    <s:param name="p1">p1value</s:param>
    <s:param name="p2">你好</s:param>
</s:a><br/>
<s:url action="RegUserUI" namespace="/user" var="url" escapeAmp="false">
    <s:param name="p1" >p1value</s:param>
    <s:param name="p2">你好</s:param>
</s:url>
<href="${url}">注册</a>
技巧:如果不确定是不是OGNL表达式,那么加上%{abc},那么abc就是一个OGNL表达式而不是字符串了
 
 
ModelDriver模型驱动。  其实就是一个拦截器
其实实现了ModelDriven接口的时,会调用getModel()方法,并把该方法返回的对象压入栈顶。是modelDriven拦截器干的。
所以必须先实例化User这个类,否则压入栈顶的时候会空指针,user必须先new出来
。可以把User这个类的get和set方法删掉,因为ModelDriver这个类已经把这个实例压入栈顶了。
public class UserAction extends  ActionSupport implements  ModelDriven<User> {
    private User user = new User();
    public User getModel() {
        return user;
    }
    private Map<String, String> hobbies = new HashMap<String, String>();
    public Map<String, String> getHobbies() {
        hobbies.put("eat""吃饭");
        hobbies.put("sleep""睡觉");
        hobbies.put("study""学java");
        return hobbies;
    }
    public void setHobbies(Map<String, String> hobbies) {
        this.hobbies = hobbies;
    }
    public String RegUserUI() {
        return SUCCESS;
    }
    public String RegUser() {
        try {
            System.out.println(user);
            // 调用service,保存数据
            System.out.println("调用后台service,保存数据到数据库中");
            return SUCCESS;
        } catch (Exception e) {
            e.printStackTrace();
            return ERROR;
        }
    }
}
写jsp页面(注意用iterator标签和checkboxlist标签都能达到一样的效果)
<s:form action="RegUser" namespace="/user">
    <s:textfield key="hello" label="用户名" name="username" ></s:textfield>
    <s:textfield label="昵称" name="nick"></s:textfield>
    <s:password label="密码" name="password"></s:password>
    爱好:
    <s:iterator value="hobbies" var="me">
        <!-- 如果要把一个字符串当做OGNL表达式对待,请使用%{}包括起来 -->
        <s:checkbox name="hobby" fieldValue="%{key}" label="%{value}"></s:checkbox>
    </s:iterator>
    <hr/>
    <s:checkboxlist list="hobbies" name="hobby" listKey="key" listValue="value" label="新爱好"></s:checkboxlist>
    <s:radio list="#{'male':'男','female':'女'}" name="gender" label="性别"></s:radio>
    <s:submit value="注册"></s:submit>
</s:form>
控制逻辑的value,90%都是OGNL表达式。而UI标签里面的东西,90%都不是OGNL表达式。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值