houzhongjian
2025-02-28 cb8c71fc15ab1bd4590dd3ef475056dd9e4f60cd
平台授权SDK
已添加14个文件
697 ■■■■■ 文件已修改
sdk/pom.xml 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sdk/src/main/java/com/iailab/sdk/SdkMain.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sdk/src/main/java/com/iailab/sdk/auth/client/IailabAuthClient.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sdk/src/main/java/com/iailab/sdk/auth/client/dto/TokenDTO.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sdk/src/main/java/com/iailab/sdk/auth/client/vo/AuthLoginReqVO.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sdk/src/main/java/com/iailab/sdk/auth/config/SdkConfiguration.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sdk/src/main/java/com/iailab/sdk/auth/interceptor/AuthInterceptor.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sdk/src/main/java/com/iailab/sdk/util/http/HttpClientFactory.java 162 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sdk/src/main/java/com/iailab/sdk/util/http/IailabHttpUtils.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sdk/src/main/java/com/iailab/sdk/util/package-info.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sdk/src/main/resources/application-dev.yaml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sdk/src/main/resources/application.yaml 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sdk/src/test/java/com/iailab/sdk/IailabClientTest.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sdk/src/test/resources/application-unit-test.yaml 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sdk/pom.xml
对比新文件
@@ -0,0 +1,86 @@
<?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">
    <parent>
        <groupId>com.iailab</groupId>
        <artifactId>iailab-plat</artifactId>
        <version>${revision}</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>sdk</artifactId>
    <packaging>jar</packaging>
    <name>${project.artifactId}</name>
    <description>
        sdk
    </description>
    <dependencies>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.13</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.55</version>
        </dependency>
        <dependency>
            <groupId>com.iailab</groupId>
            <artifactId>iailab-common</artifactId>
            <version>${revision}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </dependency>
        <dependency>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</artifactId>
        </dependency>
        <dependency>
            <groupId>com.iailab</groupId>
            <artifactId>iailab-common-test</artifactId>
        </dependency>
    </dependencies>
<!--    <build>-->
<!--        &lt;!&ndash; 设置构建的 jar 包名 &ndash;&gt;-->
<!--        <finalName>${project.artifactId}</finalName>-->
<!--        <plugins>-->
<!--            &lt;!&ndash; 打包 &ndash;&gt;-->
<!--            <plugin>-->
<!--                <groupId>org.springframework.boot</groupId>-->
<!--                <artifactId>spring-boot-maven-plugin</artifactId>-->
<!--                <version>${spring.boot.version}</version>-->
<!--                <executions>-->
<!--                    <execution>-->
<!--                        <goals>-->
<!--                            <goal>repackage</goal> &lt;!&ndash; 将引入的 jar 打入其中 &ndash;&gt;-->
<!--                        </goals>-->
<!--                    </execution>-->
<!--                </executions>-->
<!--            </plugin>-->
<!--        </plugins>-->
<!--    </build>-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.3.0</version>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
sdk/src/main/java/com/iailab/sdk/SdkMain.java
对比新文件
@@ -0,0 +1,14 @@
package com.iailab.sdk;
/**
 * 项目的主类
 *
 * @author iailab
 */
public class SdkMain {
    public static void main(String[] args) {
        System.out.println("I am the main class");
    }
}
sdk/src/main/java/com/iailab/sdk/auth/client/IailabAuthClient.java
对比新文件
@@ -0,0 +1,94 @@
package com.iailab.sdk.auth.client;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.iailab.sdk.auth.client.dto.TokenDTO;
import com.iailab.sdk.auth.client.vo.AuthLoginReqVO;
import com.iailab.sdk.auth.config.SdkConfiguration;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.web.client.RestTemplate;
import java.util.*;
/**
 * @author Houzhongjian
 * @Description
 * @createTime 2025年02月18日
 */
