com.chushang
chushang-common-log
diff --git a/chushang-common/chushang-common-mybatis-plugin/pom.xml b/chushang-common/chushang-common-mybatis-plugin/pom.xml
new file mode 100644
index 0000000..e81ab08
--- /dev/null
+++ b/chushang-common/chushang-common-mybatis-plugin/pom.xml
@@ -0,0 +1,20 @@
+
+
+
+ chushang-common
+ com.chushang
+ 1.0.0
+
+ 4.0.0
+
+ chushang-common-mybatis-plugin
+
+
+ com.chushang
+ chushang-common-mybatis
+
+
+
+
diff --git a/chushang-common/chushang-common-mybatis-plugin/src/main/java/com/chushang/common/mybatis/PluginAutoConfiguration.java b/chushang-common/chushang-common-mybatis-plugin/src/main/java/com/chushang/common/mybatis/PluginAutoConfiguration.java
new file mode 100644
index 0000000..5e4b17b
--- /dev/null
+++ b/chushang-common/chushang-common-mybatis-plugin/src/main/java/com/chushang/common/mybatis/PluginAutoConfiguration.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2020 pig4cloud Authors. All Rights Reserved.
+ *
+ * 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 com.chushang.common.mybatis;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties;
+import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import com.chushang.common.mybatis.config.MybatisPlusMapperRefresh;
+import com.chushang.common.mybatis.config.MybatisPlusMetaObjectHandler;
+import com.chushang.common.mybatis.resolver.SqlFilterArgumentResolver;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.Resource;
+import org.springframework.stereotype.Component;
+import org.springframework.web.method.support.HandlerMethodArgumentResolver;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import java.util.Arrays;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author lengleng
+ * @date 2020-03-14
+ *
+ * mybatis plus 统一配置
+ */
+@Configuration(proxyBeanMethods = false)
+public class PluginAutoConfiguration {
+
+ @Autowired
+ MybatisPlusProperties mybatisPlusProperties;
+ @Value("${mybatis-plus.global-config.refresh.enable:false}")
+ private boolean refreshMapper;
+
+ @Bean
+ public MybatisPlusMapperRefresh mybatisPlusMapperRefresh(ApplicationContext applicationContext, SqlSessionFactory sqlSessionFactory){
+ Set mapperLocations = new LinkedHashSet<>();
+ for (String xx : mybatisPlusProperties.getMapperLocations()) {
+ try {
+ mapperLocations.addAll(Arrays.asList(applicationContext.getResources(xx)));
+ } catch (Exception ignored) {
+ }
+ }
+ return new MybatisPlusMapperRefresh(mapperLocations.toArray(new Resource[mapperLocations.size()]),
+ sqlSessionFactory,
+ 10,
+ 5, refreshMapper);
+ }
+
+}
diff --git a/chushang-common/chushang-common-mybatis-plugin/src/main/java/com/chushang/common/mybatis/config/MybatisPlusMapperRefresh.java b/chushang-common/chushang-common-mybatis-plugin/src/main/java/com/chushang/common/mybatis/config/MybatisPlusMapperRefresh.java
new file mode 100644
index 0000000..ecdb897
--- /dev/null
+++ b/chushang-common/chushang-common-mybatis-plugin/src/main/java/com/chushang/common/mybatis/config/MybatisPlusMapperRefresh.java
@@ -0,0 +1,275 @@
+package com.chushang.common.mybatis.config;
+
+import com.baomidou.mybatisplus.core.config.GlobalConfig;
+import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
+import com.baomidou.mybatisplus.core.toolkit.SystemClock;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.ibatis.binding.MapperRegistry;
+import org.apache.ibatis.builder.xml.XMLMapperBuilder;
+import org.apache.ibatis.builder.xml.XMLMapperEntityResolver;
+import org.apache.ibatis.executor.ErrorContext;
+import org.apache.ibatis.executor.keygen.SelectKeyGenerator;
+import org.apache.ibatis.io.Resources;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.parsing.XNode;
+import org.apache.ibatis.parsing.XPathParser;
+import org.apache.ibatis.session.Configuration;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.UrlResource;
+import org.springframework.util.ResourceUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.*;
+
+import static java.lang.Thread.sleep;
+
+/**
+ * Mybatis 映射文件热加载(发生变动后自动重新加载).
+ * 方便开发时使用,不用每次修改xml文件后都要去重启应用.
+ */
+@Slf4j
+public class MybatisPlusMapperRefresh implements Runnable {
+ /**
+ * 记录jar包存在的mapper
+ */
+ private static final Map> jarMapper = new HashMap<>();
+ private final SqlSessionFactory sqlSessionFactory;
+ private final Resource[] mapperLocations;
+ private volatile Long beforeTime = 0L;
+ private Configuration configuration;
+ /**
+ * xml文件目录
+ */
+ private Set fileSet;
+ /**
+ * 延迟加载时间
+ */
+ private int delaySeconds = 10;
+ /**
+ * 刷新间隔时间
+ */
+ private int sleepSeconds = 20;
+ private boolean refreshMapper;
+
+ public MybatisPlusMapperRefresh(Resource[] mapperLocations, SqlSessionFactory sqlSessionFactory, int delaySeconds,
+ int sleepSeconds, boolean refreshMapper) {
+ this.mapperLocations = mapperLocations.clone();
+ this.sqlSessionFactory = sqlSessionFactory;
+ this.delaySeconds = delaySeconds;
+ this.sleepSeconds = sleepSeconds;
+ this.configuration = sqlSessionFactory.getConfiguration();
+ this.refreshMapper = refreshMapper;
+ this.run();
+ }
+
+ public MybatisPlusMapperRefresh(Resource[] mapperLocations, SqlSessionFactory sqlSessionFactory) {
+ this.mapperLocations = mapperLocations.clone();
+ this.sqlSessionFactory = sqlSessionFactory;
+ this.configuration = sqlSessionFactory.getConfiguration();
+ this.run();
+ }
+
+ @Override
+ public void run() {
+ /*
+ */
+ if (refreshMapper) {
+ beforeTime = SystemClock.now();
+ final MybatisPlusMapperRefresh runnable = this;
+ new Thread(() -> {
+ if (fileSet == null) {
+ fileSet = new HashSet<>();
+ if (mapperLocations != null) {
+ for (Resource mapperLocation : mapperLocations) {
+ try {
+ if (ResourceUtils.isJarURL(mapperLocation.getURL())) {
+ String key = new UrlResource(
+ ResourceUtils.extractJarFileURL(mapperLocation.getURL())).getFile()
+ .getPath();
+ fileSet.add(key);
+ if (jarMapper.get(key) != null) {
+ jarMapper.get(key).add(mapperLocation);
+ } else {
+ List resourcesList = new ArrayList<>();
+ resourcesList.add(mapperLocation);
+ jarMapper.put(key, resourcesList);
+ }
+ } else {
+ fileSet.add(mapperLocation.getFile().getPath());
+ }
+ } catch (IOException ioException) {
+ ioException.printStackTrace();
+ }
+ }
+ }
+ }
+ try {
+ sleep(delaySeconds * 1000L);
+ } catch (InterruptedException interruptedException) {
+ interruptedException.printStackTrace();
+ }
+ do {
+ try {
+ for (String filePath : fileSet) {
+ File file = new File(filePath);
+ if (file.isFile() && file.lastModified() > beforeTime) {
+ // 记录上次重新加载时间防止重复加载已经重载的文件
+ beforeTime = file.lastModified();
+ List removeList = jarMapper.get(filePath);
+ if (removeList != null && !removeList.isEmpty()) {
+ for (Resource resource : removeList) {
+ runnable.refresh(resource);
+ }
+ } else {
+ runnable.refresh(new FileSystemResource(file));
+ }
+ }
+ }
+ } catch (Exception exception) {
+ exception.printStackTrace();
+ }
+ try {
+ sleep(sleepSeconds * 1000L);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ } while (true);
+ }, "mybatis-plus MapperRefresh").start();
+ }
+ }
+
+ /**
+ * 刷新mapper
+ *
+ * @throws Exception
+ */
+ @SuppressWarnings("rawtypes")
+ private void refresh(Resource resource)
+ throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
+ this.configuration = sqlSessionFactory.getConfiguration();
+ boolean isSupper = configuration.getClass().getSuperclass() == Configuration.class;
+ try {
+ Field loadedResourcesField = isSupper
+ ? configuration.getClass().getSuperclass().getDeclaredField("loadedResources")
+ : configuration.getClass().getDeclaredField("loadedResources");
+ loadedResourcesField.setAccessible(true);
+ Set loadedResourcesSet = ((Set) loadedResourcesField.get(configuration));
+ XPathParser xPathParser = new XPathParser(resource.getInputStream(), true, configuration.getVariables(),
+ new XMLMapperEntityResolver());
+ XNode context = xPathParser.evalNode("/mapper");
+ String namespace = context.getStringAttribute("namespace");
+ Field field = MapperRegistry.class.getDeclaredField("knownMappers");
+ field.setAccessible(true);
+ Map mapConfig = (Map) field.get(configuration.getMapperRegistry());
+
+ mapConfig.remove(Resources.classForName(namespace));
+ loadedResourcesSet.remove(resource.toString());
+ configuration.getCacheNames().remove(namespace);
+
+ cleanParameterMap(context.evalNodes("/mapper/parameterMap"), namespace);
+ cleanResultMap(context.evalNodes("/mapper/resultMap"), namespace);
+ cleanKeyGenerators(context.evalNodes("insert|update|select|delete"), namespace);
+ cleanSqlElement(context.evalNodes("/mapper/sql"), namespace);
+ XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(resource.getInputStream(),
+ sqlSessionFactory.getConfiguration(), resource.toString(),
+ sqlSessionFactory.getConfiguration().getSqlFragments());
+ xmlMapperBuilder.parse();
+ log.debug("refresh: '" + resource + "', success!");
+ } catch (IOException e) {
+ log.error("Refresh IOException :" + e.getMessage());
+ } finally {
+ ErrorContext.instance().reset();
+ }
+ }
+
+ /**
+ * 清理parameterMap
+ *
+ * @param list
+ * @param namespace
+ */
+ private void cleanParameterMap(List list, String namespace) {
+ for (XNode parameterMapNode : list) {
+ String id = parameterMapNode.getStringAttribute("id");
+ configuration.getParameterMaps().remove(String.format("%s.%s", namespace, id));
+ }
+ }
+
+ /**
+ * 清理resultMap
+ *
+ * @param list
+ * @param namespace
+ */
+ private void cleanResultMap(List list, String namespace) {
+ for (XNode resultMapNode : list) {
+ String id = resultMapNode.getStringAttribute("id", resultMapNode.getValueBasedIdentifier());
+ configuration.getResultMapNames().remove(id);
+ configuration.getResultMapNames().remove(namespace + "." + id);
+ clearResultMap(resultMapNode, namespace);
+ }
+ }
+
+ private void clearResultMap(XNode xNode, String namespace) {
+ for (XNode resultChild : xNode.getChildren()) {
+ if ("association".equals(resultChild.getName()) || "collection".equals(resultChild.getName())
+ || "case".equals(resultChild.getName())) {
+ if (resultChild.getStringAttribute("select") == null) {
+ configuration.getResultMapNames()
+ .remove(resultChild.getStringAttribute("id", resultChild.getValueBasedIdentifier()));
+ configuration.getResultMapNames().remove(namespace + "."
+ + resultChild.getStringAttribute("id", resultChild.getValueBasedIdentifier()));
+ if (resultChild.getChildren() != null && !resultChild.getChildren().isEmpty()) {
+ clearResultMap(resultChild, namespace);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * 清理selectKey
+ *
+ * @param list
+ * @param namespace
+ */
+ private void cleanKeyGenerators(List list, String namespace) {
+ for (XNode context : list) {
+ String id = context.getStringAttribute("id");
+ configuration.getKeyGeneratorNames().remove(id + SelectKeyGenerator.SELECT_KEY_SUFFIX);
+ configuration.getKeyGeneratorNames().remove(namespace + "." + id + SelectKeyGenerator.SELECT_KEY_SUFFIX);
+
+ Collection mappedStatements = configuration.getMappedStatements();
+ List objects = new ArrayList<>();
+ for (Object object : mappedStatements) {
+ if (object instanceof MappedStatement) {
+ MappedStatement mappedStatement = (MappedStatement) object;
+ if (mappedStatement.getId().equals(namespace + "." + id)) {
+ objects.add(mappedStatement);
+ }
+ }
+ }
+ mappedStatements.removeAll(objects);
+ }
+ }
+
+ /**
+ * 清理sql节点缓存
+ *
+ * @param list
+ * @param namespace
+ */
+ private void cleanSqlElement(List list, String namespace) {
+ for (XNode context : list) {
+ String id = context.getStringAttribute("id");
+ configuration.getSqlFragments().remove(id);
+ configuration.getSqlFragments().remove(namespace + "." + id);
+ }
+ }
+}
+
+
diff --git a/chushang-common/chushang-common-mybatis-plugin/src/main/resources/META-INF/spring.factories b/chushang-common/chushang-common-mybatis-plugin/src/main/resources/META-INF/spring.factories
new file mode 100644
index 0000000..928359b
--- /dev/null
+++ b/chushang-common/chushang-common-mybatis-plugin/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+ com.chushang.common.mybatis.PluginAutoConfiguration
diff --git a/chushang-common/chushang-common-security/src/main/java/com/chushang/security/service/TokenService.java b/chushang-common/chushang-common-security/src/main/java/com/chushang/security/service/TokenService.java
index ea3ea8f..adbed13 100644
--- a/chushang-common/chushang-common-security/src/main/java/com/chushang/security/service/TokenService.java
+++ b/chushang-common/chushang-common-security/src/main/java/com/chushang/security/service/TokenService.java
@@ -145,10 +145,7 @@ public class TokenService
long currentTime = System.currentTimeMillis();
if (expireTime - currentTime <= 15 * 24 * MILLIS_HOUR)
{
- long start = System.currentTimeMillis();
refreshToken(loginUser);
- long end = System.currentTimeMillis();
- log.info("TokenService verifyToken {}", end - start);
}
}
@@ -160,7 +157,8 @@ public class TokenService
public void refreshToken(LoginUser loginUser)
{
long expireTime = 15 * 24 * MILLIS_HOUR ;
- log.info("expireTime : {}", expireTime);
+ if (log.isDebugEnabled())
+ log.debug("TokenService refreshToken");
loginUser.setLoginTime(System.currentTimeMillis());
loginUser.setExpireTime(loginUser.getLoginTime() + expireTime);
// 根据uuid将loginUser缓存
diff --git a/chushang-common/pom.xml b/chushang-common/pom.xml
index 15cc901..af04778 100644
--- a/chushang-common/pom.xml
+++ b/chushang-common/pom.xml
@@ -25,6 +25,7 @@
chushang-common-mail
chushang-common-mongo
chushang-common-mybatis
+ chushang-common-mybatis-plugin
chushang-common-redis
chushang-common-security
diff --git a/chushang-modules/chushang-module-auth/auth-service/pom.xml b/chushang-modules/chushang-module-auth/auth-service/pom.xml
index 0fdb3fc..5d3d547 100644
--- a/chushang-modules/chushang-module-auth/auth-service/pom.xml
+++ b/chushang-modules/chushang-module-auth/auth-service/pom.xml
@@ -32,6 +32,16 @@
com.chushang
system-feign
1.0.0
+
+
+ com.chushang
+ chushang-common-mybatis-plugin
+
+
+
+