Ognl更新到3.2.6之后,出现了MemberAccess implementation must be provided!这个异常,看字面意思好像是:成员访问这个接口的实现必须提供,自己去跟了一下Ognl的源码,确实这个是需要自己手动写,作者没有提供一个Default的实现。如果你不传入,作者当做null处理。
实验代码如下:
@Test
public void found() throws OgnlException {
OgnlContext context = new OgnlContext(null,null,new DefaultMemberAccess(true));
Object tail = Ognl.getValue("substring(0,4)",context, "ognl3.2.6MemeberAccess");
logger.info(tail.toString());
}
这段代码,需要传入一个自己的实现MemberAccess的接口,但是,我从Google或者Baidu搜索到的答案,中文的答案一般是:更换版本到2.7.x版本,我想既然升级,哪有倒退的道理,继续查看老外的答案,基本上就是说了一通,也没搞定。
最后去github找作者的源码,看看作者是怎么解释这个事情的(Ognl的作者的FAQ),在作者的FAQ的回复当中找到了答案:作者说,这个是必须实现的,但是为啥我在Ognl的jar包当中没有给一个默认实现,我是觉得,这个实现要符合(suite)你们的项目(project)。然后,我给你一个默认的实现例子。下面是作者的原话:
How to define an AccessMember?
the best way is to implement your own AccessMember which will suite your project best,
you can base on existing DefaultAccessMember and adjust it to your needs.
然后跟着这个链接地址,找到了作者亲自操刀写的一个默认实现:DefaultAccessMember,链接:DefaultAccessMember
下面是DefaultAccessMemeber的源码
//--------------------------------------------------------------------------
// Copyright (c) 1998-2004, Drew Davidson and Luke Blanshard
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// Neither the name of the Drew Davidson nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//--------------------------------------------------------------------------
package ognl;
import java.lang.reflect.*;
import java.util.*;
/**
* This class provides methods for setting up and restoring
* access in a Field. Java 2 provides access utilities for setting
* and getting fields that are non-public. This object provides
* coarse-grained access controls to allow access to private, protected
* and package protected members. This will apply to all classes
* and members.
*
* @author Luke Blanshard ([email protected])
* @author Drew Davidson ([email protected])
* @version 15 October 1999
*/
public class DefaultMemberAccess implements MemberAccess
{
public boolean allowPrivateAccess = false;
public boolean allowProtectedAccess = false;
public boolean allowPackageProtectedAccess = false;
/*===================================================================
Constructors
===================================================================*/
public DefaultMemberAccess(boolean allowAllAccess)
{
this(allowAllAccess, allowAllAccess, allowAllAccess);
}
public DefaultMemberAccess(boolean allowPrivateAccess, boolean allowProtectedAccess, boolean allowPackageProtectedAccess)
{
super();
this.allowPrivateAccess = allowPrivateAccess;
this.allowProtectedAccess = allowProtectedAccess;
this.allowPackageProtectedAccess = allowPackageProtectedAccess;
}
/*===================================================================
Public methods
===================================================================*/
public boolean getAllowPrivateAccess()
{
return allowPrivateAccess;
}
public void setAllowPrivateAccess(boolean value)
{
allowPrivateAccess = value;
}
public boolean getAllowProtectedAccess()
{
return allowProtectedAccess;
}
public void setAllowProtectedAccess(boolean value)
{
allowProtectedAccess = value;
}
public boolean getAllowPackageProtectedAccess()
{
return allowPackageProtectedAccess;
}
public void setAllowPackageProtectedAccess(boolean value)
{
allowPackageProtectedAccess = value;
}
/*===================================================================
MemberAccess interface
===================================================================*/
public Object setup(Map context, Object target, Member member, String propertyName)
{
Object result = null;
if (isAccessible(context, target, member, propertyName)) {
AccessibleObject accessible = (AccessibleObject)member;
if (!accessible.isAccessible()) {
result = Boolean.FALSE;
accessible.setAccessible(true);
}
}
return result;
}
public void restore(Map context, Object target, Member member, String propertyName, Object state)
{
if (state != null) {
((AccessibleObject)member).setAccessible(((Boolean)state).booleanValue());
}
}
/**
Returns true if the given member is accessible or can be made accessible
by this object.
*/
public boolean isAccessible(Map context, Object target, Member member, String propertyName)
{
int modifiers = member.getModifiers();
boolean result = Modifier.isPublic(modifiers);
if (!result) {
if (Modifier.isPrivate(modifiers)) {
result = getAllowPrivateAccess();
} else {
if (Modifier.isProtected(modifiers)) {
result = getAllowProtectedAccess();
} else {
result = getAllowPackageProtectedAccess();
}
}
}
return result;
}
}
我们使用的时候,直接Copy下来,然后构造一个DefaultAccessMember的对象,默认传入构造函数true就行了