first commit
This commit is contained in:
16
renren-dynamic-datasource/pom.xml
Normal file
16
renren-dynamic-datasource/pom.xml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<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">
|
||||||
|
<parent>
|
||||||
|
<groupId>io.renren</groupId>
|
||||||
|
<artifactId>renren-security</artifactId>
|
||||||
|
<version>5.2.0</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>renren-dynamic-datasource</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<description>多数据源</description>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<finalName>${project.artifactId}</finalName>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -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 "";
|
||||||
|
}
|
||||||
@@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<Deque<String>> 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<String> deque = CONTEXT_HOLDER.get();
|
||||||
|
deque.poll();
|
||||||
|
if (deque.isEmpty()) {
|
||||||
|
CONTEXT_HOLDER.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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<Object, Object> getDynamicDataSource(){
|
||||||
|
Map<String, DataSourceProperties> dataSourcePropertiesMap = properties.getDatasource();
|
||||||
|
Map<Object, Object> targetDataSources = new HashMap<>(dataSourcePropertiesMap.size());
|
||||||
|
dataSourcePropertiesMap.forEach((k, v) -> {
|
||||||
|
DruidDataSource druidDataSource = DynamicDataSourceFactory.buildDruidDataSource(v);
|
||||||
|
targetDataSources.put(k, druidDataSource);
|
||||||
|
});
|
||||||
|
|
||||||
|
return targetDataSources;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<String, DataSourceProperties> datasource = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
public Map<String, DataSourceProperties> getDatasource() {
|
||||||
|
return datasource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDatasource(Map<String, DataSourceProperties> datasource) {
|
||||||
|
this.datasource = datasource;
|
||||||
|
}
|
||||||
|
}
|
||||||
135
renren-generator/pom.xml
Normal file
135
renren-generator/pom.xml
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
<?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>io.renren</groupId>
|
||||||
|
<artifactId>renren-generator</artifactId>
|
||||||
|
<version>5.2.0</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<description>renren-generator</description>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>2.7.5</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
|
<java.version>1.8</java.version>
|
||||||
|
<mybatis.spring.boot.version>2.2.2</mybatis.spring.boot.version>
|
||||||
|
<pagehelper.spring.boot.version>1.4.2</pagehelper.spring.boot.version>
|
||||||
|
<druid.version>1.2.14</druid.version>
|
||||||
|
<commons.lang.version>2.6</commons.lang.version>
|
||||||
|
<commons.io.version>2.11.0</commons.io.version>
|
||||||
|
<commons.configuration.version>1.10</commons.configuration.version>
|
||||||
|
<velocity.version>1.7</velocity.version>
|
||||||
|
<mssql.version>4.0</mssql.version>
|
||||||
|
<oracle.version>11.2.0.3</oracle.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mybatis.spring.boot</groupId>
|
||||||
|
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||||
|
<version>${mybatis.spring.boot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.pagehelper</groupId>
|
||||||
|
<artifactId>pagehelper-spring-boot-starter</artifactId>
|
||||||
|
<version>${pagehelper.spring.boot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>druid</artifactId>
|
||||||
|
<version>${druid.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-lang</groupId>
|
||||||
|
<artifactId>commons-lang</artifactId>
|
||||||
|
<version>${commons.lang.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-io</groupId>
|
||||||
|
<artifactId>commons-io</artifactId>
|
||||||
|
<version>${commons.io.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-configuration</groupId>
|
||||||
|
<artifactId>commons-configuration</artifactId>
|
||||||
|
<version>${commons.configuration.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<artifactId>velocity</artifactId>
|
||||||
|
<groupId>org.apache.velocity</groupId>
|
||||||
|
<version>${velocity.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- mysql驱动 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>mysql</groupId>
|
||||||
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- oracle驱动 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.oracle</groupId>
|
||||||
|
<artifactId>ojdbc6</artifactId>
|
||||||
|
<version>${oracle.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- sqlserver驱动 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.microsoft.sqlserver</groupId>
|
||||||
|
<artifactId>sqljdbc4</artifactId>
|
||||||
|
<version>${mssql.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- postgresql驱动 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.postgresql</groupId>
|
||||||
|
<artifactId>postgresql</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<!-- 阿里云maven仓库 -->
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>public</id>
|
||||||
|
<name>aliyun nexus</name>
|
||||||
|
<url>https://maven.aliyun.com/repository/public/</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</releases>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
<pluginRepositories>
|
||||||
|
<pluginRepository>
|
||||||
|
<id>public</id>
|
||||||
|
<name>aliyun nexus</name>
|
||||||
|
<url>https://maven.aliyun.com/repository/public/</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</releases>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</pluginRepository>
|
||||||
|
</pluginRepositories>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<String, Object> 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<Map<String, Object>> queryList(Map<String, Object> map);
|
||||||
|
|
||||||
|
Map<String, String> queryTable(String tableName);
|
||||||
|
|
||||||
|
List<Map<String, String>> queryColumns(String tableName);
|
||||||
|
}
|
||||||
@@ -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 {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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 {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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 {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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 {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<ColumnEntity> 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<ColumnEntity> getColumns() {
|
||||||
|
return columns;
|
||||||
|
}
|
||||||
|
public void setColumns(List<ColumnEntity> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<Map<String, Object>> list = generatorDao.queryList(query);
|
||||||
|
|
||||||
|
return new PageUtils(list, (int)page.getTotal(), query.getLimit(), query.getPage());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> queryTable(String tableName) {
|
||||||
|
return generatorDao.queryTable(tableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Map<String, String>> 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<String, String> table = queryTable(tableName);
|
||||||
|
//查询列信息
|
||||||
|
List<Map<String, String>> columns = queryColumns(tableName);
|
||||||
|
//生成代码
|
||||||
|
GenUtils.generatorCode(table, columns, zip);
|
||||||
|
}
|
||||||
|
IOUtils.closeQuietly(zip);
|
||||||
|
return outputStream.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
77
renren-generator/src/main/java/io/renren/utils/Assert.java
Normal file
77
renren-generator/src/main/java/io/renren/utils/Assert.java
Normal file
@@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 断言类
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
254
renren-generator/src/main/java/io/renren/utils/GenUtils.java
Normal file
254
renren-generator/src/main/java/io/renren/utils/GenUtils.java
Normal file
@@ -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<String> getTemplates(){
|
||||||
|
List<String> templates = new ArrayList<String>();
|
||||||
|
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<String, String> table,
|
||||||
|
List<Map<String, String>> 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<ColumnEntity> columnsList = new ArrayList<>();
|
||||||
|
for(Map<String, String> 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<String, Object> 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<String> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
67
renren-generator/src/main/java/io/renren/utils/IdWorker.java
Normal file
67
renren-generator/src/main/java/io/renren/utils/IdWorker.java
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011-2020, hubin (jobob@qq.com).
|
||||||
|
* <p>
|
||||||
|
* 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
|
||||||
|
* <p>
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <p>
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 高效GUID产生算法(sequence),基于Snowflake实现64位自增ID算法。 <br>
|
||||||
|
* 优化开源项目 http://git.oschina.net/yu120/sequence
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @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());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 有参构造器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param workerId 工作机器 ID
|
||||||
|
* @param datacenterId 序列号
|
||||||
|
*/
|
||||||
|
public static void initSequence(long workerId, long datacenterId) {
|
||||||
|
WORKER = new Sequence(workerId, datacenterId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 使用ThreadLocalRandom获取UUID获取更优的效果 去掉"-"
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public static String get32UUID() {
|
||||||
|
ThreadLocalRandom random = ThreadLocalRandom.current();
|
||||||
|
return new UUID(random.nextLong(), random.nextLong()).toString().replace(StringPool.DASH, StringPool.EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
53
renren-generator/src/main/java/io/renren/utils/Query.java
Normal file
53
renren-generator/src/main/java/io/renren/utils/Query.java
Normal file
@@ -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<String, Object> {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
//当前页码
|
||||||
|
private int page;
|
||||||
|
//每页条数
|
||||||
|
private int limit;
|
||||||
|
|
||||||
|
public Query(Map<String, Object> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
62
renren-generator/src/main/java/io/renren/utils/R.java
Normal file
62
renren-generator/src/main/java/io/renren/utils/R.java
Normal file
@@ -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<String, Object> {
|
||||||
|
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<String, Object> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
203
renren-generator/src/main/java/io/renren/utils/Sequence.java
Normal file
203
renren-generator/src/main/java/io/renren/utils/Sequence.java
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011-2020, hubin (jobob@qq.com).
|
||||||
|
* <p>
|
||||||
|
* 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
|
||||||
|
* <p>
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <p>
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 分布式高效有序ID生产黑科技(sequence) <br>
|
||||||
|
* 优化开源项目:http://git.oschina.net/yu120/sequence
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 有参构造器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 获取 maxWorkerId
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 数据标识id部分
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
package io.renren.utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy to jodd.util
|
||||||
|
* <p>
|
||||||
|
* Pool of <code>String</code> constants to prevent repeating of
|
||||||
|
* hard-coded <code>String</code> literals in the code.
|
||||||
|
* Due to fact that these are <code>public static final</code>
|
||||||
|
* they will be inlined by java compiler and
|
||||||
|
* reference to this class will be dropped.
|
||||||
|
* There is <b>no</b> performance gain of using this pool.
|
||||||
|
* Read: http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.10.5
|
||||||
|
* <ul>
|
||||||
|
* <li>Literal strings within the same class in the same package represent references to the same <code>String</code> object.</li>
|
||||||
|
* <li>Literal strings within different classes in the same package represent references to the same <code>String</code> object.</li>
|
||||||
|
* <li>Literal strings within different classes in different packages likewise represent references to the same <code>String</code> object.</li>
|
||||||
|
* <li>Strings computed by constant expressions are computed at compile time and then treated as if they were literals.</li>
|
||||||
|
* <li>Strings computed by concatenation at run time are newly created and therefore distinct.</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
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();
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011-2020, hubin (jobob@qq.com).
|
||||||
|
* <p>
|
||||||
|
* 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
|
||||||
|
* <p>
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <p>
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 高并发场景下System.currentTimeMillis()的性能问题的优化
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* System.currentTimeMillis()的调用比new一个普通对象要耗时的多(具体耗时高出多少我还没测试过,有人说是100倍左右)<br>
|
||||||
|
* System.currentTimeMillis()之所以慢是因为去跟系统打了一次交道<br>
|
||||||
|
* 后台定时更新时钟,JVM退出时,线程自动回收<br>
|
||||||
|
* 10亿:43410,206,210.72815533980582%<br>
|
||||||
|
* 1亿:4699,29,162.0344827586207%<br>
|
||||||
|
* 1000万:480,12,40.0%<br>
|
||||||
|
* 100万:50,10,5.0%<br>
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @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);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user