文档章节

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

绝望的八皮
 绝望的八皮
发布于 2012/07/20 00:28
字数 988
阅读 8.4K
收藏 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 条评论,请先登录后再查看。
CDH5: 使用parcels配置lzo

一、Parcel 部署步骤 1 下载: 首先需要下载 Parcel。下载完成后,Parcel 将驻留在 Cloudera Manager 主机的本地目录中。 2 分配: Parcel 下载后,将分配到群集中的所有主机上并解压缩。 3 激...

cloud-coder
2014/07/01
6.8K
1
Nutch学习笔记4-Nutch 1.7 的 索引篇 ElasticSearch

上一篇讲解了爬取和分析的流程,很重要的收获就是: 解析过程中,会根据页面的ContentType获得一系列的注册解析器, 依次调用每个解析器,当其中一个解析成功后就返回,否则继续执行下一个解...

强子哥哥
2014/06/26
712
0
树莓派(Raspberry Pi):完美的家用服务器

自从树莓派发布后,所有在互联网上的网站为此激动人心的设备提供了很多有趣和具有挑战性的使用方法。虽然这些想法都很棒,但树莓派( RPi )最明显却又是最不吸引人的用处是:创建你的完美家用...

异次元
2013/11/09
7.1K
8
5分钟 maven3 快速入门指南

前提条件 你首先需要了解如何在电脑上安装软件。如果你不知道如何做到这一点,请询问你办公室,学校里的人,或花钱找人来解释这个给你。 不建议给Maven的服务邮箱来发邮件寻求支持。 安装Mav...

fanl1982
2014/01/23
1.2W
7
表单验证插件--Jquery表单验证插件

目前支持对以下格式的值进行验证: cnum-(纯数字), char-(纯字母), zwen-(中文), bysc-(字母开头), mail(邮箱), yzbm(邮政编码) 其中的‘’表示长度,比如“zwen1-5”表示中文1-5位的长度。同...

huanganiu
2013/01/23
4.4K
0

没有更多内容

加载失败,请刷新页面

加载更多

MySQL索引相关

一、索引分类 1、单列索引 1.1、主键索引(不能包含空值) 1.2、唯一索引(可以包含kong'zhi) 1.3、普通索引 2、多列索引 2.1、组合索引 3、全文索引 3.1、全文索引只针对大文本字段有效,比如:...

城里的月光
52分钟前
21
0
二级分销的理解

人人商城分销定义 例如: 分销商:A、B、C、D、E 群体1:A是B的上级分销商,B是C的上级分销商,C是D的上级分销商,则他们分销层级是:A是一级分销商,B是二级分销商,C是三级分销商 群体2:B...

红翼网
54分钟前
6
0
HBase/TiDB都在用的数据结构:LSM Tree,不得了解一下?

LSM Tree(Log-structured merge-tree)广泛应用在HBase,TiDB等诸多数据库和存储引擎上,我们先来看一下它的一些应用: 这么牛X的名单,你不想了解下LSM Tree吗?装X之前,我们先来了解一些...

Monica2333
55分钟前
26
0
Linux下如何高效切换目录?

Linux 下对于目录的切换,大家肯定会想到一个命令:cd 命令。这个是 Linux 下再基本不过的命令,如果这个命令都不知道的话,赶紧剖腹自尽去吧。 cd 命令确实很方便,但如果需要频繁在下面的目...

良许Linux
58分钟前
45
0
限流算法

1 计数算法 2 滑动窗口 (可以解决计数算法 临界线 QPS超过限流问题) 3 漏桶算法 4 令牌桶算法

yzzzzzzzz
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部