3.2.0-beta,重构很大:升级springboot2.6.6、spring-cloud-alibaba 2021.1、mybatisplus3.5.1、代码规范部分重构

This commit is contained in:
zhangdaiscott
2022-04-18 09:37:28 +08:00
parent d0b68919b3
commit 69ecb39c9e
487 changed files with 9754 additions and 2928 deletions

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-boot-starter</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-boot-starter-cloud</artifactId>
@ -30,11 +30,30 @@
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- 服务降级 -->
<!-- sentinel限流熔断降级 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--sentinel持久化 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<!-- springboot up 2.6.6 -->
<!-- Alibaba Nacos 配置 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<!-- SpringCloud 负载均衡 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!-- springboot up 2.6.6 -->
</dependencies>
</project>

View File

@ -44,12 +44,21 @@ import feign.codec.Encoder;
import feign.form.spring.SpringFormEncoder;
import lombok.extern.slf4j.Slf4j;
/**
* @Description: FeignConfig
* @author: JeecgBoot
*/
@ConditionalOnClass(Feign.class)
@AutoConfigureBefore(FeignAutoConfiguration.class)
@Slf4j
@Configuration
public class FeignConfig {
/**
* 设置feign header参数
* 【X_ACCESS_TOKEN】【X_SIGN】【X_TIMESTAMP】
* @return
*/
@Bean
public RequestInterceptor requestInterceptor() {
return requestTemplate -> {
@ -62,38 +71,40 @@ public class FeignConfig {
if(token==null || "".equals(token)){
token = request.getParameter("token");
}
log.debug("Feign request token: {}", token);
log.info("Feign Login Request token: {}", token);
requestTemplate.header(CommonConstant.X_ACCESS_TOKEN, token);
//根据URL地址过滤请求 【字典表参数签名验证】
if (PathMatcherUtil.matches(Arrays.asList(SignAuthConfiguration.urlList),requestTemplate.path())) {
try {
log.info("============================ [begin] fegin starter url ============================");
log.info(requestTemplate.path());
log.info(requestTemplate.method());
String queryLine = requestTemplate.queryLine();
if(queryLine!=null && queryLine.startsWith("?")){
queryLine = queryLine.substring(1);
}
log.info(queryLine);
if(requestTemplate.body()!=null){
log.info(new String(requestTemplate.body()));
}
SortedMap<String, String> allParams = HttpUtils.getAllParams(requestTemplate.path(),queryLine,requestTemplate.body(),requestTemplate.method());
String sign = SignUtil.getParamsSign(allParams);
log.info(" Feign request params sign: {}",sign);
log.info("============================ [end] fegin starter url ============================");
requestTemplate.header(CommonConstant.X_SIGN, sign);
requestTemplate.header(CommonConstant.X_TIMESTAMP, DateUtils.getCurrentTimestamp().toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}else{
String token = UserTokenContext.getToken();
log.debug("Feign request token: {}", token);
String token = UserTokenContext.getToken();
log.info("Feign no Login token: {}", token);
requestTemplate.header(CommonConstant.X_ACCESS_TOKEN, token);
}
//================================================================================================================
//针对特殊接口,进行加签验证 ——根据URL地址过滤请求 【字典表参数签名验证】
if (PathMatcherUtil.matches(Arrays.asList(SignAuthConfiguration.SIGN_URL_LIST),requestTemplate.path())) {
try {
log.info("============================ [begin] fegin starter url ============================");
log.info(requestTemplate.path());
log.info(requestTemplate.method());
String queryLine = requestTemplate.queryLine();
if(queryLine!=null && queryLine.startsWith("?")){
queryLine = queryLine.substring(1);
}
log.info(queryLine);
if(requestTemplate.body()!=null){
log.info(new String(requestTemplate.body()));
}
SortedMap<String, String> allParams = HttpUtils.getAllParams(requestTemplate.path(),queryLine,requestTemplate.body(),requestTemplate.method());
String sign = SignUtil.getParamsSign(allParams);
log.info(" Feign request params sign: {}",sign);
log.info("============================ [end] fegin starter url ============================");
requestTemplate.header(CommonConstant.X_SIGN, sign);
requestTemplate.header(CommonConstant.X_TIMESTAMP, DateUtils.getCurrentTimestamp().toString());
} catch (IOException e) {
e.printStackTrace();
}
}
//================================================================================================================
};
}
@ -130,7 +141,7 @@ public class FeignConfig {
return new SpringEncoder(feignHttpMessageConverter());
}
@Bean
@Bean("starterFeignDecoder")
public Decoder feignDecoder() {
return new SpringDecoder(feignHttpMessageConverter());
}

View File

@ -0,0 +1,31 @@
package org.jeecg.starter.cloud.config;
/**
* @Description: 跨域设置 (升级SpringBoot2.6.6)
* @author: zyf
* @date: 2022/02/21
* @version: V1.0
*/
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.util.pattern.PathPatternParser;
@Configuration
public class GwCorsFilter {
@Bean
public CorsWebFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOriginPattern("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.setMaxAge(18000L);
org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource source =
new org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource(new PathPatternParser());
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}
}

View File

@ -1,24 +1,24 @@
package org.jeecg.starter.cloud.config;
import feign.Client;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class PersonBeanConfiguration {
/**
* 创建FeignClient
*/
@Bean
@ConditionalOnMissingBean
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
SpringClientFactory clientFactory) {
return new LoadBalancerFeignClient(new Client.Default(null, null),
cachingFactory, clientFactory);
}
}
//package org.jeecg.starter.cloud.config;
//
//import feign.Client;
//import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
//import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
//import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
//import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//
//@Configuration
//public class PersonBeanConfiguration {
//
// /**
// * 创建FeignClient
// */
// @Bean
// @ConditionalOnMissingBean
// public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
// SpringClientFactory clientFactory) {
// return new LoadBalancerFeignClient(new Client.Default(null, null),
// cachingFactory, clientFactory);
// }
//}

View File

@ -1,6 +1,6 @@
package org.jeecg.starter.cloud.feign;
public interface IJeecgFeignService {
<T> T newInstance(Class<T> apiType, String name);
}
//package org.jeecg.starter.cloud.feign;
//
//public interface IJeecgFeignService {
//
// <T> T newInstance(Class<T> apiType, String name);
//}

View File

@ -1,60 +1,60 @@
package org.jeecg.starter.cloud.feign.impl;
import feign.*;
import feign.codec.Decoder;
import feign.codec.Encoder;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.starter.cloud.feign.IJeecgFeignService;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
import org.springframework.cloud.openfeign.FeignClientsConfiguration;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
@Service
@Slf4j
@ConditionalOnClass(Feign.class)
@AutoConfigureBefore(FeignAutoConfiguration.class)
@Import(FeignClientsConfiguration.class)
public class JeecgFeignService implements IJeecgFeignService {
//Feign 原生构造器
Feign.Builder builder;
//创建构造器
public JeecgFeignService(Decoder decoder, Encoder encoder, Client client, Contract contract) {
this.builder = Feign.builder()
.client(client)
.encoder(encoder)
.decoder(decoder)
.contract(contract);
builder.requestInterceptor(requestTemplate -> {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (null != attributes) {
HttpServletRequest request = attributes.getRequest();
log.info("Feign request: {}", request.getRequestURI());
// 将token信息放入header中
String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN);
if(token==null){
token = request.getParameter("token");
}
log.info("Feign request token: {}", token);
requestTemplate.header(CommonConstant.X_ACCESS_TOKEN, token);
}
});
}
@Override
public <T> T newInstance(Class<T> clientClass, String serviceName) {
return builder.target(clientClass, String.format("http://%s/", serviceName));
}
}
//package org.jeecg.starter.cloud.feign.impl;
//
//import feign.*;
//import feign.codec.Decoder;
//import feign.codec.Encoder;
//import lombok.extern.slf4j.Slf4j;
//import org.jeecg.common.constant.CommonConstant;
//import org.jeecg.starter.cloud.feign.IJeecgFeignService;
//import org.springframework.boot.autoconfigure.AutoConfigureBefore;
//import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
//import org.springframework.cloud.openfeign.FeignAutoConfiguration;
//import org.springframework.cloud.openfeign.FeignClientsConfiguration;
//import org.springframework.context.annotation.Import;
//import org.springframework.stereotype.Service;
//import org.springframework.web.context.request.RequestContextHolder;
//import org.springframework.web.context.request.ServletRequestAttributes;
//
//import javax.servlet.http.HttpServletRequest;
//
//@Service
//@Slf4j
//@ConditionalOnClass(Feign.class)
//@AutoConfigureBefore(FeignAutoConfiguration.class)
//@Import(FeignClientsConfiguration.class)
//public class JeecgFeignService implements IJeecgFeignService {
//
//
// //Feign 原生构造器
// Feign.Builder builder;
//
// //创建构造器
// public JeecgFeignService(Decoder decoder, Encoder encoder, Client client, Contract contract) {
// this.builder = Feign.builder()
// .client(client)
// .encoder(encoder)
// .decoder(decoder)
// .contract(contract);
//
// builder.requestInterceptor(requestTemplate -> {
// ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
// if (null != attributes) {
// HttpServletRequest request = attributes.getRequest();
// log.info("Feign request: {}", request.getRequestURI());
// // 将token信息放入header中
// String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN);
// if(token==null){
// token = request.getParameter("token");
// }
// log.info("Feign request token: {}", token);
// requestTemplate.header(CommonConstant.X_ACCESS_TOKEN, token);
// }
// });
// }
//
//
// @Override
// public <T> T newInstance(Class<T> clientClass, String serviceName) {
// return builder.target(clientClass, String.format("http://%s/", serviceName));
// }
//}

View File

@ -0,0 +1,55 @@
package org.jeecg.starter.cloud.handler;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import org.springframework.context.annotation.Configuration;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Description: 全局Sentinel自定义信息处理(需要启动Sentinel客户端)
* @author: zyf
* @date: 2022/02/18
* @version: V1.0
*/
@Configuration
public class CustomSentinelExceptionHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, BlockException ex) throws Exception {
String msg = null;
if (ex instanceof FlowException) {
msg = "访问频繁,请稍候再试";
} else if (ex instanceof DegradeException) {
msg = "系统降级";
} else if (ex instanceof ParamFlowException) {
msg = "热点参数限流";
} else if (ex instanceof SystemBlockException) {
msg = "系统规则限流或降级";
} else if (ex instanceof AuthorityException) {
msg = "授权规则不通过";
} else {
msg = "未知限流降级";
}
// http状态码
response.setStatus(200);
response.setCharacterEncoding("utf-8");
response.setHeader("Content-Type", "application/json;charset=utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("{\"code\":500,\"message\":"+msg+"}");
}
}

View File

@ -0,0 +1,22 @@
package org.jeecg.starter.cloud.interceptor;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
/**
* sentinel 授权规则拦截器
* @author zyf
*/
@Component
public class DefaultRequestOriginParser implements RequestOriginParser {
@Override
public String parseOrigin(HttpServletRequest request) {
//基于请求参数,origin对应授权规则中的流控应用名称,也可通过getHeader传参
String origin = request.getParameter("origin");
//TODO 此处做个通过IP做白名单的例子
return origin;
}
}

View File

@ -1,7 +1,10 @@
spring:
#升级SpringBoot2.6.6,允许循环依赖
main:
allow-circular-references: true
profiles:
# 当前激活环境
active: @profile.name@
active: '@profile.name@'
cloud:
#配置Bus id(远程推送事件)
bus:
@ -22,12 +25,35 @@ spring:
file-extension: yaml
prefix: @prefix.name@
# 支持多个共享 Data Id 的配置优先级小于extension-configs,自定义 Data Id 配置 属性是个集合,内部由 Config POJO 组成。Config 有 3 个属性,分别是 dataId, group 以及 refresh
#shared-configs[0]:
#data-id: @prefix.name@-common.yaml # 配置文件名-Data Id
#group: @config.group@ # 默认为DEFAULT_GROUP
#refresh: false # 是否动态刷新默认为false
# shared-configs[0]:
# data-id: @prefix.name@-sharding.yaml #分库分表配置
# group: @config.group@
# refresh: false
# shared-configs[1]:
# data-id: @prefix.name@-common.yaml # 配置文件名-Data Id
# group: @config.group@ # 默认为DEFAULT_GROUP
# refresh: false # 是否动态刷新默认为false
discovery:
namespace: @config.namespace@
server-addr: @config.server-addr@
watch:
enabled: false
# feign启用sentinel
feign:
sentinel:
enabled: true
okhttp:
enabled: true
httpclient:
enabled: false
client:
config:
default:
#不设置connectTimeout会导致readTimeout设置不生效
connectTimeout: 5000
readTimeout: 10000
compression:
request:
enabled: true
response:
enabled: true