1. 初始化代码

main
xueqingkun 12 months ago
parent 93aa0715ee
commit d4b4cb637e

54
.gitignore vendored

@ -1,26 +1,38 @@
# ---> Java
# Compiled class file
*.class
HELP.md
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
# Log file
*.log
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
# BlueJ files
*.ctxt
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/
# Mobile Tools for Java (J2ME)
.mtj.tmp/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
replay_pid*
### VS Code ###
.vscode/

@ -1,3 +1,6 @@
# KBQA
知识图谱问答系统
知识图谱问答系统
- kabq-common(公共模块:公共配置,公共代码)
- kabq-model (模型模块)
- knowledge-report (知识报送模块)

@ -0,0 +1,85 @@
<?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>
<parent>
<groupId>com.supervision</groupId>
<artifactId>KBQA</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>kbqa-common</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!--移除Tomcat依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<!-- 其他依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--jsr303-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!-- SpringBoot集成mybatis框架 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,84 @@
package com.supervision.config;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import com.supervision.exception.BusinessException;
import com.supervision.util.TokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
@Slf4j
public class JwtInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
//请求消息头获取用户ID
String token = request.getHeader("token");
if (StrUtil.isBlank(token)) {
// 如果是swagger来的接口,说明这里是测试的,会伪造一个用户
if (StrUtil.isNotBlank(request.getHeader("Knife4j-Gateway-Code"))) {
cacheAuth(JWTUtil.parseToken(devActiveUser()));
return true;
} else {
throw new BusinessException("当前用户未登录", HttpStatus.UNAUTHORIZED.value());
}
}
JWT jwt = JWTUtil.parseToken(token);
// 校验token是否过期,如果过期了,需要提示过期重新登录
checkTokenExpire(jwt);
cacheAuth(jwt);
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
// 请求结束,将用户信息从thread中移除
clearAuth();
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
private void checkTokenExpire(JWT jwt) {
Object expireTime = jwt.getPayload("expireTime");
long l = Long.parseLong(String.valueOf(expireTime));
// 校验是否比当前时间大
long currentTimeMillis = System.currentTimeMillis();
if (currentTimeMillis > l) {
throw new BusinessException("用户登录已过期,请重新登录", HttpStatus.UNAUTHORIZED.value());
}
}
private void cacheAuth(JWT jwt) {
try {
JSONObject claimsJson = jwt.getPayload().getClaimsJson();
ThreadCache.USER.set(claimsJson.toString());
} catch (Exception e) {
log.error("用户信息异常", e);
}
}
private String devActiveUser() {
Map<String, Object> map = new HashMap<>();
map.put("id", "1");
map.put("account", "test");
map.put("name", "测试账户");
return TokenUtil.creatToken(JSONUtil.toJsonStr(map));
}
private void clearAuth() {
ThreadCache.USER.remove();
}
}

@ -0,0 +1,51 @@
/*
* : Knife4jConfig
* :
* : <>
* : RedName
* : 2022/8/5
* : <>
* : <>
* : <>
*/
package com.supervision.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
/**
* <>
*
* @author ljt
* @version [, 2022/8/5]
* @see [/]
* @since [/]
*/
@Configuration
@EnableSwagger2WebMvc
public class Knife4jConfig {
@Bean(value = "defaultApi2")
public Docket defaultApi2() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(this.apiInfo())
.useDefaultResponseMessages(false)
.select()
.apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
.paths(PathSelectors.any()).build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title("API文档").description("API文档").contact(new Contact("", "", ""))
.version("1.0.0").build();
}
}

@ -0,0 +1,32 @@
/*
* : MybatisPlusConfig
* :
* : <>
* : RedName
* : 2022/8/9
* : <>
* : <>
* : <>
*/
package com.supervision.config;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* <>
*
* @author RedName
* @version [, 2022/8/9]
* @see [/]
* @since [/]
*/
@Configuration
public class MybatisPlusConfig {
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}

