在一些XML文件中,我看到了类似于<tag attr="${sys:com.foo.bar}"/>的内容,其中表示${sys:com.foo.bar}将被替换为System.getProperty("com.foo.bar").

我希望我的EL处理器支持这样的功能.然而,我找不到怎么做.

ELProcessor elProcessor = new ELProcessor();
elProcessor. ???

唯一有前缀的方法是defineFunction,但据我所知,这不是我需要的:

this.elProcessor.defineFunction(prefix, function, method);
this.elProcessor.defineFunction(prefix, function, className, method);

有人能告诉我如何让我的EL处理器使用带有名称空间的变量吗?

推荐答案

毫无疑问,您已经在与Maven/Spring/Log4j相关的XML配置文件中看到了这一点.不幸的是,他们没有利用雅加达解决这些问题.他们暗地里用Apache Commons Text StringSubstitutor来做这个.而且,雅加达El从一开始就不支持这个syntax.它甚至在有机会命中任何定制的EL侦听器或EL解析器之前就已经死于语法错误.

对于Jakarta EL,最好的 Select 是将语法更改为${sys['com.foo.bar']},并添加一个定制ELResolver,它将${sys}识别为特殊类型的基数,然后通过System#getProperty()解析其余部分.

以下是此类EL解析器的启动工作示例:

public class SystemPropertyELResolver extends ELResolver {

    @Override
    public Class<?> getCommonPropertyType(ELContext context, Object base) {
        return (base == this) ? String.class : null;
    }

    @Override
    public Class<?> getType(ELContext context, Object base, Object property) {
        if (base == null && "sys".equals(property)) {
            context.setPropertyResolved(true);
            return getClass();
        }
        else if (base == this && property != null) {
            context.setPropertyResolved(true);
            return getCommonPropertyType(context, base);
        }

        return null;
    }

    @Override
    public Object getValue(ELContext context, Object base, Object property) {
        if (base == null && "sys".equals(property)) {
            context.setPropertyResolved(true);
            return this;
        }
        else if (base == this && property != null) {
            context.setPropertyResolved(true);
            return System.getProperty(property.toString());
        }

        return null;
    }

    @Override
    public void setValue(ELContext context, Object base, Object property, Object val) {
        // NOOP.
    }

    @Override
    public boolean isReadOnly(ELContext context, Object base, Object property) {
        return true;
    }

    @Override
    public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) {
        return null;
    }

}

要使其运行,请按如下方式进行注册:

elProcessor.getELManager().addELResolver(new SystemPropertyELResolver());

然而,在System#getProperty()specific种情况下,还有另一种更简单的"使用名称空间定义变量"的方法.因为System#getProperties()已经返回了java.util.Map的实例,所以可以使用内置jakarta.el.MapELResolver来处理它,同时使用与${sys['com.foo.bar']}相同的语法.

elProcessor.defineBean("sys", System.getProperties());

这只会给您提供进一步定制EL分辨率的机会.

Java相关问答推荐

在URL类图中表示Java swing类

Java 22模式匹配不适用于记录模式匹配.给出汇编问题

如何将kotlin代码转换为java

RxJava PublishSubject缓冲区元素超时

Junit with Mockito for java

如何让JFileChooser(DIRECTORIES_ONLY)从FolderName中的空白开始?

Spring和可编辑";where";@Query

Java构造函数分支

如何在不删除Java中已有内容的情况下覆盖文件内容?

Java 11 HttpCookie.parse在解析包含JSON的Cookie时引发IlLegalArgumentException

如何从HttpResponse实例获取Entity对象的内容?

如何根据配置动态创建N个bean

在应用getCellFormula()时,Excel引用中的文件名始终为";[1]";使用Apache POI()

为了安全起见,有必要复制一份 list 吗?

如何使用jooq更新记录?

我该如何为我的类编写getter和setter方法?

我无法在我的Spring Boot应用程序中导入CSV依赖项

MapStruct记录到记录的映射不起作用

在不带instanceof或switch的java中记录模式

更新不可变的深层嵌套字段