From 62beb474b235453489a8656455f983c8d332ccaf Mon Sep 17 00:00:00 2001 From: zc Date: Fri, 6 Feb 2026 12:23:45 +0800 Subject: [PATCH] first commit --- renren-dynamic-datasource/pom.xml | 16 ++ .../datasource/annotation/DataSource.java | 25 ++ .../datasource/aspect/DataSourceAspect.java | 71 +++++ .../config/DynamicContextHolder.java | 57 ++++ .../datasource/config/DynamicDataSource.java | 26 ++ .../config/DynamicDataSourceConfig.java | 64 +++++ .../config/DynamicDataSourceFactory.java | 54 ++++ .../properties/DataSourceProperties.java | 202 ++++++++++++++ .../DynamicDataSourceProperties.java | 33 +++ renren-generator/pom.xml | 135 ++++++++++ .../java/io/renren/GeneratorApplication.java | 25 ++ .../main/java/io/renren/config/DbConfig.java | 52 ++++ .../controller/SysGeneratorController.java | 62 +++++ .../main/java/io/renren/dao/GeneratorDao.java | 25 ++ .../java/io/renren/dao/MySQLGeneratorDao.java | 23 ++ .../io/renren/dao/OracleGeneratorDao.java | 21 ++ .../io/renren/dao/PostgreSQLGeneratorDao.java | 21 ++ .../io/renren/dao/SQLServerGeneratorDao.java | 21 ++ .../java/io/renren/entity/ColumnEntity.java | 75 ++++++ .../java/io/renren/entity/TableEntity.java | 69 +++++ .../renren/service/SysGeneratorService.java | 66 +++++ .../src/main/java/io/renren/utils/Assert.java | 77 ++++++ .../main/java/io/renren/utils/DateUtils.java | 36 +++ .../main/java/io/renren/utils/GenUtils.java | 254 ++++++++++++++++++ .../main/java/io/renren/utils/IdWorker.java | 67 +++++ .../main/java/io/renren/utils/PageUtils.java | 87 ++++++ .../src/main/java/io/renren/utils/Query.java | 53 ++++ .../src/main/java/io/renren/utils/R.java | 62 +++++ .../java/io/renren/utils/RenException.java | 61 +++++ .../io/renren/utils/RenExceptionHandler.java | 42 +++ .../main/java/io/renren/utils/Sequence.java | 203 ++++++++++++++ .../main/java/io/renren/utils/StringPool.java | 95 +++++++ .../java/io/renren/utils/SystemClock.java | 80 ++++++ 33 files changed, 2260 insertions(+) create mode 100644 renren-dynamic-datasource/pom.xml create mode 100644 renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/annotation/DataSource.java create mode 100644 renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/aspect/DataSourceAspect.java create mode 100644 renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/config/DynamicContextHolder.java create mode 100644 renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/config/DynamicDataSource.java create mode 100644 renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/config/DynamicDataSourceConfig.java create mode 100644 renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/config/DynamicDataSourceFactory.java create mode 100644 renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/properties/DataSourceProperties.java create mode 100644 renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/properties/DynamicDataSourceProperties.java create mode 100644 renren-generator/pom.xml create mode 100644 renren-generator/src/main/java/io/renren/GeneratorApplication.java create mode 100644 renren-generator/src/main/java/io/renren/config/DbConfig.java create mode 100644 renren-generator/src/main/java/io/renren/controller/SysGeneratorController.java create mode 100644 renren-generator/src/main/java/io/renren/dao/GeneratorDao.java create mode 100644 renren-generator/src/main/java/io/renren/dao/MySQLGeneratorDao.java create mode 100644 renren-generator/src/main/java/io/renren/dao/OracleGeneratorDao.java create mode 100644 renren-generator/src/main/java/io/renren/dao/PostgreSQLGeneratorDao.java create mode 100644 renren-generator/src/main/java/io/renren/dao/SQLServerGeneratorDao.java create mode 100644 renren-generator/src/main/java/io/renren/entity/ColumnEntity.java create mode 100644 renren-generator/src/main/java/io/renren/entity/TableEntity.java create mode 100644 renren-generator/src/main/java/io/renren/service/SysGeneratorService.java create mode 100644 renren-generator/src/main/java/io/renren/utils/Assert.java create mode 100644 renren-generator/src/main/java/io/renren/utils/DateUtils.java create mode 100644 renren-generator/src/main/java/io/renren/utils/GenUtils.java create mode 100644 renren-generator/src/main/java/io/renren/utils/IdWorker.java create mode 100644 renren-generator/src/main/java/io/renren/utils/PageUtils.java create mode 100644 renren-generator/src/main/java/io/renren/utils/Query.java create mode 100644 renren-generator/src/main/java/io/renren/utils/R.java create mode 100644 renren-generator/src/main/java/io/renren/utils/RenException.java create mode 100644 renren-generator/src/main/java/io/renren/utils/RenExceptionHandler.java create mode 100644 renren-generator/src/main/java/io/renren/utils/Sequence.java create mode 100644 renren-generator/src/main/java/io/renren/utils/StringPool.java create mode 100644 renren-generator/src/main/java/io/renren/utils/SystemClock.java diff --git a/renren-dynamic-datasource/pom.xml b/renren-dynamic-datasource/pom.xml new file mode 100644 index 0000000..fd130a4 --- /dev/null +++ b/renren-dynamic-datasource/pom.xml @@ -0,0 +1,16 @@ + + + io.renren + renren-security + 5.2.0 + + 4.0.0 + renren-dynamic-datasource + jar + 多数据源 + + + ${project.artifactId} + + + \ No newline at end of file diff --git a/renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/annotation/DataSource.java b/renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/annotation/DataSource.java new file mode 100644 index 0000000..ea9a99c --- /dev/null +++ b/renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/annotation/DataSource.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.commons.dynamic.datasource.annotation; + +import java.lang.annotation.*; + +/** + * 多数据源注解 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +public @interface DataSource { + String value() default ""; +} diff --git a/renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/aspect/DataSourceAspect.java b/renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/aspect/DataSourceAspect.java new file mode 100644 index 0000000..9eda526 --- /dev/null +++ b/renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/aspect/DataSourceAspect.java @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.commons.dynamic.datasource.aspect; + +import io.renren.commons.dynamic.datasource.annotation.DataSource; +import io.renren.commons.dynamic.datasource.config.DynamicContextHolder; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Method; + +/** + * 多数据源,切面处理类 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Aspect +@Component +@Order(Ordered.HIGHEST_PRECEDENCE) +public class DataSourceAspect { + protected Logger logger = LoggerFactory.getLogger(getClass()); + + @Pointcut("@annotation(io.renren.commons.dynamic.datasource.annotation.DataSource) " + + "|| @within(io.renren.commons.dynamic.datasource.annotation.DataSource)") + public void dataSourcePointCut() { + + } + + @Around("dataSourcePointCut()") + public Object around(ProceedingJoinPoint point) throws Throwable { + MethodSignature signature = (MethodSignature) point.getSignature(); + Class targetClass = point.getTarget().getClass(); + Method method = signature.getMethod(); + + DataSource targetDataSource = (DataSource)targetClass.getAnnotation(DataSource.class); + DataSource methodDataSource = method.getAnnotation(DataSource.class); + if(targetDataSource != null || methodDataSource != null){ + String value; + if(methodDataSource != null){ + value = methodDataSource.value(); + }else { + value = targetDataSource.value(); + } + + DynamicContextHolder.push(value); + logger.debug("set datasource is {}", value); + } + + try { + return point.proceed(); + } finally { + DynamicContextHolder.poll(); + logger.debug("clean datasource"); + } + } +} \ No newline at end of file diff --git a/renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/config/DynamicContextHolder.java b/renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/config/DynamicContextHolder.java new file mode 100644 index 0000000..5633477 --- /dev/null +++ b/renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/config/DynamicContextHolder.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.commons.dynamic.datasource.config; + +import java.util.ArrayDeque; +import java.util.Deque; + +/** + * 多数据源上下文 + * + * @author Mark sunlightcs@gmail.com + */ +public class DynamicContextHolder { + @SuppressWarnings("unchecked") + private static final ThreadLocal> CONTEXT_HOLDER = new ThreadLocal() { + @Override + protected Object initialValue() { + return new ArrayDeque(); + } + }; + + /** + * 获得当前线程数据源 + * + * @return 数据源名称 + */ + public static String peek() { + return CONTEXT_HOLDER.get().peek(); + } + + /** + * 设置当前线程数据源 + * + * @param dataSource 数据源名称 + */ + public static void push(String dataSource) { + CONTEXT_HOLDER.get().push(dataSource); + } + + /** + * 清空当前线程数据源 + */ + public static void poll() { + Deque deque = CONTEXT_HOLDER.get(); + deque.poll(); + if (deque.isEmpty()) { + CONTEXT_HOLDER.remove(); + } + } + +} \ No newline at end of file diff --git a/renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/config/DynamicDataSource.java b/renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/config/DynamicDataSource.java new file mode 100644 index 0000000..df40588 --- /dev/null +++ b/renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/config/DynamicDataSource.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.commons.dynamic.datasource.config; + +import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; + +/** + * 多数据源 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public class DynamicDataSource extends AbstractRoutingDataSource { + + @Override + protected Object determineCurrentLookupKey() { + return DynamicContextHolder.peek(); + } + +} diff --git a/renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/config/DynamicDataSourceConfig.java b/renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/config/DynamicDataSourceConfig.java new file mode 100644 index 0000000..1de20b8 --- /dev/null +++ b/renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/config/DynamicDataSourceConfig.java @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.commons.dynamic.datasource.config; + +import com.alibaba.druid.pool.DruidDataSource; +import io.renren.commons.dynamic.datasource.properties.DataSourceProperties; +import io.renren.commons.dynamic.datasource.properties.DynamicDataSourceProperties; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.HashMap; +import java.util.Map; + +/** + * 配置多数据源 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@Configuration +@EnableConfigurationProperties(DynamicDataSourceProperties.class) +public class DynamicDataSourceConfig { + @Autowired + private DynamicDataSourceProperties properties; + + @Bean + @ConfigurationProperties(prefix = "spring.datasource.druid") + public DataSourceProperties dataSourceProperties() { + return new DataSourceProperties(); + } + + @Bean + public DynamicDataSource dynamicDataSource(DataSourceProperties dataSourceProperties) { + DynamicDataSource dynamicDataSource = new DynamicDataSource(); + dynamicDataSource.setTargetDataSources(getDynamicDataSource()); + + //默认数据源 + DruidDataSource defaultDataSource = DynamicDataSourceFactory.buildDruidDataSource(dataSourceProperties); + dynamicDataSource.setDefaultTargetDataSource(defaultDataSource); + + return dynamicDataSource; + } + + private Map getDynamicDataSource(){ + Map dataSourcePropertiesMap = properties.getDatasource(); + Map targetDataSources = new HashMap<>(dataSourcePropertiesMap.size()); + dataSourcePropertiesMap.forEach((k, v) -> { + DruidDataSource druidDataSource = DynamicDataSourceFactory.buildDruidDataSource(v); + targetDataSources.put(k, druidDataSource); + }); + + return targetDataSources; + } + +} \ No newline at end of file diff --git a/renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/config/DynamicDataSourceFactory.java b/renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/config/DynamicDataSourceFactory.java new file mode 100644 index 0000000..c73fab2 --- /dev/null +++ b/renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/config/DynamicDataSourceFactory.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.commons.dynamic.datasource.config; + +import com.alibaba.druid.pool.DruidDataSource; +import io.renren.commons.dynamic.datasource.properties.DataSourceProperties; + +import java.sql.SQLException; + +/** + * DruidDataSource + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public class DynamicDataSourceFactory { + + public static DruidDataSource buildDruidDataSource(DataSourceProperties properties) { + DruidDataSource druidDataSource = new DruidDataSource(); + druidDataSource.setDriverClassName(properties.getDriverClassName()); + druidDataSource.setUrl(properties.getUrl()); + druidDataSource.setUsername(properties.getUsername()); + druidDataSource.setPassword(properties.getPassword()); + + druidDataSource.setInitialSize(properties.getInitialSize()); + druidDataSource.setMaxActive(properties.getMaxActive()); + druidDataSource.setMinIdle(properties.getMinIdle()); + druidDataSource.setMaxWait(properties.getMaxWait()); + druidDataSource.setTimeBetweenEvictionRunsMillis(properties.getTimeBetweenEvictionRunsMillis()); + druidDataSource.setMinEvictableIdleTimeMillis(properties.getMinEvictableIdleTimeMillis()); + druidDataSource.setMaxEvictableIdleTimeMillis(properties.getMaxEvictableIdleTimeMillis()); + druidDataSource.setValidationQuery(properties.getValidationQuery()); + druidDataSource.setValidationQueryTimeout(properties.getValidationQueryTimeout()); + druidDataSource.setTestOnBorrow(properties.isTestOnBorrow()); + druidDataSource.setTestOnReturn(properties.isTestOnReturn()); + druidDataSource.setPoolPreparedStatements(properties.isPoolPreparedStatements()); + druidDataSource.setMaxOpenPreparedStatements(properties.getMaxOpenPreparedStatements()); + druidDataSource.setSharePreparedStatements(properties.isSharePreparedStatements()); + + try { + // druidDataSource.setFilters(properties.getFilters()); + druidDataSource.init(); + } catch (SQLException e) { + e.printStackTrace(); + } + return druidDataSource; + } +} \ No newline at end of file diff --git a/renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/properties/DataSourceProperties.java b/renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/properties/DataSourceProperties.java new file mode 100644 index 0000000..3e4d395 --- /dev/null +++ b/renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/properties/DataSourceProperties.java @@ -0,0 +1,202 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.commons.dynamic.datasource.properties; + +/** + * 多数据源属性 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +public class DataSourceProperties { + private String driverClassName; + private String url; + private String username; + private String password; + + /** + * Druid默认参数 + */ + private int initialSize = 2; + private int maxActive = 10; + private int minIdle = -1; + private long maxWait = 60 * 1000L; + private long timeBetweenEvictionRunsMillis = 60 * 1000L; + private long minEvictableIdleTimeMillis = 1000L * 60L * 30L; + private long maxEvictableIdleTimeMillis = 1000L * 60L * 60L * 7; + private String validationQuery = "select 1"; + private int validationQueryTimeout = -1; + private boolean testOnBorrow = false; + private boolean testOnReturn = false; + private boolean testWhileIdle = true; + private boolean poolPreparedStatements = false; + private int maxOpenPreparedStatements = -1; + private boolean sharePreparedStatements = false; + private String filters = "stat,wall"; + + public String getDriverClassName() { + return driverClassName; + } + + public void setDriverClassName(String driverClassName) { + this.driverClassName = driverClassName; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public int getInitialSize() { + return initialSize; + } + + public void setInitialSize(int initialSize) { + this.initialSize = initialSize; + } + + public int getMaxActive() { + return maxActive; + } + + public void setMaxActive(int maxActive) { + this.maxActive = maxActive; + } + + public int getMinIdle() { + return minIdle; + } + + public void setMinIdle(int minIdle) { + this.minIdle = minIdle; + } + + public long getMaxWait() { + return maxWait; + } + + public void setMaxWait(long maxWait) { + this.maxWait = maxWait; + } + + public long getTimeBetweenEvictionRunsMillis() { + return timeBetweenEvictionRunsMillis; + } + + public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) { + this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; + } + + public long getMinEvictableIdleTimeMillis() { + return minEvictableIdleTimeMillis; + } + + public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) { + this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; + } + + public long getMaxEvictableIdleTimeMillis() { + return maxEvictableIdleTimeMillis; + } + + public void setMaxEvictableIdleTimeMillis(long maxEvictableIdleTimeMillis) { + this.maxEvictableIdleTimeMillis = maxEvictableIdleTimeMillis; + } + + public String getValidationQuery() { + return validationQuery; + } + + public void setValidationQuery(String validationQuery) { + this.validationQuery = validationQuery; + } + + public int getValidationQueryTimeout() { + return validationQueryTimeout; + } + + public void setValidationQueryTimeout(int validationQueryTimeout) { + this.validationQueryTimeout = validationQueryTimeout; + } + + public boolean isTestOnBorrow() { + return testOnBorrow; + } + + public void setTestOnBorrow(boolean testOnBorrow) { + this.testOnBorrow = testOnBorrow; + } + + public boolean isTestOnReturn() { + return testOnReturn; + } + + public void setTestOnReturn(boolean testOnReturn) { + this.testOnReturn = testOnReturn; + } + + public boolean isTestWhileIdle() { + return testWhileIdle; + } + + public void setTestWhileIdle(boolean testWhileIdle) { + this.testWhileIdle = testWhileIdle; + } + + public boolean isPoolPreparedStatements() { + return poolPreparedStatements; + } + + public void setPoolPreparedStatements(boolean poolPreparedStatements) { + this.poolPreparedStatements = poolPreparedStatements; + } + + public int getMaxOpenPreparedStatements() { + return maxOpenPreparedStatements; + } + + public void setMaxOpenPreparedStatements(int maxOpenPreparedStatements) { + this.maxOpenPreparedStatements = maxOpenPreparedStatements; + } + + public boolean isSharePreparedStatements() { + return sharePreparedStatements; + } + + public void setSharePreparedStatements(boolean sharePreparedStatements) { + this.sharePreparedStatements = sharePreparedStatements; + } + + public String getFilters() { + return filters; + } + + public void setFilters(String filters) { + this.filters = filters; + } +} \ No newline at end of file diff --git a/renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/properties/DynamicDataSourceProperties.java b/renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/properties/DynamicDataSourceProperties.java new file mode 100644 index 0000000..bc97020 --- /dev/null +++ b/renren-dynamic-datasource/src/main/java/io/renren/commons/dynamic/datasource/properties/DynamicDataSourceProperties.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.commons.dynamic.datasource.properties; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * 多数据源属性 + * + * @author Mark sunlightcs@gmail.com + * @since 1.0.0 + */ +@ConfigurationProperties(prefix = "dynamic") +public class DynamicDataSourceProperties { + private Map datasource = new LinkedHashMap<>(); + + public Map getDatasource() { + return datasource; + } + + public void setDatasource(Map datasource) { + this.datasource = datasource; + } +} diff --git a/renren-generator/pom.xml b/renren-generator/pom.xml new file mode 100644 index 0000000..adb152c --- /dev/null +++ b/renren-generator/pom.xml @@ -0,0 +1,135 @@ + + + 4.0.0 + io.renren + renren-generator + 5.2.0 + jar + renren-generator + + + org.springframework.boot + spring-boot-starter-parent + 2.7.5 + + + + UTF-8 + UTF-8 + 1.8 + 2.2.2 + 1.4.2 + 1.2.14 + 2.6 + 2.11.0 + 1.10 + 1.7 + 4.0 + 11.2.0.3 + + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-web + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + ${mybatis.spring.boot.version} + + + com.github.pagehelper + pagehelper-spring-boot-starter + ${pagehelper.spring.boot.version} + + + com.alibaba + druid + ${druid.version} + + + commons-lang + commons-lang + ${commons.lang.version} + + + commons-io + commons-io + ${commons.io.version} + + + commons-configuration + commons-configuration + ${commons.configuration.version} + + + velocity + org.apache.velocity + ${velocity.version} + + + + mysql + mysql-connector-java + + + + com.oracle + ojdbc6 + ${oracle.version} + + + + com.microsoft.sqlserver + sqljdbc4 + ${mssql.version} + + + + org.postgresql + postgresql + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + + + public + aliyun nexus + https://maven.aliyun.com/repository/public/ + + true + + + + + + public + aliyun nexus + https://maven.aliyun.com/repository/public/ + + true + + + false + + + + + diff --git a/renren-generator/src/main/java/io/renren/GeneratorApplication.java b/renren-generator/src/main/java/io/renren/GeneratorApplication.java new file mode 100644 index 0000000..c0dc876 --- /dev/null +++ b/renren-generator/src/main/java/io/renren/GeneratorApplication.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * renren-generator + * + * @author Mark sunlightcs@gmail.com + */ +@SpringBootApplication +public class GeneratorApplication { + + public static void main(String[] args) { + SpringApplication.run(GeneratorApplication.class, args); + } +} diff --git a/renren-generator/src/main/java/io/renren/config/DbConfig.java b/renren-generator/src/main/java/io/renren/config/DbConfig.java new file mode 100644 index 0000000..5b67693 --- /dev/null +++ b/renren-generator/src/main/java/io/renren/config/DbConfig.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.config; + +import io.renren.dao.*; +import io.renren.utils.RenException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +/** + * 数据库配置 + * + * @author Mark sunlightcs@gmail.com + */ +@Configuration +public class DbConfig { + @Value("${renren.database: mysql}") + private String database; + @Autowired + private MySQLGeneratorDao mySQLGeneratorDao; + @Autowired + private OracleGeneratorDao oracleGeneratorDao; + @Autowired + private SQLServerGeneratorDao sqlServerGeneratorDao; + @Autowired + private PostgreSQLGeneratorDao postgreSQLGeneratorDao; + + @Bean + @Primary + public GeneratorDao getGeneratorDao(){ + if("mysql".equalsIgnoreCase(database)){ + return mySQLGeneratorDao; + }else if("oracle".equalsIgnoreCase(database)){ + return oracleGeneratorDao; + }else if("sqlserver".equalsIgnoreCase(database)){ + return sqlServerGeneratorDao; + }else if("postgresql".equalsIgnoreCase(database)){ + return postgreSQLGeneratorDao; + }else { + throw new RenException("不支持当前数据库:" + database); + } + } +} diff --git a/renren-generator/src/main/java/io/renren/controller/SysGeneratorController.java b/renren-generator/src/main/java/io/renren/controller/SysGeneratorController.java new file mode 100644 index 0000000..7baef11 --- /dev/null +++ b/renren-generator/src/main/java/io/renren/controller/SysGeneratorController.java @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.controller; + +import io.renren.service.SysGeneratorService; +import io.renren.utils.PageUtils; +import io.renren.utils.Query; +import io.renren.utils.R; +import org.apache.commons.io.IOUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Map; + +/** + * 代码生成器 + * + * @author Mark sunlightcs@gmail.com + */ +@Controller +@RequestMapping("/sys/generator") +public class SysGeneratorController { + @Autowired + private SysGeneratorService sysGeneratorService; + + /** + * 列表 + */ + @ResponseBody + @RequestMapping("/list") + public R list(@RequestParam Map params){ + PageUtils pageUtil = sysGeneratorService.queryList(new Query(params)); + + return R.ok().put("page", pageUtil); + } + + /** + * 生成代码 + */ + @RequestMapping("/code") + public void code(String tables, HttpServletResponse response) throws IOException{ + byte[] data = sysGeneratorService.generatorCode(tables.split(",")); + + response.reset(); + response.setHeader("Content-Disposition", "attachment; filename=\"renren.zip\""); + response.addHeader("Content-Length", "" + data.length); + response.setContentType("application/octet-stream; charset=UTF-8"); + + IOUtils.write(data, response.getOutputStream()); + } +} diff --git a/renren-generator/src/main/java/io/renren/dao/GeneratorDao.java b/renren-generator/src/main/java/io/renren/dao/GeneratorDao.java new file mode 100644 index 0000000..f9f2335 --- /dev/null +++ b/renren-generator/src/main/java/io/renren/dao/GeneratorDao.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.dao; + +import java.util.List; +import java.util.Map; + +/** + * 数据库接口 + * + * @author Mark sunlightcs@gmail.com + */ +public interface GeneratorDao { + List> queryList(Map map); + + Map queryTable(String tableName); + + List> queryColumns(String tableName); +} diff --git a/renren-generator/src/main/java/io/renren/dao/MySQLGeneratorDao.java b/renren-generator/src/main/java/io/renren/dao/MySQLGeneratorDao.java new file mode 100644 index 0000000..65c4ad5 --- /dev/null +++ b/renren-generator/src/main/java/io/renren/dao/MySQLGeneratorDao.java @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.dao; + +import org.apache.ibatis.annotations.Mapper; + + +/** + * MySQL代码生成器 + * + * @author Mark sunlightcs@gmail.com + */ +@Mapper +public interface MySQLGeneratorDao extends GeneratorDao { + + +} diff --git a/renren-generator/src/main/java/io/renren/dao/OracleGeneratorDao.java b/renren-generator/src/main/java/io/renren/dao/OracleGeneratorDao.java new file mode 100644 index 0000000..effd14c --- /dev/null +++ b/renren-generator/src/main/java/io/renren/dao/OracleGeneratorDao.java @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.dao; + +import org.apache.ibatis.annotations.Mapper; + +/** + * Oracle代码生成器 + * + * @author Mark sunlightcs@gmail.com + */ +@Mapper +public interface OracleGeneratorDao extends GeneratorDao { + +} diff --git a/renren-generator/src/main/java/io/renren/dao/PostgreSQLGeneratorDao.java b/renren-generator/src/main/java/io/renren/dao/PostgreSQLGeneratorDao.java new file mode 100644 index 0000000..14ad34b --- /dev/null +++ b/renren-generator/src/main/java/io/renren/dao/PostgreSQLGeneratorDao.java @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.dao; + +import org.apache.ibatis.annotations.Mapper; + +/** + * PostgreSQL代码生成器 + * + * @author Mark sunlightcs@gmail.com + */ +@Mapper +public interface PostgreSQLGeneratorDao extends GeneratorDao { + +} diff --git a/renren-generator/src/main/java/io/renren/dao/SQLServerGeneratorDao.java b/renren-generator/src/main/java/io/renren/dao/SQLServerGeneratorDao.java new file mode 100644 index 0000000..ec9c5b5 --- /dev/null +++ b/renren-generator/src/main/java/io/renren/dao/SQLServerGeneratorDao.java @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.dao; + +import org.apache.ibatis.annotations.Mapper; + +/** + * SQLServer代码生成器 + * + * @author Mark sunlightcs@gmail.com + */ +@Mapper +public interface SQLServerGeneratorDao extends GeneratorDao { + +} diff --git a/renren-generator/src/main/java/io/renren/entity/ColumnEntity.java b/renren-generator/src/main/java/io/renren/entity/ColumnEntity.java new file mode 100644 index 0000000..04fffc4 --- /dev/null +++ b/renren-generator/src/main/java/io/renren/entity/ColumnEntity.java @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.entity; + +/** + * 列的属性 + * + * @author Mark sunlightcs@gmail.com + */ +public class ColumnEntity { + //列名 + private String columnName; + //列名类型 + private String dataType; + //列名备注 + private String comments; + + //属性名称(第一个字母大写),如:user_name => UserName + private String attrName; + //属性名称(第一个字母小写),如:user_name => userName + private String attrname; + //属性类型 + private String attrType; + //auto_increment + private String extra; + + public String getColumnName() { + return columnName; + } + public void setColumnName(String columnName) { + this.columnName = columnName; + } + public String getDataType() { + return dataType; + } + public void setDataType(String dataType) { + this.dataType = dataType; + } + public String getComments() { + return comments; + } + public void setComments(String comments) { + this.comments = comments; + } + public String getAttrname() { + return attrname; + } + public void setAttrname(String attrname) { + this.attrname = attrname; + } + public String getAttrName() { + return attrName; + } + public void setAttrName(String attrName) { + this.attrName = attrName; + } + public String getAttrType() { + return attrType; + } + public void setAttrType(String attrType) { + this.attrType = attrType; + } + public String getExtra() { + return extra; + } + public void setExtra(String extra) { + this.extra = extra; + } +} diff --git a/renren-generator/src/main/java/io/renren/entity/TableEntity.java b/renren-generator/src/main/java/io/renren/entity/TableEntity.java new file mode 100644 index 0000000..a36289f --- /dev/null +++ b/renren-generator/src/main/java/io/renren/entity/TableEntity.java @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.entity; + +import java.util.List; + +/** + * 表数据 + * + * @author Mark sunlightcs@gmail.com + */ +public class TableEntity { + //表的名称 + private String tableName; + //表的备注 + private String comments; + //表的主键 + private ColumnEntity pk; + //表的列名(不包含主键) + private List columns; + + //类名(第一个字母大写),如:sys_user => SysUser + private String className; + //类名(第一个字母小写),如:sys_user => sysUser + private String classname; + + public String getTableName() { + return tableName; + } + public void setTableName(String tableName) { + this.tableName = tableName; + } + public String getComments() { + return comments; + } + public void setComments(String comments) { + this.comments = comments; + } + public ColumnEntity getPk() { + return pk; + } + public void setPk(ColumnEntity pk) { + this.pk = pk; + } + public List getColumns() { + return columns; + } + public void setColumns(List columns) { + this.columns = columns; + } + public String getClassName() { + return className; + } + public void setClassName(String className) { + this.className = className; + } + public String getClassname() { + return classname; + } + public void setClassname(String classname) { + this.classname = classname; + } +} diff --git a/renren-generator/src/main/java/io/renren/service/SysGeneratorService.java b/renren-generator/src/main/java/io/renren/service/SysGeneratorService.java new file mode 100644 index 0000000..dd6ba66 --- /dev/null +++ b/renren-generator/src/main/java/io/renren/service/SysGeneratorService.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.service; + +import com.github.pagehelper.Page; +import com.github.pagehelper.PageHelper; +import io.renren.dao.GeneratorDao; +import io.renren.utils.GenUtils; +import io.renren.utils.PageUtils; +import io.renren.utils.Query; +import org.apache.commons.io.IOUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.io.ByteArrayOutputStream; +import java.util.List; +import java.util.Map; +import java.util.zip.ZipOutputStream; + +/** + * 代码生成器 + * + * @author Mark sunlightcs@gmail.com + */ +@Service +public class SysGeneratorService { + @Autowired + private GeneratorDao generatorDao; + + public PageUtils queryList(Query query) { + Page page = PageHelper.startPage(query.getPage(), query.getLimit()); + List> list = generatorDao.queryList(query); + + return new PageUtils(list, (int)page.getTotal(), query.getLimit(), query.getPage()); + } + + public Map queryTable(String tableName) { + return generatorDao.queryTable(tableName); + } + + public List> queryColumns(String tableName) { + return generatorDao.queryColumns(tableName); + } + + public byte[] generatorCode(String[] tableNames) { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + ZipOutputStream zip = new ZipOutputStream(outputStream); + + for(String tableName : tableNames){ + //查询表信息 + Map table = queryTable(tableName); + //查询列信息 + List> columns = queryColumns(tableName); + //生成代码 + GenUtils.generatorCode(table, columns, zip); + } + IOUtils.closeQuietly(zip); + return outputStream.toByteArray(); + } +} diff --git a/renren-generator/src/main/java/io/renren/utils/Assert.java b/renren-generator/src/main/java/io/renren/utils/Assert.java new file mode 100644 index 0000000..295343b --- /dev/null +++ b/renren-generator/src/main/java/io/renren/utils/Assert.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.renren.utils; + + +/** + *

