项目初次提交

This commit is contained in:
2025-06-12 19:44:47 +08:00
commit aca37b62d4
58 changed files with 3930 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
package com.yupi.springbootinit;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* 主类(项目启动入口)
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://yupi.icu">编程导航知识星球</a>
*/
// todo 如需开启 Redis须移除 exclude 中的内容
@SpringBootApplication(exclude = {RedisAutoConfiguration.class})
@MapperScan("com.yupi.springbootinit.mapper")
@EnableScheduling
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}

View File

@@ -0,0 +1,26 @@
package com.yupi.springbootinit.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 权限校验
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://yupi.icu">编程导航知识星球</a>
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthCheck {
/**
* 必须有某个角色
*
* @return
*/
String mustRole() default "";
}

View File

@@ -0,0 +1,56 @@
package com.yupi.springbootinit.aop;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* 请求响应日志 AOP
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://yupi.icu">编程导航知识星球</a>
**/
@Aspect
@Component
@Slf4j
public class LogInterceptor {
/**
* 执行拦截
*/
@Around("execution(* com.yupi.springbootinit.controller.*.*(..))")
public Object doInterceptor(ProceedingJoinPoint point) throws Throwable {
// 计时
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// 获取请求路径
RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
HttpServletRequest httpServletRequest = ((ServletRequestAttributes) requestAttributes).getRequest();
// 生成请求唯一 id
String requestId = UUID.randomUUID().toString();
String url = httpServletRequest.getRequestURI();
// 获取请求参数
Object[] args = point.getArgs();
String reqParam = "[" + StringUtils.join(args, ", ") + "]";
// 输出请求日志
log.info("request startid: {}, path: {}, ip: {}, params: {}", requestId, url,
httpServletRequest.getRemoteHost(), reqParam);
// 执行原方法
Object result = point.proceed();
// 输出响应日志
stopWatch.stop();
long totalTimeMillis = stopWatch.getTotalTimeMillis();
log.info("request end, id: {}, cost: {}ms", requestId, totalTimeMillis);
return result;
}
}

View File

@@ -0,0 +1,35 @@
package com.yupi.springbootinit.common;
import java.io.Serializable;
import lombok.Data;
/**
* 通用返回类
*
* @param <T>
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://yupi.icu">编程导航知识星球</a>
*/
@Data
public class BaseResponse<T> implements Serializable {
private int code;
private T data;
private String message;
public BaseResponse(int code, T data, String message) {
this.code = code;
this.data = data;
this.message = message;
}
public BaseResponse(int code, T data) {
this(code, data, "");
}
public BaseResponse(ErrorCode errorCode) {
this(errorCode.getCode(), null, errorCode.getMessage());
}
}

View File

@@ -0,0 +1,21 @@
package com.yupi.springbootinit.common;
import java.io.Serializable;
import lombok.Data;
/**
* 删除请求
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://yupi.icu">编程导航知识星球</a>
*/
@Data
public class DeleteRequest implements Serializable {
/**
* id
*/
private Long id;
private static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,47 @@
package com.yupi.springbootinit.common;
/**
* 自定义错误码
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://yupi.icu">编程导航知识星球</a>
*/
public enum ErrorCode {
SUCCESS(0, "ok"),
PARAMS_ERROR(40000, "请求参数错误"),
NOT_LOGIN_ERROR(40100, "未登录"),
USERNAME_OR_PASSWORD_ERROR(40200, "账号或密码错误"),
USER_DISABLE(40300, "用户被禁用"),
NO_AUTH_ERROR(40101, "无权限"),
NOT_FOUND_ERROR(40400, "请求数据不存在"),
FORBIDDEN_ERROR(40300, "禁止访问"),
SYSTEM_ERROR(50000, "系统内部异常"),
OPERATION_ERROR(50001, "操作失败"),
QUEUE_ERROR(60001, "队列消息添加失败"),
QUEUE_CONSUMPTION_FAILURE(60001, "队列消息消费失败");
/**
* 状态码
*/
private final int code;
/**
* 信息
*/
private final String message;
ErrorCode(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}

View File

@@ -0,0 +1,34 @@
package com.yupi.springbootinit.common;
import com.yupi.springbootinit.constant.CommonConstant;
import lombok.Data;
/**
* 分页请求
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://yupi.icu">编程导航知识星球</a>
*/
@Data
public class PageRequest {
/**
* 当前页号
*/
private int current = 1;
/**
* 页面大小
*/
private int pageSize = 10;
/**
* 排序字段
*/
private String sortField;
/**
* 排序顺序(默认升序)
*/
private String sortOrder = CommonConstant.SORT_ORDER_ASC;
}

View File

@@ -0,0 +1,52 @@
package com.yupi.springbootinit.common;
/**
* 返回工具类
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://yupi.icu">编程导航知识星球</a>
*/
public class ResultUtils {
/**
* 成功
*
* @param data
* @param <T>
* @return
*/
public static <T> BaseResponse<T> success(T data) {
return new BaseResponse<>(0, data, "ok");
}
/**
* 失败
*
* @param errorCode
* @return
*/
public static BaseResponse error(ErrorCode errorCode) {
return new BaseResponse<>(errorCode);
}
/**
* 失败
*
* @param code
* @param message
* @return
*/
public static BaseResponse error(int code, String message) {
return new BaseResponse(code, null, message);
}
/**
* 失败
*
* @param errorCode
* @return
*/
public static BaseResponse error(ErrorCode errorCode, String message) {
return new BaseResponse(errorCode.getCode(), null, message);
}
}

View File

@@ -0,0 +1,28 @@
package com.yupi.springbootinit.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 全局跨域配置
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://yupi.icu">编程导航知识星球</a>
*/
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
// 覆盖所有请求
registry.addMapping("/**")
// 允许发送 Cookie
.allowCredentials(true)
// 放行哪些域名(必须用 patterns否则 * 会和 allowCredentials 冲突)
.allowedOriginPatterns("*")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.exposedHeaders("*");
}
}

View File

@@ -0,0 +1,31 @@
package com.yupi.springbootinit.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import org.springframework.boot.jackson.JsonComponent;
import org.springframework.context.annotation.Bean;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
/**
* Spring MVC Json 配置
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://yupi.icu">编程导航知识星球</a>
*/
@JsonComponent
public class JsonConfig {
/**
* 添加 Long 转 json 精度丢失的配置
*/
@Bean
public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
SimpleModule module = new SimpleModule();
module.addSerializer(Long.class, ToStringSerializer.instance);
module.addSerializer(Long.TYPE, ToStringSerializer.instance);
objectMapper.registerModule(module);
return objectMapper;
}
}

View File

@@ -0,0 +1,31 @@
package com.yupi.springbootinit.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* MyBatis Plus 配置
*
* @author https://github.com/liyupi
*/
@Configuration
@MapperScan("com.yupi.springbootinit.mapper")
public class MyBatisPlusConfig {
/**
* 拦截器配置
*
* @return
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}

View File

@@ -0,0 +1,26 @@
package com.yupi.springbootinit.config;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitMQConfig {
private static final String QUEUE = "HOST_INFO_QUEUE";
//创建队列
//true:表示持久化
//队列在默认情况下放到内存rabbitmq重启后就丢失了如果希望重启后队列
//数据还能使用,就需要持久化
@Bean
public Queue hostInfoQueue(){
return new Queue(QUEUE,true);
}
@Bean
public MessageConverter messageConverter(){
return new Jackson2JsonMessageConverter();
}
}

View File

@@ -0,0 +1,21 @@
package com.yupi.springbootinit.constant;
/**
* 通用常量
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://yupi.icu">编程导航知识星球</a>
*/
public interface CommonConstant {
/**
* 升序
*/
String SORT_ORDER_ASC = "ascend";
/**
* 降序
*/
String SORT_ORDER_DESC = " descend";
}

View File

@@ -0,0 +1,16 @@
package com.yupi.springbootinit.constant;
/**
* 文件常量
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://yupi.icu">编程导航知识星球</a>
*/
public interface FileConstant {
/**
* COS 访问地址
* todo 需替换配置
*/
String COS_HOST = "https://yupi.icu";
}

View File

@@ -0,0 +1,34 @@
package com.yupi.springbootinit.constant;
/**
* 用户常量
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://yupi.icu">编程导航知识星球</a>
*/
public interface UserConstant {
/**
* 用户登录态键
*/
String USER_LOGIN_STATE = "user_login";
// region 权限
/**
* 默认角色
*/
String DEFAULT_ROLE = "user";
/**
* 管理员角色
*/
String ADMIN_ROLE = "admin";
/**
* 被封号
*/
String BAN_ROLE = "ban";
// endregion
}

View File

@@ -0,0 +1,35 @@
package com.yupi.springbootinit.controller;
import com.yupi.springbootinit.common.BaseResponse;
import com.yupi.springbootinit.common.ResultUtils;
import com.yupi.springbootinit.model.dto.host.HostInfoDTO;
import com.yupi.springbootinit.model.entity.NewHosts;
import com.yupi.springbootinit.model.vo.hosts.NewHostsVO;
import com.yupi.springbootinit.rabbitMQ.MQSender;
import com.yupi.springbootinit.service.HostInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/*
* @author: ziin
* @date: 2025/6/10 17:09
*/
@RestController
@RequestMapping("/save_data")
@Slf4j
@CrossOrigin
public class HostInfoController {
@Resource
private MQSender mqSender;
@PostMapping("add_host")
public BaseResponse<Boolean> addHost(@RequestBody List<NewHosts> newHosts){
mqSender.send(newHosts);
return ResultUtils.success(true);
}
}

View File

@@ -0,0 +1,36 @@
package com.yupi.springbootinit.exception;
import com.yupi.springbootinit.common.ErrorCode;
/**
* 自定义异常类
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://yupi.icu">编程导航知识星球</a>
*/
public class BusinessException extends RuntimeException {
/**
* 错误码
*/
private final int code;
public BusinessException(int code, String message) {
super(message);
this.code = code;
}
public BusinessException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.code = errorCode.getCode();
}
public BusinessException(ErrorCode errorCode, String message) {
super(message);
this.code = errorCode.getCode();
}
public int getCode() {
return code;
}
}