@ -0,0 +1,156 @@
package com.supervision.config;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import java.util.HashMap;
import java.util.Map;
/**
*
*
* @author :liu
* create :2020-11-16 10:50
**/
@Component
@Aspect
@Slf4j
public class RequestLogConfig {
@SuppressWarnings("all")
@Around("within(com..*..controller..*) && @within(org.springframework.web.bind.annotation.RestController)")
public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
long start = System.currentTimeMillis();
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
Object result = proceedingJoinPoint.proceed();
RequestInfo requestInfo = new RequestInfo();
requestInfo.setUrl(request.getRequestURL().toString());
requestInfo.setHttpMethod(request.getMethod());
requestInfo.setClassMethod(String.format("%s.%s", proceedingJoinPoint.getSignature().getDeclaringTypeName(),
proceedingJoinPoint.getSignature().getName()));
requestInfo.setRequestParams(getRequestParamsByProceedingJoinPoint(proceedingJoinPoint));
requestInfo.setResult(proceedResult(result));
requestInfo.setTimeCost(System.currentTimeMillis() - start);
log.info("Request Info: {}", JSONUtil.toJsonStr(requestInfo));
return result;
}
private Object proceedResult(Object result) {
String value = null;
try {
value = JSONUtil.toJsonStr(result);
} catch (Exception e) {
value = result.toString();
}
if (StrUtil.isNotBlank(value) && value.length() > 10240){
value = value.substring(0, 1024) + "......" + value.substring(value.length() - 1024);
return value;
}
return result;
}
@SuppressWarnings("all")
@AfterThrowing(pointcut = "@within(org.springframework.web.bind.annotation.RestController)", throwing = "e")
public void doAfterThrow(JoinPoint joinPoint, RuntimeException e) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
RequestErrorInfo requestErrorInfo = new RequestErrorInfo();
requestErrorInfo.setUrl(request.getRequestURL().toString());
requestErrorInfo.setHttpMethod(request.getMethod());
requestErrorInfo.setClassMethod(String.format("%s.%s", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName()));
requestErrorInfo.setRequestParams(getRequestParamsByJoinPoint(joinPoint));
requestErrorInfo.setException(e);
log.info("Error Request Info : {}", JSONUtil.toJsonStr(requestErrorInfo));
}
/**
*
*
* @param proceedingJoinPoint
* @return
*/
private Map<String, Object> getRequestParamsByProceedingJoinPoint(ProceedingJoinPoint proceedingJoinPoint) {
//参数名
String[] paramNames = ((MethodSignature) proceedingJoinPoint.getSignature()).getParameterNames();
//参数值
Object[] paramValues = proceedingJoinPoint.getArgs();
return buildRequestParam(paramNames, paramValues);
}
private Map<String, Object> getRequestParamsByJoinPoint(JoinPoint joinPoint) {
//参数名
String[] paramNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames();
//参数值
Object[] paramValues = joinPoint.getArgs();
return buildRequestParam(paramNames, paramValues);
}
private Map<String, Object> buildRequestParam(String[] paramNames, Object[] paramValues) {
Map<String, Object> requestParams = new HashMap<>();
for (int i = 0; i < paramNames.length; i++) {
Object value = paramValues[i];
if (value instanceof ServletRequest || value instanceof ServletResponse) {
//ServletRequest不能序列化从入参里排除否则报异常java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false)
//ServletResponse不能序列化 从入参里排除否则报异常java.lang.IllegalStateException: getOutputStream() has already been called for this response
continue;
}
//如果是文件对象
if (value instanceof MultipartFile) {
MultipartFile file = (MultipartFile) value;
//获取文件名
value = file.getOriginalFilename();
} else if (value instanceof String) {
// 如果参数很长,就对参数进行修剪
String temp = (String) value;
if (!ObjectUtils.isEmpty(temp) && temp.length() > 1024) {
value = temp.substring(0, 10) + "......" + temp.substring(temp.length() - 10);
}
}
requestParams.put(paramNames[i], value);
}
return requestParams;
}
@Data
public static class RequestInfo {
private String url;
private String httpMethod;
private String classMethod;
private Object requestParams;
private Object result;
private Long timeCost;
}
@Data
public static class RequestErrorInfo {
private String url;
private String httpMethod;
private String classMethod;
private Object requestParams;
private RuntimeException exception;
}
}

@ -0,0 +1,131 @@
package com.supervision.config;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.supervision.domain.GlobalResult;
import com.supervision.exception.BusinessException;
import com.supervision.exception.HumanException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import java.util.Objects;
import java.util.stream.Collectors;
/**
*
*
* @author wb
* @date 2022/3/10 13:24
*/
@Slf4j
@RestControllerAdvice(annotations = RestController.class, basePackages = {"com.**.controller"})
public class ResponseConfig implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(@Nullable MethodParameter methodParameter,
@Nullable Class<? extends HttpMessageConverter<?>> aClass) {
assert methodParameter != null;
return !methodParameter.getDeclaringClass().getName().contains("swagger");
}
@Override
@SuppressWarnings("all")
public Object beforeBodyWrite(Object o, @Nullable MethodParameter methodParameter, @Nullable MediaType mediaType,
@Nullable Class<? extends HttpMessageConverter<?>> aClass, @Nullable ServerHttpRequest serverHttpRequest,
@Nullable ServerHttpResponse serverHttpResponse) {
serverHttpResponse.getHeaders().set("Content-Type", "application/json");
if (Objects.isNull(o)) {
return GlobalResult.ok(null, "success");
}
if (o instanceof GlobalResult) {
return o;
}
// 对于String类型的返回值需要进行特殊处理
if (o instanceof String) {
return JSONUtil.toJsonStr(GlobalResult.ok(o, "success"));
}
return GlobalResult.ok(o, "success");
}
/**
*
*
* @param exception
* @return
*/
@ExceptionHandler(BusinessException.class)
public GlobalResult<?> businessExceptionResponse(BusinessException exception) {
log.error(exception.getMessage(), exception);
Integer code = null == exception.getCode() ? HttpStatus.INTERNAL_SERVER_ERROR.value(): exception.getCode();
String message = StrUtil.isNotEmpty(exception.getMessage()) ? exception.getMessage() : "业务异常";
return GlobalResult.error( code, exception.getMessage(), message);
}
/**
*
*
* @param exception
* @return
*/
@ExceptionHandler(HumanException.class)
public GlobalResult<?> humanExceptionResponse(HumanException exception) {
log.error(exception.getMessage(), exception);
return GlobalResult.error(exception.getCode(), exception.getMessage(), "数字人异常");
}
/**
*
*
* @param exception
* @return
*/
@ExceptionHandler({MethodArgumentNotValidException.class, BindException.class})
public GlobalResult<?> validationExceptionResponse(MethodArgumentNotValidException exception) {
log.error(exception.getMessage(), exception);
// 格式化错误信息
String errorMsg = exception.getBindingResult().getFieldErrors().stream()
.map(e -> e.getField() + ":" + e.getDefaultMessage()).collect(Collectors.joining("、"));
return GlobalResult.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), errorMsg, "参数验证异常");
}
/**
*
* @param exception
* @return
*/
@ExceptionHandler(IllegalArgumentException.class)
public GlobalResult<?> manualValidationExceptionResponse(IllegalArgumentException exception) {
log.error(exception.getMessage(), exception);
return GlobalResult.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), exception.getMessage(), "参数验证异常");
}
/**
*
*
* @param exception
* @return
*/
@ExceptionHandler(Exception.class)
public GlobalResult<?> validationExceptionResponse(Exception exception) {
log.error(exception.getMessage(), exception);
return GlobalResult.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), "未知错误", "未知错误");
}
}

@ -0,0 +1,30 @@
/*
* : ThreadCache
* :
* : <>
* : RedName
* : 2023/9/4
* : <>
* : <>
* : <>
*/
package com.supervision.config;
/**
* <>
*
* @author ljt
* @version [, 2023/9/4]
* @see [/]
* @since [/]
*/
public class ThreadCache {
/**
* ID
*/
public static final ThreadLocal<String> USER = new ThreadLocal<>();
}