+ * 断言类 + *

+ * + * @author miemie + * @since 2018-07-24 + */ +public final class Assert { + + /** + * 断言这个 boolean 为 true + * 为 false 则抛出异常 + * + * @param expression boolean 值 + * @param message 消息 + */ + public static void isTrue(boolean expression, String message, Object... params) { + if (!expression) { + return; + } + } + + /** + * 断言这个 boolean 为 false + * 为 true 则抛出异常 + * + * @param expression boolean 值 + * @param message 消息 + */ + public static void isFalse(boolean expression, String message, Object... params) { + isTrue(!expression, message, params); + } + + /** + * 断言这个 object 为 null + * 不为 null 则抛异常 + * + * @param object 对象 + * @param message 消息 + */ + public static void isNull(Object object, String message, Object... params) { + isTrue(object == null, message, params); + } + + /** + * 断言这个 object 不为 null + * 为 null 则抛异常 + * + * @param object 对象 + * @param message 消息 + */ + public static void notNull(Object object, String message, Object... params) { + isTrue(object != null, message, params); + } + + +} diff --git a/renren-generator/src/main/java/io/renren/utils/DateUtils.java b/renren-generator/src/main/java/io/renren/utils/DateUtils.java new file mode 100644 index 0000000..4992d42 --- /dev/null +++ b/renren-generator/src/main/java/io/renren/utils/DateUtils.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.utils; + +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * 日期处理 + * + * @author Mark sunlightcs@gmail.com + */ +public class DateUtils { + /** 时间格式(yyyy-MM-dd) */ + public final static String DATE_PATTERN = "yyyy-MM-dd"; + /** 时间格式(yyyy-MM-dd HH:mm:ss) */ + public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss"; + + public static String format(Date date) { + return format(date, DATE_PATTERN); + } + + public static String format(Date date, String pattern) { + if(date != null){ + SimpleDateFormat df = new SimpleDateFormat(pattern); + return df.format(date); + } + return null; + } +} diff --git a/renren-generator/src/main/java/io/renren/utils/GenUtils.java b/renren-generator/src/main/java/io/renren/utils/GenUtils.java new file mode 100644 index 0000000..27793f0 --- /dev/null +++ b/renren-generator/src/main/java/io/renren/utils/GenUtils.java @@ -0,0 +1,254 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.utils; + +import io.renren.entity.ColumnEntity; +import io.renren.entity.TableEntity; +import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.WordUtils; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.Velocity; + +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import java.util.*; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +/** + * 代码生成器 工具类 + * + * @author Mark sunlightcs@gmail.com + */ +public class GenUtils { + + public static List getTemplates(){ + List templates = new ArrayList(); + templates.add("template/DTO.java.vm"); + templates.add("template/Entity.java.vm"); + templates.add("template/Dao.java.vm"); + templates.add("template/Dao.xml.vm"); + templates.add("template/Service.java.vm"); + templates.add("template/ServiceImpl.java.vm"); + templates.add("template/Controller.java.vm"); + templates.add("template/Excel.java.vm"); + templates.add("template/index.vue.vm"); + templates.add("template/add-or-update.vue.vm"); + templates.add("template/mysql.vm"); + templates.add("template/sqlserver.vm"); + templates.add("template/oracle.vm"); + templates.add("template/postgresql.vm"); + return templates; + } + + /** + * 生成代码 + */ + public static void generatorCode(Map table, + List> columns, ZipOutputStream zip){ + //配置信息 + Configuration config = getConfig(); + boolean hasBigDecimal = false; + //表信息 + TableEntity tableEntity = new TableEntity(); + tableEntity.setTableName(table.get("tableName")); + tableEntity.setComments(table.get("tableComment")); + //表名转换成Java类名 + String className = tableToJava(tableEntity.getTableName(), config.getString("tablePrefix")); + tableEntity.setClassName(className); + tableEntity.setClassname(StringUtils.uncapitalize(className)); + + //列信息 + List columnsList = new ArrayList<>(); + for(Map column : columns){ + ColumnEntity columnEntity = new ColumnEntity(); + columnEntity.setColumnName(column.get("columnName")); + columnEntity.setDataType(column.get("dataType")); + columnEntity.setComments(column.get("columnComment")); + columnEntity.setExtra(column.get("extra")); + + //列名转换成Java属性名 + String attrName = columnToJava(columnEntity.getColumnName()); + columnEntity.setAttrName(attrName); + columnEntity.setAttrname(StringUtils.uncapitalize(attrName)); + + //列的数据类型,转换成Java类型 + String attrType = config.getString(columnEntity.getDataType(), "unknowType"); + columnEntity.setAttrType(attrType); + if (!hasBigDecimal && attrType.equals("BigDecimal" )) { + hasBigDecimal = true; + } + //是否主键 + if("PRI".equalsIgnoreCase(column.get("columnKey")) && tableEntity.getPk() == null){ + tableEntity.setPk(columnEntity); + } + + columnsList.add(columnEntity); + } + tableEntity.setColumns(columnsList); + + //没主键,则第一个字段为主键 + if(tableEntity.getPk() == null){ + tableEntity.setPk(tableEntity.getColumns().get(0)); + } + + //设置velocity资源加载器 + Properties prop = new Properties(); + prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); + Velocity.init(prop); + + //封装模板数据 + Map map = new HashMap<>(); + map.put("tableName", tableEntity.getTableName()); + map.put("comments", tableEntity.getComments()); + map.put("pk", tableEntity.getPk()); + map.put("className", tableEntity.getClassName()); + map.put("classname", tableEntity.getClassname()); + map.put("pathName", tableEntity.getClassname().toLowerCase()); + map.put("columns", tableEntity.getColumns()); + map.put("hasBigDecimal", hasBigDecimal); + map.put("version", config.getString("version" )); + map.put("package", config.getString("package" )); + map.put("moduleName", config.getString("moduleName" )); + map.put("author", config.getString("author")); + map.put("email", config.getString("email")); + map.put("datetime", DateUtils.format(new Date(), DateUtils.DATE_TIME_PATTERN)); + map.put("date", DateUtils.format(new Date(), DateUtils.DATE_PATTERN)); + + for(int i=0; i<=10; i++){ + map.put("id"+i, IdWorker.getId()); + } + + VelocityContext context = new VelocityContext(map); + + //获取模板列表 + List templates = getTemplates(); + for(String template : templates){ + //渲染模板 + StringWriter sw = new StringWriter(); + Template tpl = Velocity.getTemplate(template, "UTF-8"); + tpl.merge(context, sw); + + try { + //添加到zip + zip.putNextEntry(new ZipEntry(getFileName(template, tableEntity.getClassName(), config.getString("package"), config.getString("moduleName")))); + IOUtils.write(sw.toString(), zip, "UTF-8"); + IOUtils.closeQuietly(sw); + zip.closeEntry(); + } catch (IOException e) { + throw new RenException("渲染模板失败,表名:" + tableEntity.getTableName(), e); + } + } + } + + + /** + * 列名转换成Java属性名 + */ + public static String columnToJava(String columnName) { + return WordUtils.capitalizeFully(columnName, new char[]{'_'}).replace("_", ""); + } + + /** + * 表名转换成Java类名 + */ + public static String tableToJava(String tableName, String tablePrefix) { + if(StringUtils.isNotBlank(tablePrefix)){ + tableName = tableName.startsWith(tablePrefix) ? tableName.replaceFirst(tablePrefix, "") : tableName; + } + return columnToJava(tableName); + } + + /** + * 获取配置信息 + */ + public static Configuration getConfig(){ + try { + return new PropertiesConfiguration("generator.properties"); + } catch (ConfigurationException e) { + throw new RenException("获取配置文件失败,", e); + } + } + + /** + * 获取文件名 + */ + public static String getFileName(String template, String className, String packageName, String moduleName) { + String packagePath = "main" + File.separator + "java" + File.separator; + if (StringUtils.isNotBlank(packageName)) { + packagePath += packageName.replace(".", File.separator) + File.separator + "modules" + File.separator + moduleName + File.separator; + } + + if (template.contains("Entity.java.vm" )) { + return packagePath + "entity" + File.separator + className + "Entity.java"; + } + + if (template.contains("Excel.java.vm" )) { + return packagePath + "excel" + File.separator + className + "Excel.java"; + } + + if (template.contains("Dao.java.vm" )) { + return packagePath + "dao" + File.separator + className + "Dao.java"; + } + + if (template.contains("Service.java.vm" )) { + return packagePath + "service" + File.separator + className + "Service.java"; + } + + if (template.contains("ServiceImpl.java.vm" )) { + return packagePath + "service" + File.separator + "impl" + File.separator + className + "ServiceImpl.java"; + } + + if (template.contains("Controller.java.vm" )) { + return packagePath + "controller" + File.separator + className + "Controller.java"; + } + + if (template.contains("Dao.xml.vm" )) { + return "main" + File.separator + "resources" + File.separator + "mapper" + File.separator + moduleName + File.separator + className + "Dao.xml"; + } + + if (template.contains("DTO.java.vm" )) { + return packagePath + "dto" + File.separator + className + "DTO.java"; + } + + if (template.contains("index.vue.vm" )) { + return "vue" + File.separator + "views" + File.separator + "modules" + + File.separator + moduleName + File.separator + className.toLowerCase() + ".vue"; + } + + if (template.contains("add-or-update.vue.vm" )) { + return "vue" + File.separator + "views" + File.separator + "modules" + + File.separator + moduleName + File.separator + className.toLowerCase() + "-add-or-update.vue"; + } + + if (template.contains("mysql.vm" )) { + return className.toLowerCase() + ".mysql.sql"; + } + + if (template.contains("oracle.vm" )) { + return className.toLowerCase() + ".oracle.sql"; + } + + if (template.contains("sqlserver.vm" )) { + return className.toLowerCase() + ".sqlserver.sql"; + } + + if (template.contains("postgresql.vm" )) { + return className.toLowerCase() + ".postgresql.sql"; + } + + return null; + } +} diff --git a/renren-generator/src/main/java/io/renren/utils/IdWorker.java b/renren-generator/src/main/java/io/renren/utils/IdWorker.java new file mode 100644 index 0000000..ab649c3 --- /dev/null +++ b/renren-generator/src/main/java/io/renren/utils/IdWorker.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2011-2020, hubin (jobob@qq.com). + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package io.renren.utils; + +import java.util.UUID; +import java.util.concurrent.ThreadLocalRandom; + +/** + *

+ * 高效GUID产生算法(sequence),基于Snowflake实现64位自增ID算法。
+ * 优化开源项目 http://git.oschina.net/yu120/sequence + *

+ * + * @author hubin + * @since 2016-08-01 + */ +public class IdWorker { + + /** + * 主机和进程的机器码 + */ + private static Sequence WORKER = new Sequence(); + + public static long getId() { + return WORKER.nextId(); + } + + public static String getIdStr() { + return String.valueOf(WORKER.nextId()); + } + + /** + *

+ * 有参构造器 + *

+ * + * @param workerId 工作机器 ID + * @param datacenterId 序列号 + */ + public static void initSequence(long workerId, long datacenterId) { + WORKER = new Sequence(workerId, datacenterId); + } + + /** + *

+ * 使用ThreadLocalRandom获取UUID获取更优的效果 去掉"-" + *

+ */ + public static String get32UUID() { + ThreadLocalRandom random = ThreadLocalRandom.current(); + return new UUID(random.nextLong(), random.nextLong()).toString().replace(StringPool.DASH, StringPool.EMPTY); + } + +} diff --git a/renren-generator/src/main/java/io/renren/utils/PageUtils.java b/renren-generator/src/main/java/io/renren/utils/PageUtils.java new file mode 100644 index 0000000..d28ee9f --- /dev/null +++ b/renren-generator/src/main/java/io/renren/utils/PageUtils.java @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.utils; + +import java.io.Serializable; +import java.util.List; + +/** + * 分页工具类 + * + * @author Mark sunlightcs@gmail.com + */ +public class PageUtils implements Serializable { + private static final long serialVersionUID = 1L; + //总记录数 + private int totalCount; + //每页记录数 + private int pageSize; + //总页数 + private int totalPage; + //当前页数 + private int currPage; + //列表数据 + private List list; + + /** + * 分页 + * @param list 列表数据 + * @param totalCount 总记录数 + * @param pageSize 每页记录数 + * @param currPage 当前页数 + */ + public PageUtils(List list, int totalCount, int pageSize, int currPage) { + this.list = list; + this.totalCount = totalCount; + this.pageSize = pageSize; + this.currPage = currPage; + this.totalPage = (int)Math.ceil((double)totalCount/pageSize); + } + + public int getTotalCount() { + return totalCount; + } + + public void setTotalCount(int totalCount) { + this.totalCount = totalCount; + } + + public int getPageSize() { + return pageSize; + } + + public void setPageSize(int pageSize) { + this.pageSize = pageSize; + } + + public int getTotalPage() { + return totalPage; + } + + public void setTotalPage(int totalPage) { + this.totalPage = totalPage; + } + + public int getCurrPage() { + return currPage; + } + + public void setCurrPage(int currPage) { + this.currPage = currPage; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + +} diff --git a/renren-generator/src/main/java/io/renren/utils/Query.java b/renren-generator/src/main/java/io/renren/utils/Query.java new file mode 100644 index 0000000..a932f9b --- /dev/null +++ b/renren-generator/src/main/java/io/renren/utils/Query.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.utils; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * 查询参数 + * + * @author Mark sunlightcs@gmail.com + */ +public class Query extends LinkedHashMap { + private static final long serialVersionUID = 1L; + //当前页码 + private int page; + //每页条数 + private int limit; + + public Query(Map params){ + this.putAll(params); + + //分页参数 + this.page = Integer.parseInt(params.get("page").toString()); + this.limit = Integer.parseInt(params.get("limit").toString()); + this.put("offset", (page - 1) * limit); + this.put("page", page); + this.put("limit", limit); + } + + + public int getPage() { + return page; + } + + public void setPage(int page) { + this.page = page; + } + + public int getLimit() { + return limit; + } + + public void setLimit(int limit) { + this.limit = limit; + } +} diff --git a/renren-generator/src/main/java/io/renren/utils/R.java b/renren-generator/src/main/java/io/renren/utils/R.java new file mode 100644 index 0000000..5d8d90b --- /dev/null +++ b/renren-generator/src/main/java/io/renren/utils/R.java @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.utils; + +import java.util.HashMap; +import java.util.Map; + +/** + * 返回数据 + * + * @author Mark sunlightcs@gmail.com + */ +public class R extends HashMap { + private static final long serialVersionUID = 1L; + + public R() { + put("code", 0); + } + + public static R error() { + return error(500, "未知异常,请联系管理员"); + } + + public static R error(String msg) { + return error(500, msg); + } + + public static R error(int code, String msg) { + R r = new R(); + r.put("code", code); + r.put("msg", msg); + return r; + } + + public static R ok(String msg) { + R r = new R(); + r.put("msg", msg); + return r; + } + + public static R ok(Map map) { + R r = new R(); + r.putAll(map); + return r; + } + + public static R ok() { + return new R(); + } + + @Override + public R put(String key, Object value) { + super.put(key, value); + return this; + } +} diff --git a/renren-generator/src/main/java/io/renren/utils/RenException.java b/renren-generator/src/main/java/io/renren/utils/RenException.java new file mode 100644 index 0000000..0275a4a --- /dev/null +++ b/renren-generator/src/main/java/io/renren/utils/RenException.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.utils; + +/** + * 自定义异常 + * + * @author Mark sunlightcs@gmail.com + */ +public class RenException extends RuntimeException { + private static final long serialVersionUID = 1L; + + private String msg; + private int code = 500; + + public RenException(String msg) { + super(msg); + this.msg = msg; + } + + public RenException(String msg, Throwable e) { + super(msg, e); + this.msg = msg; + } + + public RenException(String msg, int code) { + super(msg); + this.msg = msg; + this.code = code; + } + + public RenException(String msg, int code, Throwable e) { + super(msg, e); + this.msg = msg; + this.code = code; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + +} diff --git a/renren-generator/src/main/java/io/renren/utils/RenExceptionHandler.java b/renren-generator/src/main/java/io/renren/utils/RenExceptionHandler.java new file mode 100644 index 0000000..27a3822 --- /dev/null +++ b/renren-generator/src/main/java/io/renren/utils/RenExceptionHandler.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2018 人人开源 All rights reserved. + * + * https://www.renren.io + * + * 版权所有,侵权必究! + */ + +package io.renren.utils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +/** + * 异常处理器 + * + * @author Mark sunlightcs@gmail.com + */ +@RestControllerAdvice +public class RenExceptionHandler { + private Logger logger = LoggerFactory.getLogger(getClass()); + + /** + * 处理自定义异常 + */ + @ExceptionHandler(RenException.class) + public R handleRenException(RenException e){ + R r = new R(); + r.put("code", e.getCode()); + r.put("msg", e.getMessage()); + + return r; + } + + @ExceptionHandler(Exception.class) + public R handleException(Exception e){ + logger.error(e.getMessage(), e); + return R.error(); + } +} diff --git a/renren-generator/src/main/java/io/renren/utils/Sequence.java b/renren-generator/src/main/java/io/renren/utils/Sequence.java new file mode 100644 index 0000000..21a3b9b --- /dev/null +++ b/renren-generator/src/main/java/io/renren/utils/Sequence.java @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2011-2020, hubin (jobob@qq.com). + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package io.renren.utils; + +import org.apache.commons.lang.StringUtils; +import org.apache.ibatis.logging.Log; +import org.apache.ibatis.logging.LogFactory; + +import java.lang.management.ManagementFactory; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.util.concurrent.ThreadLocalRandom; + +/** + *

+ * 分布式高效有序ID生产黑科技(sequence)
+ * 优化开源项目:http://git.oschina.net/yu120/sequence + *

+ * + * @author hubin + * @since 2016-08-18 + */ +public class Sequence { + + private static final Log logger = LogFactory.getLog(Sequence.class); + /** + * 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动) + */ + private final long twepoch = 1288834974657L; + /** + * 机器标识位数 + */ + private final long workerIdBits = 5L; + private final long datacenterIdBits = 5L; + private final long maxWorkerId = -1L ^ (-1L << workerIdBits); + private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); + /** + * 毫秒内自增位 + */ + private final long sequenceBits = 12L; + private final long workerIdShift = sequenceBits; + private final long datacenterIdShift = sequenceBits + workerIdBits; + /** + * 时间戳左移动位 + */ + private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; + private final long sequenceMask = -1L ^ (-1L << sequenceBits); + + private final long workerId; + + /** + * 数据标识 ID 部分 + */ + private final long datacenterId; + /** + * 并发控制 + */ + private long sequence = 0L; + /** + * 上次生产 ID 时间戳 + */ + private long lastTimestamp = -1L; + + public Sequence() { + this.datacenterId = getDatacenterId(maxDatacenterId); + this.workerId = getMaxWorkerId(datacenterId, maxWorkerId); + } + + /** + *

+ * 有参构造器 + *

+ * + * @param workerId 工作机器 ID + * @param datacenterId 序列号 + */ + public Sequence(long workerId, long datacenterId) { + Assert.isFalse(workerId > maxWorkerId || workerId < 0, + String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); + Assert.isFalse(datacenterId > maxDatacenterId || datacenterId < 0, + String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId)); + this.workerId = workerId; + this.datacenterId = datacenterId; + } + + /** + *

+ * 获取 maxWorkerId + *

+ */ + protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) { + StringBuilder mpid = new StringBuilder(); + mpid.append(datacenterId); + String name = ManagementFactory.getRuntimeMXBean().getName(); + if (StringUtils.isNotEmpty(name)) { + /* + * GET jvmPid + */ + mpid.append(name.split(StringPool.AT)[0]); + } + /* + * MAC + PID 的 hashcode 获取16个低位 + */ + return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1); + } + + /** + *

+ * 数据标识id部分 + *

+ */ + protected static long getDatacenterId(long maxDatacenterId) { + long id = 0L; + try { + InetAddress ip = InetAddress.getLocalHost(); + NetworkInterface network = NetworkInterface.getByInetAddress(ip); + if (network == null) { + id = 1L; + } else { + byte[] mac = network.getHardwareAddress(); + if (null != mac) { + id = ((0x000000FF & (long) mac[mac.length - 1]) | (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6; + id = id % (maxDatacenterId + 1); + } + } + } catch (Exception e) { + logger.warn(" getDatacenterId: " + e.getMessage()); + } + return id; + } + + /** + * 获取下一个ID + * + * @return + */ + public synchronized long nextId() { + long timestamp = timeGen(); + //闰秒 + if (timestamp < lastTimestamp) { + long offset = lastTimestamp - timestamp; + if (offset <= 5) { + try { + wait(offset << 1); + timestamp = timeGen(); + if (timestamp < lastTimestamp) { + throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", offset)); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } else { + throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", offset)); + } + } + + if (lastTimestamp == timestamp) { + // 相同毫秒内,序列号自增 + sequence = (sequence + 1) & sequenceMask; + if (sequence == 0) { + // 同一毫秒的序列数已经达到最大 + timestamp = tilNextMillis(lastTimestamp); + } + } else { + // 不同毫秒内,序列号置为 1 - 3 随机数 + sequence = ThreadLocalRandom.current().nextLong(1, 3); + } + + lastTimestamp = timestamp; + + // 时间戳部分 | 数据中心部分 | 机器标识部分 | 序列号部分 + return ((timestamp - twepoch) << timestampLeftShift) + | (datacenterId << datacenterIdShift) + | (workerId << workerIdShift) + | sequence; + } + + protected long tilNextMillis(long lastTimestamp) { + long timestamp = timeGen(); + while (timestamp <= lastTimestamp) { + timestamp = timeGen(); + } + return timestamp; + } + + protected long timeGen() { + return SystemClock.now(); + } + +} diff --git a/renren-generator/src/main/java/io/renren/utils/StringPool.java b/renren-generator/src/main/java/io/renren/utils/StringPool.java new file mode 100644 index 0000000..f8bcc27 --- /dev/null +++ b/renren-generator/src/main/java/io/renren/utils/StringPool.java @@ -0,0 +1,95 @@ +package io.renren.utils; + +/** + * Copy to jodd.util + *

+ * Pool of String constants to prevent repeating of + * hard-coded String literals in the code. + * Due to fact that these are public static final + * they will be inlined by java compiler and + * reference to this class will be dropped. + * There is no performance gain of using this pool. + * Read: http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.10.5 + *

    + *
  • Literal strings within the same class in the same package represent references to the same String object.
  • + *
  • Literal strings within different classes in the same package represent references to the same String object.
  • + *
  • Literal strings within different classes in different packages likewise represent references to the same String object.
  • + *
  • Strings computed by constant expressions are computed at compile time and then treated as if they were literals.
  • + *
  • Strings computed by concatenation at run time are newly created and therefore distinct.
  • + *
+ */ +public interface StringPool { + + String AMPERSAND = "&"; + String AND = "and"; + String AT = "@"; + String ASTERISK = "*"; + String STAR = ASTERISK; + String BACK_SLASH = "\\"; + String COLON = ":"; + String COMMA = ","; + String DASH = "-"; + String DOLLAR = "$"; + String DOT = "."; + String DOTDOT = ".."; + String DOT_CLASS = ".class"; + String DOT_JAVA = ".java"; + String DOT_XML = ".xml"; + String EMPTY = ""; + String EQUALS = "="; + String FALSE = "false"; + String SLASH = "/"; + String HASH = "#"; + String HAT = "^"; + String LEFT_BRACE = "{"; + String LEFT_BRACKET = "("; + String LEFT_CHEV = "<"; + String NEWLINE = "\n"; + String N = "n"; + String NO = "no"; + String NULL = "null"; + String OFF = "off"; + String ON = "on"; + String PERCENT = "%"; + String PIPE = "|"; + String PLUS = "+"; + String QUESTION_MARK = "?"; + String EXCLAMATION_MARK = "!"; + String QUOTE = "\""; + String RETURN = "\r"; + String TAB = "\t"; + String RIGHT_BRACE = "}"; + String RIGHT_BRACKET = ")"; + String RIGHT_CHEV = ">"; + String SEMICOLON = ";"; + String SINGLE_QUOTE = "'"; + String BACKTICK = "`"; + String SPACE = " "; + String TILDA = "~"; + String LEFT_SQ_BRACKET = "["; + String RIGHT_SQ_BRACKET = "]"; + String TRUE = "true"; + String UNDERSCORE = "_"; + String UTF_8 = "UTF-8"; + String US_ASCII = "US-ASCII"; + String ISO_8859_1 = "ISO-8859-1"; + String Y = "y"; + String YES = "yes"; + String ONE = "1"; + String ZERO = "0"; + String DOLLAR_LEFT_BRACE = "${"; + String HASH_LEFT_BRACE = "#{"; + String CRLF = "\r\n"; + + String HTML_NBSP = " "; + String HTML_AMP = "&"; + String HTML_QUOTE = """; + String HTML_LT = "<"; + String HTML_GT = ">"; + + // ---------------------------------------------------------------- array + + String[] EMPTY_ARRAY = new String[0]; + + byte[] BYTES_NEW_LINE = StringPool.NEWLINE.getBytes(); +} diff --git a/renren-generator/src/main/java/io/renren/utils/SystemClock.java b/renren-generator/src/main/java/io/renren/utils/SystemClock.java new file mode 100644 index 0000000..6d614a6 --- /dev/null +++ b/renren-generator/src/main/java/io/renren/utils/SystemClock.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2011-2020, hubin (jobob@qq.com). + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package io.renren.utils; + +import java.sql.Timestamp; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; + +/** + *

+ * 高并发场景下System.currentTimeMillis()的性能问题的优化 + *

+ *

+ * System.currentTimeMillis()的调用比new一个普通对象要耗时的多(具体耗时高出多少我还没测试过,有人说是100倍左右)
+ * System.currentTimeMillis()之所以慢是因为去跟系统打了一次交道
+ * 后台定时更新时钟,JVM退出时,线程自动回收
+ * 10亿:43410,206,210.72815533980582%
+ * 1亿:4699,29,162.0344827586207%
+ * 1000万:480,12,40.0%
+ * 100万:50,10,5.0%
+ *

+ * + * @author hubin + * @since 2016-08-01 + */ +public class SystemClock { + + private final long period; + private final AtomicLong now; + + private SystemClock(long period) { + this.period = period; + this.now = new AtomicLong(System.currentTimeMillis()); + scheduleClockUpdating(); + } + + private static SystemClock instance() { + return InstanceHolder.INSTANCE; + } + + public static long now() { + return instance().currentTimeMillis(); + } + + public static String nowDate() { + return new Timestamp(instance().currentTimeMillis()).toString(); + } + + private void scheduleClockUpdating() { + ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(runnable -> { + Thread thread = new Thread(runnable, "System Clock"); + thread.setDaemon(true); + return thread; + }); + scheduler.scheduleAtFixedRate(() -> now.set(System.currentTimeMillis()), period, period, TimeUnit.MILLISECONDS); + } + + private long currentTimeMillis() { + return now.get(); + } + + private static class InstanceHolder { + public static final SystemClock INSTANCE = new SystemClock(1); + } +}