View File

@@ -0,0 +1,31 @@
package com.yupi.springbootinit.exception;
import com.yupi.springbootinit.common.BaseResponse;
import com.yupi.springbootinit.common.ErrorCode;
import com.yupi.springbootinit.common.ResultUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 全局异常处理器
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://yupi.icu">编程导航知识星球</a>
*/
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
@ExceptionHandler(BusinessException.class)
public BaseResponse<?> businessExceptionHandler(BusinessException e) {
log.error("BusinessException", e);
return ResultUtils.error(e.getCode(), e.getMessage());
}
@ExceptionHandler(RuntimeException.class)
public BaseResponse<?> runtimeExceptionHandler(RuntimeException e) {
log.error("RuntimeException", e);
return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "系统错误");
}
}

View File

@@ -0,0 +1,45 @@
package com.yupi.springbootinit.exception;
import com.yupi.springbootinit.common.ErrorCode;
/**
* 抛异常工具类
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://yupi.icu">编程导航知识星球</a>
*/
public class ThrowUtils {
/**
* 条件成立则抛异常
*
* @param condition
* @param runtimeException
*/
public static void throwIf(boolean condition, RuntimeException runtimeException) {
if (condition) {
throw runtimeException;
}
}
/**
* 条件成立则抛异常
*
* @param condition
* @param errorCode
*/
public static void throwIf(boolean condition, ErrorCode errorCode) {
throwIf(condition, new BusinessException(errorCode));
}
/**
* 条件成立则抛异常
*
* @param condition
* @param errorCode
* @param message
*/
public static void throwIf(boolean condition, ErrorCode errorCode, String message) {
throwIf(condition, new BusinessException(errorCode, message));
}
}

View File

@@ -0,0 +1,128 @@
package com.yupi.springbootinit.generate;
import cn.hutool.core.io.FileUtil;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.io.FileWriter;
import java.io.Writer;
/**
* 代码生成器
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://www.code-nav.cn">编程导航学习圈</a>
*/
public class CodeGenerator {
/**
* 用法:修改生成参数和生成路径,注释掉不需要的生成逻辑,然后运行即可
*
* @param args
* @throws TemplateException
* @throws IOException
*/
public static void main(String[] args) throws TemplateException, IOException {
// 指定生成参数
String packageName = "com.yupi.springbootinit";
String dataName = "用户评论";
String dataKey = "userComment";
String upperDataKey = "UserComment";
// 封装生成参数
Map<String, Object> dataModel = new HashMap<>();
dataModel.put("packageName", packageName);
dataModel.put("dataName", dataName);
dataModel.put("dataKey", dataKey);
dataModel.put("upperDataKey", upperDataKey);
// 生成路径默认值
String projectPath = System.getProperty("user.dir");
// 参考路径,可以自己调整下面的 outputPath
String inputPath = projectPath + File.separator + "src/main/resources/templates/模板名称.java.ftl";
String outputPath = String.format("%s/generator/包名/%s类后缀.java", projectPath, upperDataKey);
// 1、生成 Controller
// 指定生成路径
inputPath = projectPath + File.separator + "src/main/resources/templates/TemplateController.java.ftl";
outputPath = String.format("%s/generator/controller/%sController.java", projectPath, upperDataKey);
// 生成
doGenerate(inputPath, outputPath, dataModel);
System.out.println("生成 Controller 成功,文件路径:" + outputPath);
// 2、生成 Service 接口和实现类
// 生成 Service 接口
inputPath = projectPath + File.separator + "src/main/resources/templates/TemplateService.java.ftl";
outputPath = String.format("%s/generator/service/%sService.java", projectPath, upperDataKey);
doGenerate(inputPath, outputPath, dataModel);
System.out.println("生成 Service 接口成功,文件路径:" + outputPath);
// 生成 Service 实现类
inputPath = projectPath + File.separator + "src/main/resources/templates/TemplateServiceImpl.java.ftl";
outputPath = String.format("%s/generator/service/impl/%sServiceImpl.java", projectPath, upperDataKey);
doGenerate(inputPath, outputPath, dataModel);
System.out.println("生成 Service 实现类成功,文件路径:" + outputPath);
// 3、生成数据模型封装类包括 DTO 和 VO
// 生成 DTO
inputPath = projectPath + File.separator + "src/main/resources/templates/model/TemplateAddRequest.java.ftl";
outputPath = String.format("%s/generator/model/dto/%sAddRequest.java", projectPath, upperDataKey);
doGenerate(inputPath, outputPath, dataModel);
inputPath = projectPath + File.separator + "src/main/resources/templates/model/TemplateQueryRequest.java.ftl";
outputPath = String.format("%s/generator/model/dto/%sQueryRequest.java", projectPath, upperDataKey);
doGenerate(inputPath, outputPath, dataModel);
inputPath = projectPath + File.separator + "src/main/resources/templates/model/TemplateEditRequest.java.ftl";
outputPath = String.format("%s/generator/model/dto/%sEditRequest.java", projectPath, upperDataKey);
doGenerate(inputPath, outputPath, dataModel);
inputPath = projectPath + File.separator + "src/main/resources/templates/model/TemplateUpdateRequest.java.ftl";
outputPath = String.format("%s/generator/model/dto/%sUpdateRequest.java", projectPath, upperDataKey);
doGenerate(inputPath, outputPath, dataModel);
System.out.println("生成 DTO 成功,文件路径:" + outputPath);
// 生成 VO
inputPath = projectPath + File.separator + "src/main/resources/templates/model/TemplateVO.java.ftl";
outputPath = String.format("%s/generator/model/vo/%sVO.java", projectPath, upperDataKey);
doGenerate(inputPath, outputPath, dataModel);
System.out.println("生成 VO 成功,文件路径:" + outputPath);
}
/**
* 生成文件
*
* @param inputPath 模板文件输入路径
* @param outputPath 输出路径
* @param model 数据模型
* @throws IOException
* @throws TemplateException
*/
public static void doGenerate(String inputPath, String outputPath, Object model) throws IOException, TemplateException {
// new 出 Configuration 对象,参数为 FreeMarker 版本号
Configuration configuration = new Configuration(Configuration.VERSION_2_3_31);
// 指定模板文件所在的路径
File templateDir = new File(inputPath).getParentFile();
configuration.setDirectoryForTemplateLoading(templateDir);
// 设置模板文件使用的字符集
configuration.setDefaultEncoding("utf-8");
// 创建模板对象,加载指定模板
String templateName = new File(inputPath).getName();
Template template = configuration.getTemplate(templateName);
// 文件不存在则创建文件和父目录
if (!FileUtil.exist(outputPath)) {
FileUtil.touch(outputPath);
}
// 生成
Writer out = new FileWriter(outputPath);
template.process(model, out);
// 生成文件后别忘了关闭哦
out.close();
}
}

View File

@@ -0,0 +1,27 @@
package com.yupi.springbootinit.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yupi.springbootinit.model.entity.NewHosts;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/*
* @author: ziin
* @date: 2025/6/10 18:54
*/
public interface NewHostsMapper extends BaseMapper<NewHosts> {
int deleteByPrimaryKey(Long id);
int insert(NewHosts record);
int insertSelective(NewHosts record);
NewHosts selectByPrimaryKey(Long id);
int updateByPrimaryKeySelective(NewHosts record);
int updateByPrimaryKey(NewHosts record);
int batchInsert(@Param("list") List<NewHosts> list);
}

View File

@@ -0,0 +1,88 @@
package com.yupi.springbootinit.model.dto.host;
import lombok.Data;
import java.util.Date;
/*
* @author: ziin
* @date: 2025/6/10 18:58
*/
@Data
public class HostInfoDTO {
/**
* 主键
*/
private Long id;
/**
* 主播id
*/
private String hostsId;
/**
* 主播等级
*/
private String hostsLevel;
/**
* 主播金币
*/
private Integer hostsCoins;
/**
* 邀请类型
*/
private Integer invitationType;
/**
* 粉丝数量
*/
private Integer fans;
/**
* 关注数量
*/
private Integer fllowernum;
/**
* 昨日金币
*/
private Integer yesterdayCoins;
/**
* 主播国家
*/
private String country;
/**
* 直播类型 娱乐,游戏
*/
private String hostsKind;
/**
* 租户 Id
*/
private Long tenantId;
/**
* 入库人
*/
private Integer creator;
/**
* 数据插入时间
*/
private Date createTime;
/**
* 更新人
*/
private String updater;
/**
* 更新时间
*/
private Date updateTime;
}

View File

@@ -0,0 +1,30 @@
package com.yupi.springbootinit.model.dto.user;
import lombok.Data;
/*
* @author: ziin
* @date: 2025/6/11 20:13
*/
/**
* 用户信息表
*/
@Data
public class SystemUsersDTO {
/**
* 用户账号
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 租户编号
*/
private Long tenantId;
}

View File

@@ -0,0 +1,90 @@
package com.yupi.springbootinit.model.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.util.Date;
/*
* @author: ziin
* @date: 2025/6/10 18:54
*/
@Data
public class NewHosts {
/**
* 主键
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 主播id
*/
private String hostsId;
/**
* 主播等级
*/
private String hostsLevel;
/**
* 主播金币
*/
private Integer hostsCoins;
/**
* 邀请类型
*/
private Integer invitationType;
/**
* 粉丝数量
*/
private Integer fans;
/**
* 关注数量
*/
private Integer fllowernum;
/**
* 昨日金币
*/
private Integer yesterdayCoins;
/**
* 主播国家
*/
private String country;
/**
* 直播类型 娱乐,游戏
*/
private String hostsKind;
/**
* 租户 Id
*/
private Long tenantId;
/**
* 入库人
*/
private Long creator;
/**
* 数据插入时间
*/
private Date createTime;
/**
* 更新人
*/
private String updater;
/**
* 更新时间
*/
private Date updateTime;
}

View File

@@ -0,0 +1,124 @@
package com.yupi.springbootinit.model.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import java.util.Date;
/*
* @author: ziin
* @date: 2025/6/11 20:13
*/
/**
* 用户信息表
*/
@Data
public class SystemUsers {
/**
* 用户ID
*/
private Long id;
/**
* 用户账号
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 用户昵称
*/
private String nickname;
/**
* 备注
*/
private String remark;
/**
* 部门ID
*/
@TableField("dept_id")
private Long deptId;
/**
* 岗位编号数组
*/
@TableField("post_ids")
private String postIds;
/**
* 用户邮箱
*/
private String email;
/**
* 手机号码
*/
private String mobile;
/**
* 用户性别
*/
private Byte sex;
/**
* 头像地址
*/
private String avatar;
/**
* 帐号状态0正常 1停用
*/
private Byte status;
/**
* 最后登录IP
*/
@TableField("login_ip")
private String loginIp;
/**
* 最后登录时间
*/
@TableField("login_date")
private Date loginDate;
/**
* 创建者
*/
private String creator;
/**
* 创建时间
*/
@TableField("create_time")
private Date createTime;
/**
* 更新者
*/
private String updater;
/**
* 更新时间
*/
@TableField("update_time")
private Date updateTime;
/**
* 是否删除
*/
private Boolean deleted;
/**
* 租户编号
*/
@TableField("tenant_id")
private Long tenantId;
}

View File

@@ -0,0 +1,62 @@
package com.yupi.springbootinit.model.enums;
import org.apache.commons.lang3.ObjectUtils;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* 文件上传业务类型枚举
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://yupi.icu">编程导航知识星球</a>
*/
public enum FileUploadBizEnum {
USER_AVATAR("用户头像", "user_avatar");
private final String text;
private final String value;
FileUploadBizEnum(String text, String value) {
this.text = text;
this.value = value;
}
/**
* 获取值列表
*
* @return
*/
public static List<String> getValues() {
return Arrays.stream(values()).map(item -> item.value).collect(Collectors.toList());
}
/**
* 根据 value 获取枚举
*
* @param value
* @return
*/
public static FileUploadBizEnum getEnumByValue(String value) {
if (ObjectUtils.isEmpty(value)) {
return null;
}
for (FileUploadBizEnum anEnum : FileUploadBizEnum.values()) {
if (anEnum.value.equals(value)) {
return anEnum;
}
}
return null;
}
public String getValue() {
return value;
}
public String getText() {
return text;
}
}

View File

@@ -0,0 +1,64 @@
package com.yupi.springbootinit.model.enums;
import org.apache.commons.lang3.ObjectUtils;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* 用户角色枚举
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://yupi.icu">编程导航知识星球</a>
*/
public enum UserRoleEnum {
USER("用户", "user"),
ADMIN("管理员", "admin"),
BAN("被封号", "ban");
private final String text;
private final String value;
UserRoleEnum(String text, String value) {
this.text = text;
this.value = value;
}
/**
* 获取值列表
*
* @return
*/
public static List<String> getValues() {
return Arrays.stream(values()).map(item -> item.value).collect(Collectors.toList());
}
/**
* 根据 value 获取枚举
*
* @param value
* @return
*/
public static UserRoleEnum getEnumByValue(String value) {
if (ObjectUtils.isEmpty(value)) {
return null;
}
for (UserRoleEnum anEnum : UserRoleEnum.values()) {
if (anEnum.value.equals(value)) {
return anEnum;
}
}
return null;
}
public String getValue() {
return value;
}
public String getText() {
return text;
}
}

View File

@@ -0,0 +1,81 @@
package com.yupi.springbootinit.model.vo.hosts;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.util.Date;
/*
* @author: ziin
* @date: 2025/6/10 18:54
*/
@Data
public class NewHostsVO {
/**
* 主键
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 主播id
*/
private String hostsId;
/**
* 主播等级
*/
private String hostsLevel;
/**
* 主播金币
*/
private Integer hostsCoins;
/**
* 邀请类型
*/
private Integer invitationType;
/**
* 粉丝数量
*/
private Integer fans;
/**
* 关注数量
*/
private Integer fllowernum;
/**
* 昨日金币
*/
private Integer yesterdayCoins;
/**
* 主播国家
*/
private String country;
/**
* 直播类型 娱乐,游戏
*/
private String hostsKind;
/**
* 租户 Id
*/
private Long tenantId;
/**
* 入库人
*/
private Long creator;
/**
* 数据插入时间
*/
private Date createTime;
}

View File

@@ -0,0 +1,30 @@
package com.yupi.springbootinit.model.vo.user;
import lombok.Data;
/*
* @author: ziin
* @date: 2025/6/11 20:13
*/
/**
* 用户信息表
*/
@Data
public class SystemUsersVO {
/**
* 用户ID
*/
private Long id;
/**
* 租户编号
*/
private Long tenantId;
private String username;
private String tokenName;
private String tokenValue;
}

View File

@@ -0,0 +1,56 @@
package com.yupi.springbootinit.rabbitMQ;
import cn.hutool.core.date.DateTime;
import com.rabbitmq.client.Channel;
import com.yupi.springbootinit.common.ErrorCode;
import com.yupi.springbootinit.exception.BusinessException;
import com.yupi.springbootinit.model.entity.NewHosts;
import com.yupi.springbootinit.service.HostInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;
@Service
@Slf4j
public class MQReceiver {
@Resource
private HostInfoService hostInfoService;
// //方法:接收消息
// @RabbitListener(queues = "HOST_INFO_QUEUE")
// public void receive(List<NewHosts> hosts, Channel channel, Message message) throws IOException {
// long deliveryTag = message.getMessageProperties().getDeliveryTag();
// try {
// hostInfoService.processHosts(hosts);
// channel.basicAck(deliveryTag,false);
// log.info("deliveryTag:{}",deliveryTag);
// log.info("接收到的消息------->" + hosts.size());
// }catch (Exception e){
// channel.basicNack(deliveryTag,false,true);
// log.error("消息消费失败------->消息内容大小{}",hosts.size() );
// }
// }
@RabbitListener(queues = "HOST_INFO_QUEUE")
public void receive(List<NewHosts> hosts, Channel channel, Message message) throws IOException {
long deliveryTag = message.getMessageProperties().getDeliveryTag();
try {
// 等待所有异步任务完成
hostInfoService.processHosts(hosts).join(); // 这里会抛出异常
channel.basicAck(deliveryTag, false);
log.info("deliveryTag:{}", deliveryTag);
log.info("{} 消息消费内容大小-------> {}",DateTime.now(),hosts.size());
} catch (Exception e) {
channel.basicNack(deliveryTag, false, false);
log.error("消息消费失败------->消息内容大小{}", hosts.size(), e);
throw new BusinessException(ErrorCode.QUEUE_CONSUMPTION_FAILURE);
}
}
}

View File

@@ -0,0 +1,35 @@
package com.yupi.springbootinit.rabbitMQ;
import cn.hutool.core.date.DateTime;
import com.yupi.springbootinit.common.ErrorCode;
import com.yupi.springbootinit.exception.BusinessException;
import com.yupi.springbootinit.model.entity.NewHosts;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Slf4j
@Service
public class MQSender {
@Resource
private RabbitTemplate rabbitTemplate;
//方法:发送消息
public void send(List<NewHosts> list){
try {
log.info("{} 接收到的消息数量----------->{}", DateTime.now(),list.size());
this.rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
//指定你队列的名字
rabbitTemplate.convertAndSend("HOST_INFO_QUEUE",list);
}catch (Exception e){
throw new BusinessException(ErrorCode.QUEUE_ERROR);
}
}
}

View File

@@ -0,0 +1,23 @@
package com.yupi.springbootinit.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yupi.springbootinit.model.dto.host.HostInfoDTO;
import com.yupi.springbootinit.model.entity.NewHosts;
import com.yupi.springbootinit.model.vo.hosts.NewHostsVO;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/*
* @author: ziin
* @date: 2025/6/10 19:04
*/
public interface HostInfoService extends IService<NewHosts> {
public CompletableFuture<Void> saveHostInfo(List<NewHosts> newHosts);
public CompletableFuture<Void> processHosts(List<NewHosts> hosts);
List<NewHostsVO> getConditionHosts(HostInfoDTO hostInfoDTO);
}

View File

@@ -0,0 +1,87 @@
package com.yupi.springbootinit.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.yupi.springbootinit.mapper.NewHostsMapper;
import com.yupi.springbootinit.model.dto.host.HostInfoDTO;
import com.yupi.springbootinit.model.entity.NewHosts;
import com.yupi.springbootinit.model.vo.hosts.NewHostsVO;
import com.yupi.springbootinit.service.HostInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StopWatch;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/*
* @author: ziin
* @date: 2025/6/10 19:04
*/
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class HostInfoServiceImpl extends ServiceImpl<NewHostsMapper, NewHosts> implements HostInfoService {
@Override
@Async("taskExecutor")
public CompletableFuture<Void> saveHostInfo(List<NewHosts> newHosts) {
try {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
saveBatch(newHosts);
stopWatch.stop();
long totalTimeMillis = stopWatch.getTotalTimeMillis();
log.info("存储花费: {}ms", totalTimeMillis);
return CompletableFuture.completedFuture(null);
} catch (Exception e) {
// 将异常包装到Future使调用方能处理
return CompletableFuture.failedFuture(e);
}
}
// public void processHosts(List<NewHosts> hosts) {
// List<CompletableFuture<Void>> futures = new ArrayList<>();
// // 分片提交(避免单批次过大)
// Lists.partition(hosts, 1500).forEach(batch -> {
// CompletableFuture<Void> future = this.saveHostInfo(batch);
// futures.add(future);
// });
// CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
// .whenComplete((result, ex) -> {
// if (ex != null) {
// log.error("部分批次处理失败", ex);
// } else {
// log.info("所有批次处理完成");
// }
// // 这里可以触发其他业务逻辑(如发送通知)
// });
// }
public CompletableFuture<Void> processHosts(List<NewHosts> hosts) {
List<CompletableFuture<Void>> futures = new ArrayList<>();
// 分片提交(避免单批次过大)
Lists.partition(hosts, 1500).forEach(batch -> {
log.info("当前存储数据量大小 {}", batch.size());
CompletableFuture<Void> future = this.saveHostInfo(batch);
futures.add(future);
});
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
.whenComplete((result, ex) -> {
if (ex != null) {
log.error("部分批次处理失败", ex);
} else {
log.info("所有批次处理完成");
}
});
}
@Override
public List<NewHostsVO> getConditionHosts(HostInfoDTO hostInfoDTO) {
return List.of();
}
}

View File

@@ -0,0 +1,55 @@
package com.yupi.springbootinit.utils;
import java.net.InetAddress;
import javax.servlet.http.HttpServletRequest;
/**
* 网络工具类
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://yupi.icu">编程导航知识星球</a>
*/
public class NetUtils {
/**
* 获取客户端 IP 地址
*
* @param request
* @return
*/
public static String getIpAddress(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
if (ip.equals("127.0.0.1")) {
// 根据网卡取本机配置的 IP
InetAddress inet = null;
try {
inet = InetAddress.getLocalHost();
} catch (Exception e) {
e.printStackTrace();
}
if (inet != null) {
ip = inet.getHostAddress();
}
}
}
// 多个代理的情况第一个IP为客户端真实IP,多个IP按照','分割
if (ip != null && ip.length() > 15) {
if (ip.indexOf(",") > 0) {
ip = ip.substring(0, ip.indexOf(","));
}
}
if (ip == null) {
return "127.0.0.1";
}
return ip;
}
}

View File

@@ -0,0 +1,57 @@
package com.yupi.springbootinit.utils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* Spring 上下文获取工具
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://yupi.icu">编程导航知识星球</a>
*/
@Component
public class SpringContextUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(@NotNull ApplicationContext applicationContext) throws BeansException {
SpringContextUtils.applicationContext = applicationContext;
}
/**
* 通过名称获取 Bean
*
* @param beanName
* @return
*/
public static Object getBean(String beanName) {
return applicationContext.getBean(beanName);
}
/**
* 通过 class 获取 Bean
*
* @param beanClass
* @param <T>
* @return
*/
public static <T> T getBean(Class<T> beanClass) {
return applicationContext.getBean(beanClass);
}
/**
* 通过名称和类型获取 Bean
*
* @param beanName
* @param beanClass
* @param <T>
* @return
*/
public static <T> T getBean(String beanName, Class<T> beanClass) {
return applicationContext.getBean(beanName, beanClass);
}
}

View File

@@ -0,0 +1,25 @@
package com.yupi.springbootinit.utils;
import org.apache.commons.lang3.StringUtils;
/**
* SQL 工具
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://yupi.icu">编程导航知识星球</a>
*/
public class SqlUtils {
/**
* 校验排序字段是否合法(防止 SQL 注入)
*
* @param sortField
* @return
*/
public static boolean validSortField(String sortField) {
if (StringUtils.isBlank(sortField)) {
return false;
}
return !StringUtils.containsAny(sortField, "=", "(", ")", " ");
}
}

View File

@@ -0,0 +1,34 @@
{
"properties": [
{
"name": "cos.client.accessKey",
"type": "java.lang.String",
"description": "Description for cos.client.accessKey."
},
{
"name": "cos.client.secretKey",
"type": "java.lang.String",
"description": "Description for cos.client.secretKey."
},
{
"name": "cos.client.region",
"type": "java.lang.String",
"description": "Description for cos.client.region."
},
{
"name": "cos.client.bucket",
"type": "java.lang.String",
"description": "Description for cos.client.bucket."
},
{
"name": "wx.open.appId",
"type": "java.lang.String",
"description": "Description for wx.open.appId."
},
{
"name": "wx.open.appSecret",
"type": "java.lang.String",
"description": "Description for wx.open.appSecret."
}
]
}

View File

@@ -0,0 +1,30 @@
# 测试配置文件
# @author <a href="https://github.com/liyupi">程序员鱼皮</a>
# @from <a href="https://yupi.icu">编程导航知识星球</a>
server:
port: 19665
spring:
# 数据库配置
# todo 需替换配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ruoyi-vue-pro?rewriteBatchedStatements=true
username: root
password: 123asd
# Redis 配置
# todo 需替换配置
redis:
database: 1
host: localhost
port: 6379
timeout: 5000
password: 123456
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
listener:
simple:
acknowledge-mode: manual

View File

@@ -0,0 +1,40 @@
# 线上配置文件
# @author <a href="https://github.com/liyupi">程序员鱼皮</a>
# @from <a href="https://yupi.icu">编程导航知识星球</a>
server:
port: 19665
spring:
# 数据库配置
# todo 需替换配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ruoyi-vue-pro?rewriteBatchedStatements=true
username: root
password: 123asd
# Redis 配置
# todo 需替换配置
redis:
database: 1
host: localhost
port: 6379
timeout: 5000
password: 123456
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
listener:
simple:
acknowledge-mode: manual
mybatis-plus:
configuration:
# 生产环境关闭日志
log-impl: ''
# 接口文档配置
knife4j:
basic:
enable: false
username: root
password: 123456

View File

@@ -0,0 +1,109 @@
# 公共配置文件
# @author <a href="https://github.com/liyupi">程序员鱼皮</a>
# @from <a href="https://yupi.icu">编程导航知识星球</a>
spring:
application:
name: springboot-init
# 默认 dev 环境
profiles:
active: dev
# 支持 swagger3
mvc:
pathmatch:
matching-strategy: ant_path_matcher
# session 配置
session:
# todo 取消注释开启分布式 session须先配置 Redis
# store-type: redis
# 30 天过期
timeout: 2592000
# 数据库配置
# todo 需替换配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/my_db
username: root
password: 123asd
jackson:
date-format: yyyy-MM-dd HH:mm:ss
servlet:
multipart:
# 大小限制
max-file-size: 10MB
server:
address: 0.0.0.0
port: 8101
servlet:
context-path: /api
# cookie 30 天过期
session:
cookie:
max-age: 2592000
mybatis-plus:
configuration:
map-underscore-to-camel-case: false
log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl
log-sql:
default-executor-type: batch
global-config:
db-config:
logic-delete-field: isDelete # 全局逻辑删除的实体字段名
logic-delete-value: 1 # 逻辑已删除值(默认为 1
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0
# 微信相关
wx:
# 微信公众平台
# todo 需替换配置
mp:
token: xxx
aesKey: xxx
appId: xxx
secret: xxx
config-storage:
http-client-type: HttpClient
key-prefix: wx
redis:
host: 127.0.0.1
port: 6379
type: Memory
# 微信开放平台
# todo 需替换配置
open:
appId: xxx
appSecret: xxx
# 对象存储
# todo 需替换配置
cos:
client:
accessKey: xxx
secretKey: xxx
region: xxx
bucket: xxx
# 接口文档配置
knife4j:
enable: true
openapi:
title: "接口文档"
version: 1.0
group:
default:
api-rule: package
api-rule-resources:
- com.yupi.springbootinit.controller
############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
sa-token:
# token 名称(同时也是 cookie 名称)
token-name: vvtoken
# token 有效期(单位:秒) 默认30天-1 代表永久有效
timeout: 2592000
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
active-timeout: -1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
is-concurrent: false
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token
is-share: false
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
token-style: random-128
# 是否输出操作日志
is-log: true

View File

@@ -0,0 +1,225 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yupi.springbootinit.mapper.NewHostsMapper">
<resultMap id="BaseResultMap" type="com.yupi.springbootinit.model.entity.NewHosts">
<!--@mbg.generated-->
<!--@Table new_hosts-->
<id column="id" jdbcType="BIGINT" property="id" />
<result column="hosts_id" jdbcType="VARCHAR" property="hostsId" />
<result column="hosts_level" jdbcType="VARCHAR" property="hostsLevel" />
<result column="hosts_coins" jdbcType="INTEGER" property="hostsCoins" />
<result column="Invitation_type" jdbcType="INTEGER" property="invitationType" />
<result column="fans" jdbcType="INTEGER" property="fans" />
<result column="fllowernum" jdbcType="INTEGER" property="fllowernum" />
<result column="yesterday_coins" jdbcType="INTEGER" property="yesterdayCoins" />
<result column="country" jdbcType="VARCHAR" property="country" />
<result column="hosts_kind" jdbcType="VARCHAR" property="hostsKind" />
<result column="tenant_id" jdbcType="BIGINT" property="tenantId" />
<result column="creator" jdbcType="BIGINT" property="creator" />
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
<result column="updater" jdbcType="VARCHAR" property="updater" />
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
</resultMap>
<sql id="Base_Column_List">
<!--@mbg.generated-->
id, hosts_id, hosts_level, hosts_coins, Invitation_type, fans, fllowernum, yesterday_coins,
country, hosts_kind, tenant_id, creator, create_time, updater, update_time
</sql>
<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
<!--@mbg.generated-->
select
<include refid="Base_Column_List" />
from new_hosts
where id = #{id,jdbcType=BIGINT}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
<!--@mbg.generated-->
delete from new_hosts
where id = #{id,jdbcType=BIGINT}
</delete>
<insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.yupi.springbootinit.model.entity.NewHosts" useGeneratedKeys="true">
<!--@mbg.generated-->
insert into new_hosts (hosts_id, hosts_level, hosts_coins,
Invitation_type, fans, fllowernum,
yesterday_coins, country, hosts_kind,
tenant_id, creator
)
values (#{hostsId,jdbcType=VARCHAR}, #{hostsLevel,jdbcType=VARCHAR}, #{hostsCoins,jdbcType=INTEGER},
#{invitationType,jdbcType=INTEGER}, #{fans,jdbcType=INTEGER}, #{fllowernum,jdbcType=INTEGER},
#{yesterdayCoins,jdbcType=INTEGER}, #{country,jdbcType=VARCHAR}, #{hostsKind,jdbcType=VARCHAR},
#{tenantId,jdbcType=BIGINT}, #{creator,jdbcType=BIGINT})
</insert>
<insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="com.yupi.springbootinit.model.entity.NewHosts" useGeneratedKeys="true">
<!--@mbg.generated-->
insert into new_hosts
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="hostsId != null">
hosts_id,
</if>
<if test="hostsLevel != null">
hosts_level,
</if>
<if test="hostsCoins != null">
hosts_coins,
</if>
<if test="invitationType != null">
Invitation_type,
</if>
<if test="fans != null">
fans,
</if>
<if test="fllowernum != null">
fllowernum,
</if>
<if test="yesterdayCoins != null">
yesterday_coins,
</if>
<if test="country != null">
country,
</if>
<if test="hostsKind != null">
hosts_kind,
</if>
<if test="tenantId != null">
tenant_id,
</if>
<if test="creator != null">
creator,
</if>
<if test="createTime != null">
create_time,
</if>
<if test="updater != null">
updater,
</if>
<if test="updateTime != null">
update_time,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="hostsId != null">
#{hostsId,jdbcType=VARCHAR},
</if>
<if test="hostsLevel != null">
#{hostsLevel,jdbcType=VARCHAR},
</if>
<if test="hostsCoins != null">
#{hostsCoins,jdbcType=INTEGER},
</if>
<if test="invitationType != null">
#{invitationType,jdbcType=INTEGER},
</if>
<if test="fans != null">
#{fans,jdbcType=INTEGER},
</if>
<if test="fllowernum != null">
#{fllowernum,jdbcType=INTEGER},
</if>
<if test="yesterdayCoins != null">
#{yesterdayCoins,jdbcType=INTEGER},
</if>
<if test="country != null">
#{country,jdbcType=VARCHAR},
</if>
<if test="hostsKind != null">
#{hostsKind,jdbcType=VARCHAR},
</if>
<if test="tenantId != null">
#{tenantId,jdbcType=BIGINT},
</if>
<if test="creator != null">
#{creator,jdbcType=BIGINT},
</if>
<if test="createTime != null">
#{createTime,jdbcType=TIMESTAMP},
</if>
<if test="updater != null">
#{updater,jdbcType=VARCHAR},
</if>
<if test="updateTime != null">
#{updateTime,jdbcType=TIMESTAMP},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="com.yupi.springbootinit.model.entity.NewHosts">
<!--@mbg.generated-->
update new_hosts
<set>
<if test="hostsId != null">
hosts_id = #{hostsId,jdbcType=VARCHAR},
</if>
<if test="hostsLevel != null">
hosts_level = #{hostsLevel,jdbcType=VARCHAR},
</if>
<if test="hostsCoins != null">
hosts_coins = #{hostsCoins,jdbcType=INTEGER},
</if>
<if test="invitationType != null">
Invitation_type = #{invitationType,jdbcType=INTEGER},
</if>
<if test="fans != null">
fans = #{fans,jdbcType=INTEGER},
</if>
<if test="fllowernum != null">
fllowernum = #{fllowernum,jdbcType=INTEGER},
</if>
<if test="yesterdayCoins != null">
yesterday_coins = #{yesterdayCoins,jdbcType=INTEGER},
</if>
<if test="country != null">
country = #{country,jdbcType=VARCHAR},
</if>
<if test="hostsKind != null">
hosts_kind = #{hostsKind,jdbcType=VARCHAR},
</if>
<if test="tenantId != null">
tenant_id = #{tenantId,jdbcType=BIGINT},
</if>
<if test="creator != null">
creator = #{creator,jdbcType=INTEGER},
</if>
<if test="createTime != null">
create_time = #{createTime,jdbcType=TIMESTAMP},
</if>
<if test="updater != null">
updater = #{updater,jdbcType=VARCHAR},
</if>
<if test="updateTime != null">
update_time = #{updateTime,jdbcType=TIMESTAMP},
</if>
</set>
where id = #{id,jdbcType=BIGINT}
</update>
<update id="updateByPrimaryKey" parameterType="com.yupi.springbootinit.model.entity.NewHosts">
<!--@mbg.generated-->
update new_hosts
set hosts_id = #{hostsId,jdbcType=VARCHAR},
hosts_level = #{hostsLevel,jdbcType=VARCHAR},
hosts_coins = #{hostsCoins,jdbcType=INTEGER},
Invitation_type = #{invitationType,jdbcType=INTEGER},
fans = #{fans,jdbcType=INTEGER},
fllowernum = #{fllowernum,jdbcType=INTEGER},
yesterday_coins = #{yesterdayCoins,jdbcType=INTEGER},
country = #{country,jdbcType=VARCHAR},
hosts_kind = #{hostsKind,jdbcType=VARCHAR},
tenant_id = #{tenantId,jdbcType=BIGINT},
creator = #{creator,jdbcType=INTEGER},
create_time = #{createTime,jdbcType=TIMESTAMP},
updater = #{updater,jdbcType=VARCHAR},
update_time = #{updateTime,jdbcType=TIMESTAMP}
where id = #{id,jdbcType=BIGINT}
</update>
<insert id="batchInsert" keyColumn="id" keyProperty="id" parameterType="map">
<!--@mbg.generated-->
insert into new_hosts
(hosts_id, hosts_level, hosts_coins, Invitation_type, fans, fllowernum, yesterday_coins,
country, hosts_kind, tenant_id, creator)
values
<foreach collection="list" item="item" separator=",">
(#{item.hostsId,jdbcType=VARCHAR}, #{item.hostsLevel,jdbcType=VARCHAR}, #{item.hostsCoins,jdbcType=INTEGER},
#{item.invitationType,jdbcType=INTEGER}, #{item.fans,jdbcType=INTEGER}, #{item.fllowernum,jdbcType=INTEGER},
#{item.yesterdayCoins,jdbcType=INTEGER}, #{item.country,jdbcType=VARCHAR}, #{item.hostsKind,jdbcType=VARCHAR},
#{item.tenantId,jdbcType=BIGINT}, #{item.creator,jdbcType=INTEGER})
</foreach>
</insert>
</mapper>

View File

@@ -0,0 +1,239 @@
package ${packageName}.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import ${packageName}.annotation.AuthCheck;
import ${packageName}.common.BaseResponse;
import ${packageName}.common.DeleteRequest;
import ${packageName}.common.ErrorCode;
import ${packageName}.common.ResultUtils;
import ${packageName}.constant.UserConstant;
import ${packageName}.exception.BusinessException;
import ${packageName}.exception.ThrowUtils;
import ${packageName}.model.dto.${dataKey}.${upperDataKey}AddRequest;
import ${packageName}.model.dto.${dataKey}.${upperDataKey}EditRequest;
import ${packageName}.model.dto.${dataKey}.${upperDataKey}QueryRequest;
import ${packageName}.model.dto.${dataKey}.${upperDataKey}UpdateRequest;
import ${packageName}.model.entity.${upperDataKey};
import ${packageName}.model.entity.User;
import ${packageName}.model.vo.${upperDataKey}VO;
import ${packageName}.service.${upperDataKey}Service;
import ${packageName}.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
/**
* ${dataName}接口
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://www.code-nav.cn">编程导航学习圈</a>
*/
@RestController
@RequestMapping("/${dataKey}")
@Slf4j
public class ${upperDataKey}Controller {
@Resource
private ${upperDataKey}Service ${dataKey}Service;
@Resource
private UserService userService;
// region 增删改查
/**
* 创建${dataName}
*
* @param ${dataKey}AddRequest
* @param request
* @return
*/
@PostMapping("/add")
public BaseResponse<Long> add${upperDataKey}(@RequestBody ${upperDataKey}AddRequest ${dataKey}AddRequest, HttpServletRequest request) {
ThrowUtils.throwIf(${dataKey}AddRequest == null, ErrorCode.PARAMS_ERROR);
// todo 在此处将实体类和 DTO 进行转换
${upperDataKey} ${dataKey} = new ${upperDataKey}();
BeanUtils.copyProperties(${dataKey}AddRequest, ${dataKey});
// 数据校验
${dataKey}Service.valid${upperDataKey}(${dataKey}, true);
// todo 填充默认值
User loginUser = userService.getLoginUser(request);
${dataKey}.setUserId(loginUser.getId());
// 写入数据库
boolean result = ${dataKey}Service.save(${dataKey});
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
// 返回新写入的数据 id
long new${upperDataKey}Id = ${dataKey}.getId();
return ResultUtils.success(new${upperDataKey}Id);
}
/**
* 删除${dataName}
*
* @param deleteRequest
* @param request
* @return
*/
@PostMapping("/delete")
public BaseResponse<Boolean> delete${upperDataKey}(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request) {
if (deleteRequest == null || deleteRequest.getId() <= 0) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
User user = userService.getLoginUser(request);
long id = deleteRequest.getId();
// 判断是否存在
${upperDataKey} old${upperDataKey} = ${dataKey}Service.getById(id);
ThrowUtils.throwIf(old${upperDataKey} == null, ErrorCode.NOT_FOUND_ERROR);
// 仅本人或管理员可删除
if (!old${upperDataKey}.getUserId().equals(user.getId()) && !userService.isAdmin(request)) {
throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
}
// 操作数据库
boolean result = ${dataKey}Service.removeById(id);
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
return ResultUtils.success(true);
}
/**
* 更新${dataName}(仅管理员可用)
*
* @param ${dataKey}UpdateRequest
* @return
*/
@PostMapping("/update")
@AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
public BaseResponse<Boolean> update${upperDataKey}(@RequestBody ${upperDataKey}UpdateRequest ${dataKey}UpdateRequest) {
if (${dataKey}UpdateRequest == null || ${dataKey}UpdateRequest.getId() <= 0) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
// todo 在此处将实体类和 DTO 进行转换
${upperDataKey} ${dataKey} = new ${upperDataKey}();
BeanUtils.copyProperties(${dataKey}UpdateRequest, ${dataKey});
// 数据校验
${dataKey}Service.valid${upperDataKey}(${dataKey}, false);
// 判断是否存在
long id = ${dataKey}UpdateRequest.getId();
${upperDataKey} old${upperDataKey} = ${dataKey}Service.getById(id);
ThrowUtils.throwIf(old${upperDataKey} == null, ErrorCode.NOT_FOUND_ERROR);
// 操作数据库
boolean result = ${dataKey}Service.updateById(${dataKey});
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
return ResultUtils.success(true);
}
/**
* 根据 id 获取${dataName}(封装类)
*
* @param id
* @return
*/
@GetMapping("/get/vo")
public BaseResponse<${upperDataKey}VO> get${upperDataKey}VOById(long id, HttpServletRequest request) {
ThrowUtils.throwIf(id <= 0, ErrorCode.PARAMS_ERROR);
// 查询数据库
${upperDataKey} ${dataKey} = ${dataKey}Service.getById(id);
ThrowUtils.throwIf(${dataKey} == null, ErrorCode.NOT_FOUND_ERROR);
// 获取封装类
return ResultUtils.success(${dataKey}Service.get${upperDataKey}VO(${dataKey}, request));
}
/**
* 分页获取${dataName}列表(仅管理员可用)
*
* @param ${dataKey}QueryRequest
* @return
*/
@PostMapping("/list/page")
@AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
public BaseResponse<Page<${upperDataKey}>> list${upperDataKey}ByPage(@RequestBody ${upperDataKey}QueryRequest ${dataKey}QueryRequest) {
long current = ${dataKey}QueryRequest.getCurrent();
long size = ${dataKey}QueryRequest.getPageSize();
// 查询数据库
Page<${upperDataKey}> ${dataKey}Page = ${dataKey}Service.page(new Page<>(current, size),
${dataKey}Service.getQueryWrapper(${dataKey}QueryRequest));
return ResultUtils.success(${dataKey}Page);
}
/**
* 分页获取${dataName}列表(封装类)
*
* @param ${dataKey}QueryRequest
* @param request
* @return
*/
@PostMapping("/list/page/vo")
public BaseResponse<Page<${upperDataKey}VO>> list${upperDataKey}VOByPage(@RequestBody ${upperDataKey}QueryRequest ${dataKey}QueryRequest,
HttpServletRequest request) {
long current = ${dataKey}QueryRequest.getCurrent();
long size = ${dataKey}QueryRequest.getPageSize();
// 限制爬虫
ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR);
// 查询数据库
Page<${upperDataKey}> ${dataKey}Page = ${dataKey}Service.page(new Page<>(current, size),
${dataKey}Service.getQueryWrapper(${dataKey}QueryRequest));
// 获取封装类
return ResultUtils.success(${dataKey}Service.get${upperDataKey}VOPage(${dataKey}Page, request));
}
/**
* 分页获取当前登录用户创建的${dataName}列表
*
* @param ${dataKey}QueryRequest
* @param request
* @return
*/
@PostMapping("/my/list/page/vo")
public BaseResponse<Page<${upperDataKey}VO>> listMy${upperDataKey}VOByPage(@RequestBody ${upperDataKey}QueryRequest ${dataKey}QueryRequest,
HttpServletRequest request) {
ThrowUtils.throwIf(${dataKey}QueryRequest == null, ErrorCode.PARAMS_ERROR);
// 补充查询条件,只查询当前登录用户的数据
User loginUser = userService.getLoginUser(request);
${dataKey}QueryRequest.setUserId(loginUser.getId());
long current = ${dataKey}QueryRequest.getCurrent();
long size = ${dataKey}QueryRequest.getPageSize();
// 限制爬虫
ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR);
// 查询数据库
Page<${upperDataKey}> ${dataKey}Page = ${dataKey}Service.page(new Page<>(current, size),
${dataKey}Service.getQueryWrapper(${dataKey}QueryRequest));
// 获取封装类
return ResultUtils.success(${dataKey}Service.get${upperDataKey}VOPage(${dataKey}Page, request));
}
/**
* 编辑${dataName}(给用户使用)
*
* @param ${dataKey}EditRequest
* @param request
* @return
*/
@PostMapping("/edit")
public BaseResponse<Boolean> edit${upperDataKey}(@RequestBody ${upperDataKey}EditRequest ${dataKey}EditRequest, HttpServletRequest request) {
if (${dataKey}EditRequest == null || ${dataKey}EditRequest.getId() <= 0) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
// todo 在此处将实体类和 DTO 进行转换
${upperDataKey} ${dataKey} = new ${upperDataKey}();
BeanUtils.copyProperties(${dataKey}EditRequest, ${dataKey});
// 数据校验
${dataKey}Service.valid${upperDataKey}(${dataKey}, false);
User loginUser = userService.getLoginUser(request);
// 判断是否存在
long id = ${dataKey}EditRequest.getId();
${upperDataKey} old${upperDataKey} = ${dataKey}Service.getById(id);
ThrowUtils.throwIf(old${upperDataKey} == null, ErrorCode.NOT_FOUND_ERROR);
// 仅本人或管理员可编辑
if (!old${upperDataKey}.getUserId().equals(loginUser.getId()) && !userService.isAdmin(loginUser)) {
throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
}
// 操作数据库
boolean result = ${dataKey}Service.updateById(${dataKey});
ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
return ResultUtils.success(true);
}
// endregion
}

View File

@@ -0,0 +1,53 @@
package ${packageName}.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import ${packageName}.model.dto.${dataKey}.${upperDataKey}QueryRequest;
import ${packageName}.model.entity.${upperDataKey};
import ${packageName}.model.vo.${upperDataKey}VO;
import javax.servlet.http.HttpServletRequest;
/**
* ${dataName}服务
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://www.code-nav.cn">编程导航学习圈</a>
*/
public interface ${upperDataKey}Service extends IService<${upperDataKey}> {
/**
* 校验数据
*
* @param ${dataKey}
* @param add 对创建的数据进行校验
*/
void valid${upperDataKey}(${upperDataKey} ${dataKey}, boolean add);
/**
* 获取查询条件
*
* @param ${dataKey}QueryRequest
* @return
*/
QueryWrapper<${upperDataKey}> getQueryWrapper(${upperDataKey}QueryRequest ${dataKey}QueryRequest);
/**
* 获取${dataName}封装
*
* @param ${dataKey}
* @param request
* @return
*/
${upperDataKey}VO get${upperDataKey}VO(${upperDataKey} ${dataKey}, HttpServletRequest request);
/**
* 分页获取${dataName}封装
*
* @param ${dataKey}Page
* @param request
* @return
*/
Page<${upperDataKey}VO> get${upperDataKey}VOPage(Page<${upperDataKey}> ${dataKey}Page, HttpServletRequest request);
}

View File

@@ -0,0 +1,224 @@
package ${packageName}.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import ${packageName}.common.ErrorCode;
import ${packageName}.constant.CommonConstant;
import ${packageName}.exception.ThrowUtils;
import ${packageName}.mapper.${upperDataKey}Mapper;
import ${packageName}.model.dto.${dataKey}.${upperDataKey}QueryRequest;
import ${packageName}.model.entity.${upperDataKey};
import ${packageName}.model.entity.${upperDataKey}Favour;
import ${packageName}.model.entity.${upperDataKey}Thumb;
import ${packageName}.model.entity.User;
import ${packageName}.model.vo.${upperDataKey}VO;
import ${packageName}.model.vo.UserVO;
import ${packageName}.service.${upperDataKey}Service;
import ${packageName}.service.UserService;
import ${packageName}.utils.SqlUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* ${dataName}服务实现
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://www.code-nav.cn">编程导航学习圈</a>
*/
@Service
@Slf4j
public class ${upperDataKey}ServiceImpl extends ServiceImpl<${upperDataKey}Mapper, ${upperDataKey}> implements ${upperDataKey}Service {
@Resource
private UserService userService;
/**
* 校验数据
*
* @param ${dataKey}
* @param add 对创建的数据进行校验
*/
@Override
public void valid${upperDataKey}(${upperDataKey} ${dataKey}, boolean add) {
ThrowUtils.throwIf(${dataKey} == null, ErrorCode.PARAMS_ERROR);
// todo 从对象中取值
String title = ${dataKey}.getTitle();
// 创建数据时,参数不能为空
if (add) {
// todo 补充校验规则
ThrowUtils.throwIf(StringUtils.isBlank(title), ErrorCode.PARAMS_ERROR);
}
// 修改数据时,有参数则校验
// todo 补充校验规则
if (StringUtils.isNotBlank(title)) {
ThrowUtils.throwIf(title.length() > 80, ErrorCode.PARAMS_ERROR, "标题过长");
}
}
/**
* 获取查询条件
*
* @param ${dataKey}QueryRequest
* @return
*/
@Override
public QueryWrapper<${upperDataKey}> getQueryWrapper(${upperDataKey}QueryRequest ${dataKey}QueryRequest) {
QueryWrapper<${upperDataKey}> queryWrapper = new QueryWrapper<>();
if (${dataKey}QueryRequest == null) {
return queryWrapper;
}
// todo 从对象中取值
Long id = ${dataKey}QueryRequest.getId();
Long notId = ${dataKey}QueryRequest.getNotId();
String title = ${dataKey}QueryRequest.getTitle();
String content = ${dataKey}QueryRequest.getContent();
String searchText = ${dataKey}QueryRequest.getSearchText();
String sortField = ${dataKey}QueryRequest.getSortField();
String sortOrder = ${dataKey}QueryRequest.getSortOrder();
List<String> tagList = ${dataKey}QueryRequest.getTags();
Long userId = ${dataKey}QueryRequest.getUserId();
// todo 补充需要的查询条件
// 从多字段中搜索
if (StringUtils.isNotBlank(searchText)) {
// 需要拼接查询条件
queryWrapper.and(qw -> qw.like("title", searchText).or().like("content", searchText));
}
// 模糊查询
queryWrapper.like(StringUtils.isNotBlank(title), "title", title);
queryWrapper.like(StringUtils.isNotBlank(content), "content", content);
// JSON 数组查询
if (CollUtil.isNotEmpty(tagList)) {
for (String tag : tagList) {
queryWrapper.like("tags", "\"" + tag + "\"");
}
}
// 精确查询
queryWrapper.ne(ObjectUtils.isNotEmpty(notId), "id", notId);
queryWrapper.eq(ObjectUtils.isNotEmpty(id), "id", id);
queryWrapper.eq(ObjectUtils.isNotEmpty(userId), "userId", userId);
// 排序规则
queryWrapper.orderBy(SqlUtils.validSortField(sortField),
sortOrder.equals(CommonConstant.SORT_ORDER_ASC),
sortField);
return queryWrapper;
}
/**
* 获取${dataName}封装
*
* @param ${dataKey}
* @param request
* @return
*/
@Override
public ${upperDataKey}VO get${upperDataKey}VO(${upperDataKey} ${dataKey}, HttpServletRequest request) {
// 对象转封装类
${upperDataKey}VO ${dataKey}VO = ${upperDataKey}VO.objToVo(${dataKey});
// todo 可以根据需要为封装对象补充值,不需要的内容可以删除
// region 可选
// 1. 关联查询用户信息
Long userId = ${dataKey}.getUserId();
User user = null;
if (userId != null && userId > 0) {
user = userService.getById(userId);
}
UserVO userVO = userService.getUserVO(user);
${dataKey}VO.setUser(userVO);
// 2. 已登录,获取用户点赞、收藏状态
long ${dataKey}Id = ${dataKey}.getId();
User loginUser = userService.getLoginUserPermitNull(request);
if (loginUser != null) {
// 获取点赞
QueryWrapper<${upperDataKey}Thumb> ${dataKey}ThumbQueryWrapper = new QueryWrapper<>();
${dataKey}ThumbQueryWrapper.in("${dataKey}Id", ${dataKey}Id);
${dataKey}ThumbQueryWrapper.eq("userId", loginUser.getId());
${upperDataKey}Thumb ${dataKey}Thumb = ${dataKey}ThumbMapper.selectOne(${dataKey}ThumbQueryWrapper);
${dataKey}VO.setHasThumb(${dataKey}Thumb != null);
// 获取收藏
QueryWrapper<${upperDataKey}Favour> ${dataKey}FavourQueryWrapper = new QueryWrapper<>();
${dataKey}FavourQueryWrapper.in("${dataKey}Id", ${dataKey}Id);
${dataKey}FavourQueryWrapper.eq("userId", loginUser.getId());
${upperDataKey}Favour ${dataKey}Favour = ${dataKey}FavourMapper.selectOne(${dataKey}FavourQueryWrapper);
${dataKey}VO.setHasFavour(${dataKey}Favour != null);
}
// endregion
return ${dataKey}VO;
}
/**
* 分页获取${dataName}封装
*
* @param ${dataKey}Page
* @param request
* @return
*/
@Override
public Page<${upperDataKey}VO> get${upperDataKey}VOPage(Page<${upperDataKey}> ${dataKey}Page, HttpServletRequest request) {
List<${upperDataKey}> ${dataKey}List = ${dataKey}Page.getRecords();
Page<${upperDataKey}VO> ${dataKey}VOPage = new Page<>(${dataKey}Page.getCurrent(), ${dataKey}Page.getSize(), ${dataKey}Page.getTotal());
if (CollUtil.isEmpty(${dataKey}List)) {
return ${dataKey}VOPage;
}
// 对象列表 => 封装对象列表
List<${upperDataKey}VO> ${dataKey}VOList = ${dataKey}List.stream().map(${dataKey} -> {
return ${upperDataKey}VO.objToVo(${dataKey});
}).collect(Collectors.toList());
// todo 可以根据需要为封装对象补充值,不需要的内容可以删除
// region 可选
// 1. 关联查询用户信息
Set<Long> userIdSet = ${dataKey}List.stream().map(${upperDataKey}::getUserId).collect(Collectors.toSet());
Map<Long, List<User>> userIdUserListMap = userService.listByIds(userIdSet).stream()
.collect(Collectors.groupingBy(User::getId));
// 2. 已登录,获取用户点赞、收藏状态
Map<Long, Boolean> ${dataKey}IdHasThumbMap = new HashMap<>();
Map<Long, Boolean> ${dataKey}IdHasFavourMap = new HashMap<>();
User loginUser = userService.getLoginUserPermitNull(request);
if (loginUser != null) {
Set<Long> ${dataKey}IdSet = ${dataKey}List.stream().map(${upperDataKey}::getId).collect(Collectors.toSet());
loginUser = userService.getLoginUser(request);
// 获取点赞
QueryWrapper<${upperDataKey}Thumb> ${dataKey}ThumbQueryWrapper = new QueryWrapper<>();
${dataKey}ThumbQueryWrapper.in("${dataKey}Id", ${dataKey}IdSet);
${dataKey}ThumbQueryWrapper.eq("userId", loginUser.getId());
List<${upperDataKey}Thumb> ${dataKey}${upperDataKey}ThumbList = ${dataKey}ThumbMapper.selectList(${dataKey}ThumbQueryWrapper);
${dataKey}${upperDataKey}ThumbList.forEach(${dataKey}${upperDataKey}Thumb -> ${dataKey}IdHasThumbMap.put(${dataKey}${upperDataKey}Thumb.get${upperDataKey}Id(), true));
// 获取收藏
QueryWrapper<${upperDataKey}Favour> ${dataKey}FavourQueryWrapper = new QueryWrapper<>();
${dataKey}FavourQueryWrapper.in("${dataKey}Id", ${dataKey}IdSet);
${dataKey}FavourQueryWrapper.eq("userId", loginUser.getId());
List<${upperDataKey}Favour> ${dataKey}FavourList = ${dataKey}FavourMapper.selectList(${dataKey}FavourQueryWrapper);
${dataKey}FavourList.forEach(${dataKey}Favour -> ${dataKey}IdHasFavourMap.put(${dataKey}Favour.get${upperDataKey}Id(), true));
}
// 填充信息
${dataKey}VOList.forEach(${dataKey}VO -> {
Long userId = ${dataKey}VO.getUserId();
User user = null;
if (userIdUserListMap.containsKey(userId)) {
user = userIdUserListMap.get(userId).get(0);
}
${dataKey}VO.setUser(userService.getUserVO(user));
${dataKey}VO.setHasThumb(${dataKey}IdHasThumbMap.getOrDefault(${dataKey}VO.getId(), false));
${dataKey}VO.setHasFavour(${dataKey}IdHasFavourMap.getOrDefault(${dataKey}VO.getId(), false));
});
// endregion
${dataKey}VOPage.setRecords(${dataKey}VOList);
return ${dataKey}VOPage;
}
}

View File

@@ -0,0 +1,33 @@
package ${packageName}.model.dto.${dataKey};
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 创建${dataName}请求
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://www.code-nav.cn">编程导航学习圈</a>
*/
@Data
public class ${upperDataKey}AddRequest implements Serializable {
/**
* 标题
*/
private String title;
/**
* 内容
*/
private String content;
/**
* 标签列表
*/
private List<String> tags;
private static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,38 @@
package ${packageName}.model.dto.${dataKey};
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 编辑${dataName}请求
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://www.code-nav.cn">编程导航学习圈</a>
*/
@Data
public class ${upperDataKey}EditRequest implements Serializable {
/**
* id
*/
private Long id;
/**
* 标题
*/
private String title;
/**
* 内容
*/
private String content;
/**
* 标签列表
*/
private List<String> tags;
private static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,56 @@
package ${packageName}.model.dto.${dataKey};
import ${packageName}.common.PageRequest;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.List;
/**
* 查询${dataName}请求
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://www.code-nav.cn">编程导航学习圈</a>
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class ${upperDataKey}QueryRequest extends PageRequest implements Serializable {
/**
* id
*/
private Long id;
/**
* id
*/
private Long notId;
/**
* 搜索词
*/
private String searchText;
/**
* 标题
*/
private String title;
/**
* 内容
*/
private String content;
/**
* 标签列表
*/
private List<String> tags;
/**
* 创建用户 id
*/
private Long userId;
private static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,38 @@
package ${packageName}.model.dto.${dataKey};
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 更新${dataName}请求
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://www.code-nav.cn">编程导航学习圈</a>
*/
@Data
public class ${upperDataKey}UpdateRequest implements Serializable {
/**
* id
*/
private Long id;
/**
* 标题
*/
private String title;
/**
* 内容
*/
private String content;
/**
* 标签列表
*/
private List<String> tags;
private static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,93 @@
package ${packageName}.model.vo;
import cn.hutool.json.JSONUtil;
import ${packageName}.model.entity.${upperDataKey};
import lombok.Data;
import org.springframework.beans.BeanUtils;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* ${dataName}视图
*
* @author <a href="https://github.com/liyupi">程序员鱼皮</a>
* @from <a href="https://www.code-nav.cn">编程导航学习圈</a>
*/
@Data
public class ${upperDataKey}VO implements Serializable {
/**
* id
*/
private Long id;
/**
* 标题
*/
private String title;
/**
* 内容
*/
private String content;
/**
* 创建用户 id
*/
private Long userId;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
/**
* 标签列表
*/
private List<String> tagList;
/**
* 创建用户信息
*/
private UserVO user;
/**
* 封装类转对象
*
* @param ${dataKey}VO
* @return
*/
public static ${upperDataKey} voToObj(${upperDataKey}VO ${dataKey}VO) {
if (${dataKey}VO == null) {
return null;
}
${upperDataKey} ${dataKey} = new ${upperDataKey}();
BeanUtils.copyProperties(${dataKey}VO, ${dataKey});
List<String> tagList = ${dataKey}VO.getTagList();
${dataKey}.setTags(JSONUtil.toJsonStr(tagList));
return ${dataKey};
}
/**
* 对象转封装类
*
* @param ${dataKey}
* @return
*/
public static ${upperDataKey}VO objToVo(${upperDataKey} ${dataKey}) {
if (${dataKey} == null) {
return null;
}
${upperDataKey}VO ${dataKey}VO = new ${upperDataKey}VO();
BeanUtils.copyProperties(${dataKey}, ${dataKey}VO);
${dataKey}VO.setTagList(JSONUtil.toList(${dataKey}.getTags(), String.class));
return ${dataKey}VO;
}
}

Binary file not shown.