项目初次提交
This commit is contained in:
27
src/main/java/com/yupi/springbootinit/MainApplication.java
Normal file
27
src/main/java/com/yupi/springbootinit/MainApplication.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 "";
|
||||
|
||||
}
|
||||
|
||||
@@ -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 start,id: {}, 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
47
src/main/java/com/yupi/springbootinit/common/ErrorCode.java
Normal file
47
src/main/java/com/yupi/springbootinit/common/ErrorCode.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
28
src/main/java/com/yupi/springbootinit/config/CorsConfig.java
Normal file
28
src/main/java/com/yupi/springbootinit/config/CorsConfig.java
Normal 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("*");
|
||||
}
|
||||
}
|
||||
31
src/main/java/com/yupi/springbootinit/config/JsonConfig.java
Normal file
31
src/main/java/com/yupi/springbootinit/config/JsonConfig.java
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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";
|
||||
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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, "系统错误");
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
35
src/main/java/com/yupi/springbootinit/rabbitMQ/MQSender.java
Normal file
35
src/main/java/com/yupi/springbootinit/rabbitMQ/MQSender.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
55
src/main/java/com/yupi/springbootinit/utils/NetUtils.java
Normal file
55
src/main/java/com/yupi/springbootinit/utils/NetUtils.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
25
src/main/java/com/yupi/springbootinit/utils/SqlUtils.java
Normal file
25
src/main/java/com/yupi/springbootinit/utils/SqlUtils.java
Normal 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, "=", "(", ")", " ");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user