ai聊天功能搭建

master
chenyuepan 4 weeks ago
parent 988d790ae4
commit 7e82814906

@ -144,7 +144,6 @@
<artifactId>spring-boot-starter-data-redis</artifactId> <artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.6.8</version> <version>2.6.8</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId> <artifactId>commons-pool2</artifactId>
@ -178,25 +177,16 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId> <artifactId>spring-boot-starter-websocket</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!-- 封装了各大模型的交互接口 -->
<!-- <dependency>-->
<!-- <groupId>io.springboot.ai</groupId>-->
<!-- <artifactId>spring-ai-openai-spring-boot-starter</artifactId>-->
<!-- <version>1.0.0</version> &lt;!&ndash; 使用最新版本 &ndash;&gt;-->
<!-- </dependency>-->
</dependencies> </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> </project>

@ -0,0 +1,66 @@
package com.example.venue_reservation_service.controller;
import com.example.venue_reservation_service.domain.VeMessage;
import com.example.venue_reservation_service.domain.VeSession;
import com.example.venue_reservation_service.service.VeMessageService;
import com.example.venue_reservation_service.service.VeSessionService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jakarta.annotation.Resource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/session")
@Api("ai会话管理模块")
@CrossOrigin
public class SessionController {
@Resource
private VeSessionService sessionService;
@Resource
private VeMessageService messageService;
@ApiOperation("创建新会话")
@PostMapping("/create")
public ResponseEntity<VeSession> createSession(@RequestBody VeSession session) {
VeSession savedSession = sessionService.saveSession(session);
return ResponseEntity.status(HttpStatus.CREATED).body(savedSession);
}
@ApiOperation("获取用户会话历史")
@GetMapping("/list")
public ResponseEntity<List<VeSession>> getUserSessions(@RequestParam(name = "userId") Integer userId) {
List<VeSession> sessions = sessionService.getSessionsByUserId(userId);
return ResponseEntity.ok(sessions);
}
@ApiOperation("获取会话详情")
@GetMapping("/{sessionId}")
public ResponseEntity<VeSession> getSession(@PathVariable("sessionId") Integer sessionId) {
VeSession session = sessionService.getById(sessionId);
if (session != null) {
return ResponseEntity.ok(session);
} else {
return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
}
}
@ApiOperation("获取指定会话的所有消息")
@GetMapping("/message/{sessionId}")
public ResponseEntity<List<VeMessage>> getSessionMessages(@PathVariable("sessionId") Integer sessionId) {
List<VeMessage> messages = messageService.getMessagesBySessionId(sessionId);
return ResponseEntity.ok(messages);
}
@ApiOperation("创建新消息")
@PostMapping("/message/create")
public ResponseEntity<VeMessage> createMessage(@RequestBody VeMessage message) {
VeMessage savedMessage = messageService.saveMessage(message);
return ResponseEntity.status(HttpStatus.CREATED).body(savedMessage);
}
}

