>
快捷搜索:

代码生成器,MacOS中Maven境况陈设

- 编辑:皇家国际app -

代码生成器,MacOS中Maven境况陈设

1 duplicated blocks of code must be removed.

自己的官方网站

什么是springboot?

 笔者喜欢以“貌”取人,从字面意思上得到spring可能要booter化了*)

联想到java的bootstrap classloader,这里你只可以发出对它的恋慕了。当然springboot是这么作自己介绍的:“使用本人,能够飞快的搭建三个全体的spring应用”,曾经在念书spring时,spring自身说它是多少个轻量级的框架,可是在支付时 每一回都要布置这么多的xml 并不曾人让觉觉轻量级。当然如此清楚是有失水准的,spring三个为主IOC和Aop支撑起来那几个框架。以及后来陆陆续续家族特别庞大,当然今日以此家门成员springboot 是特别令人激动的成品,springboot = spring*。在以后利用服务化的不常下,springcloud也丰盛令人惊艳,作者此前很崇拜dubbo,很有力的RPC框架,比较那后springcloud有更庞大的存在。前天主演是springboot。当然,springboot与springcloud亦是美满良缘。

mvn -v

小结

  • 领到二个基础框架吧,不要再copy项目,删除不用的类,改来改去,复制来复制去了
  • 永不再花半小时以至越来越多日子在模板代码的copy修改上了,写个代码生成器,10s化解

终极再插嘴一句,项目管事人要有察觉的滋长组织的成本成效,代码生成器是多个相比较好的晋升,希望能令你通过想到越来越多!!

再比方重复的代码呀

这里把保存到数据库的逻辑写到了一个线程池中,首假设不期待记录日志的逻辑影响了客商须要数据接口的逻辑,和质量。

springboot vs sping*

springboot 秉承着约定大于配置的思想成功的吸引了众多的开发者。

ssm结构是前些天用的挺多的协会。特其他福利,配置spring的内外文有一点太机械化了,何况对于web项目来说tomcat的安插也是必得的还会有每一遍maven或gradle中依据密密麻麻的jar包,在springboot中一切都以可以优化的。springboot 秉承着约定大于配置的思虑成功的引发了累累的开拓者。后日小编就归纳的做一个springboot项指标例证

代码生成器,MacOS中Maven境况陈设。4.强制试行文件:source ~/.bash_profile

二、代码生成器怎么落到实处?

代码生成器的贯彻由很三种,大家以从mysql数据库表结构变迁对应代码为例来阐明怎么着兑现三个代码生成器。有以下多少个第一:

  1. 提早搭建好项目基础框架,因为变化的便是基础框架的模板代码
  2. 收获有个别数据库内的表及表结构音信,用于转移model及其余代码
  3. 利用freemarker实行模板生成

如公司项目都以左右端分离的,那自身就领取了一个rest-base项目作为基础框架,该框架满意绝抢先三分之二铺面项目支付所需的根基成效

//获取所有库select DISTINCT(TABLE_SCHEMA) from information_schema.`TABLES`;//获取所有表SELECT TABLE_NAME as tableName,TABLE_COMMENT as tableComment from information_schema.`TABLES` where TABLE_SCHEMA='test';//获取某个表的结构select COLUMN_NAME as columnName,COLUMN_TYPE as columnType,COLUMN_DEFAULT as columnDefault,COLUMN_COMMENT as columnComment,CHARACTER_MAXIMUM_LENGTH as columnCharacterMaximumLength from information_schema.columns where table_schema = 'test' and table_name = 'rule'; 

由此询问information_schema库内的TABLES、columns表,能够获取数据内的表、表字段属性等。然后就足以以此来鲜明model的剧情,如表user_role对应的实业正是UserRole,表字段和实业性质可以依赖项目和法则进行映射。