@ -0,0 +1,66 @@
package com.supervision.config;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 添加权限拦截器
registry.addInterceptor(new JwtInterceptor())
.addPathPatterns("/**")
.excludePathPatterns(ignorePathPatterns());
}
public List<String> ignorePathPatterns() {
List<String> paths = new ArrayList<>();
paths.add("/swagger-resources/**");
paths.add("/webjars/**");
paths.add("/v2/**");
paths.add("/swagger-ui.html/**");
paths.add("/doc.html/**");
paths.add("/error");
paths.add("/favicon.ico");
paths.add("/user/login");
paths.add("/webSocket/**");
paths.add("/ask/downloadTalkVideo");
paths.add("/fileManage/downloadFile");
paths.add("/aqLibrary/downloadQuestionLibraryTemplate");
paths.add("/medicalRecManage/downloadMedicalAnswerTemplate");
paths.add("/qaKnowledge/**");
// 开发环境,放开不校验token.每次修改这里需要重启(热部署不行)
// paths.add("/**");
return paths;
}
@Bean
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
objectMapper.registerModule(javaTimeModule);
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
return objectMapper;
}
}

@ -0,0 +1,14 @@
package com.supervision.constant;
public interface UserTokenConstant {
String USER_WEBSOCKET_CACHE = "USER:ID:CACHE";
String KICK_CHANNEL = "USER:KICK:CHANNEL";
Integer KICK_CODE = 10000;
Integer NO_RESOURCE_CODE = 10001;
Integer KEEPALIVE_CODE = 10002;
}

@ -0,0 +1,49 @@
package com.supervision.domain;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.http.HttpStatus;
@Data
@ApiModel
public class GlobalResult<T> {
private int code = 200;
private String msg = "success";
@ApiModelProperty
private T data;
public static <T> GlobalResult<T> ok() {
return ok(null);
}
public static <T> GlobalResult<T> ok(T data) {
GlobalResult<T> globalResult = new GlobalResult<>();
globalResult.setData(data);
return globalResult;
}
public static <T> GlobalResult<T> ok(T data, String message) {
GlobalResult<T> globalResult = new GlobalResult<>();
globalResult.setMsg(message);
globalResult.setData(data);
return globalResult;
}
public static <T> GlobalResult<T> error(String msg) {
return error(HttpStatus.INTERNAL_SERVER_ERROR.value(), null, msg);
}
public static <T> GlobalResult<T> error(int code, T data, String msg) {
GlobalResult<T> globalResult = new GlobalResult<>();
globalResult.setCode(code);
globalResult.setData(data);
globalResult.setMsg(msg);
return globalResult;
}
}

@ -0,0 +1,11 @@
package com.supervision.domain;
import lombok.Data;
@Data
public class UserInfo {
private String id;
private String name;
}

@ -0,0 +1,76 @@
/*
* : CustomException
* :
* : <>
* : RedName
* : 2022/8/5
* : <>
* : <>
* : <>
*/
package com.supervision.exception;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
/**
* <>
*
*
* @author ljt
* @version [, 2022/8/5]
* @see [/]
* @since [/]
*/
@Slf4j
public class BusinessException extends RuntimeException {
/**
*
*/
private final Integer code;
/**
*
*/
private final String message;
public BusinessException(Throwable cause) {
super(cause);
this.code = HttpStatus.INTERNAL_SERVER_ERROR.value();
this.message = null;
}
public BusinessException(Throwable cause, String message) {
super(cause);
this.code = HttpStatus.INTERNAL_SERVER_ERROR.value();
this.message = message;
}
public BusinessException(String message) {
this.code = HttpStatus.INTERNAL_SERVER_ERROR.value();
this.message = message;
}
public BusinessException(String message, Integer code) {
this.message = message;
this.code = code;
}
public BusinessException(String message, Throwable e) {
super(message, e);
log.error(message, e);
this.code = HttpStatus.INTERNAL_SERVER_ERROR.value();
this.message = message;
}
@Override
public String getMessage() {
return message;
}
public Integer getCode() {
return code;
}
}