@ -107,7 +107,7 @@ public class UserController {
@ApiOperation("用户头像上传") @ApiOperation("用户头像上传")
@PostMapping("/upload") @PostMapping("/upload")
public Result upload(@RequestParam("id") Integer userId, @RequestParam("image")MultipartFile file){ public Result upload(@RequestParam("id") Integer userId, @RequestParam("image") MultipartFile file){
return userService.upload(userId, file); return userService.upload(userId, file);
} }

@ -0,0 +1,52 @@
package com.example.venue_reservation_service.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
/**
*
* @TableName venue_message
*/
@TableName(value ="venue_message")
@Data
public class VeMessage implements Serializable {
/**
*
*/
@TableId(type = IdType.AUTO)
private Integer id;
/**
* ID
*/
private Integer sessionId;
/**
*
*/
private String content;
/**
*
*/
private Object sender;
/**
*
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createdAt;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

@ -0,0 +1,67 @@
package com.example.venue_reservation_service.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
/**
*
* @TableName venue_session
*/
@TableName(value ="venue_session")
@Data
public class VeSession implements Serializable {
/**
*
*/
@TableId(type = IdType.AUTO)
private Integer id;
/**
* ID
*/
private Integer userId;
/**
* IP
*/
private String userIp;
/**
*
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime startTime;
/**
*
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime endTime;
/**
*
*/
private String sessionToken;
/**
*
*/
private String title;
@Serial
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

@ -40,8 +40,8 @@ public class VenueLog implements Serializable {
*/ */
private String operationDesc; private String operationDesc;
/** /*
* JSON JSON
*/ */
// private String params; // private String params;
@ -76,6 +76,4 @@ public class VenueLog implements Serializable {
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime; private LocalDateTime createTime;
} }

@ -0,0 +1,18 @@
package com.example.venue_reservation_service.mapper;
import com.example.venue_reservation_service.domain.VeMessage;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author 31586
* @description venue_messageMapper
* @createDate 2025-06-17 15:36:33
* @Entity generator.domain.VeMessage
*/
public interface VeMessageMapper extends BaseMapper<VeMessage> {
}

@ -0,0 +1,24 @@
package com.example.venue_reservation_service.mapper;
import com.example.venue_reservation_service.domain.VeSession;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* @author 31586
* @description venue_sessionMapper
* @createDate 2025-06-17 15:36:33
* @Entity generator.domain.VeSession
*/
public interface VeSessionMapper extends BaseMapper<VeSession> {
}

@ -0,0 +1,18 @@
package com.example.venue_reservation_service.service;
import com.example.venue_reservation_service.domain.VeMessage;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* @author 31586
* @description venue_messageService
* @createDate 2025-06-17 15:36:33
*/
public interface VeMessageService extends IService<VeMessage> {
VeMessage saveMessage(VeMessage message);
List<VeMessage> getMessagesBySessionId(Integer sessionId);
}

@ -0,0 +1,18 @@
package com.example.venue_reservation_service.service;
import com.example.venue_reservation_service.domain.VeSession;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* @author 31586
* @description venue_sessionService
* @createDate 2025-06-17 15:36:33
*/
public interface VeSessionService extends IService<VeSession> {
VeSession saveSession(VeSession session);
List<VeSession> getSessionsByUserId(Integer userId);
}

@ -70,7 +70,9 @@ public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment>
if (dto.getOnlyOne() == 1) { if (dto.getOnlyOne() == 1) {
wrapper.eq(Comment::getUserId, dto.getUserId()); wrapper.eq(Comment::getUserId, dto.getUserId());
} }
wrapper.eq(Comment::getStatus, 2); wrapper.eq(Comment::getStatus, 2)
.orderByDesc(Comment::getCreateTime)
.orderByDesc(Comment::getUpdateTime);
page = page(page, wrapper); page = page(page, wrapper);
QueryVO<AvatarVO> vo = new QueryVO<>(); QueryVO<AvatarVO> vo = new QueryVO<>();
vo.setTotal(page.getTotal()); vo.setTotal(page.getTotal());
@ -98,6 +100,9 @@ public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment>
@Override @Override
public Result createComment(Comment comment) { public Result createComment(Comment comment) {
if (Optional.ofNullable(comment.getUserId()).isEmpty() || Optional.ofNullable(userMapper.selectById(comment.getUserId())).isEmpty()){
return Result.fail().message("用户信息不存在");
}
List<String> list; List<String> list;
try { try {
list = ListConverter.stringToList((String) redisUtil.get(REDIS_KEY)); list = ListConverter.stringToList((String) redisUtil.get(REDIS_KEY));

@ -33,7 +33,6 @@ public class SensitiveWordServiceImpl extends ServiceImpl<SensitiveWordMapper, S
private final static String REDIS_KEY = "sensitive-word"; private final static String REDIS_KEY = "sensitive-word";
/** /**
* *
*/ */
@ -124,5 +123,4 @@ public class SensitiveWordServiceImpl extends ServiceImpl<SensitiveWordMapper, S
return Result.ok().message("设置成功"); return Result.ok().message("设置成功");
} }
} }

@ -376,7 +376,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User>
user.setIsUpload(1); user.setIsUpload(1);
user.setAvatar(filename); user.setAvatar(filename);
updateById(user); updateById(user);
return Result.ok().message("头像图片上传成功"); return Result.ok(imgUrl + user.getAvatar()).message("头像图片上传成功");
} }
return Result.fail().message("非图片文件或文件过大"); return Result.fail().message("非图片文件或文件过大");
} }

@ -0,0 +1,45 @@
package com.example.venue_reservation_service.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.venue_reservation_service.domain.VeMessage;
import com.example.venue_reservation_service.service.VeMessageService;
import com.example.venue_reservation_service.mapper.VeMessageMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
/**
* @author 31586
* @description venue_messageService
* @createDate 2025-06-17 15:36:33
*/
@Service
public class VeMessageServiceImpl extends ServiceImpl<VeMessageMapper, VeMessage>
implements VeMessageService{
@Resource
private VeMessageMapper messageMapper;
@Override
public VeMessage saveMessage(VeMessage message) {
message.setCreatedAt(LocalDateTime.now());
messageMapper.insert(message);
return message;
}
@Override
public List<VeMessage> getMessagesBySessionId(Integer sessionId) {
QueryWrapper<VeMessage> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("session_id", sessionId)
.orderByAsc("created_at");
return messageMapper.selectList(queryWrapper);
}
}

@ -0,0 +1,48 @@
package com.example.venue_reservation_service.service.impl;
import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.venue_reservation_service.service.VeSessionService;
import com.example.venue_reservation_service.domain.VeSession;
import com.example.venue_reservation_service.mapper.VeSessionMapper;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
/**
* @author 31586
* &#064;description venue_sessionService
* &#064;createDate 2025-06-17 15:36:33
*/
@Service
public class VeSessionServiceImpl extends ServiceImpl<VeSessionMapper, VeSession>
implements VeSessionService {
@Resource
private VeSessionMapper sessionMapper;
public VeSession saveSession(VeSession session) {
session.setStartTime(LocalDateTime.now());
if (StringUtils.isEmpty(session.getSessionToken())) {
session.setSessionToken("sess_" + UUID.randomUUID());
}
sessionMapper.insert(session);
return session;
}
public List<VeSession> getSessionsByUserId(Integer userId) {
QueryWrapper<VeSession> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("user_id", userId)
.orderByDesc("start_time");
return sessionMapper.selectList(queryWrapper);
}
}

