feat(图书初步): 图书初步

图书初步
This commit is contained in:
ovo 2024-12-20 14:14:26 +08:00
parent 1551cc1263
commit 45512694b6
23 changed files with 413 additions and 323 deletions

27
pom.xml
View File

@ -278,6 +278,33 @@
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.agentsflex</groupId>-->
<!-- <artifactId>agents-flex-bom</artifactId>-->
<!-- <version>1.0.0-rc.3</version>-->
<!-- </dependency>-->
<!-- springboot -->
<dependency>
<groupId>com.mongoplus</groupId>
<artifactId>mongo-plus-boot-starter</artifactId>
<version>2.1.6.1</version>
</dependency>
<!-- solon -->
<dependency>
<groupId>com.mongoplus</groupId>
<artifactId>mongo-plus-solon-plugin</artifactId>
<version>2.1.6.1</version>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
<version>3.0.9</version>
</dependency>
</dependencies>

View File

@ -13,7 +13,10 @@ import java.util.List;
public class OkHttpExample {
public static void main(String[] args) {
String url = "http://localhost:9000/txt/8357cf6b-9637-4354-9ee6-2717141f665a.txt"; // 目标 URL
// String url = "http://localhost:9000/txt/f7886718-cb64-4495-9975-733f498d4706.txt"; // 目标 URL
String url = "http://localhost:9000/txt/712f63af-a974-4462-ac70-22ce8dc43b19.txt";
OkHttpClient client = new OkHttpClient();
// 创建一个请求对象
@ -24,7 +27,7 @@ public class OkHttpExample {
// 发起同步请求
try {
String content = getTextUsingOkHttp(client, request);
System.out.println("File Content:");
// System.out.println("File Content:" + content);
// 提取 "第几卷" "第几节"
processContent(content);
} catch (IOException e) {
@ -47,7 +50,8 @@ public class OkHttpExample {
public static void processContent(String content) {
// 正则表达式提取卷和节
String volumePattern = "第([一二三四五六七八九十]+)卷"; // 提取卷
String sectionPattern = "第([一二三四五六七八九十零百]+)节:(.*)"; // 提取节及其节名
// String sectionPattern = "第([一二三四五六七八九十零百]+)节:(.*)"; // 提取节及其节名
String sectionPattern = "第([一二三四五六七八九十百千零]+)章\\s*(.*)";
// 提取卷
Pattern volumeRegex = Pattern.compile(volumePattern);
@ -68,11 +72,28 @@ public class OkHttpExample {
// 收集节的信息
while (sectionMatcher.find()) {
String section = "" + sectionMatcher.group(1) + "节:" + sectionMatcher.group(2).trim(); // 这里去掉节名前后空格
sections.add(section);
String section = "" + sectionMatcher.group(1) + "章:" + sectionMatcher.group(2).trim(); // 这里去掉节名前后空格
if (sections.stream().noneMatch(s -> s.contains("" + sectionMatcher.group(1) + ""))) {
sections.add(section);
}
// sections.add(section);
// if (sectionMatcher.find()) {
// System.out.println("章节号: " + sectionMatcher.group(1)); // 中文数字部分
// System.out.println("章节名: " + sectionMatcher.group(2)); // 章节名称
// } else {
// System.out.println("没有匹配到章节信息");
// }
}
System.out.println("sections = " + sections);
boolean isFirstSection = true; // 标记是否是第一次匹配到第一节

View File

@ -13,7 +13,8 @@ import java.util.List;
public class OkHttpExample2 {
public static void main(String[] args) {
String url = "http://localhost:9000/txt/8357cf6b-9637-4354-9ee6-2717141f665a.txt"; // 目标 URL
/* String url = "http://localhost:9000/txt/712f63af-a974-4462-ac70-22ce8dc43b19.txt"; // 目标 URL
// String url = "http://localhost:9000/txt/f7886718-cb64-4495-9975-733f498d4706.txt"; // 目标 URL
OkHttpClient client = new OkHttpClient();
// 创建一个请求对象
@ -24,12 +25,14 @@ public class OkHttpExample2 {
// 发起同步请求
try {
String content = getTextUsingOkHttp(client, request);
System.out.println("File Content:");
System.out.println("File Content:" + content);
// 提取 "第几卷" "第几节"
processContent(content);
} catch (IOException e) {
e.printStackTrace();
}
}*/
test();
}
// 通过 OkHttpClient 发起同步请求获取文件内容
@ -47,8 +50,8 @@ public class OkHttpExample2 {
public static void processContent(String content) {
// 正则表达式提取卷和节
String volumePattern = "第([一二三四五六七八九十]+)卷"; // 提取卷
String sectionPattern = "第([一二三四五六七八九十零百]+)(.*)"; // 提取节及其节名
//String sectionPattern = "第([一二三四五六七八九十零百]+)(.*)"; // 提取节及其节名
String sectionPattern = "第([一二三四五六七八九十百千零]+)章\\s*(.*)";
// 提取卷
Pattern volumeRegex = Pattern.compile(volumePattern);
Matcher volumeMatcher = volumeRegex.matcher(content);
@ -122,4 +125,22 @@ public class OkHttpExample2 {
}
}
public static void test() {
String a = "第二章 骨文";
// 改进后的正则表达式处理数字空格以及章节名称
String sectionPattern = "第([一二三四五六七八九十百千零]+)章\\s*(.*)";
Pattern sectionRegex = Pattern.compile(sectionPattern);
Matcher sectionMatcher = sectionRegex.matcher(a);
if (sectionMatcher.find()) {
System.out.println("章节号: " + sectionMatcher.group(1)); // 中文数字部分
System.out.println("章节名: " + sectionMatcher.group(2)); // 章节名称
} else {
System.out.println("没有匹配到章节信息");
}
}
}

View File

@ -1,84 +0,0 @@
package com.guwan.backend.client;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@Slf4j
@Component
@RequiredArgsConstructor
public class Go2RTCClient {
private final RestTemplate restTemplate;
@Value("${go2rtc.api.url}")
private String apiUrl;
/**
* 创建流
*/
public void createStream(String streamId, String sourceUrl) {
String url = apiUrl + "/api/streams/" + streamId;
StreamConfig config = new StreamConfig(sourceUrl);
try {
restTemplate.postForEntity(url, config, String.class);
} catch (Exception e) {
log.error("创建流失败: {}", e.getMessage());
throw new RuntimeException("创建流失败", e);
}
}
/**
* 删除流
*/
public void deleteStream(String streamId) {
String url = apiUrl + "/api/streams/" + streamId;
try {
restTemplate.delete(url);
} catch (Exception e) {
log.error("删除流失败: {}", e.getMessage());
throw new RuntimeException("删除流失败", e);
}
}
/**
* 获取WebRTC Offer
*/
public String getOffer(String streamId, String sdp) {
String url = apiUrl + "/api/stream/" + streamId + "/webrtc";
WebRTCRequest request = new WebRTCRequest(sdp);
try {
ResponseEntity<WebRTCResponse> response =
restTemplate.postForEntity(url, request, WebRTCResponse.class);
return response.getBody().getSdp();
} catch (Exception e) {
log.error("获取WebRTC Offer失败: {}", e.getMessage());
throw new RuntimeException("获取WebRTC Offer失败", e);
}
}
@Data
@AllArgsConstructor
static class StreamConfig {
private String input;
}
@Data
@AllArgsConstructor
static class WebRTCRequest {
private String sdp;
}
@Data
static class WebRTCResponse {
private String sdp;
}
}

View File

@ -1,83 +0,0 @@
//package com.guwan.backend.client;
//
//import lombok.Data;
//import lombok.RequiredArgsConstructor;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.http.ResponseEntity;
//import org.springframework.stereotype.Component;
//import org.springframework.web.client.RestTemplate;
//
//@Slf4j
//@Component
//@RequiredArgsConstructor
//public class SrsClient {
//
// private final RestTemplate restTemplate;
//
// @Value("${srs.server.url}")
// private String srsServerUrl;
//
// /**
// * 开始录制
// */
// public void startRecord(String streamKey, RecordConfig config) {
// String url = String.format("%s/api/v1/streams/%s/recording/start", srsServerUrl, streamKey);
// try {
// ResponseEntity<String> response = restTemplate.postForEntity(url, config, String.class);
// if (!response.getStatusCode().is2xxSuccessful()) {
// throw new RuntimeException("开始录制失败: " + response.getBody());
// }
// } catch (Exception e) {
// log.error("开始录制失败", e);
// throw new RuntimeException("开始录制失败", e);
// }
// }
//
// /**
// * 停止录制
// */
// public void stopRecord(String streamKey) {
// String url = String.format("%s/api/v1/streams/%s/recording/stop", srsServerUrl, streamKey);
// try {
// ResponseEntity<String> response = restTemplate.postForEntity(url, null, String.class);
// if (!response.getStatusCode().is2xxSuccessful()) {
// throw new RuntimeException("停止录制失败: " + response.getBody());
// }
// } catch (Exception e) {
// log.error("停止录制失败", e);
// throw new RuntimeException("停止录制失败", e);
// }
// }
//
// /**
// * 获取流信息
// */
// public StreamInfo getStreamInfo(String streamKey) {
// String url = String.format("%s/api/v1/streams/%s", srsServerUrl, streamKey);
// try {
// ResponseEntity<StreamInfo> response = restTemplate.getForEntity(url, StreamInfo.class);
// return response.getBody();
// } catch (Exception e) {
// log.error("获取流信息失败", e);
// throw new RuntimeException("获取流信息失败", e);
// }
// }
//
// @Data
// public static class RecordConfig {
// private String format = "flv"; // 录制格式
// private String filePath; // 文件路径
// }
//
// @Data
// public static class StreamInfo {
// private String streamId; // 流ID
// private String clientId; // 客户端ID
// private String ip; // 客户端IP
// private Long startTime; // 开始时间
// private String status; // 状态
// private Long bytesIn; // 输入字节数
// private Long bytesOut; // 输出字节数
// }
//}

View File

@ -0,0 +1,53 @@
package com.guwan.backend.config;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.apache.kafka.common.serialization.StringSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
import org.springframework.kafka.core.*;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class KafkaConfig {
@Bean
public ProducerFactory<String, String> producerFactory() {
Map<String, Object> config = new HashMap<>();
config.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
config.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
config.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
return new DefaultKafkaProducerFactory<>(config);
}
@Bean
public ConsumerFactory<String, String> consumerFactory() {
Map<String, Object> config = new HashMap<>();
config.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
config.put(ConsumerConfig.GROUP_ID_CONFIG, "book-recommendation-group");
config.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
config.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
return new DefaultKafkaConsumerFactory<>(config);
}
@Bean
public KafkaTemplate<String, String> kafkaTemplate() {
return new KafkaTemplate<>(producerFactory());
}
@Bean
public ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory() {
ConcurrentKafkaListenerContainerFactory<String, String> factory =
new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(consumerFactory());
return factory;
}
}

View File

@ -2,6 +2,8 @@ package com.guwan.backend.controller;
import com.guwan.backend.common.Result;
import com.guwan.backend.entity.BookContent;
import com.guwan.backend.mongodb.User;
import com.guwan.backend.mongodb.MongodbUserService;
import com.guwan.backend.service.BookContentService;
import com.guwan.backend.util.MinioUtil;
import lombok.RequiredArgsConstructor;
@ -32,6 +34,8 @@ public class CommonController {
private final BookContentService bookContentService;
private final MongodbUserService mongodbUserService;
@PostMapping("/uploadFile")
public Result<String> uploadFile(String bucketName, MultipartFile file){
return Result.success(minioUtil.getUrl(minioUtil.getFileUrl
@ -40,6 +44,7 @@ public class CommonController {
@PostMapping("/addBookComment")
public Result<String> addBookComment(String url) {
log.debug(url);
// "http://localhost:9000/txt/8357cf6b-9637-4354-9ee6-2717141f665a.txt";
OkHttpClient client = new OkHttpClient();
@ -186,8 +191,8 @@ public class CommonController {
@GetMapping("/getBookCommentByPath")
public ResponseEntity<Map<String, Object>> getBookCommentByPath(@RequestParam("id") Long id) {
@GetMapping("/getBookCommentByPath")
public ResponseEntity<Map<String, Object>> getBookCommentByPath(@RequestParam("id") Long id) {
// 从数据库中获取评论内容
String comments = bookContentService.getById(id).getSectionContent();
@ -202,8 +207,21 @@ public class CommonController {
}
@GetMapping("/testMongodb")
public Result testMongodb(){
User user = new User();
user.setId("1");
user.setName("1");
user.setAge(1L);
user.setEmail("1");
mongodbUserService.save(user);
return Result.success();
}
}

View File

@ -0,0 +1,11 @@
package com.guwan.backend.entity;
public class BookOfUser {
private Long UserId;
private Long bookId;
private String evaluate;
}

View File

@ -1,16 +0,0 @@
package com.guwan.backend.entity;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class LiveMessage {
private String type; // 消息类型CHAT-聊天GIFT-礼物LIKE-点赞ENTER-进入LEAVE-离开
private Long userId; // 用户ID
private String username; // 用户名
private String content; // 消息内容
private String giftType; // 礼物类型
private Integer giftCount; // 礼物数量
private LocalDateTime time; // 时间
}

View File

@ -1,29 +0,0 @@
package com.guwan.backend.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("live_room")
public class LiveRoom {
@TableId(type = IdType.AUTO)
private Long id;
private String title; // 直播间标题
private String description; // 直播间描述
private String coverUrl; // 封面图
private Long userId; // 主播ID
private String username; // 主播名称
private String streamId; // Go2RTC流ID
private String status; // 状态PREPARING-准备中LIVING-直播中ENDED-已结束
private Integer onlineCount; // 在线人数
private Integer likeCount; // 点赞数
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createdTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updatedTime;
}

View File

@ -0,0 +1,16 @@
package com.guwan.backend.kafka;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.Map;
@Data
public class BookEvent {
private String eventId;
private String eventType; // READ, RATE, BOOKMARK
private String userId;
private String bookId;
private String bookName;
private LocalDateTime timestamp;
private Map<String, Object> eventData;
}

View File

@ -0,0 +1,31 @@
//package com.guwan.backend.kafka;
//
//import com.fasterxml.jackson.databind.ObjectMapper;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.kafka.annotation.KafkaListener;
//import org.springframework.stereotype.Service;
//
//import lombok.extern.slf4j.Slf4j;
//
//@Service
//@Slf4j
//public class BookEventConsumer {
//
// @Autowired
// private ObjectMapper objectMapper;
//
// @KafkaListener(topics = "book-events", groupId = "book-recommendation-group")
// public void consume(String message) {
// try {
// BookEvent event = objectMapper.readValue(message, BookEvent.class);
// processBookEvent(event);
// } catch (Exception e) {
// log.error("Error processing book event", e);
// }
// }
//
// private void processBookEvent(BookEvent event) {
// // 处理接收到的事件
// log.info("Processing book event: {}", event);
// }
//}

View File

@ -0,0 +1,28 @@
package com.guwan.backend.kafka;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
@Service
public class BookEventProducer {
private static final String TOPIC = "book-events";
@Autowired
private KafkaTemplate<String, String> kafkaTemplate;
@Autowired
private ObjectMapper objectMapper;
public void sendBookEvent(BookEvent event) {
try {
String message = objectMapper.writeValueAsString(event);
kafkaTemplate.send(TOPIC, message);
} catch (Exception e) {
throw new RuntimeException("Error sending book event", e);
}
}
}

View File

@ -0,0 +1,37 @@
package com.guwan.backend.kafka;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
@RestController
@RequestMapping("/api/common/v1/books")
public class BookOfKafkaController {
@Autowired
private BookService bookService;
@PostMapping("/{bookId}/reading")
public void recordReading(
@PathVariable String bookId,
@RequestParam String userId) {
bookService.recordReadingEvent(userId, bookId);
}
@PostMapping("/{bookId}/rating")
public void rateBook(
@PathVariable String bookId,
@RequestParam String userId,
@RequestParam int rating) {
bookService.recordBookRating(userId, bookId, rating);
}
@PostMapping("/{bookId}/bookmark")
public void bookmarkBook(
@PathVariable String bookId,
@RequestParam String userId) {
bookService.recordBookmarkEvent(userId, bookId);
}
}

View File

@ -0,0 +1,51 @@
package com.guwan.backend.kafka;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.UUID;
import java.time.LocalDateTime;
@Service
public class BookService {
@Autowired
private BookEventProducer producer;
public void recordReadingEvent(String userId, String bookId) {
BookEvent event = new BookEvent();
event.setEventId(UUID.randomUUID().toString());
event.setEventType("READ");
event.setUserId(userId);
event.setBookId(bookId);
event.setBookName("大爱仙尊");
event.setTimestamp(LocalDateTime.now());
event.setEventData(Map.of("readingTime", 30));
producer.sendBookEvent(event);
}
public void recordBookRating(String userId, String bookId, int rating) {
BookEvent event = new BookEvent();
event.setEventId(UUID.randomUUID().toString());
event.setEventType("RATE");
event.setUserId(userId);
event.setBookId(bookId);
event.setTimestamp(LocalDateTime.now());
event.setEventData(Map.of("rating", rating));
producer.sendBookEvent(event);
}
public void recordBookmarkEvent(String userId, String bookId) {
BookEvent event = new BookEvent();
event.setEventId(UUID.randomUUID().toString());
event.setEventType("BOOKMARK");
event.setUserId(userId);
event.setBookId(bookId);
event.setTimestamp(LocalDateTime.now());
producer.sendBookEvent(event);
}
}

View File

@ -0,0 +1,15 @@
package com.guwan.backend.kafka;
import java.time.LocalDateTime;
public class EveryReadDetailOfKafka {
private Long UserId;
private Long bookId;
private LocalDateTime startTime;
private LocalDateTime endTime;
}

View File

@ -1,9 +0,0 @@
package com.guwan.backend.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.guwan.backend.entity.LiveRoom;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface LiveRoomMapper extends BaseMapper<LiveRoom> {
}

View File

@ -0,0 +1,15 @@
package com.guwan.backend.mongodb;
import java.time.LocalDateTime;
public class EveryReadDetailOfMongodb {
private Long UserId;
private Long bookId;
private LocalDateTime startTime;
private LocalDateTime endTime;
}

View File

@ -0,0 +1,7 @@
package com.guwan.backend.mongodb;
import com.mongoplus.service.IService;
public interface MongodbUserService extends IService<User> {
}

View File

@ -0,0 +1,9 @@
package com.guwan.backend.mongodb;
import com.mongoplus.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service
public class MongodbUserServiceImpl extends ServiceImpl<User> implements MongodbUserService {
}

View File

@ -0,0 +1,13 @@
package com.guwan.backend.mongodb;
import com.mongoplus.annotation.ID;
import lombok.Data;
@Data
public class User {
@ID //使用ID注解标注此字段为MongoDB的_id或者继承BaseModelID类
private String id;
private String name;
private Long age;
private String email;
}

View File

@ -1,88 +0,0 @@
package com.guwan.backend.service;
import com.guwan.backend.client.Go2RTCClient;
import com.guwan.backend.entity.LiveRoom;
import com.guwan.backend.mapper.LiveRoomMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.UUID;
@Slf4j
@Service
@RequiredArgsConstructor
public class LiveStreamService {
private final Go2RTCClient go2rtcClient;
private final LiveRoomMapper liveRoomMapper;
/**
* 创建直播间
*/
@Transactional
public LiveRoom createLiveRoom(String title, String description, Long userId) {
// 生成streamId
String streamId = UUID.randomUUID().toString();
// 创建直播间记录
LiveRoom room = new LiveRoom();
room.setTitle(title);
room.setDescription(description);
room.setUserId(userId);
room.setStreamId(streamId);
room.setStatus("PREPARING");
liveRoomMapper.insert(room);
return room;
}
/**
* 开始直播
*/
@Transactional
public void startLive(Long roomId, String sourceUrl) {
LiveRoom room = liveRoomMapper.selectById(roomId);
if (room == null) {
throw new IllegalArgumentException("直播间不存在");
}
// 创建Go2RTC流
go2rtcClient.createStream(room.getStreamId(), sourceUrl);
// 更新状态
room.setStatus("LIVING");
liveRoomMapper.updateById(room);
}
/**
* 结束直播
*/
@Transactional
public void endLive(Long roomId) {
LiveRoom room = liveRoomMapper.selectById(roomId);
if (room == null) {
throw new IllegalArgumentException("直播间不存在");
}
// 删除Go2RTC流
go2rtcClient.deleteStream(room.getStreamId());
// 更新状态
room.setStatus("ENDED");
liveRoomMapper.updateById(room);
}
/**
* 获取WebRTC Offer
*/
public String getWebRTCOffer(Long roomId, String sdp) {
LiveRoom room = liveRoomMapper.selectById(roomId);
if (room == null) {
throw new IllegalArgumentException("直播间不存在");
}
return go2rtcClient.getOffer(room.getStreamId(), sdp);
}
}

View File

@ -5,6 +5,15 @@ spring:
application:
name: backend
kafka:
bootstrap-servers: localhost:9092
consumer:
group-id: book-recommendation-group
auto-offset-reset: earliest
producer:
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-serializer: org.apache.kafka.common.serialization.StringSerializer
# 视频上传配置
servlet:
multipart:
@ -58,7 +67,9 @@ spring:
exclude:
- org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration
# MyBatis-Plus配置
# MyBatis-Plus配置
mybatis-plus:
global-config:
db-config:
@ -162,4 +173,19 @@ netty:
go2rtc:
api:
url: http://localhost:1984 # Go2RTC API地址
url: http://localhost:1984 # Go2RTC API地址
# DataSource Config
mongo-plus:
data:
mongodb:
host: 127.0.0.1 #ip
port: 27017 #端口
database: test #数据库名
username: #用户名,没有可不填(若账号中出现@,!等等符号,不需要再进行转码!!!)
password: #密码,同上(若密码中出现@,!等等符号,不需要再进行转码!!!)
authenticationDatabase: admin #验证数据库
connectTimeoutMS: 50000 #在超时之前等待连接打开的最长时间(以毫秒为单位)