文档章节

修改整合的Jfinal的Model自动绑定表插件 AutoTableBindPlugin

绝望的八皮
 绝望的八皮
发布于 2012/07/20 00:28
字数 988
阅读 3950
收藏 18

之前发过一个

JFinal 自动探测Model 注册插件 AutoScanPlugin

http://my.oschina.net/b1412/blog/67764

然后参考了 @Flio 对我的代码做出的扩展

jfinal的Model自动绑定表插件

http://www.oschina.net/code/snippet_591384_12022

现在整合下代码采用@Flio的插件命名,并且重构了一下搜索类的代码。

类探测api如下方便以后其类探测的使用.

List<Class> classList = ClassSearcher.findClasses(Model.class);

 插件注册代码,由于AutoTableBindPlugin继承自ActiveRecordPlugin,所以不需要单独注册它了.

主要数据库连接池插件要在AutoTableBindPlugin之前注册.

public void configPlugin(Plugins me) {
		DruidPlugin druidPlugin = new DruidPlugin.DruidBuilder(
				getProperty("url"), getProperty("username"),
				getProperty("password")).build();
		AutoTableBindPlugin autoTableBindPlugin = new AutoTableBindPlugin(
				druidPlugin, TableNameStyle.LOWER);
		autoTableBindPlugin.setShowSql(true);
		SqlReporter.setLogger(true);
		SqlInXmlPlugin sqlInXmlPlugin = new SqlInXmlPlugin();
		QuartzPlugin quartzPlugin = new QuartzPlugin();
		me.add(druidPlugin).add(sqlInXmlPlugin).add(autoTableBindPlugin).add(quartzPlugin);
            
	}

目前之内探测/classes下的类,如果是/lib下jar包中的类还不能探测。

之前做过运行动态修改字节码的工具,是吧lib下的jar解压出来然后修改了打包回去。如果需要探测jar中类是否为Model子类是否必须坐jar包解压的工作?大家有什么好的方案么?这个问题弄清楚了再加上扫描jar包中Model的工作。

目前如果是有项目吧class文件打成jar包部署的朋友暂时无法使用自动探测绑定的功能...

 

 

package com.jfinal.plugin.tablebind;

import java.util.List;

import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.activerecord.IDataSourceProvider;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.util.StringKit;

public class AutoTableBindPlugin extends ActiveRecordPlugin {
	private TableNameStyle tableNameStyle;
	private Logger logger = LoggerFactory.getLogger(getClass());

	public AutoTableBindPlugin(DataSource dataSource) {
		super(dataSource);
	}

	public AutoTableBindPlugin(IDataSourceProvider dataSourceProvider, TableNameStyle tableNameStyle) {
		super(dataSourceProvider);
		this.tableNameStyle = tableNameStyle;
	}