@ -24,6 +24,11 @@ public class AvatarVO {
*/ */
private Integer isUpload; private Integer isUpload;
/**
*
*/
private Integer id;
/** /**
* *
*/ */

@ -1,5 +1,7 @@
server: server:
port: 9020 port: 9020
# servlet:
# context-path: /api
#localhosturl: 172.16.6.53 # 学校服务器 #localhosturl: 172.16.6.53 # 学校服务器
localhosturl: 119.29.191.232 # 双创服务器 localhosturl: 119.29.191.232 # 双创服务器

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.venue_reservation_service.mapper.VeMessageMapper">
<resultMap id="BaseResultMap" type="com.example.venue_reservation_service.domain.VeMessage">
<id property="id" column="id" jdbcType="INTEGER"/>
<result property="sessionId" column="session_id" jdbcType="INTEGER"/>
<result property="content" column="content" jdbcType="VARCHAR"/>
<result property="sender" column="sender" jdbcType="OTHER"/>
<result property="createdAt" column="created_at" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="Base_Column_List">
id,session_id,content,
sender,created_at
</sql>
</mapper>

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.venue_reservation_service.mapper.VeSessionMapper">
<resultMap id="BaseResultMap" type="com.example.venue_reservation_service.domain.VeSession">
<id property="id" column="id" jdbcType="INTEGER"/>
<result property="userId" column="user_id" jdbcType="INTEGER"/>
<result property="userIp" column="user_ip" jdbcType="VARCHAR"/>
<result property="startTime" column="start_time" jdbcType="TIMESTAMP"/>
<result property="endTime" column="end_time" jdbcType="TIMESTAMP"/>
<result property="sessionToken" column="session_token" jdbcType="VARCHAR"/>
</resultMap>
<sql id="Base_Column_List">
id,user_id,user_ip,
start_time,end_time,session_token
</sql>
</mapper>

@ -1,22 +1,11 @@
package com.example.venue_reservation_service; package com.example.venue_reservation_service;
import cn.hutool.core.lang.UUID;
import com.example.venue_reservation_service.controller.UserController;
import com.example.venue_reservation_service.dto.AdminDTO;
import com.example.venue_reservation_service.filter.SensitiveFilter;
import com.example.venue_reservation_service.utils.MD5Util; import com.example.venue_reservation_service.utils.MD5Util;
import com.example.venue_reservation_service.vo.Result;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.commons.io.FilenameUtils;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import reactor.core.publisher.Flux;
import java.util.*;
@SpringBootTest @SpringBootTest
class VenueReservationServiceApplicationTests { class VenueReservationServiceApplicationTests {
@ -30,22 +19,21 @@ class VenueReservationServiceApplicationTests {
System.out.println(MD5Util.generateRandomString(10)); System.out.println(MD5Util.generateRandomString(10));
} }
public static void main(String[] args) { // public static void main(String[] args) {
// 1. 初始化敏感词库 // // 1. 初始化敏感词库
List<String> sensitiveWords = Arrays.asList("赌博", "毒品", "色情"); // List<String> sensitiveWords = Arrays.asList("赌博", "毒品", "色情");
//
// 2. 构建过滤器 // // 2. 构建过滤器
SensitiveFilter filter = new SensitiveFilter(); // SensitiveFilter filter = new SensitiveFilter();
filter.buildTrie(sensitiveWords); // filter.buildTrie(sensitiveWords);
//
// 3. 测试文本过滤 // // 3. 测试文本过滤
String input = "远离赌博,拒绝毒品,健康上网!"; // String input = "远离赌博,拒绝毒品,健康上网!";
String output = filter.filter(input); // String output = filter.filter(input);
//
System.out.println("原始文本: " + input); // System.out.println("原始文本: " + input);
System.out.println("过滤结果: " + output); // System.out.println("过滤结果: " + output);
// 输出:远离***,拒绝***,健康上网! // // 输出:远离***,拒绝***,健康上网!
} // }
} }

@ -21,7 +21,8 @@ public class IfsDcpIcdcShareTest {
public void test_getGzzxList() throws Exception { public void test_getGzzxList() throws Exception {
String param="<param>" String param="<param>"
+ "<module>IcdcShare</module>" + "<module>IcdcShare</module>"
+ "<method>getUnit</method>" //+ "<method>getUnit</method>"
+ "<method>08192ec57d80193b9fa4b9a0</method>"
//+"<params>pageSize=8&pageNo=1</params>" //+"<params>pageSize=8&pageNo=1</params>"
+"<params>STUDENTID=1966&pageSize=5&pageNo=1</params>" +"<params>STUDENTID=1966&pageSize=5&pageNo=1</params>"
//+"<params>STUDENTID=2017</params>" //+"<params>STUDENTID=2017</params>"

Loading…
Cancel
Save