`
zuoge85
  • 浏览: 78923 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

简单el表达式实现

阅读更多

一个简单的el表达式实现

 

实现还在完善种,现在只能处理引用类型的的属性字段和函数,不支持容器类数组!不支持子类型

 

线来个测试用例

 

package com.isnowfox.oel;

import java.util.Date;

import com.isnowfox.core.junit.BaseTest;
import com.isnowfox.util.RandomUtils;

/**
 * el 测试用例
 * @author zuoge85
 *
 */
public class OelTest extends BaseTest{
	public void testBasObject() throws UnknownKeyException{
		OelEngine oel = OelEngine.getInstance();
		TestObject obj = new TestObject();
		Date date = new Date();
		int number = RandomUtils.randInt();
		String string = "测试用例";
		
		obj.dateField =date;
		obj.setDateProperty(date);
		
		obj.intField =number;
		obj.setIntProperty(number);
		
		obj.stringField = string;
		obj.setStringProperty(string);
		
		obj.dateMethod(date);
		
		assertEquals(date, oel.el(obj, "dateProperty"));
		assertEquals(date.getTime(), oel.el(obj, "dateProperty.time"));
		assertEquals(date, oel.el(obj, "dateField"));
		assertEquals(date.getTime(), oel.el(obj, "dateField.time"));
		assertEquals(date, oel.el(obj, "dateMethod()"));
		assertEquals(date.getTime(), oel.el(obj, "dateMethod().time"));
		
		assertEquals(number, oel.el(obj, "intField"));
		assertEquals(number, oel.el(obj, "intProperty"));
		
		assertEquals(string, oel.el(obj, "stringField"));
		assertEquals(string, oel.el(obj, "stringProperty"));
		
		
		
	}
}

 

package com.isnowfox.oel;

import java.util.Date;

public class TestObject {
	public int intField;
	public String stringField;
	public Date dateField;
	private int intProperty;
	private String StringProperty;
	private Date dateProperty;
	private Date dateMethod;
	public int getIntProperty() {
		return intProperty;
	}
	public void setIntProperty(int intProperty) {
		this.intProperty = intProperty;
	}
	public String getStringProperty() {
		return StringProperty;
	}
	public void setStringProperty(String stringProperty) {
		StringProperty = stringProperty;
	}
	public Date getDateProperty() {
		return dateProperty;
	}
	public void setDateProperty(Date dateProperty) {
		this.dateProperty = dateProperty;
	}
	public Date dateMethod(){
		return dateMethod;
	}
	public void dateMethod(Date dateMethod){
		this.dateMethod = dateMethod;
	}
	@Override
	public String toString() {
		return "TestObject [intField=" + intField + ", StringField="
				+ stringField + ", dataField=" + dateField + ", intProperty="
				+ intProperty + ", StringProperty=" + StringProperty
				+ ", dataProperty=" + dateProperty + "]";
	}
}

 

 

下面是实现

 

package com.isnowfox.oel;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.NotFoundException;

import com.isnowfox.oel.KeyInfo.Type;

/**
 * oel引擎
 * @author zuoge85
 *
 */
public class OelEngine {
	private static final boolean DEBUG = true;
	
	private static final String PACKAGE_NAME = OelEngine.class.getPackage().getName();
	private static Map<Class<?>, Class<?>> primitivesWrapMap = new HashMap<Class<?>, Class<?>>(16);
	static{
		primitivesWrapMap.put(boolean.class, Boolean.class);
		primitivesWrapMap.put(byte.class, Byte.class);
		primitivesWrapMap.put(char.class, Character.class);
		primitivesWrapMap.put(double.class, Double.class);
		primitivesWrapMap.put(float.class, Float.class);
		primitivesWrapMap.put(int.class, Integer.class);
		primitivesWrapMap.put(long.class, Long.class);
		primitivesWrapMap.put(short.class, Short.class);
		primitivesWrapMap.put( void.class, Void.class);
	}
	
	public static final OelEngine getInstance(){
		return Inner.instance;
	}
	
	private Map<String,OelProxy> cacheMap = new HashMap<>();
	
	private AtomicInteger itemSeed = new AtomicInteger();
	public Object el(Object obj,String el) throws UnknownKeyException{
		if(obj == null){
			throw new NullPointerException("null");
		}
		try {
			Class<?> cls = obj.getClass();
			String cacheKey = cls.getName() + el;
			OelProxy p =cacheMap.get(cacheKey);
			if(p==null){
				ClassPool pool = ClassPool.getDefault();
				CtClass cc = pool.makeClass(PACKAGE_NAME + ".MyOelProxy" + itemSeed.incrementAndGet()); 
				cc.addInterface(pool.get(PACKAGE_NAME +".OelProxy"));
				CtMethod method = CtNewMethod.make("public Object el(Object obj);", cc);
				method.setBody(makeMethod(cls, obj, el));
				cc.addMethod(method);
				if(DEBUG){
					cc.debugWriteFile("debug");
				}
				p =  (OelProxy) cc.toClass().newInstance();
				cacheMap.put(cacheKey, p);
			}
			return p.el(obj);
		} catch (NotFoundException|CannotCompileException|InstantiationException|IllegalAccessException e) {
			throw new RuntimeException(e);
		} 
	}
	
	private String makeMethod(Class<?> cls, Object obj, String el) throws UnknownKeyException{
		int varSeed = 0;
		StringBuilder sb = new StringBuilder("{\n");
		String[] keys = el.split("\\.");
		sb.append(cls.getCanonicalName() + " var_" + (++varSeed) + " = (" +cls.getCanonicalName() + ")$1;\n" );
		for(String key:keys){
			KeyInfo info =analyse(cls,key);
			int nextVar = varSeed++ ;
			switch (info.getType()) {
			case FIELD:
				sb.append(info.getCls().getCanonicalName() +" var_" + varSeed + " = var_"+ nextVar +"." + key + ";\n");
				break;
			case PROPERTY:
				sb.append(info.getCls().getCanonicalName() +" var_" + varSeed + " = var_"+ nextVar +"." + info.getMethodName() + "();\n");
				break;
			case METHOD:
				sb.append(info.getCls().getCanonicalName() +" var_" + varSeed + " = var_"+ nextVar +"." + key + ";\n");
				break;
			default:
				break;
			}
			cls = info.getCls();
		}
		if(cls.isPrimitive()){
			cls = wrap(cls);
			sb.append("return "+cls.getCanonicalName()+".valueOf(var_" + varSeed + ");}");
		}else{
			sb.append("return var_" + varSeed + ";}");
		}
		return sb.toString();
	}
	
	private KeyInfo analyse(Class<?> cls,String key) throws UnknownKeyException{
		try {
			if(key.endsWith("()")){
				try {
					Method method = cls.getMethod(key.substring(0, key.length()-2));
					return new KeyInfo(Type.METHOD, method.getReturnType());
				} catch (Exception e2) {
					
				}
			}
			PropertyDescriptor prop = new PropertyDescriptor(key, cls);
			return new KeyInfo(Type.PROPERTY, prop.getPropertyType(), prop.getReadMethod().getName());
		} catch (IntrospectionException e) {
			//属性没找到那么可能是field
			Field field;
			try {
				field = cls.getField(key);
				return new KeyInfo(Type.FIELD, field.getType());
			} catch (Exception e1) {
				
			}
		}
		throw new UnknownKeyException("未知的 key:"+key +",cls:"+ cls);
	}
	private Class<?> wrap(Class<?> cls){
		return primitivesWrapMap.get(cls);
	}
	public Object part(Object Obj,String name){
		return null;
	}
	
	private static class Inner{
		private static final OelEngine instance = new OelEngine();
	}
}

 

 

 

分享到:
评论

相关推荐

    el表达式用法部分解说

    ### EL表达式详解 EL(Expression Language)表达式在Java Web开发中扮演着重要的角色,尤其是在JSP(Java Server Pages)技术中。本文将详细解释EL表达式的使用方法及其应用场景,帮助开发者更好地理解和掌握这一...

    EL表达式包括字符串处理,时间日期的格式化,数字处理

    ### EL表达式详解 #### 一、EL表达式的概述与基本使用 EL(Expression Language),即表达式语言,是JavaServer Pages (JSP) 2.0标准的一部分,用于简化JSP页面中对数据访问的操作。它允许开发者通过简单的语法在...

    jsp页面中EL表达式被当成字符串处理不显示值问题的解决方法

    此外,在每个JSP文件中也可以通过page directive指令来控制是否忽略EL表达式的解析,通过isELIgnored属性来实现。该属性可以设置为"true"或"false",来决定是否忽略EL表达式。例如,通过以下指令可以关闭对EL表达式...

    JSTL自定义EL表达式

    本资源主要讲解了如何在JSTL中定义和使用自定义的EL表达式,这对于提高JSP页面的可读性和可维护性至关重要。 首先,理解JSTL的基础概念。JSTL由几个核心标签库组成,如fmt、fn、sql、xml等,它们提供了处理日期和...

    简单使用EL表达式标签

    **EL表达式简介** EL(Expression Language,表达式语言...通过简单使用EL表达式标签,我们可以轻松地在JSP页面中展示和处理数据,实现页面与后台的高效交互。理解和熟练运用EL表达式,对于提升Web开发技能至关重要。

    JSTL,EL表达式语法简介

    例如,使用EL表达式和`&lt;c:if&gt;`标签可以实现简单的条件判断: ```jsp ${user != null}"&gt; 用户已登录:${user.name} ``` 综上所述,JSTL和EL是JSP开发中非常重要的工具,它们提供了丰富的功能,使开发者能够更加...

    el表达式介绍 el表达式使用帮助文档

    EL表达式的主要目标是提高JSP页面的可读性和可维护性,减少脚本代码的数量。 ### EL表达式的基本语法 EL表达式通常以`$`符号开头,后跟大括号`{}`,如`${expression}`。表达式可以是简单的属性引用,也可以包含...

    EL表达式的使用方法

    EL表达式常常与JSTL(JavaServer Pages Standard Tag Library)一起使用,以实现更强大的功能。 ##### 1. JSTL简介 JSTL是一组标准标签库,用于简化JSP页面的开发工作,其中包括了条件判断、循环控制等功能。 ####...

    关于EL表达式语言的简单总结

    EL表达式的语法结构非常简单,主要形式为`{expression}`。这里`expression`代表具体的表达式,它可以是变量名、方法调用等。 ##### 2. 运算符 EL提供了两种运算符用于访问对象属性: - **`.`**:点运算符,用于...

    EL表达式语言 非常详细

    ### EL表达式语言详解 #### 9.1 概述 在JSP页面开发中,为了提高代码的可读性和可维护性,开发者们逐渐转向使用标签库来替代传统的Java片段语言来实现页面的显示逻辑。然而,自定义标签虽然灵活,但也容易导致重复...

    EL表达式所需要的jar包

    JSTL也包含了EL表达式的实现,使得在JSP页面上可以直接使用EL语法进行数据操作。 2. **el-api.jar** 和 **el-impl.jar**:这两个jar包分别包含了EL表达式的API接口和其实现。`el-api.jar`定义了EL表达式的接口和类...

    EL表达式详解教程.zip

    此外,EL表达式还可以与JSP动作标签(如`&lt;jsp:useBean&gt;`、`&lt;jsp:setProperty&gt;`等)配合,实现更复杂的业务逻辑。 EL表达式与JavaBeans的结合使用是其核心优势之一。JavaBeans是一种遵循特定规范的Java类,通常用于...

    Servlet+MySql+Web(HTML+CSS+JSP技术+EL表达式)通过IDEA来实现数据库的增删改查(crud)

    在IT行业中,构建基于Web的应用程序是常见的任务,而Servlet、MySQL、HTML、CSS、JSP和EL表达式是实现这一目标的关键技术。本项目利用IntelliJ IDEA这个强大的集成开发环境(IDE)来整合这些技术,实现了数据库的CRUD...

    EL表达式(全部)

    EL表达式EL表达式 JSTL JSP标准标签库 在EL表达式中只能进行逻辑运算 并不能进行逻辑控制 也就是说 使用了EL表达式 还是无法真正实现JSP页面完全无脚本 这时我们可以借助JSTL来

    EL表达式学习资料

    ### EL表达式学习资料 #### 一、EL简介 EL(Expression Language)是Java Server Pages (JSP) 技术中的一种简化的脚本语言,主要用于简化页面开发中对对象和属性的访问过程。EL 表达式允许开发者在 JSP 页面中直接...

    EL表达式所用的jar包.rar

    首先,`el-api.jar`包含了EL表达式的API定义,定义了EL表达式的语法和行为。这个库提供了一种标准,使得开发者可以使用统一的方式来处理表达式,而无需关心具体的实现细节。例如,你可以使用`${}`来引用JavaBeans的...

    使用EL表达式时候用到的jar包

    在JSP页面中,EL表达式通常以`${}`包裹,可以用来访问页面作用域、请求作用域、会话作用域或应用作用域的属性,以及执行简单的算术运算、条件判断和方法调用。例如: ```jsp &lt;p&gt;Welcome, ${user.name}! ${user....

    练习1:使用EL表达式实现一项问卷调查.zip

    在本实践项目“练习1:使用EL表达式实现一项问卷调查”中,我们将深入探讨Java Web开发中的一个重要组件——EL(Expression Language),它是JavaServer Pages(JSP)标准的一部分,用于简化网页和JavaBean之间的...

    EL表达式详解

    EL表达式极大地简化了JSP页面的开发过程,通过简单的语法和丰富的隐含对象,使得开发者可以更加专注于业务逻辑的实现,而不是页面的布局和样式。了解并熟练掌握EL表达式的使用方法对于提升Web开发效率具有重要意义。

    Fel Javael表达式引擎

    对于需要使用到Fel的特定功能,比如自定义上下文环境,需要按照Fel引擎提供的API进行编程实现。 总体而言,Fel表达式引擎以其轻量级、高效和易用性特点,在Java社区中占据一席之地。尤其对于需要处理复杂逻辑和性能...

Global site tag (gtag.js) - Google Analytics