@ -0,0 +1,58 @@
/*
* : CustomException
* :
* : <>
* : RedName
* : 2022/8/5
* : <>
* : <>
* : <>
*/
package com.supervision.exception;
import lombok.extern.slf4j.Slf4j;
/**
* <>
*
*
* @author ljt
* @version [, 2022/8/5]
* @see [/]
* @since [/]
*/
@Slf4j
public class HumanException extends RuntimeException {
/**
* ,,
*/
private static final Integer HUMAN_ERROR = 6001;
/**
*
*/
private final Integer code;
/**
*
*/
private final String message;
private HumanException(Integer code, String message) {
this.code = code;
this.message = message;
}
public static HumanException humanError(String message) {
return new HumanException(HUMAN_ERROR, message);
}
@Override
public String getMessage() {
return message;
}
public Integer getCode() {
return code;
}
}

@ -0,0 +1,127 @@
package com.supervision.util;
import cn.hutool.core.util.ArrayUtil;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import java.util.Map;
/***
* @author ljt
* @since 2020/8/4 17:37
*
*/
@Component
@Lazy(false)
public class SpringBeanUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
/**
* applicationContext
*
* @return ApplicationContext
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
SpringBeanUtil.applicationContext = applicationContext;
}
//通过name获取 Bean.
/**
* name Bean
*
* @param <T> Bean
* @param name Bean
* @return Bean
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
return (T) applicationContext.getBean(name);
}
/**
* classBean
*
* @param <T> Bean
* @param clazz Bean
* @return Bean
*/
public static <T> T getBean(Class<T> clazz) {
return applicationContext.getBean(clazz);
}
/**
* name,ClazzBean
*
* @param <T> bean
* @param name Bean
* @param clazz bean
* @return Bean
*/
public static <T> T getBean(String name, Class<T> clazz) {
return applicationContext.getBean(name, clazz);
}
/**
* Bean
*
* @param <T> Bean
* @param type nullbean
* @return beankeybeannamevalueBean
* @since 5.3.3
*/
public static <T> Map<String, T> getBeansOfType(Class<T> type) {
return applicationContext.getBeansOfType(type);
}
/**
* Bean
*
* @param type nullbean
* @return bean
* @since 5.3.3
*/
public static String[] getBeanNamesForType(Class<?> type) {
return applicationContext.getBeanNamesForType(type);
}
/**
*
*
* @param key key
* @return
* @since 5.3.3
*/
public static String getProperty(String key) {
return applicationContext.getEnvironment().getProperty(key);
}
/**
* null
*
* @return
* @since 5.3.3
*/
public static String[] getActiveProfiles() {
return applicationContext.getEnvironment().getActiveProfiles();
}
/**
*
*
* @return
* @since 5.3.3
*/
public static String getActiveProfile() {
final String[] activeProfiles = getActiveProfiles();
return ArrayUtil.isNotEmpty(activeProfiles) ? activeProfiles[0] : null;
}
}

@ -0,0 +1,19 @@
package com.supervision.util;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.jwt.JWTUtil;
import cn.hutool.jwt.signers.JWTSigner;
import cn.hutool.jwt.signers.JWTSignerUtil;
public class TokenUtil {
public static String creatToken(String userInfo){
final JWTSigner signer = JWTSignerUtil.hs256("123456".getBytes());
JSONObject info = JSONUtil.parseObj(userInfo);
// 过期时间一天,同时这个字段也作为单点登录使用
info.putOnce("expireTime",System.currentTimeMillis() + 1000 * 60 * 60 * 24);
info.putOnce("issueTime",System.currentTimeMillis());
return JWTUtil.createToken(info, signer);
}
}

@ -0,0 +1,20 @@
<?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>
<parent>
<groupId>com.supervision</groupId>
<artifactId>KBQA</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>kbqa-model</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

