反射和注解的原理这里就不描述了。
这里就说明一下要实现的功能和用反射和注解如何实现的。
我们目前项目的整体思路是客户端传人定义的model定义(如xxx.class)和数据源data(目前是通过sql查出来的ResultSet)、以及规则文件,然后通过drools服务返回执行的结果。入下图:
这样就需要动态加载model定义,并实例化model,然后Data解析后把数据赋值到model定义的属性上。然后把model实例化的对象放入到drools的 StatefulKnowledgeSession里面去执行规则。
具体解决方法是在model类里面定义set方法上增加列名的注解,然后通过反射实例化对象后执行有注解的方法给对象属性赋值。
代码如下:
注解类定义:
package com.test.AnnotationTest;
import java.lang.annotation.*;
/**
* Created by xuzhongxing on 2016/4/12.
*/
@Target (ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Column {
String name() default "fieldName";
}
model类定义如下:
package com.test.AnnotationTest;
import java.util.Date;
public class Student {
private String no;
private String name;
private Date createtime;
private Integer id;
public Date getCreatetime() {
return createtime;
}
@Column (name = "createTime")
public void setCreatetime(Date createtime) {
this.createtime = createtime;
}
public Integer getId() {
return id;
}
@Column (name = "id")
public void setId(Integer id) {
this.id = id;
}
public String getNo() {
return no;
}
@Column(name = "NO")
public void setNo(String no) {
this.no = no == null ? null : no.trim();
}
public String getName() {
return name;
}
@Column(name = "name")
public void setName(String name) {
this.name = name == null ? null : name.trim();
}
}
具体实现方法:
/**
* 使用注解通过反射实例化model并赋值
*/
public static void testAnnotation() {
Connection conn = null;
String sql;
String url = "jdbc:mysql://192.168.4.88:3306/test?user=testuser&password=testuser&useUnicode=true&characterEncoding=UTF8";
try {
Class.forName("com.mysql.jdbc.Driver");// 动态加载mysql驱动
conn = DriverManager.getConnection(url);
Statement stmt = conn.createStatement();
sql = "select * from student";
ResultSet rs = stmt.executeQuery(sql);// executeQuery会返回结果的集合,否则返回空值
while (rs.next()) {
String projectKnowledgePath = "\\RuleEngineBase\\trunk\\src\\resource\\";
URL url1 = new URL("file:" + projectKnowledgePath + "ProjectOrder\\Models\\Order.jar");
URLClassLoader myClassLoader1 = new URLClassLoader(new URL[]{url1}, Thread.currentThread()
.getContextClassLoader());
Class<?> clz = myClassLoader1.loadClass("com.test.AnnotationTest.Student");
Object objectInstance = clz.newInstance();
//使用注解
Method[] yy = clz.getMethods();
for (Method method : yy) {
//拿到方法上的注解
Column column = method.getAnnotation(Column.class);
if (column != null) {
String columnName = column.name();
Class<?>[] clazz = method.getParameterTypes();
String type = clazz[0].getName();
if (type.equals("java.lang.String")) {
method.invoke(objectInstance, (String) rs.getString(columnName));
} else if (type.equals("java.util.Date")) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
java.util.Date date = sdf.parse(rs.getString(columnName));
method.invoke(objectInstance, date);
} else if (type.equals("java.lang.Integer")) {
method.invoke(objectInstance, new Integer((String) rs.getString(columnName)));
} else {
//........
}
System.out.println("输出Method的name:" + method.getName());
}
}
System.out.println("object对象数据如下" + JSONObject.fromObject(objectInstance).toString());
}
} catch (SQLException e) {
System.out.println("MySQL操作错误");
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
这是一个测试的例子。
后来发现org.apache.commons.beanutils.BeanUtils.getProperty这个可以直接对反射对象的属性赋值。
欢迎交流谢谢。