• OGNL(对象图导航语言)学习


    一、关于OGNL(Object-Graph Navigation Language),一种可以方便地操作对象属性的开源表达式语言。

      特点:  1)支持对象方法调用,形式如:objName.methodName();

                  2)支持类静态的方法调用和值访问,表达式的格式为@[类全名(包括包路)]@[方法名 |  值名]

                  3)支持赋值操作和表达式串联,

                  4)访问OGNL上下文(OGNL context)和ActionContext;

                  5)操作集合对象。

    1.新建项目:并且有一个主包com.bjsxt.struts2.ognl。

    2.最重要是的配置struts.xml文件,关乎action的具体动作和行为,此处只是设置了struts的具体权限,可以执行实例方法等。

    <struts>
    <constant name="struts.enable.DynamicMethodInvocation" value="false" />
    <constant name="struts.devMode" value="true" />
    <constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
    <include file="com/bjsxt/struts2/ognl/ognl.xml"/>
    </struts>

    3.配置ognl.xml文件。主要指引struts去执行对应的action。

    <struts>
    <package name="ognl" extends="struts-default">
    <action name="ognl" class="com.bjsxt.struts2.ognl.OgnlAction">
    <result>/ognl.jsp</result>
    </action>
    <action name="test" class="com.bjsxt.struts2.ognl.TestAction">
    <result type="chain">ognl</result>
    </action>
    </package>
    </struts>

    4.写OgnlAction的方法:为了实践ognl表达式,就设置了包括有User、Dag、Cat、Map、List、Set等类,并且具体某个类具有的方法也不一。

    package com.bjsxt.struts2.ognl;

    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;

    import com.opensymphony.xwork2.ActionSupport;

    public class OgnlAction extends ActionSupport {
    private Cat cat;
    private Map<String, Dog> dogMap = new HashMap<String, Dog>();

    private Set<Dog> dogs = new HashSet<Dog>();

    private String password;

    private User user;
    private String username;

    private List<User> users = new ArrayList<User>();

    public OgnlAction() {
    users.add(new User(1));
    users.add(new User(2));
    users.add(new User(3));

    dogs.add(new Dog("dog1"));
    dogs.add(new Dog("dog2"));
    dogs.add(new Dog("dog3"));

    dogMap.put("dog100", new Dog("dog100"));
    dogMap.put("dog101", new Dog("dog101"));
    dogMap.put("dog102", new Dog("dog102"));
    }

    public String execute() {
    return SUCCESS;
    }

    public Cat getCat() {
    return cat;
    }
    public Map<String, Dog> getDogMap() {
    return dogMap;
    }

    public Set<Dog> getDogs() {
    return dogs;
    }

    public String getPassword() {
    return password;
    }
    public User getUser() {
    return user;
    }

    public String getUsername() {
    return username;
    }

    public List<User> getUsers() {
    return users;
    }

    public String m() {
    return "hello";
    }

    public void setCat(Cat cat) {
    this.cat = cat;
    }
    public void setDogMap(Map<String, Dog> dogMap) {
    this.dogMap = dogMap;
    }

    public void setDogs(Set<Dog> dogs) {
    this.dogs = dogs;
    }

    public void setPassword(String password) {
    this.password = password;
    }

    public void setUser(User user) {
    this.user = user;
    }

    public void setUsername(String username) {
    this.username = username;
    }

    public void setUsers(List<User> users) {
    this.users = users;
    }
    }

    4.1 User类:User只有一个属性Age,并且具有它自身相应的get和set方法,以及值栈输出需要具有的toString方法。

    package com.bjsxt.struts2.ognl;

    public class User {
    private int age = 8;

    public User() {

    }
    public User(int age) {
    super();
    this.age = age;
    }
    public int getAge() {
    return age;
    }
    public void setAge(int age) {
    this.age = age;
    }
    @Override
    public String toString() {
    return "user" + age;
    }
    }

    4.2 Cat类:在这个类中定义了Cat的friend Dog,以及Cat自身具有的一个方法miaomiao(),这样定义也就意味着访问Dog时需要在地址栏输入cat.friend.name=?才能访问到Cat 的friend: Dog。

    package com.bjsxt.struts2.ognl;

    public class Cat {
    private Dog friend;
    public Dog getFriend() {
    return friend;
    }
    public String miaomiao() {
    return "miaomiao";
    }
    public void setFriend(Dog friend) {
    this.friend = friend;
    }
    }

    4.3 Dog类:定义了Dog的一个属性name,相应的需要get,set,toString 方法。

    package com.bjsxt.struts2.ognl;

    public class Dog {

    private String name;

    public Dog() {

    }
    public Dog(String name) {
    super();
    this.name = name;
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    @Override
    public String toString() {
    return "dog: " + name;
    }
    }

    4.4 S类:主要用于测试static静态方法的调用,如果调用成功则返回一个 "static method";。

    package com.bjsxt.struts2.ognl;

    public class S {
    public static String STR = "STATIC STRING";
    public static String s() {
    return "static method";
    }
    }

    4.5 TestAction类

    package com.bjsxt.struts2.ognl;

    import com.opensymphony.xwork2.ActionSupport;

    public class TestAction extends ActionSupport {

    @Override
    public String execute() throws Exception {
    return super.execute();
    }

    }

    5.V层: index.jsp,只有一个超链接,点击超链接即可出现各种属性的访问情况。现在从页面手动传过去了一个username:admin和password:123。

    <%
    String contextPath = request.getContextPath();
    %>

    <body>
    访问属性
    <a href="<%=contextPath %>/ognl.action?username=admin&password=123">ognl</a>
    </body>

    6.ognl.jsp:此页面用于显示各个属性访问情况。

    <?xml version="1.0" encoding="UTF-8" ?>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%@ taglib uri="/struts-tags" prefix="s"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>OGNL表达式语言学习</title>
    </head>
    <body>
    <ol>
    <li>访问值栈中的action的普通属性: username = <s:property value="username" />
    </li>
    <li>访问值栈中对象的普通属性(get set方法):<s:property value="user.age" /> | <s:property
    value="user['age']" /> | <s:property value="user["age"]" /> |
    wrong: <s:property value="user[age]" /></li>
    <li>访问值栈中对象的普通属性(get set方法): <s:property value="cat.friend.name" /></li>
    <li>访问值栈中对象的普通方法:<s:property value="password.length()" /></li>
    <li>访问值栈中对象的普通方法:<s:property value="cat.miaomiao()" /></li>
    <li>访问值栈中action的普通方法:<s:property value="m()" /></li>
    <hr />
    <li>访问静态方法:<s:property value="@com.bjsxt.struts2.ognl.S@s()" /></li>
    <li>访问静态属性:<s:property value="@com.bjsxt.struts2.ognl.S@STR" /></li>
    <li>访问Math类的静态方法:<s:property value="@@max(2,3)" /></li>
    <hr />
    <li>访问普通类的构造方法:<s:property
    value="new com.bjsxt.struts2.ognl.User(8)" /></li>
    <hr />
    <li>访问List:<s:property value="users" /></li>
    <li>访问List中某个元素:<s:property value="users[1]" /></li>
    <li>访问List中元素某个属性的集合:<s:property value="users.{age}" /></li>
    <li>访问List中元素某个属性的集合中的特定值:<s:property value="users.{age}[0]" /> |
    <s:property value="users[0].age" /></li>
    <li>访问Set:<s:property value="dogs" /></li>
    <li>访问Set中某个元素:<s:property value="dogs[1]" /></li>
    <li>访问Map:<s:property value="dogMap" /></li>
    <li>访问Map中某个元素:<s:property value="dogMap.dog101" /> | <s:property
    value="dogMap['dog101']" /> | <s:property value="dogMap["dog101"]" /></li>
    <li>访问Map中所有的key:<s:property value="dogMap.keys" /></li>
    <li>访问Map中所有的value:<s:property value="dogMap.values" /></li>
    <li>访问容器的大小:<s:property value="dogMap.size()" /> | <s:property
    value="users.size" />
    </li>
    <hr />
    <li>投影(过滤):<s:property value="users.{?#this.age==1}[0]" /></li>
    <li>投影:<s:property value="users.{^#this.age>1}.{age}" /></li>
    <li>投影:<s:property value="users.{$#this.age>1}.{age}" /></li>
    <li>投影:<s:property value="users.{$#this.age>1}.{age} == null" /></li>
    <hr />
    <li>[]:<s:property value="[0].username" /></li>

    </ol>

    <s:debug></s:debug>
    </body>
    </html>

    :正则表达式;?#:表示过滤条件;^#:表示开头;$#:表示结束。

    7.运行、调试。

    7.1 我们先把部分属性打上注释:先访问值栈对象中属性即方法。可以发现只访问到部分属性。

    用Debug方式可以发现只有手动输入的username和password有值,而user是空的 ,说明其对应的age默认值是8都取不到。

    所以我们需要在地址栏手动输入对应的age就可以实现取值:

    从结果可以看出Cat的friend :Dog没有名字给它,所以没有结果:

     

    我们只要在地址栏输入cat.friend.name=Cookie即(曲奇)即可看到运行结果显示了Dog 的名字是Cookie

    还有就是访问值栈对象中的普通方法即Cat自己独有的"miaomiao()"也是空值,按照之前的Cat方法来看,应该输出“miaomiao”才对。

    是的,解决办法还是如出一辙,即手动输入Cat具有的方法miaomiao(),只是在地址栏输入要跟ognl.jsp中的一致:cat.mioamiao。

    7.2 运行测试静态方法,可以发现静态方法没有访问到。

     

    原因是struts.xml中没有设置权限,加上这句话:<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>即可。

    :访问静态方法:<s:property value="@cn.cqvie.ognldemo.S@s()"/>@类名@方法名(或者属性名)。

          toStrng()方法:用于打印出某些字符串(对象)而且形式较为规范。
          若是写成:@@max(2,3)也不奇怪,只是这样就只能访问该类的属性,一般不常用。

    7.3测试List、Map、Set方法:

           Set:无序、不重复, 所以无法访问到具体的某个值栈,也没有意义。可以按照默认排序,也可以通
                  过实现java.util.Comparator<Type>接口来自定义排序方式。
          Map: 每一个元素包含一个键对象和值对象,它们成对出现。键对象不能重复,值对象可以重复。
          List:有序可以重复,可以访问到值栈中的某个特定的属性。允许按照对象在集合中的索引位置检索对
                  象,如通过list.get(i)方式来获得List集合中的元素。

    7.4 ognl的过滤、投影方法

    正如之前所分析的一样,Set是无序的,所以无法访问到该集合中具体的键值。所以是空的。

    8.总结、教训

    8.1  各种表达式需要熟练运用,才能掌握其中的奥妙,并且联合起来运用,而我用的很吃力,原因是没有深究过其中的门道;

          但是通过今天我似乎熟悉了很多,学会运用这个表达式可以省好多事。

    8.2  ognl表达式算是一个新知识了,我还做不到完全接受,但是现在不代表以后,我相信时间可以沉淀自己。

    8.3  在学习这个标签的过程中,感觉还是Java基础不牢固,以至于很多常用的方法都理解不来,还有很多东西需要加强学习。

    8.4  需要明白的一点是当自己没有创建构造方法时,系统会自动为你创建一个无参的构造方法并调用;当你自己创建了一个 

          有参的构造方法时,系统将不会再创建无参的构造方法。

    8.5 ognl表达式:必须要使用对象.属性才能传值即构造出一个对象。必须提供一个空的构造方法,否则系统不会自动调用

           那个无参的构造方法,即无法初始化,不会自动new 一个对象,从而不会调用到对象的属性和值。

     

    没有人能一路单纯到底,但是要记住,别忘了最初的自己!
  • 相关阅读:
    Python--day34--socket模块的方法
    Python--day32--ftp文件传输报错的原因
    Python--day32--struct模块
    Python--day32--复习:https和http的区别;黏包;黏包问题的解决方式;
    快捷键(随时补充)
    turtle 20秒画完小猪佩奇“社会人”
    Kibana使用教程
    Elasticsearch: 权威指南
    數據可視化大屏
    newtonsoft文檔說明
  • 原文地址:https://www.cnblogs.com/LindaBlog/p/5408672.html
Copyright © 2020-2023  润新知