@ -0,0 +1,119 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.supervision</groupId>
<artifactId>KBQA</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>knowledge-report</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>knowledge-report</name>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<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>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!-- <dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<exclusions>
<exclusion>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</exclusion>
<exclusion>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-common</artifactId>
</exclusion>
</exclusions>
<version>${nacos.discovery.version}</version>
</dependency>-->
<!--<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>-->
<!-- <dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-common</artifactId>
</dependency>-->
<!--<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>${nacos.config.version}</version>
</dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.6.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>4.0.9.RELEASE</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,13 @@
package com.supervision;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class KnowledgeReportApplication {
public static void main(String[] args) {
SpringApplication.run(KnowledgeReportApplication.class, args);
}
}

@ -0,0 +1,21 @@
package com.supervision.controller;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("test")
@RequiredArgsConstructor
public class TestController {
@GetMapping("hello")
public String hello() {
System.out.println("hello");
return "OK";
}
}

@ -0,0 +1,48 @@
server:
port: 9800
servlet:
context-path: /knowledge-report
undertow:
# HTTP post内容的最大大小。当值为-1时默认值为大小是无限的
max-http-post-size: -1
# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
# 每块buffer的空间大小,越小的空间被利用越充分
buffer-size: 512
# 是否分配的直接内存
direct-buffers: true
spring:
profiles:
active: dev
application:
name: knowledge-report
servlet:
multipart:
max-file-size: 100MB
max-request-size: 100MB
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
initial-size: 5 # 初始化大小
min-idle: 10 # 最小连接数
max-active: 20 # 最大连接数
max-wait: 60000 # 获取连接时的最大等待时间
min-evictable-idle-time-millis: 300000 # 一个连接在池中最小生存的时间,单位是毫秒
time-between-eviction-runs-millis: 60000 # 多久才进行一次检测需要关闭的空闲连接,单位是毫秒
filters: stat,wall # 配置扩展插件stat-监控统计log4j-日志wall-防火墙防止SQL注入去掉后监控界面的sql无法统计
validation-query: SELECT 1 # 检测连接是否有效的 SQL语句为空时以下三个配置均无效
test-on-borrow: true # 申请连接时执行validationQuery检测连接是否有效默认true开启后会降低性能
test-on-return: true # 归还连接时执行validationQuery检测连接是否有效默认false开启后会降低性能
test-while-idle: true # 申请连接时如果空闲时间大于timeBetweenEvictionRunsMillis执行validationQuery检测连接是否有效默认false建议开启不影响性能
stat-view-servlet:
enabled: false # 是否开启 StatViewServlet
filter:
stat:
enabled: true # 是否开启 FilterStat默认true
log-slow-sql: true # 是否开启 慢SQL 记录默认false
slow-sql-millis: 5000 # 慢 SQL 的标准,默认 3000单位毫秒
merge-sql: false # 合并多个连接池的监控数据默认false
mybatis-plus:
mapper-locations: classpath*:mapper/**/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

