Java代码中使用JSP/JSF表达式语言EL

JSP/JSF中的“EL”有很多版本,Tomcat对应的EL版本如下:
[img]http://dl2.iteye.com/upload/attachment/0093/6964/89558aa2-7a63-3475-b258-f0ebd8b5a54e.png[/img]
[list][*]EL2.1:JavaEE5/Tomcat6 (Unified EL:${}和#{}作用相同但不能混用)
[*]EL2.2:JavaEE6/Tomcat7
[*]EL3.0:JavaEE7/Tomcat8[/list]

从JavaEE5开始,EL的package使用javax.el.*。这个EL功能不仅可以使用在JSP/JSF中,也可以使用在所有的Java代码中,el-api.jar、jasper-el.jar可以在Tomcat的lib文件夹中找到,放入自己的工程中即可使用。

[b](1)EL2.2[/b]
这个版本的EL还不怎么支持独立程序使用,用起来也比较复杂。需要用到的几个类:ELContext、FunctionMapper、VariableMapper、ELResolver。

[b]最简单的使用[/b]
// (1)Resolver、VariableMapper、FunctionMapper都使用默认实现
final CompositeELResolver resolver = new CompositeELResolver();
resolver.add(new ResourceBundleELResolver());
resolver.add(new MapELResolver());
resolver.add(new ListELResolver());
resolver.add(new ArrayELResolver());
resolver.add(new BeanELResolver());
final VariableMapper varMapper = new VariableMapperImpl();
final FunctionMapper funcMapper = new FunctionMapperImpl();

// (2)创建ELContext
ELContext elContext = new ELContext() {
@Override
public ELResolver getELResolver() {
return resolver;
}
@Override
public FunctionMapper getFunctionMapper() {
return funcMapper;
}
@Override
public VariableMapper getVariableMapper() {
return varMapper;
}
};

// (3)EL表达式工厂类
ExpressionFactory ef = ExpressionFactory.newInstance();

// (4)设置变量的值
varMapper.setVariable("foo", ef.createValueExpression("FOO", String.class));

MyBean myBean = new MyBean();
myBean.setX(1);
myBean.setY(2);
varMapper.setVariable("bar", ef.createValueExpression(myBean, myBean.getClass()));

// (5)读入EL表达式
String expression = "hello, ${foo}! ${bar.x + 234}";// 等价于"hello, #{foo}! #{bar.x + 234}"
ValueExpression ve = ef.createValueExpression(elContext, expression, String.class);

// (6)获取表达式的值
String ret = (String) ve.getValue(elContext);
System.out.println("result=" + ret);// result=hello, FOO! 235

// 更新变量值(对象实例的场合,原有实例的值也会被修改)
String expression2 = "${bar.x}";
ValueExpression ve2 = ef.createValueExpression(elContext, expression2, Object.class);
ve2.setValue(elContext, 123);
System.out.println("myBean.x=" + myBean.getX());// myBean.x=123

// 调用对象实例的方法
String expression31 = "${bar.mes('hello')}";
MethodExpression me1 = ef.createMethodExpression(elContext, expression31, Object.class, new Class[0]);
me1.invoke(elContext, new Object[0]);// mes=hello

String expression32 = "#{bar.mes}";
MethodExpression me2 = ef.createMethodExpression(elContext, expression32, Object.class, new Class[] {String.class});
me2.invoke(elContext, new Object[] {"hello"});// mes=hello

public class MyBean {
private int x;

private int y;

public int getX() {
return x;
}

public void setX(int x) {
this.x = x;
}

public int getY() {
return y;
}

public void setY(int y) {
this.y = y;
}

public void mes(String mes) {
System.out.println("mes=" + mes);
}

@Override
public String toString() {
return "(x: " + x + ", y:" + y + ")";
}
}


[b]设置预定义变量[/b]
final CompositeELResolver resolver = new CompositeELResolver();
resolver.add(new ResourceBundleELResolver());
resolver.add(new MapELResolver());
resolver.add(new ListELResolver());
resolver.add(new ArrayELResolver());
resolver.add(new BeanELResolver());
resolver.add(new MyImplicitELResolver());// *****添加自定义Resolver*****
final VariableMapper varMapper = new VariableMapperImpl();
final FunctionMapper funcMapper = new FunctionMapperImpl();

ELContext elContext = new ELContext() {
@Override
public ELResolver getELResolver() {
return resolver;
}
@Override
public FunctionMapper getFunctionMapper() {
return funcMapper;
}
@Override
public VariableMapper getVariableMapper() {
return varMapper;
}
};

ExpressionFactory ef = ExpressionFactory.newInstance();

List<String> lst = Arrays.asList("aaa", "bbb", "ccc", "ddd");
varMapper.setVariable("list", ef.createValueExpression(lst, List.class));

// 包含预定义变量implicit的EL表达式
String expression = "${list[implicit.idx]}";
ValueExpression ve = ef.createValueExpression(elContext, expression, String.class);

// 设置预定义变量implicit的Context
ImplicitContext implicitContext = new ImplicitContext();
elContext.putContext(ImplicitContext.class, implicitContext);

for (int idx = 0; idx < lst.size(); idx++) {
implicitContext.put("idx", Integer.valueOf(idx));
String ret = (String) ve.getValue(elContext);
System.out.println("ret[" + idx + "]=" + ret);
}
// ret[0]=aaa
// ret[1]=bbb
// ret[2]=ccc
// ret[3]=ddd

public class ImplicitContext extends HashMap<String, Object> {}
public class MyImplicitELResolver extends ELResolver {

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

@Override
public Iterator<FeatureDescriptor> getFeatureDescriptors(
ELContext context, Object base) {
if (base != null) {
return Collections.<FeatureDescriptor>emptyList().iterator();
}
return null;
}

@Override
public Class<?> getType(ELContext context, Object base, Object property) {
if (base == null && property != null) {
String name = property.toString();
if ("implicit".equals(name)) {
context.setPropertyResolved(true);
return ImplicitContext.class;
}
}
return null;
}

@Override
public Object getValue(ELContext context, Object base, Object property) {
if (base == null && property != null) {
String name = property.toString();
if ("implicit".equals(name)) {
context.setPropertyResolved(true);
return context.getContext(ImplicitContext.class);
}
}
return null;
}

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

@Override
public void setValue(ELContext context, Object base, Object property, Object value) {
throw new PropertyNotWritableException("base=" + base + "/property=" + property);
}

}


[b]自定义函数[/b]

final CompositeELResolver resolver = new CompositeELResolver();
resolver.add(new ResourceBundleELResolver());
resolver.add(new MapELResolver());
resolver.add(new ListELResolver());
resolver.add(new ArrayELResolver());
resolver.add(new BeanELResolver());
final VariableMapper varMapper = new VariableMapperImpl();

// *****定义FunctionMapper*****
final FunctionMapper funcMapper = new FunctionMapper() {
private HashMap<String, Method> methods = new HashMap<String, Method>();
{
for (Method method : Math.class.getMethods()) {
if (Modifier.isStatic(method.getModifiers())) {
String name = method.getName();
Class<?>[] params = method.getParameterTypes();
boolean accept = true;
if (params.length > 0) {
if (!params[0].isAssignableFrom(double.class)) {
accept = false;
}
}
if (accept) {
methods.put(name, method);
}
}
}
}

@Override
public Method resolveFunction(String prefix, String localName) {
if ("math".equals(prefix)) {
return methods.get(localName);
}
return null;
}
};

ELContext elContext = new ELContext() {
@Override
public ELResolver getELResolver() {
return resolver;
}
@Override
public FunctionMapper getFunctionMapper() {
return funcMapper;
}
@Override
public VariableMapper getVariableMapper() {
return varMapper;
}
};

ExpressionFactory ef = ExpressionFactory.newInstance();

varMapper.setVariable("a", ef.createValueExpression(10, Integer.class));
varMapper.setVariable("b", ef.createValueExpression(20, Integer.class));

String expression = "max=${math:max(a,b)}, min=${math:min(a,b)}";
ValueExpression ve = ef.createValueExpression(elContext, expression, String.class);

String ret = (String) ve.getValue(elContext);
System.out.println("ret=" + ret);// ret=max=20.0, min=10.0


[b](2)EL3.0[/b]
在最新版的EL3.0中,Java代码中可以通过ELProcessor来很简单的使用EL。
ELProcessor elProc = new ELProcessor();

// 设置变量
elProc.defineBean("foo", new BigDecimal("123"));
elProc.defineBean("bar", "brabrabra");

// 获取表达式的值getValue()
String expression = "bar += '☆' += foo"; // 不需要使用${}或#{}
String ret1 = (String)elProc.getValue(expression, String.class);
System.out.println("ret=" + ret1);// ret=brabrabra☆123

// 获取表达式的值eval()
Number ret2 = (Number)elProc.eval("foo + 1");
System.out.println("ret=" + ret2);// ret=124

// 变量的嵌套
elProc.setVariable("v1", "foo * 2");
Number ret3 = (Number)elProc.eval("v1 + 1");
System.out.println("ret=" + ret3);// ret=247

Number ret4 = (Number)elProc.eval("v1 + foo");
System.out.println("ret=" + ret4);// ret=369

// 给不存在的变量设置值
elProc.setValue("baz", "1234");
Number ret5 = (Number)elProc.eval("baz + 1");
System.out.println("ret=" + ret5);// ret=1235

// 设置其他类型的变量
elProc.eval("qux = [1,2,3,4]");
elProc.eval("map = {'a': 111, 'b': 222}");
System.out.println("qux=" + elProc.getValue("qux", Object.class));// qux=[1, 2, 3, 4]
System.out.println("map=" + elProc.getValue("map", Object.class));// map={b=222, a=111}

// 计算多个表达式
Integer ret6 = (Integer) elProc.getValue("x=1;y=2;z=x+y", Integer.class);
System.out.println("ret=" + ret6);// ret=3

// 静态变量
elProc.defineBean("Color", new ELClass(java.awt.Color.class));
Color color = (Color) elProc.eval("Color.red");
System.out.println("ret=" + color);// ret=java.awt.Color[r=255,g=0,b=0]

// 默认导入了「java.lang.*」
System.out.println("ret=" + elProc.eval("Math.random()"));

// 自定义函数
Method method = MyClass.class.getMethod("strJoin", new Class[] {String.class, List.class});
elProc.defineFunction("myFn", "join", method);
Object ret = elProc.eval("myFn:join(',', ['aaa', 'bbb', 'ccc', 123])");
System.out.println("ret=" + ret);// ret=aaa,bbb,ccc,123

// 计算lambda表达式
List<Integer> listdata = Arrays.asList(1, 2, 3, 4, 5, 6);
elProc.defineBean("list", listdata);

String lambda1 = "sum=0;list.stream().forEach(x->(sum=sum+x));sum";
Number ret8 = (Number) elProc.eval(lambda1);
System.out.println("ret=" + ret8.intValue());// ret=21

String lambda1b = "list.stream().sum()";
Number ret9 = (Number) elProc.eval(lambda1b);
System.out.println("ret=" + ret9.intValue());// ret=21

String lambda1c = "list.stream().reduce(0,(a,b)->a+b)";
Number ret10 = (Number) elProc.eval(lambda1c);
System.out.println("ret=" + ret10.intValue());// ret=21

public class MyClass {
public static String strJoin(String sep, List<Object> args) {
StringBuilder buf = new StringBuilder();
if (args != null) {
for (Object arg : args) {
if (buf.length() > 0) {
buf.append(sep);
}
buf.append(arg != null ? arg.toString() : "");
}
}
return buf.toString();
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值