1.上一篇文章,我介绍了OGNL表达式语言,本来想在那篇文章上加上一个使用OGNL访问静态方法和静态属性的例子,但是昨天晚上我写代码时,报了一个警告,获取得到静态属性的值,却获取不到静态方法的返回值,所以今天特别的写篇文章来介绍一下。

2.这里我先附上这个例子,来了解如何使用OGNL表达式访问静态方法和属性。

(1).其中访问静态方法或者静态属性的语法分别为:@类的路径@方法名,@类的路径@属性名,语法中类的路径,即包名+类名。

(2).对于OGNL来说,java.lang.Math是其默认的类,如果调用java.lang.Math的静态方法时,无需指定类的名字,比如:@@min(4,10),就比较两者谁比较小,输出较小的那个数。

注:其中第一点也可以理解为调用一个类的静态方法和静态属性,其中第二点也可以理解为调用JDK类中的静态方法。

(3).项目结构图如下:

(4).首先新建一个Struts2项目,项目名为StaticTest,新建一个类,放在com.gk包下,类名为StaticTest,完整代码如下:

package com.gk;public class StaticTest{public static String str="static property";public static String s(){return "static method";}
}

打开index.jsp页面,编码格式改为utf-8,加入<%@ taglib uri="/struts-tags"  prefix="s" %>,就可以使用struts的标签,具体代码如下:

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="/struts-tags"  prefix="s" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><base href="<%=basePath%>"><title>My JSP 'index.jsp' starting page</title><meta http-equiv="pragma" content="no-cache"><meta http-equiv="cache-control" content="no-cache"><meta http-equiv="expires" content="0">    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"><meta http-equiv="description" content="This is my page"><!--<link rel="stylesheet" type="text/css" href="styles.css">--></head><body><ol><li>访问静态方法:<s:property value="@com.gk.StaticTest@s()"/></li><li>访问静态属性:<s:property value="@com.gk.StaticTest@str"/></li><li>访问java.lang.Math类的静态方法:<s:property value="@@max(2,5)"/></li><s:debug></s:debug></ol></body>
</html>

一定要在struts.xml配置文件中配置允许使用OGNL访问静态方法,否则不能使用OGNL访问静态方法,必须在struts.xml文件中加入这行代码:

<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>

其中完整struts.xml文件如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!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.enable.DynamicMethodInvocation" value="true"></constant><constant name="struts.devMode" value="true"></constant><constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
</struts>

(5).接着部署该项目到Tomcat服务器上,开启Tomcat服务器,运行后如下:

为何取不到静态方法的返回值呢?很奇怪!

3.发现访问静态方法,获取不出它的返回值,然后看一下控制台,有警告信息,但是不是错误,警告信息如下图所示:

这个警告信息使我搞了我半天都没解决,控制台输出的信息是com.opensymphony.xwork2.ognl.SecurityMemberAccess warn个类警告,警告内容是Target class [class com.gk.StaticTest] or declaring class of member type [public static java.lang.String com.gk.StaticTest.s()] are excluded! ,意思是目标类StaicTest类或者声明类的成员类型[public static java.lang.String com.gk.StaticTest.s()]是被排除,被赶出了,表明意思是这样,我就百度了一下,发现有小部分的同学都会报这错误,但是都没解决,所以我就去查看一下底层代码,看能看出个所以然么?

(1).这个警告是com.opensymphony.xwork2.ognl.SecurityMemberAccess warn,所以我就找到这个SecurityMemberAccess类,它是放在com.opensymphony.xwork2.ognl包下的,而这个包是放在xwork-core-2.3.20.jar 包下的,所以我们必须导入这个包的源代码,才能查看,这个导入我在之前的文章说过,这里再用图的方式显示一次:

首先找到这个jar包:

选中这个jar包,然后鼠标右键单击,选择Properties属性,找到你下载的那个搭建环境所需要的包,然后找到xwork-core相关的文件,即E:/struts-2.3.20/struts-2.3.20/src/xwork-core/src/main/java,复制到下图的红色框框的地方,点击箭头指向的两个按钮,首先Apply应用按钮,再点击Ok确定按钮:

这样我们就可以打开这个jar包下的.class文件,都是我们熟悉的Java代码。

(2).打开com.opensymphony.xwork2.ognl包下的SecurityMemberAccess类,即如下图所示:

双击打开后,代码如下:

/** Copyright 2002-2006,2009 The Apache Software Foundation.* * Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at* *      http://www.apache.org/licenses/LICENSE-2.0* * Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
package com.opensymphony.xwork2.ognl;import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import ognl.DefaultMemberAccess;import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** Allows access decisions to be made on the basis of whether a member is static or not.* Also blocks or allows access to properties.*/
public class SecurityMemberAccess extends DefaultMemberAccess {private static final Logger LOG = LoggerFactory.getLogger(SecurityMemberAccess.class);private final boolean allowStaticMethodAccess;private Set<Pattern> excludeProperties = Collections.emptySet();private Set<Pattern> acceptProperties = Collections.emptySet();private Set<Class<?>> excludedClasses = Collections.emptySet();private Set<Pattern> excludedPackageNamePatterns = Collections.emptySet();public SecurityMemberAccess(boolean method) {super(false);allowStaticMethodAccess = method;}public boolean getAllowStaticMethodAccess() {return allowStaticMethodAccess;}@Overridepublic boolean isAccessible(Map context, Object target, Member member, String propertyName) {if (checkEnumAccess(target, member)) {if (LOG.isTraceEnabled()) {LOG.trace("Allowing access to enum #0", target);}return true;}if (isPackageExcluded(target.getClass().getPackage(), member.getDeclaringClass().getPackage())) {if (LOG.isWarnEnabled()) {LOG.warn("Package of target [#0] or package of member [#1] are excluded!", target, member);}return false;}if (isClassExcluded(target.getClass(), member.getDeclaringClass())) {if (LOG.isWarnEnabled()) {LOG.warn("Target class [#0] or declaring class of member type [#1] are excluded!", target, member);}return false;}boolean allow = true;if (!checkStaticMethodAccess(member)) {if (LOG.isTraceEnabled()) {LOG.warn("Access to static [#0] is blocked!", member);}allow = false;}//failed static testif (!allow)return false;// Now check for standard scope rulesreturn super.isAccessible(context, target, member, propertyName)&& isAcceptableProperty(propertyName);}protected boolean checkStaticMethodAccess(Member member) {int modifiers = member.getModifiers();if (Modifier.isStatic(modifiers)) {return allowStaticMethodAccess;} else {return true;}}protected boolean checkEnumAccess(Object target, Member member) {if (target instanceof Class) {Class clazz = (Class) target;if (Enum.class.isAssignableFrom(clazz) && member.getName().equals("values"))return true;}return false;}protected boolean isPackageExcluded(Package targetPackage, Package memberPackage) {for (Pattern pattern : excludedPackageNamePatterns) {if (pattern.matcher(targetPackage.getName()).matches() || pattern.matcher(memberPackage.getName()).matches()) {return true;}}return false;}protected boolean isClassExcluded(Class<?> targetClass, Class<?> declaringClass) {if (targetClass == Object.class || declaringClass == Object.class) {return true;}for (Class<?> excludedClass : excludedClasses) {if (targetClass.isAssignableFrom(excludedClass) || declaringClass.isAssignableFrom(excludedClass)) {return true;}}return false;}protected boolean isAcceptableProperty(String name) {return name == null || ((!isExcluded(name)) && isAccepted(name));}protected boolean isAccepted(String paramName) {if (!this.acceptProperties.isEmpty()) {for (Pattern pattern : acceptProperties) {Matcher matcher = pattern.matcher(paramName);if (matcher.matches()) {return true;}}//no match, but acceptedParams is not emptyreturn false;}//empty acceptedParamsreturn true;}protected boolean isExcluded(String paramName) {if (!this.excludeProperties.isEmpty()) {for (Pattern pattern : excludeProperties) {Matcher matcher = pattern.matcher(paramName);if (matcher.matches()) {return true;}}}return false;}public void setExcludeProperties(Set<Pattern> excludeProperties) {this.excludeProperties = excludeProperties;}public void setAcceptProperties(Set<Pattern> acceptedProperties) {this.acceptProperties = acceptedProperties;}public void setExcludedClasses(Set<Class<?>> excludedClasses) {this.excludedClasses = excludedClasses;}public void setExcludedPackageNamePatterns(Set<Pattern> excludedPackageNamePatterns) {this.excludedPackageNamePatterns = excludedPackageNamePatterns;}
}

代码也不多,我们只看重要的,可以通过大纲看代码:

大纲中有变量,常量,和方法,一个个点击来看,其中我找到了报错的那一行,但是看了也不知道怎么解决,郁闷!如下图所示:

它就是报这行警告,这行警告是通过判断isClassExcluded这个方法来决定的:

这个方法判断了目标类和超类是否相等或者声明类和超类是否相同,相等的话返回真,这就不多做解释了,然后我们报错的那行的那幅图里传进来的两个类,一个是目标类,一个是声明类,而这个声明类是通过成员来获得的,这又不知道为何了,所以看底层代码又看不懂,所以只能求助我热心的群友了。

注:这里我为何要介绍看底层代码呢,因为这样有利于我们理解和学习代码为什么这样写,又为什么报这警告。由于水平有限,所以我也郁闷了!

(3).我就去请教一下我的群友,我那个群是安卓群,发了一下牢骚,群友就问你遇到什么问题了,说一下,看我懂不,我就跟他们说了这个问题,过了一会儿一位群友说我去Struts的官网查了下,说最新版本的struts2不支持OGNL访问静态方法了,估计是因为安全问题,访问静态方法怕不安全,想想我用的还真是最新版本,我说难怪老师要我们用较稳定的版本,别用最新的,果然,我把上面这个项目的核心代码复制到低版本的项目中,就可以了,真是一波三折啊!

4.以上那个例子的代码是没错的,是因为版本问题,才导致只可以使用OGNL访问静态属性,而访问不了静态方法,所以我使用较低版本jar包,我把上面这个项目的一些代码复制,调整一下,改变一些名字等等,我用的是下图的版本:

一切搞定之后,运行效果如下:

这样就可以使用OGNL访问静态方法,并获取得到它的值。

5.总结:对于使用OGNL表达式语言来访问静态方法,这个比较少用,如果在使用OGNL访问静态方法,但是获取不到值,并控制台输出如上面我所介绍的一些警告信息,有可能是你版本是最新的原因,代码是没错误的,所以建议大家使用较稳定版本,使用较稳定版本后,通过上面这个例子就可以使用OGNL访问静态方法并获取其静态方法的返回值。

6.以上内容仅供大家学习参考,写的不好,请见谅,如有问题,请指出,如文章有错误,请指出,谢谢!

.

Struts2中使用OGNL表达式语言访问静态方法和静态属性以及我遇到的问题和解决方法相关推荐