@ -0,0 +1,150 @@
package com.supervision;
import com.supervision.entity.Item;
import com.supervision.repository.ItemRepository;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.aggregations.metrics.InternalAvg;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.FetchSourceFilter;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import java.util.List;
@SpringBootTest
public class DocumentTest {
@Autowired
private ItemRepository itemRepository;
@Test
public void testSave() {
//单个添加
/* Item item = new Item(1L, "小米8", "手机", "小米", 2299.00, "img13.360buyimg.com/12345.jpg");
itemRepository.save(item);
//批量添加
List<Item> list = new ArrayList<>();
list.add(new Item(2L, "荣耀V10", "手机", "华为", 2799.00, "img13.360buyimg.com/111.jpg"));
list.add(new Item(3L, "坚果手机R1", "手机", "锤子", 3699.00, "img13.360buyimg.com/222.jpg"));
list.add(new Item(4L, "华为meta10", "手机", "华为", 4499.00, "img13.360buyimg.com/333.jpg"));
list.add(new Item(5L, "小米Mix2S", "手机", "小米", 4299.00, "img13.360buyimg.com/444.jpg"));
itemRepository.saveAll(list);*/
}
@Test
public void testFindAll() {
Iterable<Item> items = itemRepository.findAll(Sort.by(Sort.Direction.DESC, "price"));
items.forEach(item -> System.out.println(item));
}
@Test
public void queryByPriceBetween() {
List<Item> items = itemRepository.findByPriceBetween(4000.00, 5000.00);
items.forEach(item -> System.out.println(item));
}
@Test
public void testNativeQuery() {
// 构建查询条件
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// 添加基本的分词查询
queryBuilder.withQuery(QueryBuilders.matchQuery("title", "小米"));
// 执行搜索,获取结果
Page<Item> items = itemRepository.search(queryBuilder.build());
// 打印总条数
System.out.println(items.getTotalElements());
// 打印总页数
System.out.println(items.getTotalPages());
items.forEach(System.out::println);
}
@Test
public void testNativePageQuery() {
//设置分页
int page = 0;
int size = 3;
//构建查询条件
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchQuery("category", "手机"))
.withPageable(PageRequest.of(page, size)).build();
//获取结果
Page<Item> items = itemRepository.search(searchQuery);
System.out.println(String.format("总页数:%s", items.getTotalPages()));
System.out.println(String.format("总条数:%s", items.getTotalElements()));
System.out.println(String.format("每页大小:%s", items.getSize()));
System.out.println(String.format("当前页:%s", items.getNumber()));
items.forEach(System.out::println);
}
@Test
public void testSort() {
// 构建查询条件
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchQuery("category", "手机"))
.withSort(SortBuilders.fieldSort("price").order(SortOrder.DESC)).build();
// 执行搜索,获取结果
Page<Item> items = itemRepository.search(searchQuery);
System.out.println(String.format("总条数:%s", items.getTotalElements()));
items.forEach(System.out::println);
}
@Test
public void testAgg() {
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
//不查询任何结果
.withSourceFilter(new FetchSourceFilter(new String[]{""}, null))
// 1、添加一个新的聚合聚合类型为terms聚合名称为brands聚合字段为brand
.addAggregation(AggregationBuilders.terms("brands").field("brand"))
.build();
// 2、查询,需要把结果强转为AggregatedPage类型
AggregatedPage<Item> aggPage = (AggregatedPage<Item>) itemRepository.search(searchQuery);
//3.解析
//3.1取出名为brands的聚合
StringTerms agg = (StringTerms) aggPage.getAggregation("brands");
//3.2获取桶
List<StringTerms.Bucket> buckets = agg.getBuckets();
//3.3遍历
buckets.forEach(bucket ->
System.out.println(String.format("桶的key%s,文档数量:%s", bucket.getKeyAsString(), bucket.getDocCount()))
);
}
@Test
public void testSubAgg() {
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withSourceFilter(new FetchSourceFilter(new String[]{}, null))
.addAggregation(
// 1、添加一个新的聚合聚合类型为terms聚合名称为brands聚合字段为brand
AggregationBuilders.terms("brands").field("brand")
// 在品牌聚合桶内进行嵌套聚合,求平均值
.subAggregation(AggregationBuilders.avg("priceAvg").field("price"))
).build();
// 2、查询,需要把结果强转为AggregatedPage类型
AggregatedPage<Item> aggPage = (AggregatedPage<Item>) itemRepository.search(searchQuery);
// 3、解析
// 3.1、从结果中取出名为brands的那个聚合
// 因为是利用String类型字段来进行的term聚合所以结果要强转为StringTerm类型
StringTerms agg = (StringTerms) aggPage.getAggregation("brands");
// 3.2、获取桶
List<StringTerms.Bucket> buckets = agg.getBuckets();
// 3.3 遍历
buckets.forEach(bucket -> {
// 3.4 获取桶中的key和文档数量
System.out.println(String.format("桶的key%s,文档数量:%s", bucket.getKeyAsString(), bucket.getDocCount()));
// 3.5 获取子聚合结果
InternalAvg avg = (InternalAvg) bucket.getAggregations().asMap().get("priceAvg");
System.out.println("平均售价:" + avg.getValue());
});
}
}

