🎉 2.6.0.RELEASE 升级Hoxton.SR1 适配最新架构

This commit is contained in:
smallchill 2019-12-22 23:43:17 +08:00
parent 457ab4088f
commit 181063c231
39 changed files with 419 additions and 182 deletions

View File

@ -1,7 +1,7 @@
<p align="center"> <p align="center">
<img src="https://img.shields.io/badge/license-LGPL%20v3-blue.svg" alt="Build Status"> <img src="https://img.shields.io/badge/license-LGPL%20v3-blue.svg" alt="Build Status">
<img src="https://img.shields.io/badge/Spring%20Cloud-Greenwich.SR3-blue.svg" alt="Coverage Status"> <img src="https://img.shields.io/badge/Spring%20Cloud-Hoxton.SR1-blue.svg" alt="Coverage Status">
<img src="https://img.shields.io/badge/Spring%20Boot-2.1.9.RELEASE-blue.svg" alt="Downloads"> <img src="https://img.shields.io/badge/Spring%20Boot-2.2.2.RELEASE-blue.svg" alt="Downloads">
</p> </p>
## SpringBlade微服务开发平台 ## SpringBlade微服务开发平台

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>org.springblade</groupId> <groupId>org.springblade</groupId>
<artifactId>blade-tool</artifactId> <artifactId>blade-tool</artifactId>
<version>2.5.4</version> <version>2.6.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -62,28 +62,6 @@
<artifactId>blade-core-swagger</artifactId> <artifactId>blade-core-swagger</artifactId>
<version>${blade.tool.version}</version> <version>${blade.tool.version}</version>
</dependency> </dependency>
<!--Swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
<exclusions>
<exclusion>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>${swagger.models.version}</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>${swagger.bootstrapui.version}</version>
</dependency>
<!--Redis--> <!--Redis-->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>

View File

@ -16,13 +16,12 @@
package org.springblade.core.boot.config; package org.springblade.core.boot.config;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor;
import org.mybatis.spring.annotation.MapperScan; import org.mybatis.spring.annotation.MapperScan;
import org.springblade.core.launch.constant.AppConstant; import org.springblade.core.mp.plugins.SqlLogInterceptor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
/** /**
* mybatisplus 配置 * mybatisplus 配置
@ -40,14 +39,12 @@ public class MybatisPlusConfiguration {
} }
/** /**
* SQL执行效率插件 * sql 日志
*
* @return PerformanceInterceptor
*/ */
@Bean @Bean
@Profile({AppConstant.DEV_CODE, AppConstant.TEST_CODE}) @ConditionalOnProperty(value = "blade.mybatis-plus.sql-log.enable", matchIfMissing = true)
public PerformanceInterceptor performanceInterceptor() { public SqlLogInterceptor sqlLogInterceptor() {
return new PerformanceInterceptor(); return new SqlLogInterceptor();
} }
} }

View File