Code Smells 这一个名字实在是太唬人了,在 重构 里定义设计的高低在于有未有代码的坏味道,借使 sonarqube 有力量甄别全体的代码坏味道的话,那还怕神马低质量代码呢。可是起码sonarqube 有力量甄别一部分初级的代码坏味道,比方过长的不二秘技参数:

客商点击了某些分界面,央求了后台有个别接口。接口乞请到后台后,记录诉求的数量到数据库中。

②编制pom增多正视
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>is.jack.boots</groupId> <artifactId>boot</artifactId> <version>1.0-SNAPSHOT</version> <!--添加springboot的家族长老 ^_^ 方便管理依赖版本 以及后续支持数据持久化 缓存 模板引擎 中间件等等--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.8.RELEASE</version> </parent> <!-- springboot 依赖核心 一个jar包 包罗众多spring 组件 以及 tomcat --> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> <properties> <java.version>1.8</java.version> </properties> <!-- maven spring 插件 用于maven打包管理 以及maven命令化springboot --> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>

3.settings文件的路子

一、代码生成器能干什么?

三个Mini的事务种类,平常无需很复杂的架构,平日便是经过单个或多个档案的次序来贯彻。大家先来看下最基础的支付流程:

  1. 叩问要求
  2. 设计表结构
  3. 创制基础框架
  4. 创建开采布置,按模块分配职分
  5. 开展模块开辟
  6. 测试、上线

技师实行模块开垦的章程有以下三种:

  1. 传闻表结构设计,手工业创制model,然后copy UserDao改名称叫CompanyDao,copy UserServiceImpl改名字为CompanyServiceImpl,并修改援引的UserDao为CompanyDao等;
  2. 依据表结构划设想计,使用工具生成model,后续手续同1

借使可是细,总是要修改个两一回工夫让叁个模块有三个气派,然后再起来实行真正关注的事体支付,而那时时间可能已经长逝了三个钟头,或者更加持久。

程序猿在付出时应当“懒”一点,若是类似的代码多次油但是生,不要在copy了,提取为公共的艺术;若是类似的copy、修改的操作重复的面世的贰个品种、不相同的档次里,那就写个代码生成器吧,一键完毕你手工业几十步的操作。

代码生成器是用来生成有规律的代码的,就好像controller、service、serviceImpl、dao、daoImpl、model、jsp的布局,客商、剧中人物、权限等等模块都有周围的结构,代码生成器能够代表我们的copy操作,自动生成那个不一致职业对象的模版代码。

sonarQube 本人说自个儿用于做 continuous code quality, 从它所生成的暗中同意的告知来看,首要包涵了如下多少个部分:

翻见到刚刚央浼顾客列表分界面包车型大巴执市价况

①新建三个maven web项目

图片 1maven工程.png

旅社地址:

在规模极小的厂商里,大多数的品种范围不是特意大,手艺达成难度不是异常高,关切点更加多是在作业功用的付出及保险业务流程的不利上。当有三个新的类别来时,常常会找三个门类进行copy,删除不用的包和类,然后以此为基础,进行继续的费用,开拓有个别模块,就copy出一份controller、service、serviceImpl、dao、daoImpl、model、jsp,然后改成类名。项目内十分二上述的代码都是模板性的,假若用手工业copy、修改的不二法门来促成,就太烦人也没成效,而此时就是代码生成器小展身手的时候,应用代码生成器生成模板性的代码,收缩手工业操作的麻烦,聚焦精力在业务支付上,进步开垦功效,代码生成器是三个很简短的东西,一点都不高深。

那样看来其功用依然可圈可点的,而且我所使用的还独自是最基本的布置,未有做任何的自定义。

@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface SLog { String value() default "";}