@ -0,0 +1,24 @@
package com.supervision;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;
@Configuration
public class ElasticsearchConfig extends AbstractElasticsearchConfiguration {
@Value("${es.url:127.0.0.1}")
private String url;
@Value("${es.port:9200}")
private Integer port;
@Override
public RestHighLevelClient elasticsearchClient() {
RestClientBuilder builder = RestClient.builder(new HttpHost(url,port));
RestHighLevelClient restHighLevelClient = new RestHighLevelClient(builder);
return restHighLevelClient;
}
}

@ -0,0 +1,13 @@
package com.supervision;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class KnowledgeReportApplicationTests {
@Test
void contextLoads() {
}
}

@ -0,0 +1,109 @@
package com.supervision.entity;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
/**
* Spring Data
*
* @Document
* indexName
* type
* shards5
* replicas1
* @Id id
* @Field
* typeFieldType
* indextrue
* storefalse
* analyzer
*/
@Document(indexName = "item")
public class Item {
@Id
Long id;
@Field(type = FieldType.Text,analyzer = "ik_max_word")
String title; //标题
@Field(type = FieldType.Keyword)
String category;// 分类
@Field(type = FieldType.Keyword)
String brand; // 品牌
@Field(type = FieldType.Double)
Double price; // 价格
@Field(index = false,type = FieldType.Keyword)
String images; // 图片地址
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public String getImages() {
return images;
}
public void setImages(String images) {
this.images = images;
}
public Item() {
}
public Item(Long id, String title, String category, String brand, Double price, String images) {
this.id = id;
this.title = title;
this.category = category;
this.brand = brand;
this.price = price;
this.images = images;
}
@Override
public String toString() {
return "Item{" +
"id=" + id +
", title='" + title + '\'' +
", category='" + category + '\'' +
", brand='" + brand + '\'' +
", price=" + price +
", images='" + images + '\'' +
'}';
}
}

@ -0,0 +1,13 @@
package com.supervision.repository;
import com.supervision.entity.Item;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import java.util.List;
public interface ItemRepository extends ElasticsearchRepository<Item, Long> {
/**
*
*/
List<Item> findByPriceBetween(Double price11, Double price2);
}

@ -0,0 +1,105 @@
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.supervision</groupId>
<artifactId>KBQA</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>knowledge-report</module>
<module>kbqa-common</module>
<module>kbqa-model</module>
</modules>
<properties>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<mysql-connector-java.version>8.0.26</mysql-connector-java.version>
<alibaba.cloud.version>2.2.5.RELEASE</alibaba.cloud.version>
<spring.cloud.version>Hoxton.SR6</spring.cloud.version>
<spring.boot.version>2.3.5.RELEASE</spring.boot.version>
<fastjson.version>1.2.76</fastjson.version>
<mybatis-puls-spring-boot.version>3.3.1</mybatis-puls-spring-boot.version>
<druid.version>1.1.22</druid.version>
<hutool.version>5.8.16</hutool.version>
<knife4j.version>3.0.3</knife4j.version>
<alibaba.cloud.version>2.2.5.RELEASE</alibaba.cloud.version>
<nacos.common.version>1.4.1</nacos.common.version>
<nacos.config.version>2.1.1.RELEASE</nacos.config.version>
<nacos.discovery.version>2.2.3.RELEASE</nacos.discovery.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<!-- SpringBoot集成mybatis框架 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-puls-spring-boot.version}</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>${knife4j.version}</version>
</dependency>
<!-- 数据库连接相关配置 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector-java.version}</version>
</dependency>
<!-- <dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-common</artifactId>
<version>${nacos.common.version}</version>
</dependency>-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${alibaba.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
Loading…
Cancel
Save