关于直接main方法运行生成代码可参考我的这篇文章:MP实战系列(六)之代码生成器讲解
在线配置主要参考jeesite和jeecg,gun等开源项目,但是与它们相比又有很多不同?
与jeesite相比,jeesite采用的自己重新改装的MyBatis和使用freemarker模板进行在线代码配置生成;与jeecg相比,jeecg的持久层叫minidao,该dao按照其官方文档所说,即具有Hibernate的全自动性,又兼有MyBatis的灵活性。与gun相比,gun的与我该在线配置代码生成器,比较相似,但总的来说,并不一样。
关于jeesite开源地址可以参考该网址:https://gitee.com/thinkgem/jeesite4
关于jeecg开源地址可以参考该网址:https://gitee.com/jeecg
我的关于EasyPoi导出Excel和EasyPoi以Excel格式批量录入数据,均采用jeecg的开源项目EasyPoi。
gun的话,我之所以与其不一样,是因为其代码生成器以zip包形式生成相关表代码。而我直接就是在页面上输入路径,直接在本地生成,当然了,生成以后还不能直接用,需要导入本地,但是总的来说,改动几乎为零,与之前我所提到过的MyBatis的逆向工程对比而言。
当然了,也不能完全否定MyBatis的逆向工程,毕竟只要项目结构和架构设计妥当还是很有效率的。
关于MyBatis的逆向工程可以参考我的这两篇博文:
动态web项目的逆向工程地址为:mybatis逆向工程之动态web项目
Maven工程的逆向工程地址为:mybatis逆向工程之maven工程
在线配置代码生成主要是为了提高研发人员的工作效率。之前我就强调过,DRY原则的重要性,并为此写了这篇文章编程之代码抽象三原则,大家可以借鉴和参考。
首先准备环境:JDK8+MAVEN3+Eclipse或IDEA+Spring+MyBatis Plus+SpringMVC
一、导入MAVEN依赖
以下依赖,是我公司中几个项目比较通用的依赖,大家可以直接导入进来即可。当然了,建议阿里云私服,因为在maven公共仓库下载如下依赖,对于网速具有一定的要求,记得之前研究某个开源技术是,光下载依赖就耽误我不少时间,而且有的时候因为本地仓库依赖冲突问题或者其他意外问题使对应的开源项目暂时无法运行起来。
<properties> <!-- 文件拷贝时的编码 --> project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> .reporting.outputEncodingproject.reporting.outputEncoding 编译时的编码 maven.compiler.encodingmaven.compiler.encoding> spring.version>4.3.13.RELEASEspring.versionjunit>4.12junit.versiondruid>1.1.0druid.versionfastjson>1.2.8fastjson.versionmybaitsplus>2.1.8mybaitsplus.versionMysqL>5.1.38MysqL.versionlog4j>1.2.17log4j.versionslf4j>1.7.19slf4j.versionaspectjweaver>1.8.8aspectjweaver.versionfileupload>1.3.1fileupload.versionjstl>1.2jstl.versioncommons-io>2.5commons-io.versioncommons-fileuploadcommons-fileupload.versionruedigermoeller-fst>2.56ruedigermoeller-fst.versionjson>20170516json.versiondozer>5.5.1dozer.version> <!-- --> runtime>7.0.0.Finalruntime.version> > dependencies> redis --> dependency> groupId>redis.clientsartifactId>jedisversion>2.1.0 spring-data-redis > >org.springframework.data> >spring-data-redis> >1.0.2.RELEASE mybatis-ehcache > >org.mybatis.caches>mybatis-ehcache>1.0.3 drools规则引擎 > >org.kie>kie-api>${runtime.version}>org.drools>drools-core>drools-decisiontables>org.jbpm>jbpm-test JUnit >junit>${junit.version}scope>test> Spring >org.springframework>spring-core>${spring.version}type>jar>compile>spring-context>spring-context-support>spring-tx>spring-test> >spring-aop>spring-beans>spring-jdbc> Spring MVC >spring-web>spring-webmvc AOP >org.aspectj>aspectjweaver>${aspectjweaver.version} FileUpload >commons-fileupload>${fileupload.version}>javax.servlet>jstl>${jstl.version} Mybatis-Plus >com.baomidou>mybatis-plus>${mybaitsplus.version} MysqL >MysqL>mysql-connector-java>${MysqL.version} Druid >com.alibaba>druid>${druid.version} FastJson >fastjson>${fastjson.version} Log >log4j>${log4j.version}>org.slf4j>slf4j-api>${slf4j.version}>slf4j-log4j12> >org.apache.commons>commons-lang3>3.3.2>commons-io>${commons-io.version}>de.ruedigermoeller>fst>${ruedigermoeller-fst.version}> >commons-codec>1.10>commons-beanutils>1.9.3> Json in java >org.json>json Email >commons-email>1.4>javax.activation>activation>1.1.1 条形码、二维码生成 >com.google.zxing>core>3.3.0>javase User Agent >eu.bitwalker>UserAgentUtils>1.20 Apache HTTP >org.apache.httpcomponents>httpclient>4.5.3 Jsoup HTTP >org.jsoup>jsoup>1.9.1 图片Meta获取 >com.drewnoakes>Metadata-extractor>2.9.1 缩略图工具 >net.coobird>thumbnailator>0.4.8 图片验证码生成 >com.bladejava>blade-patchca>1.0.5 jackson --> >com.fasterxml.jackson.core>jackson-core>2.9.4>jackson-databind>2.9.5 https://mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/jackson-dataformat-xml >com.fasterxml.jackson.dataformat>jackson-dataformat-xml Java xml >dom4j>1.6.1 XPath xml >jaxen>1.1.6 Snake YAML >org.yaml>snakeyaml>1.17> Bean To Bean copy >net.sf.dozer>dozer>${dozer.version}> pinyin4j >com.belerweb>pinyin4j>2.5.0 Apache Tools Ant Tar Zip >org.apache.ant>ant>1.9.7 File MimeType ContentType >net.sf.jmimemagic>jmimemagic>0.1.3exclusionsexclusion> >xerces>xercesImpl>org.codehaus.jackson>jackson-xc>jackson-jaxrs> 腾讯云 --> >com.qcloud>cos_api>5.2.4 https://mvnrepository.com/artifact/commons-codec/commons-codec >1.11> https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp >com.squareup.okhttp3>okhttp>3.9.1 https://mvnrepository.com/artifact/com.squareup.okio/okio >com.squareup.okio>okio>1.13.0> 注册加密常用工具 >org.mindrot>jbcrypt>0.4 easypoi导入导出excel --> >cn.afterturn>easypoi-base>3.1.0> >easypoi-web>easypoi-annotation> hutool --> >cn.hutool>hutool-all>4.1.0> swagger api文档管理 >com.mangofactory>swagger-springmvc>1.0.2>swagger-models>com.wordnik>swagger-annotations>1.3.11>com.google.guava>guava>15.0 集成springfox > >io.springfox>springfox-swagger2>2.7.0> >springfox-swagger-ui>net.sf.ehcache>ehcache-core>2.6.6> jsp >javax.servlet.jsp> >jsp-api>2.1 servlet >javax.servlet-api shiro >org.apache.shiro>shiro-core>1.4.0>shiro-web>shiro-spring>shiro-ehcache> >shiro-quartz> 个推 推送 >com.gexin.platform>gexin-rp-sdk-http>4.0.1.17> veLocity >org.apache.veLocity>veLocity>1.6.4>
二、导入正确的依赖后,即可编写对应的Controller方法
关于@ApiOperation注解主要是为了接口文档自动化,传统的编写word文档作为接口管理,耗时效率低,使用swagger或者swagger2在线可以直接测试,又方便安卓或者web研发人员管理和测试
MP实战系列(十)之SpringMVC集成SpringFox+Swagger2
这几篇文章我相信应该可以减少走弯路的可能性。
关于JSONObject,这里使用的是Hutool开源项目,该开源项目之前我也介绍过,集成Java研发常用工具类。
参考文档地址为:http://hutool.mydoc.io/
/** * 代码生成器接口 * @param author * dir * tableName * @return */ @PostMapping(value="/productCode",produces="application/json;charset=utf-8") @ApiOperation(value="代码生成器接口",httpMethod="POST",notes="代码生成器接口") public JSONObject productCode(String author,String dir,String tableName) { JSONObject json = new JSONObject(); try { if(!StrUtil.hasEmpty(author,dir,tableName)) { // 自定义需要填充的字段 List<TableFill> tableFillList = new ArrayList<>(); tableFillList.add(new TableFill("ASDD_SS",FieldFill.INSERT_UPDATE)); 代码生成器 AutoGenerator mpg = AutoGenerator().setGlobalConfig( 全局配置 GlobalConfig() .setoutputDir(dir)输出目录 .setFileOverride(true) 是否覆盖文件 .setActiveRecord( 开启 activeRecord 模式 .setEnableCache(false) XML 二级缓存 .setBaseResultMap( XML ResultMap .setBaseColumnList( XML columList .setAuthor(author) 自定义文件命名,注意 %s 会自动填充表实体属性! .setMapperName("%sDao") .setXmlName("%sDao") .setServiceName("%sService") .setServiceImplName("%sServiceImpl") .setControllerName("%sController") ).setDataSource( 数据源配置 DataSourceConfig() .setDbType(DbType.MysqL) 数据库类型 .setTypeConvert( MysqLTypeConvert() { 自定义数据库表字段类型转换【可选】 @Override DbColumnType processtypeConvert(String fieldType) { System.out.println("转换类型:" + fieldType); return super.processtypeConvert(fieldType); } }) .setDriverName("com.MysqL.jdbc.Driver") .setUsername("root") .setPassword("1234") .setUrl("jdbc:MysqL://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false") ).setStrategy( 策略配置 StrategyConfig() .setTablePrefix(new String[]{"rms","js"})/ 此处可以修改为您的表前缀 .setNaming(NamingStrategy.underline_to_camel) 表名生成策略 .setInclude(new String[] {tableName}) 需要生成的表 .setTableFillList(tableFillList) ).setPackageInfo( 包配置 PackageConfig() .setParent("com.blog") 自定义包路径 .setController("controller") 这里是控制器包名,默认 web ).setCfg( 注入自定义配置,可以在 VM 中使用 cfg.abc 设置的值 InjectionConfig() { @Override public void initMap() { Map<String,Object> map = new HashMap<>(); map.put("abc",this.getConfig().getGlobalConfig().getAuthor() + ""); this.setMap(map); } }.setFileOutConfigList(Collections.<FileOutConfig>singletonList(new FileOutConfig("/templates/mapper.xml.vm") { 自定义输出文件目录 @Override String outputFile(TableInfo tableInfo) { return dir+"//"+ tableInfo.getEntityName()+"Dao" + ".xml"; } })) ).setTemplate( 关闭默认 xml 生成,调整生成 至 根目录 new TemplateConfig().setXml(null) ); 执行生成 mpg.execute(); 打印注入设置,这里演示模板里面怎么获取注入内容【可无】 System.err.println(mpg.getCfg().getMap().get("abc")); json.put("returnMsg","代码生成成功"); json.put("returnCode","000000"); }else { json.put("returnMsg","参数异常"); } } catch (Exception e) { e.printstacktrace(); json.put("returnMsg","代码生成失败"); json.put("returnCode","222222"); } return json; }
三、界面
让大家看看效果:
有一点需要明确的是,该代码在线配置生成,只能针对本地window系统,如果已经部署到线上是无法生成的,也不会报错,因为window的文件系统和linux的文件系统存在差异。
当然了,这里的差异也不影响我们研发人员的正常使用。
该在线代码生成器的意义在于,每当用户提出一个新的需求时,我们总能快速生成相关的代码,然后专注于复杂的业务。简单的增删改查,谁都会。但是复杂的业务逻辑,就不仅仅谁都会了,虽然在网上看不少朋友说,重复的业务代码写久了也没意思。其实怎么说呢?我看过不少业务代码,发现一点,我和我的同学们都发现了这点,那就是许多业务代码基本就是复制粘贴的作品,甚至将代码上开发者名字都复制下来的,我想说,老兄你也太懒了吧。
当然了,复制粘贴是可以提高效率,但是好歹也得代码格式化下,让代码看起来工整,还有就是有些注释该加还是要加,当然注释越少越好,真正优秀的代码,是让人一看就明白是什么意思,所以说那些自以为是的人,自以为自己代码写的让人看不懂就自我感觉非常牛逼,其实那样只会让你越来越退步,直到失业。所以说,代码就好比讲通俗易懂的故事,至少要让人家在最短的时间看懂,而不是光看你这个代码我就花了一天,到最好我只有重构了这样的不是办法中的办法。
关于web界面上展示MysqL所有数据库信息,单个数据库所有表信息,数据表所有字段信息,大家可以参考我编写的如下DAO:
public interface DataBaseDao {
@Select("SHOW DATABASES")
public List<Map<String,String>> selectDataBases();
@Select("show columns from ${tableName}")
public List<Map<String,String>> showColumns(@Param("tableName")String tableName);
@Select("SHOW tables from ${databaseName}")
public List<Map<String,String>> showTables(@Param("databaseName")String databaseName);
}
xml文件:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.mapper.DataBaseDao"> </mapper>
这里我采用的是MyBatis的注解,当然这种注解的最不好缺点就是使Java代码和sql混合一起显得杂乱,当然少的时候看起来没什么,多的话,建议使用xml方式,这也是MyBatis官方比较推崇的方式。
补充说明:使用MyBatis的注解还是得存在对应的xml文件,尽管你的xml文件没有对应的sql。
DataBaseService代码和实现类如下:
Service代码:
interface DataBaseService { public List<Map<String,String>> selectDataBases(); aram("databaseName")String databaseName); aram("tableName")String tableName); }
Service实现类:
@Service class DataBaseServiceImpl implements DataBaseService { @Autowired private DataBaseDao dataBaseDao; @Override selectDataBases() { Todo Auto-generated method stub dataBaseDao.selectDataBases(); } @Override showTables(String databaseName) { dataBaseDao.showTables(databaseName); } @Override showColumns(String tableName) { dataBaseDao.showColumns(tableName); } }
对应的Controller如下:
* 获取所有数据库 * @GetMapping(value="/getAllDataBaseInfo",1)">) @ApiOperation(value="获取所有数据库",httpMethod="GET",notes="获取所有数据库" JSONObject getAllDataBaseInfo() { JSONObject json = JSONObject(); { List<Map<String,String>> list = dataBaseService.selectDataBases(); if(list.size()!=0) { json.put("lines"); }); } } (Exception e) { e.printstacktrace(); json.put("returnMsg","特殊异常" Todo: handle exception } json; } * 获取单个数据库所有表信息 * databaseName * @GetMapping(value="/querySingleDataBaseInfo",1)">) @ApiOperation(value="获取单个数据库所有表信息",notes="获取单个数据库所有表信息" JSONObject querySingleDataBaseInfo(String databaseName) { JSONObject json = JSONObject(); { StrUtil.isEmpty(databaseName)) { List<Map<String,1)"> dataBaseService.showTables(databaseName); ) { json.put("lines"获取数据"); json.put("returnCode",1)">); } { json.put("returnMsg","获取数据失败"); } } { json.put("returnMsg",1)">); } } json; } * 获取单个表所有字段信息 * @GetMapping(value="/querySingleTableInfo",1)">) @ApiOperation(value="获取单个表所有字段信息",1)"> JSONObject querySingleTableInfo(String tableName) { JSONObject json = StrUtil.isEmpty(tableName)) { List<Map<String,1)"> dataBaseService.showColumns(tableName); json; }
希望本篇文章能够给大家的开发效率带来提升