@Component
@Service
public class IailabAuthClient {
    /**
     * 平台地址
     */
    public static String BASE_URL = "http://172.16.8.100:48080/admin-api";
    /**
     * 租户编号
     */
    public static String TENANT_ID = "1";
    private static final RestTemplate restTemplate = new RestTemplate();
    /**
     * 用户名密码方式获取平台token
     */
    public static synchronized TokenDTO login(AuthLoginReqVO loginReqVO) throws Exception {
        System.out.println("登录获取平台token");
        ObjectMapper objectMapper = new ObjectMapper();
        String paramString = objectMapper.writeValueAsString(loginReqVO);
        // 1.1 构建请求头
        HttpHeaders headers = new HttpHeaders();
        addClientHeader(headers);
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        // 1.2 构建authenticate请求URL
        String authenticateUrl = BASE_URL + "/system/auth/login";
        // 2. 执行请求
        ResponseEntity<Map<String, Object>> exchange = restTemplate.exchange(
                authenticateUrl,
                HttpMethod.POST,
                new HttpEntity<>(paramString, headers),
                new ParameterizedTypeReference<Map<String, Object>>() {
                });
        return handleResponse(exchange);
    }
    public static synchronized TokenDTO refreshToken(String refreshToken) {
        System.out.println("刷新token");
        // 1.1 构建请求头
        HttpHeaders headers = new HttpHeaders();
        addClientHeader(headers);
        // 1.2 构建authenticate请求URL
        String authenticateUrl = BASE_URL + "/system/auth/refresh-token?refreshToken=" + refreshToken;
        // 2. 执行请求
        ResponseEntity<Map<String, Object>> exchange = restTemplate.exchange(
                authenticateUrl,
                HttpMethod.POST,
                new HttpEntity<>(headers),
                new ParameterizedTypeReference<Map<String, Object>>() {
                });
        return handleResponse(exchange);
    }
    private static void addClientHeader(HttpHeaders headers) {
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.set("tenant-id", TENANT_ID);
    }
    // 统一处理响应
    private static <T> TokenDTO handleResponse(ResponseEntity<T> response) {
        Assert.isTrue(response.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功");
        System.out.println(response);
        TokenDTO authTokenDTO = new TokenDTO();
        Map<String, Object> authMap = (Map<String, Object>)response.getBody();
        Map<String, Object> tokenData = (Map<String, Object>)authMap.get("data");
        authTokenDTO.setAccessToken(tokenData.get("accessToken").toString());
        authTokenDTO.setRefreshToken(tokenData.get("refreshToken").toString());
        authTokenDTO.setExpiresTime(Long.valueOf(tokenData.get("expiresTime").toString()));
        return authTokenDTO;
    }
}
sdk/src/main/java/com/iailab/sdk/auth/client/dto/TokenDTO.java
对比新文件
@@ -0,0 +1,11 @@
package com.iailab.sdk.auth.client.dto;
import lombok.Data;
@Data
public class TokenDTO {
    private String accessToken;
    private String refreshToken;
    private Long expiresTime;
    private String tokenType;
}
sdk/src/main/java/com/iailab/sdk/auth/client/vo/AuthLoginReqVO.java
对比新文件
@@ -0,0 +1,31 @@
package com.iailab.sdk.auth.client.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AuthLoginReqVO {
    @NotEmpty(message = "登录账号不能为空")
    @Length(min = 4, max = 16, message = "账号长度为 4-16 位")
    @Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母")
    private String username;
    @NotEmpty(message = "密码不能为空")
    @Length(min = 4, max = 16, message = "密码长度为 4-16 位")
    private String password;
    // ========== 图片验证码相关 ==========
    private String captchaVerification;
}
sdk/src/main/java/com/iailab/sdk/auth/config/SdkConfiguration.java
对比新文件
@@ -0,0 +1,48 @@
package com.iailab.sdk.auth.config;
import org.springframework.context.annotation.Configuration;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
 * SDK配置文件
 */
@Configuration
public class SdkConfiguration {
    private String baseUrl;
    public String getTenantId() {
        return tenantId;
    }
    private String tenantId;
    public static SdkConfiguration load() {
        SdkConfiguration config = new SdkConfiguration();
        try(InputStream is = SdkConfiguration.class.getResourceAsStream("/application.yaml")) {
            Properties props = new Properties();
            props.load(is);
            config.baseUrl = props.getProperty("base-url");
            config.tenantId = props.getProperty("tenant-id");
        } catch (IOException e) {
            // 处理异常或使用默认值
        }
        if(config.baseUrl == null) {
            throw new IllegalStateException("BaseUrl must be configured");
        }
        if(config.tenantId  == null) {
            throw new IllegalStateException("TenantId must be configured");
        }
        return config;
    }
    public String getBaseUrl() {
        return baseUrl;
    }
}
sdk/src/main/java/com/iailab/sdk/auth/interceptor/AuthInterceptor.java
对比新文件
@@ -0,0 +1,26 @@
//package com.iailab.module.sdk.auth.interceptor;
//
//import org.springframework.http.HttpRequest;
//import org.springframework.http.client.ClientHttpRequestExecution;
//import org.springframework.http.client.ClientHttpRequestInterceptor;
//import org.springframework.http.client.ClientHttpResponse;
//
//import java.io.IOException;
//
//public class AuthInterceptor implements ClientHttpRequestInterceptor {
//
//    private final AuthTokenHolder tokenHolder;
//
//    public AuthInterceptor(AuthTokenHolder tokenHolder) {
//        this.tokenHolder = tokenHolder;
//    }
//
//    @Override
//    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) {
//        if (tokenHolder.getToken() != null) {
//            request.getHeaders().setBearerAuth(tokenHolder.getToken());
//        }
//        return execution.execute(request, body);
//    }
//
//}
sdk/src/main/java/com/iailab/sdk/util/http/HttpClientFactory.java
对比新文件
@@ -0,0 +1,162 @@
package com.iailab.sdk.util.http;
import com.alibaba.fastjson.JSON;
import org.apache.http.HttpEntity;
import org.apache.http.HttpRequest;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.SSLContext;
import java.io.Closeable;
import java.io.IOException;
import java.util.Map;
public  class HttpClientFactory {
    private static final Logger logger = LoggerFactory.getLogger(HttpClientFactory.class);
    private static PoolingHttpClientConnectionManager clientConnectionManager=null;
    // private static CloseableHttpClient httpClient=null;
    private static RequestConfig config = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD_STRICT).build();
    // private final static Object syncLock = new Object();
    private static boolean isInited=false;
    /**
     * 创建httpclient连接池并初始化
     */
    private static void init(){
    if(isInited)return;
        try {
            //添加对https的支持,该sslContext没有加载客户端证书
            // 如果需要加载客户端证书,请使用如下sslContext,其中KEYSTORE_FILE和KEYSTORE_PASSWORD分别是你的证书路径和证书密码
            //KeyStore keyStore  =  KeyStore.getInstance(KeyStore.getDefaultType()
            //FileInputStream instream =   new FileInputStream(new File(KEYSTORE_FILE));
            //keyStore.load(instream, KEYSTORE_PASSWORD.toCharArray());
            //SSLContext sslContext = SSLContexts.custom().loadKeyMaterial(keyStore,KEYSTORE_PASSWORD.toCharArray())
            // .loadTrustMaterial(null, new TrustSelfSignedStrategy())
            //.build();
            SSLContext sslContext = SSLContexts.custom()
                    .loadTrustMaterial(null, new TrustSelfSignedStrategy())
                    .build();
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,SSLConnectionSocketFactory.getDefaultHostnameVerifier());
            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("https", sslsf)
                    .register("http", PlainConnectionSocketFactory.getSocketFactory())
                    .build();
            clientConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
            clientConnectionManager.setMaxTotal(50);
            clientConnectionManager.setDefaultMaxPerRoute(25);
            isInited=true;
        }catch (Exception e){
            logger.warn("httpUtils init get exception:",e);
        }
    }
    public static CloseableHttpClient getHttpClient(){
        init();
//        if(httpClient == null){
//            synchronized (syncLock){
//                if(httpClient == null){
////                    CookieStore cookieStore = new BasicCookieStore();
////                    BasicClientCookie cookie = new BasicClientCookie("sessionID", "######");
////                    cookie.setDomain("#####");
////                    cookie.setPath("/");
////                    cookieStore.addCookie(cookie);
//                    httpClient =HttpClients.custom().setConnectionManager(clientConnectionManager)
//                            //.setDefaultCookieStore(cookieStore)
//                            .setDefaultRequestConfig(config).build();
//                }
//            }
//        }
 //       return httpClient;
        return HttpClients.custom().setConnectionManager(clientConnectionManager)
                            //.setDefaultCookieStore(cookieStore)
                            .setDefaultRequestConfig(config).build();
    }
    /**
     * 设置请求头信息
     * @param headers
     * @param request
     * @return
     */
    private static HttpRequest setHeaders(Map<String,Object> headers, HttpRequest request) {
        for (Map.Entry entry : headers.entrySet()) {
            if (!entry.getKey().equals("Cookie")) {
                request.addHeader((String) entry.getKey(), (String) entry.getValue());
            } else {
                Map<String, Object> Cookies = (Map<String, Object>) entry.getValue();
                for (Map.Entry entry1 : Cookies.entrySet()) {
                    request.addHeader(new BasicHeader("Cookie", (String) entry1.getValue()));
                }
            }
        }
        return request;
    }
    /**
     * post请求,使用json格式传参
     * @param url
     * @param data
     * @param headers
     * @return
     */
    public static <T> T httpPost(String url, String data, Map<String,Object> headers,Class<T> clazz){
        CloseableHttpClient httpClient = getHttpClient();
        HttpRequest request = new HttpPost(url);
        if(headers!=null&&!headers.isEmpty()){
            request = setHeaders(headers,request);
        }
        CloseableHttpResponse response = null;
        try {
            HttpPost httpPost = (HttpPost) request;
            httpPost.setEntity(new StringEntity(data, ContentType.create("application/json", "UTF-8")));
            response=httpClient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            if (HttpStatus.SC_OK == response.getStatusLine().getStatusCode() && null != entity) {
                String respBody = EntityUtils.toString(entity);
                logger.info("validate st response:"+respBody);
                T respObj = (T) JSON.parseObject(respBody, clazz);
                return respObj;
            }
        } catch (IOException e) {
            logger.error("http post exec error,msg"+e.getMessage(),e);
        }
        finally {
            safeClose(response,null);
           // safeClose(httpClient,null);
        }
        return null;
    }
    private static   void safeClose(Closeable closeable,String errMsg){
        try{
            if(closeable!=null)
            closeable.close();
        }catch (Exception ex){
            if(errMsg!=null && "".equals(errMsg)){
                logger.error(errMsg+",error:"+ex.getMessage(),ex);
            }
        }
    }
}
sdk/src/main/java/com/iailab/sdk/util/http/IailabHttpUtils.java
对比新文件
@@ -0,0 +1,106 @@
package com.iailab.sdk.util.http;
import com.iailab.sdk.auth.client.IailabAuthClient;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.springframework.util.CollectionUtils;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;
public class IailabHttpUtils {
    /**
     *
     * @param url
     * @param map
     * @param charset
     * @return
     */
    public static String doGet(String url, Map<String, String> map, String charset, String accessToken) {
        System.out.println("start doGet url: " + url);
        org.apache.http.client.HttpClient httpClient = null;
        HttpGet httpGet = null;
        String result = null;
        try {
            StringBuilder sb = new StringBuilder();
            sb.append(url);
            if (!CollectionUtils.isEmpty(map)) {
                if ((url.indexOf("?") == -1)) {
                    sb.append("?");
                } else {
                    sb.append("&");
                }
                map.forEach((k, v) -> {
                    try {
                        sb.append(k + "=" + URLEncoder.encode(v, charset) + "&");
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                });
                sb.append("t=" + System.currentTimeMillis());
            }
            httpClient = HttpClientFactory.getHttpClient();
            httpGet = new HttpGet(sb.toString());
            //设置参数
            httpGet.addHeader("Accept", "application/json");
            httpGet.addHeader("Content-Type", "application/json;charset=UTF-8");
            httpGet.addHeader("Authorization", "Bearer " + accessToken);
            httpGet.addHeader("Tenant-Id", String.valueOf(IailabAuthClient.TENANT_ID));
            HttpResponse response = httpClient.execute(httpGet);
            if (response != null) {
                HttpEntity resEntity = response.getEntity();
                if (resEntity != null) {
                    result = EntityUtils.toString(resEntity, charset);
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return result;
    }
    /**
     *
     * @param url
     * @param json
     * @param charset
     * @return
     */
    public static String doPost(String url, String json, String charset, String accessToken) {
        System.out.println("start doPost url: " + url);
        org.apache.http.client.HttpClient httpClient = null;
        HttpPost httpPost = null;
        String result = null;
        try {
            httpClient = HttpClientFactory.getHttpClient();
            httpPost = new HttpPost(url);
            //设置参数
            httpPost.addHeader("Accept", "application/json");
            httpPost.addHeader("Content-Type", "application/json;charset=UTF-8");
            httpPost.addHeader("Authorization", "Bearer " + accessToken);
            httpPost.addHeader("Tenant-Id", String.valueOf(IailabAuthClient.TENANT_ID));
            StringEntity stringEntity = new StringEntity(json);
            stringEntity.setContentEncoding("UTF-8");
            stringEntity.setContentType("application/json");
            httpPost.setEntity(stringEntity);
            HttpResponse response = httpClient.execute(httpPost);
            if (response != null) {
                HttpEntity resEntity = response.getEntity();
                if (resEntity != null) {
                    result = EntityUtils.toString(resEntity, charset);
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return result;
    }
}
sdk/src/main/java/com/iailab/sdk/util/package-info.java
对比新文件
@@ -0,0 +1,4 @@
/**
 * 每个模块的 util 包,放专属当前模块的 Utils 工具类
 */
package com.iailab.sdk.util;
sdk/src/main/resources/application-dev.yaml
对比新文件
@@ -0,0 +1,6 @@
--- #################### SDK相关配置 ####################
iailab:
  auth:
    base-url: http://172.16.8.100:48080/admin-api
    tenant-id: 1
sdk/src/main/resources/application.yaml
对比新文件
@@ -0,0 +1,13 @@
spring:
  application:
    name: sdk
  profiles:
    active: dev
iailab:
  auth:
    base-url: http://172.16.8.100:48080/admin-api
    tenant-id: 1
sdk/src/test/java/com/iailab/sdk/IailabClientTest.java
对比新文件
@@ -0,0 +1,39 @@
package com.iailab.sdk;
import com.iailab.framework.test.core.ut.BaseMockitoUnitTest;
import com.iailab.sdk.auth.client.IailabAuthClient;
import com.iailab.sdk.auth.client.dto.TokenDTO;
import com.iailab.sdk.auth.client.vo.AuthLoginReqVO;
import org.junit.jupiter.api.Test;
import javax.annotation.Resource;
/**
 * {@link IailabClientTest} 的单元测试
 *
 * @author iailab
 */
public class IailabClientTest extends BaseMockitoUnitTest {
    @Test
    public void testLogin() throws Exception {
        // 准备参数
        AuthLoginReqVO authLoginReqVO = new AuthLoginReqVO();
        authLoginReqVO.setUsername("sysadmin");
        authLoginReqVO.setPassword("iailab2019");
        TokenDTO login = IailabAuthClient.login(authLoginReqVO);
        System.out.println(login.getAccessToken());
        System.out.println(login.getRefreshToken());
    }
    @Test
    public void testRefreshToken() {
        // 准备参数
        String refreshToken = "1d62031562364ed29d6d414fea97e2dd";
        TokenDTO tokenDTO = IailabAuthClient.refreshToken(refreshToken);
        System.out.println(tokenDTO);
    }
}
sdk/src/test/resources/application-unit-test.yaml
对比新文件
@@ -0,0 +1,57 @@
spring:
  main:
    lazy-initialization: true # 开启懒加载,加快速度
    banner-mode: off # 单元测试,禁用 Banner
--- #################### 数据库相关配置 ####################
spring:
  # 数据源配置项
  datasource:
    name: ruoyi-vue-pro
    url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false;NON_KEYWORDS=value; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写
    driver-class-name: org.h2.Driver
    username: sa
    password:
    druid:
      async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度
      initial-size: 1 # 单元测试,配置为 1,提升启动速度
  sql:
    init:
      schema-locations: classpath:/sql/create_tables.sql
  # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
  redis:
    host: 127.0.0.1 # 地址
    port: 16379 # 端口(单元测试,使用 16379 端口)
    database: 0 # 数据库索引
mybatis:
  lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试
mybatis-plus:
  global-config:
    db-config:
      id-type: AUTO # H2 主键递增
--- #################### 定时任务相关配置 ####################
--- #################### 配置中心相关配置 ####################
--- #################### 服务保障相关配置 ####################
# Lock4j 配置项(单元测试,禁用 Lock4j)
--- #################### 监控相关配置 ####################
--- #################### 平台相关配置 ####################
# 平台配置项,设置当前项目所有自定义的配置
iailab:
  info:
    base-package: com.iailab.module
  captcha:
    timeout: 5m
    width: 160
    height: 60
    enable: true