├── .DS_Store ├── src ├── .DS_Store ├── test │ ├── .DS_Store │ └── java │ │ └── com │ │ └── yupi │ │ └── springbootinit │ │ ├── MainApplicationTests.java │ │ ├── manager │ │ ├── RedisLimiterManagerTest.java │ │ ├── CosManagerTest.java │ │ ├── AiManagerTestMarkDown.java │ │ └── AiManagerTest.java │ │ ├── mapper │ │ └── ChartMapperTest.java │ │ ├── utils │ │ ├── EasyExcelTest.java │ │ └── TxtUtilsTest.java │ │ └── service │ │ └── UserServiceTest.java └── main │ ├── resources │ ├── banner.txt │ ├── 图表数据.xlsx │ ├── application-test.yml │ ├── application-prod.yml │ ├── mapper │ │ ├── CreditMapper.xml │ │ ├── UserMapper.xml │ │ ├── TextRecordMapper.xml │ │ ├── OrdersMapper.xml │ │ ├── TextTaskMapper.xml │ │ └── ChartMapper.xml │ ├── META-INF │ │ └── additional-spring-configuration-metadata.json │ ├── 笔记.txt │ └── application.yml │ └── java │ └── com │ └── yupi │ └── springbootinit │ ├── model │ ├── vo │ │ ├── AiResponse.java │ │ ├── TextTaskVO.java │ │ ├── UserVO.java │ │ ├── LoginUserVO.java │ │ └── ChartVO.java │ ├── dto │ │ ├── text │ │ │ ├── TextRebuildRequest.java │ │ │ ├── GenTextTaskByAiRequest.java │ │ │ ├── TextAddRequest.java │ │ │ ├── TextEditRequest.java │ │ │ ├── TextUpdateRequest.java │ │ │ └── TextTaskQueryRequest.java │ │ ├── chart │ │ │ ├── ChartRebuildRequest.java │ │ │ ├── GenChartByAiRequest.java │ │ │ ├── ChartAddRequest.java │ │ │ ├── ChartEditRequest.java │ │ │ ├── ChartUpdateRequest.java │ │ │ └── ChartQueryRequest.java │ │ ├── file │ │ │ └── UploadFileRequest.java │ │ ├── user │ │ │ ├── UserLoginRequest.java │ │ │ ├── UserRegisterRequest.java │ │ │ ├── UserUpdateMyRequest.java │ │ │ ├── UserAddRequest.java │ │ │ ├── UserUpdateRequest.java │ │ │ └── UserQueryRequest.java │ │ ├── order │ │ │ ├── OrderAddRequest.java │ │ │ └── OrderUpdateRequest.java │ │ └── credit │ │ │ ├── CreditEditRequest.java │ │ │ ├── CreditUpdateRequest.java │ │ │ ├── CreditAddRequest.java │ │ │ └── CreditQueryRequest.java │ ├── entity │ │ ├── Credit.java │ │ ├── User.java │ │ ├── TextRecord.java │ │ ├── Orders.java │ │ ├── TextTask.java │ │ └── Chart.java │ └── enums │ │ ├── FileUploadBizEnum.java │ │ └── UserRoleEnum.java │ ├── constant │ ├── FileConstant.java │ ├── CommonConstant.java │ ├── TextConstant.java │ ├── CreditConstant.java │ ├── OrdersConstant.java │ ├── UserConstant.java │ ├── ChartConstant.java │ └── MqConstant.java │ ├── wxmp │ ├── WxMpConstant.java │ ├── handler │ │ ├── EventHandler.java │ │ ├── MessageHandler.java │ │ └── SubscribeHandler.java │ └── WxMpMsgRouter.java │ ├── service │ ├── OrdersService.java │ ├── TextRecordService.java │ ├── impl │ │ ├── OrdersServiceImpl.java │ │ ├── TextRecordServiceImpl.java │ │ ├── CreditServiceImpl.java │ │ ├── TextTaskServiceImpl.java │ │ └── ChartServiceImpl.java │ ├── CreditService.java │ ├── TextTaskService.java │ ├── ChartService.java │ └── UserService.java │ ├── mapper │ ├── UserMapper.java │ ├── CreditMapper.java │ ├── OrdersMapper.java │ ├── TextTaskMapper.java │ ├── TextRecordMapper.java │ └── ChartMapper.java │ ├── common │ ├── DeleteRequest.java │ ├── PageRequest.java │ ├── BaseResponse.java │ ├── ErrorCode.java │ └── ResultUtils.java │ ├── annotation │ └── AuthCheck.java │ ├── utils │ ├── SqlUtils.java │ ├── SpringContextUtils.java │ ├── NetUtils.java │ ├── TxtUtils.java │ └── ExcelUtils.java │ ├── mq │ ├── common │ │ └── MqMessageProducer.java │ ├── Bi │ │ ├── BiMqInitMain.java │ │ ├── BiMessageDeadConsumer.java │ │ └── BiMessageConsumer.java │ ├── Text │ │ ├── TextMqInitMain.java │ │ ├── TextMessageDeadConsumer.java │ │ └── TextMessageConsumer.java │ └── Alipay │ │ ├── AlipayMqInitMain.java │ │ ├── AlipayMessageConsumer.java │ │ └── AlipayMessageDeadConsumer.java │ ├── exception │ ├── BusinessException.java │ ├── GlobalExceptionHandler.java │ └── ThrowUtils.java │ ├── config │ ├── CorsConfig.java │ ├── MyBatisPlusConfig.java │ ├── RedissonConfig.java │ ├── JsonConfig.java │ ├── ThreadPoolExecutorConfig.java │ ├── CosClientConfig.java │ ├── Knife4jConfig.java │ ├── WxOpenConfig.java │ └── AliPayConfig.java │ ├── MainApplication.java │ ├── manager │ ├── RedisLimiterManager.java │ ├── AiManager.java │ └── CosManager.java │ ├── controller │ ├── QueueController.java │ ├── FileController.java │ └── AliPayController.java │ └── aop │ ├── LogInterceptor.java │ └── AuthInterceptor.java ├── doc └── swagger.png ├── .mvn └── wrapper │ └── maven-wrapper.properties ├── Dockerfile ├── sql ├── post_es_mapping.json └── create_table.sql ├── README.md ├── .gitignore ├── pom.xml └── mvnw.cmd /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MA-douzhang/gebi-backend/HEAD/.DS_Store -------------------------------------------------------------------------------- /src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MA-douzhang/gebi-backend/HEAD/src/.DS_Store -------------------------------------------------------------------------------- /doc/swagger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MA-douzhang/gebi-backend/HEAD/doc/swagger.png -------------------------------------------------------------------------------- /src/test/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MA-douzhang/gebi-backend/HEAD/src/test/.DS_Store -------------------------------------------------------------------------------- /src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | by 程序员鱼皮:https://github.com/liyupi 2 | 可能是最好的编程学习圈子:https://yupi.icu 3 | -------------------------------------------------------------------------------- /src/main/resources/图表数据.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MA-douzhang/gebi-backend/HEAD/src/main/resources/图表数据.xlsx -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar 3 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/vo/AiResponse.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.vo; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class AiResponse { 7 | 8 | /** 9 | * 返回结果id 10 | */ 11 | private Long resultId; 12 | } 13 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM maven:3.8.1-jdk-8-slim as builder 2 | 3 | # Copy local code to the container image. 4 | WORKDIR /app 5 | COPY pom.xml . 6 | COPY src ./src 7 | 8 | # Build a release artifact. 9 | RUN mvn package -DskipTests 10 | 11 | # Run the web service on container startup. 12 | CMD ["java","-jar","/app/target/gebi-backend-0.0.1-SNAPSHOT.jar","--spring.profiles.active=prod"] 13 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/constant/FileConstant.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.constant; 2 | 3 | /** 4 | * 文件常量 5 | * 6 | * @author 程序员鱼皮 7 | * @from 编程导航知识星球 8 | */ 9 | public interface FileConstant { 10 | 11 | /** 12 | * COS 访问地址 13 | * todo 需替换配置 14 | */ 15 | String COS_HOST = "https://yupi.icu"; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/wxmp/WxMpConstant.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.wxmp; 2 | 3 | /** 4 | * 微信公众号相关常量 5 | * 6 | * @author 程序员鱼皮 7 | * @from 编程导航知识星球 8 | **/ 9 | public class WxMpConstant { 10 | 11 | /** 12 | * 点击菜单 key 13 | */ 14 | public static final String CLICK_MENU_KEY = "CLICK_MENU_KEY"; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/service/OrdersService.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.service; 2 | 3 | import com.yupi.springbootinit.model.entity.Orders; 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | 6 | /** 7 | * @author MA_dou 8 | * @description 针对表【orders(充值订单表)】的数据库操作Service 9 | * @createDate 2023-07-06 20:36:41 10 | */ 11 | public interface OrdersService extends IService { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/dto/text/TextRebuildRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.dto.text; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * 重新生成请求 9 | * 10 | */ 11 | @Data 12 | public class TextRebuildRequest implements Serializable { 13 | 14 | /** 15 | * id 16 | */ 17 | private Long id; 18 | 19 | private static final long serialVersionUID = 1L; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/dto/chart/ChartRebuildRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.dto.chart; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * 重新生成请求 9 | * 10 | */ 11 | @Data 12 | public class ChartRebuildRequest implements Serializable { 13 | 14 | /** 15 | * id 16 | */ 17 | private Long id; 18 | 19 | private static final long serialVersionUID = 1L; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.mapper; 2 | 3 | import com.yupi.springbootinit.model.entity.User; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | 6 | /** 7 | * @author MA_dou 8 | * @description 针对表【user(用户)】的数据库操作Mapper 9 | * @createDate 2023-05-26 23:18:53 10 | * @Entity com.yupi.springbootinit.model.entity.User 11 | */ 12 | public interface UserMapper extends BaseMapper { 13 | 14 | } 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/constant/CommonConstant.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.constant; 2 | 3 | /** 4 | * 通用常量 5 | * 6 | * @author 程序员鱼皮 7 | * @from 编程导航知识星球 8 | */ 9 | public interface CommonConstant { 10 | 11 | /** 12 | * 升序 13 | */ 14 | String SORT_ORDER_ASC = "ascend"; 15 | 16 | /** 17 | * 降序 18 | */ 19 | String SORT_ORDER_DESC = " descend"; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/mapper/CreditMapper.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.mapper; 2 | 3 | import com.yupi.springbootinit.model.entity.Credit; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | 6 | /** 7 | * @author MA_dou 8 | * @description 针对表【credit(积分表)】的数据库操作Mapper 9 | * @createDate 2023-06-28 21:29:40 10 | * @Entity com.yupi.springbootinit.model.entity.Credit 11 | */ 12 | public interface CreditMapper extends BaseMapper { 13 | 14 | } 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/mapper/OrdersMapper.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.mapper; 2 | 3 | import com.yupi.springbootinit.model.entity.Orders; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | 6 | /** 7 | * @author MA_dou 8 | * @description 针对表【orders(充值订单表)】的数据库操作Mapper 9 | * @createDate 2023-07-06 20:36:41 10 | * @Entity com.yupi.springbootinit.model.entity.Orders 11 | */ 12 | public interface OrdersMapper extends BaseMapper { 13 | 14 | } 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/common/DeleteRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.common; 2 | 3 | import java.io.Serializable; 4 | import lombok.Data; 5 | 6 | /** 7 | * 删除请求 8 | * 9 | * @author 程序员鱼皮 10 | * @from 编程导航知识星球 11 | */ 12 | @Data 13 | public class DeleteRequest implements Serializable { 14 | 15 | /** 16 | * id 17 | */ 18 | private Long id; 19 | 20 | private static final long serialVersionUID = 1L; 21 | } -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/mapper/TextTaskMapper.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.mapper; 2 | 3 | import com.yupi.springbootinit.model.entity.TextTask; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | 6 | /** 7 | * @author MA_dou 8 | * @description 针对表【text_task(文本任务表)】的数据库操作Mapper 9 | * @createDate 2023-07-12 20:32:15 10 | * @Entity com.yupi.springbootinit.model.entity.TextTask 11 | */ 12 | public interface TextTaskMapper extends BaseMapper { 13 | 14 | } 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/mapper/TextRecordMapper.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.mapper; 2 | 3 | import com.yupi.springbootinit.model.entity.TextRecord; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | 6 | /** 7 | * @author MA_dou 8 | * @description 针对表【text_record(文本记录表)】的数据库操作Mapper 9 | * @createDate 2023-07-12 20:32:09 10 | * @Entity com.yupi.springbootinit.model.entity.TextRecord 11 | */ 12 | public interface TextRecordMapper extends BaseMapper { 13 | 14 | } 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/dto/file/UploadFileRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.dto.file; 2 | 3 | import java.io.Serializable; 4 | import lombok.Data; 5 | 6 | /** 7 | * 文件上传请求 8 | * 9 | * @author 程序员鱼皮 10 | * @from 编程导航知识星球 11 | */ 12 | @Data 13 | public class UploadFileRequest implements Serializable { 14 | 15 | /** 16 | * 业务 17 | */ 18 | private String biz; 19 | 20 | private static final long serialVersionUID = 1L; 21 | } -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/dto/text/GenTextTaskByAiRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.dto.text; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * 文本生成请求 9 | * 10 | */ 11 | @Data 12 | public class GenTextTaskByAiRequest implements Serializable { 13 | 14 | /** 15 | * 笔记名称 16 | */ 17 | private String name; 18 | 19 | /** 20 | * 文本类型 21 | */ 22 | private String textType; 23 | 24 | 25 | 26 | private static final long serialVersionUID = 1L; 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/dto/user/UserLoginRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.dto.user; 2 | 3 | import java.io.Serializable; 4 | import lombok.Data; 5 | 6 | /** 7 | * 用户登录请求 8 | * 9 | * @author 程序员鱼皮 10 | * @from 编程导航知识星球 11 | */ 12 | @Data 13 | public class UserLoginRequest implements Serializable { 14 | 15 | private static final long serialVersionUID = 3191241716373120793L; 16 | 17 | private String userAccount; 18 | 19 | private String userPassword; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/resources/application-test.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8101 3 | spring: 4 | # 数据库配置 5 | # todo 需替换配置 6 | datasource: 7 | driver-class-name: com.mysql.cj.jdbc.Driver 8 | url: jdbc:mysql://localhost:3306/my_db 9 | username: root 10 | password: 123456 11 | # Redis 配置 12 | # todo 需替换配置 13 | redis: 14 | database: 1 15 | host: localhost 16 | port: 6379 17 | timeout: 5000 18 | password: 123456 19 | # Elasticsearch 配置 20 | # todo 需替换配置 21 | elasticsearch: 22 | uris: http://localhost:9200 23 | username: root 24 | password: 123456 -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/mapper/ChartMapper.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.mapper; 2 | 3 | import com.yupi.springbootinit.model.entity.Chart; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | /** 10 | * @author MA_dou 11 | * @description 针对表【chart(图表信息表)】的数据库操作Mapper 12 | * @createDate 2023-05-26 23:18:07 13 | * @Entity com.yupi.springbootinit.model.entity.Chart 14 | */ 15 | public interface ChartMapper extends BaseMapper { 16 | List> queryChartData(String querySql); 17 | } 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/dto/chart/GenChartByAiRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.dto.chart; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * 图表生成请求 9 | * 10 | */ 11 | @Data 12 | public class GenChartByAiRequest implements Serializable { 13 | 14 | /** 15 | * 图表名称 16 | */ 17 | private String name; 18 | /** 19 | * 图表描述 20 | */ 21 | private String goal; 22 | 23 | /** 24 | * 图表类型 25 | */ 26 | private String chartType; 27 | 28 | 29 | private static final long serialVersionUID = 1L; 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/dto/user/UserRegisterRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.dto.user; 2 | 3 | import java.io.Serializable; 4 | import lombok.Data; 5 | 6 | /** 7 | * 用户注册请求体 8 | * 9 | * @author 程序员鱼皮 10 | * @from 编程导航知识星球 11 | */ 12 | @Data 13 | public class UserRegisterRequest implements Serializable { 14 | 15 | private static final long serialVersionUID = 3191241716373120793L; 16 | 17 | private String userAccount; 18 | 19 | private String userPassword; 20 | 21 | private String checkPassword; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/dto/order/OrderAddRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.dto.order; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | import java.util.Date; 8 | 9 | 10 | /** 11 | * 创建充值订单表 12 | * @TableName orders 13 | */ 14 | @Data 15 | public class OrderAddRequest implements Serializable { 16 | 17 | /** 18 | * 交易名称 19 | */ 20 | private String subject; 21 | 22 | /** 23 | * 交易金额 24 | */ 25 | private Double totalAmount; 26 | 27 | private static final long serialVersionUID = 1L; 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/service/TextRecordService.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.service; 2 | 3 | import com.yupi.springbootinit.model.entity.TextRecord; 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | 6 | /** 7 | * @author MA_dou 8 | * @description 针对表【text_record(文本记录表)】的数据库操作Service 9 | * @createDate 2023-07-12 20:32:09 10 | */ 11 | public interface TextRecordService extends IService { 12 | /** 13 | * 文本用户输入构造 14 | * @param textRecord 15 | * @param textTaskType 16 | * @return 17 | */ 18 | String buildUserInput(TextRecord textRecord,String textTaskType); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/constant/TextConstant.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.constant; 2 | 3 | /** 4 | * 图表常量 5 | * 6 | */ 7 | public interface TextConstant { 8 | 9 | /** 10 | * 等待 11 | */ 12 | String WAIT = "wait"; 13 | 14 | // region 权限 15 | 16 | /** 17 | * 执行 18 | */ 19 | String RUNNING = "running"; 20 | 21 | /** 22 | * 成功 23 | */ 24 | String SUCCEED = "succeed"; 25 | 26 | /** 27 | * 失败 28 | */ 29 | String FAILED = "failed"; 30 | 31 | /** 32 | * AI模型ID 33 | */ 34 | Long MODE_ID = 1666258198769700865L; 35 | // endregion 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/dto/user/UserUpdateMyRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.dto.user; 2 | 3 | import java.io.Serializable; 4 | import lombok.Data; 5 | 6 | /** 7 | * 用户更新个人信息请求 8 | * 9 | * @author 程序员鱼皮 10 | * @from 编程导航知识星球 11 | */ 12 | @Data 13 | public class UserUpdateMyRequest implements Serializable { 14 | 15 | /** 16 | * 用户昵称 17 | */ 18 | private String userName; 19 | 20 | /** 21 | * 用户头像 22 | */ 23 | private String userAvatar; 24 | 25 | 26 | private static final long serialVersionUID = 1L; 27 | } 28 | -------------------------------------------------------------------------------- /src/main/resources/application-prod.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8101 3 | spring: 4 | # 数据库配置 5 | # todo 需替换配置 6 | datasource: 7 | driver-class-name: com.mysql.cj.jdbc.Driver 8 | url: jdbc:mysql://localhost:3306/my_db 9 | username: root 10 | password: 123456 11 | # Redis 配置 12 | # todo 需替换配置 13 | redis: 14 | database: 1 15 | host: localhost 16 | port: 6379 17 | timeout: 5000 18 | password: 123456 19 | # Elasticsearch 配置 20 | # todo 需替换配置 21 | elasticsearch: 22 | uris: http://localhost:9200 23 | username: root 24 | password: 123456 25 | mybatis-plus: 26 | configuration: 27 | # 生产环境关闭日志 28 | log-impl: '' -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/constant/CreditConstant.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.constant; 2 | 3 | /** 4 | * 积分常量 5 | * 6 | */ 7 | public interface CreditConstant { 8 | 9 | /** 10 | * 签到积分 11 | */ 12 | long CREDIT_DAILY = 100; 13 | 14 | /** 15 | * 生成图表消耗积分 16 | */ 17 | long CREDIT_CHART_SUCCESS = -1; 18 | 19 | /** 20 | * 生成图表失败返回积分 21 | */ 22 | long CREDIT_CHART_FALSE = 1; 23 | 24 | /** 25 | * 生成文本消耗积分 26 | */ 27 | long CREDIT_TEXT_SUCCESS = -10; 28 | 29 | /** 30 | * 生成文本失败返回积分 31 | */ 32 | long CREDIT_TEXT_FALSE = 10; 33 | 34 | // endregion 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/dto/credit/CreditEditRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.dto.credit; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | import java.util.Date; 9 | 10 | /** 11 | * 编辑请求 12 | * 13 | */ 14 | @Data 15 | public class CreditEditRequest implements Serializable { 16 | 17 | /** 18 | * id 19 | */ 20 | private Long id; 21 | /** 22 | * 总积分 23 | */ 24 | private Long creditTotal; 25 | 26 | 27 | 28 | 29 | private static final long serialVersionUID = 1L; 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/dto/credit/CreditUpdateRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.dto.credit; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | import java.util.Date; 9 | 10 | /** 11 | * 更新请求 12 | * 13 | */ 14 | @Data 15 | public class CreditUpdateRequest implements Serializable { 16 | 17 | /** 18 | * id 19 | */ 20 | private Long id; 21 | 22 | /** 23 | * 总积分 24 | */ 25 | private Long creditTotal; 26 | 27 | 28 | private static final long serialVersionUID = 1L; 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/dto/credit/CreditAddRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.dto.credit; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | import java.util.Date; 9 | 10 | /** 11 | * 创建请求 12 | */ 13 | @Data 14 | public class CreditAddRequest implements Serializable { 15 | 16 | 17 | /** 18 | * 创建用户Id 19 | */ 20 | private Long userId; 21 | 22 | /** 23 | * 总积分 24 | */ 25 | private Long creditTotal; 26 | 27 | 28 | 29 | private static final long serialVersionUID = 1L; 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/annotation/AuthCheck.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * 权限校验 10 | * 11 | * @author 程序员鱼皮 12 | * @from 编程导航知识星球 13 | */ 14 | @Target(ElementType.METHOD) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | public @interface AuthCheck { 17 | 18 | /** 19 | * 必须有某个角色 20 | * 21 | * @return 22 | */ 23 | String mustRole() default ""; 24 | 25 | } 26 | 27 | -------------------------------------------------------------------------------- /src/test/java/com/yupi/springbootinit/MainApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit; 2 | 3 | import com.yupi.springbootinit.config.WxOpenConfig; 4 | import javax.annotation.Resource; 5 | import org.junit.jupiter.api.Test; 6 | import org.springframework.boot.test.context.SpringBootTest; 7 | 8 | /** 9 | * 主类测试 10 | * 11 | * @author 程序员鱼皮 12 | * @from 编程导航知识星球 13 | */ 14 | @SpringBootTest 15 | class MainApplicationTests { 16 | 17 | @Resource 18 | private WxOpenConfig wxOpenConfig; 19 | 20 | @Test 21 | void contextLoads() { 22 | System.out.println(wxOpenConfig); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/constant/OrdersConstant.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.constant; 2 | 3 | /** 4 | * 支付订单常量 5 | * 6 | */ 7 | public interface OrdersConstant { 8 | 9 | /** 10 | * 回调地址(本地部署时需要内网穿透) 11 | */ 12 | String NOTIFYURL = "http://6ytvug.natappfree.cc/api/alipay/notify"; 13 | 14 | /** 15 | * 未支付 16 | */ 17 | String UNPAID = "unpaid"; 18 | 19 | // region 权限 20 | 21 | /** 22 | * 支付中 23 | */ 24 | String PAYING = "paying"; 25 | 26 | /** 27 | * 成功 28 | */ 29 | String SUCCEED = "succeed"; 30 | 31 | /** 32 | * 失败 33 | */ 34 | String FAILED = "failed"; 35 | 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/constant/UserConstant.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.constant; 2 | 3 | /** 4 | * 用户常量 5 | * 6 | * @author 程序员鱼皮 7 | * @from 编程导航知识星球 8 | */ 9 | public interface UserConstant { 10 | 11 | /** 12 | * 用户登录态键 13 | */ 14 | String USER_LOGIN_STATE = "user_login"; 15 | 16 | // region 权限 17 | 18 | /** 19 | * 默认角色 20 | */ 21 | String DEFAULT_ROLE = "user"; 22 | 23 | /** 24 | * 管理员角色 25 | */ 26 | String ADMIN_ROLE = "admin"; 27 | 28 | /** 29 | * 被封号 30 | */ 31 | String BAN_ROLE = "ban"; 32 | 33 | // endregion 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/service/impl/OrdersServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.yupi.springbootinit.model.entity.Orders; 5 | import com.yupi.springbootinit.service.OrdersService; 6 | import com.yupi.springbootinit.mapper.OrdersMapper; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * @author MA_dou 11 | * @description 针对表【orders(充值订单表)】的数据库操作Service实现 12 | * @createDate 2023-07-06 20:36:41 13 | */ 14 | @Service 15 | public class OrdersServiceImpl extends ServiceImpl 16 | implements OrdersService{ 17 | 18 | } 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/utils/SqlUtils.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.utils; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | 5 | /** 6 | * SQL 工具 7 | * 8 | * @author 程序员鱼皮 9 | * @from 编程导航知识星球 10 | */ 11 | public class SqlUtils { 12 | 13 | /** 14 | * 校验排序字段是否合法(防止 SQL 注入) 15 | * 16 | * @param sortField 17 | * @return 18 | */ 19 | public static boolean validSortField(String sortField) { 20 | if (StringUtils.isBlank(sortField)) { 21 | return false; 22 | } 23 | return !StringUtils.containsAny(sortField, "=", "(", ")", " "); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/dto/text/TextAddRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.dto.text; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableLogic; 6 | import lombok.Data; 7 | 8 | import java.io.Serializable; 9 | import java.util.Date; 10 | 11 | /** 12 | * 创建请求 13 | * 14 | */ 15 | @Data 16 | public class TextAddRequest implements Serializable { 17 | 18 | /** 19 | * 笔记名称 20 | */ 21 | private String name; 22 | 23 | /** 24 | * 文本类型 25 | */ 26 | private String textType; 27 | 28 | 29 | 30 | private static final long serialVersionUID = 1L; 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/dto/order/OrderUpdateRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.dto.order; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * 更新请求 9 | * 10 | */ 11 | @Data 12 | public class OrderUpdateRequest implements Serializable { 13 | 14 | /** 15 | * 订单id 16 | */ 17 | private Long id; 18 | 19 | /** 20 | * 支付宝交易凭证id 21 | */ 22 | private String alipayTradeNo; 23 | 24 | /** 25 | * unpaid,paying,succeed,failed 26 | */ 27 | private String tradeStatus; 28 | 29 | /** 30 | * 支付宝买家id 31 | */ 32 | private String buyerId; 33 | 34 | 35 | private static final long serialVersionUID = 1L; 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/com/yupi/springbootinit/manager/RedisLimiterManagerTest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.manager; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | import javax.annotation.Resource; 7 | 8 | import static org.junit.jupiter.api.Assertions.*; 9 | 10 | @SpringBootTest 11 | class RedisLimiterManagerTest { 12 | 13 | @Resource 14 | RedisLimiterManager redisLimiterManager; 15 | 16 | @Test 17 | void doRateLimit() { 18 | long userId = 1L; 19 | for (int i = 0; i < 1; i++) { 20 | redisLimiterManager.doRateLimit("doRateLimit_" + userId); 21 | System.out.println("success"); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/mq/common/MqMessageProducer.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.mq.common; 2 | 3 | import org.springframework.amqp.rabbit.core.RabbitTemplate; 4 | import org.springframework.stereotype.Component; 5 | 6 | import javax.annotation.Resource; 7 | 8 | /** 9 | * 公共队列生产者 10 | */ 11 | @Component 12 | public class MqMessageProducer { 13 | 14 | @Resource 15 | private RabbitTemplate rabbitTemplate; 16 | 17 | /** 18 | * 发信息 19 | * @param exchange 20 | * @param routingKey 21 | * @param message 22 | */ 23 | public void sendMessage(String exchange,String routingKey,String message){ 24 | rabbitTemplate.convertAndSend(exchange,routingKey,message); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/common/PageRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.common; 2 | 3 | import com.yupi.springbootinit.constant.CommonConstant; 4 | import lombok.Data; 5 | 6 | /** 7 | * 分页请求 8 | * 9 | * @author 程序员鱼皮 10 | * @from 编程导航知识星球 11 | */ 12 | @Data 13 | public class PageRequest { 14 | 15 | /** 16 | * 当前页号 17 | */ 18 | private long current = 1; 19 | 20 | /** 21 | * 页面大小 22 | */ 23 | private long pageSize = 10; 24 | 25 | /** 26 | * 排序字段 27 | */ 28 | private String sortField; 29 | 30 | /** 31 | * 排序顺序(默认升序) 32 | */ 33 | private String sortOrder = CommonConstant.SORT_ORDER_ASC; 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/constant/ChartConstant.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.constant; 2 | 3 | /** 4 | * 图表常量 5 | * 6 | * @author 程序员鱼皮 7 | * @from 编程导航知识星球 8 | */ 9 | public interface ChartConstant { 10 | 11 | /** 12 | * 等待 13 | */ 14 | String WAIT = "wait"; 15 | 16 | // region 权限 17 | 18 | /** 19 | * 执行 20 | */ 21 | String RUNNING = "running"; 22 | 23 | /** 24 | * 成功 25 | */ 26 | String SUCCEED = "succeed"; 27 | 28 | /** 29 | * 失败 30 | */ 31 | String FAILED = "failed"; 32 | 33 | /** 34 | * AI模型ID 35 | */ 36 | Long MODE_ID = 1659171950288818178L; 37 | // endregion 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/vo/TextTaskVO.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.vo; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.Date; 6 | 7 | @Data 8 | public class TextTaskVO { 9 | 10 | /** 11 | * 任务id 12 | */ 13 | private Long id; 14 | 15 | /** 16 | * 笔记名称 17 | */ 18 | private String name; 19 | 20 | /** 21 | * 文本类型 22 | */ 23 | private String textType; 24 | 25 | /** 26 | * 生成的文本内容 27 | */ 28 | private String genTextContent; 29 | 30 | /** 31 | * wait,running,succeed,failed 32 | */ 33 | private String status; 34 | 35 | /** 36 | * 创建时间 37 | */ 38 | private Date createTime; 39 | 40 | 41 | private static final long serialVersionUID = 1L; 42 | } 43 | -------------------------------------------------------------------------------- /src/test/java/com/yupi/springbootinit/mapper/ChartMapperTest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.mapper; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | import javax.annotation.Resource; 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | import static org.junit.jupiter.api.Assertions.*; 12 | 13 | @SpringBootTest 14 | class ChartMapperTest { 15 | 16 | @Resource 17 | ChartMapper chartMapper; 18 | 19 | @Test 20 | void queryChartData() { 21 | long chartId=1663172101098369026L; 22 | String sql = String.format("select * from chart_%s",chartId); 23 | List> maps = chartMapper.queryChartData(sql); 24 | System.out.println(maps); 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/dto/user/UserAddRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.dto.user; 2 | 3 | import java.io.Serializable; 4 | import lombok.Data; 5 | 6 | /** 7 | * 用户创建请求 8 | * 9 | * @author 程序员鱼皮 10 | * @from 编程导航知识星球 11 | */ 12 | @Data 13 | public class UserAddRequest implements Serializable { 14 | 15 | /** 16 | * 用户昵称 17 | */ 18 | private String userName; 19 | 20 | /** 21 | * 账号 22 | */ 23 | private String userAccount; 24 | 25 | /** 26 | * 用户头像 27 | */ 28 | private String userAvatar; 29 | 30 | /** 31 | * 用户角色: user, admin 32 | */ 33 | private String userRole; 34 | 35 | private static final long serialVersionUID = 1L; 36 | } -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/dto/user/UserUpdateRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.dto.user; 2 | 3 | import java.io.Serializable; 4 | import lombok.Data; 5 | 6 | /** 7 | * 用户更新请求 8 | * 9 | * @author 程序员鱼皮 10 | * @from 编程导航知识星球 11 | */ 12 | @Data 13 | public class UserUpdateRequest implements Serializable { 14 | /** 15 | * id 16 | */ 17 | private Long id; 18 | 19 | /** 20 | * 用户昵称 21 | */ 22 | private String userName; 23 | 24 | /** 25 | * 用户头像 26 | */ 27 | private String userAvatar; 28 | 29 | /** 30 | * 用户角色:user/admin/ban 31 | */ 32 | private String userRole; 33 | 34 | private static final long serialVersionUID = 1L; 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/dto/text/TextEditRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.dto.text; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * 编辑请求 9 | * 10 | */ 11 | @Data 12 | public class TextEditRequest implements Serializable { 13 | /** 14 | * 任务id 15 | */ 16 | private Long id; 17 | 18 | /** 19 | * 笔记名称 20 | */ 21 | private String name; 22 | 23 | /** 24 | * 文本类型 25 | */ 26 | private String textType; 27 | 28 | /** 29 | * 生成的文本内容 30 | */ 31 | private String genTextContent; 32 | 33 | /** 34 | * 创建用户Id 35 | */ 36 | private Long userId; 37 | 38 | /** 39 | * wait,running,succeed,failed 40 | */ 41 | private String status; 42 | 43 | 44 | private static final long serialVersionUID = 1L; 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/dto/text/TextUpdateRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.dto.text; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * 创建请求 9 | * 10 | */ 11 | @Data 12 | public class TextUpdateRequest implements Serializable { 13 | 14 | /** 15 | * 任务id 16 | */ 17 | private Long id; 18 | 19 | /** 20 | * 笔记名称 21 | */ 22 | private String name; 23 | 24 | /** 25 | * 文本类型 26 | */ 27 | private String textType; 28 | 29 | /** 30 | * 生成的文本内容 31 | */ 32 | private String genTextContent; 33 | 34 | /** 35 | * wait,running,succeed,failed 36 | */ 37 | private String status; 38 | 39 | /** 40 | * 执行信息 41 | */ 42 | private String execMessage; 43 | 44 | 45 | 46 | private static final long serialVersionUID = 1L; 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/com/yupi/springbootinit/manager/CosManagerTest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.manager; 2 | 3 | import javax.annotation.Resource; 4 | 5 | import cn.hutool.core.date.DateTime; 6 | import cn.hutool.core.date.DateUnit; 7 | import cn.hutool.core.date.DateUtil; 8 | import cn.hutool.core.io.unit.DataUnit; 9 | import org.junit.jupiter.api.Test; 10 | import org.springframework.boot.test.context.SpringBootTest; 11 | 12 | import java.util.Date; 13 | 14 | /** 15 | * Cos 操作测试 16 | * 17 | * @author 程序员鱼皮 18 | * @from 编程导航知识星球 19 | */ 20 | @SpringBootTest 21 | class CosManagerTest { 22 | 23 | @Resource 24 | private CosManager cosManager; 25 | 26 | @Test 27 | void putObject() { 28 | cosManager.putObject("test", "test.json"); 29 | DateUtil.isSameDay(new Date(),new Date()); 30 | } 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/common/BaseResponse.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.common; 2 | 3 | import java.io.Serializable; 4 | import lombok.Data; 5 | 6 | /** 7 | * 通用返回类 8 | * 9 | * @param 10 | * @author 程序员鱼皮 11 | * @from 编程导航知识星球 12 | */ 13 | @Data 14 | public class BaseResponse implements Serializable { 15 | 16 | private int code; 17 | 18 | private T data; 19 | 20 | private String message; 21 | 22 | public BaseResponse(int code, T data, String message) { 23 | this.code = code; 24 | this.data = data; 25 | this.message = message; 26 | } 27 | 28 | public BaseResponse(int code, T data) { 29 | this(code, data, ""); 30 | } 31 | 32 | public BaseResponse(ErrorCode errorCode) { 33 | this(errorCode.getCode(), null, errorCode.getMessage()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/service/CreditService.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.service; 2 | 3 | import com.yupi.springbootinit.model.entity.Credit; 4 | 5 | import com.baomidou.mybatisplus.extension.service.IService; 6 | 7 | import javax.servlet.http.HttpServletRequest; 8 | 9 | /** 10 | * @author MA_dou 11 | * @description 针对表【credit(积分表)】的数据库操作Service 12 | * @createDate 2023-06-28 21:29:40 13 | */ 14 | public interface CreditService extends IService { 15 | /** 16 | * 根据 当前用户ID 获取积分总数 17 | * @param userId 18 | * @return 19 | */ 20 | Long getCreditTotal(Long userId); 21 | 22 | /** 23 | * 每日签到 24 | * @param userId 25 | * @return 26 | */ 27 | Boolean signUser(Long userId); 28 | 29 | /** 30 | * 更新积分(内部方法) 正数为增加积分,负数为消耗积分 31 | * @param userId 32 | * @param credits 33 | * @return 34 | */ 35 | Boolean updateCredits(Long userId,long credits); 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/vo/UserVO.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.vo; 2 | 3 | import java.io.Serializable; 4 | import java.util.Date; 5 | import lombok.Data; 6 | 7 | /** 8 | * 用户视图(脱敏) 9 | * 10 | * @author 程序员鱼皮 11 | * @from 编程导航知识星球 12 | */ 13 | @Data 14 | public class UserVO implements Serializable { 15 | 16 | /** 17 | * id 18 | */ 19 | private Long id; 20 | 21 | /** 22 | * 用户昵称 23 | */ 24 | private String userName; 25 | 26 | /** 27 | * 用户头像 28 | */ 29 | private String userAvatar; 30 | 31 | /** 32 | * 用户简介 33 | */ 34 | private String userProfile; 35 | 36 | /** 37 | * 用户角色:user/admin/ban 38 | */ 39 | private String userRole; 40 | 41 | /** 42 | * 创建时间 43 | */ 44 | private Date createTime; 45 | 46 | private static final long serialVersionUID = 1L; 47 | } -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/exception/BusinessException.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.exception; 2 | 3 | import com.yupi.springbootinit.common.ErrorCode; 4 | 5 | /** 6 | * 自定义异常类 7 | * 8 | * @author 程序员鱼皮 9 | * @from 编程导航知识星球 10 | */ 11 | public class BusinessException extends RuntimeException { 12 | 13 | /** 14 | * 错误码 15 | */ 16 | private final int code; 17 | 18 | public BusinessException(int code, String message) { 19 | super(message); 20 | this.code = code; 21 | } 22 | 23 | public BusinessException(ErrorCode errorCode) { 24 | super(errorCode.getMessage()); 25 | this.code = errorCode.getCode(); 26 | } 27 | 28 | public BusinessException(ErrorCode errorCode, String message) { 29 | super(message); 30 | this.code = errorCode.getCode(); 31 | } 32 | 33 | public int getCode() { 34 | return code; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/dto/text/TextTaskQueryRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.dto.text; 2 | 3 | import com.yupi.springbootinit.common.PageRequest; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * 查询 11 | */ 12 | @EqualsAndHashCode(callSuper = true) 13 | @Data 14 | public class TextTaskQueryRequest extends PageRequest implements Serializable { 15 | 16 | /** 17 | * 任务id 18 | */ 19 | private Long id; 20 | 21 | /** 22 | * 笔记名称 23 | */ 24 | private String name; 25 | 26 | /** 27 | * 文本类型 28 | */ 29 | private String textType; 30 | 31 | /** 32 | * 生成的文本内容 33 | */ 34 | private String genTextContent; 35 | 36 | /** 37 | * 创建用户Id 38 | */ 39 | private Long userId; 40 | 41 | /** 42 | * wait,running,succeed,failed 43 | */ 44 | private String status; 45 | 46 | private static final long serialVersionUID = 1L; 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/dto/chart/ChartAddRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.dto.chart; 2 | 3 | import java.io.Serializable; 4 | import java.util.Date; 5 | import java.util.List; 6 | 7 | import com.baomidou.mybatisplus.annotation.IdType; 8 | import com.baomidou.mybatisplus.annotation.TableField; 9 | import com.baomidou.mybatisplus.annotation.TableId; 10 | import lombok.Data; 11 | 12 | /** 13 | * 创建请求 14 | * 15 | * @author 程序员鱼皮 16 | * @from 编程导航知识星球 17 | */ 18 | @Data 19 | public class ChartAddRequest implements Serializable { 20 | 21 | /** 22 | * 分析目标 23 | */ 24 | private String goal; 25 | /** 26 | * 图表名称 27 | */ 28 | private String name; 29 | 30 | /** 31 | * 图表数据 32 | */ 33 | private String chartData; 34 | 35 | /** 36 | * 图表类型 37 | */ 38 | private String chatType; 39 | 40 | 41 | 42 | private static final long serialVersionUID = 1L; 43 | } 44 | -------------------------------------------------------------------------------- /src/main/resources/mapper/CreditMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | id,userId,creditTotal, 18 | createTime,updateTime,isDelete 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/entity/Credit.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | 5 | import java.io.Serializable; 6 | import java.util.Date; 7 | import lombok.Data; 8 | 9 | /** 10 | * 积分表 11 | * @TableName credit 12 | */ 13 | @TableName(value ="credit") 14 | @Data 15 | public class Credit implements Serializable { 16 | /** 17 | * id 18 | */ 19 | @TableId(type = IdType.ASSIGN_ID) 20 | private Long id; 21 | 22 | /** 23 | * 创建用户Id 24 | */ 25 | private Long userId; 26 | 27 | /** 28 | * 总积分 29 | */ 30 | private Long creditTotal; 31 | 32 | /** 33 | * 创建时间 34 | */ 35 | private Date createTime; 36 | 37 | /** 38 | * 更新时间 39 | */ 40 | private Date updateTime; 41 | 42 | /** 43 | * 是否删除 44 | */ 45 | @TableLogic 46 | private Integer isDelete; 47 | 48 | @TableField(exist = false) 49 | private static final long serialVersionUID = 1L; 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/dto/user/UserQueryRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.dto.user; 2 | 3 | import com.yupi.springbootinit.common.PageRequest; 4 | import java.io.Serializable; 5 | import lombok.Data; 6 | import lombok.EqualsAndHashCode; 7 | 8 | /** 9 | * 用户查询请求 10 | * 11 | * @author 程序员鱼皮 12 | * @from 编程导航知识星球 13 | */ 14 | @EqualsAndHashCode(callSuper = true) 15 | @Data 16 | public class UserQueryRequest extends PageRequest implements Serializable { 17 | /** 18 | * id 19 | */ 20 | private Long id; 21 | 22 | /** 23 | * 开放平台id 24 | */ 25 | private String unionId; 26 | 27 | /** 28 | * 公众号openId 29 | */ 30 | private String mpOpenId; 31 | 32 | /** 33 | * 用户昵称 34 | */ 35 | private String userName; 36 | 37 | /** 38 | * 用户角色:user/admin/ban 39 | */ 40 | private String userRole; 41 | 42 | private static final long serialVersionUID = 1L; 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/dto/credit/CreditQueryRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.dto.credit; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.yupi.springbootinit.common.PageRequest; 6 | import lombok.Data; 7 | import lombok.EqualsAndHashCode; 8 | 9 | import java.io.Serializable; 10 | import java.util.Date; 11 | 12 | /** 13 | * 查询请求 14 | * 15 | */ 16 | @EqualsAndHashCode(callSuper = true) 17 | @Data 18 | public class CreditQueryRequest extends PageRequest implements Serializable { 19 | 20 | /** 21 | * id 22 | */ 23 | private Long id; 24 | 25 | /** 26 | * 创建用户Id 27 | */ 28 | private Long userId; 29 | 30 | /** 31 | * 总积分 32 | */ 33 | private Long creditTotal; 34 | 35 | /** 36 | * 创建时间 37 | */ 38 | private Date createTime; 39 | 40 | /** 41 | * 更新时间 42 | */ 43 | private Date updateTime; 44 | 45 | 46 | private static final long serialVersionUID = 1L; 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/vo/LoginUserVO.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.vo; 2 | 3 | import java.io.Serializable; 4 | import java.util.Date; 5 | import lombok.Data; 6 | 7 | /** 8 | * 已登录用户视图(脱敏) 9 | * 10 | * @author 程序员鱼皮 11 | * @from 编程导航知识星球 12 | **/ 13 | @Data 14 | public class LoginUserVO implements Serializable { 15 | 16 | /** 17 | * 用户 id 18 | */ 19 | private Long id; 20 | 21 | /** 22 | * 用户昵称 23 | */ 24 | private String userName; 25 | 26 | /** 27 | * 用户头像 28 | */ 29 | private String userAvatar; 30 | 31 | /** 32 | * 用户简介 33 | */ 34 | private String userProfile; 35 | 36 | /** 37 | * 用户角色:user/admin/ban 38 | */ 39 | private String userRole; 40 | 41 | /** 42 | * 创建时间 43 | */ 44 | private Date createTime; 45 | 46 | /** 47 | * 更新时间 48 | */ 49 | private Date updateTime; 50 | 51 | private static final long serialVersionUID = 1L; 52 | } -------------------------------------------------------------------------------- /src/main/resources/META-INF/additional-spring-configuration-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "properties": [ 3 | { 4 | "name": "cos.client.accessKey", 5 | "type": "java.lang.String", 6 | "description": "Description for cos.client.accessKey." 7 | }, 8 | { 9 | "name": "cos.client.secretKey", 10 | "type": "java.lang.String", 11 | "description": "Description for cos.client.secretKey." 12 | }, 13 | { 14 | "name": "cos.client.region", 15 | "type": "java.lang.String", 16 | "description": "Description for cos.client.region." 17 | }, 18 | { 19 | "name": "cos.client.bucket", 20 | "type": "java.lang.String", 21 | "description": "Description for cos.client.bucket." 22 | }, 23 | { 24 | "name": "wx.open.appId", 25 | "type": "java.lang.String", 26 | "description": "Description for wx.open.appId." 27 | }, 28 | { 29 | "name": "wx.open.appSecret", 30 | "type": "java.lang.String", 31 | "description": "Description for wx.open.appSecret." 32 | } 33 | ] 34 | } -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/config/CorsConfig.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.web.servlet.config.annotation.CorsRegistry; 5 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 6 | 7 | /** 8 | * 全局跨域配置 9 | * 10 | * @author 程序员鱼皮 11 | * @from 编程导航知识星球 12 | */ 13 | @Configuration 14 | public class CorsConfig implements WebMvcConfigurer { 15 | 16 | @Override 17 | public void addCorsMappings(CorsRegistry registry) { 18 | // 覆盖所有请求 19 | registry.addMapping("/**") 20 | // 允许发送 Cookie 21 | .allowCredentials(true) 22 | // 放行哪些域名(必须用 patterns,否则 * 会和 allowCredentials 冲突) 23 | .allowedOriginPatterns("*") 24 | .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") 25 | .allowedHeaders("*") 26 | .exposedHeaders("*"); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; 7 | import org.springframework.context.annotation.EnableAspectJAutoProxy; 8 | import org.springframework.scheduling.annotation.EnableScheduling; 9 | 10 | /** 11 | * 主类(项目启动入口) 12 | * 13 | * @author 程序员鱼皮 14 | * @from 编程导航知识星球 15 | */ 16 | // todo 如需开启 Redis,须移除 exclude 中的内容 17 | @SpringBootApplication(exclude = {RedisAutoConfiguration.class}) 18 | @MapperScan("com.yupi.springbootinit.mapper") 19 | @EnableScheduling 20 | @EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true) 21 | public class MainApplication { 22 | 23 | public static void main(String[] args) { 24 | SpringApplication.run(MainApplication.class, args); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/config/MyBatisPlusConfig.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.config; 2 | 3 | import com.baomidou.mybatisplus.annotation.DbType; 4 | import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; 5 | import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; 6 | import org.mybatis.spring.annotation.MapperScan; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | /** 11 | * MyBatis Plus 配置 12 | * 13 | * @author https://github.com/liyupi 14 | */ 15 | @Configuration 16 | @MapperScan("com.yupi.springbootinit.mapper") 17 | public class MyBatisPlusConfig { 18 | 19 | /** 20 | * 拦截器配置 21 | * 22 | * @return 23 | */ 24 | @Bean 25 | public MybatisPlusInterceptor mybatisPlusInterceptor() { 26 | MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); 27 | // 分页插件 28 | interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); 29 | return interceptor; 30 | } 31 | } -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/config/RedissonConfig.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.config; 2 | 3 | 4 | import lombok.Data; 5 | import org.redisson.Redisson; 6 | import org.redisson.api.RedissonClient; 7 | import org.redisson.config.Config; 8 | import org.springframework.boot.context.properties.ConfigurationProperties; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.Configuration; 11 | 12 | @Configuration 13 | @ConfigurationProperties(prefix = "spring.redis") 14 | @Data 15 | public class RedissonConfig { 16 | 17 | private Integer database; 18 | 19 | private String host; 20 | 21 | private Integer port; 22 | 23 | private String password; 24 | 25 | @Bean 26 | public RedissonClient redissonClient() { 27 | Config config = new Config(); 28 | config.useSingleServer() 29 | .setDatabase(database) 30 | .setAddress("redis://" + host + ":" + port); 31 | RedissonClient redisson = Redisson.create(config); 32 | return redisson; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/common/ErrorCode.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.common; 2 | 3 | /** 4 | * 自定义错误码 5 | * 6 | * @author 程序员鱼皮 7 | * @from 编程导航知识星球 8 | */ 9 | public enum ErrorCode { 10 | 11 | SUCCESS(0, "ok"), 12 | PARAMS_ERROR(40000, "请求参数错误"), 13 | NOT_LOGIN_ERROR(40100, "未登录"), 14 | NO_AUTH_ERROR(40101, "无权限"), 15 | NOT_FOUND_ERROR(40400, "请求数据不存在"), 16 | TOO_MANY_REQUEST(42900, "请求太过频繁"), 17 | FORBIDDEN_ERROR(40300, "禁止访问"), 18 | SYSTEM_ERROR(50000, "系统内部异常"), 19 | OPERATION_ERROR(50001, "操作失败"); 20 | 21 | /** 22 | * 状态码 23 | */ 24 | private final int code; 25 | 26 | /** 27 | * 信息 28 | */ 29 | private final String message; 30 | 31 | ErrorCode(int code, String message) { 32 | this.code = code; 33 | this.message = message; 34 | } 35 | 36 | public int getCode() { 37 | return code; 38 | } 39 | 40 | public String getMessage() { 41 | return message; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/dto/chart/ChartEditRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.dto.chart; 2 | 3 | import java.io.Serializable; 4 | import java.util.Date; 5 | import java.util.List; 6 | 7 | import com.baomidou.mybatisplus.annotation.IdType; 8 | import com.baomidou.mybatisplus.annotation.TableField; 9 | import com.baomidou.mybatisplus.annotation.TableId; 10 | import lombok.Data; 11 | 12 | /** 13 | * 编辑请求 14 | * 15 | * @author 程序员鱼皮 16 | * @from 编程导航知识星球 17 | */ 18 | @Data 19 | public class ChartEditRequest implements Serializable { 20 | 21 | /** 22 | * id 23 | */ 24 | private Long id; 25 | /** 26 | * 图表名称 27 | */ 28 | private String name; 29 | 30 | /** 31 | * 分析目标 32 | */ 33 | private String goal; 34 | 35 | /** 36 | * 图表数据 37 | */ 38 | private String chartData; 39 | 40 | /** 41 | * 图表类型 42 | */ 43 | private String chatType; 44 | 45 | 46 | private static final long serialVersionUID = 1L; 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/com/yupi/springbootinit/utils/EasyExcelTest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.utils; 2 | 3 | import com.alibaba.excel.EasyExcel; 4 | import com.alibaba.excel.support.ExcelTypeEnum; 5 | import org.junit.jupiter.api.Test; 6 | import org.springframework.boot.test.context.SpringBootTest; 7 | import org.springframework.util.ResourceUtils; 8 | 9 | import java.io.File; 10 | import java.io.FileNotFoundException; 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | /** 15 | * EasyExcel 测试 16 | * 17 | * @author 程序员鱼皮 18 | * @from 编程导航知识星球 19 | */ 20 | @SpringBootTest 21 | public class EasyExcelTest { 22 | 23 | @Test 24 | public void doImport() throws FileNotFoundException { 25 | File file = ResourceUtils.getFile("classpath:图表数据.xlsx"); 26 | List> list = EasyExcel.read(file) 27 | .excelType(ExcelTypeEnum.XLSX) 28 | .sheet() 29 | .headRowNumber(0) 30 | .doReadSync(); 31 | System.out.println(list); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/dto/chart/ChartUpdateRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.dto.chart; 2 | 3 | import java.io.Serializable; 4 | import java.util.Date; 5 | import java.util.List; 6 | 7 | import com.baomidou.mybatisplus.annotation.IdType; 8 | import com.baomidou.mybatisplus.annotation.TableField; 9 | import com.baomidou.mybatisplus.annotation.TableId; 10 | import lombok.Data; 11 | 12 | /** 13 | * 更新请求 14 | * 15 | */ 16 | @Data 17 | public class ChartUpdateRequest implements Serializable { 18 | 19 | 20 | /** 21 | * id 22 | */ 23 | private Long id; 24 | /** 25 | * 图表名称 26 | */ 27 | private String name; 28 | 29 | /** 30 | * 分析目标 31 | */ 32 | private String goal; 33 | 34 | /** 35 | * 图表数据 36 | */ 37 | private String chartData; 38 | 39 | /** 40 | * 图表类型 41 | */ 42 | private String chatType; 43 | 44 | /** 45 | * 生成的图表数据 46 | */ 47 | private String genChat; 48 | 49 | /** 50 | * 生成的分析结论 51 | */ 52 | private String genResult; 53 | 54 | private static final long serialVersionUID = 1L; 55 | } 56 | -------------------------------------------------------------------------------- /src/test/java/com/yupi/springbootinit/service/UserServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.service; 2 | 3 | import javax.annotation.Resource; 4 | import org.junit.jupiter.api.Assertions; 5 | import org.junit.jupiter.api.Test; 6 | import org.springframework.boot.test.context.SpringBootTest; 7 | 8 | /** 9 | * 用户服务测试 10 | * 11 | * @author 程序员鱼皮 12 | * @from 编程导航知识星球 13 | */ 14 | @SpringBootTest 15 | public class UserServiceTest { 16 | 17 | @Resource 18 | private UserService userService; 19 | 20 | @Test 21 | void userRegister() { 22 | String userAccount = "yupi"; 23 | String userPassword = ""; 24 | String checkPassword = "123456"; 25 | try { 26 | long result = userService.userRegister(userAccount, userPassword, checkPassword); 27 | Assertions.assertEquals(-1, result); 28 | userAccount = "yu"; 29 | result = userService.userRegister(userAccount, userPassword, checkPassword); 30 | Assertions.assertEquals(-1, result); 31 | } catch (Exception e) { 32 | 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/manager/RedisLimiterManager.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.manager; 2 | 3 | 4 | import com.yupi.springbootinit.common.ErrorCode; 5 | import com.yupi.springbootinit.exception.BusinessException; 6 | import org.redisson.api.RRateLimiter; 7 | import org.redisson.api.RateIntervalUnit; 8 | import org.redisson.api.RateType; 9 | import org.redisson.api.RedissonClient; 10 | import org.springframework.stereotype.Service; 11 | 12 | import javax.annotation.Resource; 13 | 14 | /** 15 | * redis限流控制器 16 | */ 17 | @Service 18 | public class RedisLimiterManager { 19 | 20 | @Resource 21 | RedissonClient redissonClient; 22 | 23 | /** 24 | * 限流操作 25 | * 26 | * @param key 27 | */ 28 | public void doRateLimit(String key) { 29 | RRateLimiter rRateLimiter = redissonClient.getRateLimiter(key); 30 | //限流器 31 | rRateLimiter.trySetRate(RateType.OVERALL, 2, 1, RateIntervalUnit.SECONDS); 32 | //每次消耗1个令牌 33 | boolean canOp = rRateLimiter.tryAcquire(1); 34 | if (!canOp) { 35 | throw new BusinessException(ErrorCode.TOO_MANY_REQUEST); 36 | } 37 | 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /sql/post_es_mapping.json: -------------------------------------------------------------------------------- 1 | { 2 | "aliases": { 3 | "post": {} 4 | }, 5 | "mappings": { 6 | "properties": { 7 | "title": { 8 | "type": "text", 9 | "analyzer": "ik_max_word", 10 | "search_analyzer": "ik_smart", 11 | "fields": { 12 | "keyword": { 13 | "type": "keyword", 14 | "ignore_above": 256 15 | } 16 | } 17 | }, 18 | "content": { 19 | "type": "text", 20 | "analyzer": "ik_max_word", 21 | "search_analyzer": "ik_smart", 22 | "fields": { 23 | "keyword": { 24 | "type": "keyword", 25 | "ignore_above": 256 26 | } 27 | } 28 | }, 29 | "tags": { 30 | "type": "keyword" 31 | }, 32 | "thumbNum": { 33 | "type": "long" 34 | }, 35 | "favourNum": { 36 | "type": "long" 37 | }, 38 | "userId": { 39 | "type": "keyword" 40 | }, 41 | "createTime": { 42 | "type": "date" 43 | }, 44 | "updateTime": { 45 | "type": "date" 46 | }, 47 | "isDelete": { 48 | "type": "keyword" 49 | } 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/exception/GlobalExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.exception; 2 | 3 | import com.yupi.springbootinit.common.BaseResponse; 4 | import com.yupi.springbootinit.common.ErrorCode; 5 | import com.yupi.springbootinit.common.ResultUtils; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.web.bind.annotation.ExceptionHandler; 8 | import org.springframework.web.bind.annotation.RestControllerAdvice; 9 | 10 | /** 11 | * 全局异常处理器 12 | * 13 | * @author 程序员鱼皮 14 | * @from 编程导航知识星球 15 | */ 16 | @RestControllerAdvice 17 | @Slf4j 18 | public class GlobalExceptionHandler { 19 | 20 | @ExceptionHandler(BusinessException.class) 21 | public BaseResponse businessExceptionHandler(BusinessException e) { 22 | log.error("BusinessException", e); 23 | return ResultUtils.error(e.getCode(), e.getMessage()); 24 | } 25 | 26 | @ExceptionHandler(RuntimeException.class) 27 | public BaseResponse runtimeExceptionHandler(RuntimeException e) { 28 | log.error("RuntimeException", e); 29 | return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "系统错误"); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/service/TextTaskService.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.service; 2 | 3 | import com.yupi.springbootinit.model.dto.text.GenTextTaskByAiRequest; 4 | import com.yupi.springbootinit.model.entity.Chart; 5 | import com.yupi.springbootinit.model.entity.TextRecord; 6 | import com.yupi.springbootinit.model.entity.TextTask; 7 | import com.baomidou.mybatisplus.extension.service.IService; 8 | import com.yupi.springbootinit.model.entity.User; 9 | import org.springframework.web.multipart.MultipartFile; 10 | 11 | /** 12 | * @author MA_dou 13 | * @description 针对表【text_task(文本任务表)】的数据库操作Service 14 | * @createDate 2023-07-12 20:32:15 15 | */ 16 | public interface TextTaskService extends IService { 17 | 18 | /** 19 | * 获取准备分析的表数据(事务回滚) 20 | * @param multipartFile 21 | * @param genTextTaskByAiRequest 22 | * @param loginUser 23 | * @return 24 | */ 25 | TextTask getTextTask(MultipartFile multipartFile, GenTextTaskByAiRequest genTextTaskByAiRequest, User loginUser); 26 | 27 | /** 28 | * 文本更新失败 29 | * @param textTaskId 30 | * @param execMessage 31 | */ 32 | void handleTextTaskUpdateError(Long textTaskId, String execMessage); 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/manager/AiManager.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.manager; 2 | 3 | import com.yupi.springbootinit.common.ErrorCode; 4 | import com.yupi.springbootinit.exception.BusinessException; 5 | import com.yupi.yucongming.dev.client.YuCongMingClient; 6 | import com.yupi.yucongming.dev.common.BaseResponse; 7 | import com.yupi.yucongming.dev.model.DevChatRequest; 8 | import com.yupi.yucongming.dev.model.DevChatResponse; 9 | import org.springframework.stereotype.Service; 10 | 11 | import javax.annotation.Resource; 12 | 13 | /** 14 | * Ai控制器 15 | */ 16 | @Service 17 | public class AiManager { 18 | @Resource 19 | private YuCongMingClient client; 20 | 21 | public String doChat(String message,Long modelId){ 22 | DevChatRequest devChatRequest = new DevChatRequest(); 23 | devChatRequest.setModelId(modelId); 24 | devChatRequest.setMessage(message); 25 | 26 | // 获取响应 27 | BaseResponse response = client.doChat(devChatRequest); 28 | 29 | if (response == null){ 30 | throw new BusinessException(ErrorCode.SYSTEM_ERROR,"AI 响应错误"); 31 | } 32 | return response.getData().getContent(); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 前言 2 | *** 3 | 开源地址 4 | 5 | [微服务框架前端代码](https://github.com/MA-douzhang/gebi-frontend/tree/dev-cloud) 6 | 7 | [微服务框架后端代码](https://github.com/MA-douzhang/gebi-backend/tree/dev-cloud) 8 | 9 | [SpringBoot框架前端代码](https://github.com/MA-douzhang/gebi-frontend) 10 | 11 | [SpringBoot框架后端代码](https://github.com/MA-douzhang/gebi-backend) 12 | 13 | *** 14 | GeBI项目的后端源码,主要是用于总结学习中间件的知识和利用AI实现更便捷的功能。 15 | 16 | 后端功能主要分为,三个服务模块,用户服务,图表服务,文本服务。 17 | 18 | ## 技术栈 19 | *** 20 | 框架:Spring Boot 21 | 22 | 数据库:MySQL 23 | 24 | 中间件:Redis + RabbitMq 25 | 26 | 插件:Mybatis(Plus),Swagger(接口文档),鱼聪明 27 | 28 | # 服务器部署 29 | 1. 使用服务器配置为2核4G 30 | 2. 宝塔面板 31 | 3. 详细步骤和思路笔记在项目doc目录下 32 | 33 | ## 说明 34 | *** 35 | >如果对您有帮助,您可以右上角点一个“start”支持一下,👍 36 | > 37 | > 如有问题请直接在 Issues 中提,或者您发现问题并有非常好的解决方案,欢迎 PR 👍 38 | 39 | # 效果展示 40 | *** 41 | [查看在线展示](http://60.204.157.128/) 42 | 43 | ## 功能 44 | *** 45 | + [x] 登录注册功能 46 | + [x] 消息队列保证服务的健壮性 47 | + [x] 支付模块 48 | + [x] AI将文本格式转换 49 | + [x] AI将表格转为可视化 50 | 51 | ~~给开发者打钱的支付功能~~ 52 | 53 | 54 | # 总结 55 | *** 56 | 1. 将Spring Boot项目重构成Spring Cloud项目,利用微服务将多个模块解耦合,保证服务的稳定性, 57 | 当有一个服务出错时也不会影响其它服务进行。 58 | 2. 消息队列使用死信队列,保证当AI服务偶尔出错时,能够重新放回队列继续服务,提高服务稳定性,当超过1min还未成功就放入死信队列。 59 | 3. 将多个服务解耦合后,在后续项目扩展中可以更加便捷得增加模块且不影响原来的项目框架。 60 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/config/JsonConfig.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.config; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import com.fasterxml.jackson.databind.module.SimpleModule; 5 | import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; 6 | import org.springframework.boot.jackson.JsonComponent; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; 9 | 10 | /** 11 | * Spring MVC Json 配置 12 | * 13 | * @author 程序员鱼皮 14 | * @from 编程导航知识星球 15 | */ 16 | @JsonComponent 17 | public class JsonConfig { 18 | 19 | /** 20 | * 添加 Long 转 json 精度丢失的配置 21 | */ 22 | @Bean 23 | public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) { 24 | ObjectMapper objectMapper = builder.createXmlMapper(false).build(); 25 | SimpleModule module = new SimpleModule(); 26 | module.addSerializer(Long.class, ToStringSerializer.instance); 27 | module.addSerializer(Long.TYPE, ToStringSerializer.instance); 28 | objectMapper.registerModule(module); 29 | return objectMapper; 30 | } 31 | } -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/dto/chart/ChartQueryRequest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.dto.chart; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.yupi.springbootinit.common.PageRequest; 7 | import java.io.Serializable; 8 | import java.util.Date; 9 | import java.util.List; 10 | import lombok.Data; 11 | import lombok.EqualsAndHashCode; 12 | 13 | /** 14 | * 查询请求 15 | * 16 | * @author 程序员鱼皮 17 | * @from 编程导航知识星球 18 | */ 19 | @EqualsAndHashCode(callSuper = true) 20 | @Data 21 | public class ChartQueryRequest extends PageRequest implements Serializable { 22 | 23 | /** 24 | * id 25 | */ 26 | private Long id; 27 | /** 28 | * 图表名称 29 | */ 30 | private String name; 31 | 32 | /** 33 | * 分析目标 34 | */ 35 | private String goal; 36 | 37 | 38 | /** 39 | * 图表类型 40 | */ 41 | private String chatType; 42 | 43 | /** 44 | * 创建用户Id 45 | */ 46 | private Long userId; 47 | 48 | private static final long serialVersionUID = 1L; 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/exception/ThrowUtils.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.exception; 2 | 3 | import com.yupi.springbootinit.common.ErrorCode; 4 | 5 | /** 6 | * 抛异常工具类 7 | * 8 | * @author 程序员鱼皮 9 | * @from 编程导航知识星球 10 | */ 11 | public class ThrowUtils { 12 | 13 | /** 14 | * 条件成立则抛异常 15 | * 16 | * @param condition 17 | * @param runtimeException 18 | */ 19 | public static void throwIf(boolean condition, RuntimeException runtimeException) { 20 | if (condition) { 21 | throw runtimeException; 22 | } 23 | } 24 | 25 | /** 26 | * 条件成立则抛异常 27 | * 28 | * @param condition 29 | * @param errorCode 30 | */ 31 | public static void throwIf(boolean condition, ErrorCode errorCode) { 32 | throwIf(condition, new BusinessException(errorCode)); 33 | } 34 | 35 | /** 36 | * 条件成立则抛异常 37 | * 38 | * @param condition 39 | * @param errorCode 40 | * @param message 41 | */ 42 | public static void throwIf(boolean condition, ErrorCode errorCode, String message) { 43 | throwIf(condition, new BusinessException(errorCode, message)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/config/ThreadPoolExecutorConfig.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.config; 2 | 3 | 4 | import org.jetbrains.annotations.NotNull; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | import java.util.concurrent.ArrayBlockingQueue; 9 | import java.util.concurrent.ThreadFactory; 10 | import java.util.concurrent.ThreadPoolExecutor; 11 | import java.util.concurrent.TimeUnit; 12 | 13 | @Configuration 14 | public class ThreadPoolExecutorConfig { 15 | 16 | @Bean 17 | public ThreadPoolExecutor threadPoolExecutor(){ 18 | 19 | ThreadFactory threadFactory = new ThreadFactory() { 20 | private int count = 1; 21 | 22 | @Override 23 | public Thread newThread(@NotNull Runnable runnable) { 24 | Thread thread = new Thread(runnable); 25 | thread.setName("线程"+count); 26 | count++; 27 | return thread; 28 | } 29 | }; 30 | 31 | 32 | ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,4,100, 33 | TimeUnit.SECONDS,new ArrayBlockingQueue<>(4),threadFactory); 34 | return threadPoolExecutor; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/entity/User.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | 5 | import java.io.Serializable; 6 | import java.util.Date; 7 | import lombok.Data; 8 | 9 | /** 10 | * 用户 11 | * @TableName user 12 | */ 13 | @TableName(value ="user") 14 | @Data 15 | public class User implements Serializable { 16 | /** 17 | * id 18 | */ 19 | @TableId(type = IdType.ASSIGN_ID) 20 | private Long id; 21 | 22 | /** 23 | * 账号 24 | */ 25 | private String userAccount; 26 | 27 | /** 28 | * 密码 29 | */ 30 | private String userPassword; 31 | 32 | /** 33 | * 用户昵称 34 | */ 35 | private String userName; 36 | 37 | /** 38 | * 用户头像 39 | */ 40 | private String userAvatar; 41 | 42 | /** 43 | * 用户角色:user/admin/ban 44 | */ 45 | private String userRole; 46 | 47 | /** 48 | * 创建时间 49 | */ 50 | private Date createTime; 51 | 52 | /** 53 | * 更新时间 54 | */ 55 | private Date updateTime; 56 | 57 | /** 58 | * 是否删除 59 | */ 60 | @TableLogic 61 | private Integer isDelete; 62 | 63 | @TableField(exist = false) 64 | private static final long serialVersionUID = 1L; 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/wxmp/handler/EventHandler.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.wxmp.handler; 2 | 3 | import java.util.Map; 4 | import me.chanjar.weixin.common.error.WxErrorException; 5 | import me.chanjar.weixin.common.session.WxSessionManager; 6 | import me.chanjar.weixin.mp.api.WxMpMessageHandler; 7 | import me.chanjar.weixin.mp.api.WxMpService; 8 | import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; 9 | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; 10 | import org.springframework.stereotype.Component; 11 | 12 | /** 13 | * 事件处理器 14 | * 15 | * @author 程序员鱼皮 16 | * @from 编程导航知识星球 17 | **/ 18 | @Component 19 | public class EventHandler implements WxMpMessageHandler { 20 | 21 | @Override 22 | public WxMpXmlOutMessage handle(WxMpXmlMessage wxMpXmlMessage, Map map, WxMpService wxMpService, 23 | WxSessionManager wxSessionManager) throws WxErrorException { 24 | final String content = "您点击了菜单"; 25 | // 调用接口,返回验证码 26 | return WxMpXmlOutMessage.TEXT().content(content) 27 | .fromUser(wxMpXmlMessage.getToUser()) 28 | .toUser(wxMpXmlMessage.getFromUser()) 29 | .build(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/wxmp/handler/MessageHandler.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.wxmp.handler; 2 | 3 | import java.util.Map; 4 | import me.chanjar.weixin.common.error.WxErrorException; 5 | import me.chanjar.weixin.common.session.WxSessionManager; 6 | import me.chanjar.weixin.mp.api.WxMpMessageHandler; 7 | import me.chanjar.weixin.mp.api.WxMpService; 8 | import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; 9 | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; 10 | import org.springframework.stereotype.Component; 11 | 12 | /** 13 | * 消息处理器 14 | * 15 | * @author 程序员鱼皮 16 | * @from 编程导航知识星球 17 | **/ 18 | @Component 19 | public class MessageHandler implements WxMpMessageHandler { 20 | 21 | @Override 22 | public WxMpXmlOutMessage handle(WxMpXmlMessage wxMpXmlMessage, Map map, 23 | WxMpService wxMpService, WxSessionManager wxSessionManager) throws WxErrorException { 24 | String content = "我是复读机:" + wxMpXmlMessage.getContent(); 25 | return WxMpXmlOutMessage.TEXT().content(content) 26 | .fromUser(wxMpXmlMessage.getToUser()) 27 | .toUser(wxMpXmlMessage.getFromUser()) 28 | .build(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/common/ResultUtils.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.common; 2 | 3 | /** 4 | * 返回工具类 5 | * 6 | * @author 程序员鱼皮 7 | * @from 编程导航知识星球 8 | */ 9 | public class ResultUtils { 10 | 11 | /** 12 | * 成功 13 | * 14 | * @param data 15 | * @param 16 | * @return 17 | */ 18 | public static BaseResponse success(T data) { 19 | return new BaseResponse<>(0, data, "ok"); 20 | } 21 | 22 | /** 23 | * 失败 24 | * 25 | * @param errorCode 26 | * @return 27 | */ 28 | public static BaseResponse error(ErrorCode errorCode) { 29 | return new BaseResponse<>(errorCode); 30 | } 31 | 32 | /** 33 | * 失败 34 | * 35 | * @param code 36 | * @param message 37 | * @return 38 | */ 39 | public static BaseResponse error(int code, String message) { 40 | return new BaseResponse(code, null, message); 41 | } 42 | 43 | /** 44 | * 失败 45 | * 46 | * @param errorCode 47 | * @return 48 | */ 49 | public static BaseResponse error(ErrorCode errorCode, String message) { 50 | return new BaseResponse(errorCode.getCode(), null, message); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/wxmp/handler/SubscribeHandler.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.wxmp.handler; 2 | 3 | import java.util.Map; 4 | import me.chanjar.weixin.common.error.WxErrorException; 5 | import me.chanjar.weixin.common.session.WxSessionManager; 6 | import me.chanjar.weixin.mp.api.WxMpMessageHandler; 7 | import me.chanjar.weixin.mp.api.WxMpService; 8 | import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; 9 | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; 10 | import org.springframework.stereotype.Component; 11 | 12 | /** 13 | * 关注处理器 14 | * 15 | * @author 程序员鱼皮 16 | * @from 编程导航知识星球 17 | **/ 18 | @Component 19 | public class SubscribeHandler implements WxMpMessageHandler { 20 | 21 | @Override 22 | public WxMpXmlOutMessage handle(WxMpXmlMessage wxMpXmlMessage, Map map, 23 | WxMpService wxMpService, WxSessionManager wxSessionManager) throws WxErrorException { 24 | final String content = "感谢关注"; 25 | // 调用接口,返回验证码 26 | return WxMpXmlOutMessage.TEXT().content(content) 27 | .fromUser(wxMpXmlMessage.getToUser()) 28 | .toUser(wxMpXmlMessage.getFromUser()) 29 | .build(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/constant/MqConstant.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.constant; 2 | 3 | /** 4 | * mq初始化常量 5 | */ 6 | public interface MqConstant { 7 | String BI_EXCHANGE_NAME = "bi_exchange"; 8 | 9 | String BI_QUEUE_NAME="bi_queue"; 10 | 11 | String BI_ROUTING_KEY="bi_routingKey"; 12 | //死信 13 | String BI_DEAD_EXCHANGE_NAME="bi_dead_exchange"; 14 | String BI_DEAD_QUEUE_NAME="bi_dead_queue"; 15 | 16 | String BI_DEAD_ROUTING_KEY="bi_dead_routingKey"; 17 | 18 | 19 | //订单支付队列 20 | String ORDERS_EXCHANGE_NAME = "orders_exchange"; 21 | 22 | String ORDERS_QUEUE_NAME="orders_queue"; 23 | 24 | String ORDERS_ROUTING_KEY="orders_routingKey"; 25 | //死信 26 | String ORDERS_DEAD_EXCHANGE_NAME="orders_dead_exchange"; 27 | String ORDERS_DEAD_QUEUE_NAME="orders_dead_queue"; 28 | 29 | String ORDERS_DEAD_ROUTING_KEY="orders_dead_routingKey"; 30 | 31 | //文本AI生成队列 32 | 33 | String TEXT_EXCHANGE_NAME = "text_exchange"; 34 | 35 | String TEXT_QUEUE_NAME="text_queue"; 36 | 37 | String TEXT_ROUTING_KEY="text_routingKey"; 38 | //死信 39 | String TEXT_DEAD_EXCHANGE_NAME="text_dead_exchange"; 40 | String TEXT_DEAD_QUEUE_NAME="text_dead_queue"; 41 | 42 | String TEXT_DEAD_ROUTING_KEY="text_dead_routingKey"; 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/entity/TextRecord.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | 5 | import java.io.Serializable; 6 | import java.util.Date; 7 | import lombok.Data; 8 | 9 | /** 10 | * 文本记录表 11 | * @TableName text_record 12 | */ 13 | @TableName(value ="text_record") 14 | @Data 15 | public class TextRecord implements Serializable { 16 | /** 17 | * id 18 | */ 19 | @TableId(type = IdType.ASSIGN_ID) 20 | private Long id; 21 | 22 | /** 23 | * 文本任务id 24 | */ 25 | private Long textTaskId; 26 | 27 | /** 28 | * 文本内容 29 | */ 30 | private String textContent; 31 | 32 | /** 33 | * 生成的文本内容 34 | */ 35 | private String genTextContent; 36 | 37 | /** 38 | * wait,running,succeed,failed 39 | */ 40 | private String status; 41 | 42 | /** 43 | * 执行信息 44 | */ 45 | private String execMessage; 46 | 47 | /** 48 | * 创建时间 49 | */ 50 | private Date createTime; 51 | 52 | /** 53 | * 更新时间 54 | */ 55 | private Date updateTime; 56 | 57 | /** 58 | * 是否删除 59 | */ 60 | @TableLogic 61 | private Integer isDelete; 62 | 63 | @TableField(exist = false) 64 | private static final long serialVersionUID = 1L; 65 | } 66 | -------------------------------------------------------------------------------- /src/main/resources/mapper/UserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | id,userAccount,userPassword, 21 | userName,userAvatar,userRole, 22 | createTime,updateTime,isDelete 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/vo/ChartVO.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.vo; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | import java.util.Date; 11 | 12 | /** 13 | * 图表信息表(脱敏) 14 | */ 15 | @Data 16 | public class ChartVO implements Serializable { 17 | 18 | private Long id; 19 | 20 | /** 21 | * 图表名称 22 | */ 23 | private String name; 24 | 25 | /** 26 | * 分析目标 27 | */ 28 | private String goal; 29 | 30 | /** 31 | * 图表数据 32 | */ 33 | private String chartData; 34 | 35 | /** 36 | * 图表类型 37 | */ 38 | private String chatType; 39 | 40 | /** 41 | * 生成的图表数据 42 | */ 43 | private String genChat; 44 | 45 | /** 46 | * 生成的分析结论 47 | */ 48 | private String genResult; 49 | /** 50 | * 执行状态 51 | */ 52 | private String status; 53 | /** 54 | * 执行信息 55 | */ 56 | private String execMessage; 57 | 58 | /** 59 | * 创建时间 60 | */ 61 | private Date createTime; 62 | 63 | 64 | private static final long serialVersionUID = 1L; 65 | } 66 | -------------------------------------------------------------------------------- /src/main/resources/mapper/TextRecordMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | id,textTaskId,textContent, 21 | genTextContent,status,execMessage, 22 | createTime,updateTime,isDelete 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/service/impl/TextRecordServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.yupi.springbootinit.model.entity.TextRecord; 5 | import com.yupi.springbootinit.service.TextRecordService; 6 | import com.yupi.springbootinit.mapper.TextRecordMapper; 7 | import org.apache.commons.lang3.StringUtils; 8 | import org.springframework.stereotype.Service; 9 | 10 | /** 11 | * @author MA_dou 12 | * @description 针对表【text_record(文本记录表)】的数据库操作Service实现 13 | * @createDate 2023-07-12 20:32:09 14 | */ 15 | @Service 16 | public class TextRecordServiceImpl extends ServiceImpl 17 | implements TextRecordService{ 18 | 19 | @Override 20 | public String buildUserInput(TextRecord textRecord,String textTaskType) { 21 | String textContent = textRecord.getTextContent(); 22 | //构造用户输入 23 | StringBuilder userInput = new StringBuilder(); 24 | String gold = "请使用"+textTaskType+"语法对下面文章格式化"; 25 | 26 | userInput.append(gold).append("\n"); 27 | 28 | if (StringUtils.isNotBlank(textContent)) { 29 | textContent = textContent.trim(); 30 | userInput.append(textContent); 31 | } 32 | return userInput.toString(); 33 | } 34 | 35 | } 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/entity/Orders.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | 5 | import java.io.Serializable; 6 | import java.util.Date; 7 | import lombok.Data; 8 | 9 | /** 10 | * 充值订单表 11 | * @TableName orders 12 | */ 13 | @TableName(value ="orders") 14 | @Data 15 | public class Orders implements Serializable { 16 | /** 17 | * 订单id 18 | */ 19 | @TableId(type = IdType.ASSIGN_ID) 20 | private Long id; 21 | 22 | /** 23 | * 支付宝交易凭证id 24 | */ 25 | private String alipayTradeNo; 26 | 27 | /** 28 | * 用户id 29 | */ 30 | private Long userId; 31 | /** 32 | * 交易名称 33 | */ 34 | private String subject; 35 | 36 | /** 37 | * 交易金额 38 | */ 39 | private Double totalAmount; 40 | 41 | /** 42 | * unpaid,paying,succeed,failed 43 | */ 44 | private String tradeStatus; 45 | 46 | /** 47 | * 支付宝买家id 48 | */ 49 | private String buyerId; 50 | 51 | /** 52 | * 创建时间 53 | */ 54 | private Date createTime; 55 | 56 | /** 57 | * 更新时间 58 | */ 59 | private Date updateTime; 60 | 61 | /** 62 | * 是否删除 63 | */ 64 | @TableLogic 65 | private Integer isDelete; 66 | 67 | @TableField(exist = false) 68 | private static final long serialVersionUID = 1L; 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/entity/TextTask.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | 5 | import java.io.Serializable; 6 | import java.util.Date; 7 | import lombok.Data; 8 | 9 | /** 10 | * 文本任务表 11 | * @TableName text_task 12 | */ 13 | @TableName(value ="text_task") 14 | @Data 15 | public class TextTask implements Serializable { 16 | /** 17 | * 任务id 18 | */ 19 | @TableId(type = IdType.ASSIGN_ID) 20 | private Long id; 21 | 22 | /** 23 | * 笔记名称 24 | */ 25 | private String name; 26 | 27 | /** 28 | * 文本类型 29 | */ 30 | private String textType; 31 | 32 | /** 33 | * 生成的文本内容 34 | */ 35 | private String genTextContent; 36 | 37 | /** 38 | * 创建用户Id 39 | */ 40 | private Long userId; 41 | 42 | /** 43 | * wait,running,succeed,failed 44 | */ 45 | private String status; 46 | 47 | /** 48 | * 执行信息 49 | */ 50 | private String execMessage; 51 | 52 | /** 53 | * 创建时间 54 | */ 55 | private Date createTime; 56 | 57 | /** 58 | * 更新时间 59 | */ 60 | private Date updateTime; 61 | 62 | /** 63 | * 是否删除 64 | */ 65 | @TableLogic 66 | private Integer isDelete; 67 | 68 | @TableField(exist = false) 69 | private static final long serialVersionUID = 1L; 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/service/ChartService.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.service; 2 | 3 | import com.yupi.springbootinit.model.dto.chart.GenChartByAiRequest; 4 | import com.yupi.springbootinit.model.entity.Chart; 5 | import com.baomidou.mybatisplus.extension.service.IService; 6 | import com.yupi.springbootinit.model.entity.User; 7 | import org.springframework.web.multipart.MultipartFile; 8 | 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | /** 13 | * @author MA_dou 14 | * @description 针对表【chart(图表信息表)】的数据库操作Service 15 | * @createDate 2023-05-26 23:18:07 16 | */ 17 | public interface ChartService extends IService { 18 | 19 | /** 20 | * 图表用户输入构造 21 | * @param chart 22 | * @return 23 | */ 24 | String buildUserInput(Chart chart); 25 | /** 26 | * 处理Ai返回信息保存 27 | * @param result 28 | * @return 29 | */ 30 | boolean saveChartAiResult(String result, long chartId); 31 | 32 | /** 33 | * 图表更新失败 34 | * @param chartId 35 | * @param execMessage 36 | */ 37 | void handleChartUpdateError(Long chartId, String execMessage); 38 | /** 39 | * 获取准备分析的表数据(事务回滚) 40 | * @param multipartFile 41 | * @param genChartByAiRequest 42 | * @param loginUser 43 | * @return 44 | */ 45 | Chart getChartTask(MultipartFile multipartFile, GenChartByAiRequest genChartByAiRequest, User loginUser); 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/resources/mapper/OrdersMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | id,alipayTradeNo,userId,`subject`, 22 | totalAmount,tradeStatus,buyerId, 23 | createTime,updateTime,isDelete 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/main/resources/mapper/TextTaskMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | id,name,textType, 22 | genTextContent,userId,status, 23 | execMessage,createTime,updateTime, 24 | isDelete 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/test/java/com/yupi/springbootinit/utils/TxtUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.utils; 2 | 3 | import org.springframework.util.ResourceUtils; 4 | 5 | import java.io.*; 6 | 7 | public class TxtUtilsTest { 8 | public static void main(String[] args) { 9 | try { 10 | File file = ResourceUtils.getFile("classpath:笔记.txt"); 11 | readerFile(file); 12 | } catch (FileNotFoundException e) { 13 | throw new RuntimeException(e); 14 | } 15 | } 16 | public static void readerFile(File file) { 17 | try { 18 | // 获取文件内容 19 | BufferedReader reader = new BufferedReader(new FileReader(file)); 20 | String line; 21 | StringBuilder builder = new StringBuilder(); 22 | while ((line = reader.readLine()) != null) { 23 | // 处理文件内容,例如输出到控制台 24 | if (builder.length()+line.length()<=980){ 25 | builder.append(line).append("\n"); 26 | }else { 27 | //保存数据库 28 | 29 | 30 | System.out.println(builder); 31 | System.out.println("长度为"+builder.length()); 32 | System.out.println("========================="); 33 | builder.delete(0,builder.length()); 34 | } 35 | } 36 | reader.close(); 37 | } catch (IOException e) { 38 | e.printStackTrace(); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/config/CosClientConfig.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.config; 2 | 3 | import com.qcloud.cos.COSClient; 4 | import com.qcloud.cos.ClientConfig; 5 | import com.qcloud.cos.auth.BasicCOSCredentials; 6 | import com.qcloud.cos.auth.COSCredentials; 7 | import com.qcloud.cos.region.Region; 8 | import lombok.Data; 9 | import org.springframework.boot.context.properties.ConfigurationProperties; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | 13 | /** 14 | * 腾讯云对象存储客户端 15 | * 16 | * @author 程序员鱼皮 17 | * @from 编程导航知识星球 18 | */ 19 | @Configuration 20 | @ConfigurationProperties(prefix = "cos.client") 21 | @Data 22 | public class CosClientConfig { 23 | 24 | /** 25 | * accessKey 26 | */ 27 | private String accessKey; 28 | 29 | /** 30 | * secretKey 31 | */ 32 | private String secretKey; 33 | 34 | /** 35 | * 区域 36 | */ 37 | private String region; 38 | 39 | /** 40 | * 桶名 41 | */ 42 | private String bucket; 43 | 44 | @Bean 45 | public COSClient cosClient() { 46 | // 初始化用户身份信息(secretId, secretKey) 47 | COSCredentials cred = new BasicCOSCredentials(accessKey, secretKey); 48 | // 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224 49 | ClientConfig clientConfig = new ClientConfig(new Region(region)); 50 | // 生成cos客户端 51 | return new COSClient(cred, clientConfig); 52 | } 53 | } -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/manager/CosManager.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.manager; 2 | 3 | import com.qcloud.cos.COSClient; 4 | import com.qcloud.cos.model.PutObjectRequest; 5 | import com.qcloud.cos.model.PutObjectResult; 6 | import com.yupi.springbootinit.config.CosClientConfig; 7 | import java.io.File; 8 | import javax.annotation.Resource; 9 | import org.springframework.stereotype.Component; 10 | 11 | /** 12 | * Cos 对象存储操作 13 | * 14 | * @author 程序员鱼皮 15 | * @from 编程导航知识星球 16 | */ 17 | @Component 18 | public class CosManager { 19 | 20 | @Resource 21 | private CosClientConfig cosClientConfig; 22 | 23 | @Resource 24 | private COSClient cosClient; 25 | 26 | /** 27 | * 上传对象 28 | * 29 | * @param key 唯一键 30 | * @param localFilePath 本地文件路径 31 | * @return 32 | */ 33 | public PutObjectResult putObject(String key, String localFilePath) { 34 | PutObjectRequest putObjectRequest = new PutObjectRequest(cosClientConfig.getBucket(), key, 35 | new File(localFilePath)); 36 | return cosClient.putObject(putObjectRequest); 37 | } 38 | 39 | /** 40 | * 上传对象 41 | * 42 | * @param key 唯一键 43 | * @param file 文件 44 | * @return 45 | */ 46 | public PutObjectResult putObject(String key, File file) { 47 | PutObjectRequest putObjectRequest = new PutObjectRequest(cosClientConfig.getBucket(), key, 48 | file); 49 | return cosClient.putObject(putObjectRequest); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/entity/Chart.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | 5 | import java.io.Serializable; 6 | import java.util.Date; 7 | import lombok.Data; 8 | 9 | /** 10 | * 图表信息表 11 | * @TableName chart 12 | */ 13 | @TableName(value ="chart") 14 | @Data 15 | public class Chart implements Serializable { 16 | /** 17 | * id 18 | */ 19 | @TableId(type = IdType.ASSIGN_ID) 20 | private Long id; 21 | 22 | /** 23 | * 图表名称 24 | */ 25 | private String name; 26 | 27 | /** 28 | * 分析目标 29 | */ 30 | private String goal; 31 | 32 | /** 33 | * 图表数据 34 | */ 35 | private String chartData; 36 | 37 | /** 38 | * 图表类型 39 | */ 40 | private String chatType; 41 | 42 | /** 43 | * 生成的图表数据 44 | */ 45 | private String genChat; 46 | 47 | /** 48 | * 生成的分析结论 49 | */ 50 | private String genResult; 51 | 52 | /** 53 | * 创建用户Id 54 | */ 55 | private Long userId; 56 | 57 | /** 58 | * 执行状态 59 | */ 60 | private String status; 61 | /** 62 | * 执行信息 63 | */ 64 | private String execMessage; 65 | 66 | /** 67 | * 创建时间 68 | */ 69 | private Date createTime; 70 | 71 | /** 72 | * 更新时间 73 | */ 74 | private Date updateTime; 75 | 76 | /** 77 | * 是否删除 78 | */ 79 | @TableLogic 80 | private Integer isDelete; 81 | 82 | @TableField(exist = false) 83 | private static final long serialVersionUID = 1L; 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/config/Knife4jConfig.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.context.annotation.Profile; 6 | import springfox.documentation.builders.ApiInfoBuilder; 7 | import springfox.documentation.builders.PathSelectors; 8 | import springfox.documentation.builders.RequestHandlerSelectors; 9 | import springfox.documentation.spi.DocumentationType; 10 | import springfox.documentation.spring.web.plugins.Docket; 11 | import springfox.documentation.swagger2.annotations.EnableSwagger2; 12 | 13 | /** 14 | * Knife4j 接口文档配置 15 | * https://doc.xiaominfo.com/knife4j/documentation/get_start.html 16 | * 17 | * @author 程序员鱼皮 18 | * @from 编程导航知识星球 19 | */ 20 | @Configuration 21 | @EnableSwagger2 22 | @Profile({"dev", "test"}) 23 | public class Knife4jConfig { 24 | 25 | @Bean 26 | public Docket defaultApi2() { 27 | return new Docket(DocumentationType.SWAGGER_2) 28 | .apiInfo(new ApiInfoBuilder() 29 | .title("接口文档") 30 | .description("gebi-backend") 31 | .version("1.0") 32 | .build()) 33 | .select() 34 | // 指定 Controller 扫描包路径 35 | .apis(RequestHandlerSelectors.basePackage("com.yupi.springbootinit.controller")) 36 | .paths(PathSelectors.any()) 37 | .build(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/enums/FileUploadBizEnum.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.enums; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.stream.Collectors; 6 | import org.apache.commons.lang3.ObjectUtils; 7 | 8 | /** 9 | * 文件上传业务类型枚举 10 | * 11 | * @author 程序员鱼皮 12 | * @from 编程导航知识星球 13 | */ 14 | public enum FileUploadBizEnum { 15 | 16 | USER_AVATAR("用户头像", "user_avatar"); 17 | 18 | private final String text; 19 | 20 | private final String value; 21 | 22 | FileUploadBizEnum(String text, String value) { 23 | this.text = text; 24 | this.value = value; 25 | } 26 | 27 | /** 28 | * 获取值列表 29 | * 30 | * @return 31 | */ 32 | public static List getValues() { 33 | return Arrays.stream(values()).map(item -> item.value).collect(Collectors.toList()); 34 | } 35 | 36 | /** 37 | * 根据 value 获取枚举 38 | * 39 | * @param value 40 | * @return 41 | */ 42 | public static FileUploadBizEnum getEnumByValue(String value) { 43 | if (ObjectUtils.isEmpty(value)) { 44 | return null; 45 | } 46 | for (FileUploadBizEnum anEnum : FileUploadBizEnum.values()) { 47 | if (anEnum.value.equals(value)) { 48 | return anEnum; 49 | } 50 | } 51 | return null; 52 | } 53 | 54 | public String getValue() { 55 | return value; 56 | } 57 | 58 | public String getText() { 59 | return text; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/model/enums/UserRoleEnum.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.model.enums; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.stream.Collectors; 6 | import org.apache.commons.lang3.ObjectUtils; 7 | 8 | /** 9 | * 用户角色枚举 10 | * 11 | * @author 程序员鱼皮 12 | * @from 编程导航知识星球 13 | */ 14 | public enum UserRoleEnum { 15 | 16 | USER("用户", "user"), 17 | ADMIN("管理员", "admin"), 18 | BAN("被封号", "ban"); 19 | 20 | private final String text; 21 | 22 | private final String value; 23 | 24 | UserRoleEnum(String text, String value) { 25 | this.text = text; 26 | this.value = value; 27 | } 28 | 29 | /** 30 | * 获取值列表 31 | * 32 | * @return 33 | */ 34 | public static List getValues() { 35 | return Arrays.stream(values()).map(item -> item.value).collect(Collectors.toList()); 36 | } 37 | 38 | /** 39 | * 根据 value 获取枚举 40 | * 41 | * @param value 42 | * @return 43 | */ 44 | public static UserRoleEnum getEnumByValue(String value) { 45 | if (ObjectUtils.isEmpty(value)) { 46 | return null; 47 | } 48 | for (UserRoleEnum anEnum : UserRoleEnum.values()) { 49 | if (anEnum.value.equals(value)) { 50 | return anEnum; 51 | } 52 | } 53 | return null; 54 | } 55 | 56 | public String getValue() { 57 | return value; 58 | } 59 | 60 | public String getText() { 61 | return text; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/config/WxOpenConfig.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.config; 2 | 3 | import lombok.Data; 4 | import lombok.extern.slf4j.Slf4j; 5 | import me.chanjar.weixin.mp.api.WxMpService; 6 | import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; 7 | import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl; 8 | import org.springframework.boot.context.properties.ConfigurationProperties; 9 | import org.springframework.context.annotation.Configuration; 10 | 11 | /** 12 | * 微信开放平台配置 13 | * 14 | * @author 程序员鱼皮 15 | * @from 编程导航知识星球 16 | */ 17 | @Slf4j 18 | @Configuration 19 | @ConfigurationProperties(prefix = "wx.open") 20 | @Data 21 | public class WxOpenConfig { 22 | 23 | private String appId; 24 | 25 | private String appSecret; 26 | 27 | private WxMpService wxMpService; 28 | 29 | /** 30 | * 单例模式(不用 @Bean 是为了防止和公众号的 service 冲突) 31 | * 32 | * @return 33 | */ 34 | public WxMpService getWxMpService() { 35 | if (wxMpService != null) { 36 | return wxMpService; 37 | } 38 | synchronized (this) { 39 | if (wxMpService != null) { 40 | return wxMpService; 41 | } 42 | WxMpDefaultConfigImpl config = new WxMpDefaultConfigImpl(); 43 | config.setAppId(appId); 44 | config.setSecret(appSecret); 45 | WxMpService service = new WxMpServiceImpl(); 46 | service.setWxMpConfigStorage(config); 47 | wxMpService = service; 48 | return wxMpService; 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/config/AliPayConfig.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.config; 2 | 3 | import com.alipay.api.AlipayApiException; 4 | import com.alipay.api.AlipayClient; 5 | import com.alipay.api.AlipayConfig; 6 | import com.alipay.api.DefaultAlipayClient; 7 | import lombok.Data; 8 | import org.springframework.boot.context.properties.ConfigurationProperties; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.Configuration; 11 | 12 | /** 13 | * 支付宝支付配置 14 | */ 15 | @Data 16 | @Configuration 17 | @ConfigurationProperties(prefix = "alipay") 18 | public class AliPayConfig { 19 | private String appId; 20 | private String appPrivateKey; 21 | private String alipayPublicKey; 22 | private static final String GATEWAY_URL = "https://openapi-sandbox.dl.alipaydev.com/gateway.do"; 23 | private static final String FORMAT = "JSON"; 24 | private static final String CHARSET = "UTF-8"; 25 | //签名方式 26 | private static final String SIGN_TYPE = "RSA2"; 27 | 28 | @Bean 29 | public AlipayClient alipayClient(){ 30 | AlipayConfig alipayConfig = new AlipayConfig(); 31 | alipayConfig.setServerUrl(GATEWAY_URL); 32 | alipayConfig.setAppId(appId); 33 | alipayConfig.setPrivateKey(appPrivateKey); 34 | alipayConfig.setFormat("json"); 35 | alipayConfig.setCharset(CHARSET); 36 | alipayConfig.setAlipayPublicKey(alipayPublicKey); 37 | alipayConfig.setSignType(SIGN_TYPE); 38 | try { 39 | return new DefaultAlipayClient(alipayConfig); 40 | } catch (AlipayApiException e) { 41 | throw new RuntimeException(e); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/resources/mapper/ChartMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | id,`name`,goal,chartData, 25 | chatType,genChat,genResult, 26 | userId,`status`,execMessage,createTime,updateTime, 27 | isDelete 28 | 29 | 32 | 33 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/utils/SpringContextUtils.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.utils; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | import org.springframework.beans.BeansException; 5 | import org.springframework.context.ApplicationContext; 6 | import org.springframework.context.ApplicationContextAware; 7 | import org.springframework.stereotype.Component; 8 | 9 | /** 10 | * Spring 上下文获取工具 11 | * 12 | * @author 程序员鱼皮 13 | * @from 编程导航知识星球 14 | */ 15 | @Component 16 | public class SpringContextUtils implements ApplicationContextAware { 17 | 18 | private static ApplicationContext applicationContext; 19 | 20 | @Override 21 | public void setApplicationContext(@NotNull ApplicationContext applicationContext) throws BeansException { 22 | SpringContextUtils.applicationContext = applicationContext; 23 | } 24 | 25 | /** 26 | * 通过名称获取 Bean 27 | * 28 | * @param beanName 29 | * @return 30 | */ 31 | public static Object getBean(String beanName) { 32 | return applicationContext.getBean(beanName); 33 | } 34 | 35 | /** 36 | * 通过 class 获取 Bean 37 | * 38 | * @param beanClass 39 | * @param 40 | * @return 41 | */ 42 | public static T getBean(Class beanClass) { 43 | return applicationContext.getBean(beanClass); 44 | } 45 | 46 | /** 47 | * 通过名称和类型获取 Bean 48 | * 49 | * @param beanName 50 | * @param beanClass 51 | * @param 52 | * @return 53 | */ 54 | public static T getBean(String beanName, Class beanClass) { 55 | return applicationContext.getBean(beanName, beanClass); 56 | } 57 | } -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/utils/NetUtils.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.utils; 2 | 3 | import java.net.InetAddress; 4 | import javax.servlet.http.HttpServletRequest; 5 | 6 | /** 7 | * 网络工具类 8 | * 9 | * @author 程序员鱼皮 10 | * @from 编程导航知识星球 11 | */ 12 | public class NetUtils { 13 | 14 | /** 15 | * 获取客户端 IP 地址 16 | * 17 | * @param request 18 | * @return 19 | */ 20 | public static String getIpAddress(HttpServletRequest request) { 21 | String ip = request.getHeader("x-forwarded-for"); 22 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 23 | ip = request.getHeader("Proxy-Client-IP"); 24 | } 25 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 26 | ip = request.getHeader("WL-Proxy-Client-IP"); 27 | } 28 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 29 | ip = request.getRemoteAddr(); 30 | if (ip.equals("127.0.0.1")) { 31 | // 根据网卡取本机配置的 IP 32 | InetAddress inet = null; 33 | try { 34 | inet = InetAddress.getLocalHost(); 35 | } catch (Exception e) { 36 | e.printStackTrace(); 37 | } 38 | if (inet != null) { 39 | ip = inet.getHostAddress(); 40 | } 41 | } 42 | } 43 | // 多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割 44 | if (ip != null && ip.length() > 15) { 45 | if (ip.indexOf(",") > 0) { 46 | ip = ip.substring(0, ip.indexOf(",")); 47 | } 48 | } 49 | if (ip == null) { 50 | return "127.0.0.1"; 51 | } 52 | return ip; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/mq/Bi/BiMqInitMain.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.mq.Bi; 2 | 3 | import com.yupi.springbootinit.constant.MqConstant; 4 | import org.springframework.amqp.core.*; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | /** 12 | * 用于创建程序的交换机和队列 13 | */ 14 | @Configuration 15 | public class BiMqInitMain { 16 | 17 | /** 18 | * 将死信队列和交换机声明 19 | */ 20 | @Bean 21 | Queue BiDeadQueue(){ 22 | return QueueBuilder.durable(MqConstant.BI_DEAD_QUEUE_NAME).build(); 23 | } 24 | 25 | @Bean 26 | DirectExchange BiDeadExchange() { 27 | return new DirectExchange(MqConstant.BI_DEAD_EXCHANGE_NAME); 28 | } 29 | 30 | 31 | @Bean 32 | Binding BiDeadBinding(Queue BiDeadQueue, DirectExchange BiDeadExchange) { 33 | return BindingBuilder.bind(BiDeadQueue).to(BiDeadExchange).with(MqConstant.BI_DEAD_ROUTING_KEY); 34 | } 35 | 36 | /** 37 | * 将队列和交换机声明 38 | */ 39 | @Bean 40 | Queue BiQueue(){ 41 | //信息参数 设置TTL为1min 42 | Map arg = new HashMap<>(); 43 | arg.put("x-message-ttl",60000); 44 | //绑定死信交换机 45 | arg.put("x-dead-letter-exchange",MqConstant.BI_DEAD_EXCHANGE_NAME); 46 | arg.put("x-dead-letter-routing-key",MqConstant.BI_DEAD_ROUTING_KEY); 47 | return QueueBuilder.durable(MqConstant.BI_QUEUE_NAME).withArguments(arg).build(); 48 | } 49 | 50 | @Bean 51 | DirectExchange BiExchange() { 52 | return new DirectExchange(MqConstant.BI_EXCHANGE_NAME); 53 | } 54 | 55 | @Bean 56 | Binding BiBinding(Queue BiQueue, DirectExchange BiExchange) { 57 | return BindingBuilder.bind(BiQueue).to(BiExchange).with(MqConstant.BI_ROUTING_KEY); 58 | } 59 | 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/test/java/com/yupi/springbootinit/manager/AiManagerTestMarkDown.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.manager; 2 | 3 | import com.yupi.yucongming.dev.client.YuCongMingClient; 4 | import com.yupi.yucongming.dev.common.BaseResponse; 5 | import com.yupi.yucongming.dev.model.DevChatRequest; 6 | import com.yupi.yucongming.dev.model.DevChatResponse; 7 | 8 | public class AiManagerTestMarkDown { 9 | 10 | public static void main(String[] args) { 11 | String accessKey = "ux7bpq5mqr8db3n0dfhd46bunkebr8f3"; 12 | String secretKey = "eg6zsakkz0av0f6jae3g3cw163nw56hc"; 13 | YuCongMingClient yuCongMingClient = new YuCongMingClient(accessKey, secretKey); 14 | DevChatRequest devChatRequest = new DevChatRequest(); 15 | devChatRequest.setModelId(1666258198769700865L); 16 | 17 | String dataText =" log.warn(\\\"订单未支付成功,重新放回队列,订单号为\\\"+order.getId()); channel.basicNack(deliveryTag,false,true); }else { //消息确认 channel.basicAck(deliveryTag,false); } }注意rabbitmq的重发机制不能在try-catch中使用,否则会不生效,因为catch也会算一次确定消息。"; 18 | System.out.println(dataText.length()); 19 | String trim = dataText.trim(); 20 | // String replace = trim.replaceAll("\\s*|\r|\n|\t", ""); 21 | // replace="请使用markdown语法对下面文章格式化,并生成markdown语法"+"\n"+replace; 22 | // System.out.println(replace); 23 | trim="请使用markdown语法对下面文章格式化,并生成markdown语法"+"\n"+trim; 24 | devChatRequest.setMessage(trim); 25 | BaseResponse devChatResponseBaseResponse = yuCongMingClient.doChat(devChatRequest); 26 | System.out.println(devChatResponseBaseResponse); 27 | DevChatResponse data = (DevChatResponse)devChatResponseBaseResponse.getData(); 28 | if (data != null) { 29 | String content = data.getContent(); 30 | System.out.println(content); 31 | } 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/mq/Text/TextMqInitMain.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.mq.Text; 2 | 3 | import com.yupi.springbootinit.constant.MqConstant; 4 | import org.springframework.amqp.core.*; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | /** 12 | * 用于创建程序的交换机和队列 13 | */ 14 | @Configuration 15 | public class TextMqInitMain { 16 | 17 | /** 18 | * 将死信队列和交换机声明 19 | */ 20 | @Bean 21 | Queue TxtDeadQueue(){ 22 | return QueueBuilder.durable(MqConstant.TEXT_DEAD_QUEUE_NAME).build(); 23 | } 24 | 25 | @Bean 26 | DirectExchange TxtDeadExchange() { 27 | return new DirectExchange(MqConstant.TEXT_DEAD_EXCHANGE_NAME); 28 | } 29 | 30 | 31 | @Bean 32 | Binding TxtDeadBinding(Queue TxtDeadQueue, DirectExchange TxtDeadExchange) { 33 | return BindingBuilder.bind(TxtDeadQueue).to(TxtDeadExchange).with(MqConstant.TEXT_DEAD_ROUTING_KEY); 34 | } 35 | 36 | /** 37 | * 将队列和交换机声明 38 | */ 39 | @Bean 40 | Queue TxtQueue(){ 41 | //信息参数 设置TTL为1min 42 | Map arg = new HashMap<>(); 43 | arg.put("x-message-ttl",60000); 44 | //绑定死信交换机 45 | arg.put("x-dead-letter-exchange",MqConstant.TEXT_DEAD_EXCHANGE_NAME); 46 | arg.put("x-dead-letter-routing-key",MqConstant.TEXT_DEAD_ROUTING_KEY); 47 | return QueueBuilder.durable(MqConstant.TEXT_QUEUE_NAME).withArguments(arg).build(); 48 | } 49 | 50 | @Bean 51 | DirectExchange TxtExchange() { 52 | return new DirectExchange(MqConstant.TEXT_EXCHANGE_NAME); 53 | } 54 | 55 | @Bean 56 | Binding TxtBinding(Queue TxtQueue, DirectExchange TxtExchange) { 57 | return BindingBuilder.bind(TxtQueue).to(TxtExchange).with(MqConstant.TEXT_ROUTING_KEY); 58 | } 59 | 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/mq/Alipay/AlipayMqInitMain.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.mq.Alipay; 2 | 3 | import com.yupi.springbootinit.constant.MqConstant; 4 | import org.springframework.amqp.core.*; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | /** 12 | * 用于创建订单程序的交换机和队列 13 | */ 14 | @Configuration 15 | public class AlipayMqInitMain { 16 | 17 | /** 18 | * 将死信队列和交换机声明 19 | */ 20 | @Bean 21 | Queue AliPayDeadQueue(){ 22 | return QueueBuilder.durable(MqConstant.ORDERS_DEAD_QUEUE_NAME).build(); 23 | } 24 | 25 | @Bean 26 | DirectExchange AliPayDeadExchange() { 27 | return new DirectExchange(MqConstant.ORDERS_DEAD_EXCHANGE_NAME); 28 | } 29 | 30 | 31 | @Bean 32 | Binding AliPayDeadBinding(Queue AliPayDeadQueue, DirectExchange AliPayDeadExchange) { 33 | return BindingBuilder.bind(AliPayDeadQueue).to(AliPayDeadExchange).with(MqConstant.ORDERS_DEAD_ROUTING_KEY); 34 | } 35 | 36 | /** 37 | * 将队列和交换机声明 38 | */ 39 | @Bean 40 | Queue AliPayQueue(){ 41 | //信息参数 设置TTL为1min 42 | Map arg = new HashMap<>(); 43 | arg.put("x-message-ttl",1000*60); 44 | //绑定死信交换机 45 | arg.put("x-dead-letter-exchange",MqConstant.ORDERS_DEAD_EXCHANGE_NAME); 46 | arg.put("x-dead-letter-routing-key",MqConstant.ORDERS_DEAD_ROUTING_KEY); 47 | return QueueBuilder.durable(MqConstant.ORDERS_QUEUE_NAME).withArguments(arg).build(); 48 | } 49 | 50 | @Bean 51 | DirectExchange AliPayExchange() { 52 | return new DirectExchange(MqConstant.ORDERS_EXCHANGE_NAME); 53 | } 54 | 55 | @Bean 56 | Binding AliPayBinding(Queue AliPayQueue, DirectExchange AliPayExchange) { 57 | return BindingBuilder.bind(AliPayQueue).to(AliPayExchange).with(MqConstant.ORDERS_ROUTING_KEY); 58 | } 59 | 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/utils/TxtUtils.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.utils; 2 | 3 | import com.alibaba.excel.util.FileUtils; 4 | import org.apache.tomcat.util.http.fileupload.disk.DiskFileItem; 5 | import org.springframework.http.MediaType; 6 | import org.springframework.util.ResourceUtils; 7 | import org.springframework.web.multipart.MultipartFile; 8 | import org.springframework.web.multipart.commons.CommonsMultipartFile; 9 | 10 | import java.io.*; 11 | import java.util.ArrayList; 12 | 13 | /** 14 | * 读取文本工具类 15 | */ 16 | public class TxtUtils { 17 | public static void main(String[] args) { 18 | try { 19 | File file = ResourceUtils.getFile("classpath:笔记.txt"); 20 | 21 | } catch (FileNotFoundException e) { 22 | throw new RuntimeException(e); 23 | } 24 | } 25 | public static ArrayList readerFile(MultipartFile file) { 26 | ArrayList list= new ArrayList<>(); 27 | try { 28 | // 获取文件内容 29 | BufferedReader reader = new BufferedReader(new InputStreamReader(file.getInputStream())); 30 | String line; 31 | StringBuilder builder = new StringBuilder(); 32 | 33 | while ((line = reader.readLine()) != null) { 34 | // 处理文件内容,例如输出到控制台 35 | if (builder.length()+line.length()<920){ 36 | builder.append(line); 37 | }else { 38 | //保存数据库 39 | list.add(builder.toString()); 40 | builder.delete(0,builder.length()); 41 | } 42 | //保证数据不丢失 43 | if (builder.length()==0){ 44 | builder.append(line); 45 | } 46 | } 47 | //数据可能不超过990 48 | list.add(builder.toString()); 49 | reader.close(); 50 | } catch (IOException e) { 51 | e.printStackTrace(); 52 | } 53 | return list; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/wxmp/WxMpMsgRouter.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.wxmp; 2 | 3 | import com.yupi.springbootinit.wxmp.handler.EventHandler; 4 | import com.yupi.springbootinit.wxmp.handler.MessageHandler; 5 | import com.yupi.springbootinit.wxmp.handler.SubscribeHandler; 6 | import javax.annotation.Resource; 7 | import me.chanjar.weixin.common.api.WxConsts.EventType; 8 | import me.chanjar.weixin.common.api.WxConsts.XmlMsgType; 9 | import me.chanjar.weixin.mp.api.WxMpMessageRouter; 10 | import me.chanjar.weixin.mp.api.WxMpService; 11 | import org.springframework.context.annotation.Bean; 12 | import org.springframework.context.annotation.Configuration; 13 | 14 | /** 15 | * 微信公众号路由 16 | * 17 | * @author 程序员鱼皮 18 | * @from 编程导航知识星球 19 | */ 20 | @Configuration 21 | public class WxMpMsgRouter { 22 | 23 | @Resource 24 | private WxMpService wxMpService; 25 | 26 | @Resource 27 | private EventHandler eventHandler; 28 | 29 | @Resource 30 | private MessageHandler messageHandler; 31 | 32 | @Resource 33 | private SubscribeHandler subscribeHandler; 34 | 35 | @Bean 36 | public WxMpMessageRouter getWxMsgRouter() { 37 | WxMpMessageRouter router = new WxMpMessageRouter(wxMpService); 38 | // 消息 39 | router.rule() 40 | .async(false) 41 | .msgType(XmlMsgType.TEXT) 42 | .handler(messageHandler) 43 | .end(); 44 | // 关注 45 | router.rule() 46 | .async(false) 47 | .msgType(XmlMsgType.EVENT) 48 | .event(EventType.SUBSCRIBE) 49 | .handler(subscribeHandler) 50 | .end(); 51 | // 点击按钮 52 | router.rule() 53 | .async(false) 54 | .msgType(XmlMsgType.EVENT) 55 | .event(EventType.CLICK) 56 | .eventKey(WxMpConstant.CLICK_MENU_KEY) 57 | .handler(eventHandler) 58 | .end(); 59 | return router; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/controller/QueueController.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.controller; 2 | 3 | 4 | import cn.hutool.json.JSONUtil; 5 | import com.yupi.springbootinit.common.ErrorCode; 6 | import com.yupi.springbootinit.config.ThreadPoolExecutorConfig; 7 | import com.yupi.springbootinit.exception.BusinessException; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.context.annotation.Profile; 10 | import org.springframework.web.bind.annotation.GetMapping; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | import javax.annotation.Resource; 15 | import java.util.HashMap; 16 | import java.util.Map; 17 | import java.util.concurrent.CompletableFuture; 18 | import java.util.concurrent.ThreadPoolExecutor; 19 | 20 | /** 21 | * 查看线程池资源类(测试环境) 22 | */ 23 | @RestController 24 | @RequestMapping("/queue") 25 | @Slf4j 26 | @Profile({"dev","local"}) 27 | public class QueueController { 28 | 29 | @Resource 30 | ThreadPoolExecutor threadPoolExecutor; 31 | 32 | @GetMapping("/add") 33 | public void add(String name){ 34 | try { 35 | CompletableFuture.runAsync(()->{ 36 | System.out.println("任务执行中"+name); 37 | try { 38 | Thread.sleep(60000); 39 | } catch (InterruptedException e) { 40 | throw new RuntimeException(e); 41 | } 42 | },threadPoolExecutor); 43 | } catch (Exception e) { 44 | throw new BusinessException(ErrorCode.SYSTEM_ERROR,"系统繁忙,请稍后重试"); 45 | } 46 | } 47 | 48 | @GetMapping("/get") 49 | public String get(){ 50 | Map map = new HashMap<>(); 51 | int size = threadPoolExecutor.getQueue().size(); 52 | map.put("队列长度",size); 53 | long taskCount = threadPoolExecutor.getTaskCount(); 54 | map.put("任务总数",taskCount); 55 | long completedTaskCount = threadPoolExecutor.getCompletedTaskCount(); 56 | map.put("已经完成任务数",completedTaskCount); 57 | int activeCount = threadPoolExecutor.getActiveCount(); 58 | map.put("正在工作的线程数",activeCount); 59 | return JSONUtil.toJsonStr(map); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/aop/LogInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.aop; 2 | 3 | import java.util.UUID; 4 | import javax.servlet.http.HttpServletRequest; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.apache.commons.lang3.StringUtils; 7 | import org.aspectj.lang.ProceedingJoinPoint; 8 | import org.aspectj.lang.annotation.Around; 9 | import org.aspectj.lang.annotation.Aspect; 10 | import org.springframework.stereotype.Component; 11 | import org.springframework.util.StopWatch; 12 | import org.springframework.web.context.request.RequestAttributes; 13 | import org.springframework.web.context.request.RequestContextHolder; 14 | import org.springframework.web.context.request.ServletRequestAttributes; 15 | 16 | /** 17 | * 请求响应日志 AOP 18 | * 19 | * @author 程序员鱼皮 20 | * @from 编程导航知识星球 21 | **/ 22 | @Aspect 23 | @Component 24 | @Slf4j 25 | public class LogInterceptor { 26 | 27 | /** 28 | * 执行拦截 29 | */ 30 | @Around("execution(* com.yupi.springbootinit.controller.*.*(..))") 31 | public Object doInterceptor(ProceedingJoinPoint point) throws Throwable { 32 | // 计时 33 | StopWatch stopWatch = new StopWatch(); 34 | stopWatch.start(); 35 | // 获取请求路径 36 | RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes(); 37 | HttpServletRequest httpServletRequest = ((ServletRequestAttributes) requestAttributes).getRequest(); 38 | // 生成请求唯一 id 39 | String requestId = UUID.randomUUID().toString(); 40 | String url = httpServletRequest.getRequestURI(); 41 | // 获取请求参数 42 | Object[] args = point.getArgs(); 43 | String reqParam = "[" + StringUtils.join(args, ", ") + "]"; 44 | // 输出请求日志 45 | log.info("request start,id: {}, path: {}, ip: {}, params: {}", requestId, url, 46 | httpServletRequest.getRemoteHost(), reqParam); 47 | // 执行原方法 48 | Object result = point.proceed(); 49 | // 输出响应日志 50 | stopWatch.stop(); 51 | long totalTimeMillis = stopWatch.getTotalTimeMillis(); 52 | log.info("request end, id: {}, cost: {}ms", requestId, totalTimeMillis); 53 | return result; 54 | } 55 | } 56 | 57 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/utils/ExcelUtils.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.utils; 2 | 3 | import cn.hutool.core.collection.CollUtil; 4 | import com.alibaba.excel.EasyExcel; 5 | import com.alibaba.excel.support.ExcelTypeEnum; 6 | import com.yupi.springbootinit.common.ErrorCode; 7 | import com.yupi.springbootinit.exception.BusinessException; 8 | import io.swagger.models.auth.In; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.apache.commons.lang3.ObjectUtils; 11 | import org.apache.commons.lang3.StringUtils; 12 | import org.springframework.util.ResourceUtils; 13 | import org.springframework.web.multipart.MultipartFile; 14 | 15 | import java.io.File; 16 | import java.io.FileNotFoundException; 17 | import java.io.IOException; 18 | import java.util.LinkedHashMap; 19 | import java.util.List; 20 | import java.util.Map; 21 | import java.util.stream.Collectors; 22 | 23 | /** 24 | * excel数据读取工具栏 25 | */ 26 | @Slf4j 27 | public class ExcelUtils { 28 | 29 | public static String excelToCsv(MultipartFile multipartFile) { 30 | List> list = null; 31 | try { 32 | list = EasyExcel.read(multipartFile.getInputStream()) 33 | .excelType(ExcelTypeEnum.XLSX) 34 | .sheet() 35 | .headRowNumber(0) 36 | .doReadSync(); 37 | } catch (IOException e) { 38 | log.error("表格转换错误"); 39 | } 40 | 41 | if (CollUtil.isEmpty(list)){ 42 | return ""; 43 | } 44 | //转cvs 45 | StringBuilder stringBuilder = new StringBuilder(); 46 | //读取表头 47 | LinkedHashMap headerMap = (LinkedHashMap) list.get(0); 48 | List headerList = headerMap.values().stream().filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()); 49 | stringBuilder.append(StringUtils.join(headerList,",")).append("\n"); 50 | 51 | //读数据 52 | for (int i = 1; i < list.size(); i++) { 53 | Map dataMap = list.get(i); 54 | List dataList = dataMap.values().stream().filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()); 55 | stringBuilder.append(StringUtils.join(dataList,",")).append("\n"); 56 | } 57 | return stringBuilder.toString(); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/mq/Alipay/AlipayMessageConsumer.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.mq.Alipay; 2 | 3 | import com.rabbitmq.client.Channel; 4 | import com.yupi.springbootinit.common.ErrorCode; 5 | import com.yupi.springbootinit.constant.OrdersConstant; 6 | import com.yupi.springbootinit.constant.MqConstant; 7 | import com.yupi.springbootinit.exception.BusinessException; 8 | import com.yupi.springbootinit.model.entity.Orders; 9 | 10 | import com.yupi.springbootinit.service.OrdersService; 11 | 12 | import lombok.SneakyThrows; 13 | import lombok.extern.slf4j.Slf4j; 14 | import org.apache.commons.lang3.StringUtils; 15 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 16 | import org.springframework.amqp.support.AmqpHeaders; 17 | import org.springframework.messaging.handler.annotation.Header; 18 | import org.springframework.stereotype.Component; 19 | 20 | import javax.annotation.Resource; 21 | 22 | /** 23 | * 阿里支付队列消费者 24 | */ 25 | @Component 26 | @Slf4j 27 | public class AlipayMessageConsumer { 28 | 29 | 30 | @Resource 31 | OrdersService ordersService; 32 | 33 | @SneakyThrows 34 | @RabbitListener(queues = {MqConstant.ORDERS_QUEUE_NAME}) 35 | public void receiveMessage(String message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag){ 36 | log.warn("接收到队列信息,receiveMessage={}=======================================",message); 37 | if (StringUtils.isBlank(message)){ 38 | //消息为空,消息拒绝,不重复发送,不重新放入队列 39 | channel.basicNack(deliveryTag,false,false); 40 | throw new BusinessException(ErrorCode.SYSTEM_ERROR,"消息为空"); 41 | } 42 | long orderId = Long.parseLong(message); 43 | Orders order = ordersService.getById(orderId); 44 | if (order == null){ 45 | channel.basicNack(deliveryTag,false,false); 46 | throw new BusinessException(ErrorCode.SYSTEM_ERROR,"订单为空"); 47 | } 48 | //查询订单信息看是完成支付,未支付则重新放入队列中直至过期 49 | String tradeStatus = order.getTradeStatus(); 50 | log.warn("订单查询为"+order.getTradeStatus()); 51 | if (!tradeStatus.equals(OrdersConstant.SUCCEED)){ 52 | log.warn("订单未支付成功,重新放回队列,订单号为"+order.getId()); 53 | channel.basicNack(deliveryTag,false,true); 54 | }else { 55 | //消息确认 56 | channel.basicAck(deliveryTag,false); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/test/java/com/yupi/springbootinit/manager/AiManagerTest.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.manager; 2 | 3 | import cn.hutool.json.JSONUtil; 4 | import com.yupi.springbootinit.common.ErrorCode; 5 | import com.yupi.springbootinit.exception.BusinessException; 6 | import org.junit.jupiter.api.Test; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | 9 | import javax.annotation.Resource; 10 | 11 | import java.util.HashMap; 12 | 13 | @SpringBootTest 14 | class AiManagerTest { 15 | 16 | @Resource 17 | private AiManager aiManager; 18 | 19 | @Test 20 | void doChat() { 21 | String input ="分析需求:\n" + 22 | "分析网站人数增长情况,请使用折线图\n" + 23 | "原始数据:\n" + 24 | "日期,用户数\n" + 25 | "1号,10\n" + 26 | "2号,20\n" + 27 | "3号,30\n" + 28 | "4号,0\n" + 29 | "5号,130\n" + 30 | "6号,230\n" + 31 | "7号,20\n" + 32 | "8号,30\n"+ 33 | "9号,20\n" + 34 | "10号,30\n"; 35 | 36 | String chat = aiManager.doChat(input, 1659171950288818178L); 37 | System.out.println(chat); 38 | // String[] splits = chat.split("【【【【【"); 39 | // if (splits.length < 3){ 40 | // throw new BusinessException(ErrorCode.SYSTEM_ERROR,"AI 生成错误"); 41 | // } 42 | // //todo 可以使用正则表达式保证数据准确性,防止中文出现 43 | // String genChart= splits[1].trim(); 44 | // String genResult = splits[2].trim(); 45 | // System.out.println("genChart: "+genChart); 46 | // System.out.println("genResult: "+genResult); 47 | } 48 | 49 | public static void main(String[] args) { 50 | //将非Json格式转化为json格式 51 | String res = "这个分析数据的图片代码" + 52 | "" + 53 | "{\n" + 54 | " xAxis: {\n" + 55 | " type: 'category',\n" + 56 | " data: ['1号', '2号', '3号', '4号', '5号', '6号', '7号', '8号']\n" + 57 | " },\n" + 58 | " yAxis: {\n" + 59 | " type: 'value'\n" + 60 | " },\n" + 61 | " series: [{\n" + 62 | " data: [10, 20, 30, 0, 130, 230, 20, 30],\n" + 63 | " type: 'line'\n" + 64 | " }]\n" + 65 | "}"; 66 | HashMap map1 = JSONUtil.toBean(res, HashMap.class); 67 | String toJsonStr = JSONUtil.toJsonStr(map1); 68 | System.out.println("str: "+toJsonStr); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/mq/Text/TextMessageDeadConsumer.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.mq.Text; 2 | 3 | import com.rabbitmq.client.Channel; 4 | import com.yupi.springbootinit.common.ErrorCode; 5 | import com.yupi.springbootinit.constant.MqConstant; 6 | import com.yupi.springbootinit.constant.TextConstant; 7 | import com.yupi.springbootinit.exception.BusinessException; 8 | import com.yupi.springbootinit.model.entity.TextTask; 9 | import com.yupi.springbootinit.service.TextTaskService; 10 | import lombok.SneakyThrows; 11 | import lombok.extern.slf4j.Slf4j; 12 | import org.apache.commons.lang3.StringUtils; 13 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 14 | import org.springframework.amqp.support.AmqpHeaders; 15 | import org.springframework.messaging.handler.annotation.Header; 16 | import org.springframework.stereotype.Component; 17 | 18 | import javax.annotation.Resource; 19 | 20 | /** 21 | * 文本转换队列的死信队列 22 | */ 23 | @Component 24 | @Slf4j 25 | public class TextMessageDeadConsumer { 26 | 27 | @Resource 28 | private TextTaskService textTaskService; 29 | 30 | 31 | @SneakyThrows 32 | @RabbitListener(queues = {MqConstant.TEXT_DEAD_QUEUE_NAME},ackMode = "MANUAL") 33 | public void receiveMessage(String message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag){ 34 | log.warn("接收到死信队列信息,receiveMessage={}=======================================",message); 35 | if (StringUtils.isBlank(message)){ 36 | //消息为空,消息拒绝,不重复发送,不重新放入队列 37 | channel.basicNack(deliveryTag,false,false); 38 | throw new BusinessException(ErrorCode.SYSTEM_ERROR,"消息为空"); 39 | } 40 | long textTaskId = Long.parseLong(message); 41 | TextTask textTask = textTaskService.getById(textTaskId); 42 | if (textTask == null){ 43 | channel.basicNack(deliveryTag,false,false); 44 | throw new BusinessException(ErrorCode.SYSTEM_ERROR,"文本为空"); 45 | } 46 | 47 | //修改表状态为执行中,执行成功修改为“已完成”;执行失败修改为“失败” 48 | TextTask updateTextTask = new TextTask(); 49 | updateTextTask.setId(textTask.getId()); 50 | updateTextTask.setStatus(TextConstant.FAILED); 51 | boolean updateResult = textTaskService.updateById(updateTextTask); 52 | //这里不对记录表状态修改,记录只能内部使用 53 | if (!updateResult){ 54 | textTaskService.handleTextTaskUpdateError(updateTextTask.getId(),"更新图表执行状态失败"); 55 | return; 56 | } 57 | //消息确认 58 | channel.basicAck(deliveryTag,false); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/aop/AuthInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.aop; 2 | 3 | import com.yupi.springbootinit.annotation.AuthCheck; 4 | import com.yupi.springbootinit.common.ErrorCode; 5 | import com.yupi.springbootinit.exception.BusinessException; 6 | import com.yupi.springbootinit.model.entity.User; 7 | import com.yupi.springbootinit.model.enums.UserRoleEnum; 8 | import com.yupi.springbootinit.service.UserService; 9 | import javax.annotation.Resource; 10 | import javax.servlet.http.HttpServletRequest; 11 | import org.apache.commons.lang3.StringUtils; 12 | import org.aspectj.lang.ProceedingJoinPoint; 13 | import org.aspectj.lang.annotation.Around; 14 | import org.aspectj.lang.annotation.Aspect; 15 | import org.springframework.stereotype.Component; 16 | import org.springframework.web.context.request.RequestAttributes; 17 | import org.springframework.web.context.request.RequestContextHolder; 18 | import org.springframework.web.context.request.ServletRequestAttributes; 19 | 20 | /** 21 | * 权限校验 AOP 22 | * 23 | * @author 程序员鱼皮 24 | * @from 编程导航知识星球 25 | */ 26 | @Aspect 27 | @Component 28 | public class AuthInterceptor { 29 | 30 | @Resource 31 | private UserService userService; 32 | 33 | /** 34 | * 执行拦截 35 | * 36 | * @param joinPoint 37 | * @param authCheck 38 | * @return 39 | */ 40 | @Around("@annotation(authCheck)") 41 | public Object doInterceptor(ProceedingJoinPoint joinPoint, AuthCheck authCheck) throws Throwable { 42 | String mustRole = authCheck.mustRole(); 43 | RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes(); 44 | HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest(); 45 | // 当前登录用户 46 | User loginUser = userService.getLoginUser(request); 47 | // 必须有该权限才通过 48 | if (StringUtils.isNotBlank(mustRole)) { 49 | UserRoleEnum mustUserRoleEnum = UserRoleEnum.getEnumByValue(mustRole); 50 | if (mustUserRoleEnum == null) { 51 | throw new BusinessException(ErrorCode.NO_AUTH_ERROR); 52 | } 53 | String userRole = loginUser.getUserRole(); 54 | // 如果被封号,直接拒绝 55 | if (UserRoleEnum.BAN.equals(mustUserRoleEnum)) { 56 | throw new BusinessException(ErrorCode.NO_AUTH_ERROR); 57 | } 58 | // 必须有管理员权限 59 | if (UserRoleEnum.ADMIN.equals(mustUserRoleEnum)) { 60 | if (!mustRole.equals(userRole)) { 61 | throw new BusinessException(ErrorCode.NO_AUTH_ERROR); 62 | } 63 | } 64 | } 65 | // 通过权限校验,放行 66 | return joinPoint.proceed(); 67 | } 68 | } 69 | 70 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/mq/Alipay/AlipayMessageDeadConsumer.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.mq.Alipay; 2 | 3 | import com.rabbitmq.client.Channel; 4 | import com.yupi.springbootinit.common.ErrorCode; 5 | import com.yupi.springbootinit.constant.OrdersConstant; 6 | import com.yupi.springbootinit.constant.MqConstant; 7 | import com.yupi.springbootinit.exception.BusinessException; 8 | import com.yupi.springbootinit.model.entity.Orders; 9 | import com.yupi.springbootinit.service.OrdersService; 10 | import lombok.SneakyThrows; 11 | import lombok.extern.slf4j.Slf4j; 12 | import org.apache.commons.lang3.StringUtils; 13 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 14 | import org.springframework.amqp.support.AmqpHeaders; 15 | import org.springframework.messaging.handler.annotation.Header; 16 | import org.springframework.stereotype.Component; 17 | 18 | import javax.annotation.Resource; 19 | 20 | /** 21 | * 阿里支付队列的死信队列 22 | */ 23 | @Component 24 | @Slf4j 25 | public class AlipayMessageDeadConsumer { 26 | 27 | @Resource 28 | private OrdersService ordersService; 29 | 30 | 31 | @SneakyThrows 32 | @RabbitListener(queues = {MqConstant.ORDERS_DEAD_QUEUE_NAME}) 33 | public void receiveMessage(String message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag){ 34 | log.warn("接收到死信队列信息,receiveMessage={}=======================================",message); 35 | if (StringUtils.isBlank(message)){ 36 | //消息为空,消息拒绝,不重复发送,不重新放入队列 37 | channel.basicNack(deliveryTag,false,false); 38 | throw new BusinessException(ErrorCode.SYSTEM_ERROR,"消息为空"); 39 | } 40 | long ordersId = Long.parseLong(message); 41 | Orders orders = ordersService.getById(ordersId); 42 | if (orders == null){ 43 | channel.basicNack(deliveryTag,false,false); 44 | throw new BusinessException(ErrorCode.SYSTEM_ERROR,"订单为空"); 45 | } 46 | 47 | //修改表状态为执行中,执行成功修改为“已完成”;执行失败修改为“失败” 48 | Orders updateOrders = new Orders(); 49 | updateOrders.setId(orders.getId()); 50 | updateOrders.setTradeStatus(OrdersConstant.FAILED); 51 | boolean updateResult = ordersService.updateById(updateOrders); 52 | if (!updateResult){ 53 | handleOrdersUpdateError(orders.getId(),"更新订单执行状态失败"); 54 | return; 55 | } 56 | //消息确认 57 | channel.basicAck(deliveryTag,false); 58 | } 59 | private void handleOrdersUpdateError(Long ordersId, String execMessage) { 60 | Orders updateOrdersResult = new Orders(); 61 | updateOrdersResult.setTradeStatus(OrdersConstant.FAILED); 62 | updateOrdersResult.setId(ordersId); 63 | boolean updateResult = ordersService.updateById(updateOrdersResult); 64 | if (!updateResult){ 65 | log.error("更新订单失败状态失败"+ordersId+","+execMessage); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/mq/Bi/BiMessageDeadConsumer.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.mq.Bi; 2 | 3 | import com.rabbitmq.client.Channel; 4 | import com.yupi.springbootinit.common.ErrorCode; 5 | import com.yupi.springbootinit.constant.ChartConstant; 6 | import com.yupi.springbootinit.constant.MqConstant; 7 | import com.yupi.springbootinit.exception.BusinessException; 8 | import com.yupi.springbootinit.model.entity.Chart; 9 | import com.yupi.springbootinit.service.ChartService; 10 | import lombok.SneakyThrows; 11 | import lombok.extern.slf4j.Slf4j; 12 | import org.apache.commons.lang3.StringUtils; 13 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 14 | import org.springframework.amqp.support.AmqpHeaders; 15 | import org.springframework.messaging.handler.annotation.Header; 16 | import org.springframework.stereotype.Component; 17 | 18 | import javax.annotation.Resource; 19 | 20 | /** 21 | * 图表分析队列的死信队列 22 | */ 23 | @Component 24 | @Slf4j 25 | public class BiMessageDeadConsumer { 26 | 27 | @Resource 28 | private ChartService chartService; 29 | 30 | 31 | @SneakyThrows 32 | @RabbitListener(queues = {MqConstant.BI_DEAD_QUEUE_NAME},ackMode = "MANUAL") 33 | public void receiveMessage(String message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag){ 34 | log.warn("接收到死信队列信息,receiveMessage={}=======================================",message); 35 | if (StringUtils.isBlank(message)){ 36 | //消息为空,消息拒绝,不重复发送,不重新放入队列 37 | channel.basicNack(deliveryTag,false,false); 38 | throw new BusinessException(ErrorCode.SYSTEM_ERROR,"消息为空"); 39 | } 40 | long chartId = Long.parseLong(message); 41 | Chart chart = chartService.getById(chartId); 42 | if (chart == null){ 43 | channel.basicNack(deliveryTag,false,false); 44 | throw new BusinessException(ErrorCode.SYSTEM_ERROR,"图表为空"); 45 | } 46 | 47 | //修改表状态为执行中,执行成功修改为“已完成”;执行失败修改为“失败” 48 | Chart updateChart = new Chart(); 49 | updateChart.setId(chart.getId()); 50 | updateChart.setStatus(ChartConstant.FAILED); 51 | boolean updateResult = chartService.updateById(updateChart); 52 | if (!updateResult){ 53 | handleChartUpdateError(chart.getId(),"更新图表执行状态失败"); 54 | return; 55 | } 56 | //消息确认 57 | channel.basicAck(deliveryTag,false); 58 | } 59 | private void handleChartUpdateError(Long chartId, String execMessage) { 60 | Chart updateChartResult = new Chart(); 61 | updateChartResult.setStatus(ChartConstant.FAILED); 62 | updateChartResult.setId(chartId); 63 | updateChartResult.setExecMessage(execMessage); 64 | boolean updateResult = chartService.updateById(updateChartResult); 65 | if (!updateResult){ 66 | log.error("更新图片失败状态失败"+chartId+","+execMessage); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.service; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | import com.yupi.springbootinit.model.dto.user.UserQueryRequest; 6 | import com.yupi.springbootinit.model.entity.User; 7 | import com.yupi.springbootinit.model.vo.LoginUserVO; 8 | import com.yupi.springbootinit.model.vo.UserVO; 9 | import java.util.List; 10 | import javax.servlet.http.HttpServletRequest; 11 | import me.chanjar.weixin.common.bean.WxOAuth2UserInfo; 12 | 13 | /** 14 | * 用户服务 15 | * 16 | * @author 程序员鱼皮 17 | * @from 编程导航知识星球 18 | */ 19 | public interface UserService extends IService { 20 | 21 | /** 22 | * 用户注册 23 | * 24 | * @param userAccount 用户账户 25 | * @param userPassword 用户密码 26 | * @param checkPassword 校验密码 27 | * @return 新用户 id 28 | */ 29 | long userRegister(String userAccount, String userPassword, String checkPassword); 30 | 31 | /** 32 | * 用户登录 33 | * 34 | * @param userAccount 用户账户 35 | * @param userPassword 用户密码 36 | * @param request 37 | * @return 脱敏后的用户信息 38 | */ 39 | LoginUserVO userLogin(String userAccount, String userPassword, HttpServletRequest request); 40 | 41 | /** 42 | * 用户登录(微信开放平台) 43 | * 44 | * @param wxOAuth2UserInfo 从微信获取的用户信息 45 | * @param request 46 | * @return 脱敏后的用户信息 47 | */ 48 | LoginUserVO userLoginByMpOpen(WxOAuth2UserInfo wxOAuth2UserInfo, HttpServletRequest request); 49 | 50 | /** 51 | * 获取当前登录用户 52 | * 53 | * @param request 54 | * @return 55 | */ 56 | User getLoginUser(HttpServletRequest request); 57 | 58 | /** 59 | * 获取当前登录用户(允许未登录) 60 | * 61 | * @param request 62 | * @return 63 | */ 64 | User getLoginUserPermitNull(HttpServletRequest request); 65 | 66 | /** 67 | * 是否为管理员 68 | * 69 | * @param request 70 | * @return 71 | */ 72 | boolean isAdmin(HttpServletRequest request); 73 | 74 | /** 75 | * 是否为管理员 76 | * 77 | * @param user 78 | * @return 79 | */ 80 | boolean isAdmin(User user); 81 | 82 | /** 83 | * 用户注销 84 | * 85 | * @param request 86 | * @return 87 | */ 88 | boolean userLogout(HttpServletRequest request); 89 | 90 | /** 91 | * 获取脱敏的已登录用户信息 92 | * 93 | * @return 94 | */ 95 | LoginUserVO getLoginUserVO(User user); 96 | 97 | /** 98 | * 获取脱敏的用户信息 99 | * 100 | * @param user 101 | * @return 102 | */ 103 | UserVO getUserVO(User user); 104 | 105 | /** 106 | * 获取脱敏的用户信息 107 | * 108 | * @param userList 109 | * @return 110 | */ 111 | List getUserVO(List userList); 112 | 113 | /** 114 | * 获取查询条件 115 | * 116 | * @param userQueryRequest 117 | * @return 118 | */ 119 | QueryWrapper getQueryWrapper(UserQueryRequest userQueryRequest); 120 | 121 | } 122 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | ### Java template 35 | # Compiled class file 36 | *.class 37 | 38 | # Log file 39 | *.log 40 | 41 | # BlueJ files 42 | *.ctxt 43 | 44 | # Mobile Tools for Java (J2ME) 45 | .mtj.tmp/ 46 | 47 | # Package Files # 48 | *.jar 49 | *.war 50 | *.nar 51 | *.ear 52 | *.zip 53 | *.tar.gz 54 | *.rar 55 | 56 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 57 | hs_err_pid* 58 | 59 | ### Maven template 60 | target/ 61 | pom.xml.tag 62 | pom.xml.releaseBackup 63 | pom.xml.versionsBackup 64 | pom.xml.next 65 | release.properties 66 | dependency-reduced-pom.xml 67 | buildNumber.properties 68 | .mvn/timing.properties 69 | # https://github.com/takari/maven-wrapper#usage-without-binary-jar 70 | .mvn/wrapper/maven-wrapper.jar 71 | 72 | ### JetBrains template 73 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 74 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 75 | 76 | # User-specific stuff 77 | .idea/**/workspace.xml 78 | .idea/**/tasks.xml 79 | .idea/**/usage.statistics.xml 80 | .idea/**/dictionaries 81 | .idea/**/shelf 82 | 83 | # Generated files 84 | .idea/**/contentModel.xml 85 | 86 | # Sensitive or high-churn files 87 | .idea/**/dataSources/ 88 | .idea/**/dataSources.ids 89 | .idea/**/dataSources.local.xml 90 | .idea/**/sqlDataSources.xml 91 | .idea/**/dynamic.xml 92 | .idea/**/uiDesigner.xml 93 | .idea/**/dbnavigator.xml 94 | 95 | # Gradle 96 | .idea/**/gradle.xml 97 | .idea/**/libraries 98 | 99 | # Gradle and Maven with auto-import 100 | # When using Gradle or Maven with auto-import, you should exclude module files, 101 | # since they will be recreated, and may cause churn. Uncomment if using 102 | # auto-import. 103 | # .idea/artifacts 104 | # .idea/compiler.xml 105 | # .idea/jarRepositories.xml 106 | # .idea/modules.xml 107 | # .idea/*.iml 108 | # .idea/modules 109 | # *.iml 110 | # *.ipr 111 | 112 | # CMake 113 | cmake-build-*/ 114 | 115 | # Mongo Explorer plugin 116 | .idea/**/mongoSettings.xml 117 | 118 | # File-based project format 119 | *.iws 120 | 121 | # IntelliJ 122 | out/ 123 | 124 | # mpeltonen/sbt-idea plugin 125 | .idea_modules/ 126 | 127 | # JIRA plugin 128 | atlassian-ide-plugin.xml 129 | 130 | # Cursive Clojure plugin 131 | .idea/replstate.xml 132 | 133 | # Crashlytics plugin (for Android Studio and IntelliJ) 134 | com_crashlytics_export_strings.xml 135 | crashlytics.properties 136 | crashlytics-build.properties 137 | fabric.properties 138 | 139 | # Editor-based Rest Client 140 | .idea/httpRequests 141 | 142 | # Android studio 3.1+ serialized cache file 143 | .idea/caches/build_file_checksums.ser 144 | 145 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/service/impl/CreditServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.service.impl; 2 | 3 | import cn.hutool.core.date.DateTime; 4 | import cn.hutool.core.date.DateUtil; 5 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 6 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 7 | import com.yupi.springbootinit.common.ErrorCode; 8 | import com.yupi.springbootinit.constant.CreditConstant; 9 | import com.yupi.springbootinit.exception.BusinessException; 10 | import com.yupi.springbootinit.exception.ThrowUtils; 11 | import com.yupi.springbootinit.model.entity.Credit; 12 | import com.yupi.springbootinit.model.entity.User; 13 | import com.yupi.springbootinit.service.CreditService; 14 | import com.yupi.springbootinit.mapper.CreditMapper; 15 | import com.yupi.springbootinit.service.UserService; 16 | import org.springframework.stereotype.Service; 17 | import org.springframework.transaction.annotation.Transactional; 18 | 19 | import javax.annotation.Resource; 20 | import javax.servlet.http.HttpServletRequest; 21 | 22 | /** 23 | * @author MA_dou 24 | * @description 针对表【credit(积分表)】的数据库操作Service实现 25 | * @createDate 2023-06-28 21:29:40 26 | */ 27 | @Service 28 | public class CreditServiceImpl extends ServiceImpl 29 | implements CreditService{ 30 | 31 | @Override 32 | public Long getCreditTotal(Long userId) { 33 | if (userId == null){ 34 | throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR); 35 | } 36 | QueryWrapper queryWrapper = new QueryWrapper<>(); 37 | queryWrapper.eq("userId",userId); 38 | Credit credit = this.getOne(queryWrapper); 39 | ThrowUtils.throwIf(credit == null, ErrorCode.NOT_FOUND_ERROR); 40 | return credit.getCreditTotal(); 41 | } 42 | 43 | @Override 44 | public Boolean signUser(Long userId) { 45 | if (userId == null){ 46 | throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR); 47 | } 48 | synchronized (userId.toString().intern()) { 49 | QueryWrapper queryWrapper = new QueryWrapper<>(); 50 | queryWrapper.eq("userId", userId); 51 | Credit credit = this.getOne(queryWrapper); 52 | ThrowUtils.throwIf(credit == null, ErrorCode.NOT_FOUND_ERROR); 53 | //判断今天是否已经签过 54 | if (DateUtil.isSameDay(credit.getUpdateTime(), new DateTime())) { 55 | return false; 56 | } 57 | Long creditTotal = credit.getCreditTotal() + CreditConstant.CREDIT_DAILY; 58 | credit.setCreditTotal(creditTotal); 59 | //保持更新时间 60 | credit.setUpdateTime(null); 61 | return this.updateById(credit); 62 | } 63 | } 64 | 65 | @Override 66 | public Boolean updateCredits(Long userId, long credits) { 67 | if (userId == null){ 68 | throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR); 69 | } 70 | QueryWrapper queryWrapper = new QueryWrapper<>(); 71 | queryWrapper.eq("userId",userId); 72 | Credit credit = this.getOne(queryWrapper); 73 | ThrowUtils.throwIf(credit == null, ErrorCode.NOT_FOUND_ERROR); 74 | Long creditTotal = credit.getCreditTotal(); 75 | //积分不足时 76 | if (creditTotal+credits<0) return false; 77 | creditTotal =creditTotal + credits; 78 | credit.setCreditTotal(creditTotal); 79 | //保持更新时间 80 | credit.setUpdateTime(null); 81 | return this.updateById(credit); 82 | } 83 | 84 | } 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/mq/Bi/BiMessageConsumer.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.mq.Bi; 2 | 3 | import cn.hutool.core.date.DateTime; 4 | import cn.hutool.json.JSONUtil; 5 | import com.rabbitmq.client.Channel; 6 | import com.yupi.springbootinit.common.ErrorCode; 7 | import com.yupi.springbootinit.constant.ChartConstant; 8 | import com.yupi.springbootinit.constant.MqConstant; 9 | import com.yupi.springbootinit.exception.BusinessException; 10 | import com.yupi.springbootinit.manager.AiManager; 11 | import com.yupi.springbootinit.model.entity.Chart; 12 | import com.yupi.springbootinit.service.ChartService; 13 | import lombok.SneakyThrows; 14 | import lombok.extern.slf4j.Slf4j; 15 | import org.apache.commons.lang3.StringUtils; 16 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 17 | import org.springframework.amqp.support.AmqpHeaders; 18 | import org.springframework.messaging.handler.annotation.Header; 19 | import org.springframework.stereotype.Component; 20 | 21 | import javax.annotation.Resource; 22 | import java.util.HashMap; 23 | 24 | /** 25 | * 图表分析消费者队列 26 | */ 27 | @Component 28 | @Slf4j 29 | public class BiMessageConsumer { 30 | 31 | @Resource 32 | private ChartService chartService; 33 | 34 | @Resource 35 | private AiManager aiManager; 36 | 37 | @SneakyThrows 38 | @RabbitListener(queues = {MqConstant.BI_QUEUE_NAME},ackMode = "MANUAL") 39 | public void receiveMessage(String message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag){ 40 | log.warn("接收到队列信息,receiveMessage={}=======================================",message); 41 | if (StringUtils.isBlank(message)){ 42 | //消息为空,消息拒绝,不重复发送,不重新放入队列 43 | channel.basicNack(deliveryTag,false,false); 44 | throw new BusinessException(ErrorCode.SYSTEM_ERROR,"消息为空"); 45 | } 46 | long chartId = Long.parseLong(message); 47 | Chart chart = chartService.getById(chartId); 48 | if (chart == null){ 49 | channel.basicNack(deliveryTag,false,false); 50 | throw new BusinessException(ErrorCode.SYSTEM_ERROR,"图表为空"); 51 | } 52 | 53 | //修改表状态为执行中,执行成功修改为“已完成”;执行失败修改为“失败” 54 | Chart updateChart = new Chart(); 55 | updateChart.setId(chart.getId()); 56 | updateChart.setStatus(ChartConstant.RUNNING); 57 | boolean updateResult = chartService.updateById(updateChart); 58 | if (!updateResult){ 59 | handleChartUpdateError(chart.getId(),"更新图表执行状态失败"); 60 | return; 61 | } 62 | //调用AI 63 | String result = null; 64 | try { 65 | result = aiManager.doChat(chartService.buildUserInput(chart).toString(), ChartConstant.MODE_ID); 66 | } catch (Exception e) { 67 | channel.basicNack(deliveryTag,false,true); 68 | log.warn("信息放入队列{}", DateTime.now()); 69 | throw new BusinessException(ErrorCode.SYSTEM_ERROR,"AI 服务错误"); 70 | } 71 | //处理返回的数据 72 | try { 73 | boolean saveResult = chartService.saveChartAiResult(result, chart.getId()); 74 | if (!saveResult){ 75 | chartService.handleChartUpdateError(chart.getId(), "图表数据保存失败"); 76 | } 77 | } catch (Exception e) { 78 | //重新放回队列 79 | channel.basicNack(deliveryTag,false,true); 80 | throw new BusinessException(ErrorCode.SYSTEM_ERROR,"图表数据保存失败"); 81 | } 82 | //消息确认 83 | channel.basicAck(deliveryTag,false); 84 | } 85 | private void handleChartUpdateError(Long chartId, String execMessage) { 86 | Chart updateChartResult = new Chart(); 87 | updateChartResult.setStatus(ChartConstant.FAILED); 88 | updateChartResult.setId(chartId); 89 | updateChartResult.setExecMessage(execMessage); 90 | boolean updateResult = chartService.updateById(updateChartResult); 91 | if (!updateResult){ 92 | log.error("更新图片失败状态失败"+chartId+","+execMessage); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/controller/FileController.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.controller; 2 | 3 | import cn.hutool.core.io.FileUtil; 4 | import com.yupi.springbootinit.common.BaseResponse; 5 | import com.yupi.springbootinit.common.ErrorCode; 6 | import com.yupi.springbootinit.common.ResultUtils; 7 | import com.yupi.springbootinit.constant.FileConstant; 8 | import com.yupi.springbootinit.exception.BusinessException; 9 | import com.yupi.springbootinit.manager.CosManager; 10 | import com.yupi.springbootinit.model.dto.file.UploadFileRequest; 11 | import com.yupi.springbootinit.model.entity.User; 12 | import com.yupi.springbootinit.model.enums.FileUploadBizEnum; 13 | import com.yupi.springbootinit.service.UserService; 14 | import java.io.File; 15 | import java.util.Arrays; 16 | import javax.annotation.Resource; 17 | import javax.servlet.http.HttpServletRequest; 18 | import lombok.extern.slf4j.Slf4j; 19 | import org.apache.commons.lang3.RandomStringUtils; 20 | import org.springframework.web.bind.annotation.PostMapping; 21 | import org.springframework.web.bind.annotation.RequestMapping; 22 | import org.springframework.web.bind.annotation.RequestPart; 23 | import org.springframework.web.bind.annotation.RestController; 24 | import org.springframework.web.multipart.MultipartFile; 25 | 26 | /** 27 | * 文件接口 28 | * 29 | * @author 程序员鱼皮 30 | * @from 编程导航知识星球 31 | */ 32 | @RestController 33 | @RequestMapping("/file") 34 | @Slf4j 35 | public class FileController { 36 | 37 | @Resource 38 | private UserService userService; 39 | 40 | @Resource 41 | private CosManager cosManager; 42 | 43 | /** 44 | * 文件上传 45 | * 46 | * @param multipartFile 47 | * @param uploadFileRequest 48 | * @param request 49 | * @return 50 | */ 51 | @PostMapping("/upload") 52 | public BaseResponse uploadFile(@RequestPart("file") MultipartFile multipartFile, 53 | UploadFileRequest uploadFileRequest, HttpServletRequest request) { 54 | String biz = uploadFileRequest.getBiz(); 55 | FileUploadBizEnum fileUploadBizEnum = FileUploadBizEnum.getEnumByValue(biz); 56 | if (fileUploadBizEnum == null) { 57 | throw new BusinessException(ErrorCode.PARAMS_ERROR); 58 | } 59 | validFile(multipartFile, fileUploadBizEnum); 60 | User loginUser = userService.getLoginUser(request); 61 | // 文件目录:根据业务、用户来划分 62 | String uuid = RandomStringUtils.randomAlphanumeric(8); 63 | String filename = uuid + "-" + multipartFile.getOriginalFilename(); 64 | String filepath = String.format("/%s/%s/%s", fileUploadBizEnum.getValue(), loginUser.getId(), filename); 65 | File file = null; 66 | try { 67 | // 上传文件 68 | file = File.createTempFile(filepath, null); 69 | multipartFile.transferTo(file); 70 | cosManager.putObject(filepath, file); 71 | // 返回可访问地址 72 | return ResultUtils.success(FileConstant.COS_HOST + filepath); 73 | } catch (Exception e) { 74 | log.error("file upload error, filepath = " + filepath, e); 75 | throw new BusinessException(ErrorCode.SYSTEM_ERROR, "上传失败"); 76 | } finally { 77 | if (file != null) { 78 | // 删除临时文件 79 | boolean delete = file.delete(); 80 | if (!delete) { 81 | log.error("file delete error, filepath = {}", filepath); 82 | } 83 | } 84 | } 85 | } 86 | 87 | /** 88 | * 校验文件 89 | * 90 | * @param multipartFile 91 | * @param fileUploadBizEnum 业务类型 92 | */ 93 | private void validFile(MultipartFile multipartFile, FileUploadBizEnum fileUploadBizEnum) { 94 | // 文件大小 95 | long fileSize = multipartFile.getSize(); 96 | // 文件后缀 97 | String fileSuffix = FileUtil.getSuffix(multipartFile.getOriginalFilename()); 98 | final long ONE_M = 1024 * 1024L; 99 | if (FileUploadBizEnum.USER_AVATAR.equals(fileUploadBizEnum)) { 100 | if (fileSize > ONE_M) { 101 | throw new BusinessException(ErrorCode.PARAMS_ERROR, "文件大小不能超过 1M"); 102 | } 103 | if (!Arrays.asList("jpeg", "jpg", "svg", "png", "webp").contains(fileSuffix)) { 104 | throw new BusinessException(ErrorCode.PARAMS_ERROR, "文件类型错误"); 105 | } 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/main/resources/笔记.txt: -------------------------------------------------------------------------------- 1 | 接入支付宝沙盒支付 2 | 当充值积分时,生成订单消息存入数据库,可以假入延迟队列,当时间过期时,给这个订单设置为支付过期,当选择成功支付后给延迟队列回复并更新数据库为成功支付并增加积分。 3 | 说明:用于充值积分,1元==100积分,设计订单表 4 | -- 充值订单表 5 | create table if not exists orders 6 | ( 7 | id bigint auto_increment comment 'id' primary key comment '订单id', 8 | alipayTradeNo varchar(128) null comment '支付宝交易凭证id', 9 | subject varchar(128) not null comment '交易名称' , 10 | totalAmount double not null comment '交易金额', 11 | tradeStatus varchar(128) not null default 'unpaid ' comment 'unpaid,paying,succeed,failed', 12 | buyerId varchar(64) null comment '支付宝买家id', 13 | createTime datetime default CURRENT_TIMESTAMP not null comment '创建时间', 14 | updateTime datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间', 15 | isDelete tinyint default 0 not null comment '是否删除' 16 | ) comment '充值订单表' collate = utf8mb4_unicode_ci; 17 | 内网穿透地址设置 需要加上/api/alipay/notify 18 | 作用是作为支付成功后的回调接收消息 19 | request.setNotifyUrl("http://d2a39q.natappfree.cc/api/alipay/notify"); 20 | 在本地环境内网穿透时,地址需要更改 21 | 订单支付成功回调 22 | // 查询订单并更新状态并加积分 23 | //查询当前订单消息 24 | Orders orders = ordersService.getById(outTradeNo); 25 | orders.setTradeStatus(OrderConstant.SUCCEED); 26 | orders.setAlipayTradeNo(alipayTradeNo); 27 | orders.setBuyerId(buyerId); 28 | boolean result = ordersService.updateById(orders); 29 | ThrowUtils.throwIf(!result, ErrorCode.SYSTEM_ERROR,"订单更新错误"); 30 | //根据充值金额增加积分 31 | result = creditService.updateCredits(orders.getUserId(), 100L * totalAmount); 32 | ThrowUtils.throwIf(!result, ErrorCode.SYSTEM_ERROR,"积分更新错误"); 33 | 34 | 后端支付流程: 35 | 延迟队列 36 | 定义一个支付的队列采用TTL队列和死信队列,当订单超过5分钟未支付,设置该订单失效 37 | /** 38 | * 用于创建订单程序的交换机和队列 39 | */ 40 | @Configuration 41 | public class AlipayMqInitMain { 42 | /** 43 | * 将死信队列和交换机声明 44 | */ 45 | @Bean 46 | Queue AliPayDeadQueue(){ 47 | return QueueBuilder.durable(MqConstant.ORDERS_DEAD_QUEUE_NAME).build(); 48 | } 49 | @Bean 50 | DirectExchange AliPayDeadExchange() { 51 | return new DirectExchange(MqConstant.ORDERS_DEAD_EXCHANGE_NAME); 52 | } 53 | @Bean 54 | Binding AliPayDeadBinding(Queue AliPayDeadQueue, DirectExchange AliPayDeadExchange) { 55 | return BindingBuilder.bind(AliPayDeadQueue).to(AliPayDeadExchange).with(MqConstant.ORDERS_DEAD_ROUTING_KEY); 56 | } 57 | /** 58 | * 将队列和交换机声明 59 | */ 60 | @Bean 61 | Queue AliPayQueue(){ 62 | //信息参数 设置TTL为1min 63 | Map arg = new HashMap<>(); 64 | arg.put("x-message-ttl",1000*5*60); 65 | //绑定死信交换机 66 | arg.put("x-dead-letter-exchange",MqConstant.ORDERS_DEAD_EXCHANGE_NAME); 67 | arg.put("x-dead-letter-routing-key",MqConstant.ORDERS_DEAD_ROUTING_KEY); 68 | return QueueBuilder.durable(MqConstant.ORDERS_QUEUE_NAME).withArguments(arg).build(); 69 | } 70 | @Bean 71 | DirectExchange AliPayExchange() { 72 | return new DirectExchange(MqConstant.ORDERS_EXCHANGE_NAME); 73 | } 74 | @Bean 75 | Binding AliPayBinding(Queue AliPayQueue, DirectExchange AliPayExchange) { 76 | return BindingBuilder.bind(AliPayQueue).to(AliPayExchange).with(MqConstant.ORDERS_ROUTING_KEY); 77 | } 78 | } 79 | 80 | 死信队列用于记录订单失效后,消费者队列在回调接口中实现,保证支付成功后信息被消费 81 | 订单消费者 82 | @SneakyThrows 83 | @RabbitListener(queues = {MqConstant.ORDERS_QUEUE_NAME}) 84 | public void receiveMessage(String message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag){ 85 | log.warn("接收到队列信息,receiveMessage={}=======================================",message); 86 | if (StringUtils.isBlank(message)){ 87 | //消息为空,消息拒绝,不重复发送,不重新放入队列 88 | channel.basicNack(deliveryTag,false,false); 89 | throw new BusinessException(ErrorCode.SYSTEM_ERROR,"消息为空"); 90 | } 91 | long orderId = Long.parseLong(message); 92 | Orders order = ordersService.getById(orderId); 93 | if (order == null){ 94 | channel.basicNack(deliveryTag,false,false); 95 | throw new BusinessException(ErrorCode.SYSTEM_ERROR,"订单为空"); 96 | } 97 | //查询订单信息看是完成支付,未支付则重新放入队列中直至过期 98 | String tradeStatus = order.getTradeStatus(); 99 | log.warn("订单查询为"+order.getTradeStatus()); 100 | if (!tradeStatus.equals(OrdersConstant.SUCCEED)){ 101 | log.warn("订单未支付成功,重新放回队列,订单号为"+order.getId()); 102 | channel.basicNack(deliveryTag,false,true); 103 | }else { 104 | //消息确认 105 | channel.basicAck(deliveryTag,false); 106 | } 107 | } 108 | 注意 109 | rabbitmq的重发机制不能在try-catch中使用,否则会不生效,因为catch也会算一次确定消息。 -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: gebi-backend 4 | # 默认 dev 环境 5 | profiles: 6 | active: dev 7 | # 支持 swagger3 8 | mvc: 9 | pathmatch: 10 | matching-strategy: ant_path_matcher 11 | # session 配置 12 | session: 13 | # todo 取消注释开启分布式 session(须先配置 Redis) 14 | # store-type: redis 15 | # 30 天过期 16 | timeout: 2592000 17 | # 数据库配置 18 | # todo 需替换配置 19 | datasource: 20 | driver-class-name: com.mysql.cj.jdbc.Driver 21 | url: jdbc:mysql://localhost:3306/ge_bi 22 | username: root 23 | password: 123456 24 | # Redis 配置 25 | # todo 需替换配置,然后取消注释 26 | redis: 27 | database: 4 28 | host: 127.0.0.1 29 | port: 6379 30 | timeout: 5000 31 | # password: 123456 32 | # Elasticsearch 配置 33 | # todo 需替换配置,然后取消注释 34 | # elasticsearch: 35 | # uris: http://localhost:9200 36 | # username: root 37 | # password: 123456 38 | # 文件上传 39 | servlet: 40 | multipart: 41 | # 大小限制 42 | max-file-size: 10MB 43 | rabbitmq: 44 | addresses: localhost 45 | port: 5672 46 | password: guest 47 | username: guest 48 | listener: 49 | direct: 50 | acknowledge-mode: manual 51 | retry: 52 | enabled: true 53 | max-attempts: 5 54 | initial-interval: 5000 55 | multiplier: 1.5 56 | max-interval: 60000 57 | server: 58 | address: 0.0.0.0 59 | port: 9099 60 | servlet: 61 | context-path: /api 62 | # cookie 30 天过期 63 | session: 64 | cookie: 65 | max-age: 2592000 66 | mybatis-plus: 67 | configuration: 68 | map-underscore-to-camel-case: false 69 | log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 70 | global-config: 71 | db-config: 72 | logic-delete-field: isDelete # 全局逻辑删除的实体字段名 73 | logic-delete-value: 1 # 逻辑已删除值(默认为 1) 74 | logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) 75 | # 微信相关 76 | wx: 77 | # 微信公众平台 78 | # todo 需替换配置 79 | mp: 80 | token: xxx 81 | aesKey: xxx 82 | appId: xxx 83 | secret: xxx 84 | config-storage: 85 | http-client-type: HttpClient 86 | key-prefix: wx 87 | redis: 88 | host: 127.0.0.1 89 | port: 6379 90 | type: Memory 91 | # 微信开放平台 92 | # todo 需替换配置 93 | open: 94 | appId: xxx 95 | appSecret: xxx 96 | # 对象存储 97 | # todo 需替换配置 98 | cos: 99 | client: 100 | accessKey: xxx 101 | secretKey: xxx 102 | region: xxx 103 | bucket: xxx 104 | #鱼聪明 105 | yuapi: 106 | client: 107 | access-key: ux7bpq5mqr8db3n0dfhd46bunkebr8f3 108 | secret-key: eg6zsakkz0av0f6jae3g3cw163nw56hc 109 | #支付宝支付 110 | alipay: 111 | appId: 9021000122698871 112 | appPrivateKey: MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCBHgcsrfkv0Nr53utTVrahPROCYrubDm5pplOuP++h3PnDdUNWw+h6l3kB8X6Kl8/tt2OESWC97z8/TnBm7dG/LDVMQ+qLsjBATsRXYzhe/HwYdHxy+x2n3Hn1mVcTdP30U4WspRPBtD/cTQk8Ad/q3DWXbWiX6GWcRB9J+OrB2bu55thxRkFfUsfsYLempc4ClrTgt142nkyTJWf9ZWIFezNkLFRsMH/Gas+vN4Y9dx7mnQIvqS0tdJta6Uc9KBxDggN3qtOhkbh2HxVDzCUVp0cuuTV6jeji7V5f9QEV5NSex3J6yMc2OA9XatkuKeH9lSCXaPSOK7uVpT0/pzIJAgMBAAECggEAQPcp5vo2Si/NLjJSt6EGzUQc39rryE3PkksFCcTTvt6fsQ/8bNivzZcPZMHsyLEwBsziPrpo+cg6S5EdDz0T7xvASXpWtilXC9RWCB49S9XAXtGlmHjvZ/mQR9n6rSiNavTnaoG42hrmkuMUBWRwFQztzh5XpS9iiOjh0Wd0P0qmi8R74LKjposd/fV/PvX+Y3aVznI2MxDXg4ZYEEk2kp6Str7sed6SY1l47u7Ok4ACVqVrdjozveQ6CRdpiYZ+InoEQ3sOcJsypJ9H/vTiKHMhT14I/K9D3be/R/zFjaeteH7y5VMLLnkFFdnXhMw1SyT6669FIvfooeBlaJQB/QKBgQC8toZtGfZ+zl2Z5260NhZaO8bBklCfpmsW4cowxLF3bdtjSSu9umgKLGT/VHfMrlh5g6Kp4T6t5DGBISGHS53PqNmAlR9QzXXpg4p1z5gWKE7G7+JCxzXFZUKz7Hj3AhhA7DH+4oZ5rzyHQN25tMH8LLP+x6JiF0W5xLrxlNYG2wKBgQCvJ6+j72y7BMxPC2Ke7DMGjIo9gFnt/vALJ2qTNK/bcHbZruAsq6hFJIwSqrLzM0n7oDPRJbMEElX90xLzEvoqYBLzRcxcHWQFqnNr6RVId6BMnVduNioS4o5IWqgVxAsYV7mMb4pGH+vMak/P4tXxqwHUzPyzSVeW7jLhtjfl6wKBgQCjRFcw9RFpzCj3Cl+g0lqsXqMqvee6+EQWW+qOHt5bMVRppdiOIUP56UbIENBE6WHqX5TP3OxZjd+2lG9pmmZCTxc+Q8YAJoIpMYENRDmUkfL18nySwb8ntN/swl41dj59jNwEZP9rL8zyR5CNJnHeNt7TQuyeaPwOKMKEV/yDmQKBgHGaIdcH0NOzlvelgL9mnumeeYLOHoW4FeSGGh+DypNe7Bbfz1Hpu+esfpUU1Z/bIh7rlvANrX/0jIVmQyIYqtyVF3VlTdhoz5jFJrtUn5My02sdmblHtB4vhuzyr5X+YtvU+elV5q74wS0BvuYsT2rA6R0mHrgB16dystmmH7clAoGAFDfjBgb2NvjS41fFbBPj32UHwXN4W9R9Nb2E+ERwhr36ztzfIHA871Za497/+jUXOMmsu44Iz3la6wZMKWCweSUJfqeZ7Vfz5gchjHPO17159S0WRd2vpS32QEtzPr8FYYDBpGGQVuwD/VM9E4w16qq10SeMMwZxRsr7rAMuXdc= 113 | alipayPublicKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtArMSQwGm+etlaXghRdcgodQc8AaVRbN9oReCP1VID8145qeP238rRFr55kUdnUnUGUlb4bDAsUIZfNHexGM4hceEtv3AETBkm7r/5o5VFi86zWF536rg2GDqDbNIu0apTXIqpSYAqZRlwTCuz0BXrWWe/dd4O0KF/WLLh5Doyrghcu0oVzd6UahZ5IJdOzpmAXuSW+8fNxaddyBtFoIfa+NFc/xbqcCwhjaP4bT8NCfBeYmhYraqdVgM2ljINs8jS+DZkmLnbDvBlIQwt/8irKoSN2aCYc/GzCSPxh7L/dWiGppekQU55K5T6pU9cQDRSKzWMgqxlpF2ak3MjcLxQIDAQAB 114 | 115 | 116 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/mq/Text/TextMessageConsumer.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.mq.Text; 2 | 3 | import cn.hutool.core.date.DateTime; 4 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 5 | import com.rabbitmq.client.Channel; 6 | import com.yupi.springbootinit.common.ErrorCode; 7 | import com.yupi.springbootinit.constant.MqConstant; 8 | import com.yupi.springbootinit.constant.TextConstant; 9 | import com.yupi.springbootinit.exception.BusinessException; 10 | import com.yupi.springbootinit.manager.AiManager; 11 | import com.yupi.springbootinit.model.entity.TextRecord; 12 | import com.yupi.springbootinit.model.entity.TextTask; 13 | import com.yupi.springbootinit.service.TextRecordService; 14 | import com.yupi.springbootinit.service.TextTaskService; 15 | import lombok.SneakyThrows; 16 | import lombok.extern.slf4j.Slf4j; 17 | import org.apache.commons.lang3.StringUtils; 18 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 19 | import org.springframework.amqp.support.AmqpHeaders; 20 | import org.springframework.messaging.handler.annotation.Header; 21 | import org.springframework.stereotype.Component; 22 | 23 | import javax.annotation.Resource; 24 | import java.util.List; 25 | 26 | /** 27 | * 文本转换消费者队列 28 | */ 29 | @Component 30 | @Slf4j 31 | public class TextMessageConsumer { 32 | 33 | @Resource 34 | private TextTaskService textTaskService; 35 | 36 | @Resource 37 | private TextRecordService textRecordService; 38 | @Resource 39 | private AiManager aiManager; 40 | 41 | @SneakyThrows 42 | @RabbitListener(queues = {MqConstant.TEXT_QUEUE_NAME},ackMode = "MANUAL") 43 | public void receiveMessage(String message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag){ 44 | log.warn("接收到队列信息,receiveMessage={}=======================================",message); 45 | if (StringUtils.isBlank(message)){ 46 | //消息为空,消息拒绝,不重复发送,不重新放入队列 47 | channel.basicNack(deliveryTag,false,false); 48 | throw new BusinessException(ErrorCode.SYSTEM_ERROR,"消息为空"); 49 | } 50 | 51 | long textTaskId = Long.parseLong(message); 52 | List textRecordList = textRecordService.list(new QueryWrapper().eq("textTaskId", textTaskId)); 53 | //todo 可以将记录表字段增加一个type 减少一次查询表 54 | TextTask textTask = textTaskService.getById(textTaskId); 55 | if (textRecordList == null){ 56 | channel.basicNack(deliveryTag,false,false); 57 | throw new BusinessException(ErrorCode.SYSTEM_ERROR,"文本为空"); 58 | } 59 | //修改表状态为执行中,执行成功修改为“已完成”;执行失败修改为“失败” 60 | TextTask updateTask = new TextTask(); 61 | updateTask.setId(textTaskId); 62 | updateTask.setStatus(TextConstant.RUNNING); 63 | boolean updateResult = textTaskService.updateById(updateTask); 64 | if (!updateResult){ 65 | textTaskService.handleTextTaskUpdateError(textTaskId,"更新图表执行状态失败"); 66 | return; 67 | } 68 | //调用AI 69 | 70 | for (TextRecord textRecord : textRecordList) { 71 | String result = null; 72 | //队列重新消费时,不在重新生成已经生成过的数据 73 | if (textRecord.getGenTextContent() != null) continue; 74 | try { 75 | result = aiManager.doChat(textRecordService.buildUserInput(textRecord,textTask.getTextType()).toString(), TextConstant.MODE_ID); 76 | } catch (Exception e) { 77 | channel.basicNack(deliveryTag,false,true); 78 | log.warn("信息放入队列{}", DateTime.now()); 79 | throw new BusinessException(ErrorCode.SYSTEM_ERROR,"AI 服务错误"); 80 | } 81 | textRecord.setGenTextContent(result); 82 | textRecord.setStatus(TextConstant.SUCCEED); 83 | boolean updateById = textRecordService.updateById(textRecord); 84 | if (!updateById){ 85 | log.warn("AI生成错误,重新放入队列"); 86 | channel.basicNack(deliveryTag,false,true); 87 | throw new BusinessException(ErrorCode.SYSTEM_ERROR,"保存失败"); 88 | } 89 | } 90 | //将记录表中已经生成好的内容合并存入任务表 91 | StringBuilder stringBuilder = new StringBuilder(); 92 | textRecordList.forEach(textRecord1 -> { 93 | stringBuilder.append(textRecord1.getGenTextContent()).append('\n'); 94 | }); 95 | TextTask textTask1 = new TextTask(); 96 | textTask1.setId(textTaskId); 97 | textTask1.setGenTextContent(stringBuilder.toString()); 98 | textTask1.setStatus(TextConstant.SUCCEED); 99 | boolean save = textTaskService.updateById(textTask1); 100 | if (!save){ 101 | channel.basicNack(deliveryTag,false,true); 102 | textTaskService.handleTextTaskUpdateError(textTask.getId(), "ai返回文本任务保存失败"); 103 | } 104 | 105 | //消息确认 106 | channel.basicAck(deliveryTag,false); 107 | } 108 | 109 | 110 | } 111 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/service/impl/TextTaskServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.service.impl; 2 | 3 | import cn.hutool.core.io.FileUtil; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import com.yupi.springbootinit.common.ErrorCode; 6 | import com.yupi.springbootinit.constant.CreditConstant; 7 | import com.yupi.springbootinit.constant.TextConstant; 8 | import com.yupi.springbootinit.exception.ThrowUtils; 9 | import com.yupi.springbootinit.model.dto.text.GenTextTaskByAiRequest; 10 | import com.yupi.springbootinit.model.entity.Chart; 11 | import com.yupi.springbootinit.model.entity.TextRecord; 12 | import com.yupi.springbootinit.model.entity.TextTask; 13 | import com.yupi.springbootinit.model.entity.User; 14 | import com.yupi.springbootinit.service.CreditService; 15 | import com.yupi.springbootinit.service.TextRecordService; 16 | import com.yupi.springbootinit.service.TextTaskService; 17 | import com.yupi.springbootinit.mapper.TextTaskMapper; 18 | import com.yupi.springbootinit.utils.TxtUtils; 19 | import org.apache.commons.lang3.StringUtils; 20 | import org.springframework.stereotype.Service; 21 | import org.springframework.transaction.annotation.Transactional; 22 | import org.springframework.web.multipart.MultipartFile; 23 | 24 | import javax.annotation.Resource; 25 | import java.util.ArrayList; 26 | import java.util.Arrays; 27 | import java.util.List; 28 | 29 | /** 30 | * @author MA_dou 31 | * @description 针对表【text_task(文本任务表)】的数据库操作Service实现 32 | * @createDate 2023-07-12 20:32:15 33 | */ 34 | @Service 35 | public class TextTaskServiceImpl extends ServiceImpl 36 | implements TextTaskService{ 37 | 38 | @Resource 39 | private CreditService creditService; 40 | 41 | @Resource 42 | private TextRecordService textRecordService; 43 | 44 | @Transactional(rollbackFor = Exception.class) 45 | @Override 46 | public TextTask getTextTask(MultipartFile multipartFile, GenTextTaskByAiRequest genTextTaskByAiRequest, User loginUser) { 47 | String textTaskType = genTextTaskByAiRequest.getTextType(); 48 | String name = genTextTaskByAiRequest.getName(); 49 | //校验 50 | ThrowUtils.throwIf(StringUtils.isBlank(textTaskType), ErrorCode.PARAMS_ERROR,"目标为空"); 51 | ThrowUtils.throwIf(StringUtils.isNotBlank(name)&&name.length()>=100,ErrorCode.PARAMS_ERROR,"名称过长"); 52 | //校验文件 53 | long size = multipartFile.getSize(); 54 | String originalFilename = multipartFile.getOriginalFilename(); 55 | final long ONE_MB = 1024*1024; 56 | ThrowUtils.throwIf(size>ONE_MB,ErrorCode.PARAMS_ERROR,"文件超过1MB"); 57 | ThrowUtils.throwIf(size==0,ErrorCode.PARAMS_ERROR,"文件为空"); 58 | //校验文件后缀 59 | String suffix = FileUtil.getSuffix(originalFilename); 60 | final List validFileSuffix = Arrays.asList("txt"); 61 | ThrowUtils.throwIf(!validFileSuffix.contains(suffix),ErrorCode.PARAMS_ERROR,"文件后缀名非法"); 62 | 63 | //消耗积分 64 | Boolean creditResult = creditService.updateCredits(loginUser.getId(), CreditConstant.CREDIT_CHART_SUCCESS); 65 | ThrowUtils.throwIf(!creditResult,ErrorCode.OPERATION_ERROR,"你的积分不足"); 66 | 67 | //保存数据库 wait 68 | //保存任务进数据库 69 | TextTask textTask = new TextTask(); 70 | textTask.setTextType(textTaskType); 71 | textTask.setName(name); 72 | textTask.setUserId(loginUser.getId()); 73 | textTask.setStatus(TextConstant.WAIT); 74 | boolean saveResult = this.save(textTask); 75 | ThrowUtils.throwIf(!saveResult,ErrorCode.SYSTEM_ERROR,"文本任务保存失败"); 76 | 77 | Long taskId = textTask.getId(); 78 | // 压缩后的数据 79 | ArrayList textContentList = TxtUtils.readerFile(multipartFile); 80 | ThrowUtils.throwIf(textContentList.size() ==0,ErrorCode.PARAMS_ERROR,"文件为空"); 81 | 82 | //将分割的内容保存入记录表 83 | ArrayList taskArrayList = new ArrayList<>(); 84 | textContentList.forEach(textContent ->{ 85 | TextRecord textRecord = new TextRecord(); 86 | textRecord.setTextTaskId(taskId); 87 | textRecord.setTextContent(textContent); 88 | textRecord.setStatus(TextConstant.WAIT); 89 | taskArrayList.add(textRecord); 90 | }); 91 | 92 | boolean batchResult = textRecordService.saveBatch(taskArrayList); 93 | ThrowUtils.throwIf(!batchResult,ErrorCode.SYSTEM_ERROR,"文本记录保存失败"); 94 | 95 | return textTask; 96 | } 97 | 98 | @Override 99 | public void handleTextTaskUpdateError(Long textTaskId, String execMessage) { 100 | TextTask updateTextTaskResult = new TextTask(); 101 | updateTextTaskResult.setStatus(TextConstant.FAILED); 102 | updateTextTaskResult.setId(textTaskId); 103 | updateTextTaskResult.setExecMessage(execMessage); 104 | boolean updateResult = this.updateById(updateTextTaskResult); 105 | if (!updateResult){ 106 | log.error("更新文本失败状态失败"+textTaskId+","+execMessage); 107 | } 108 | } 109 | 110 | 111 | } 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /sql/create_table.sql: -------------------------------------------------------------------------------- 1 | # 建表脚本 2 | 3 | -- 创建库 4 | create database if not exists ge_bi; 5 | 6 | -- 切换库 7 | use ge_bi; 8 | 9 | -- 用户表 10 | create table if not exists user 11 | ( 12 | id bigint auto_increment comment 'id' primary key, 13 | userAccount varchar(256) not null comment '账号', 14 | userPassword varchar(512) not null comment '密码', 15 | userName varchar(256) null comment '用户昵称', 16 | userAvatar varchar(1024) null comment '用户头像', 17 | userRole varchar(256) default 'user' not null comment '用户角色:user/admin/ban', 18 | createTime datetime default CURRENT_TIMESTAMP not null comment '创建时间', 19 | updateTime datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间', 20 | isDelete tinyint default 0 not null comment '是否删除', 21 | index idx_userAccount (userAccount) 22 | ) comment '用户' collate = utf8mb4_unicode_ci; 23 | 24 | -- 图表 25 | create table if not exists chart 26 | ( 27 | id bigint auto_increment comment 'id' primary key, 28 | `name` varchar(128) null comment '图表名称', 29 | goal text null comment '分析目标', 30 | chartData text null comment '图表数据', 31 | chatType varchar(128) null comment '图表类型', 32 | genChat text null comment '生成的图表数据', 33 | genResult text null comment '生成的分析结论', 34 | userId bigint null comment '创建用户Id', 35 | `status` varchar(128) not null default 'wait' comment 'wait,running,succeed,failed', 36 | execMessage text null comment '执行信息', 37 | createTime datetime default CURRENT_TIMESTAMP not null comment '创建时间', 38 | updateTime datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间', 39 | isDelete tinyint default 0 not null comment '是否删除' 40 | ) comment '图表信息表' collate = utf8mb4_unicode_ci; 41 | 42 | -- 积分表 43 | create table if not exists credit 44 | ( 45 | id bigint auto_increment comment 'id' primary key, 46 | userId bigint null comment '创建用户Id', 47 | creditTotal bigint null default 0 comment '总积分', 48 | createTime datetime default CURRENT_TIMESTAMP not null comment '创建时间', 49 | updateTime datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间', 50 | isDelete tinyint default 0 not null comment '是否删除' 51 | ) comment '积分表' collate = utf8mb4_unicode_ci; 52 | 53 | -- 充值订单表 54 | create table if not exists orders 55 | ( 56 | id bigint auto_increment comment 'id' primary key comment '订单id', 57 | alipayTradeNo varchar(128) null comment '支付宝交易凭证id', 58 | `userId` bigint NOT NULL COMMENT '用户id', 59 | subject varchar(128) not null comment '交易名称', 60 | totalAmount double not null comment '交易金额', 61 | tradeStatus varchar(128) not null default 'unpaid ' comment 'unpaid,paying,succeed,failed', 62 | buyerId varchar(64) null comment '支付宝买家id', 63 | createTime datetime default CURRENT_TIMESTAMP not null comment '创建时间', 64 | updateTime datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间', 65 | isDelete tinyint default 0 not null comment '是否删除' 66 | ) comment '充值订单表' collate = utf8mb4_unicode_ci; 67 | -- 文本任务表 68 | create table if not exists text_task 69 | ( 70 | id bigint auto_increment comment '任务id' primary key, 71 | `name` varchar(128) null comment '笔记名称', 72 | textType varchar(128) null comment '文本类型', 73 | genTextContent text null comment '生成的文本内容', 74 | userId bigint null comment '创建用户Id', 75 | `status` varchar(128) not null default 'wait' comment 'wait,running,succeed,failed', 76 | execMessage text null comment '执行信息', 77 | createTime datetime default CURRENT_TIMESTAMP not null comment '创建时间', 78 | updateTime datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间', 79 | isDelete tinyint default 0 not null comment '是否删除' 80 | ) comment '文本任务表' collate = utf8mb4_unicode_ci; 81 | 82 | -- 文本记录表 83 | create table if not exists text_record 84 | ( 85 | id bigint auto_increment comment 'id' primary key, 86 | textTaskId bigint comment '文本任务id', 87 | textContent text null comment '文本内容', 88 | genTextContent text null comment '生成的文本内容', 89 | `status` varchar(128) not null default 'wait' comment 'wait,running,succeed,failed', 90 | execMessage text null comment '执行信息', 91 | createTime datetime default CURRENT_TIMESTAMP not null comment '创建时间', 92 | updateTime datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间', 93 | isDelete tinyint default 0 not null comment '是否删除' 94 | ) comment '文本记录表' collate = utf8mb4_unicode_ci; 95 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/service/impl/ChartServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.service.impl; 2 | 3 | import cn.hutool.core.io.FileUtil; 4 | import cn.hutool.json.JSONUtil; 5 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 6 | import com.yupi.springbootinit.common.ErrorCode; 7 | import com.yupi.springbootinit.constant.ChartConstant; 8 | import com.yupi.springbootinit.constant.CreditConstant; 9 | import com.yupi.springbootinit.exception.BusinessException; 10 | import com.yupi.springbootinit.exception.ThrowUtils; 11 | import com.yupi.springbootinit.model.dto.chart.GenChartByAiRequest; 12 | import com.yupi.springbootinit.model.entity.Chart; 13 | import com.yupi.springbootinit.model.entity.User; 14 | import com.yupi.springbootinit.service.ChartService; 15 | import com.yupi.springbootinit.mapper.ChartMapper; 16 | import com.yupi.springbootinit.service.CreditService; 17 | import com.yupi.springbootinit.utils.ExcelUtils; 18 | import org.apache.commons.lang3.StringUtils; 19 | import org.springframework.stereotype.Service; 20 | import org.springframework.transaction.annotation.Transactional; 21 | import org.springframework.web.multipart.MultipartFile; 22 | 23 | import javax.annotation.Resource; 24 | import java.util.Arrays; 25 | import java.util.HashMap; 26 | import java.util.List; 27 | 28 | /** 29 | * @author MA_dou 30 | * @description 针对表【chart(图表信息表)】的数据库操作Service实现 31 | * @createDate 2023-05-26 23:18:07 32 | */ 33 | @Service 34 | public class ChartServiceImpl extends ServiceImpl 35 | implements ChartService{ 36 | 37 | 38 | @Resource 39 | CreditService creditService; 40 | 41 | @Override 42 | public String buildUserInput(Chart chart){ 43 | String goal = chart.getGoal(); 44 | String chatType = chart.getChatType(); 45 | String csvData = chart.getChartData(); 46 | //构造用户输入 47 | StringBuilder userInput = new StringBuilder(); 48 | userInput.append("分析需求:").append("\n"); 49 | 50 | // 拼接分析目标 51 | String userGoal = goal; 52 | if (StringUtils.isNotBlank(chatType)) { 53 | userGoal += ",请使用" + chatType; 54 | } 55 | userInput.append(userGoal).append("\n"); 56 | userInput.append("原始数据:").append("\n"); 57 | userInput.append(csvData).append("\n"); 58 | return userInput.toString(); 59 | } 60 | 61 | @Transactional(rollbackFor = Exception.class) 62 | @Override 63 | public Chart getChartTask(MultipartFile multipartFile, GenChartByAiRequest genChartByAiRequest, User loginUser) { 64 | String chartType = genChartByAiRequest.getChartType(); 65 | String goal = genChartByAiRequest.getGoal(); 66 | String name = genChartByAiRequest.getName(); 67 | //校验 68 | ThrowUtils.throwIf(StringUtils.isBlank(goal), ErrorCode.PARAMS_ERROR,"目标为空"); 69 | ThrowUtils.throwIf(StringUtils.isNotBlank(name)&&name.length()>=100,ErrorCode.PARAMS_ERROR,"名称不规范"); 70 | //校验文件 71 | long size = multipartFile.getSize(); 72 | String originalFilename = multipartFile.getOriginalFilename(); 73 | final long ONE_MB = 1024*1024; 74 | ThrowUtils.throwIf(size>ONE_MB,ErrorCode.PARAMS_ERROR,"文件超过1MB"); 75 | ThrowUtils.throwIf(size==0,ErrorCode.PARAMS_ERROR,"文件为空"); 76 | //校验文件后缀 77 | String suffix = FileUtil.getSuffix(originalFilename); 78 | final List validFileSuffix = Arrays.asList("png","xlsx","svg","webp","jpeg"); 79 | ThrowUtils.throwIf(!validFileSuffix.contains(suffix),ErrorCode.PARAMS_ERROR,"文件后缀名非法"); 80 | 81 | // 压缩后的数据 82 | String csvData = ExcelUtils.excelToCsv(multipartFile); 83 | //消耗积分 84 | Boolean creditResult = creditService.updateCredits(loginUser.getId(), CreditConstant.CREDIT_CHART_SUCCESS); 85 | ThrowUtils.throwIf(!creditResult,ErrorCode.OPERATION_ERROR,"你的积分不足"); 86 | //保存数据库 wait 87 | Chart chart = new Chart(); 88 | chart.setUserId(loginUser.getId()); 89 | chart.setChartData(csvData); 90 | chart.setChatType(chartType); 91 | chart.setStatus(ChartConstant.WAIT); 92 | chart.setName(name); 93 | chart.setGoal(goal); 94 | boolean saveResult = this.save(chart); 95 | ThrowUtils.throwIf(!saveResult,ErrorCode.SYSTEM_ERROR,"图表保存失败"); 96 | return chart; 97 | } 98 | 99 | @Override 100 | public boolean saveChartAiResult(String result, long chartId) { 101 | String[] splits = result.split("【【【【【"); 102 | 103 | if (splits.length < 3){ 104 | throw new BusinessException(ErrorCode.SYSTEM_ERROR,"AI 生成错误"); 105 | } 106 | //todo 可以使用正则表达式保证数据准确性,防止中文出现 107 | String genChart= splits[1].trim(); 108 | String genResult = splits[2].trim(); 109 | //将非js格式转化为js格式 110 | try { 111 | HashMap genChartJson = JSONUtil.toBean(genChart, HashMap.class); 112 | genChart = JSONUtil.toJsonStr(genChartJson); 113 | } catch (Exception e) { 114 | throw new BusinessException(ErrorCode.SYSTEM_ERROR,"AI生成图片错误"); 115 | } 116 | //保存数据库 117 | Chart updateChartResult = new Chart(); 118 | updateChartResult.setId(chartId); 119 | updateChartResult.setStatus(ChartConstant.SUCCEED); 120 | updateChartResult.setGenChat(genChart); 121 | updateChartResult.setGenResult(genResult); 122 | return this.updateById(updateChartResult); 123 | 124 | } 125 | 126 | @Override 127 | public void handleChartUpdateError(Long chartId, String execMessage) { 128 | Chart updateChartResult = new Chart(); 129 | updateChartResult.setStatus(ChartConstant.FAILED); 130 | updateChartResult.setId(chartId); 131 | updateChartResult.setExecMessage(execMessage); 132 | boolean updateResult = this.updateById(updateChartResult); 133 | if (!updateResult){ 134 | log.error("更新图片失败状态失败"+chartId+","+execMessage); 135 | } 136 | } 137 | } 138 | 139 | 140 | 141 | 142 | -------------------------------------------------------------------------------- /src/main/java/com/yupi/springbootinit/controller/AliPayController.java: -------------------------------------------------------------------------------- 1 | package com.yupi.springbootinit.controller; 2 | 3 | import cn.hutool.json.JSONObject; 4 | import com.alipay.api.AlipayApiException; 5 | import com.alipay.api.AlipayClient; 6 | import com.alipay.api.internal.util.AlipaySignature; 7 | import com.alipay.api.request.AlipayTradePagePayRequest; 8 | import com.yupi.springbootinit.mq.common.MqMessageProducer; 9 | import com.yupi.springbootinit.common.ErrorCode; 10 | import com.yupi.springbootinit.config.AliPayConfig; 11 | import com.yupi.springbootinit.constant.MqConstant; 12 | import com.yupi.springbootinit.constant.OrdersConstant; 13 | import com.yupi.springbootinit.exception.ThrowUtils; 14 | import com.yupi.springbootinit.model.dto.order.OrderAddRequest; 15 | import com.yupi.springbootinit.model.entity.Orders; 16 | import com.yupi.springbootinit.model.entity.User; 17 | import com.yupi.springbootinit.service.CreditService; 18 | import com.yupi.springbootinit.service.OrdersService; 19 | import com.yupi.springbootinit.service.UserService; 20 | import org.springframework.web.bind.annotation.GetMapping; 21 | import org.springframework.web.bind.annotation.PostMapping; 22 | import org.springframework.web.bind.annotation.RequestMapping; 23 | import org.springframework.web.bind.annotation.RestController; 24 | 25 | import javax.annotation.Resource; 26 | import javax.servlet.http.HttpServletRequest; 27 | import javax.servlet.http.HttpServletResponse; 28 | import java.util.HashMap; 29 | import java.util.Map; 30 | 31 | /** 32 | * 支付宝支付接口 33 | */ 34 | @RestController 35 | @RequestMapping("/alipay") 36 | public class AliPayController { 37 | private static final String GATEWAY_URL = "https://openapi.alipaydev.com/gateway.do"; 38 | private static final String FORMAT = "JSON"; 39 | private static final String CHARSET = "UTF-8"; 40 | //签名方式 41 | private static final String SIGN_TYPE = "RSA2"; 42 | @Resource 43 | private AlipayClient alipayClient; 44 | 45 | @Resource 46 | private AliPayConfig aliPayConfig; 47 | 48 | @Resource 49 | private OrdersService ordersService; 50 | 51 | @Resource 52 | private CreditService creditService; 53 | 54 | @Resource 55 | private UserService userService; 56 | 57 | @Resource 58 | private MqMessageProducer mqMessageProducer; 59 | 60 | 61 | @GetMapping("/pay") // &subject=xxx&traceNo=xxx&totalAmount=xxx 62 | public void pay(OrderAddRequest aliPay,HttpServletRequest httpServletRequest, HttpServletResponse httpResponse) throws Exception { 63 | //1. 插入数据库订单消息 64 | User loginUser = userService.getLoginUser(httpServletRequest); 65 | 66 | Orders orders = new Orders(); 67 | orders.setSubject(aliPay.getSubject()); 68 | orders.setTotalAmount(aliPay.getTotalAmount()); 69 | orders.setUserId(loginUser.getId()); 70 | boolean result = ordersService.save(orders); 71 | ThrowUtils.throwIf(!result, ErrorCode.SYSTEM_ERROR,"订单保存错误"); 72 | 73 | // 2. 创建 Request并设置Request参数 74 | AlipayTradePagePayRequest request = new AlipayTradePagePayRequest(); // 发送请求的 Request类 75 | 76 | request.setNotifyUrl(OrdersConstant.NOTIFYURL); 77 | JSONObject bizContent = new JSONObject(); 78 | bizContent.set("out_trade_no", orders.getId()); // 我们自己生成的订单编号 79 | bizContent.set("total_amount", orders.getTotalAmount()); // 订单的总金额 80 | bizContent.set("subject", orders.getSubject()); // 支付的名称 81 | bizContent.set("product_code", "FAST_INSTANT_TRADE_PAY"); // 固定配置 82 | request.setBizContent(bizContent.toString()); 83 | 84 | // 执行请求,拿到响应的结果,返回给浏览器 85 | String form = ""; 86 | try { 87 | form = alipayClient.pageExecute(request).getBody(); // 调用SDK生成表单 88 | } catch (AlipayApiException e) { 89 | e.printStackTrace(); 90 | } 91 | mqMessageProducer.sendMessage(MqConstant.ORDERS_EXCHANGE_NAME,MqConstant.ORDERS_ROUTING_KEY,String.valueOf(orders.getId())); 92 | httpResponse.setContentType("text/html;charset=" + CHARSET); 93 | httpResponse.getWriter().write(form);// 直接将完整的表单html输出到页面 94 | httpResponse.getWriter().flush(); 95 | httpResponse.getWriter().close(); 96 | } 97 | 98 | @PostMapping("/notify") // 注意这里必须是POST接口 99 | public String payNotify(HttpServletRequest request) throws Exception { 100 | if (request.getParameter("trade_status").equals("TRADE_SUCCESS")) { 101 | System.out.println("=========支付宝异步回调========"); 102 | 103 | Map params = new HashMap<>(); 104 | Map requestParams = request.getParameterMap(); 105 | for (String name : requestParams.keySet()) { 106 | params.put(name, request.getParameter(name)); 107 | // System.out.println(name + " = " + request.getParameter(name)); 108 | } 109 | 110 | String outTradeNo = params.get("out_trade_no"); 111 | String buyerId = params.get("buyer_id"); 112 | String alipayTradeNo = params.get("trade_no"); 113 | //给金额转型 114 | String[] total_amounts = params.get("total_amount").split("\\."); 115 | Integer totalAmount = Integer.valueOf(total_amounts[0]); 116 | 117 | String sign = params.get("sign"); 118 | String content = AlipaySignature.getSignCheckContentV1(params); 119 | boolean checkSignature = AlipaySignature.rsa256CheckContent(content, sign, aliPayConfig.getAlipayPublicKey(), "UTF-8"); // 验证签名 120 | // 支付宝验签 121 | if (checkSignature) { 122 | // // 验签通过 123 | // System.out.println("交易名称: " + params.get("subject")); 124 | // System.out.println("交易状态: " + params.get("trade_status")); 125 | // System.out.println("支付宝交易凭证号: " + params.get("trade_no")); 126 | // System.out.println("商户订单号: " + params.get("out_trade_no")); 127 | // System.out.println("交易金额: " + params.get("total_amount")); 128 | // System.out.println("买家在支付宝唯一id: " + params.get("buyer_id")); 129 | // System.out.println("买家付款时间: " + params.get("gmt_payment")); 130 | // System.out.println("买家付款金额: " + params.get("buyer_pay_amount")); 131 | 132 | // 查询订单并更新状态并加积分 133 | //查询当前订单消息 134 | Orders orders = ordersService.getById(outTradeNo); 135 | orders.setTradeStatus(OrdersConstant.SUCCEED); 136 | orders.setAlipayTradeNo(alipayTradeNo); 137 | orders.setBuyerId(buyerId); 138 | boolean result = ordersService.updateById(orders); 139 | ThrowUtils.throwIf(!result, ErrorCode.SYSTEM_ERROR,"订单更新错误"); 140 | //根据充值金额增加积分 141 | result = creditService.updateCredits(orders.getUserId(), 100L * totalAmount); 142 | ThrowUtils.throwIf(!result, ErrorCode.SYSTEM_ERROR,"积分更新错误"); 143 | } 144 | } 145 | return "success"; 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.springframework.boot 8 | spring-boot-starter-parent 9 | 2.7.2 10 | 11 | 12 | com.yupi 13 | gebi-backend 14 | 0.0.1-SNAPSHOT 15 | gebi-backend 16 | 17 | 1.8 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-freemarker 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-web 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-aop 31 | 32 | 33 | org.mybatis.spring.boot 34 | mybatis-spring-boot-starter 35 | 2.2.2 36 | 37 | 38 | 39 | org.redisson 40 | redisson 41 | 3.21.3 42 | 43 | 44 | 45 | com.yucongming 46 | yucongming-java-sdk 47 | 0.0.2 48 | 49 | 50 | 51 | com.baomidou 52 | mybatis-plus-boot-starter 53 | 3.5.2 54 | 55 | 56 | 57 | org.springframework.boot 58 | spring-boot-starter-data-redis 59 | 60 | 61 | org.springframework.session 62 | spring-session-data-redis 63 | 64 | 65 | 66 | org.springframework.boot 67 | spring-boot-starter-data-elasticsearch 68 | 69 | 70 | 71 | com.github.binarywang 72 | wx-java-mp-spring-boot-starter 73 | 4.4.0 74 | 75 | 76 | 77 | com.github.xiaoymin 78 | knife4j-spring-boot-starter 79 | 3.0.3 80 | 81 | 82 | 83 | org.springframework.boot 84 | spring-boot-starter-amqp 85 | 2.7.2 86 | 87 | 88 | 89 | 90 | com.qcloud 91 | cos_api 92 | 5.6.89 93 | 94 | 95 | 96 | org.apache.commons 97 | commons-lang3 98 | 99 | 100 | 101 | com.google.code.gson 102 | gson 103 | 2.9.1 104 | 105 | 106 | 107 | com.alibaba 108 | easyexcel 109 | 3.1.1 110 | 111 | 112 | 113 | cn.hutool 114 | hutool-all 115 | 5.8.8 116 | 117 | 118 | 119 | com.alipay.sdk 120 | alipay-sdk-java 121 | 4.38.4.ALL 122 | 123 | 124 | org.springframework.boot 125 | spring-boot-devtools 126 | runtime 127 | true 128 | 129 | 130 | mysql 131 | mysql-connector-java 132 | runtime 133 | 134 | 135 | org.springframework.boot 136 | spring-boot-configuration-processor 137 | true 138 | 139 | 140 | org.projectlombok 141 | lombok 142 | true 143 | 144 | 145 | org.springframework.boot 146 | spring-boot-starter-test 147 | test 148 | 149 | 150 | 151 | 152 | 153 | 154 | org.springframework.boot 155 | spring-boot-maven-plugin 156 | 157 | 158 | 159 | org.projectlombok 160 | lombok 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM https://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM set title of command window 39 | title %0 40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' 41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 42 | 43 | @REM set %HOME% to equivalent of $HOME 44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 45 | 46 | @REM Execute a user defined script before this one 47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 49 | if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* 50 | if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* 51 | :skipRcPre 52 | 53 | @setlocal 54 | 55 | set ERROR_CODE=0 56 | 57 | @REM To isolate internal variables from possible post scripts, we use another setlocal 58 | @setlocal 59 | 60 | @REM ==== START VALIDATION ==== 61 | if not "%JAVA_HOME%" == "" goto OkJHome 62 | 63 | echo. 64 | echo Error: JAVA_HOME not found in your environment. >&2 65 | echo Please set the JAVA_HOME variable in your environment to match the >&2 66 | echo location of your Java installation. >&2 67 | echo. 68 | goto error 69 | 70 | :OkJHome 71 | if exist "%JAVA_HOME%\bin\java.exe" goto init 72 | 73 | echo. 74 | echo Error: JAVA_HOME is set to an invalid directory. >&2 75 | echo JAVA_HOME = "%JAVA_HOME%" >&2 76 | echo Please set the JAVA_HOME variable in your environment to match the >&2 77 | echo location of your Java installation. >&2 78 | echo. 79 | goto error 80 | 81 | @REM ==== END VALIDATION ==== 82 | 83 | :init 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 122 | 123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" 124 | 125 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B 127 | ) 128 | 129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 131 | if exist %WRAPPER_JAR% ( 132 | if "%MVNW_VERBOSE%" == "true" ( 133 | echo Found %WRAPPER_JAR% 134 | ) 135 | ) else ( 136 | if not "%MVNW_REPOURL%" == "" ( 137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" 138 | ) 139 | if "%MVNW_VERBOSE%" == "true" ( 140 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 141 | echo Downloading from: %DOWNLOAD_URL% 142 | ) 143 | 144 | powershell -Command "&{"^ 145 | "$webclient = new-object System.Net.WebClient;"^ 146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ 147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ 148 | "}"^ 149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ 150 | "}" 151 | if "%MVNW_VERBOSE%" == "true" ( 152 | echo Finished downloading %WRAPPER_JAR% 153 | ) 154 | ) 155 | @REM End of extension 156 | 157 | @REM Provide a "standardized" way to retrieve the CLI args that will 158 | @REM work with both Windows and non-Windows executions. 159 | set MAVEN_CMD_LINE_ARGS=%* 160 | 161 | %MAVEN_JAVA_EXE% ^ 162 | %JVM_CONFIG_MAVEN_PROPS% ^ 163 | %MAVEN_OPTS% ^ 164 | %MAVEN_DEBUG_OPTS% ^ 165 | -classpath %WRAPPER_JAR% ^ 166 | "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ 167 | %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 168 | if ERRORLEVEL 1 goto error 169 | goto end 170 | 171 | :error 172 | set ERROR_CODE=1 173 | 174 | :end 175 | @endlocal & set ERROR_CODE=%ERROR_CODE% 176 | 177 | if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost 178 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 179 | if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" 180 | if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" 181 | :skipRcPost 182 | 183 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 184 | if "%MAVEN_BATCH_PAUSE%"=="on" pause 185 | 186 | if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% 187 | 188 | cmd /C exit /B %ERROR_CODE% 189 | --------------------------------------------------------------------------------