@ -41,7 +41,7 @@ public class BladeTenantHandler implements TenantHandler {
* @return 租户ID * @return 租户ID
*/ */
@Override @Override
public Expression getTenantId() { public Expression getTenantId(boolean where) {
return new StringValue(Func.toStr(SecureUtil.getTenantId(), TenantConstant.DEFAULT_TENANT_ID)); return new StringValue(Func.toStr(SecureUtil.getTenantId(), TenantConstant.DEFAULT_TENANT_ID));
} }

View File

@ -100,7 +100,7 @@ mybatis-plus:
swagger: swagger:
title: SpringBlade 接口文档系统 title: SpringBlade 接口文档系统
description: SpringBlade 接口文档系统 description: SpringBlade 接口文档系统
version: 2.5.4 version: 2.6.0
license: Powered By SpringBlade license: Powered By SpringBlade
licenseUrl: https://bladex.vip licenseUrl: https://bladex.vip
terms-of-service-url: https://bladex.vip terms-of-service-url: https://bladex.vip

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>blade-tool</artifactId> <artifactId>blade-tool</artifactId>
<groupId>org.springblade</groupId> <groupId>org.springblade</groupId>
<version>2.5.4</version> <version>2.6.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>blade-tool</artifactId> <artifactId>blade-tool</artifactId>
<groupId>org.springblade</groupId> <groupId>org.springblade</groupId>
<version>2.5.4</version> <version>2.6.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -16,9 +16,9 @@
package $!{package.Controller}; package $!{package.Controller};
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperationSupport;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiParam;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import javax.validation.Valid; import javax.validation.Valid;

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>blade-tool</artifactId> <artifactId>blade-tool</artifactId>
<groupId>org.springblade</groupId> <groupId>org.springblade</groupId>
<version>2.5.4</version> <version>2.6.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -25,7 +25,7 @@ public interface AppConstant {
/** /**
* 应用版本 * 应用版本
*/ */
String APPLICATION_VERSION = "2.5.4"; String APPLICATION_VERSION = "2.6.0";
/** /**
* 基础包 * 基础包

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>blade-tool</artifactId> <artifactId>blade-tool</artifactId>
<groupId>org.springblade</groupId> <groupId>org.springblade</groupId>
<version>2.5.4</version> <version>2.6.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>blade-tool</artifactId> <artifactId>blade-tool</artifactId>
<groupId>org.springblade</groupId> <groupId>org.springblade</groupId>
<version>2.5.4</version> <version>2.6.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -32,7 +32,7 @@ public interface BaseService<T> extends IService<T> {
* 逻辑删除 * 逻辑删除
* *
* @param ids id集合(逗号分隔) * @param ids id集合(逗号分隔)
* @return * @return boolean
*/ */
boolean deleteLogic(@NotEmpty List<Integer> ids); boolean deleteLogic(@NotEmpty List<Integer> ids);

View File

@ -24,8 +24,6 @@ import org.springblade.core.tool.utils.DateUtil;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotEmpty;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -39,14 +37,6 @@ import java.util.List;
@Validated @Validated
public class BaseServiceImpl<M extends BaseMapper<T>, T extends BaseEntity> extends ServiceImpl<M, T> implements BaseService<T> { public class BaseServiceImpl<M extends BaseMapper<T>, T extends BaseEntity> extends ServiceImpl<M, T> implements BaseService<T> {
private Class<T> modelClass;
@SuppressWarnings("unchecked")
public BaseServiceImpl() {
Type type = this.getClass().getGenericSuperclass();
this.modelClass = (Class<T>) ((ParameterizedType) type).getActualTypeArguments()[1];
}
@Override @Override
public boolean save(T entity) { public boolean save(T entity) {
BladeUser user = SecureUtil.getUser(); BladeUser user = SecureUtil.getUser();

View File

@ -18,6 +18,7 @@ package org.springblade.core.mp.base;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode;
/** /**
* 租户基础实体类 * 租户基础实体类
@ -25,6 +26,7 @@ import lombok.Data;
* @author Chill * @author Chill
*/ */
@Data @Data
@EqualsAndHashCode(callSuper = true)
public class TenantEntity extends BaseEntity { public class TenantEntity extends BaseEntity {
/** /**

View File

@ -0,0 +1,185 @@
package org.springblade.core.mp.plugins;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.SystemClock;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.session.ResultHandler;
import org.springblade.core.tool.utils.StringUtil;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Statement;
import java.util.*;
/**
* 用于输出每条 SQL 语句及其执行时间
*
* @author hubin nieqiurong TaoYu
* @since 2016-07-07
*/
@Slf4j
@Intercepts({
@Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class}),
@Signature(type = StatementHandler.class, method = "update", args = Statement.class),
@Signature(type = StatementHandler.class, method = "batch", args = Statement.class)
})
public class SqlLogInterceptor implements Interceptor {
private static final String DRUID_POOLED_PREPARED_STATEMENT = "com.alibaba.druid.pool.DruidPooledPreparedStatement";
private static final String T4C_PREPARED_STATEMENT = "oracle.jdbc.driver.T4CPreparedStatement";
private static final String ORACLE_PREPARED_STATEMENT_WRAPPER = "oracle.jdbc.driver.OraclePreparedStatementWrapper";
private Method oracleGetOriginalSqlMethod;
private Method druidGetSqlMethod;
@Override
public Object intercept(Invocation invocation) throws Throwable {
Statement statement;
Object firstArg = invocation.getArgs()[0];
if (Proxy.isProxyClass(firstArg.getClass())) {
statement = (Statement) SystemMetaObject.forObject(firstArg).getValue("h.statement");
} else {
statement = (Statement) firstArg;
}
MetaObject stmtMetaObj = SystemMetaObject.forObject(statement);
try {
statement = (Statement) stmtMetaObj.getValue("stmt.statement");
} catch (Exception e) {
// do nothing
}
if (stmtMetaObj.hasGetter("delegate")) {
//Hikari
try {
statement = (Statement) stmtMetaObj.getValue("delegate");
} catch (Exception ignored) {
}
}
String originalSql = null;
String stmtClassName = statement.getClass().getName();
if (DRUID_POOLED_PREPARED_STATEMENT.equals(stmtClassName)) {
try {
if (druidGetSqlMethod == null) {
Class<?> clazz = Class.forName(DRUID_POOLED_PREPARED_STATEMENT);
druidGetSqlMethod = clazz.getMethod("getSql");
}
Object stmtSql = druidGetSqlMethod.invoke(statement);
if (stmtSql instanceof String) {
originalSql = (String) stmtSql;
}
} catch (Exception e) {
e.printStackTrace();
}
} else if (T4C_PREPARED_STATEMENT.equals(stmtClassName)
|| ORACLE_PREPARED_STATEMENT_WRAPPER.equals(stmtClassName)) {
try {
if (oracleGetOriginalSqlMethod != null) {
Object stmtSql = oracleGetOriginalSqlMethod.invoke(statement);
if (stmtSql instanceof String) {
originalSql = (String) stmtSql;
}
} else {
Class<?> clazz = Class.forName(stmtClassName);
oracleGetOriginalSqlMethod = getMethodRegular(clazz, "getOriginalSql");
if (oracleGetOriginalSqlMethod != null) {
//OraclePreparedStatementWrapper is not a public class, need set this.
oracleGetOriginalSqlMethod.setAccessible(true);
if (null != oracleGetOriginalSqlMethod) {
Object stmtSql = oracleGetOriginalSqlMethod.invoke(statement);
if (stmtSql instanceof String) {
originalSql = (String) stmtSql;
}
}
}
}
} catch (Exception e) {
//ignore
}
}
if (originalSql == null) {
originalSql = statement.toString();
}
originalSql = originalSql.replaceAll("[\\s]+", StringPool.SPACE);
int index = indexOfSqlStart(originalSql);
if (index > 0) {
originalSql = originalSql.substring(index);
}
// 计算执行 SQL 耗时
long start = SystemClock.now();
Object result = invocation.proceed();
long timing = SystemClock.now() - start;
// SQL 打印执行结果
Object target = PluginUtils.realTarget(invocation.getTarget());
MetaObject metaObject = SystemMetaObject.forObject(target);
MappedStatement ms = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
// 打印 sql
System.err.println(
StringUtil.format(
"\n============== Sql Start ==============" +
"\nExecute ID {}" +
"\nExecute SQL {}" +
"\nExecute Time{} ms" +
"\n============== Sql End ==============\n",
ms.getId(), originalSql, timing));
return result;
}
@Override
public Object plugin(Object target) {
if (target instanceof StatementHandler) {
return Plugin.wrap(target, this);
}
return target;
}
/**
* 获取此方法名的具体 Method
*
* @param clazz class 对象
* @param methodName 方法名
* @return 方法
*/
private Method getMethodRegular(Class<?> clazz, String methodName) {
if (Object.class.equals(clazz)) {
return null;
}
for (Method method : clazz.getDeclaredMethods()) {
if (method.getName().equals(methodName)) {
return method;
}
}
return getMethodRegular(clazz.getSuperclass(), methodName);
}
/**
* 获取sql语句开头部分
*
* @param sql ignore
* @return ignore
*/
private int indexOfSqlStart(String sql) {
String upperCaseSql = sql.toUpperCase();
Set<Integer> set = new HashSet<>();
set.add(upperCaseSql.indexOf("SELECT "));
set.add(upperCaseSql.indexOf("UPDATE "));
set.add(upperCaseSql.indexOf("INSERT "));
set.add(upperCaseSql.indexOf("DELETE "));
set.remove(-1);
if (CollectionUtils.isEmpty(set)) {
return -1;
}
List<Integer> list = new ArrayList<>(set);
list.sort(Comparator.naturalOrder());
return list.get(0);
}
}

View File

@ -30,15 +30,17 @@ public abstract class BaseEntityWrapper<E, V> {
/** /**
* 单个实体类包装 * 单个实体类包装
* @param entity *
* @return * @param entity 实体类
* @return V
*/ */
public abstract V entityVO(E entity); public abstract V entityVO(E entity);
/** /**
* 实体类集合包装 * 实体类集合包装
* @param list *
* @return * @param list 猎豹
* @return List V
*/ */
public List<V> listVO(List<E> list) { public List<V> listVO(List<E> list) {
return list.stream().map(this::entityVO).collect(Collectors.toList()); return list.stream().map(this::entityVO).collect(Collectors.toList());
@ -46,8 +48,9 @@ public abstract class BaseEntityWrapper<E, V> {
/** /**
* 分页实体类集合包装 * 分页实体类集合包装
* @param pages *
* @return * @param pages 分页
* @return Page V
*/ */
public IPage<V> pageVO(IPage<E> pages) { public IPage<V> pageVO(IPage<E> pages) {
List<V> records = listVO(pages.getRecords()); List<V> records = listVO(pages.getRecords());

View File

@ -33,8 +33,8 @@ public class Condition {
/** /**
* 转化成mybatis plus中的Page * 转化成mybatis plus中的Page
* *
* @param query * @param query 查询包装类
* @return * @return Page T
*/ */
public static <T> IPage<T> getPage(Query query) { public static <T> IPage<T> getPage(Query query) {
Page<T> page = new Page<>(Func.toInt(query.getCurrent(), 1), Func.toInt(query.getSize(), 10)); Page<T> page = new Page<>(Func.toInt(query.getCurrent(), 1), Func.toInt(query.getSize(), 10));
@ -46,9 +46,9 @@ public class Condition {
/** /**
* 获取mybatis plus中的QueryWrapper * 获取mybatis plus中的QueryWrapper
* *
* @param entity * @param entity 实体类
* @param <T> * @param <T> 泛型
* @return * @return QueryWrapper
*/ */
public static <T> QueryWrapper<T> getQueryWrapper(T entity) { public static <T> QueryWrapper<T> getQueryWrapper(T entity) {
return new QueryWrapper<>(entity); return new QueryWrapper<>(entity);
@ -57,10 +57,10 @@ public class Condition {
/** /**
* 获取mybatis plus中的QueryWrapper * 获取mybatis plus中的QueryWrapper
* *
* @param query * @param query 查询包装类
* @param clazz * @param clazz 实体类
* @param <T> * @param <T> 泛型
* @return * @return QueryWrapper
*/ */
public static <T> QueryWrapper<T> getQueryWrapper(Map<String, Object> query, Class<T> clazz) { public static <T> QueryWrapper<T> getQueryWrapper(Map<String, Object> query, Class<T> clazz) {
query.remove("current"); query.remove("current");

View File

@ -88,7 +88,7 @@ public class SqlKeyword {
* *
* @param column 字段名 * @param column 字段名
* @param keyword 关键字 * @param keyword 关键字
* @return * @return String
*/ */
private static String getColumn(String column, String keyword) { private static String getColumn(String column, String keyword) {
return StringUtil.humpToUnderline(StringUtil.removeSuffix(column, keyword)); return StringUtil.humpToUnderline(StringUtil.removeSuffix(column, keyword));

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>blade-tool</artifactId> <artifactId>blade-tool</artifactId>
<groupId>org.springblade</groupId> <groupId>org.springblade</groupId>
<version>2.5.4</version> <version>2.6.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>blade-tool</artifactId> <artifactId>blade-tool</artifactId>
<groupId>org.springblade</groupId> <groupId>org.springblade</groupId>
<version>2.5.4</version> <version>2.6.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>blade-tool</artifactId> <artifactId>blade-tool</artifactId>
<groupId>org.springblade</groupId> <groupId>org.springblade</groupId>
<version>2.5.4</version> <version>2.6.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -23,26 +23,10 @@
<version>${blade.tool.version}</version> <version>${blade.tool.version}</version>
</dependency> </dependency>
<!--Swagger--> <!--Swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
<exclusions>
<exclusion>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>${swagger.models.version}</version>
</dependency>
<dependency> <dependency>
<groupId>com.github.xiaoymin</groupId> <groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId> <artifactId>knife4j-micro-spring-boot-starter</artifactId>
<version>${swagger.bootstrapui.version}</version> <version>${knife4j.version}</version>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -16,14 +16,16 @@
package org.springblade.core.swagger; package org.springblade.core.swagger;
import com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrapUI; import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Profile; import org.springframework.context.annotation.Profile;
import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.PathSelectors;
import springfox.documentation.service.*; import springfox.documentation.service.*;
@ -42,10 +44,11 @@ import java.util.List;
* @author Chill * @author Chill
*/ */
@Configuration @Configuration
@EnableKnife4j
@EnableSwagger2 @EnableSwagger2
@EnableSwaggerBootstrapUI
@Profile({"dev", "test"}) @Profile({"dev", "test"})
@EnableConfigurationProperties(SwaggerProperties.class) @EnableConfigurationProperties(SwaggerProperties.class)
@Import(BeanValidatorPluginsConfiguration.class)
public class SwaggerAutoConfiguration { public class SwaggerAutoConfiguration {
private static final String DEFAULT_EXCLUDE_PATH = "/error"; private static final String DEFAULT_EXCLUDE_PATH = "/error";

View File

@ -55,7 +55,7 @@ public class SwaggerProperties {
/** /**
* 版本 * 版本
**/ **/
private String version = "2.5.4"; private String version = "2.6.0";
/** /**
* 许可证 * 许可证
**/ **/

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>org.springblade</groupId> <groupId>org.springblade</groupId>
<artifactId>blade-tool</artifactId> <artifactId>blade-tool</artifactId>
<version>2.5.4</version> <version>2.6.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.springblade</groupId> <groupId>org.springblade</groupId>
<artifactId>blade-tool</artifactId> <artifactId>blade-tool</artifactId>
<version>2.5.4</version> <version>2.6.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -16,9 +16,11 @@
package org.springblade.core.tool.config; package org.springblade.core.tool.config;
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.json.JsonReadFeature;
import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.SerializationFeature;
import lombok.AllArgsConstructor;
import org.springblade.core.tool.jackson.BladeJavaTimeModule; import org.springblade.core.tool.jackson.BladeJavaTimeModule;
import org.springblade.core.tool.utils.DateUtil; import org.springblade.core.tool.utils.DateUtil;
import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.AutoConfigureBefore;
@ -40,6 +42,7 @@ import java.util.TimeZone;
* @author Chill * @author Chill
*/ */
@Configuration @Configuration
@AllArgsConstructor
@ConditionalOnClass(ObjectMapper.class) @ConditionalOnClass(ObjectMapper.class)
@AutoConfigureBefore(JacksonAutoConfiguration.class) @AutoConfigureBefore(JacksonAutoConfiguration.class)
public class JacksonConfiguration { public class JacksonConfiguration {
@ -59,8 +62,8 @@ public class JacksonConfiguration {
//序列化时日期的统一格式 //序列化时日期的统一格式
objectMapper.setDateFormat(new SimpleDateFormat(DateUtil.PATTERN_DATETIME, Locale.CHINA)); objectMapper.setDateFormat(new SimpleDateFormat(DateUtil.PATTERN_DATETIME, Locale.CHINA));
//序列化处理 //序列化处理
objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true); objectMapper.configure(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature(), true);
objectMapper.configure(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true); objectMapper.configure(JsonReadFeature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER.mappedFeature(), true);
objectMapper.findAndRegisterModules(); objectMapper.findAndRegisterModules();
//失败处理 //失败处理
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

View File

@ -19,11 +19,7 @@ package org.springblade.core.tool.config;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.springblade.core.tool.jackson.MappingApiJackson2HttpMessageConverter; import org.springblade.core.tool.jackson.MappingApiJackson2HttpMessageConverter;
import org.springblade.core.tool.support.xss.XssFilter;
import org.springblade.core.tool.support.xss.XssProperties;
import org.springblade.core.tool.utils.Charsets; import org.springblade.core.tool.utils.Charsets;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
@ -31,7 +27,6 @@ import org.springframework.http.converter.*;
import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter; import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.servlet.DispatcherType;
import java.util.List; import java.util.List;
/** /**
@ -46,8 +41,6 @@ public class MessageConfiguration implements WebMvcConfigurer {
private final ObjectMapper objectMapper; private final ObjectMapper objectMapper;
private final XssProperties xssProperties;
/** /**
* 使用 JACKSON 作为JSON MessageConverter * 使用 JACKSON 作为JSON MessageConverter
*/ */
@ -61,20 +54,4 @@ public class MessageConfiguration implements WebMvcConfigurer {
converters.add(new MappingApiJackson2HttpMessageConverter(objectMapper)); converters.add(new MappingApiJackson2HttpMessageConverter(objectMapper));
} }
/**
* 防XSS注入
*
* @return FilterRegistrationBean
*/
@Bean
public FilterRegistrationBean xssFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setDispatcherTypes(DispatcherType.REQUEST);
registration.setFilter(new XssFilter(xssProperties));
registration.addUrlPatterns("/*");
registration.setName("xssFilter");
registration.setOrder(Ordered.LOWEST_PRECEDENCE);
return registration;
}
} }

View File

@ -16,9 +16,7 @@
package org.springblade.core.tool.config; package org.springblade.core.tool.config;
import org.springblade.core.tool.support.xss.XssProperties;
import org.springblade.core.tool.utils.SpringUtil; import org.springblade.core.tool.utils.SpringUtil;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
@ -32,7 +30,6 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
*/ */
@Configuration @Configuration
@Order(Ordered.HIGHEST_PRECEDENCE) @Order(Ordered.HIGHEST_PRECEDENCE)
@EnableConfigurationProperties(XssProperties.class)
public class ToolConfiguration implements WebMvcConfigurer { public class ToolConfiguration implements WebMvcConfigurer {
/** /**

View File

@ -0,0 +1,58 @@
/**
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <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 org.springblade.core.tool.config;
import lombok.AllArgsConstructor;
import org.springblade.core.tool.support.xss.XssFilter;
import org.springblade.core.tool.support.xss.XssProperties;
import org.springblade.core.tool.support.xss.XssUrlProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import javax.servlet.DispatcherType;
/**
* Xss配置类
*
* @author Chill
*/
@Configuration
@AllArgsConstructor
@ConditionalOnProperty(value = "blade.xss.enable", havingValue = "true")
@EnableConfigurationProperties({XssProperties.class, XssUrlProperties.class})
public class XssConfiguration {
private final XssProperties xssProperties;
private final XssUrlProperties xssUrlProperties;
/**
* 防XSS注入
*/
@Bean
public FilterRegistrationBean<XssFilter> xssFilterRegistration() {
FilterRegistrationBean<XssFilter> registration = new FilterRegistrationBean<>();
registration.setDispatcherTypes(DispatcherType.REQUEST);
registration.setFilter(new XssFilter(xssProperties, xssUrlProperties));
registration.addUrlPatterns("/*");
registration.setName("xssFilter");
registration.setOrder(Ordered.LOWEST_PRECEDENCE);
return registration;
}
}

View File

@ -17,6 +17,7 @@ package org.springblade.core.tool.jackson;
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.json.JsonReadFeature;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
@ -97,7 +98,7 @@ public class JsonUtil {
* @param <T> T 泛型标记 * @param <T> T 泛型标记
* @return Bean * @return Bean
*/ */
public static <T> T parse(String content, TypeReference<?> typeReference) { public static <T> T parse(String content, TypeReference<T> typeReference) {
try { try {
return getInstance().readValue(content, typeReference); return getInstance().readValue(content, typeReference);
} catch (IOException e) { } catch (IOException e) {
@ -130,7 +131,7 @@ public class JsonUtil {
* @param <T> T 泛型标记 * @param <T> T 泛型标记
* @return Bean * @return Bean
*/ */
public static <T> T parse(byte[] bytes, TypeReference<?> typeReference) { public static <T> T parse(byte[] bytes, TypeReference<T> typeReference) {
try { try {
return getInstance().readValue(bytes, typeReference); return getInstance().readValue(bytes, typeReference);
} catch (IOException e) { } catch (IOException e) {
@ -162,7 +163,7 @@ public class JsonUtil {
* @param <T> T 泛型标记 * @param <T> T 泛型标记
* @return Bean * @return Bean
*/ */
public static <T> T parse(InputStream in, TypeReference<?> typeReference) { public static <T> T parse(InputStream in, TypeReference<T> typeReference) {
try { try {
return getInstance().readValue(in, typeReference); return getInstance().readValue(in, typeReference);
} catch (IOException e) { } catch (IOException e) {
@ -184,7 +185,7 @@ public class JsonUtil {
content = StringPool.LEFT_SQ_BRACKET + content + StringPool.RIGHT_SQ_BRACKET; content = StringPool.LEFT_SQ_BRACKET + content + StringPool.RIGHT_SQ_BRACKET;
} }
List<Map<String, Object>> list = getInstance().readValue(content, new TypeReference<List<T>>() { List<Map<String, Object>> list = getInstance().readValue(content, new TypeReference<List<Map<String, Object>>>() {
}); });
List<T> result = new ArrayList<>(); List<T> result = new ArrayList<>();
for (Map<String, Object> map : list) { for (Map<String, Object> map : list) {
@ -208,7 +209,7 @@ public class JsonUtil {
public static <T> Map<String, T> toMap(String content, Class<T> valueTypeRef) { public static <T> Map<String, T> toMap(String content, Class<T> valueTypeRef) {
try { try {
Map<String, Map<String, Object>> map = getInstance().readValue(content, new TypeReference<Map<String, T>>() { Map<String, Map<String, Object>> map = getInstance().readValue(content, new TypeReference<Map<String, Map<String, Object>>>() {
}); });
Map<String, T> result = new HashMap<>(16); Map<String, T> result = new HashMap<>(16);
for (Map.Entry<String, Map<String, Object>> entry : map.entrySet()) { for (Map.Entry<String, Map<String, Object>> entry : map.entrySet()) {
@ -305,8 +306,8 @@ public class JsonUtil {
//序列化时日期的统一格式 //序列化时日期的统一格式
super.setDateFormat(new SimpleDateFormat(DateUtil.PATTERN_DATETIME, Locale.CHINA)); super.setDateFormat(new SimpleDateFormat(DateUtil.PATTERN_DATETIME, Locale.CHINA));
//序列化处理 //序列化处理
super.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true); super.configure(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature(), true);
super.configure(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true); super.configure(JsonReadFeature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER.mappedFeature(), true);
super.findAndRegisterModules(); super.findAndRegisterModules();
//失败处理 //失败处理
super.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); super.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

View File

@ -16,6 +16,7 @@
package org.springblade.core.tool.support.xss; package org.springblade.core.tool.support.xss;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.springblade.core.tool.utils.StringPool;
import javax.servlet.*; import javax.servlet.*;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -30,6 +31,7 @@ import java.io.IOException;
public class XssFilter implements Filter { public class XssFilter implements Filter {
private XssProperties xssProperties; private XssProperties xssProperties;
private XssUrlProperties xssUrlProperties;
@Override @Override
public void init(FilterConfig config) { public void init(FilterConfig config) {
@ -39,7 +41,7 @@ public class XssFilter implements Filter {
@Override @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
String path = ((HttpServletRequest) request).getServletPath(); String path = ((HttpServletRequest) request).getServletPath();
if (xssProperties.getExcludePatterns().stream().anyMatch(path::contains)) { if (isSkip(path)) {
chain.doFilter(request, response); chain.doFilter(request, response);
} else { } else {
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request); XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
@ -47,6 +49,11 @@ public class XssFilter implements Filter {
} }
} }
private boolean isSkip(String path) {
return (xssUrlProperties.getExcludePatterns().stream().anyMatch(path::startsWith))
|| (xssProperties.getSkipUrl().stream().map(url -> url.replace("/**", StringPool.EMPTY)).anyMatch(path::startsWith));
}
@Override @Override
public void destroy() { public void destroy() {

View File

@ -15,9 +15,7 @@
*/ */
package org.springblade.core.tool.support.xss; package org.springblade.core.tool.support.xss;
import org.springblade.core.tool.utils.Charsets;
import org.springblade.core.tool.utils.StringUtil; import org.springblade.core.tool.utils.StringUtil;
import org.springblade.core.tool.utils.WebUtil;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
@ -29,6 +27,7 @@ import java.io.BufferedReader;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
@ -49,15 +48,9 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
*/ */
private final static HtmlFilter HTML_FILTER = new HtmlFilter(); private final static HtmlFilter HTML_FILTER = new HtmlFilter();
/** public XssHttpServletRequestWrapper(HttpServletRequest request) {
* 缓存报文,支持多次读取流
*/
private final byte[] body;
public XssHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request); super(request);
orgRequest = request; orgRequest = request;
body = WebUtil.getRequestBytes(request);
} }
@Override @Override
@ -67,51 +60,67 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
@Override @Override
public ServletInputStream getInputStream() throws IOException { public ServletInputStream getInputStream() throws IOException {
//为空直接返回
if (null == super.getHeader(HttpHeaders.CONTENT_TYPE)) { if (null == super.getHeader(HttpHeaders.CONTENT_TYPE)) {
return super.getInputStream(); return super.getInputStream();
} }
//非json类型直接返回 if (super.getHeader(HttpHeaders.CONTENT_TYPE).startsWith(MediaType.MULTIPART_FORM_DATA_VALUE)) {
if (!super.getHeader(HttpHeaders.CONTENT_TYPE).equalsIgnoreCase(MediaType.APPLICATION_JSON_VALUE)
&& !super.getHeader(HttpHeaders.CONTENT_TYPE).equalsIgnoreCase(MediaType.APPLICATION_JSON_UTF8_VALUE)) {
return super.getInputStream(); return super.getInputStream();
} }
//为空直接返回 final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(inputHandlers(super.getInputStream()).getBytes());
String requestStr = WebUtil.getRequestStr(orgRequest, body);
if (StringUtil.isBlank(requestStr)) {
return super.getInputStream();
}
requestStr = xssEncode(requestStr);
final ByteArrayInputStream bis = new ByteArrayInputStream(requestStr.getBytes(Charsets.UTF_8));
return new ServletInputStream() { return new ServletInputStream() {
@Override
public int read() {
return byteArrayInputStream.read();
}
@Override @Override
public boolean isFinished() { public boolean isFinished() {
return true; return false;
} }
@Override @Override
public boolean isReady() { public boolean isReady() {
return true; return false;
} }
@Override @Override
public void setReadListener(ReadListener readListener) { public void setReadListener(ReadListener readListener) {
}
@Override
public int read() throws IOException {
return bis.read();
} }
}; };
}
private String inputHandlers(ServletInputStream servletInputStream) {
StringBuilder sb = new StringBuilder();
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(servletInputStream, StandardCharsets.UTF_8));
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (servletInputStream != null) {
try {
servletInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return xssEncode(sb.toString());
} }
@Override @Override
@ -129,7 +138,6 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
if (parameters == null || parameters.length == 0) { if (parameters == null || parameters.length == 0) {
return null; return null;
} }
for (int i = 0; i < parameters.length; i++) { for (int i = 0; i < parameters.length; i++) {
parameters[i] = xssEncode(parameters[i]); parameters[i] = xssEncode(parameters[i]);
} }
@ -165,6 +173,7 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
/** /**
* 获取最原始的request * 获取最原始的request
*
* @return HttpServletRequest * @return HttpServletRequest
*/ */
public HttpServletRequest getOrgRequest() { public HttpServletRequest getOrgRequest() {
@ -173,6 +182,7 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
/** /**
* 获取最原始的request * 获取最原始的request
*
* @param request request * @param request request
* @return HttpServletRequest * @return HttpServletRequest
*/ */
@ -180,7 +190,6 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
if (request instanceof XssHttpServletRequestWrapper) { if (request instanceof XssHttpServletRequestWrapper) {
return ((XssHttpServletRequestWrapper) request).getOrgRequest(); return ((XssHttpServletRequestWrapper) request).getOrgRequest();
} }
return request; return request;
} }

View File

@ -27,9 +27,17 @@ import java.util.List;
* @author Chill * @author Chill
*/ */
@Data @Data
@ConfigurationProperties("blade.xss.url") @ConfigurationProperties("blade.xss")
public class XssProperties { public class XssProperties {
private final List<String> excludePatterns = new ArrayList<>(); /**
* 开启xss
*/
private Boolean enable = true;
/**
* 放行url
*/
private List<String> skipUrl = new ArrayList<>();
} }

View File

@ -0,0 +1,35 @@
/**
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <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 org.springblade.core.tool.support.xss;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.ArrayList;
import java.util.List;
/**
* Xss配置类
*
* @author Chill
*/
@Data
@ConfigurationProperties("blade.xss.url")
public class XssUrlProperties {
private final List<String> excludePatterns = new ArrayList<>();
}

View File

@ -1124,7 +1124,7 @@ public class Func {
* @param <T> T 泛型标记 * @param <T> T 泛型标记
* @return Bean * @return Bean
*/ */
public static <T> T parse(byte[] bytes, TypeReference<?> typeReference) { public static <T> T parse(byte[] bytes, TypeReference<T> typeReference) {
return JsonUtil.parse(bytes, typeReference); return JsonUtil.parse(bytes, typeReference);
} }
@ -1136,7 +1136,7 @@ public class Func {
* @param <T> T 泛型标记 * @param <T> T 泛型标记
* @return Bean * @return Bean
*/ */
public static <T> T parse(String jsonString, TypeReference<?> typeReference) { public static <T> T parse(String jsonString, TypeReference<T> typeReference) {
return JsonUtil.parse(jsonString, typeReference); return JsonUtil.parse(jsonString, typeReference);
} }
@ -1148,7 +1148,7 @@ public class Func {
* @param <T> T 泛型标记 * @param <T> T 泛型标记
* @return Bean * @return Bean
*/ */
public static <T> T parse(InputStream in, TypeReference<?> typeReference) { public static <T> T parse(InputStream in, TypeReference<T> typeReference) {
return JsonUtil.parse(in, typeReference); return JsonUtil.parse(in, typeReference);
} }

View File

@ -186,7 +186,7 @@ public class StringUtil extends org.springframework.util.StringUtils {
* @return {String} * @return {String}
*/ */
public static String escapeHtml(String html) { public static String escapeHtml(String html) {
return HtmlUtils.htmlEscape(html); return StringUtil.isBlank(html) ? StringPool.EMPTY : HtmlUtils.htmlEscape(html);
} }
/** /**
@ -1250,7 +1250,7 @@ public class StringUtil extends org.springframework.util.StringUtils {
/** /**
* 创建StringBuilder对象 * 创建StringBuilder对象
* *
* @param sb 初始StringBuilder * @param sb 初始StringBuilder
* @param strs 初始字符串列表 * @param strs 初始字符串列表
* @return StringBuilder对象 * @return StringBuilder对象
*/ */

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>blade-tool</artifactId> <artifactId>blade-tool</artifactId>
<groupId>org.springblade</groupId> <groupId>org.springblade</groupId>
<version>2.5.4</version> <version>2.6.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

18
pom.xml
View File

@ -5,7 +5,7 @@
<groupId>org.springblade</groupId> <groupId>org.springblade</groupId>
<artifactId>blade-tool</artifactId> <artifactId>blade-tool</artifactId>
<version>2.5.4</version> <version>2.6.0</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>blade-tool</name> <name>blade-tool</name>
<description> <description>
@ -36,24 +36,24 @@
</scm> </scm>
<properties> <properties>
<blade.tool.version>2.5.4</blade.tool.version> <blade.tool.version>2.6.0</blade.tool.version>
<java.version>1.8</java.version> <java.version>1.8</java.version>
<maven.plugin.version>3.8.0</maven.plugin.version> <maven.plugin.version>3.8.0</maven.plugin.version>
<swagger.version>2.9.2</swagger.version> <swagger.version>2.9.2</swagger.version>
<swagger.models.version>1.5.21</swagger.models.version> <swagger.models.version>1.5.21</swagger.models.version>
<swagger.bootstrapui.version>1.9.6</swagger.bootstrapui.version> <knife4j.version>2.0.1</knife4j.version>
<mybatis.plus.version>3.1.2</mybatis.plus.version> <mybatis.plus.version>3.2.0</mybatis.plus.version>
<curator.framework.version>4.0.1</curator.framework.version> <curator.framework.version>4.0.1</curator.framework.version>
<protostuff.version>1.6.0</protostuff.version> <protostuff.version>1.6.0</protostuff.version>
<disruptor.version>3.4.2</disruptor.version> <disruptor.version>3.4.2</disruptor.version>
<spring.boot.admin.version>2.1.5</spring.boot.admin.version> <spring.boot.admin.version>2.2.0</spring.boot.admin.version>
<mica.auto.version>1.1.0</mica.auto.version> <mica.auto.version>1.1.0</mica.auto.version>
<alibaba.cloud.version>2.1.0.RELEASE</alibaba.cloud.version> <alibaba.cloud.version>2.1.1.RELEASE</alibaba.cloud.version>
<alibaba.seata.version>0.9.0</alibaba.seata.version> <alibaba.seata.version>1.0.0</alibaba.seata.version>
<spring.boot.version>2.1.9.RELEASE</spring.boot.version> <spring.boot.version>2.2.2.RELEASE</spring.boot.version>
<spring.cloud.version>Greenwich.SR3</spring.cloud.version> <spring.cloud.version>Hoxton.SR1</spring.cloud.version>
<spring.platform.version>Cairo-SR8</spring.platform.version> <spring.platform.version>Cairo-SR8</spring.platform.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>