@Aspect@Componentpublic class SLogAspect { /** * 保存日志到数据库的线程池 */ ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("SLogAspect-Thread-%d").build(); ExecutorService executor = new ThreadPoolExecutor(5,200,0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>, threadFactory, new ThreadPoolExecutor.AbortPolicy; @Pointcut("@annotation(com.slife.annotation.SLog)") public void logPointCut() { } @Around("logPointCut public Object around(ProceedingJoinPoint point) throws Throwable { long beginTime = System.currentTimeMillis(); // 执行方法 Object result = point.proceed(); // 执行时长 long time = System.currentTimeMillis() - beginTime; // 获取request HttpServletRequest request = ServletUtils.getHttpServletRequest(); //获取请求的ip String ip = IPUtils.getIpAddr; SaveLogTask saveLogTask = new SaveLogTask(point, time, ip); //保存日志到数据库 executor.execute(saveLogTask); return result; }}

/** * * @author chen * @date 2017/9/19 * <p> * Email 122741482@qq.com * <p> * Describe: */public class SaveLogTask implements Runnable { private SlifeLogDao slifeLogDao = ApplicationContextRegister.getBean(SlifeLogDao.class); private ProceedingJoinPoint joinPoint; private long time; private String ip; public SaveLogTask(ProceedingJoinPoint point, long time, String ip) { this.joinPoint = point; this.time = time; this.ip = ip; } @Override public void run() { saveLog(joinPoint, time, ip); } /** * 保存日志 到数据库 * * @param joinPoint * @param time */ private void saveLog(ProceedingJoinPoint joinPoint, long time, String ip) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); SlifeLog slifeLog = new SlifeLog(); SLog sLog = method.getAnnotation(SLog.class); if (slifeLog != null) { // 注解上的描述 slifeLog.setMsg(sLog.value; } // 请求的方法名 String className = joinPoint.getTarget().getClass().getName(); String methodName = signature.getName(); slifeLog.setSrc(className + "." + methodName + "; // 请求的参数 Object[] args = joinPoint.getArgs(); try { String params = JSON.toJSONString; slifeLog.setParams; } catch (Exception e) { } // 设置IP地址 slifeLog.setIp; // 用户名 ShiroUser currUser = SlifeSysUser.ShiroUser(); if (null == currUser) { if (null != slifeLog.getParams { slifeLog.setName(slifeLog.getParams; slifeLog.setLoginName(slifeLog.getParams; } else { slifeLog.setName("获取用户信息为空"); slifeLog.setLoginName("获取用户信息为空"); slifeLog.setCreateId; } } else { slifeLog.setName(currUser.getName; slifeLog.setLoginName(currUser.getUsername; } slifeLog.setUseTime; // 保存系统日志 slifeLogDao.insert; }}

 @SLog("获取用户列表数据") @ApiOperation(value = "获取用户列表数据", notes = "获取用户列表:使用约定的DataTable") @PostMapping(value = "/list") @ResponseBody public DataTable<SysUser> list(@RequestBody DataTable dt, ServletRequest request) { return sysUserService.pageSearch; } @SLog("获取用户列表数据")

IDEA+maven 构建

3、freemarker生成模板代码

先大约讲下思路:

  1. 依靠申明,按法则获得实体名称,进而也认可了dao、service等的类名;
  2. 将表字段转为map结构,作为参数字传送入model对于的模板内,进而生成对应的model类;
  3. 依次传入参数,通过沙盘生成dao、service等代码

需求会或多或少freemarker的语法,基本上看个偶尔辰就高达了写轻易模板的程度了。

接口:

public interface GeneratorHelperService { /** * 设置公共参数,如 * projectPath 要生成代码的项目的路径: D:/workspace/code-generator * packagePath 要生成代码的项目的包的根路径:/src/main/java/com/hexun/bdc/generator * templetePath 本项目内代码模板路径: /src/main/resources/code-templete */ boolean setProperty(Map<String, String> map); /** * 生成某个库内所有表对应的代码 * @author yangwenkui * @time 2017年10月29日 下午8:22:35 * @param dbname 数据库名称 * @return */ boolean allTables(String dbname); /** * 生成某个库内某个表对应的代码 * @author yangwenkui * @time 2017年10月29日 下午8:22:35 * @param dbname 数据库名称 * @param tableName 表名称 * @return */ boolean oneTable(String dbname, String tableName);}

实现:

@Service("generatorHelperService")public class GeneratorHelperServiceImpl implements GeneratorHelperService { private static Logger logger = LoggerFactory .getLogger(GeneratorHelperServiceImpl.class); private static Map<String, String> propertyMap = Maps.newConcurrentMap(); @Autowired GeneratorHelperDao generatorHelperDao; @Value("${generator.project.path}") private String localProjectPath; @Override public boolean setProperty(Map<String, String> map) { propertyMap.putAll; return true; } @Override public boolean allTables(String dbname) { List<Object> tables = generatorHelperDao.listAllTable; for (Object item : tables) { Object[] arr =  item; TableInfo tableInfo = new TableInfo; boolean success = generateCode(dbname, tableInfo); if  { logger.error("generator code table=[{}] fail", item.toString; } } return true; } @Override public boolean oneTable(String dbname, String tableName) { Object entity = generatorHelperDao.findTableInfo(dbname, tableName); Object[] arr =  entity; TableInfo tableInfo = new TableInfo; return generateCode(dbname, tableInfo); } private boolean generateCode(String dbname, TableInfo item) { List<Object> list = generatorHelperDao.listColumInfos(dbname, item.getTabelName; List<ColumnInfo> columnInfos = new ArrayList<ColumnInfo>(list.size; String idType = "String"; for (Object obj : list) { Object[] arr =  obj; ColumnInfo columnInfo = new ColumnInfo; columnInfos.add(columnInfo); if("id".equals{ if("int".equals(columnInfo.getModelType{ idType = "Integer"; } else if("long".equals(columnInfo.getModelType{ idType = "Long"; } } } item.setIdType; createModel(item, columnInfos); createOther(item,"dao"); createOther(item,"service"); createOther(item,"serviceImpl"); createOther(item,"controller"); return true; } private void createModel(TableInfo item, List<ColumnInfo> columnInfos) { String path = getUpPath(); String dir = String.format("%s/domain",path); File file = new File; if(!file.exists{ file.mkdirs(); } String templetePath = String.format("%s%s", localProjectPath,propertyMap.get("templetePath")); String filePath = String.format("%s/%s.java", dir,item.getModleName; Map<String, Object> data = Maps.newHashMap(); data.put("proList", columnInfos); data.put("modelParam", String.format("%s%s",item.getModleName().substring.toLowerCase(),item.getModleName().substring; data.put("modellower", item.getModleName().toLowerCase; data.put("tableInfo", item); data.put("packagePath", Joiner.on.join(propertyMap.get("packagePath").split.substring; createTempleteFile(filePath,templetePath,"domain.flt",data); } private void createTempleteFile(String filename, String templetePath,String templeteName, Map<String, Object> data) { try { Configuration cfg = new Configuration(); cfg.setDirectoryForTemplateLoading(new File(templetePath)); cfg.setObjectWrapper(new DefaultObjectWrapper; //设置字符集 cfg.setDefaultEncoding; //设置尖括号语法和方括号语法,默认是自动检测语法 // 自动 AUTO_DETECT_TAG_SYNTAX // 尖括号 ANGLE_BRACKET_TAG_SYNTAX // 方括号 SQUARE_BRACKET_TAG_SYNTAX cfg.setTagSyntax(Configuration.AUTO_DETECT_TAG_SYNTAX); Writer out = new OutputStreamWriter(new FileOutputStream,"UTF-8"); Template temp = cfg.getTemplate(templeteName); temp.process(data, out); out.flush(); out.close(); }catch (Exception e) { logger.error("process due to erro",e); } } private String getUpPath() { return String.format("%s/%s", propertyMap.get("projectPath"), propertyMap.get("packagePath")); } private void createOther(TableInfo item,String type) { String path = getUpPath(); String lastDir = type; if("serviceImpl".equals{ lastDir = "service/impl"; } String dir = String.format("%s/%s",path,lastDir); File file = new File; if(!file.exists{ file.mkdirs(); } String templetePath = String.format("%s%s", localProjectPath,propertyMap.get("templetePath")); String filePath = String.format("%s/%s.java", dir,item.getModleName()+type.substring.toUpperCase()+type.substring; Map<String, Object> data = Maps.newHashMap(); data.put("modelParam", String.format("%s%s",item.getModleName().substring.toLowerCase(),item.getModleName().substring; data.put("modellower", item.getModleName().toLowerCase; data.put("item", item); data.put("packagePath", Joiner.on.join(propertyMap.get("packagePath").split.substring; createTempleteFile(filePath,templetePath,String.format("%s.flt", type),data); }}

model模板(domain.flt):

package ${packagePath}.domain;import io.swagger.annotations.ApiModelProperty;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.Table;import java.sql.Timestamp;/** * ${tableInfo.tableComment} */@Entity@Table(name = "${tableInfo.tabelName}")public class ${tableInfo.modleName} { <#list proList as item><#if item.modelName == "id"> @ApiModelProperty(value="主键") @Id <#if item.modelType == "int"> @GeneratedValue(strategy=GenerationType.AUTO) private Integer id; </#if> <#if item.modelType == "long"> @GeneratedValue(strategy=GenerationType.AUTO) private Long id; </#if> <#if item.modelType == "String"> @GeneratedValue(generator="system-uuid") @GenericGenerator(name="system-uuid",strategy="uuid") @Column(length=${item.modelCharacterMaximumLength}) private String id;//主键 </#if><#else> @ApiModelProperty(value="${item.modelComment}") @Column(name="${item.columnName}"<#if (item.modelCharacterMaximumLength?exists && item.modelType == "String" && item.modelCharacterMaximumLength?number<=255)>,length=${item.modelCharacterMaximumLength}</#if><#if item.modelDefault?exists && item.modelDefault != "">,columnDefinition="${item.modelDefault}"</#if>) private ${item.modelType} ${item.modelName}; </#if></#list><#list proList as item> public ${item.modelType} get${item.modelNameFirstUpper}() { return ${item.modelName}; } public void set${item.modelNameFirstUpper}(${item.modelType} ${item.modelName}) { this.${item.modelName} = ${item.modelName}; } </#list> @Override public String toString() { return String.format("${tableInfo.modleName} [<#list proList as item>, ${item.modelName}=%s</#list>]" <#list proList as item>, ${item.modelName}</#list>); }}

dao模板:

package ${packagePath}.dao;import com.hexun.bdc.base.component.common.BaseDao;import ${packagePath}.domain.${item.modleName};public interface ${item.modleName}Dao extends BaseDao<${item.modleName}, ${item.idType}>{}

代码逻辑不复杂,service提供了三个接口,setProperty用于安装要调换的代码的路子及包名等,allTables用于初次生成,贰回生成二个库内全部表对应的代码;oneTable用于转移钦赐表对应的代码,注意代码开采一段时间后,不要在上传至svn此前给覆盖了。完整代码在code-generation,在此基础上,你能够便捷修改出符合您集团的代码生成器!

只是展开一看会发觉其实 Bugs & VulnerabilitiesCode Smells 基本上正是 lint 所做的事体,比方代码风格不相符 java 的轨道呀,在运用 Optional 从前剖断其是或不是 isPresent 呀等等,不过人家本来正是做静态检查的也没有什么能够指责。

图片 2那边写图片描述

③选取springboot maven插件试行项目

在巅峰输入 mvn package target/boot-1.0-SNAPSHOT.jar 将项目打成jar包再输入 java -jar target/boot-1.0-SNAPSHOT.jar 这里springboot maven 插件会自行找到main函数实施 springboot 当然上述操作实现后 开启工程还大概有个法子

快使用Ali云的maven商旅

本文由皇家国际app发布,转载请注明来源:代码生成器,MacOS中Maven境况陈设