  1. Struts2中的OGNL表达式

    基础知识(三) Struts2中的OGNL表达式 浅析值栈 ValueStack对象相当于一个栈,它贯穿整个Action的生命周期,每个Action类的对象实例都会拥有一个ValueStack对象 当 ...

  2. Struts2中的OGNL表达式的详解

    首先了解下OGNL的概念: OGNL是Object-Graph Navigation Language的缩写,全称为对象图导航语言,是一种功能强大的表达式语言,它通过简单一致的语法,可以任意存取对象的 ...

  3. 深入理解Struts2中的OGNL表达式

    Struts 2中的表达式语言 Struts 2支持以下几种表达式语言: OGNL(Object-Graph Navigation Language),可以方便地操作对象属性的开源表达式语言: JST ...

  4. Struts2中使用OGNL表达式投影(过滤)集合

    1.集合的投影(过滤)有以下三种方式: a."?#":投影(过滤)所有符合条件的集合,如:users.{?#this.age > 19}: b."^#": ...

  5. struts2中No result defined for action xxx.xxx.xxx and result xxx错误的几种解决方法

    首先先说一下No result defined for action xxx.xxx.xxx and result xxx这个错误 action后跟的是你的action名称 result是返回值错误, ...

  6. Struts2之OGNL表达式语言

    1.OGNL是Object-Graph Navigation Language的缩写,是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构 ...

  7. OGNL表达式语言浅谈

    OGNL(Object Graphic Navigation Language,对象图导航语言)是一种功能强大的EL(Expression Language,表达式语言,JSP2.0规范),Strut ...

  8. OGNL表达式语言中的#和$的区别

    Struts2使用标准的Context来进行OGNL表达式语言求值,OGNL的顶级对象是一个Context,这个Context对象就是一个Map类型实例,其根对象就是 ValueStack,如果需要访 ...

  9. Struts2的OGNL表达式语言

    支持Struts2的OGNL表达式语言(2009-04-25 01:11:36) <script></script> 标签:struts2 ognl it  分类:Spring ...

最新文章

  1. C语言输入3298运行结果为,浙江农林大C语言程序设计习题集答.doc
  2. 64位系统上使用*** Client端
  3. 谈从10亿个数中找出前10万个最大的
  4. 如何使用Quagga,将你的CentOS设备变成OSPF路由器
  5. 在国外读phd 的时候和supervisor沟通的时候需要注意的点
  6. 放假了,暂告一段落,迎接研究生
  7. 计算机网络课制作双绞线实验,《计算机网络》课程实验——网线制作.pdf
  8. 达梦数据库连接(单机、多实例、多数据源版本)
  9. mysql max 命令大全_MySQL常用命令,34道练习题(持续更新中)。
  10. golang之网络开发
  11. Flutter基础—绘画效果之装饰容器
  12. Spring day03笔记
  13. 2010十一月份日用百货热销品货源推荐
  14. Java-Lambda表达式第二篇认识Lambda表达式
  15. 【转】JavaScript生成GUID的算法
  16. Nginx+Tomcat web站(Linux)   动静站分离
  17. 国家何时整治程序员的高薪现象???
  18. CF1428F-Fruit Sequences
  19. AutoHotKey写一个改键的小脚本
  20. Java Email

热门文章

  1. 给tomcat 配置https
  2. Oracle中dmp/dmpdp导出,imp/impdp导入
  3. Java中Cookie常用操作类(Spring中操作Cookie)
  4. Xcode中常见的错误,警告和解决方法
  5. JS中URL中的特殊字符问题:escape,encodeURI,encodeURIComponent(转)
  6. spring security3(转)
  7. WCF学习笔记(2)——独立WCF服务
  8. [Vue.js]实战 -- 电商项目(四)
  9. [Ajax] jQuery中的Ajax -- 04-异步提交表单
  10. 初步了解react-babel-虚拟DOM-JSX-类组件-函数式组件