	@Override
	public boolean start() {
		try {
			List<Class> modelClasses = ClassSearcher.findClasses(Model.class);
			logger.debug("modelClasses.size  {}",modelClasses.size());
			TableBind tb = null;
			for (Class modelClass : modelClasses) {
				tb = (TableBind) modelClass.getAnnotation(TableBind.class);
				if (tb == null) {
					this.addMapping(tableName(modelClass), modelClass);
					logger.debug("auto bindTable: addMapping({}, {})", tableName(modelClass), modelClass.getName());
				} else {
					if (StringKit.notBlank(tb.pkName())) {
						this.addMapping(tb.tableName(), tb.pkName(), modelClass);
						logger.debug("auto bindTable: addMapping({}, {},{})", new Object[]{tb.tableName(),tb.pkName(), modelClass.getName()});
					} else {
						this.addMapping(tb.tableName(), modelClass);
						logger.debug("auto bindTable: addMapping({}, {})", tb.tableName(), modelClass.getName());
					}
				}
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return super.start();
	}

	@Override
	public boolean stop() {
		return super.stop();
	}

	private String tableName(Class<?> clazz) {
		String tableName = clazz.getSimpleName();
		if (tableNameStyle == TableNameStyle.UP) {
			tableName = tableName.toUpperCase();
		} else if (tableNameStyle == TableNameStyle.LOWER) {
			tableName = tableName.toLowerCase();
		} else {
			tableName = StringKit.firstCharToLowerCase(tableName);
		}
		return tableName;
	}
}

package com.jfinal.plugin.tablebind;

import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public  @ interface  TableBind {
	String tableName();
	String pkName() default "";
}

package com.jfinal.plugin.tablebind;



import java.io.File;

import java.net.URL;

import java.util.ArrayList;

import java.util.List;



public class ClassSearcher {

	

	private static List<File> classFiles;



	/**

	 * 递归查找文件

	 * 

	 * @param baseDirName

	 *            查找的文件夹路径

	 * @param targetFileName

	 *            需要查找的文件名

	 */

	private  static List<File> findFiles(String baseDirName, String targetFileName) {


		/**

		 * 算法简述: 从某个给定的需查找的文件夹出发,搜索该文件夹的所有子文件夹及文件,

		 * 若为文件,则进行匹配,匹配成功则加入结果集,若为子文件夹,则进队列。 队列不空,重复上述操作,队列为空,程序结束,返回结果。

		 */

		classFiles = new ArrayList<File>();

		String tempName = null;

		// 判断目录是否存在

		File baseDir = new File(baseDirName);

		if (!baseDir.exists() || !baseDir.isDirectory()) {

			System.out.println("文件查找失败:" + baseDirName + "不是一个目录!");

		} else {

			String[] filelist = baseDir.list();

			for (int i = 0; i < filelist.length; i++) {

				File readfile = new File(baseDirName + File.separator

						+ filelist[i]);

				if (!readfile.isDirectory()) {

					tempName = readfile.getName();

					if (ClassSearcher.wildcardMatch(targetFileName, tempName)) {

						classFiles.add(readfile.getAbsoluteFile());

					}

				} else if (readfile.isDirectory()) {

					classFiles.addAll(findFiles(baseDirName + File.separator

							+ filelist[i], targetFileName));

				}

			}

		}

		return classFiles;

	}



	public static List<Class> findClasses(Class clazz) {

		List<Class> classList = new ArrayList<>();

		URL classPathUrl = ClassSearcher.class

				.getResource("/");

		List<File> classFileList = findFiles(classPathUrl.getFile(), "*.class");

		

		String lib = new File(classPathUrl.getFile()).getParent() + "/lib/";



		for (File classFile : classFileList) {

			String className = className(classFile, "/classes");

			try {

				Class<?> classInFile = Class.forName(className);

				if (classInFile.getSuperclass() == clazz) {

					classList.add(classInFile);

				}

			} catch (ClassNotFoundException e) {

				e.printStackTrace();

			}

		}

		return classList;

	}



	private static String className(File classFile, String pre) {

		String objStr = classFile.toString().replaceAll("\\\\", "/");

		String className;

		className = objStr.substring(objStr.indexOf(pre) + pre.length(),

				objStr.indexOf(".class"));

		if (className.startsWith("/")) {

			className = className.substring(className.indexOf("/") + 1);

		}

		return className.replaceAll("/", ".");

	}



	/**

	 * 通配符匹配

	 * 

	 * @param pattern

	 *            通配符模式

	 * @param str

	 *            待匹配的字符串

	 * @return  匹配成功则返回true,否则返回false

	 */

	private static boolean wildcardMatch(String pattern, String str) {

		int patternLength = pattern.length();

		int strLength = str.length();

		int strIndex = 0;

		char ch;

		for (int patternIndex = 0; patternIndex < patternLength; patternIndex++) {

			ch = pattern.charAt(patternIndex);

			if (ch == '*') {

				// 通配符星号*表示可以匹配任意多个字符

				while (strIndex < strLength) {

					if (wildcardMatch(pattern.substring(patternIndex + 1),

							str.substring(strIndex))) {

						return true;

					}

					strIndex++;

				}

			} else if (ch == '?') {

				// 通配符问号?表示匹配任意一个字符

				strIndex++;

				if (strIndex > strLength) {

					// 表示str中已经没有字符匹配?了。

					return false;

				}

			} else {

				if ((strIndex >= strLength) || (ch != str.charAt(strIndex))) {

					return false;

				}

				strIndex++;

			}

		}

		return (strIndex == strLength);

	}

}

 

package com.jfinal.plugin.tablebind;

public enum TableNameStyle {
	UP, LOWER, UP_UNDERLINE, LOWER_UNDERLINE
}

© 著作权归作者所有

共有 人打赏支持
绝望的八皮

绝望的八皮

粉丝 392
博文 22
码字总数 10505
作品 2
其它
CTO(技术副总裁)
私信 提问
加载中

评论(9)

绝望的八皮
绝望的八皮
public class TestTableBind {
  static class Inner extends Model<Inner>{
    
  }
  @BeforeClass
  public static void init() {
    DruidPlugin c3p0 = new DruidPlugin(
        "jdbc:mysql://127.0.0.1/jfinal_demo", "root", "root");
    AutoTableBindPlugin atbp = new AutoTableBindPlugin(c3p0,TableNameStyle.LOWER);
    c3p0.start();
    atbp.start();
  }

  @Test
  public void test01() throws InterruptedException {
  }

}



2012-11-01 17:07:12
[DEBUG]-[Thread: main]-[jfinal.ext.plugin.tablebind.AutoTableBindPlugin.start()]: addMapping(inner, test.jfinal.plugin.tablebind.TestTableBind$Inner)

2012-11-01 17:07:12
[DEBUG]-[Thread: main]-[jfinal.ext.plugin.tablebind.AutoTableBindPlugin.start()]: addMapping(testmodel, test.jfinal.plugin.tablebind.TestModel)
osrchina
osrchina

引用来自“绝望的八皮”的评论

引用来自“os4china”的评论

引用来自“龙影”的评论

引用来自“os4china”的评论

当有内部静态类的时候,类文件是Render$a.class,Render$v.class这种的怎么办?

你觉得数据库映射的类会使用静态类吗

不要你觉得..要是有呢?

Render$a.class,Render$v.class映射出来的依然是a,b
取的是simpleclassname

真的假的,你把你代码亮出来看看
绝望的八皮
绝望的八皮

引用来自“os4china”的评论

引用来自“龙影”的评论

引用来自“os4china”的评论

当有内部静态类的时候,类文件是Render$a.class,Render$v.class这种的怎么办?

你觉得数据库映射的类会使用静态类吗

不要你觉得..要是有呢?

Render$a.class,Render$v.class映射出来的依然是a,b
取的是simpleclassname
osrchina
osrchina

引用来自“龙影”的评论

引用来自“os4china”的评论

当有内部静态类的时候,类文件是Render$a.class,Render$v.class这种的怎么办?

你觉得数据库映射的类会使用静态类吗

不要你觉得..要是有呢?
绝望的八皮
绝望的八皮
github变更为 https://github.com/b1412/jfinal-ext
绝望的八皮
绝望的八皮

引用来自“龙影”的评论

真是对你无语啊 classSeacher里的查找文件的方法有错误 啊 居然在迭代方法里将classFiles = new ArrayList<File>(); 这样怎么取都是要看最后一个目录和文件的结果了。
方法是 private static List<File> findFiles(String baseDirName, String targetFileName)

新代码已经托管github,博客不再更新代码了。有Bug欢迎反馈,谢谢支持~
https://github.com/zhoulei-kid/jfinal-ext
龙影
龙影
真是对你无语啊 classSeacher里的查找文件的方法有错误 啊 居然在迭代方法里将classFiles = new ArrayList<File>(); 这样怎么取都是要看最后一个目录和文件的结果了。
方法是 private static List<File> findFiles(String baseDirName, String targetFileName)
龙影
龙影

引用来自“os4china”的评论

当有内部静态类的时候,类文件是Render$a.class,Render$v.class这种的怎么办?

你觉得数据库映射的类会使用静态类吗
osrchina
osrchina
当有内部静态类的时候,类文件是Render$a.class,Render$v.class这种的怎么办?
关于getModel的modelName

@JFinal 你好,想跟你请教个问题:老大,我用了jfinal-ext的自动绑定表插件AutoTableBindPlugin。在这个插件里可以自定义model名字和表的映射关系,比如我可以指定UserModel->user表。但是现...

ramnight
2014/07/09
352
1
JFinal Extensions 1.0 发布,JFinal 扩展

Jfinal-ext是对java极速web框架 jfinal 的一个扩充,主要利用jfinal的plugin机制集成各种第三方框架,像spring一样,简化开发者的学习应用成本,使用时请将jfinal.jar先引入工程。 Jfinal-e...

绝望的八皮
2012/10/14
1K
13
对AutoTableBindPlugin的一点改造使它支持多数据源

在使用jFinal的时候因为不想每个Model都一个个去写映射关系,因此使用了@绝望的八皮 的AutoTableBindPlugin来自动绑定Model与表之间的映射,但是在jFinal升级到1.6后AutoTableBindPlugin不支...

helloyangxp
2014/04/07
0
4
使用AutoTableBindPlugin后,启动非常慢

@绝望的八皮 你好,想跟你请教个问题: @绝望的八皮 你好,想跟你请教个问题: 运行Server.java中的main函数,启动信息如下: Starting JFinal 1.5 Starting scanner at interval of 5 seco...

zmb做人厚道
2016/06/15
709
0
JFinal Extensions 1.3 发布,JFinal 扩展

Jfinal-ext是对java极速web框架 jfinal 的一个扩充,主要利用jfinal微内核高扩展的特性扩展常用的实用功能和集成各种第三方框架,简化开发者的学习应用成本,为您节约更多时间,去陪恋人、家...

绝望的八皮
2013/01/04
1K
14

没有更多内容

加载失败,请刷新页面

加载更多

winscp中使用sudo的方法

用截图了解如何在 WinSCP 中使用 sudo。 首先你需要检查你尝试使用 WinSCP 连接的 sftp 服务器的二进制文件的位置。 你可以使用以下命令检查 SFTP 服务器二进制文件位置: [root@kerneltalk...

Linux就该这么学
21分钟前
1
0
四、MyBatis中查询执行流程

一、查询执行大致流程 在MyBatis中,查询执行的大致流程如下:

yangjianzhou
27分钟前
1
0
系统幂等设计

前言 幂等简单的定义: 系统中的多次操作,不管多少次,都应该产生一样的效果,或返回一样的效果。 比如实际的业务请求为创建一个活动,理论上需要根据业务形态开发幂等创建活动的接口,这样...

春哥大魔王的博客
52分钟前
2
0
DevSecOps 运维模式中的安全性

导读 本文想从技术的角度谈谈我对云计算数据中心 DevSecOps 运维模式中的安全性的理解,和过去几年我在云服务业务连续性管理方面的探索。 现在公有云服务商都不约而同地转向 DevSecOps 模式。...

问题终结者
54分钟前
0
0
java 基础脑图 转载来的

NotFound403
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部