`
zuoge85
  • 浏览: 77969 次
  • 性别: 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表达式的各种使用方法,以及EL表达式配合JSTL的使用

    EL表达式(全部)

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

    EL表达式 (详解)

    EL表达式 (详解) EL表达式 1、EL简介 1)语法结构 ${expression} 2)[]与.运算符 EL 提供.和[]两种运算符来存取数据。 当要存取的属性名称中包含一些特殊字符,如.或?等并非字母或数字的符号,就一定要使用 ...

    jsp+servlet+EL表达式分页

    jsp+servlet+el 分页 实现的简单 分页

    JSTL和EL表达式源码.rar

    jstl+EL ,一些简单的代码实现,主要介绍了EL的语法,以及JSTL的几个常用标签,需要的可以下载查看。

    JSTL标记标签+EL表达式 简单操作

    本小小系统采用JSP实现了JSTL标记标签结合EL表达式一起使用. 适合JSP初学者适用 适合教学讨论使用 -- 评论返还积分

    JavaEE+JDBC+Servlet+EL表达式的员工信息管理系统源码+数据库+项目说明(高分课设).zip

    JavaEE+JDBC+Servlet+EL表达式的员工信息管理系统源码+数据库+项目说明(高分课设).zip # :heart: JavaEE+JDBC+Servlet+EL表达式的员工信息管理系统 ## 介绍 简易的员工管理系统,包括信息的增删改查,新增员工...

    【JavaScript源代码】jquery+Ajax实现简单分页条效果.docx

    用EL表达式和JSTL标签实现的缺点就是无法实现异步效果,整个页面是重新刷新了一遍的。 二、如果是普通的html页面,当然是无法使用EL表达式和JSTL标签的,这时只能通过异步Ajax的方式去实现。当然了,JSP页面两种...

    Struts2用到的核心jar包

    用来支持ognl表达式的,类似于EL表达式,功能比EL表达式强大的多。 freemarker-2.3.15.jar freemarker是比jsp更简单好用,功能更加强大的表现层技术,用来替代jsp的。 在Struts2中提倡使用 freemarker模板,但实际...

    struts实现二级联动下拉框

    由于时间有限,直接将个人实现的JSP上传至...对于JSP里的html:select及其html:option几乎只用直接拷贝,没什么需要修改的(除了修改页面的EL表达式);如果有不懂的,可以直接联系我;电子邮件:zyyceo@gmail.com; QQ:114948587

    jsp+servlet简易购物车

    4.进行验证码收发操作,系统进入后展示商品列表,利用c标签将db入库的数据进行动态渲染,el表达式进行数据取值展示,添加购物车利用ajax请求 5.进行添加购物车、移除购物车的技术实现,根据所添加的购

    JSP+SERVLET+MYSQL实现的增删改查javaweb新闻管理系统小例子,主页有具体介绍,界面图片

    能学到什么:①练习JSP,EL表达式,SERVLET关键点技术项目;②分层开发的管理系统,都是如何设计和实现的,简单的展现,通俗易懂。 阅读建议:此资源以开发简化版jsp学习其原理和内核,不仅是代码编写实现也更注重...

    jQuery+CSS3文字跑马灯特效的简单实现

    jQuery+CSS3文字跑马灯特效是一款将跑马灯背景制作为3D立方体效果,文字在上面移动时,就像是文字投影到墙壁上,在转角出会改变运动方向。 效果图如下: ... &lt;!...meta name="viewport" content="width=device-width,...

    JSP实现的留言管理

    MVC+DAO设计模式实现的的留言管理 可以实现简单的留言添加修改查看和删除 包含了登录验证,EL表达式+javabean

    ognl-2.6.11.jar 的使用源码。EL语言的使用实例

    Graph Navigation Language的缩写,它是一种功能强大的表达式语言(Expression Language,简称为EL),通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型...

    Jsp+Servlet+Cookie实现记住密码,自动登录,防止表单提交,记录登录次数

    Jsp+Servlet+Cookie实现记住密码,自动登录,防止表单提交,记录登录次数的新手例子。简单明了,大量注释,El表达式等。

    一个简单的通用分页工具条

    使用集合类、EL表达式以及标准标签库,实现在客户端对所查询的结果集分页的效果,简单实用!

    j2EE的简单web开发

    对于j2EE的简单web开发,其中有各种j2EE web开发过程中会使用到的技巧,如el表达式,jstl自定义标签,过滤器的使用等 通过这些来实现登录 注册 修改 删除 分页 等功能

    AJAX分页效果简单实现

    最近写一个给用户组添加角色的功能,要求一边是未添加的角色,一边是已添加的角色,还有搜索功能, 点击添加后,ajax保存操作. 考虑功能为待查询功能分页 , 下方分页条, 一共有 2*2 ,4个ajax… JS代码如下: ...

    传智书城项目jsp servlet c3p0 完整版.rar

    压缩包内包含《Java Web程序设计任务教程》教材第13-15章的教材资源,即传智书城项目,包括数据库文件。 说明文件: 【代码相关】 ...网上书城开发记录、注册功能邮箱调试、(基本语法)EL表达式与JSTL

Global site tag (gtag.js) - Google Analytics