# xiaodu-demo **Repository Path**: chenchenche/xiaodu-demo ## Basic Information - **Project Name**: xiaodu-demo - **Description**: 基于 Spring Boot + OkHttp 实现的百度小度 DuerOS API 集成项目,支持OAuth认证和7种推送模板类型。采用DTO设计模式,提供清晰、类型安全的API接口。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-01-30 - **Last Updated**: 2026-01-30 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 百度小度 API 集成项目 基于 Spring Boot + OkHttp 实现的百度小度 DuerOS API 集成项目,支持OAuth认证和7种推送模板类型。采用**DTO设计模式**,提供清晰、类型安全的API接口。 ## 功能特性 - ✅ OAuth 2.0 认证(获取/刷新Access Token) - ✅ 7种推送模板类型完整实现 - ✅ **DTO设计模式** - 请求响应全部对象化 - ✅ **统一响应格式** - Result统一封装 - ✅ **参数校验** - JSR-303注解验证 - ✅ 完整的异常处理和日志记录 - ✅ 代码复用性高,易于维护 - ✅ **完整测试套件** - JUnit 单元测试 + 集成测试 - ✅ **便捷测试工具** - Shell/Batch 脚本 + Postman 集合 ## 快速开始 ### 1. 配置应用信息 编辑 `src/main/resources/application.yml`: ```yaml xiaodu: api: base-url: https://dueros.baidu.com/business app-id: YOUR_APP_ID # 替换为你的 APP_ID app-secret: YOUR_APP_SECRET # 替换为你的 APP_SECRET ``` ### 2. 构建并运行 ```bash # 构建项目 mvn clean package # 运行项目 mvn spring-boot:run ``` ### 3. 运行测试 项目提供了完整的测试用例,包括 OAuth 认证和所有 7 种推送模板的测试。 **注意**: 运行测试前,请修改测试类中的 `TEST_CUID` 为您的真实设备 ID: ```java // 位置:src/test/java/com/xiaodu/demo/service/XiaoduPushServiceTest.java private static final String TEST_CUID = "your-device-cuid-here"; ``` **运行所有测试:** ```bash mvn test ``` **运行单个测试:** ```bash # 测试 OAuth 服务 mvn test -Dtest=XiaoduOAuthServiceTest # 测试推送服务 mvn test -Dtest=XiaoduPushServiceTest ``` **测试覆盖:** - ✅ OAuth 认证测试(获取/刷新 Token) - ✅ 纯文本推送测试 - ✅ 全图片推送测试 - ✅ 左图右文推送测试 - ✅ 上图下文推送测试 - ✅ 音频推送测试 - ✅ 视频推送测试 - ✅ SSML 播报推送测试 ### 4. 使用测试脚本 项目提供了便捷的测试脚本,可一键测试所有接口: **Linux/Mac:** ```bash # 赋予执行权限 chmod +x test-api.sh # 运行测试(替换为您的设备 CUID) ./test-api.sh your-device-cuid ``` **Windows:** ```cmd # 运行测试(替换为您的设备 CUID) test-api.bat your-device-cuid ``` ### 5. 使用 Postman 项目提供了 Postman 集合文件 `Xiaodu-API.postman_collection.json`,包含所有接口: 1. 导入 Postman 集合 2. 设置环境变量: - `base_url`: http://localhost:8080 - `device_cuid`: 您的设备 CUID 3. 执行 "获取 Access Token" 请求 4. 将返回的 `accessToken` 设置到环境变量 `access_token` 5. 测试其他推送接口 ## API接口文档 ### 统一响应格式 所有接口统一返回`Result`对象: ```json { "success": true, "errno": null, "message": "操作成功", "data": { // 具体业务数据 } } ``` --- ### OAuth认证接口 #### 1. 获取Access Token ```bash curl -X GET http://localhost:8080/api/xiaodu/token ``` **响应示例:** ```json { "success": true, "message": "操作成功", "data": { "accessToken": "eyJ0eXAiOiJKV1QiLCJhbGc...", "expiresIn": 2592000, "deadline": 1543393183, "refreshToken": "eyJ0eXAiOiJKV1QiLCJhbGc..." } } ``` --- ### 推送接口 所有推送接口都使用 **POST + JSON Body** 方式,并在Header中携带Authorization。 #### 1. 纯文本推送(AllText) **接口:** `POST /api/xiaodu/push/text` **请求示例:** ```bash curl -X POST \ http://localhost:8080/api/xiaodu/push/text \ -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "cuid": "MA718CNBFCL010122", "title": "托尔斯泰格言", "content": "托尔斯泰 - 理想的书籍,是智慧的钥匙" }' ``` **请求字段:** | 字段 | 类型 | 必填 | 说明 | |-----|------|-----|------| | cuid | String | 是 | 设备唯一标识 | | title | String | 是 | 推送标题 | | content | String | 是 | 推送内容 | **响应示例:** ```json { "success": true, "message": "推送成功", "data": { "result": "success", "msgId": "1234567890" } } ``` --- #### 2. 全图片推送(AllImage) **接口:** `POST /api/xiaodu/push/allImage` **请求示例:** ```bash curl -X POST \ http://localhost:8080/api/xiaodu/push/allImage \ -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "cuid": "MA718CNBFCL010122", "imageSrc": "https://example.com/image.jpg", "imageThumb": "https://example.com/thumb.jpg" }' ``` **请求字段:** | 字段 | 类型 | 必填 | 说明 | |-----|------|-----|------| | cuid | String | 是 | 设备唯一标识 | | imageSrc | String | 是 | 图片地址 | | imageThumb | String | 是 | 图片缩略图地址 | --- #### 3. 左图右文推送(TextRight) **接口:** `POST /api/xiaodu/push/textRight` **请求示例:** ```bash curl -X POST \ http://localhost:8080/api/xiaodu/push/textRight \ -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "cuid": "MA718CNBFCL010122", "title": "托尔斯泰格言", "content": "托尔斯泰 - 理想的书籍,是智慧的钥匙", "image": "https://example.com/image.jpg" }' ``` **请求字段:** | 字段 | 类型 | 必填 | 说明 | |-----|------|-----|------| | cuid | String | 是 | 设备唯一标识 | | title | String | 是 | 推送标题 | | content | String | 是 | 推送内容 | | image | String | 是 | 图片地址 | --- #### 4. 上图下文推送(TextBottom) **接口:** `POST /api/xiaodu/push/textBottom` **请求参数同左图右文,使用相同的请求格式。** --- #### 5. 音频推送(AudioPlayer) **接口:** `POST /api/xiaodu/push/audio` **请求示例:** ```bash curl -X POST \ http://localhost:8080/api/xiaodu/push/audio \ -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "cuid": "MA718CNBFCL010122", "streamUrl": "https://example.com/audio.mp3", "title": "告白气球", "titleSubtext1": "周杰伦", "titleSubtext2": "周杰伦的床边故事", "artSrc": "https://example.com/cover.jpg" }' ``` **请求字段:** | 字段 | 类型 | 必填 | 说明 | |-----|------|-----|------| | cuid | String | 是 | 设备唯一标识 | | streamUrl | String | 是 | 音频流地址 | | title | String | 否 | 音频标题 | | titleSubtext1 | String | 否 | 子标题1(歌手名) | | titleSubtext2 | String | 否 | 子标题2(专辑名) | | artSrc | String | 否 | 封面图片 | --- #### 6. 视频推送(VideoPlayer) **接口:** `POST /api/xiaodu/push/video` **请求示例:** ```bash curl -X POST \ http://localhost:8080/api/xiaodu/push/video \ -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "cuid": "MA718CNBFCL010122", "streamUrl": "https://example.com/video.mp4" }' ``` **请求字段:** | 字段 | 类型 | 必填 | 说明 | |-----|------|-----|------| | cuid | String | 是 | 设备唯一标识 | | streamUrl | String | 是 | 视频流地址 | --- #### 7. SSML播报推送(SsmlText) **接口:** `POST /api/xiaodu/push/ssml` **请求示例:** ```bash curl -X POST \ http://localhost:8080/api/xiaodu/push/ssml \ -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "cuid": "MA718CNBFCL010122", "title": "托尔斯泰格言", "content": "托尔斯泰 - 理想的书籍,是智慧的钥匙", "outputSpeech": "这句话之后会有3秒钟的停顿停顿结束" }' ``` **请求字段:** | 字段 | 类型 | 必填 | 说明 | |-----|------|-----|------| | cuid | String | 是 | 设备唯一标识 | | title | String | 是 | 推送标题 | | content | String | 是 | 显示内容 | | outputSpeech | String | 是 | SSML播报内容 | --- ## 代码使用示例 ### 在Java代码中使用(推荐DTO方式) ```java @Autowired private XiaoduOAuthService oauthService; @Autowired private XiaoduPushService pushService; public void example() { // 1. 获取Access Token TokenData tokenData = oauthService.getAccessToken(); String accessToken = tokenData.getAccessToken(); // 2. 发送纯文本推送(使用DTO) TextPushRequest textRequest = TextPushRequest.builder() .cuid("MA718CNBFCL010122") .title("托尔斯泰格言") .content("托尔斯泰 - 理想的书籍,是智慧的钥匙") .build(); PushResponse response = pushService.sendTextPush(accessToken, textRequest); System.out.println("推送成功,消息ID:" + response.getMsgId()); // 3. 发送音频推送(使用DTO) AudioPushRequest audioRequest = AudioPushRequest.builder() .cuid("MA718CNBFCL010122") .streamUrl("https://example.com/audio.mp3") .title("告白气球") .titleSubtext1("周杰伦") .build(); PushResponse audioResponse = pushService.sendAudioPush(accessToken, audioRequest); } ``` ## 项目结构 ``` xiaodu-demo/ ├── src/ │ ├── main/java/com/xiaodu/demo/ │ │ ├── config/ # 配置类 │ │ │ ├── OkHttpConfig.java │ │ │ └── XiaoduApiProperties.java │ │ ├── constant/ # 常量定义 │ │ │ └── PushTemplateType.java │ │ ├── controller/ # REST控制器(使用DTO) │ │ │ ├── XiaoduOAuthController.java │ │ │ └── XiaoduPushController.java │ │ ├── service/ # 业务服务 │ │ │ ├── XiaoduOAuthService.java │ │ │ └── XiaoduPushService.java │ │ ├── dto/ # 数据传输对象 │ │ │ ├── request/ # 请求DTO │ │ │ │ ├── BasePushRequest.java │ │ │ │ ├── TextPushRequest.java │ │ │ │ ├── AllImagePushRequest.java │ │ │ │ ├── ImageTextPushRequest.java │ │ │ │ ├── AudioPushRequest.java │ │ │ │ ├── VideoPushRequest.java │ │ │ │ └── SsmlPushRequest.java │ │ │ └── response/ # 响应DTO │ │ │ ├── Result.java │ │ │ ├── TokenResponse.java │ │ │ └── PushResponse.java │ │ ├── model/ # 实体类(百度API原始数据结构) │ │ │ ├── PushParam.java │ │ │ ├── TokenData.java │ │ │ └── XiaoduResponse.java │ │ ├── util/ # 工具类 │ │ │ └── OkHttpUtil.java │ │ ├── exception/ # 异常类 │ │ │ ├── XiaoduApiException.java │ │ │ └── GlobalExceptionHandler.java │ │ └── XiaoduDemoApplication.java │ ├── main/resources/ │ │ └── application.yml # 应用配置 │ └── test/java/com/xiaodu/demo/service/ # 测试用例 │ ├── XiaoduOAuthServiceTest.java # OAuth服务测试 │ └── XiaoduPushServiceTest.java # 推送服务测试 ├── test-api.sh # Linux/Mac 测试脚本 ├── test-api.bat # Windows 测试脚本 ├── Xiaodu-API.postman_collection.json # Postman 集合 ├── pom.xml └── README.md ``` ## 设计优势 ### 1. DTO设计模式 - ✅ 请求参数对象化,类型安全 - ✅ 参数校验自动化(JSR-303注解) - ✅ 代码可读性强,易于维护 ### 2. 统一响应格式 ```java Result { success: Boolean // 是否成功 errno: Integer // 错误码 message: String // 提示信息 data: T // 业务数据 } ``` ### 3. 继承结构 - `BasePushRequest` - 所有推送请求的基类 - 各推送类型继承基类,复用cuid字段 - 提高代码复用性 ### 4. 参数校验示例 ```java @NotBlank(message = "设备ID不能为空") private String cuid; @NotBlank(message = "标题不能为空") private String title; ``` ## 模板类型总览 | 模板类型 | 接口路径 | 请求DTO | 响应DTO | 说明 | |---------|---------|---------|---------|------| | AllText | `/push/text` | TextPushRequest | PushResponse | 纯文本 | | AllImage | `/push/allImage` | AllImagePushRequest | PushResponse | 纯图片 | | TextRight | `/push/textRight` | ImageTextPushRequest | PushResponse | 左图右文 | | TextBottom | `/push/textBottom` | ImageTextPushRequest | PushResponse | 上图下文 | | AudioPlayer | `/push/audio` | AudioPushRequest | PushResponse | 音频 | | VideoPlayer | `/push/video` | VideoPushRequest | PushResponse | 视频 | | SsmlText | `/push/ssml` | SsmlPushRequest | PushResponse | SSML播报 | ## 技术栈 - Spring Boot 2.7.18 - OkHttp 4.9.3 - Gson(JSON序列化) - Lombok(简化代码) - JSR-303(参数校验) - Java 8+ ## 注意事项 1. **Access Token有效期**:默认30天,建议提前5分钟刷新 2. **请求格式**:所有推送接口使用POST + JSON Body 3. **参数校验**:必填字段会自动校验,返回清晰的错误提示 4. **设备ID**:cuid需要从小度设备或API中获取 5. **媒体资源**:图片、音频、视频URL必须是公网可访问的HTTPS地址 ## 完整测试示例 ### 端到端测试流程(使用 curl) ```bash # 1. 获取 Access Token curl -X GET "http://localhost:8080/api/xiaodu/token" # 响应示例: # { # "success": true, # "message": "操作成功", # "data": { # "accessToken": "24.abcdef123456...", # "expiresIn": 2592000, # "deadline": 1738108800 # } # } # 2. 使用获取的 Token 发送推送(以纯文本推送为例) ACCESS_TOKEN="24.abcdef123456..." # 替换为实际获取的 token curl -X POST "http://localhost:8080/api/xiaodu/push/text" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "cuid": "your-device-cuid", "title": "测试推送", "content": "这是一条测试消息" }' # 响应示例: # { # "success": true, # "message": "推送成功", # "data": { # "result": "success", # "msgId": "1234567890" # } # } ``` ### 批量测试所有推送类型 ```bash # 设置变量 ACCESS_TOKEN="your-access-token" DEVICE_CUID="your-device-cuid" BASE_URL="http://localhost:8080/api/xiaodu" # 1. 纯文本推送 curl -X POST "$BASE_URL/push/text" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"cuid\":\"$DEVICE_CUID\",\"title\":\"天气提醒\",\"content\":\"今天北京晴转多云\"}" # 2. 全图片推送 curl -X POST "$BASE_URL/push/allImage" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"cuid\":\"$DEVICE_CUID\",\"imageSrc\":\"https://example.com/image.jpg\",\"imageThumb\":\"https://example.com/thumb.jpg\"}" # 3. 左图右文推送 curl -X POST "$BASE_URL/push/textRight" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"cuid\":\"$DEVICE_CUID\",\"title\":\"新闻标题\",\"content\":\"新闻内容\",\"image\":\"https://example.com/news.jpg\"}" # 4. 音频推送 curl -X POST "$BASE_URL/push/audio" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"cuid\":\"$DEVICE_CUID\",\"streamUrl\":\"https://example.com/music.mp3\",\"title\":\"歌曲名\",\"titleSubtext1\":\"歌手名\"}" # 5. 视频推送 curl -X POST "$BASE_URL/push/video" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"cuid\":\"$DEVICE_CUID\",\"streamUrl\":\"https://example.com/video.mp4\"}" ``` ## 最佳实践 ### 1. Token 管理 **推荐实现 Token 缓存和自动刷新机制:** ```java @Service public class TokenManagerService { @Autowired private XiaoduOAuthService oauthService; private String cachedToken; private long tokenExpireTime; /** * 获取有效的 Access Token(带缓存) */ public synchronized String getValidToken() { // 检查 token 是否即将过期(提前 5 分钟刷新) if (cachedToken == null || System.currentTimeMillis() > tokenExpireTime - 300000) { refreshToken(); } return cachedToken; } private void refreshToken() { TokenData tokenData = oauthService.getAccessToken(); this.cachedToken = tokenData.getAccessToken(); this.tokenExpireTime = tokenData.getDeadline() * 1000L; log.info("Token已更新,过期时间:{}", new Date(tokenExpireTime)); } } ``` ### 2. 异步推送 **对于高并发场景,建议使用异步推送:** ```java @Service public class AsyncPushService { @Autowired private XiaoduPushService pushService; @Autowired private TokenManagerService tokenManager; @Async public CompletableFuture sendTextPushAsync(TextPushRequest request) { String token = tokenManager.getValidToken(); PushResponse response = pushService.sendTextPush(token, request); return CompletableFuture.completedFuture(response); } } ``` ### 3. 错误重试 **实现自动重试机制:** ```java @Service public class RetryablePushService { private static final int MAX_RETRIES = 3; @Retryable( value = {XiaoduApiException.class}, maxAttempts = MAX_RETRIES, backoff = @Backoff(delay = 1000, multiplier = 2) ) public PushResponse sendWithRetry(String token, TextPushRequest request) { return pushService.sendTextPush(token, request); } } ``` ### 4. 日志脱敏 **生产环境建议对敏感信息脱敏:** ```java private String maskToken(String token) { if (token == null || token.length() < 10) { return "***"; } return token.substring(0, 10) + "..." + token.substring(token.length() - 10); } log.info("使用 Token: {}", maskToken(accessToken)); ``` ## 配置详解 ### 使用环境变量(推荐用于生产环境) **application.yml:** ```yaml xiaodu: api: base-url: ${XIAODU_BASE_URL:https://dueros.baidu.com/business} app-id: ${XIAODU_APP_ID} app-secret: ${XIAODU_APP_SECRET} ``` **设置环境变量:** ```bash # Linux/Mac export XIAODU_APP_ID="your-app-id" export XIAODU_APP_SECRET="your-app-secret" # Windows set XIAODU_APP_ID=your-app-id set XIAODU_APP_SECRET=your-app-secret ``` ### 多环境配置 **application-dev.yml (开发环境):** ```yaml xiaodu: api: base-url: https://dueros-test.baidu.com/business app-id: dev-app-id app-secret: dev-app-secret logging: level: okhttp3.logging.HttpLoggingInterceptor: DEBUG com.xiaodu.demo: DEBUG ``` **application-prod.yml (生产环境):** ```yaml xiaodu: api: base-url: https://dueros.baidu.com/business app-id: ${XIAODU_APP_ID} app-secret: ${XIAODU_APP_SECRET} logging: level: okhttp3.logging.HttpLoggingInterceptor: INFO com.xiaodu.demo: INFO ``` **启动时指定环境:** ```bash # 开发环境 java -jar xiaodu-demo.jar --spring.profiles.active=dev # 生产环境 java -jar xiaodu-demo.jar --spring.profiles.active=prod ``` ## 常见问题 (FAQ) ### Q1: 如何获取设备 CUID? **A:** CUID(Client Unique ID)是设备的唯一标识,需要通过以下方式获取: - 从百度小度开放平台的设备管理页面查看 - 通过设备绑定时的回调接口获取 - 联系百度小度技术支持获取测试设备 CUID ### Q2: 推送失败,返回 401 错误怎么办? **A:** 401 错误通常表示 Access Token 无效或过期,请检查: 1. Token 是否正确获取 2. Token 是否已过期(有效期 30 天) 3. 请求头格式是否正确:`Authorization: Bearer {token}` 4. App ID 和 App Secret 是否正确 ### Q3: 如何查看 HTTP 请求详细日志? **A:** 项目已配置 OkHttp 日志拦截器,在 application.yml 中设置日志级别: ```yaml logging: level: okhttp3.logging.HttpLoggingInterceptor: DEBUG # 显示完整请求响应 com.xiaodu.demo: DEBUG ``` ### Q4: 推送成功但设备没有收到消息? **A:** 请检查: 1. CUID 是否正确 2. 设备是否在线 3. 设备是否已授权接收推送 4. 推送内容格式是否符合要求 5. 媒体资源 URL 是否可访问(需要 HTTPS) ### Q5: 如何在生产环境中管理 Token? **A:** 建议: 1. 使用缓存机制存储 Token(Redis/内存) 2. 实现自动刷新逻辑(提前 5-10 分钟) 3. 使用分布式锁避免并发刷新 4. 记录 Token 刷新日志便于追踪 ### Q6: 参数校验失败如何处理? **A:** 项目使用 JSR-303 校验,失败时会返回: ```json { "success": false, "errno": 400, "message": "设备ID不能为空", "data": null } ``` 请根据错误信息检查请求参数。 ### Q7: 如何集成到现有项目? **A:** 有两种方式: 1. **作为独立服务**:启动本项目,其他项目通过 REST API 调用 2. **集成到现有项目**:复制 service、dto、config 等包到您的项目中 ### Q8: 支持批量推送吗? **A:** 当前实现是单个设备推送,如需批量推送,可以: ```java public List batchPush(String token, List requests) { return requests.stream() .map(req -> pushService.sendTextPush(token, req)) .collect(Collectors.toList()); } ``` ## 错误码说明 | 错误码 | 说明 | 解决方案 | |-------|------|---------| | 0 | 成功 | - | | 401 | Token 无效 | 重新获取 Access Token | | 403 | 权限不足 | 检查 App ID 和 Secret | | 404 | 接口不存在 | 检查 API 路径 | | 400 | 参数错误 | 检查请求参数格式 | | 500 | 服务器错误 | 联系技术支持 | ## 性能优化建议 1. **连接池配置**:OkHttp 默认连接池已优化,如需调整: ```java @Bean public OkHttpClient okHttpClient() { ConnectionPool connectionPool = new ConnectionPool(10, 5, TimeUnit.MINUTES); return new OkHttpClient.Builder() .connectionPool(connectionPool) .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .writeTimeout(30, TimeUnit.SECONDS) .addInterceptor(loggingInterceptor) .build(); } ``` 2. **异步处理**:使用 `@Async` 注解实现异步推送 3. **批量处理**:合并多个推送请求减少网络开销 4. **Token 缓存**:避免频繁请求 Token 接口 ## 监控与运维 ### 健康检查 ```java @RestController @RequestMapping("/actuator") public class HealthController { @GetMapping("/health") public Map health() { Map health = new HashMap<>(); health.put("status", "UP"); health.put("service", "xiaodu-push-service"); return health; } } ``` ### 日志监控 建议监控以下日志关键字: - `推送失败` - 推送失败次数 - `HTTP请求异常` - 网络问题 - `Token已更新` - Token 刷新记录 ### 指标收集 可集成 Spring Boot Actuator 和 Prometheus: ```xml org.springframework.boot spring-boot-starter-actuator io.micrometer micrometer-registry-prometheus ``` ## 贡献指南 欢迎提交 Issue 和 Pull Request! 1. Fork 本仓库 2. 创建特性分支 (`git checkout -b feature/AmazingFeature`) 3. 提交更改 (`git commit -m 'Add some AmazingFeature'`) 4. 推送到分支 (`git push origin feature/AmazingFeature`) 5. 开启 Pull Request ## 更新日志 ### v1.0.0 (2024-01-30) - ✅ 实现 OAuth 2.0 认证 - ✅ 支持 7 种推送模板 - ✅ DTO 设计模式 - ✅ 统一异常处理 - ✅ HTTP 请求日志 - ✅ 完整测试用例 ## 相关链接 - [百度小度开放平台](https://dueros.baidu.com/) - [DuerOS 开发文档](https://dueros.baidu.com/doc) - [Spring Boot 官方文档](https://spring.io/projects/spring-boot) - [OkHttp 官方文档](https://square.github.io/okhttp/) ## License MIT License