package init
parent
bd7831b4bc
commit
9edb5300a9
@ -0,0 +1,91 @@
|
|||||||
|
package com.supervision.nxllmcommon.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.nxllmcommon.exception.BusinessException;
|
||||||
|
import com.supervision.nxllmcommon.util.TokenUtil;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class JwtInterceptor implements HandlerInterceptor {
|
||||||
|
|
||||||
|
public JwtInterceptor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
|
||||||
|
//请求消息头获取用户ID
|
||||||
|
String token = request.getHeader("token");
|
||||||
|
if (StrUtil.isBlank(token)) {
|
||||||
|
// 如果是swagger来的接口,说明这里是测试的,会伪造一个用户
|
||||||
|
String referer = request.getHeader("Referer");
|
||||||
|
if (StrUtil.isNotBlank(referer) && StrUtil.contains(referer, "doc.html")) {
|
||||||
|
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(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull 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,31 @@
|
|||||||
|
package com.supervision.nxllmcommon.config;
|
||||||
|
|
||||||
|
import io.minio.MinioClient;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class MinioConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建基于Java端的MinioClient
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnProperty(prefix = "minio", name = "url")
|
||||||
|
public MinioClient minioClient(MinioProperties minioProperties) {
|
||||||
|
OkHttpClient.Builder builder = new OkHttpClient.Builder();
|
||||||
|
builder.connectTimeout(60, TimeUnit.SECONDS);
|
||||||
|
builder.readTimeout(120, TimeUnit.SECONDS);
|
||||||
|
builder.callTimeout(120, TimeUnit.SECONDS);
|
||||||
|
return MinioClient.builder().endpoint(minioProperties.getUrl())
|
||||||
|
.httpClient(builder.build())
|
||||||
|
.credentials(minioProperties.getAccessKey(), minioProperties.getSecretKey())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.supervision.nxllmcommon.config;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Component
|
||||||
|
@ConfigurationProperties(prefix = "minio")
|
||||||
|
public class MinioProperties {
|
||||||
|
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
private String accessKey;
|
||||||
|
|
||||||
|
private String secretKey;
|
||||||
|
|
||||||
|
private String bucketName;
|
||||||
|
}
|
@ -0,0 +1,125 @@
|
|||||||
|
package com.supervision.nxllmcommon.config;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import com.supervision.nxllmcommon.domain.GlobalResult;
|
||||||
|
import com.supervision.nxllmcommon.exception.BusinessException;
|
||||||
|
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.supervision.**.controller"})
|
||||||
|
public class ResponseConfig implements ResponseBodyAdvice<Object> {
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supports(@Nullable MethodParameter methodParameter,
|
||||||
|
@Nullable Class<? extends HttpMessageConverter<?>> aClass) {
|
||||||
|
assert methodParameter != null;
|
||||||
|
String lowerCase = methodParameter.getDeclaringClass().getName().toLowerCase();
|
||||||
|
log.info(lowerCase);
|
||||||
|
if (lowerCase.contains("swagger") || lowerCase.contains("springdoc")) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
log.info("--------{}---------", lowerCase);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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({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.nxllmcommon.config;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <功能详细描述>
|
||||||
|
*
|
||||||
|
* @author ljt
|
||||||
|
* @version [版本号, 2023/9/4]
|
||||||
|
* @see [相关类/方法]
|
||||||
|
* @since [产品/模块版本]
|
||||||
|
*/
|
||||||
|
public class ThreadCache {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户ID
|
||||||
|
*/
|
||||||
|
public static final ThreadLocal<String> USER = new ThreadLocal<>();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
package com.supervision.nxllmcommon.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("/v3/**");
|
||||||
|
paths.add("/swagger-ui.html/**");
|
||||||
|
paths.add("/swagger-ui/**");
|
||||||
|
paths.add("/webjars/");
|
||||||
|
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,45 @@
|
|||||||
|
package com.supervision.nxllmcommon.domain;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class GlobalResult<T> {
|
||||||
|
|
||||||
|
private int code = 200;
|
||||||
|
|
||||||
|
private String msg = "success";
|
||||||
|
|
||||||
|
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,76 @@
|
|||||||
|
/*
|
||||||
|
* 文 件 名: CustomException
|
||||||
|
* 版 权:
|
||||||
|
* 描 述: <描述>
|
||||||
|
* 修 改 人: RedName
|
||||||
|
* 修改时间: 2022/8/5
|
||||||
|
* 跟踪单号: <跟踪单号>
|
||||||
|
* 修改单号: <修改单号>
|
||||||
|
* 修改内容: <修改内容>
|
||||||
|
*/
|
||||||
|
package com.supervision.nxllmcommon.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,106 @@
|
|||||||
|
package com.supervision.nxllmcommon.util;
|
||||||
|
|
||||||
|
import cn.hutool.core.thread.ThreadUtil;
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.ai.chat.ChatResponse;
|
||||||
|
import org.springframework.ai.chat.messages.Message;
|
||||||
|
import org.springframework.ai.chat.messages.UserMessage;
|
||||||
|
import org.springframework.ai.chat.prompt.Prompt;
|
||||||
|
import org.springframework.ai.ollama.OllamaChatClient;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class AiChatUtil {
|
||||||
|
|
||||||
|
private static final ExecutorService chatExecutor = ThreadUtil.newFixedExecutor(5, 5, "chat", new ThreadPoolExecutor.CallerRunsPolicy());
|
||||||
|
|
||||||
|
private static final OllamaChatClient chatClient = SpringBeanUtil.getBean(OllamaChatClient.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单轮对话
|
||||||
|
*
|
||||||
|
* @param chat 对话的内容
|
||||||
|
* @return jsonObject
|
||||||
|
*/
|
||||||
|
public static Optional<JSONObject> chat(String chat) {
|
||||||
|
Prompt prompt = new Prompt(List.of(new UserMessage(chat)));
|
||||||
|
Future<String> submit = chatExecutor.submit(new ChatTask(chatClient, prompt));
|
||||||
|
try {
|
||||||
|
return Optional.of(JSONUtil.parseObj(submit.get()));
|
||||||
|
} catch (ExecutionException | InterruptedException e) {
|
||||||
|
log.error("调用大模型生成失败");
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支持多轮对话,自定义消息
|
||||||
|
*
|
||||||
|
* @param messageList 消息列表
|
||||||
|
* @return jsonObject
|
||||||
|
*/
|
||||||
|
public static Optional<JSONObject> chat(List<Message> messageList) {
|
||||||
|
Prompt prompt = new Prompt(messageList);
|
||||||
|
Future<String> submit = chatExecutor.submit(new ChatTask(chatClient, prompt));
|
||||||
|
try {
|
||||||
|
return Optional.of(JSONUtil.parseObj(submit.get()));
|
||||||
|
} catch (ExecutionException | InterruptedException e) {
|
||||||
|
log.error("调用大模型生成失败");
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支持序列化的方式
|
||||||
|
*
|
||||||
|
* @param messageList 消息列表
|
||||||
|
* @param clazz 需要序列化的对象
|
||||||
|
* @param <T> 需要序列化的对象的泛型
|
||||||
|
* @return 对应对象类型, 不支持列表类型
|
||||||
|
*/
|
||||||
|
public static <T> Optional<T> chat(List<Message> messageList, Class<T> clazz) {
|
||||||
|
Prompt prompt = new Prompt(messageList);
|
||||||
|
Future<String> submit = chatExecutor.submit(new ChatTask(chatClient, prompt));
|
||||||
|
try {
|
||||||
|
String s = submit.get();
|
||||||
|
return Optional.ofNullable(JSONUtil.toBean(s, clazz));
|
||||||
|
} catch (ExecutionException | InterruptedException e) {
|
||||||
|
log.error("调用大模型生成失败", e);
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支持序列化的方式的对话
|
||||||
|
*
|
||||||
|
* @param chat 对话的消息
|
||||||
|
* @param clazz 需要序列化的对象
|
||||||
|
* @param <T> 需要序列化的对象的泛型
|
||||||
|
* @return 对应对象类型, 不支持列表类型
|
||||||
|
*/
|
||||||
|
public static <T> Optional<T> chat(String chat, Class<T> clazz) {
|
||||||
|
Prompt prompt = new Prompt(List.of(new UserMessage(chat)));
|
||||||
|
Future<String> submit = chatExecutor.submit(new ChatTask(chatClient, prompt));
|
||||||
|
try {
|
||||||
|
String s = submit.get();
|
||||||
|
return Optional.ofNullable(JSONUtil.toBean(s, clazz));
|
||||||
|
} catch (ExecutionException | InterruptedException e) {
|
||||||
|
log.error("调用大模型生成失败");
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private record ChatTask(OllamaChatClient chatClient, Prompt prompt) implements Callable<String> {
|
||||||
|
@Override
|
||||||
|
public String call() {
|
||||||
|
ChatResponse call = chatClient.call(prompt);
|
||||||
|
return call.getResult().getOutput().getContent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.supervision.nxllmcommon.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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue