Commit 91401ea615b3950d33148642655348596478e5c7

Authored by 谢茂盛
1 parent 62dd484b

feat:定时任务项目

Showing 57 changed files with 4804 additions and 0 deletions

Too many changes to show.

To preserve performance only 57 of 59 files are displayed.

job/Dockerfile 0 → 100644
  1 +# 使用官方 OpenJDK 8 映像作为基础镜像
  2 +FROM openjdk:8-jdk-alpine
  3 +
  4 +# 将当前目录下的所有 jar 包复制到容器中的 /app 目录下
  5 +COPY *.jar /app/
  6 +
  7 +# 设置容器启动时执行的命令
  8 +CMD ["java", "-jar", "/app/job.services-1.0-SNAPSHOT.jar"]
... ...
job/docker-compose.yml 0 → 100644
  1 +version: "3"
  2 +
  3 +services:
  4 + # 定义 Spring Boot 应用程序所需要的服务(容器)
  5 + shop:
  6 + # 构建镜像的路径。"." 表示 Dockerfile 文件所在的当前目录
  7 + build: ..
  8 + # 指定容器名称
  9 + container_name: job
  10 + # 容器所要使用的端口号
  11 + ports:
  12 + - "9000:9000"
0 13 \ No newline at end of file
... ...
job/pom.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <parent>
  6 + <artifactId>canrd-services</artifactId>
  7 + <groupId>com.canrd.shop</groupId>
  8 + <version>1.0-SNAPSHOT</version>
  9 + </parent>
  10 + <modelVersion>4.0.0</modelVersion>
  11 +
  12 + <artifactId>job</artifactId>
  13 +
  14 + <dependencies>
  15 + <dependency>
  16 + <groupId>org.springframework.boot</groupId>
  17 + <artifactId>spring-boot-starter-web</artifactId>
  18 + <!-- <version>2.2.5.RELEASE</version>-->
  19 + <exclusions>
  20 + <exclusion>
  21 + <groupId>org.springframework.boot</groupId>
  22 + <artifactId>spring-boot-starter-logging</artifactId>
  23 + </exclusion>
  24 + </exclusions>
  25 + </dependency>
  26 +
  27 + <!-- Lombok 依赖-->
  28 + <dependency>
  29 + <groupId>org.projectlombok</groupId>
  30 + <artifactId>lombok</artifactId>
  31 + <version>1.18.12</version>
  32 + <optional>true</optional>
  33 + </dependency>
  34 + <dependency>
  35 + <groupId>org.springframework.boot</groupId>
  36 + <artifactId>spring-boot-starter-aop</artifactId>
  37 + </dependency>
  38 + <dependency>
  39 + <groupId>org.springframework.boot</groupId>
  40 + <artifactId>spring-boot-starter-test</artifactId>
  41 + <scope>test</scope>
  42 + </dependency>
  43 +
  44 + <dependency>
  45 + <groupId>com.baomidou</groupId>
  46 + <artifactId>mybatis-plus-boot-starter</artifactId>
  47 + </dependency>
  48 + <!-- <dependency>-->
  49 + <!-- <groupId>com.baomidou</groupId>-->
  50 + <!-- <artifactId>dynamic-datasource-spring-boot-starter</artifactId>-->
  51 + <!-- </dependency>-->
  52 + <dependency>
  53 + <groupId>mysql</groupId>
  54 + <artifactId>mysql-connector-java</artifactId>
  55 + </dependency>
  56 + <dependency>
  57 + <groupId>com.alibaba</groupId>
  58 + <artifactId>druid-spring-boot-starter</artifactId>
  59 + </dependency>
  60 +
  61 + <dependency>
  62 + <groupId>org.springframework.boot</groupId>
  63 + <artifactId>spring-boot-starter-log4j2</artifactId>
  64 + </dependency>
  65 +
  66 +
  67 + <dependency>
  68 + <groupId>com.alibaba</groupId>
  69 + <artifactId>fastjson</artifactId>
  70 + </dependency>
  71 +
  72 + <dependency>
  73 + <groupId>cn.hutool</groupId>
  74 + <artifactId>hutool-crypto</artifactId>
  75 + </dependency>
  76 +
  77 + <dependency>
  78 + <groupId>org.apache.commons</groupId>
  79 + <artifactId>commons-pool2</artifactId>
  80 + </dependency>
  81 + <dependency>
  82 + <groupId>org.apache.commons</groupId>
  83 + <artifactId>commons-lang3</artifactId>
  84 + </dependency>
  85 +
  86 +
  87 + <!--工具包-->
  88 + <dependency>
  89 + <groupId>cn.hutool</groupId>
  90 + <artifactId>hutool-all</artifactId>
  91 + </dependency>
  92 +
  93 + <dependency>
  94 + <groupId>joda-time</groupId>
  95 + <artifactId>joda-time</artifactId>
  96 + </dependency>
  97 + <dependency>
  98 + <groupId>com.google.guava</groupId>
  99 + <artifactId>guava</artifactId>
  100 + </dependency>
  101 + </dependencies>
  102 + <build>
  103 + <finalName>job.services-1.0-SNAPSHOT</finalName>
  104 + <plugins>
  105 + <plugin>
  106 + <groupId>org.apache.maven.plugins</groupId>
  107 + <artifactId>maven-source-plugin</artifactId>
  108 + </plugin>
  109 +
  110 + <plugin>
  111 + <groupId>org.springframework.boot</groupId>
  112 + <artifactId>spring-boot-maven-plugin</artifactId>
  113 + <configuration>
  114 + <executable>true</executable>
  115 + </configuration>
  116 + </plugin>
  117 +
  118 + </plugins>
  119 + </build>
  120 +</project>
0 121 \ No newline at end of file
... ...
job/src/main/java/com/canrd/shop/JobApplication.java 0 → 100644
  1 +package com.canrd.shop;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.DbType;
  4 +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
  5 +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
  6 +import com.canrd.shop.common.Path;
  7 +import org.mybatis.spring.annotation.MapperScan;
  8 +import org.springframework.boot.SpringApplication;
  9 +import org.springframework.boot.autoconfigure.SpringBootApplication;
  10 +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
  11 +import org.springframework.context.annotation.Bean;
  12 +import org.springframework.scheduling.annotation.EnableScheduling;
  13 +import org.springframework.transaction.annotation.EnableTransactionManagement;
  14 +
  15 +/**
  16 + * @author: xms
  17 + * @description: 管理后台启动
  18 + * @date: 2023/3/29 18:00
  19 + * @version: 1.0
  20 + */
  21 +@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}, scanBasePackages = {"com.canrd.shop"})
  22 +@MapperScan("com.canrd.shop.**.mapper")
  23 +@EnableScheduling
  24 +@EnableTransactionManagement
  25 +public class JobApplication {
  26 +
  27 + private static void setLogPath() {
  28 + String appPath = Path.getAppPath(JobApplication.class);
  29 + System.setProperty("logging.path", appPath);
  30 + }
  31 +
  32 + public static void main(String[] args) {
  33 + setLogPath();
  34 + SpringApplication.run(JobApplication.class, args);
  35 + }
  36 +
  37 + /**
  38 + * 分页插件
  39 + *
  40 + * @return
  41 + */
  42 + @Bean
  43 + public MybatisPlusInterceptor mybatisPlusInterceptor() {
  44 + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
  45 + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
  46 + return interceptor;
  47 + }
  48 +}
... ...
job/src/main/java/com/canrd/shop/common/Path.java 0 → 100644
  1 +package com.canrd.shop.common;
  2 +
  3 +
  4 +import com.canrd.shop.common.constant.Constant;
  5 +
  6 +/**
  7 + * @author xms
  8 + */
  9 +public class Path {
  10 + /**
  11 + * 获取程序启动路径
  12 + *
  13 + * @param cls,建议直接传 ServiceApplication.class
  14 + * @return 应用启动路径
  15 + */
  16 + public static String getAppPath(Class cls) {
  17 + String path = cls.getResource(Constant.SLASH_MARK_CHARACTER).getPath();
  18 + String os = System.getProperty("os.name").toLowerCase();
  19 + final String OSWINDOW = "windows";
  20 + if (os.indexOf(OSWINDOW) != -1 && path.length() > 1) {
  21 + //windows路径样例: /D:/work/code/shop-services/online-shop-oss/target/classes/
  22 + return path.substring(1);
  23 + }
  24 +
  25 + //linux 路径样例 file:/opt/target/online-shop-oss-SNAPSHOT.jar!/BOOT-INF/classes!/";
  26 + final String FILE = "file:";
  27 + if (path.indexOf(FILE) != -1) {
  28 + path = path.substring(FILE.length());
  29 + }
  30 +
  31 + int pos = -1;
  32 + if ((pos = path.indexOf(Constant.EXCLAMATION_MARK_CHARACTER)) != -1) {
  33 + if (-1 != (pos = path.lastIndexOf(Constant.SLASH_MARK_CHARACTER, pos))) {
  34 + path = path.substring(0, pos + 1);
  35 + }
  36 + }
  37 +
  38 + return path;
  39 + }
  40 +}
... ...
job/src/main/java/com/canrd/shop/common/constant/Constant.java 0 → 100644
  1 +package com.canrd.shop.common.constant;
  2 +
  3 +import java.util.Arrays;
  4 +import java.util.List;
  5 +
  6 +public class Constant {
  7 + /**
  8 + * 分隔符英文的横杠
  9 + */
  10 + public static final String CROSS_BAR_CHARACTER = "-";
  11 + /**
  12 + * 英文的 .
  13 + */
  14 + public static final String POINT_BAR_CHARACTER = ".";
  15 + /**
  16 + * 英文的 !
  17 + */
  18 + public static final String EXCLAMATION_MARK_CHARACTER = "!";
  19 + /**
  20 + * 英文的 /
  21 + */
  22 + public static final String SLASH_MARK_CHARACTER = "/";
  23 + /**
  24 + * 英文的 :
  25 + */
  26 + public static final String COLON_CHARACTER = ":";
  27 +
  28 + /**
  29 + * 英文的 ;
  30 + */
  31 + public static final String SEMICOLON_CHARACTER = ";";
  32 +
  33 + /**
  34 + * 英文的逗号
  35 + */
  36 + public static final String COMMA_CHARACTER = ",";
  37 + /**
  38 + * 英文的*号
  39 + */
  40 + public static final String START_CHARACTER = "*";
  41 + /**
  42 + * 分隔符
  43 + */
  44 + public static final String SPLIT_SYMBOL = ",|,";
  45 +
  46 + /**
  47 + * 特殊分隔符 _
  48 + */
  49 + public static final String SPECIAL_KEY = "_";
  50 +
  51 +
  52 + /**
  53 + * 括号
  54 + */
  55 + public static final String BRACKETS_RIGHT = "]";
  56 + /**
  57 + * 括号
  58 + */
  59 + public static final String BRACKETS_LEFT = "[";
  60 +
  61 + /**
  62 + * 手机号码正则校验
  63 + */
  64 + public static final String PHONE_REGEXP = "^[1][3,4,5,6,7,8,9][0-9]{9}$";
  65 +
  66 + /**
  67 + * 脱敏手机号
  68 + */
  69 + public static final String PHONE_DESENSITIZATION_REGEXP = "^[1][3,4,5,6,7,8,9][0-9][*]{4}[0-9]{4}$";
  70 +
  71 + /**
  72 + * 邮箱
  73 + */
  74 + public static final String EMAIL_REGEXP = "^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$";
  75 +
  76 + /**
  77 + * 三位数字
  78 + */
  79 + public static final String THREE_DIGITS_REGEXP = "\\d{3}";
  80 +
  81 + /**
  82 + * 中文 英文 数字
  83 + */
  84 + public static final String CHI_EN_NUM_REGEXP = "^[A-z0-9\\u4e00-\\u9fa5]*$";
  85 +
  86 +
  87 + /**
  88 + * 仅包含英文和数字
  89 + */
  90 + public static final String EN_REGEXP = "^[a-zA-Z]+$";
  91 +
  92 + public static final String EN_NUM_REGEXP = "^[a-z0-9A-Z]+$";
  93 +
  94 + public static final String LINE_EN_NUM_REGEXP = "^[a-z0-9A-Z\\-]+$";
  95 +
  96 + /**
  97 + * 仅包含英文和中文
  98 + */
  99 + public static final String CHI_EN_REGEXP = "^[A-z\\u4e00-\\u9fa5]*$";
  100 +
  101 + /**
  102 + * 纯数字
  103 + */
  104 + public static final String NUMERIC_REGEXP = "^\\d+$";
  105 + /**
  106 + * 纯中文
  107 + */
  108 + public static final String CHI_REGEXP = "^[\u4e00-\u9fa5]+$";
  109 + /**
  110 + * 不超过两位小数
  111 + */
  112 + public static final String DICMAL_REGEXP = "^(([1-9]{1}\\d*)|([0]{1}))(\\.(\\d){0,3})?$";
  113 +
  114 + /**
  115 + * 默认空字符串
  116 + */
  117 + public static final String EMPTY_STRING = "";
  118 +
  119 + /**
  120 + * 统一返回data的key
  121 + */
  122 + public static final String RESULT_CHARACTER = "result";
  123 +
  124 + /**
  125 + * 统一返回data的key
  126 + */
  127 + public static final String SUCCESS_RESULT_CHARACTER = "success";
  128 +
  129 + /**
  130 + * 返回的默认结果集
  131 + */
  132 + public static final String RESULT_FAIL = null;
  133 +
  134 + /**
  135 + * ENABLE_FLAG
  136 + */
  137 + public static final String ENABLE_FLAG = "enable_flag";
  138 +
  139 + /**
  140 + * 是否可用 10-可用 20-删除
  141 + */
  142 + public static final int ENABLE_TEN = 10;
  143 + /**
  144 + * 是否可用 10-可用 20-删除
  145 + */
  146 + public static final int UNABLE_TWENTY = 20;
  147 +
  148 + public static final int ONE = 1;
  149 +
  150 + public static final Integer INTEGER_ONE = 1;
  151 +
  152 + public static final int TWO = 2;
  153 +
  154 + public static final int THREE = 3;
  155 +
  156 + public static final int FOUR = 4;
  157 +
  158 + public static final int FIVE = 5;
  159 +
  160 + public static final int SIX = 6;
  161 +
  162 + public static final int SEVEN = 7;
  163 +
  164 + public static final int THIRTY = 30;
  165 +
  166 + public static final int NINETEEN = 19;
  167 +
  168 + public static final int THOUSAND = 1000;
  169 +
  170 + public static final String DATE_TIME = "yyyy-MM-dd HH:mm:ss";
  171 +
  172 + public static final int ZERO = 0;
  173 +
  174 + public static final String STRING_ZERO = "0";
  175 +
  176 + public static final String ZERO_STRING = "0";
  177 +
  178 + public static final String THOUSAND_STRING = "1000";
  179 +
  180 + public static final String SYSTEM_USER = "System";
  181 +
  182 + public static final String percent50 = "0.5";
  183 +
  184 + public static final String DELETE_SUCCESS_RESULT_CHARACTER = "删除成功";
  185 +
  186 +
  187 + /**
  188 + * token rediskey
  189 + */
  190 + public static final String TOKEN_FLAG = "token:";
  191 + /**
  192 + * token 限制api请求
  193 + */
  194 + public static final String PERMISSION_API_LIMIT = "token_api_limit:";
  195 +
  196 + /**
  197 + * token过期时间
  198 + */
  199 + public static final Integer TOKEN_EXPIRE_HOURS = 1;
  200 + /**
  201 + * 密码3次错误锁定
  202 + */
  203 + public static final int LOCK_ERROR_TIMES = 3;
  204 +
  205 + /**
  206 + * session字段
  207 + */
  208 + public static final String HEAD_TOKEN = "Authorization";
  209 + public static final String ACCESS_TOKEN = "token";
  210 + public static final String REQUEST_ORIGIN = "source";
  211 + public static final String REQUEST_IP = "ip";
  212 + public static final String USER_INFO = "userInfo";
  213 + public static final String FILED_ID = "id";
  214 + public static final String FILED_USER_NAME = "username";
  215 + public static final String FILED_DEVICE_NUM = "deviceNum";
  216 +
  217 + /**
  218 + * 请求来源
  219 + */
  220 + public static final String ORIGIN_WEB = "WEB";
  221 + public static final String ORIGIN_PDA = "PDA";
  222 +
  223 + /**
  224 + * 1001 参数校验不通过
  225 + * 1002 签名验证不通过
  226 + */
  227 + public static final List<String> ERROR_CODE_LIST = Arrays.asList("1001", "1002");
  228 +
  229 + /**
  230 + * 分布式锁超时时间
  231 + */
  232 + public static final long REDIS_LOCK_DEFAULT_TIME_OUT_MILLIS = 3000;
  233 + public static final long REDIS_LOCK_FIVE_SECONDS_TIME_OUT_MILLIS = 5000;
  234 +
  235 + /**
  236 + * 系统来源WMS
  237 + */
  238 + public static final String SYS_ORIGIN_WMS = "WMS";
  239 +
  240 + public static final String STRING_ONE = "1";
  241 +
  242 +
  243 + public static final String STRING_TWO = "2";
  244 +
  245 + public static final String STRING_THREE = "3";
  246 +
  247 + public static final String STRING_FOUR = "4";
  248 +
  249 + public static final String STRING_FIVE = "5";
  250 +
  251 + public static final String STRING_SIX = "6";
  252 +
  253 + public static final String STRING_SEVEN = "7";
  254 +
  255 + public static final String STRING_EIGHT = "8";
  256 +
  257 + public static final String STRING_NINE = "9";
  258 +
  259 + public static final String STRING_TEN = "10";
  260 +
  261 + public static final String STRING_ELEVEN = "11";
  262 +
  263 + public static final String STRING_TWELVE = "12";
  264 +
  265 + /**
  266 + * 异常延时队列后缀
  267 + */
  268 + public static final String ERROR_DELAY_QUEUE_SUFFIX = "error";
  269 +
  270 + /**
  271 + * 推送出库数据延时队列 redis key prefix
  272 + */
  273 + public static final String OUTBOUND_NOTIFY_DELAY_QUEUE_PREFIX = "outbound:notify:";
  274 +
  275 + /**
  276 + * 同步MES库存队列 redis key prefix
  277 + */
  278 + public static final String MES_STOCK_SYNC_QUEUE_PREFIX = "mes:stock_sync:";
  279 +
  280 + /**
  281 + * 分拣详情 错误码: 157205 返回值段
  282 + */
  283 + public static final String SEPARATE_PICK_QUERY_RETURN_FIELD = "separatePickQuery";
  284 + /**
  285 + * 限制上限值
  286 + */
  287 + public static final Integer LIMIT_999 = 999;
  288 +
  289 + /**
  290 + * 东八区
  291 + */
  292 + public static final String GMT_8 = "GMT+8";
  293 +
  294 + /**
  295 + * 英文的 "
  296 + */
  297 + public static final String QUOTATION_MARK_CHARACTER = "\"";
  298 +
  299 +
  300 + /**
  301 + * 英文的 \"
  302 + */
  303 + public static final String QUOTATION_SLASH_MARK_CHARACTER = "\\\"";
  304 +
  305 + public static final String SUCCESS_VALUE = "success";
  306 +
  307 +
  308 + public static final String TRUE = "true";
  309 +
  310 + public static final String ROOT_PARENT_ID = "0";
  311 +
  312 + public static final Long ROOT_PARENT_ID_LONG = 0L;
  313 +
  314 +
  315 + /**
  316 + * 短信验证码 redis key
  317 + */
  318 + public static final String SMS_AUTH_CODE_PREFIX = "sms:auth:code:";
  319 +
  320 + public static final String DEFAULT_PASSWORD = "JBXT123456";
  321 +
  322 + /**
  323 + * 账号在线队列 redis key
  324 + */
  325 + public static final String ACCOUNT_ONLINE_LIST = "account:online:";
  326 +
  327 + /**
  328 + * 缓存导入excel错误信息 redis key
  329 + */
  330 + public static final String EXCEL_IMPORT_ERROR_PREFIX = "excel:import:error:";
  331 +
  332 +}
... ...
job/src/main/java/com/canrd/shop/common/constant/ServerResult.java 0 → 100644
  1 +package com.canrd.shop.common.constant;
  2 +
  3 +
  4 +import java.io.Serializable;
  5 +import java.util.HashMap;
  6 +import java.util.Map;
  7 +
  8 +/**
  9 + * @author : dengbin
  10 + * @Date: 2020/9/5
  11 + * 统一的返回结果实体
  12 + */
  13 +public class ServerResult<T> implements Serializable {
  14 + /**
  15 + * 序列化ID
  16 + */
  17 + private static final long serialVersionUID = -5809782578272943999L;
  18 + /**
  19 + * 返回的状态码
  20 + */
  21 + private int result = ServerResultCode.SUCCESS.getErrorCode();
  22 + /**
  23 + * 返回的消息
  24 + */
  25 + private String message = ServerResultCode.SUCCESS.getErrorDesc();
  26 + /**
  27 + * 返回的数据实体
  28 + */
  29 + private T data = null;
  30 + /**
  31 + *
  32 + */
  33 + final int INIT_SIZE = 128;
  34 +
  35 + /**
  36 + *
  37 + */
  38 + public ServerResult() {
  39 + }
  40 +
  41 + @Override
  42 + public String toString() {
  43 + StringBuilder buffer = new StringBuilder(INIT_SIZE);
  44 + buffer.append("{\"result\":").append(this.result);
  45 + buffer.append(",\"message\":\"").append(this.message != null ? message : "").append("\"");
  46 + buffer.append(",\"data\":").append(data).append("}");
  47 + return buffer.toString();
  48 + }
  49 +
  50 + public int getResult() {
  51 + return result;
  52 + }
  53 +
  54 + public ServerResult setResult(int result) {
  55 + this.result = result;
  56 + return this;
  57 + }
  58 +
  59 + public ServerResult setResult(ServerResultCode serverResultCode) {
  60 + this.result = serverResultCode.getErrorCode();
  61 + this.message = serverResultCode.getErrorDesc();
  62 + return this;
  63 + }
  64 +
  65 + public ServerResult setResult(int errorCode, String errorDesc) {
  66 + this.result = errorCode;
  67 + this.message = errorDesc;
  68 + return this;
  69 + }
  70 +
  71 + public String getMessage() {
  72 + return message;
  73 + }
  74 +
  75 + public ServerResult<T> setMessage(String message) {
  76 + this.message = message;
  77 + return this;
  78 + }
  79 +
  80 + public T getData() {
  81 + return data;
  82 + }
  83 +
  84 + public ServerResult setData(T data) {
  85 + this.data = data;
  86 + return this;
  87 + }
  88 +
  89 + public static <T> ServerResult<T> success() {
  90 + return new ServerResult()
  91 + .setResult(ServerResultCode.SUCCESS)
  92 + .setMessage(ServerResultCode.SUCCESS.getErrorDesc())
  93 + .setData(defaultResult(ServerResultCode.SUCCESS));
  94 + }
  95 +
  96 + public static <T> ServerResult<T> success(T data) {
  97 + return new ServerResult()
  98 + .setResult(ServerResultCode.SUCCESS)
  99 + .setMessage(ServerResultCode.SUCCESS.getErrorDesc())
  100 + .setData(data);
  101 + }
  102 +
  103 + public static <T> ServerResult<T> success(T data, String message) {
  104 + return new ServerResult()
  105 + .setResult(ServerResultCode.SUCCESS)
  106 + .setMessage(message)
  107 + .setData(data);
  108 + }
  109 +
  110 + /**
  111 + * @description 错误码使用系统错误 1000 错误类型自定义
  112 + * @author dengbin
  113 + * @date 2020/9/12
  114 + */
  115 + public static <T> ServerResult<T> fail(String message) {
  116 + return new ServerResult()
  117 + .setResult(ServerResultCode.FAIL)
  118 + .setMessage(message)
  119 + .setData(defaultResult(Constant.RESULT_FAIL));
  120 + }
  121 +
  122 + /**
  123 + * 错误时需要返回相关数据时使用
  124 + *
  125 + * @param data
  126 + * @param <T>
  127 + * @return
  128 + */
  129 + public static <T> ServerResult<T> fail(T data, ServerResultCode serverResultCode) {
  130 + return new ServerResult()
  131 + .setData(data)
  132 + .setResult(serverResultCode)
  133 + .setMessage(serverResultCode.getErrorDesc());
  134 + }
  135 +
  136 + /**
  137 + * 错误时需要返回相关数据时使用(不设值 data)
  138 + *
  139 + * @param sr
  140 + * @param
  141 + * @return
  142 + */
  143 + public static <T> ServerResult<T> fail(ServerResult<?> sr) {
  144 + return new ServerResult<>()
  145 + .setMessage(sr.getMessage())
  146 + .setResult(sr.getResult());
  147 +
  148 + }
  149 +
  150 + /**
  151 + * @description 错误码使用上面的枚举定义的,错误信息重新定义
  152 + * @author dengbin
  153 + * @date 2020/9/12
  154 + */
  155 + public static <T> ServerResult<T> fail(ServerResultCode serverResultCode, String msg) {
  156 + return new ServerResult()
  157 + .setResult(serverResultCode)
  158 + .setMessage(msg)
  159 + .setData(defaultResult(Constant.RESULT_FAIL));
  160 + }
  161 +
  162 + /**
  163 + * @return
  164 + * @description 直接选用上面的枚举错误码,输出定义的错误信息
  165 + * @author dengbin
  166 + * @date 2020/9/12
  167 + */
  168 + public static <T> ServerResult<T> fail(ServerResultCode serverResultCode) {
  169 + return new ServerResult()
  170 + .setResult(serverResultCode)
  171 + .setMessage(serverResultCode.getErrorDesc())
  172 + .setData(defaultResult(Constant.RESULT_FAIL));
  173 + }
  174 +
  175 + /**
  176 + * 错误时需要返回相关数据时使用
  177 + *
  178 + * @param data
  179 + * @param <T>
  180 + * @return
  181 + */
  182 + public static <T> ServerResult<T> fail(T data, int errorCode, String errorDesc) {
  183 + return new ServerResult()
  184 + .setData(data)
  185 + .setResult(errorCode, errorDesc);
  186 + }
  187 +
  188 +
  189 + public static <T> ServerResult<T> fail() {
  190 + return new ServerResult()
  191 + .setResult(ServerResultCode.FAIL.getErrorCode())
  192 + .setMessage(ServerResultCode.FAIL.getErrorDesc())
  193 + .setData(defaultResult(Constant.RESULT_FAIL));
  194 + }
  195 +
  196 +
  197 + /**
  198 + * @description 直接选用上面的枚举错误码,输出定义的错误信息
  199 + * @author dengbin
  200 + * @date 2020/9/12
  201 + */
  202 + public ServerResult failEnum(ServerResultCode serverResultCode) {
  203 + setResult(serverResultCode);
  204 + setMessage(serverResultCode.getErrorDesc());
  205 + return this;
  206 + }
  207 +
  208 + public static <T> ServerResult<T> fail(int errorCode, String errorDesc) {
  209 + return new ServerResult()
  210 + .setResult(errorCode, errorDesc)
  211 + .setData(defaultResult(Constant.RESULT_FAIL));
  212 +
  213 + }
  214 +
  215 + /**
  216 + * 判断当前的状态码是否是SUCCESS
  217 + *
  218 + * @return 结果 ture or false
  219 + */
  220 + public boolean checkSuccess() {
  221 + return result == ServerResultCode.SUCCESS.getErrorCode();
  222 + }
  223 +
  224 + public boolean checkNotSuccess() {
  225 + return !checkSuccess();
  226 + }
  227 +
  228 + private static Map<String, Object> defaultResult(Object object) {
  229 + Map<String, Object> map = new HashMap<>(Constant.ONE);
  230 + map.put(Constant.RESULT_CHARACTER, null);
  231 + return map;
  232 + }
  233 +}
... ...
job/src/main/java/com/canrd/shop/common/constant/ServerResultCode.java 0 → 100644
  1 +package com.canrd.shop.common.constant;
  2 +
  3 +
  4 +import com.canrd.shop.common.exception.ErrorInfo;
  5 +import lombok.Setter;
  6 +
  7 +
  8 +/**
  9 + * 请求成功 返回 0
  10 + */
  11 +public enum ServerResultCode implements ErrorInfo {
  12 + //成功 "0"
  13 + SUCCESS(0, "成功"),
  14 + FAIL(1000, "系统内部错误,请联系业务系统运维管理员"),
  15 + FIlE_UPLOAD_TOO_LARGE(1051, "上传文件太大,图片文件一般小于2兆"),
  16 +
  17 + //空指针异常
  18 + NULL_POINT(1001, "空指针异常"),
  19 +
  20 + //校验异常
  21 + RUN_ERROR(1002, "程序运行报错"),
  22 + ILLEGAL_ARGUMENT(1003, "参数非法"),
  23 + FILED_ERROR(1004, "传入参数错误"),
  24 + PARAM_ERROR(1005, "入参为空"),
  25 + EMPTY_RESULT(1006, "数据不存在"),
  26 + EMPTY_LIST(1007, "查询结果为空"),
  27 +
  28 + //认证授权异常
  29 + UNAUTHENTICATION(401, "未登录"),
  30 +
  31 +
  32 + //用户
  33 + USER_NOT_EXIT(20001, "用户不存在"),
  34 +
  35 +
  36 + // 公司
  37 + COMPANY_NOT_EXIT(30001, "公司不存在"),
  38 + ;
  39 +
  40 +
  41 + ServerResultCode(Integer errorCode, String errorDesc) {
  42 + this.errorCode = errorCode;
  43 + this.errorDesc = errorDesc;
  44 + }
  45 +
  46 + @Setter
  47 + private Integer errorCode;
  48 + @Setter
  49 + private String errorDesc;
  50 +
  51 + @Override
  52 + public Integer getErrorCode() {
  53 + return this.errorCode;
  54 + }
  55 +
  56 + @Override
  57 + public String getErrorDesc() {
  58 + return this.errorDesc;
  59 + }
  60 +
  61 + /**
  62 + * 根据errorCode获得枚举
  63 + *
  64 + * @param errorCode
  65 + * @return
  66 + */
  67 + public static String getDescByCode(Integer errorCode) {
  68 + if (errorCode == null) {
  69 + return null;
  70 + }
  71 + ServerResultCode[] serverResults = values();
  72 + for (ServerResultCode serverResult : serverResults) {
  73 + if (serverResult.getErrorCode().equals(errorCode)) {
  74 + return serverResult.getErrorDesc();
  75 + }
  76 + }
  77 + return null;
  78 + }
  79 +
  80 +}
0 81 \ No newline at end of file
... ...
job/src/main/java/com/canrd/shop/common/exception/BadRequestException.java 0 → 100644
  1 +package com.canrd.shop.common.exception;
  2 +
  3 +import lombok.Getter;
  4 +import org.springframework.http.HttpStatus;
  5 +
  6 +import static org.springframework.http.HttpStatus.BAD_REQUEST;
  7 +
  8 +/**
  9 + *
  10 + * @date 2018-11-23
  11 + * 统一异常处理
  12 + */
  13 +@Getter
  14 +public class BadRequestException extends RuntimeException {
  15 +
  16 + private Integer status = BAD_REQUEST.value();
  17 +
  18 + public BadRequestException(String msg) {
  19 + super(msg);
  20 + }
  21 +
  22 + public BadRequestException(HttpStatus status, String msg) {
  23 + super(msg);
  24 + this.status = status.value();
  25 + }
  26 +}
... ...
job/src/main/java/com/canrd/shop/common/exception/BusinessException.java 0 → 100644
  1 +package com.canrd.shop.common.exception;
  2 +
  3 +import com.canrd.shop.common.constant.ServerResult;
  4 +import com.canrd.shop.common.constant.ServerResultCode;
  5 +import lombok.Getter;
  6 +import lombok.Setter;
  7 +import lombok.extern.slf4j.Slf4j;
  8 +
  9 +/**
  10 + * <p>基础异常类,所有自定义异常类都需要继承本类</p>
  11 + *
  12 + * @author A80076
  13 + * @date 2021/1/11
  14 + */
  15 +@Slf4j
  16 +public class BusinessException extends RuntimeException {
  17 +
  18 + private static final long serialVersionUID = 3152549963899218489L;
  19 + @Setter
  20 + @Getter
  21 + private String errorDesc;
  22 + @Setter
  23 + @Getter
  24 + private Integer errorCode;
  25 + @Setter
  26 + @Getter
  27 + private Object data;
  28 +
  29 + public BusinessException() {
  30 + super(ServerResultCode.FAIL.getErrorDesc());
  31 + this.errorCode = ServerResultCode.FAIL.getErrorCode();
  32 + this.errorDesc = ServerResultCode.FAIL.getErrorDesc();
  33 + }
  34 +
  35 + public BusinessException(int errorCode, String errorDesc) {
  36 + super(errorDesc);
  37 + this.errorCode = errorCode;
  38 + this.errorDesc = errorDesc;
  39 + }
  40 +
  41 + public BusinessException(ServerResultCode serverResultCode) {
  42 + super(serverResultCode.getErrorDesc());
  43 + this.errorCode = serverResultCode.getErrorCode();
  44 + this.errorDesc = serverResultCode.getErrorDesc();
  45 + log.error("业务异常: ", this);
  46 + }
  47 +
  48 + public BusinessException(ErrorInfo errorInfo) {
  49 + super(errorInfo.getErrorDesc());
  50 + this.errorCode = errorInfo.getErrorCode();
  51 + this.errorDesc = errorInfo.getErrorDesc();
  52 + log.error("业务异常: ", this);
  53 + }
  54 +
  55 + public BusinessException(ServerResult<?> serverResult) {
  56 + super(serverResult == null ? ServerResultCode.FAIL.getErrorDesc() : serverResult.getMessage());
  57 + if (serverResult == null) {
  58 + this.errorCode = ServerResultCode.FAIL.getErrorCode();
  59 + this.errorDesc = ServerResultCode.FAIL.getErrorDesc();
  60 + } else {
  61 + this.errorCode = serverResult.getResult();
  62 + this.errorDesc = serverResult.getMessage();
  63 + this.data = serverResult.getData();
  64 + }
  65 + log.error("业务异常: ", this);
  66 + }
  67 +
  68 + public BusinessException(String message) {
  69 + super(message);
  70 + }
  71 +
  72 + public BusinessException(Throwable cause) {
  73 + super(cause);
  74 + log.error("业务异常: ", this);
  75 + }
  76 +
  77 + public BusinessException(String message, Throwable cause) {
  78 + super(message, cause);
  79 + log.error("业务异常: ", this);
  80 + }
  81 +}
... ...
job/src/main/java/com/canrd/shop/common/exception/BusinessExceptionHandlerAdvice.java 0 → 100644
  1 +package com.canrd.shop.common.exception;
  2 +
  3 +import com.canrd.shop.common.constant.ServerResult;
  4 +import com.canrd.shop.common.constant.ServerResultCode;
  5 +import org.springframework.core.annotation.Order;
  6 +import org.springframework.http.HttpStatus;
  7 +import org.springframework.http.ResponseEntity;
  8 +import org.springframework.web.bind.annotation.ControllerAdvice;
  9 +import org.springframework.web.bind.annotation.ExceptionHandler;
  10 +import org.springframework.web.bind.annotation.ResponseStatus;
  11 +
  12 +import java.util.Optional;
  13 +
  14 +/**
  15 + * 业务异常统一处理类
  16 + *
  17 + * @author A80076
  18 + * @date 2021/1/11
  19 + */
  20 +@ControllerAdvice
  21 +@Order(5)
  22 +public class BusinessExceptionHandlerAdvice {
  23 +
  24 +
  25 + @ExceptionHandler(value = {BusinessException.class})
  26 + @ResponseStatus(value = HttpStatus.OK)
  27 + public ResponseEntity<Object> handleException(BusinessException exception) throws Exception {
  28 + return new ResponseEntity<Object>(handleBusinessException(exception), HttpStatus.OK);
  29 + }
  30 +
  31 + private ServerResult handleBusinessException(BusinessException exception) {
  32 + Integer code = Optional.ofNullable(exception.getErrorCode()).orElse(ServerResultCode.FAIL.getErrorCode());
  33 + String msg = Optional.ofNullable(exception.getMessage()).orElse(ServerResultCode.FAIL.getErrorDesc());
  34 + Object data = Optional.ofNullable(exception.getData()).orElse(null);
  35 + return ServerResult.fail(data, code, msg);
  36 + }
  37 +}
... ...
job/src/main/java/com/canrd/shop/common/exception/EntityExistException.java 0 → 100644
  1 +package com.canrd.shop.common.exception;
  2 +
  3 +import org.springframework.util.StringUtils;
  4 +
  5 +/**
  6 + *
  7 + * @date 2018-11-23
  8 + */
  9 +public class EntityExistException extends RuntimeException {
  10 +
  11 + public EntityExistException(Class clazz, String field, String val) {
  12 + super(EntityExistException.generateMessage(clazz.getSimpleName(), field, val));
  13 + }
  14 +
  15 + private static String generateMessage(String entity, String field, String val) {
  16 + return StringUtils.capitalize(entity)
  17 + + " with " + field + " " + val + " existed";
  18 + }
  19 +}
0 20 \ No newline at end of file
... ...
job/src/main/java/com/canrd/shop/common/exception/EntityNotFoundException.java 0 → 100644
  1 +package com.canrd.shop.common.exception;
  2 +
  3 +import org.springframework.util.StringUtils;
  4 +
  5 +/**
  6 + *
  7 + * @date 2018-11-23
  8 + */
  9 +public class EntityNotFoundException extends RuntimeException {
  10 +
  11 + public EntityNotFoundException(Class clazz, String field, String val) {
  12 + super(EntityNotFoundException.generateMessage(clazz.getSimpleName(), field, val));
  13 + }
  14 +
  15 + private static String generateMessage(String entity, String field, String val) {
  16 + return StringUtils.capitalize(entity)
  17 + + " with " + field + " " + val + " does not exist";
  18 + }
  19 +}
0 20 \ No newline at end of file
... ...
job/src/main/java/com/canrd/shop/common/exception/ErrorInfo.java 0 → 100644
  1 +package com.canrd.shop.common.exception;
  2 +
  3 +/**
  4 + * @author fanzhenyu
  5 + * @date 2023-01-12
  6 + */
  7 +public interface ErrorInfo {
  8 +
  9 + Integer getErrorCode();
  10 +
  11 + String getErrorDesc();
  12 +}
... ...
job/src/main/java/com/canrd/shop/common/exception/handler/ApiError.java 0 → 100644
  1 +package com.canrd.shop.common.exception.handler;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonFormat;
  4 +import lombok.Data;
  5 +
  6 +import java.time.LocalDateTime;
  7 +
  8 +/**
  9 + *
  10 + * @date 2018-11-23
  11 + */
  12 +@Data
  13 +class ApiError {
  14 +
  15 + private Integer status = 200;
  16 + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
  17 + private LocalDateTime timestamp;
  18 + private String message;
  19 + private String errorCode;
  20 +
  21 + private ApiError() {
  22 + timestamp = LocalDateTime.now();
  23 + }
  24 +
  25 + public static ApiError error(String message){
  26 + ApiError apiError = new ApiError();
  27 + apiError.setMessage(message);
  28 + return apiError;
  29 + }
  30 +
  31 + public static ApiError error(Integer status, String message){
  32 + ApiError apiError = new ApiError();
  33 + apiError.setStatus(status);
  34 + apiError.setMessage(message);
  35 + return apiError;
  36 + }
  37 +}
  38 +
  39 +
... ...
job/src/main/java/com/canrd/shop/common/exception/handler/GlobalExceptionHandler.java 0 → 100644
  1 +package com.canrd.shop.common.exception.handler;
  2 +
  3 +
  4 +import com.canrd.shop.common.constant.ServerResult;
  5 +import com.canrd.shop.common.constant.ServerResultCode;
  6 +import com.canrd.shop.common.exception.BadRequestException;
  7 +import com.canrd.shop.common.exception.BusinessException;
  8 +import com.canrd.shop.common.exception.EntityExistException;
  9 +import com.canrd.shop.common.exception.EntityNotFoundException;
  10 +import com.canrd.shop.common.utils.ThrowableUtil;
  11 +import lombok.extern.slf4j.Slf4j;
  12 +import org.springframework.http.HttpStatus;
  13 +import org.springframework.http.ResponseEntity;
  14 +import org.springframework.web.bind.MethodArgumentNotValidException;
  15 +import org.springframework.web.bind.annotation.ExceptionHandler;
  16 +import org.springframework.web.bind.annotation.ResponseStatus;
  17 +import org.springframework.web.bind.annotation.RestControllerAdvice;
  18 +import org.springframework.web.multipart.MaxUploadSizeExceededException;
  19 +
  20 +import java.util.Objects;
  21 +
  22 +/**
  23 + * @date 2018-11-23
  24 + */
  25 +@Slf4j
  26 +@RestControllerAdvice
  27 +public class GlobalExceptionHandler {
  28 + /**
  29 + * @param exception
  30 + * @return
  31 + * @throws Exception
  32 + */
  33 + @ExceptionHandler(value = RuntimeException.class)
  34 + public ResponseEntity<Object> handleServiceException(Exception exception) throws Exception {
  35 + return new ResponseEntity(translateException(exception), HttpStatus.OK);
  36 + }
  37 +
  38 + /**
  39 + * @param exception
  40 + * @return
  41 + * @throws Exception
  42 + */
  43 + @ExceptionHandler(value = Exception.class)
  44 + @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
  45 + public ResponseEntity<Object> handleException(Exception exception) throws Exception {
  46 + return new ResponseEntity<Object>(translateException(exception), HttpStatus.OK);
  47 + }
  48 +
  49 +
  50 + /**
  51 + * 处理所有接口数据验证异常
  52 + *
  53 + * @param e
  54 + * @return
  55 + */
  56 + @ExceptionHandler(MethodArgumentNotValidException.class)
  57 + public ResponseEntity<ServerResult> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
  58 + // 打印堆栈信息
  59 + log.error(ThrowableUtil.getStackTrace(e));
  60 + String[] str = Objects.requireNonNull(e.getBindingResult().getAllErrors().get(0).getCodes())[1].split("\\.");
  61 + String message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage();
  62 + String msg = "不能为空";
  63 + if (msg.equals(message)) {
  64 + message = str[1] + ":" + message;
  65 + }
  66 + return buildResponseEntity(ServerResult.fail(message));
  67 + }
  68 +
  69 + /**
  70 + * 处理自定义异常
  71 + *
  72 + * @param e
  73 + * @return
  74 + */
  75 + @ExceptionHandler(value = BadRequestException.class)
  76 + public ResponseEntity<ServerResult> badRequestException(BadRequestException e) {
  77 + // 打印堆栈信息
  78 + log.error(ThrowableUtil.getStackTrace(e));
  79 + return buildResponseEntity(ServerResult.fail(e.getStatus(), e.getMessage()));
  80 + }
  81 +
  82 + /**
  83 + * 处理 EntityExist
  84 + */
  85 + @ExceptionHandler(value = EntityExistException.class)
  86 + public ResponseEntity<ServerResult> entityExistException(EntityExistException e) {
  87 + // 打印堆栈信息
  88 + log.error(ThrowableUtil.getStackTrace(e));
  89 + return buildResponseEntity(ServerResult.fail(e.getMessage()));
  90 + }
  91 +
  92 + /**
  93 + * 处理 EntityNotFound
  94 + *
  95 + * @param e
  96 + * @return
  97 + */
  98 + @ExceptionHandler(value = EntityNotFoundException.class)
  99 + public ResponseEntity<ServerResult> entityNotFoundException(EntityNotFoundException e) {
  100 + // 打印堆栈信息
  101 + log.error(ThrowableUtil.getStackTrace(e));
  102 + return buildResponseEntity(ServerResult.fail(HttpStatus.NOT_FOUND.value(), e.getMessage()));
  103 + }
  104 +
  105 + /**
  106 + * @param serverResult
  107 + * @return
  108 + */
  109 + private ResponseEntity<ServerResult> buildResponseEntity(ServerResult serverResult) {
  110 + return new ResponseEntity<>(serverResult, HttpStatus.valueOf(200));
  111 + }
  112 +
  113 + /**
  114 + * @param e
  115 + * @return
  116 + * @throws Exception
  117 + */
  118 + private Object translateException(Exception e) throws Exception {
  119 + ServerResult serverResult = null;
  120 + if (e instanceof NullPointerException) {
  121 + serverResult = ServerResult.fail(ServerResultCode.NULL_POINT);
  122 + } else if (e instanceof IllegalArgumentException) {
  123 + serverResult = ServerResult.fail(ServerResultCode.FAIL);
  124 + } else if (e instanceof MaxUploadSizeExceededException) {
  125 + serverResult = ServerResult.fail(ServerResultCode.FIlE_UPLOAD_TOO_LARGE);
  126 + } else if (e instanceof BusinessException) {
  127 + serverResult = ServerResult.fail(((BusinessException) e).getErrorCode(), ((BusinessException) e).getErrorDesc());
  128 + } else {
  129 + serverResult = ServerResult.fail(ServerResultCode.FAIL);
  130 + serverResult.setMessage(serverResult.getMessage() + "|,业务异常:" + e.getMessage());
  131 + }
  132 +
  133 + log.error("业务异常", e);
  134 + return serverResult;
  135 + }
  136 +}
... ...
job/src/main/java/com/canrd/shop/common/jsr303/ListValueConstraintValidator.java 0 → 100644
  1 +package com.canrd.shop.common.jsr303;
  2 +
  3 +
  4 +import com.canrd.shop.common.jsr303.annotation.ListIntValue;
  5 +
  6 +import javax.validation.ConstraintValidator;
  7 +import javax.validation.ConstraintValidatorContext;
  8 +import java.util.HashSet;
  9 +import java.util.Set;
  10 +
  11 +/**
  12 + * 自定义校验注解 -枚举值校验
  13 + *
  14 + * @author fanzhenyu
  15 + * @date 2023-01-15
  16 + */
  17 +public class ListValueConstraintValidator implements ConstraintValidator<ListIntValue, Integer> {
  18 + private Set<Integer> set = new HashSet<>();
  19 + // 是否必填
  20 + private boolean require;
  21 +
  22 + @Override
  23 + public void initialize(ListIntValue constraintAnnotation) {
  24 + for (int i : constraintAnnotation.enumValue()) {
  25 + set.add(i);
  26 + }
  27 + require = constraintAnnotation.require();
  28 + }
  29 +
  30 + /**
  31 + * 判断是否通过校验
  32 + *
  33 + * @param value 传入的值
  34 + * @param context
  35 + * @return
  36 + */
  37 + @Override
  38 + public boolean isValid(Integer value, ConstraintValidatorContext context) {
  39 + if (!require && value == null) {
  40 + return true;
  41 + }
  42 + return set.contains(value);
  43 + }
  44 +
  45 +}
... ...
job/src/main/java/com/canrd/shop/common/jsr303/OperateGroup.java 0 → 100644
  1 +package com.canrd.shop.common.jsr303;
  2 +
  3 +
  4 +public class OperateGroup {
  5 + /**
  6 + * 新增校验
  7 + */
  8 + public interface Save {
  9 + }
  10 +
  11 + /**
  12 + * 删除校验
  13 + */
  14 + public interface Delete {
  15 + }
  16 +
  17 + /**
  18 + * 修改校验
  19 + */
  20 + public interface Update {
  21 + }
  22 +
  23 + /**
  24 + * 查询列表
  25 + */
  26 + public interface List {
  27 + }
  28 +
  29 + /**
  30 + * 分页查询
  31 + */
  32 + public interface Page {
  33 + }
  34 +
  35 + /**
  36 + * 长度校验
  37 + */
  38 + public interface Length {
  39 + }
  40 +
  41 + /**
  42 + * 格式校验
  43 + */
  44 + public interface Format {
  45 + }
  46 +
  47 + /**
  48 + * 详情
  49 + */
  50 + public interface Detail {
  51 + }
  52 +
  53 + /**
  54 + * 单条
  55 + */
  56 + public interface One {
  57 + }
  58 +
  59 +
  60 + public interface Trace {
  61 +
  62 + }
  63 +
  64 + /**
  65 + * 批量查询
  66 + */
  67 + public interface BatchQuery {
  68 + }
  69 +
  70 +
  71 + /**
  72 + * 导出
  73 + */
  74 + public interface Export {
  75 + }
  76 +
  77 +}
... ...
job/src/main/java/com/canrd/shop/common/jsr303/annotation/ListIntValue.java 0 → 100644
  1 +package com.canrd.shop.common.jsr303.annotation;
  2 +
  3 +
  4 +import com.canrd.shop.common.jsr303.ListValueConstraintValidator;
  5 +
  6 +import javax.validation.Constraint;
  7 +import javax.validation.Payload;
  8 +import java.lang.annotation.*;
  9 +
  10 +/**
  11 + * @author fanzhenyu
  12 + * @date 2023-01-15
  13 + */
  14 +@Constraint(validatedBy = {ListValueConstraintValidator.class})
  15 +@Documented
  16 +@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
  17 +@Retention(RetentionPolicy.RUNTIME)
  18 +public @interface ListIntValue {
  19 +
  20 +
  21 + // 配置文件中错误提示信息的名称
  22 + String message() default "非法的类型";
  23 +
  24 + Class<?>[] groups() default {};
  25 +
  26 + Class<? extends Payload>[] payload() default {};
  27 +
  28 + // 自定义值的类型
  29 + int[] enumValue() default {};
  30 +
  31 + // 是否必填,默认允许为空
  32 + boolean require() default false;
  33 +}
... ...
job/src/main/java/com/canrd/shop/common/utils/EncryptUtils.java 0 → 100644
  1 +package com.canrd.shop.common.utils;
  2 +
  3 +import javax.crypto.Cipher;
  4 +import javax.crypto.SecretKey;
  5 +import javax.crypto.SecretKeyFactory;
  6 +import javax.crypto.spec.DESKeySpec;
  7 +import javax.crypto.spec.IvParameterSpec;
  8 +import java.nio.charset.StandardCharsets;
  9 +
  10 +/**
  11 + * 加密
  12 + *
  13 + * @date 2018-11-23
  14 + */
  15 +public class EncryptUtils {
  16 +
  17 + private static String strParam = "Passw0rd";
  18 +
  19 + private static Cipher cipher;
  20 +
  21 + private static IvParameterSpec iv = new IvParameterSpec(strParam.getBytes(StandardCharsets.UTF_8));
  22 +
  23 + private static DESKeySpec getDesKeySpec(String source) throws Exception {
  24 + if (source == null || source.length() == 0) {
  25 + return null;
  26 + }
  27 + cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
  28 + String strKey = "Passw0rd";
  29 + return new DESKeySpec(strKey.getBytes(StandardCharsets.UTF_8));
  30 + }
  31 +
  32 + /**
  33 + * 对称加密
  34 + */
  35 + public static String desEncrypt(String source) throws Exception {
  36 + DESKeySpec desKeySpec = getDesKeySpec(source);
  37 + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
  38 + SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
  39 + cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
  40 + return byte2hex(
  41 + cipher.doFinal(source.getBytes(StandardCharsets.UTF_8))).toUpperCase();
  42 + }
  43 +
  44 + /**
  45 + * 对称解密
  46 + */
  47 + public static String desDecrypt(String source) throws Exception {
  48 + byte[] src = hex2byte(source.getBytes());
  49 + DESKeySpec desKeySpec = getDesKeySpec(source);
  50 + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
  51 + SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
  52 + cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
  53 + byte[] retByte = cipher.doFinal(src);
  54 + return new String(retByte);
  55 + }
  56 +
  57 + private static String byte2hex(byte[] inStr) {
  58 + String stmp;
  59 + StringBuilder out = new StringBuilder(inStr.length * 2);
  60 + for (byte b : inStr) {
  61 + stmp = Integer.toHexString(b & 0xFF);
  62 + if (stmp.length() == 1) {
  63 + // 如果是0至F的单位字符串,则添加0
  64 + out.append("0").append(stmp);
  65 + } else {
  66 + out.append(stmp);
  67 + }
  68 + }
  69 + return out.toString();
  70 + }
  71 +
  72 + private static byte[] hex2byte(byte[] b) {
  73 + int size = 2;
  74 + if ((b.length % size) != 0) {
  75 + throw new IllegalArgumentException("长度不是偶数");
  76 + }
  77 + byte[] b2 = new byte[b.length / 2];
  78 + for (int n = 0; n < b.length; n += size) {
  79 + String item = new String(b, n, 2);
  80 + b2[n / 2] = (byte) Integer.parseInt(item, 16);
  81 + }
  82 + return b2;
  83 + }
  84 +}
... ...
job/src/main/java/com/canrd/shop/common/utils/JsonUtil.java 0 → 100644
  1 +package com.canrd.shop.common.utils;
  2 +
  3 +
  4 +import com.alibaba.fastjson.JSONException;
  5 +import com.alibaba.fastjson.JSONObject;
  6 +import com.fasterxml.jackson.annotation.JsonInclude;
  7 +import com.fasterxml.jackson.core.JsonGenerator;
  8 +import com.fasterxml.jackson.core.JsonProcessingException;
  9 +import com.fasterxml.jackson.core.type.TypeReference;
  10 +import com.fasterxml.jackson.databind.*;
  11 +import com.fasterxml.jackson.databind.node.ArrayNode;
  12 +import com.fasterxml.jackson.databind.node.ObjectNode;
  13 +import lombok.extern.slf4j.Slf4j;
  14 +
  15 +import java.io.IOException;
  16 +
  17 +/**
  18 + *
  19 + * @author achims
  20 + * @date 2019/11/4
  21 + * 用于转换成json字符串以及解析成对象
  22 + */
  23 +@Slf4j
  24 +public class JsonUtil {
  25 +
  26 + private static ObjectMapper mapper = new ObjectMapper();
  27 +
  28 + static {
  29 + log.info("注册jackson-datatype-jsr310的java8时间处理模块");
  30 + mapper.findAndRegisterModules();
  31 + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
  32 + mapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
  33 + @Override
  34 + public void serialize(Object paramT, JsonGenerator paramJsonGenerator,
  35 + SerializerProvider paramSerializerProvider) throws IOException {
  36 + //设置返回null转为 空字符串""
  37 + paramJsonGenerator.writeString("");
  38 + }
  39 + });
  40 + }
  41 +
  42 +
  43 +
  44 +
  45 + /**
  46 + * Create empty json node
  47 + *
  48 + * @return
  49 + */
  50 + public static ObjectNode createJsonNode() {
  51 + return mapper.createObjectNode();
  52 + }
  53 +
  54 + /**
  55 + * Create empty json Array
  56 + *
  57 + * @return
  58 + */
  59 + public static ArrayNode createJsonArray() {
  60 + return mapper.createArrayNode();
  61 +
  62 + }
  63 +
  64 + /**
  65 + * Convert the object to corresponding json string
  66 + *
  67 + * @param obj
  68 + * @return
  69 + */
  70 + public static String toJsonString(Object obj) {
  71 + try {
  72 + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
  73 + return mapper.writeValueAsString(obj);
  74 + } catch (JsonProcessingException e) {
  75 + return null;
  76 + }
  77 + }
  78 +
  79 + /**
  80 + * 转成格式化后的json,便于调试排错
  81 + * @param obj
  82 + * @return
  83 + */
  84 + public static String toJsonStringWithDefaultPretty(Object obj) {
  85 + try {
  86 + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
  87 + return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
  88 + } catch (JsonProcessingException e) {
  89 +
  90 + return null;
  91 + }
  92 + }
  93 +
  94 + public static <T> T jsonToEntity(String json, Class<T> clazz) {
  95 + if (StringUtils.isEmpty(json)) return null;
  96 + try {
  97 + return mapper.readValue(json, clazz);
  98 + } catch (IOException e) {
  99 + e.printStackTrace();
  100 + }
  101 + return null;
  102 + }
  103 +
  104 + /**
  105 + * 借助json做中转,实体类转实体类
  106 + * @param obj 实体
  107 + * @param clazz 目标类型
  108 + * @param <T> 目标泛型
  109 + * @return 结果
  110 + */
  111 + public static <T> T entityConvert(Object obj, Class<T> clazz) {
  112 + return jsonToEntity(toJsonString(obj), clazz);
  113 + }
  114 +
  115 + /**
  116 + * 带泛型返回不告警
  117 + * @param json json字符
  118 + * @param typeReference TypeReference
  119 + * @param <R> 返回类型
  120 + * @param <T> 转换的类型
  121 + * @return 转换结果
  122 + * @author 刘迪榕
  123 + * @version Date 2022-08-26
  124 + */
  125 + public static <R, T extends R> R jsonToEntity(String json, TypeReference<T> typeReference) {
  126 + if (StringUtils.isEmpty(json)) return null;
  127 + try {
  128 + return mapper.readValue(json, typeReference);
  129 + } catch (IOException e) {
  130 + e.printStackTrace();
  131 + }
  132 + return null;
  133 + }
  134 +
  135 + public static JsonNode readStringAsJsonNode(String json) {
  136 + try {
  137 + return mapper.readValue(json, JsonNode.class);
  138 + } catch (IOException e) {
  139 + e.printStackTrace();
  140 + }
  141 + return null;
  142 + }
  143 +
  144 + public static JsonNode valueToTree(Object value) {
  145 + return mapper.valueToTree(value);
  146 + }
  147 +
  148 + public static <T> T treeToValue(JsonNode jsonNode, Class<T> clazz) {
  149 + try {
  150 + return mapper.treeToValue(jsonNode, clazz);
  151 + } catch (IOException e) {
  152 + e.printStackTrace();
  153 + }
  154 + return null;
  155 + }
  156 +
  157 + /**
  158 + * 是否爲json格式的數據
  159 + *
  160 + * @param test
  161 + * @return
  162 + */
  163 + public final static boolean isJSONValid(String test) {
  164 + try {
  165 + JSONObject.parseObject(test);
  166 + } catch (JSONException ex) {
  167 + try {
  168 + JSONObject.parseArray(test);
  169 + } catch (JSONException ex1) {
  170 + return false;
  171 + }
  172 + }
  173 + return true;
  174 + }
  175 +
  176 + public <T> T paraseJsonTOClass(String json, Class<T> cla) {
  177 + try {
  178 + return JSONObject.parseObject(json, cla);
  179 + } catch (JSONException ex) {
  180 + return null;
  181 + }
  182 + }
  183 +}
... ...
job/src/main/java/com/canrd/shop/common/utils/LocalDateTimeUtil.java 0 → 100644
  1 +package com.canrd.shop.common.utils;
  2 +
  3 +import org.joda.time.DateTime;
  4 +
  5 +import java.time.LocalDateTime;
  6 +
  7 +/**
  8 + * @author: xms
  9 + * @description: TODO
  10 + * @date: 2023/1/16 16:35
  11 + * @version: 1.0
  12 + */
  13 +public class LocalDateTimeUtil {
  14 +
  15 + /**
  16 + * @param dateTime
  17 + * @return
  18 + */
  19 + public static LocalDateTime toLocalDateTime(DateTime dateTime) {
  20 + return LocalDateTime.of(dateTime.getYear(), dateTime.getMonthOfYear(),
  21 + dateTime.getDayOfMonth(), dateTime.getHourOfDay(),
  22 + dateTime.getMinuteOfHour(), dateTime.getSecondOfMinute());
  23 + }
  24 +
  25 + /**
  26 + *
  27 + * @param localDateTime
  28 + * @return
  29 + */
  30 + public static DateTime toDateTime(LocalDateTime localDateTime) {
  31 + return new DateTime().withYear(localDateTime.getYear()).withMonthOfYear(localDateTime.getMonthValue())
  32 + .withDayOfMonth(localDateTime.getDayOfMonth()).withHourOfDay(localDateTime.getHour())
  33 + .withMinuteOfHour(localDateTime.getMinute()).withSecondOfMinute(localDateTime.getSecond());
  34 + }
  35 +}
... ...
job/src/main/java/com/canrd/shop/common/utils/PageUtils.java 0 → 100644
  1 +package com.canrd.shop.common.utils;
  2 +
  3 +import com.baomidou.mybatisplus.core.metadata.IPage;
  4 +import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  5 +import com.canrd.shop.module.vo.BasePageVO;
  6 +import org.springframework.util.CollectionUtils;
  7 +
  8 +import java.io.Serializable;
  9 +import java.util.*;
  10 +
  11 +/**
  12 + * @Author: dengbin
  13 + * @Date: 2020/9/11
  14 + * 分页工具类
  15 + */
  16 +
  17 +public class PageUtils implements Serializable {
  18 + private static final long serialVersionUID = 4359709211352400087L;
  19 + private static final String PAGE_INDEX = "pageNo";
  20 + private static final String PAGE_SIZE = "pageSize";
  21 + private static final String TOTAL_ROWS = "total";
  22 + private static final String TOTAL_PAGES = "pages";
  23 + private static final String RECORDS = "records";
  24 +
  25 + private static final int DEFAULT_PAGE_INDEX = 1;
  26 + private static final int DEFAULT_PAGE_SIZE = 10;
  27 + private static final int DEFAULT_MAP_CAPACITY = 5;
  28 +
  29 + /**
  30 + * 统一分页返回对象
  31 + *
  32 + * @param list
  33 + * @return
  34 + */
  35 + public static Map<String, Object> getUnifiedPageReturn(IPage list) {
  36 + if (list == null) {
  37 + return getUnifiedEmptyPage(DEFAULT_PAGE_INDEX, DEFAULT_PAGE_SIZE);
  38 + }
  39 +
  40 + Map<String, Object> resultMap = new HashMap<>(DEFAULT_MAP_CAPACITY);
  41 + resultMap.put(PAGE_INDEX, list.getCurrent());
  42 + resultMap.put(PAGE_SIZE, list.getSize());
  43 + resultMap.put(RECORDS, list.getRecords());
  44 + resultMap.put(TOTAL_PAGES, list.getPages());
  45 + resultMap.put(TOTAL_ROWS, list.getTotal());
  46 +
  47 + return resultMap;
  48 + }
  49 +
  50 + /**
  51 + * 返回空分页信息给前端
  52 + * 返回空或其他字段不满足前端要求,会报错
  53 + *
  54 + * @return
  55 + */
  56 + public static Map<String, Object> getUnifiedEmptyPage(int pageIndex, int pageSize) {
  57 + Map<String, Object> resultMap = new HashMap<>(DEFAULT_MAP_CAPACITY);
  58 + resultMap.put(PAGE_INDEX, pageIndex);
  59 + resultMap.put(PAGE_SIZE, pageSize);
  60 + resultMap.put(RECORDS, new ArrayList<>());
  61 + resultMap.put(TOTAL_PAGES, 0);
  62 + resultMap.put(TOTAL_ROWS, 0);
  63 + return resultMap;
  64 + }
  65 +
  66 + public static Map<String, Object> getUnifiedEmptyPage(BasePageVO pageVO) {
  67 + return getUnifiedEmptyPage(pageVO.getPageNo(), pageVO.getPageSize());
  68 + }
  69 +
  70 +
  71 + /**
  72 + * 将旧的分页转换成新的分页对象
  73 + *
  74 + * @param oldPage 旧的分页对象,例如:xxDo的分页对象
  75 + * @param records 新的分页对象,例如:xxVo的分页对象
  76 + * @param <T> 新的分页对象的类型
  77 + * @return 统一的返回的分页对象
  78 + */
  79 + public static <T> Map<String, Object> transferPage(IPage<?> oldPage, List<T> records) {
  80 + Page<T> newPage = new Page<>();
  81 + newPage.setCurrent(oldPage.getCurrent());
  82 + newPage.setSize(oldPage.getSize());
  83 + newPage.setRecords(records);
  84 + newPage.setPages(oldPage.getPages());
  85 + newPage.setTotal(oldPage.getTotal());
  86 + return getUnifiedPageReturn(newPage);
  87 + }
  88 +
  89 + /**
  90 + * 统一分页返回对象
  91 + *
  92 + * @param records 分页数据
  93 + * @param pageVO 分页参数
  94 + * @return
  95 + */
  96 + public static Map<String, Object> getPageReturn(List records, BasePageVO pageVO) {
  97 + if (records == null) {
  98 + return getUnifiedEmptyPage(DEFAULT_PAGE_INDEX, DEFAULT_PAGE_SIZE);
  99 + }
  100 + if (CollectionUtils.isEmpty(records)) {
  101 + return getUnifiedEmptyPage(Math.toIntExact(pageVO.getPageNo()), Math.toIntExact(pageVO.getPageSize()));
  102 + }
  103 + Map<String, Object> resultMap = new HashMap<>(DEFAULT_MAP_CAPACITY);
  104 + resultMap.put(PAGE_INDEX, pageVO.getPageNo());
  105 + resultMap.put(PAGE_SIZE, pageVO.getPageSize());
  106 + resultMap.put(RECORDS, records);
  107 + resultMap.put(TOTAL_PAGES, (pageVO.getTotal() + pageVO.getPageSize() - 1) / pageVO.getPageSize());
  108 + resultMap.put(TOTAL_ROWS, pageVO.getTotal());
  109 +
  110 + return resultMap;
  111 + }
  112 +
  113 + public static <T> Page<T> getRAMPageReturn(Integer current, Integer size, List<T> records) {
  114 + if (Objects.isNull(current)) {
  115 + current = 1;
  116 + }
  117 + if (Objects.isNull(size)) {
  118 + size = 10;
  119 + }
  120 + int startIndex = (current - 1) * size;
  121 + int endIndex = Math.min(current * size, records.size());
  122 + if (startIndex > endIndex) {
  123 + startIndex = endIndex;
  124 + }
  125 + Page<T> page = new Page<>();
  126 + page.setCurrent(current);
  127 + page.setSize(size);
  128 + page.setRecords(records.subList(startIndex, endIndex));
  129 + int totalPages = size == 0 ? 0 : records.size() % size == 0 ? (records.size() / size) : (records.size() / size + 1);
  130 + page.setPages(totalPages);
  131 + page.setTotal(records.size());
  132 + return page;
  133 + }
  134 +
  135 +
  136 +}
... ...
job/src/main/java/com/canrd/shop/common/utils/RequestContextUtil.java 0 → 100644
  1 +package com.canrd.shop.common.utils;
  2 +
  3 +import org.springframework.web.context.ContextLoader;
  4 +import org.springframework.web.context.request.RequestContextHolder;
  5 +import org.springframework.web.context.request.ServletRequestAttributes;
  6 +
  7 +import javax.servlet.ServletContext;
  8 +import javax.servlet.http.HttpServletRequest;
  9 +import javax.servlet.http.HttpServletResponse;
  10 +import javax.servlet.http.HttpSession;
  11 +
  12 +
  13 +public class RequestContextUtil {
  14 +
  15 + public static HttpServletRequest getRequest() {
  16 + return getRequestAttributes().getRequest();
  17 + }
  18 +
  19 + public static HttpServletResponse getResponse() {
  20 + return getRequestAttributes().getResponse();
  21 + }
  22 +
  23 + public static HttpSession getSession() {
  24 + return getRequest().getSession();
  25 + }
  26 +
  27 + public static ServletRequestAttributes getRequestAttributes() {
  28 + return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes());
  29 + }
  30 +
  31 + public static ServletContext getServletContext() {
  32 + return ContextLoader.getCurrentWebApplicationContext().getServletContext();
  33 + }
  34 +
  35 +}
... ...
job/src/main/java/com/canrd/shop/common/utils/ServletUtils.java 0 → 100644
  1 +package com.canrd.shop.common.utils;
  2 +
  3 +import com.canrd.shop.common.constant.ServerResult;
  4 +import lombok.extern.slf4j.Slf4j;
  5 +import org.springframework.http.HttpStatus;
  6 +
  7 +import javax.servlet.http.HttpServletResponse;
  8 +import java.io.IOException;
  9 +
  10 +/**
  11 + * @date 2023-02-02
  12 + */
  13 +@Slf4j
  14 +public class ServletUtils {
  15 +
  16 +
  17 + public static void renderServerResult(HttpServletResponse response, ServerResult serverResult, HttpStatus httpStatus)
  18 + {
  19 + try
  20 + {
  21 + response.setStatus(httpStatus.value());
  22 + response.setContentType("application/json");
  23 + response.setCharacterEncoding("utf-8");
  24 + response.getWriter().print(JsonUtil.toJsonString(serverResult));
  25 + }
  26 + catch (IOException e)
  27 + {
  28 + log.error("ServletUtils#renderServerResult:",e);
  29 + }
  30 + }
  31 +
  32 +
  33 + public static void renderExcelFileNotFound(HttpServletResponse response){
  34 + try {
  35 + response.setStatus(404);
  36 + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
  37 + //test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
  38 + response.setHeader("Content-Disposition", "attachment;filename=file.xlsx");
  39 + response.sendError(HttpStatus.NOT_FOUND.value(),"下载失败,资源不存在");
  40 + }catch (IOException e){
  41 + log.error("ServletUtils#renderWithResourceNotFound:",e);
  42 + }
  43 + }
  44 +}
... ...
job/src/main/java/com/canrd/shop/common/utils/SpringContextHolder.java 0 → 100644
  1 +package com.canrd.shop.common.utils;
  2 +
  3 +import lombok.extern.slf4j.Slf4j;
  4 +import org.springframework.beans.BeansException;
  5 +import org.springframework.beans.factory.DisposableBean;
  6 +import org.springframework.context.ApplicationContext;
  7 +import org.springframework.context.ApplicationContextAware;
  8 +
  9 +/**
  10 + * @author Jie
  11 + * @date 2019-01-07
  12 + */
  13 +@Slf4j
  14 +public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
  15 +
  16 + private static ApplicationContext applicationContext = null;
  17 +
  18 + /**
  19 + * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
  20 + */
  21 + @SuppressWarnings("unchecked")
  22 + public static <T> T getBean(String name) {
  23 + assertContextInjected();
  24 + return (T) applicationContext.getBean(name);
  25 + }
  26 +
  27 + /**
  28 + * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
  29 + */
  30 + public static <T> T getBean(Class<T> requiredType) {
  31 + assertContextInjected();
  32 + return applicationContext.getBean(requiredType);
  33 + }
  34 +
  35 + /**
  36 + * 检查ApplicationContext不为空.
  37 + */
  38 + private static void assertContextInjected() {
  39 + if (applicationContext == null) {
  40 + throw new IllegalStateException("applicaitonContext属性未注入, 请在applicationContext" +
  41 + ".xml中定义SpringContextHolder或在SpringBoot启动类中注册SpringContextHolder.");
  42 + }
  43 + }
  44 +
  45 + /**
  46 + * 清除SpringContextHolder中的ApplicationContext为Null.
  47 + */
  48 + private static void clearHolder() {
  49 + log.debug("清除SpringContextHolder中的ApplicationContext:"
  50 + + applicationContext);
  51 + applicationContext = null;
  52 + }
  53 +
  54 + @Override
  55 + public void destroy() {
  56 + SpringContextHolder.clearHolder();
  57 + }
  58 +
  59 + @Override
  60 + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  61 + if (SpringContextHolder.applicationContext != null) {
  62 + log.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext);
  63 + }
  64 + SpringContextHolder.applicationContext = applicationContext;
  65 + }
  66 +}
... ...
job/src/main/java/com/canrd/shop/common/utils/StringUtils.java 0 → 100644
  1 +package com.canrd.shop.common.utils;
  2 +
  3 +import com.canrd.shop.common.constant.Constant;
  4 +import lombok.extern.slf4j.Slf4j;
  5 +import org.springframework.util.CollectionUtils;
  6 +
  7 +import java.io.ByteArrayInputStream;
  8 +import java.io.ByteArrayOutputStream;
  9 +import java.io.IOException;
  10 +import java.math.BigDecimal;
  11 +import java.nio.charset.StandardCharsets;
  12 +import java.util.*;
  13 +import java.util.regex.Matcher;
  14 +import java.util.regex.Pattern;
  15 +import java.util.regex.PatternSyntaxException;
  16 +import java.util.stream.Collectors;
  17 +import java.util.stream.Stream;
  18 +import java.util.zip.GZIPInputStream;
  19 +import java.util.zip.GZIPOutputStream;
  20 +
  21 +/**
  22 + * @param
  23 + * @author 邓彬
  24 + * @version 0.1.0
  25 + * @Description
  26 + * @return
  27 + * @date 2021/4/16 17:44
  28 + * @since 0.1.0
  29 + */
  30 +@Slf4j
  31 +public class StringUtils {
  32 + /**
  33 + * 首字母变小写
  34 + *
  35 + * @param str
  36 + * @return
  37 + */
  38 + public static String firstCharToLowerCase(String str) {
  39 + char firstChar = str.charAt(0);
  40 + if (firstChar >= 'A' && firstChar <= 'Z') {
  41 + char[] arr = str.toCharArray();
  42 + arr[0] += ('a' - 'A');
  43 + return new String(arr);
  44 + }
  45 + return str;
  46 + }
  47 +
  48 + /**
  49 + * 首字母变大写
  50 + *
  51 + * @param str
  52 + * @return
  53 + */
  54 + public static String firstCharToUpperCase(String str) {
  55 + char firstChar = str.charAt(0);
  56 + if (firstChar >= 'a' && firstChar <= 'z') {
  57 + char[] arr = str.toCharArray();
  58 + arr[0] -= ('a' - 'A');
  59 + return new String(arr);
  60 + }
  61 + return str;
  62 + }
  63 +
  64 + /**
  65 + * 判断是否为空
  66 + *
  67 + * @param str
  68 + * @return
  69 + */
  70 + public static boolean isEmpty(final String str) {
  71 + return (str == null) || (str.length() == 0);
  72 + }
  73 +
  74 + /**
  75 + * 判断是否不为空
  76 + *
  77 + * @param str
  78 + * @return
  79 + */
  80 + public static boolean isNotEmpty(final String str) {
  81 + return !isEmpty(str);
  82 + }
  83 +
  84 + /**
  85 + * 判断是否空白
  86 + *
  87 + * @param str
  88 + * @return
  89 + */
  90 + public static boolean isBlank(final String str) {
  91 + int strLen;
  92 + if ((str == null) || ((strLen = str.length()) == 0)) {
  93 + return true;
  94 + }
  95 + for (int i = 0; i < strLen; i++) {
  96 + if (!Character.isWhitespace(str.charAt(i))) {
  97 + return false;
  98 + }
  99 + }
  100 + return true;
  101 + }
  102 +
  103 + /**
  104 + * 判断是否不是空白
  105 + *
  106 + * @param str
  107 + * @return
  108 + */
  109 + public static boolean isNotBlank(final String str) {
  110 + return !isBlank(str);
  111 + }
  112 +
  113 + /**
  114 + * 判断多个字符串全部是否为空
  115 + *
  116 + * @param strings
  117 + * @return
  118 + */
  119 + public static boolean isAllEmpty(String... strings) {
  120 + if (strings == null) {
  121 + return true;
  122 + }
  123 + for (String str : strings) {
  124 + if (isNotEmpty(str)) {
  125 + return false;
  126 + }
  127 + }
  128 + return true;
  129 + }
  130 +
  131 + /**
  132 + * 判断多个字符串其中任意一个是否为空
  133 + *
  134 + * @param strings
  135 + * @return
  136 + */
  137 + public static boolean isHasEmpty(String... strings) {
  138 + if (strings == null) {
  139 + return true;
  140 + }
  141 + for (String str : strings) {
  142 + if (isEmpty(str)) {
  143 + return true;
  144 + }
  145 + }
  146 + return false;
  147 + }
  148 +
  149 + /**
  150 + * 判断多个字符串是否都为blank
  151 + *
  152 + * @param strings
  153 + * @return
  154 + */
  155 + public static boolean isAllBlank(String... strings) {
  156 + if (strings == null) {
  157 + return true;
  158 + }
  159 + for (String str : strings) {
  160 + if (isNotBlank(str)) {
  161 + return false;
  162 + }
  163 + }
  164 + return true;
  165 + }
  166 +
  167 + /**
  168 + * checkValue为 null 或者为 "" 时返回 defaultValue
  169 + *
  170 + * @param checkValue
  171 + * @param defaultValue
  172 + * @return
  173 + */
  174 + public static String isEmpty(String checkValue, String defaultValue) {
  175 + return isEmpty(checkValue) ? defaultValue : checkValue;
  176 + }
  177 +
  178 + /**
  179 + * 字符串不为 null 而且不为 "" 并且等于other
  180 + *
  181 + * @param str
  182 + * @param other
  183 + * @return
  184 + */
  185 + public static boolean isNotEmptyAndEqualsOther(String str, String other) {
  186 + return !isEmpty(str) && str.equals(other);
  187 + }
  188 +
  189 + /**
  190 + * 字符串不为 null 而且不为 "" 并且不等于other
  191 + *
  192 + * @param str
  193 + * @param other
  194 + * @return
  195 + */
  196 + public static boolean isNotEmptyAndNotEqualsOther(String str, String... other) {
  197 + if (isEmpty(str)) {
  198 + return false;
  199 + }
  200 + for (String s : other) {
  201 + if (str.equals(s)) {
  202 + return false;
  203 + }
  204 + }
  205 + return true;
  206 + }
  207 +
  208 + /**
  209 + * 字符串不等于other
  210 + *
  211 + * @param str
  212 + * @param other
  213 + * @return
  214 + */
  215 + public static boolean isNotEqualsOther(String str, String... other) {
  216 + for (String s : other) {
  217 + if (s.equals(str)) {
  218 + return false;
  219 + }
  220 + }
  221 + return true;
  222 + }
  223 +
  224 + /**
  225 + * 判断字符串不为空
  226 + *
  227 + * @param strings
  228 + * @return
  229 + */
  230 + public static boolean isNotEmpty(String... strings) {
  231 + if (strings == null || strings.length == 0) {
  232 + return false;
  233 + }
  234 + for (String str : strings) {
  235 + if (str == null || "".equals(str.trim())) {
  236 + return false;
  237 + }
  238 + }
  239 + return true;
  240 + }
  241 +
  242 + /**
  243 + * 比较字符相等
  244 + *
  245 + * @param value
  246 + * @param equals
  247 + * @return
  248 + */
  249 + public static boolean equals(String value, String equals) {
  250 + if (isAllEmpty(value, equals)) {
  251 + return true;
  252 + }
  253 + //进一步判断value是不是空,如果是空,要直接equals会报NPE异常
  254 + if (value == null) {
  255 + return false;
  256 + }
  257 + return value.equals(equals);
  258 + }
  259 +
  260 + /**
  261 + * @description 将字符串转换为数字数组
  262 + * @author 黄楷涵
  263 + * @date 2020/9/15
  264 + */
  265 + public static int[] stringParseToInt(String str, String regex) {
  266 + return stringParseToInt(str.split(regex));
  267 + }
  268 +
  269 + /**
  270 + * @description 将字符串数组转换为数字数组
  271 + * @author dengbin
  272 + * @date 2020/9/15
  273 + */
  274 + public static int[] stringParseToInt(String[] str) {
  275 + int[] num = new int[str.length];
  276 + for (int i = 0; i < str.length; i++) {
  277 + num[i] = Integer.parseInt(str[i]);
  278 + }
  279 + return num;
  280 + }
  281 +
  282 + /**
  283 + * 比较字符串不相等
  284 + *
  285 + * @param value
  286 + * @param equals
  287 + * @return
  288 + */
  289 + public static boolean isNotEquals(String value, String equals) {
  290 + return !equals(value, equals);
  291 + }
  292 +
  293 + public static String[] split(String content, String separatorChars) {
  294 + return splitWorker(content, separatorChars, -1, false);
  295 + }
  296 +
  297 + public static String[] split(String str, String separatorChars, int max) {
  298 + return splitWorker(str, separatorChars, max, false);
  299 + }
  300 +
  301 + public static final String[] EMPTY_STRING_ARRAY = new String[0];
  302 +
  303 + private static String[] splitWorker(String str, String separatorChars, int max, boolean preserveAllTokens) {
  304 + if (str == null) {
  305 + return null;
  306 + }
  307 + int len = str.length();
  308 + if (len == 0) {
  309 + return EMPTY_STRING_ARRAY;
  310 + }
  311 + List<String> list = new ArrayList<String>();
  312 + int sizePlus1 = 1;
  313 + int i = 0, start = 0;
  314 + boolean match = false;
  315 + boolean lastMatch = false;
  316 + if (separatorChars == null) {
  317 + while (i < len) {
  318 + if (Character.isWhitespace(str.charAt(i))) {
  319 + if (match || preserveAllTokens) {
  320 + lastMatch = true;
  321 + if (sizePlus1++ == max) {
  322 + i = len;
  323 + lastMatch = false;
  324 + }
  325 + list.add(str.substring(start, i));
  326 + match = false;
  327 + }
  328 + start = ++i;
  329 + continue;
  330 + }
  331 + lastMatch = false;
  332 + match = true;
  333 + i++;
  334 + }
  335 + } else if (separatorChars.length() == 1) {
  336 + char sep = separatorChars.charAt(0);
  337 + while (i < len) {
  338 + if (str.charAt(i) == sep) {
  339 + if (match || preserveAllTokens) {
  340 + lastMatch = true;
  341 + if (sizePlus1++ == max) {
  342 + i = len;
  343 + lastMatch = false;
  344 + }
  345 + list.add(str.substring(start, i));
  346 + match = false;
  347 + }
  348 + start = ++i;
  349 + continue;
  350 + }
  351 + lastMatch = false;
  352 + match = true;
  353 + i++;
  354 + }
  355 + } else {
  356 + while (i < len) {
  357 + if (separatorChars.indexOf(str.charAt(i)) >= 0) {
  358 + if (match || preserveAllTokens) {
  359 + lastMatch = true;
  360 + if (sizePlus1++ == max) {
  361 + i = len;
  362 + lastMatch = false;
  363 + }
  364 + list.add(str.substring(start, i));
  365 + match = false;
  366 + }
  367 + start = ++i;
  368 + continue;
  369 + }
  370 + lastMatch = false;
  371 + match = true;
  372 + i++;
  373 + }
  374 + }
  375 + if (match || (preserveAllTokens && lastMatch)) {
  376 + list.add(str.substring(start, i));
  377 + }
  378 + return list.toArray(EMPTY_STRING_ARRAY);
  379 + }
  380 +
  381 + /**
  382 + * 消除转义字符
  383 + *
  384 + * @param str
  385 + * @return
  386 + */
  387 + public static String escapeXml(String str) {
  388 + if (str == null) {
  389 + return "";
  390 + }
  391 + StringBuilder sb = new StringBuilder();
  392 + for (int i = 0; i < str.length(); ++i) {
  393 + char c = str.charAt(i);
  394 + switch (c) {
  395 + case '\u00FF':
  396 + case '\u0024':
  397 + break;
  398 + case '&':
  399 + sb.append("&amp;");
  400 + break;
  401 + case '<':
  402 + sb.append("&lt;");
  403 + break;
  404 + case '>':
  405 + sb.append("&gt;");
  406 + break;
  407 + case '\"':
  408 + sb.append("&quot;");
  409 + break;
  410 + case '\'':
  411 + sb.append("&apos;");
  412 + break;
  413 + default:
  414 + if (c <= '\u001F') {
  415 + break;
  416 + }
  417 + if (c >= '\uE000' && c <= '\uF8FF') {
  418 + break;
  419 + }
  420 + if (c >= '\uFFF0') {
  421 + break;
  422 + }
  423 + sb.append(c);
  424 + break;
  425 + }
  426 + }
  427 + return sb.toString();
  428 + }
  429 +
  430 + /**
  431 + * 将字符串中特定模式的字符转换成map中对应的值
  432 + *
  433 + * @param s 需要转换的字符串
  434 + * @param map 转换所需的键值对集合
  435 + * @return 转换后的字符串
  436 + */
  437 + public static String replace(String s, Map<String, Object> map) {
  438 + StringBuilder ret = new StringBuilder((int) (s.length() * 1.5));
  439 + int cursor = 0;
  440 + for (int start, end; (start = s.indexOf("${", cursor)) != -1 && (end = s.indexOf("}", start)) != -1; ) {
  441 + ret.append(s.substring(cursor, start)).append(map.get(s.substring(start + 2, end)));
  442 + cursor = end + 1;
  443 + }
  444 + ret.append(s.substring(cursor, s.length()));
  445 + return ret.toString();
  446 + }
  447 +
  448 + public static String replace(String s, Object... objs) {
  449 + if (objs == null || objs.length == 0) {
  450 + return s;
  451 + }
  452 + if (!s.contains("{}")) {
  453 + return s;
  454 + }
  455 + StringBuilder ret = new StringBuilder((int) (s.length() * 1.5));
  456 + int cursor = 0;
  457 + int index = 0;
  458 + for (int start; (start = s.indexOf("{}", cursor)) != -1; ) {
  459 + ret.append(s.substring(cursor, start));
  460 + if (index < objs.length) {
  461 + ret.append(objs[index]);
  462 + } else {
  463 + ret.append("{}");
  464 + }
  465 + cursor = start + 2;
  466 + index++;
  467 + }
  468 + ret.append(s.substring(cursor, s.length()));
  469 + return ret.toString();
  470 + }
  471 +
  472 +
  473 + /**
  474 + * 转换为字节数组
  475 + *
  476 + * @param bytes
  477 + * @return
  478 + */
  479 + public static String toString(byte[] bytes) {
  480 + return new String(bytes, StandardCharsets.UTF_8);
  481 + }
  482 +
  483 + /**
  484 + * 转换为字节数组
  485 + *
  486 + * @param str
  487 + * @return
  488 + */
  489 + public static byte[] getBytes(String str) {
  490 + return str != null ? str.getBytes(StandardCharsets.UTF_8) : null;
  491 + }
  492 +
  493 + public static boolean isNumeric(String cs) {
  494 + if (isEmpty(cs)) {
  495 + return false;
  496 + }
  497 + for (int i = 0, sz = cs.length(); i < sz; ++i) {
  498 + if (!Character.isDigit(cs.charAt(i))) {
  499 + return false;
  500 + }
  501 + }
  502 + return true;
  503 +
  504 + }
  505 +
  506 + /**
  507 + * 手机号脱敏
  508 + *
  509 + * @param phoneNumber
  510 + * @return
  511 + */
  512 + public static String desensitizedPhoneNumber(String phoneNumber) {
  513 + if (StringUtils.isNotEmpty(phoneNumber)) {
  514 + phoneNumber = phoneNumber.replaceAll("(\\w{3})\\w*(\\w{4})", "$1****$2");
  515 + }
  516 + return phoneNumber;
  517 + }
  518 +
  519 + /**
  520 + * 校验3位小数
  521 + *
  522 + * @param str
  523 + * @return
  524 + */
  525 + public static boolean checkDecimal(String str) {
  526 + return Pattern.compile(Constant.DICMAL_REGEXP).matcher(str).find();
  527 + }
  528 +
  529 + /**
  530 + * 校验11位国内手机号
  531 + * <p>规则: 11位数,首位必须为1,第二位可以是3-9;其他位数不限制
  532 + *
  533 + * @param phone 手机号
  534 + * @return 格式正确则返回false; 反之为true
  535 + * @author A80080
  536 + * @createDate 2020/12/19
  537 + */
  538 + public static boolean checkPhoneNum(String phone) {
  539 + return StringUtils.isEmpty(phone) || !Pattern.compile("^1([3-9])[0-9]{9}$").matcher(phone).find();
  540 + }
  541 +
  542 + /**
  543 + * @param str
  544 + * @return boolean
  545 + * @Description 判断字符串是否含有空格
  546 + * @version 0.1.0
  547 + * @author 邓彬
  548 + * @date 2021/1/13 18:10
  549 + * @since 0.1.0
  550 + */
  551 + public static boolean checkStringContainEmpty(String str) {
  552 + return !StringUtils.isEmpty(str) && str.contains(" ");
  553 + }
  554 +
  555 + /**
  556 + * 字符串切分
  557 + *
  558 + * @param splitStr
  559 + * @param splitFlag
  560 + * @return
  561 + */
  562 + public static List<String> splitTag(String splitStr, String splitFlag) {
  563 + return StringUtils.isBlank(splitStr) || StringUtils.isBlank(splitFlag) ?
  564 + new ArrayList<>() :
  565 + Arrays.stream(splitStr.split(splitFlag)).collect(Collectors.toList());
  566 + }
  567 +
  568 + /**
  569 + * @param name
  570 + * @return true代表全是汉字
  571 + * @Description 校验String是否全是中文
  572 + * @version 0.1.0
  573 + * @author 邓彬
  574 + * @date 2021/1/18 19:54
  575 + * @since 0.1.0
  576 + */
  577 + public static boolean checkNameChina(String name) {
  578 + boolean res = true;
  579 + char[] cTemp = name.toCharArray();
  580 + for (int i = 0; i < name.length(); i++) {
  581 + if (!isChinese(cTemp[i])) {
  582 + res = false;
  583 + break;
  584 + }
  585 + }
  586 + return res;
  587 + }
  588 +
  589 + /**
  590 + * @param c
  591 + * @return true代表是汉字
  592 + * @Description 判定输入的是否是汉字
  593 + * @version 0.1.0
  594 + * @author 邓彬
  595 + * @date 2021/1/18 19:53
  596 + * @since 0.1.0
  597 + */
  598 + public static boolean isChinese(char c) {
  599 + Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
  600 + if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
  601 + || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
  602 + || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
  603 + || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
  604 + || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
  605 + || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
  606 + return true;
  607 + }
  608 + return false;
  609 + }
  610 +
  611 + /**
  612 + * @param c
  613 + * @return true代表符合条件
  614 + * @Description 校验某个字符是否是a-z、A-Z、_、0-9
  615 + * @version 0.1.0
  616 + * @author 邓彬
  617 + * @date 2021/1/18 19:56
  618 + * @since 0.1.0
  619 + */
  620 + public static boolean isWord(char c) {
  621 + return Pattern.compile("[\\w]").matcher("" + c).matches();
  622 + }
  623 +
  624 + /**
  625 + * @param str
  626 + * @return boolean
  627 + * @Description 字符串是否仅包含数字和字母
  628 + * @version 0.1.0
  629 + * @author 邓彬
  630 + * @date 2021/1/18 20:00
  631 + * @since 0.1.0
  632 + */
  633 + public static boolean isLetterDigit(String str) {
  634 + return str.matches("^[a-z0-9A-Z]+$");
  635 + }
  636 +
  637 + /**
  638 + * @param str
  639 + * @return boolean
  640 + * @Description 判断是否是纯数字
  641 + * @version 0.1.0
  642 + * @author 邓彬
  643 + * @date 2021/1/23 16:33
  644 + * @since 0.1.0
  645 + */
  646 + public static boolean isDigit(String str) {
  647 + return str.matches("^[0-9]+$");
  648 + }
  649 +
  650 + /**
  651 + * 是否合法手机号
  652 + *
  653 + * @param phone
  654 + * @return
  655 + */
  656 + public static boolean isMobilePhone(String phone) {
  657 + return Pattern.compile(Constant.PHONE_REGEXP).matcher(phone).matches();
  658 + }
  659 +
  660 + /**
  661 + * 是否脱敏手机号
  662 + *
  663 + * @param phone
  664 + * @return
  665 + */
  666 + public static boolean isDesensitizationMobilePhone(String phone) {
  667 + return Pattern.compile(Constant.PHONE_DESENSITIZATION_REGEXP).matcher(phone).matches();
  668 + }
  669 +
  670 + /**
  671 + * 判断String是否是整数<br>
  672 + * 支持10进制
  673 + *
  674 + * @param s String
  675 + * @return 是否为整数
  676 + */
  677 + public static boolean isInteger(String s) {
  678 + try {
  679 + Integer.parseInt(s);
  680 + } catch (NumberFormatException e) {
  681 + return false;
  682 + }
  683 + return true;
  684 + }
  685 +
  686 + /**
  687 + * 判断对象能否转
  688 + *
  689 + * @param o Object
  690 + * @return 是否为Integer
  691 + */
  692 + public static boolean isInteger(Object o) {
  693 + try {
  694 + Integer.parseInt(String.valueOf(o));
  695 + return true;
  696 + } catch (NumberFormatException e) {
  697 + return false;
  698 + }
  699 + }
  700 +
  701 + public static String escapeCharacter(String str) {
  702 + if (!isEmpty(str)) {
  703 + if (str.contains("\\")) {
  704 + str = str.replaceAll("\\\\", "\\\\\\\\");
  705 + }
  706 + }
  707 + return str;
  708 + }
  709 +
  710 + /**
  711 + * @param str
  712 + * @return boolean
  713 + * @Description 匹配字符串是,数字、26个英文字母、下划线组成的8-16位的字符串组合
  714 + * @version 0.1.0
  715 + * @author A80077-刘始达
  716 + * @date 2021/04/06
  717 + * @since 0.1.0
  718 + */
  719 + public static boolean checkPWD(String str) {
  720 + return str.matches("^(?=.*([a-zA-Z].*))(?=.*[0-9].*)[a-zA-Z0-9-_]{8,16}+$");
  721 + }
  722 +
  723 + /**
  724 + * 判断是否包含特殊字符
  725 + *
  726 + * @param str
  727 + * @return
  728 + */
  729 + public static boolean checkSpecificSymbol(String str) {
  730 + String regEx = "[ _`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~!@#¥%……&*()——+|{}【】‘;:”“’。,、?]|\n|\r|\t";
  731 + Pattern p = Pattern.compile(regEx);
  732 + Matcher m = p.matcher(str);
  733 + return m.find();
  734 + }
  735 +
  736 + /**
  737 + * 拼接图片标签url
  738 + *
  739 + * @param str
  740 + * @param ossDomain
  741 + * @return
  742 + */
  743 + public static String replaceHtmlTag(String str, String ossDomain) {
  744 + if (StringUtils.isEmpty(str)) {
  745 + return "";
  746 + }
  747 + if (StringUtils.isEmpty(ossDomain)) {
  748 + return str;
  749 + }
  750 + return replaceHtmlTag(str, "img", "src", "src=\"" + ossDomain, "\"");
  751 + }
  752 +
  753 + /**
  754 + * html格式处理:替换指定标签的属性和值
  755 + *
  756 + * @param str 需要处理的字符串
  757 + * @param tag 标签名称
  758 + * @param tagAttrib 要替换的标签属性值
  759 + * @param startTag 新标签开始标记
  760 + * @param endTag 新标签结束标记
  761 + * @return
  762 + */
  763 + public static String replaceHtmlTag(String str, String tag, String tagAttrib, String startTag, String endTag) {
  764 + String regxpForTag = "<\\s*" + tag + "\\s+([^>]*)\\s*";
  765 + String regxpForTagAttrib = tagAttrib + "=\\s*\"([^\"]+)\"";
  766 + Pattern patternForTag = Pattern.compile(regxpForTag, Pattern.CASE_INSENSITIVE);
  767 + Pattern patternForAttrib = Pattern.compile(regxpForTagAttrib, Pattern.CASE_INSENSITIVE);
  768 + Matcher matcherForTag = patternForTag.matcher(str);
  769 + StringBuffer sb = new StringBuffer();
  770 + boolean result = matcherForTag.find();
  771 + while (result) {
  772 + StringBuffer stringBuffer = new StringBuffer("<" + tag + " ");
  773 + Matcher matcherForAttrib = patternForAttrib.matcher(matcherForTag.group(1));
  774 + if (matcherForAttrib.find()) {
  775 + String attributeStr = matcherForAttrib.group(1);
  776 + if (!attributeStr.contains("https") && !attributeStr.contains("http")) {
  777 + matcherForAttrib.appendReplacement(stringBuffer, startTag + attributeStr + endTag);
  778 + }
  779 + }
  780 + matcherForAttrib.appendTail(stringBuffer);
  781 + matcherForTag.appendReplacement(sb, stringBuffer.toString());
  782 + result = matcherForTag.find();
  783 + }
  784 + matcherForTag.appendTail(sb);
  785 + return sb.toString();
  786 + }
  787 +
  788 + /**
  789 + * @param str
  790 + * @return java.util.Map<String, List < String>>
  791 + * @Description 字符串的连续切割 返回中文词组 数字和字母的集合
  792 + * @version 0.1.0
  793 + * @author 邓彬
  794 + * @date 2021/4/15 13:53
  795 + * @since 0.1.0
  796 + */
  797 + public static Map<String, List<String>> convertStrToChineseList(String str) {
  798 + if (StringUtils.isEmpty(str)) {
  799 + return null;
  800 + }
  801 + Map<String, List<String>> resultMap = new HashMap<>();
  802 + List<String> chineseList;
  803 + List<String> charList;
  804 + char[] list = str.toCharArray();
  805 + StringBuilder chineseStr = new StringBuilder();
  806 + StringBuilder charStr = new StringBuilder();
  807 + for (char c : list) {
  808 + if (StringUtils.isChinese(c)) {
  809 + chineseStr.append(c);
  810 + charStr.append(Constant.SLASH_MARK_CHARACTER);
  811 + } else if (Character.isLetterOrDigit(c)) {
  812 + charStr.append(c);
  813 + chineseStr.append(Constant.SLASH_MARK_CHARACTER);
  814 + } else {
  815 + charStr.append(Constant.SLASH_MARK_CHARACTER);
  816 + chineseStr.append(Constant.SLASH_MARK_CHARACTER);
  817 + }
  818 +
  819 + }
  820 + chineseList = Arrays.stream(chineseStr.toString()
  821 + .split(Constant.SLASH_MARK_CHARACTER))
  822 + .filter(StringUtils::isNotEmpty).collect(Collectors.toList());
  823 + charList = Arrays.stream(charStr.toString()
  824 + .split(Constant.SLASH_MARK_CHARACTER))
  825 + .filter(StringUtils::isNotEmpty).map(String::toLowerCase).collect(Collectors.toList());
  826 +
  827 + resultMap.put("chineseKey", chineseList);
  828 + resultMap.put("charKey", charList);
  829 + return resultMap;
  830 + }
  831 +
  832 + /**
  833 + * 单个字符转换为小写
  834 + *
  835 + * @param c
  836 + * @return
  837 + */
  838 + public static char singleCharToLowerCase(char c) {
  839 + if (c >= 'A' && c <= 'Z') {
  840 + c += ('a' - 'A');
  841 + return c;
  842 + }
  843 + return c;
  844 + }
  845 +
  846 + public static boolean isLong(String shopId) {
  847 + try {
  848 + Long.parseLong(shopId);
  849 + } catch (NumberFormatException e) {
  850 + return false;
  851 + }
  852 + return true;
  853 + }
  854 +
  855 + public static String priceFormatting(String price) {
  856 + if (StringUtils.isEmpty(price)) {
  857 + return Constant.EMPTY_STRING;
  858 + }
  859 +
  860 + String newPrice = "";
  861 + // 价格不存在小数点,则直接返回,无需处理
  862 + if (!price.contains(Constant.POINT_BAR_CHARACTER)) {
  863 + newPrice = price;
  864 + return newPrice;
  865 + }
  866 +
  867 + // 有小数点,则分割字符串
  868 + String[] s = price.split("\\.");
  869 +
  870 + // 小数位数大于0 且小于2 且存在非0字符
  871 + if (s[1].length() > 0 && s[1].length() <= 2 && !judgeIsNumeric(s[1])) {
  872 + BigDecimal bigDecimal = new BigDecimal(price).setScale(2, BigDecimal.ROUND_HALF_UP);
  873 + newPrice = bigDecimal.toPlainString();
  874 + }
  875 + // 【保留这个else if】小数位数大于0 且大于2 且存在非0字符,理论上不会存在,因为新增商品时已经限定最多输入2个小数点
  876 + else if (s[1].length() > 0 && s[1].length() > 2 && !judgeIsNumeric(s[1])) {
  877 + BigDecimal bigDecimal = new BigDecimal(price).setScale(2, BigDecimal.ROUND_HALF_UP);
  878 + String[] split = bigDecimal.toPlainString().split("\\.");
  879 + if (split[1].length() > 0 && judgeIsNumeric(split[1])) {
  880 + newPrice = new BigDecimal(bigDecimal.toPlainString()).setScale(0, BigDecimal.ROUND_HALF_UP).toPlainString();
  881 + } else {
  882 + newPrice = bigDecimal.toPlainString();
  883 + }
  884 + } else {
  885 + // 小数位数大于0 且小于2 且小数点都是0
  886 + newPrice = new BigDecimal(price).setScale(0, BigDecimal.ROUND_HALF_UP).toPlainString();
  887 + }
  888 + return newPrice;
  889 + }
  890 +
  891 + /**
  892 + * 判断字符串是否只包含0
  893 + *
  894 + * @param str
  895 + * @return
  896 + */
  897 + private static boolean judgeIsNumeric(String str) {
  898 + return Pattern.compile("[0]*").matcher(str).matches();
  899 + }
  900 +
  901 + /**
  902 + * 字符串以","分隔后转为String[]
  903 + *
  904 + * @param s
  905 + * @return
  906 + */
  907 + public static String[] string2ArraySplitByComma(String s) {
  908 + if (s == null || s.length() == 0) {
  909 + return new String[]{};
  910 + }
  911 + return s.split(Constant.COMMA_CHARACTER);
  912 + }
  913 +
  914 + public static boolean isStringArrayContainsSpecifiedValue(String[] strings, String value) {
  915 + if (null == strings || strings.length <= 0 || value == null || value.length() == 0) {
  916 + return false;
  917 + }
  918 + boolean isContainsSpecifiedValue = false;
  919 + for (String s : strings) {
  920 + if (s.equals(value)) {
  921 + isContainsSpecifiedValue = true;
  922 + break;
  923 + }
  924 + }
  925 + return isContainsSpecifiedValue;
  926 + }
  927 +
  928 + /**
  929 + * 字符串以","分隔后转为list
  930 + *
  931 + * @param s
  932 + * @return
  933 + */
  934 + public static List<String> string2ListSplitByComma(String s) {
  935 + List<String> stringList = new ArrayList<>();
  936 + if (s == null || s.length() == 0) {
  937 + return stringList;
  938 + }
  939 + String[] strArray = string2ArraySplitByComma(s);
  940 +
  941 + for (String st : strArray) {
  942 + if (null != st && st.trim() != null || st.trim().length() != 0) {
  943 + stringList.add(st.trim());
  944 + }
  945 + }
  946 +
  947 + return stringList;
  948 + }
  949 +
  950 + /**
  951 + * 字符串按照特殊符号
  952 + * ".*[`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~!@#¥%……&*()——+|{}【】‘;:”“’。,、?\\\\]+.*"
  953 + * 截取转成字符串集合
  954 + *
  955 + * @param str
  956 + * @return
  957 + */
  958 + public static List<String> splitStringBySpecificSymbol(String str) throws PatternSyntaxException {
  959 + String regEx = "[`~!@#$%^&*()\\-+=|{}':;,\\[\\].<>/?!¥…()—【】‘;:”“’。,、?\\\\]";
  960 + Pattern p = Pattern.compile(regEx);
  961 + Matcher m = p.matcher(str);
  962 + return Stream.of(m.replaceAll("_").split("_")).map(String::trim).filter(StringUtils::isNotBlank).collect(Collectors.toList());
  963 + }
  964 +
  965 + /**
  966 + * 使用gzip压缩字符串
  967 + *
  968 + * @param str 要压缩的字符串
  969 + * @return 压缩后的字符串
  970 + */
  971 + public static String compressByGZip(String str) {
  972 + if (str == null || str.length() == 0) {
  973 + return str;
  974 + }
  975 + ByteArrayOutputStream out = new ByteArrayOutputStream();
  976 + GZIPOutputStream gzip = null;
  977 + try {
  978 + gzip = new GZIPOutputStream(out);
  979 + gzip.write(str.getBytes(StandardCharsets.UTF_8));
  980 + } catch (IOException e) {
  981 + log.error("compressByGZip error: {}", e);
  982 + } finally {
  983 + if (gzip != null) {
  984 + try {
  985 + gzip.close();
  986 + } catch (IOException e) {
  987 + log.error("compressByGZip gzip close error: {}", e);
  988 + }
  989 + }
  990 + }
  991 + // 必须在关闭gzip流之后再读取
  992 + try {
  993 + return new sun.misc.BASE64Encoder().encode(out.toByteArray());
  994 + } catch (Exception e) {
  995 + log.error("compressByGZip BASE64Encoder error:{}", e);
  996 + }
  997 + return str;
  998 + }
  999 +
  1000 + /**
  1001 + * 使用gzip解压缩
  1002 + *
  1003 + * @param compressedStr 已压缩的字符串
  1004 + * @return 解压之后的字符串
  1005 + */
  1006 + public static String uncompressByGZip(String compressedStr) {
  1007 + if (compressedStr == null || compressedStr.length() == 0) {
  1008 + return compressedStr;
  1009 + }
  1010 +
  1011 + String decompressed;
  1012 + try (
  1013 + ByteArrayOutputStream out = new ByteArrayOutputStream();
  1014 + ByteArrayInputStream in = new ByteArrayInputStream(new sun.misc.BASE64Decoder().decodeBuffer(compressedStr));
  1015 + GZIPInputStream ginzip = new GZIPInputStream(in);
  1016 + ) {
  1017 + byte[] buffer = new byte[1024];
  1018 + int offset;
  1019 + while ((offset = ginzip.read(buffer)) != -1) {
  1020 + out.write(buffer, 0, offset);
  1021 + }
  1022 + decompressed = out.toString();
  1023 + } catch (IOException e) {
  1024 + log.error("uncompressByGZip error:{}", e);
  1025 + return compressedStr;
  1026 + }
  1027 + return decompressed;
  1028 + }
  1029 +
  1030 + /**
  1031 + * 将list转为字符串,用逗号隔开
  1032 + *
  1033 + * @param list
  1034 + * @return
  1035 + */
  1036 + public static String listTransToStr(List<String> list) {
  1037 + if (CollectionUtils.isEmpty(list)) return null;
  1038 + StringBuilder sb = new StringBuilder();
  1039 + list.forEach(x -> {
  1040 + sb.append(x);
  1041 + sb.append(",");
  1042 + });
  1043 + String str = sb.toString();
  1044 + return str.substring(0, str.length() - 1);
  1045 + }
  1046 +
  1047 + /**
  1048 + * 是否包含中英文
  1049 + *
  1050 + * @param str
  1051 + * @return
  1052 + */
  1053 + public static boolean checkCnAndEn(String str) {
  1054 + String regEx = Constant.CHI_EN_REGEXP;
  1055 + Pattern p = Pattern.compile(regEx);
  1056 + Matcher m = p.matcher(str);
  1057 + return m.find();
  1058 + }
  1059 +
  1060 +
  1061 + /**
  1062 + * @param code 要隐藏显示的字符串
  1063 + * @param head 前面保留的位数
  1064 + * @param tail 后面保留的位数
  1065 + * @return 处理后的字符串
  1066 + */
  1067 + public static String getEncryptCode(String code, int head, int tail) {
  1068 + int body = code.length() - head - tail;
  1069 + String regexVar = "(\\w{%d})(\\w{%d})(\\w{%d})";
  1070 + String regex = String.format(regexVar, head, body, tail);
  1071 + String bodyPart = code.replaceAll(regex, "$2");
  1072 + String bodyEncrypt = bodyPart.replaceAll("\\w", "*");
  1073 + String replacement = String.format("$1%s$3", bodyEncrypt);
  1074 + return code.replaceAll(regex, replacement);
  1075 + }
  1076 +}
... ...
job/src/main/java/com/canrd/shop/common/utils/TemplateFormatUtils.java 0 → 100644
  1 +package com.canrd.shop.common.utils;
  2 +
  3 +import java.util.Map;
  4 +import java.util.regex.Matcher;
  5 +import java.util.regex.Pattern;
  6 +
  7 +/**
  8 + *
  9 + * 消息模板占位符替换工具
  10 + *
  11 + * @author fanzhenyu
  12 + * @date 2022-04-20
  13 + */
  14 +public class TemplateFormatUtils {
  15 +
  16 +
  17 + /**
  18 + * 正则 匹配 { + "多个任意字符" + }
  19 + */
  20 + private static final String DEFAULT_REG = "\\{[\\w]+\\}";
  21 +
  22 + /**
  23 + *
  24 + * @param text 原模板 占位符格式必须为:{fieldName}
  25 + * @param map 模板参数
  26 + * @return
  27 + */
  28 + public static String replaceTemplateContent(String text, Map<String, String> map){
  29 + return replaceTemplateContent(text,map,DEFAULT_REG);
  30 + }
  31 +
  32 + /**
  33 + *
  34 + * @param text 原模板 占位符格式必须为:{fieldName}
  35 + * @param map 模板参数
  36 + * @param reg 自定义占位符样式 - 正则匹配
  37 + * @return
  38 + */
  39 + public static String replaceTemplateContent(String text,Map<String,String> map,String reg){
  40 +
  41 + if(StringUtils.isBlank(reg)){
  42 + reg = DEFAULT_REG;
  43 + }
  44 +
  45 + Pattern pattern = Pattern.compile(reg);
  46 + Matcher m = pattern.matcher(text);
  47 + while(m.find()){
  48 + String currentGroup = m.group();
  49 + String currentPattern = currentGroup.replaceAll("^\\{", "").replaceAll("\\}$", "").trim();
  50 + String mapValue = map.get(currentPattern);
  51 + if (mapValue != null){
  52 + text = text.replace(currentGroup, mapValue);
  53 + }
  54 + }
  55 + return text;
  56 + }
  57 +}
... ...
job/src/main/java/com/canrd/shop/common/utils/ThrowableUtil.java 0 → 100644
  1 +package com.canrd.shop.common.utils;
  2 +
  3 +
  4 +import com.canrd.shop.common.exception.BadRequestException;
  5 +
  6 +import javax.validation.ConstraintViolationException;
  7 +import java.io.PrintWriter;
  8 +import java.io.StringWriter;
  9 +
  10 +/**
  11 + * 异常工具 2019-01-06
  12 + */
  13 +public class ThrowableUtil {
  14 +
  15 + /**
  16 + * 获取堆栈信息
  17 + */
  18 + public static String getStackTrace(Throwable throwable) {
  19 + StringWriter sw = new StringWriter();
  20 + try (PrintWriter pw = new PrintWriter(sw)) {
  21 + throwable.printStackTrace(pw);
  22 + return sw.toString();
  23 + }
  24 + }
  25 +
  26 + public static void throwForeignKeyException(Throwable e, String msg) {
  27 + Throwable t = e.getCause();
  28 + while ((t != null) && !(t instanceof ConstraintViolationException)) {
  29 + t = t.getCause();
  30 + }
  31 + if (t != null) {
  32 + throw new BadRequestException(msg);
  33 + }
  34 + assert false;
  35 + throw new BadRequestException("删除失败:" + t.getMessage());
  36 + }
  37 +}
... ...
job/src/main/java/com/canrd/shop/common/utils/TransactionHelper.java 0 → 100644
  1 +package com.canrd.shop.common.utils;
  2 +
  3 +import org.springframework.stereotype.Component;
  4 +import org.springframework.transaction.annotation.Propagation;
  5 +import org.springframework.transaction.annotation.Transactional;
  6 +
  7 +import java.util.function.Supplier;
  8 +
  9 +/**
  10 + * @author:
  11 + * @date: 2021/12/21
  12 + */
  13 +@Component
  14 +public class TransactionHelper {
  15 +
  16 + @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
  17 + public <T> T run(Supplier<T> command) {
  18 + return command.get();
  19 + }
  20 +
  21 + @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
  22 + public void run(Runnable command) {
  23 + command.run();
  24 + }
  25 +
  26 +
  27 +}
... ...
job/src/main/java/com/canrd/shop/config/MybatisPlusConfig.java 0 → 100644
  1 +package com.canrd.shop.config;
  2 +
  3 +import org.springframework.context.annotation.Configuration;
  4 +
  5 +
  6 +@Configuration
  7 +public class MybatisPlusConfig {
  8 +
  9 +}
... ...
job/src/main/java/com/canrd/shop/config/RestTemplateConfig.java 0 → 100644
  1 +package com.canrd.shop.config;
  2 +
  3 +import org.springframework.context.annotation.Bean;
  4 +import org.springframework.context.annotation.Configuration;
  5 +import org.springframework.http.client.ClientHttpRequestFactory;
  6 +import org.springframework.http.client.SimpleClientHttpRequestFactory;
  7 +import org.springframework.web.client.RestTemplate;
  8 +
  9 +
  10 +@Configuration
  11 +public class RestTemplateConfig {
  12 +
  13 + @Bean
  14 + public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
  15 + return new RestTemplate(factory);
  16 + }
  17 +
  18 + @Bean
  19 + public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
  20 + SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
  21 + factory.setReadTimeout(3000);
  22 + factory.setConnectTimeout(5000);
  23 + return factory;
  24 + }
  25 +
  26 +}
... ...
job/src/main/java/com/canrd/shop/config/WebConfig.java 0 → 100644
  1 +package com.canrd.shop.config;
  2 +
  3 +import com.alibaba.fastjson.support.config.FastJsonConfig;
  4 +import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
  5 +import lombok.extern.slf4j.Slf4j;
  6 +import org.springframework.context.annotation.Configuration;
  7 +import org.springframework.http.MediaType;
  8 +import org.springframework.http.converter.HttpMessageConverter;
  9 +import org.springframework.http.converter.StringHttpMessageConverter;
  10 +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  11 +
  12 +import java.nio.charset.StandardCharsets;
  13 +import java.util.ArrayList;
  14 +import java.util.Collections;
  15 +import java.util.List;
  16 +import java.util.stream.Collectors;
  17 +
  18 +
  19 +@Slf4j
  20 +@Configuration
  21 +public class WebConfig implements WebMvcConfigurer {
  22 +
  23 +
  24 + @Override
  25 + public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
  26 + FastJsonHttpMessageConverter fastConverter = getFastJsonHttpMessageConverter();
  27 +
  28 + StringHttpMessageConverter stringHttpMessageConverter = getStringHttpMessageConverter();
  29 +
  30 + /**
  31 + * 添加StringHttpMessageConverter ,让其转化String。注意顺序,StringHttpMessageConverter 要在FastJsonHttpMessageConverter 之前。
  32 + *
  33 + * https://www.cnblogs.com/slankka/p/11437034.html
  34 + */
  35 + converters.add(0, fastConverter);
  36 + converters.add(0, stringHttpMessageConverter);
  37 + log.info("HttpMessageConverter顺序\n{}", converters.stream().map(c -> c.getClass().getName()).collect(Collectors.joining("\n")));
  38 + }
  39 +
  40 + private static StringHttpMessageConverter getStringHttpMessageConverter() {
  41 + StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
  42 + stringHttpMessageConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.TEXT_PLAIN));
  43 + return stringHttpMessageConverter;
  44 + }
  45 +
  46 + private static FastJsonHttpMessageConverter getFastJsonHttpMessageConverter() {
  47 + FastJsonConfig fastJsonConfig = new FastJsonConfig();
  48 + //解决空值序列化的问题,改为不序列化
  49 + /*fastJsonConfig.setSerializeFilters(new PropertyFilter() {
  50 + @Override
  51 + public boolean apply(Object source,String name, Object value) {
  52 + //if(value.getClass().isPrimitive() == null){
  53 + if(value == null){
  54 + return false;
  55 + }
  56 + return true;
  57 + }
  58 + });*/
  59 + fastJsonConfig.setCharset(StandardCharsets.UTF_8);
  60 + FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
  61 + List<MediaType> supportedMediaTypes = new ArrayList<>();
  62 + supportedMediaTypes.add(MediaType.APPLICATION_JSON);
  63 + supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
  64 + supportedMediaTypes.add(MediaType.APPLICATION_ATOM_XML);
  65 +// supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
  66 + supportedMediaTypes.add(MediaType.APPLICATION_OCTET_STREAM);
  67 + supportedMediaTypes.add(MediaType.APPLICATION_PDF);
  68 + supportedMediaTypes.add(MediaType.APPLICATION_RSS_XML);
  69 + supportedMediaTypes.add(MediaType.APPLICATION_XHTML_XML);
  70 +// supportedMediaTypes.add(MediaType.APPLICATION_XML);
  71 + supportedMediaTypes.add(MediaType.IMAGE_GIF);
  72 + supportedMediaTypes.add(MediaType.IMAGE_JPEG);
  73 + supportedMediaTypes.add(MediaType.IMAGE_PNG);
  74 + supportedMediaTypes.add(MediaType.TEXT_EVENT_STREAM);
  75 + supportedMediaTypes.add(MediaType.TEXT_HTML);
  76 + supportedMediaTypes.add(MediaType.TEXT_MARKDOWN);
  77 + supportedMediaTypes.add(MediaType.TEXT_PLAIN);
  78 +// supportedMediaTypes.add(MediaType.TEXT_XML);
  79 + fastConverter.setSupportedMediaTypes(supportedMediaTypes);
  80 + fastConverter.setFastJsonConfig(fastJsonConfig);
  81 + fastConverter.setDefaultCharset(StandardCharsets.UTF_8);
  82 + return fastConverter;
  83 + }
  84 +}
... ...
job/src/main/java/com/canrd/shop/controller/HelloController.java 0 → 100644
  1 +package com.canrd.shop.controller;
  2 +
  3 +import com.canrd.shop.common.constant.ServerResult;
  4 +import com.canrd.shop.common.jsr303.OperateGroup;
  5 +import com.canrd.shop.module.vo.ProductQueryVO;
  6 +import org.springframework.validation.annotation.Validated;
  7 +import org.springframework.web.bind.annotation.PostMapping;
  8 +import org.springframework.web.bind.annotation.RequestBody;
  9 +import org.springframework.web.bind.annotation.RequestMapping;
  10 +import org.springframework.web.bind.annotation.RestController;
  11 +
  12 +/**
  13 + * (Product)表控制层
  14 + *
  15 + * @author makejava
  16 + * @since 2023-05-29 11:43:33
  17 + */
  18 +@RestController
  19 +@RequestMapping("/canrd/job")
  20 +public class HelloController {
  21 +
  22 + /**
  23 + * 分页查询
  24 + *
  25 + * @param productQueryVO 查询条件
  26 + * @return 查询结果
  27 + */
  28 + @PostMapping("/list")
  29 + public ServerResult hello(@RequestBody @Validated({OperateGroup.List.class}) ProductQueryVO productQueryVO) {
  30 + return ServerResult.success("hello world!");
  31 + }
  32 +
  33 +}
  34 +
... ...
job/src/main/java/com/canrd/shop/job/OrderOverTimeJob.java 0 → 100644
  1 +package com.canrd.shop.job;
  2 +
  3 +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  4 +import com.canrd.shop.common.constant.Constant;
  5 +import com.canrd.shop.module.dto.OrdersDO;
  6 +import com.canrd.shop.service.OrdersService;
  7 +import lombok.extern.slf4j.Slf4j;
  8 +import org.joda.time.DateTime;
  9 +import org.springframework.scheduling.annotation.Scheduled;
  10 +import org.springframework.stereotype.Component;
  11 +import org.springframework.util.CollectionUtils;
  12 +
  13 +import javax.annotation.Resource;
  14 +import java.util.ArrayList;
  15 +import java.util.Arrays;
  16 +import java.util.List;
  17 +
  18 +/**
  19 + * @author: xms
  20 + * @description: TODO
  21 + * @date: 2023/6/25 10:35
  22 + * @version: 1.0
  23 + */
  24 +@Slf4j
  25 +@Component
  26 +public class OrderOverTimeJob {
  27 +
  28 + @Resource
  29 + private OrdersService ordersService;
  30 +
  31 + /**
  32 + * 每隔5分执行一次
  33 + */
  34 + @Scheduled(cron = "0 */5 * * * ?")
  35 +// @Scheduled(cron = "*/5 * * * * ?")
  36 + public void payOverTimeExecute() {
  37 + log.info("执行开始时间:{}", DateTime.now().toString("yyyy-MM-dd HH:mm:ss"));
  38 + LambdaQueryWrapper<OrdersDO> queryWrapper = new LambdaQueryWrapper<OrdersDO>()
  39 + .in(OrdersDO::getPaymentstatus, Arrays.asList(0, 1));
  40 + List<OrdersDO> ordersDOS = ordersService.list(queryWrapper);
  41 +
  42 + if (!CollectionUtils.isEmpty(ordersDOS)) {
  43 + List<OrdersDO> updateOrdersList = new ArrayList<>();
  44 + ordersDOS.forEach(ordersDO -> {
  45 + DateTime createTime = new DateTime(ordersDO.getCreatedate());
  46 + if (DateTime.now().isAfter(createTime.plusDays(Constant.ONE))) {
  47 + ordersDO.setOrderstatus(-1);
  48 + ordersDO.setPaymentstatus(-1);
  49 + ordersDO.setModifydate(DateTime.now().toDate());
  50 + updateOrdersList.add(ordersDO);
  51 + }
  52 +
  53 + });
  54 + if (!CollectionUtils.isEmpty(updateOrdersList)) {
  55 + ordersService.updateBatchById(ordersDOS);
  56 + }
  57 +
  58 + }
  59 + log.info("执行结束时间:{}", DateTime.now().toString("yyyy-MM-dd HH:mm:ss"));
  60 + }
  61 +
  62 +}
... ...
job/src/main/java/com/canrd/shop/mapper/OrdersMapper.java 0 → 100644
  1 +package com.canrd.shop.mapper;
  2 +
  3 +import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  4 +import com.canrd.shop.module.dto.OrdersDO;
  5 +
  6 +/**
  7 + * (Orders)表数据库访问层
  8 + *
  9 + * @author makejava
  10 + * @since 2023-06-25 10:43:07
  11 + */
  12 +public interface OrdersMapper extends BaseMapper<OrdersDO> {
  13 +
  14 +
  15 +}
  16 +
... ...
job/src/main/java/com/canrd/shop/mapper/ProductMapper.java 0 → 100644
  1 +package com.canrd.shop.mapper;
  2 +
  3 +import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  4 +import com.canrd.shop.module.dto.ProductDO;
  5 +import org.apache.ibatis.annotations.Mapper;
  6 +
  7 +/**
  8 + * (Product)表数据库访问层
  9 + *
  10 + * @author makejava
  11 + * @since 2023-05-29 11:43:34
  12 + */
  13 +@Mapper
  14 +public interface ProductMapper extends BaseMapper<ProductDO> {
  15 +
  16 +
  17 +}
  18 +
... ...
job/src/main/java/com/canrd/shop/module/dto/OrdersDO.java 0 → 100644
  1 +package com.canrd.shop.module.dto;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.TableName;
  4 +import lombok.*;
  5 +import lombok.experimental.SuperBuilder;
  6 +
  7 +import java.io.Serializable;
  8 +import java.util.Date;
  9 +
  10 +/**
  11 + * (Orders)实体类
  12 + *
  13 + * @author makejava
  14 + * @since 2023-06-25 10:42:58
  15 + */
  16 +@TableName("orders")
  17 +@Data
  18 +@AllArgsConstructor
  19 +@ToString
  20 +@NoArgsConstructor
  21 +@EqualsAndHashCode(callSuper = false)
  22 +@SuperBuilder
  23 +public class OrdersDO implements Serializable {
  24 + private static final long serialVersionUID = -34170173982796273L;
  25 +
  26 + private String id;
  27 +
  28 + private Date createdate;
  29 +
  30 + private Date modifydate;
  31 +
  32 + private Double deliveryfee;
  33 +
  34 + private String deliverytypename;
  35 +
  36 + private String memo;
  37 +
  38 + private String ordersn;
  39 +
  40 + private Integer orderstatus;
  41 +
  42 + private Double paidamount;
  43 +
  44 + private String paymentconfigname;
  45 +
  46 + private Double paymentfee;
  47 +
  48 + private Integer paymentstatus;
  49 +
  50 + private Double producttotalprice;
  51 +
  52 + private Integer producttotalquantity;
  53 +
  54 + private Double productweight;
  55 +
  56 + private Integer productweightunit;
  57 +
  58 + private String shipaddress;
  59 +
  60 + private String shiparea;
  61 +
  62 + private String shipareapath;
  63 +
  64 + private String shipmobile;
  65 +
  66 + private String shipname;
  67 +
  68 + private String shipphone;
  69 +
  70 + private String shipzipcode;
  71 +
  72 + private String invoice;
  73 +
  74 + private String tax;
  75 +
  76 + private String invoiceId;
  77 +
  78 + private String invoiceType;
  79 +
  80 + private Integer shippingstatus;
  81 +
  82 + private Double totalamount;
  83 +
  84 + private String memberId;
  85 +
  86 + private String deliverytypeId;
  87 +
  88 + private String paymentconfigId;
  89 +
  90 + private String school;
  91 +
  92 + private String college;
  93 +
  94 + private String teacher;
  95 +
  96 + private String teacherphone;
  97 +
  98 +}
... ...
job/src/main/java/com/canrd/shop/module/dto/ProductDO.java 0 → 100644
  1 +package com.canrd.shop.module.dto;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.TableName;
  4 +import lombok.*;
  5 +import lombok.experimental.SuperBuilder;
  6 +
  7 +import java.io.Serializable;
  8 +import java.util.Date;
  9 +
  10 +/**
  11 + * (Product)实体类
  12 + *
  13 + * @author makejava
  14 + * @since 2023-05-29 11:43:32
  15 + */
  16 +@TableName("product")
  17 +@Data
  18 +@AllArgsConstructor
  19 +@ToString
  20 +@NoArgsConstructor
  21 +@EqualsAndHashCode(callSuper = false)
  22 +@SuperBuilder
  23 +public class ProductDO implements Serializable {
  24 +
  25 + private String id;
  26 +
  27 + private Date createdate;
  28 +
  29 + private Date modifydate;
  30 +
  31 + private String description;
  32 +
  33 + private Integer freezestore;
  34 +
  35 + private String htmlfilepath;
  36 +
  37 + private Byte isbest;
  38 +
  39 + private Byte ishot;
  40 + /**
  41 + * 是否上架
  42 + */
  43 + private Byte ismarketable;
  44 +
  45 + private Byte isnew;
  46 +
  47 + private Double marketprice;
  48 +
  49 + private String metadescription;
  50 +
  51 + private String metakeywords;
  52 +
  53 + private String name;
  54 +
  55 + private String englishname;
  56 +
  57 + private String model;
  58 +
  59 + private String exterior;
  60 +
  61 + private String basecore1;
  62 +
  63 + private String basename2;
  64 +
  65 + private String basecore2;
  66 +
  67 + private String basename3;
  68 +
  69 + private String basecore3;
  70 +
  71 + private String basename4;
  72 +
  73 + private String basecore4;
  74 +
  75 + private String basename5;
  76 +
  77 + private String basecore5;
  78 +
  79 + private String basename6;
  80 +
  81 + private String basecore6;
  82 +
  83 + private String basename7;
  84 +
  85 + private String basecore7;
  86 +
  87 + private String basename8;
  88 +
  89 + private String basecore8;
  90 +
  91 + private String basename1;
  92 +
  93 + private Integer point;
  94 +
  95 + private Double price;
  96 +
  97 + private String productimageliststore;
  98 +
  99 + private String productsn;
  100 +
  101 + private Integer store;
  102 +
  103 + private Double weight;
  104 +
  105 + private Integer weightunit;
  106 +
  107 + private String brandId;
  108 +
  109 + private String productcategoryId;
  110 +
  111 + private String productcategoryName;
  112 +
  113 + private String producttypeId;
  114 +
  115 + private String producttypeName;
  116 +
  117 + private String introduction;
  118 +
  119 + private String storage;
  120 +
  121 + private String physicalproperty;
  122 +
  123 + private String advantage;
  124 +
  125 + private String wiki;
  126 +
  127 +}
... ...
job/src/main/java/com/canrd/shop/module/vo/BasePageVO.java 0 → 100644
  1 +package com.canrd.shop.module.vo;
  2 +
  3 +import com.canrd.shop.common.constant.Constant;
  4 +import com.canrd.shop.common.jsr303.OperateGroup;
  5 +import com.fasterxml.jackson.annotation.JsonInclude;
  6 +import lombok.AllArgsConstructor;
  7 +import lombok.Data;
  8 +import lombok.NoArgsConstructor;
  9 +import lombok.experimental.SuperBuilder;
  10 +
  11 +import javax.validation.constraints.Max;
  12 +import javax.validation.constraints.Min;
  13 +import javax.validation.constraints.NotNull;
  14 +
  15 +
  16 +@SuperBuilder(toBuilder = true)
  17 +@Data
  18 +@NoArgsConstructor
  19 +@AllArgsConstructor
  20 +public class BasePageVO {
  21 +
  22 + /**
  23 + * 页码
  24 + */
  25 + @JsonInclude(JsonInclude.Include.NON_NULL)
  26 + @NotNull(message = "页码不能为空", groups = {OperateGroup.List.class})
  27 + @Min(value = Constant.ONE, message = "页码不能小于1", groups = {OperateGroup.List.class})
  28 + private Integer pageNo = 1;
  29 + /**
  30 + * 页
  31 + */
  32 + @JsonInclude(JsonInclude.Include.NON_NULL)
  33 + @NotNull(message = "每页大小不能为空", groups = {OperateGroup.List.class})
  34 + @Min(value = 1, message = "每页大小不能小于1", groups = {OperateGroup.List.class})
  35 + @Max(value = 5000, message = "每页大小不能大于5000", groups = {OperateGroup.List.class})
  36 + private Integer pageSize = 10;
  37 +
  38 + /**
  39 + * 总数
  40 + */
  41 + @JsonInclude(JsonInclude.Include.NON_NULL)
  42 + private Integer total;
  43 +}
... ...
job/src/main/java/com/canrd/shop/module/vo/OrdersQueryVO.java 0 → 100644
  1 +package com.canrd.shop.module.vo;
  2 +
  3 +import lombok.*;
  4 +import lombok.experimental.SuperBuilder;
  5 +
  6 +import java.io.Serializable;
  7 +import java.util.Date;
  8 +import java.util.List;
  9 +
  10 +/**
  11 + * (Orders)实体类
  12 + *
  13 + * @author makejava
  14 + * @since 2023-06-25 10:43:07
  15 + */
  16 +@Data
  17 +@AllArgsConstructor
  18 +@ToString
  19 +@NoArgsConstructor
  20 +@EqualsAndHashCode(callSuper = false)
  21 +@SuperBuilder
  22 +public class OrdersQueryVO extends BasePageVO implements Serializable {
  23 +
  24 + private List<Long> ids;
  25 +
  26 +
  27 + private String id;
  28 +
  29 + private Date createdate;
  30 +
  31 + private Date modifydate;
  32 +
  33 + private Double deliveryfee;
  34 +
  35 + private String deliverytypename;
  36 +
  37 + private String memo;
  38 +
  39 + private String ordersn;
  40 +
  41 + private Integer orderstatus;
  42 +
  43 + private Double paidamount;
  44 +
  45 + private String paymentconfigname;
  46 +
  47 + private Double paymentfee;
  48 +
  49 + private Integer paymentstatus;
  50 +
  51 + private Double producttotalprice;
  52 +
  53 + private Integer producttotalquantity;
  54 +
  55 + private Double productweight;
  56 +
  57 + private Integer productweightunit;
  58 +
  59 + private String shipaddress;
  60 +
  61 + private String shiparea;
  62 +
  63 + private String shipareapath;
  64 +
  65 + private String shipmobile;
  66 +
  67 + private String shipname;
  68 +
  69 + private String shipphone;
  70 +
  71 + private String shipzipcode;
  72 +
  73 + private String invoice;
  74 +
  75 + private String tax;
  76 +
  77 + private String invoiceId;
  78 +
  79 + private String invoiceType;
  80 +
  81 + private Integer shippingstatus;
  82 +
  83 + private Double totalamount;
  84 +
  85 + private String memberId;
  86 +
  87 + private String deliverytypeId;
  88 +
  89 + private String paymentconfigId;
  90 +
  91 + private String school;
  92 +
  93 + private String college;
  94 +
  95 + private String teacher;
  96 +
  97 + private String teacherphone;
  98 +
  99 +
  100 +}
  101 +
... ...
job/src/main/java/com/canrd/shop/module/vo/OrdersVO.java 0 → 100644
  1 +package com.canrd.shop.module.vo;
  2 +
  3 +import lombok.*;
  4 +import lombok.experimental.SuperBuilder;
  5 +
  6 +import java.io.Serializable;
  7 +import java.util.Date;
  8 +
  9 +/**
  10 + * (Orders)实体类
  11 + *
  12 + * @author makejava
  13 + * @since 2023-06-25 10:43:04
  14 + */
  15 +@Data
  16 +@AllArgsConstructor
  17 +@ToString
  18 +@NoArgsConstructor
  19 +@EqualsAndHashCode(callSuper = false)
  20 +@SuperBuilder
  21 +public class OrdersVO implements Serializable {
  22 + private static final long serialVersionUID = -82673229208636654L;
  23 +
  24 + private String id;
  25 +
  26 + private Date createdate;
  27 +
  28 + private Date modifydate;
  29 +
  30 + private Double deliveryfee;
  31 +
  32 + private String deliverytypename;
  33 +
  34 + private String memo;
  35 +
  36 + private String ordersn;
  37 +
  38 + private Integer orderstatus;
  39 +
  40 + private Double paidamount;
  41 +
  42 + private String paymentconfigname;
  43 +
  44 + private Double paymentfee;
  45 +
  46 + private Integer paymentstatus;
  47 +
  48 + private Double producttotalprice;
  49 +
  50 + private Integer producttotalquantity;
  51 +
  52 + private Double productweight;
  53 +
  54 + private Integer productweightunit;
  55 +
  56 + private String shipaddress;
  57 +
  58 + private String shiparea;
  59 +
  60 + private String shipareapath;
  61 +
  62 + private String shipmobile;
  63 +
  64 + private String shipname;
  65 +
  66 + private String shipphone;
  67 +
  68 + private String shipzipcode;
  69 +
  70 + private String invoice;
  71 +
  72 + private String tax;
  73 +
  74 + private String invoiceId;
  75 +
  76 + private String invoiceType;
  77 +
  78 + private Integer shippingstatus;
  79 +
  80 + private Double totalamount;
  81 +
  82 + private String memberId;
  83 +
  84 + private String deliverytypeId;
  85 +
  86 + private String paymentconfigId;
  87 +
  88 + private String school;
  89 +
  90 + private String college;
  91 +
  92 + private String teacher;
  93 +
  94 + private String teacherphone;
  95 +
  96 +
  97 +}
... ...
job/src/main/java/com/canrd/shop/module/vo/ProductQueryVO.java 0 → 100644
  1 +package com.canrd.shop.module.vo;
  2 +
  3 +import lombok.*;
  4 +import lombok.experimental.SuperBuilder;
  5 +
  6 +import java.io.Serializable;
  7 +import java.util.List;
  8 +
  9 +/**
  10 + * (Product)实体类
  11 + *
  12 + * @author makejava
  13 + * @since 2023-05-29 11:43:33
  14 + */
  15 +@Data
  16 +@AllArgsConstructor
  17 +@ToString
  18 +@NoArgsConstructor
  19 +@EqualsAndHashCode(callSuper = false)
  20 +@SuperBuilder
  21 +public class ProductQueryVO extends BasePageVO implements Serializable {
  22 + private static final long serialVersionUID = 108846000631816096L;
  23 +
  24 + private List<Long> ids;
  25 +
  26 +
  27 + private String id;
  28 +
  29 +
  30 +}
  31 +
... ...
job/src/main/java/com/canrd/shop/module/vo/ProductVO.java 0 → 100644
  1 +package com.canrd.shop.module.vo;
  2 +
  3 +import lombok.*;
  4 +import lombok.experimental.SuperBuilder;
  5 +
  6 +import java.io.Serializable;
  7 +import java.util.Date;
  8 +
  9 +/**
  10 + * (Product)实体类
  11 + *
  12 + * @author makejava
  13 + * @since 2023-05-29 11:43:33
  14 + */
  15 +@Data
  16 +@AllArgsConstructor
  17 +@ToString
  18 +@NoArgsConstructor
  19 +@EqualsAndHashCode(callSuper = false)
  20 +@SuperBuilder
  21 +public class ProductVO implements Serializable {
  22 + private static final long serialVersionUID = -82998374747158271L;
  23 +
  24 + private String id;
  25 +
  26 + private Date createdate;
  27 +
  28 + private Date modifydate;
  29 +
  30 + private String description;
  31 +
  32 + private Integer freezestore;
  33 +
  34 + private String htmlfilepath;
  35 +
  36 + private Byte isbest;
  37 +
  38 + private Byte ishot;
  39 + /**
  40 + * 是否上架
  41 + */
  42 + private Byte ismarketable;
  43 +
  44 + private Byte isnew;
  45 +
  46 + private Double marketprice;
  47 +
  48 + private String metadescription;
  49 +
  50 + private String metakeywords;
  51 +
  52 + private String name;
  53 +
  54 + private String englishname;
  55 +
  56 + private String model;
  57 +
  58 + private String exterior;
  59 +
  60 + private String basecore1;
  61 +
  62 + private String basename2;
  63 +
  64 + private String basecore2;
  65 +
  66 + private String basename3;
  67 +
  68 + private String basecore3;
  69 +
  70 + private String basename4;
  71 +
  72 + private String basecore4;
  73 +
  74 + private String basename5;
  75 +
  76 + private String basecore5;
  77 +
  78 + private String basename6;
  79 +
  80 + private String basecore6;
  81 +
  82 + private String basename7;
  83 +
  84 + private String basecore7;
  85 +
  86 + private String basename8;
  87 +
  88 + private String basecore8;
  89 +
  90 + private String basename1;
  91 +
  92 + private Integer point;
  93 +
  94 + private Double price;
  95 +
  96 + private String productimageliststore;
  97 +
  98 + private String productsn;
  99 +
  100 + private Integer store;
  101 +
  102 + private Double weight;
  103 +
  104 + private Integer weightunit;
  105 +
  106 + private String brandId;
  107 +
  108 + private String productcategoryId;
  109 +
  110 + private String productcategoryName;
  111 +
  112 + private String producttypeId;
  113 +
  114 + private String producttypeName;
  115 +
  116 + private String introduction;
  117 +
  118 + private String storage;
  119 +
  120 + private String physicalproperty;
  121 +
  122 + private String advantage;
  123 +
  124 + private String wiki;
  125 +
  126 +
  127 +}
... ...
job/src/main/java/com/canrd/shop/service/OrdersService.java 0 → 100644
  1 +package com.canrd.shop.service;
  2 +
  3 +import com.baomidou.mybatisplus.extension.service.IService;
  4 +import com.canrd.shop.common.constant.ServerResult;
  5 +import com.canrd.shop.module.dto.OrdersDO;
  6 +import com.canrd.shop.module.vo.OrdersQueryVO;
  7 +import com.canrd.shop.module.vo.OrdersVO;
  8 +
  9 +/**
  10 + * (Orders)表服务接口
  11 + *
  12 + * @author makejava
  13 + * @since 2023-06-25 10:43:08
  14 + */
  15 +public interface OrdersService extends IService<OrdersDO> {
  16 +
  17 + /**
  18 + * 通过ID查询单条数据
  19 + *
  20 + * @param ordersQueryVO 主键
  21 + * @return 实例对象
  22 + */
  23 + ServerResult queryById(OrdersQueryVO ordersQueryVO);
  24 +
  25 + /**
  26 + * 分页查询
  27 + *
  28 + * @param ordersQueryVO 筛选条件
  29 + * @return 查询结果
  30 + */
  31 + ServerResult list(OrdersQueryVO ordersQueryVO);
  32 +
  33 + /**
  34 + * 新增数据
  35 + *
  36 + * @param ordersVO 数据VO
  37 + * @return 新增结果
  38 + */
  39 + ServerResult add(OrdersVO ordersVO);
  40 +
  41 + /**
  42 + * 修改数据
  43 + *
  44 + * @param ordersVO 数据VO
  45 + * @return 编辑结果
  46 + */
  47 + ServerResult edit(OrdersVO ordersVO);
  48 +
  49 + /**
  50 + * 通过主键删除数据
  51 + *
  52 + * @param ordersQueryVO 筛选条件
  53 + * @return 是否成功
  54 + */
  55 + ServerResult deleteById(OrdersQueryVO ordersQueryVO);
  56 +
  57 +}
... ...
job/src/main/java/com/canrd/shop/service/ProductService.java 0 → 100644
  1 +package com.canrd.shop.service;
  2 +
  3 +import com.baomidou.mybatisplus.extension.service.IService;
  4 +import com.canrd.shop.common.constant.ServerResult;
  5 +import com.canrd.shop.module.dto.ProductDO;
  6 +import com.canrd.shop.module.vo.ProductQueryVO;
  7 +import com.canrd.shop.module.vo.ProductVO;
  8 +
  9 +/**
  10 + * (Product)表服务接口
  11 + *
  12 + * @author makejava
  13 + * @since 2023-05-29 11:43:34
  14 + */
  15 +public interface ProductService extends IService<ProductDO> {
  16 +
  17 + /**
  18 + * 通过ID查询单条数据
  19 + *
  20 + * @param productQueryVO 主键
  21 + * @return 实例对象
  22 + */
  23 + ServerResult queryById(ProductQueryVO productQueryVO);
  24 +
  25 + /**
  26 + * 分页查询
  27 + *
  28 + * @param productQueryVO 筛选条件
  29 + * @return 查询结果
  30 + */
  31 + ServerResult list(ProductQueryVO productQueryVO);
  32 +
  33 + /**
  34 + * 新增数据
  35 + *
  36 + * @param productVO 数据VO
  37 + * @return 新增结果
  38 + */
  39 + ServerResult add(ProductVO productVO);
  40 +
  41 + /**
  42 + * 修改数据
  43 + *
  44 + * @param productVO 数据VO
  45 + * @return 编辑结果
  46 + */
  47 + ServerResult edit(ProductVO productVO);
  48 +
  49 + /**
  50 + * 通过主键删除数据
  51 + *
  52 + * @param productQueryVO 筛选条件
  53 + * @return 是否成功
  54 + */
  55 + ServerResult deleteById(ProductQueryVO productQueryVO);
  56 +
  57 +}
... ...
job/src/main/java/com/canrd/shop/service/impl/OrdersServiceImpl.java 0 → 100644
  1 +package com.canrd.shop.service.impl;
  2 +
  3 +import cn.hutool.core.bean.BeanUtil;
  4 +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  5 +import com.canrd.shop.common.constant.ServerResult;
  6 +import com.canrd.shop.mapper.OrdersMapper;
  7 +import com.canrd.shop.module.dto.OrdersDO;
  8 +import com.canrd.shop.module.vo.OrdersQueryVO;
  9 +import com.canrd.shop.module.vo.OrdersVO;
  10 +import com.canrd.shop.service.OrdersService;
  11 +import lombok.extern.slf4j.Slf4j;
  12 +import org.springframework.stereotype.Service;
  13 +
  14 +import java.util.Objects;
  15 +
  16 +/**
  17 + * (Orders)表服务实现类
  18 + *
  19 + * @author makejava
  20 + * @since 2023-06-25 10:43:09
  21 + */
  22 +@Slf4j
  23 +@Service
  24 +public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, OrdersDO> implements OrdersService {
  25 +
  26 +
  27 + /**
  28 + * 通过ID查询单条数据
  29 + * <p>
  30 + * ordersQueryVO 主键
  31 + *
  32 + * @return 实例对象
  33 + */
  34 + @Override
  35 + public ServerResult queryById(OrdersQueryVO ordersQueryVO) {
  36 + if (Objects.isNull(ordersQueryVO.getId())) {
  37 + return ServerResult.fail("id 不能为空");
  38 + }
  39 + OrdersDO OrdersDo = getById(ordersQueryVO.getId());
  40 + if (Objects.isNull(OrdersDo)) {
  41 + return ServerResult.success(null);
  42 + }
  43 + return ServerResult.success(BeanUtil.copyProperties(OrdersDo, OrdersVO.class));
  44 + }
  45 +
  46 + /**
  47 + * 分页查询
  48 + *
  49 + * @param ordersQueryVO 筛选条件
  50 + * @return 查询结果
  51 + */
  52 + @Override
  53 + public ServerResult list(OrdersQueryVO ordersQueryVO) {
  54 +
  55 + return ServerResult.success();
  56 + }
  57 +
  58 + /**
  59 + * 新增数据
  60 + *
  61 + * @param ordersVO 实例对象
  62 + * @return 实例对象
  63 + */
  64 + @Override
  65 + public ServerResult add(OrdersVO ordersVO) {
  66 + //todo 校验
  67 + if (Objects.nonNull(ordersVO.getId())) {
  68 + ordersVO.setId(null);
  69 + }
  70 + OrdersDO ordersDo = BeanUtil.copyProperties(ordersVO, OrdersDO.class);
  71 +
  72 + save(ordersDo);
  73 +
  74 + return ServerResult.success();
  75 + }
  76 +
  77 + /**
  78 + * 修改数据
  79 + *
  80 + * @param ordersVO 实例对象
  81 + * @return 实例对象
  82 + */
  83 + @Override
  84 + public ServerResult edit(OrdersVO ordersVO) {
  85 + //todo 校验
  86 + if (Objects.isNull(ordersVO.getId())) {
  87 + return ServerResult.fail("id 不能为空");
  88 + }
  89 + OrdersDO ordersDo = BeanUtil.copyProperties(ordersVO, OrdersDO.class);
  90 +
  91 + updateById(ordersDo);
  92 +
  93 + return ServerResult.success();
  94 + }
  95 +
  96 + /**
  97 + * 通过主键删除数据
  98 + *
  99 + * @param ordersQueryVO 筛选条件
  100 + * @return 是否成功
  101 + */
  102 + @Override
  103 + public ServerResult deleteById(OrdersQueryVO ordersQueryVO) {
  104 + return ServerResult.success();
  105 + }
  106 +}
... ...
job/src/main/java/com/canrd/shop/service/impl/ProductServiceImpl.java 0 → 100644
  1 +package com.canrd.shop.service.impl;
  2 +
  3 +import cn.hutool.core.bean.BeanUtil;
  4 +import cn.hutool.core.collection.CollUtil;
  5 +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  6 +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
  7 +import com.baomidou.mybatisplus.core.metadata.IPage;
  8 +import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  9 +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  10 +import com.canrd.shop.common.constant.ServerResult;
  11 +import com.canrd.shop.common.utils.PageUtils;
  12 +import com.canrd.shop.mapper.ProductMapper;
  13 +import com.canrd.shop.module.dto.ProductDO;
  14 +import com.canrd.shop.module.vo.ProductQueryVO;
  15 +import com.canrd.shop.module.vo.ProductVO;
  16 +import com.canrd.shop.service.ProductService;
  17 +import lombok.extern.slf4j.Slf4j;
  18 +import org.springframework.stereotype.Service;
  19 +
  20 +import java.util.List;
  21 +import java.util.Objects;
  22 +
  23 +/**
  24 + * (Product)表服务实现类
  25 + *
  26 + * @author makejava
  27 + * @since 2023-05-29 11:43:35
  28 + */
  29 +@Slf4j
  30 +@Service
  31 +public class ProductServiceImpl extends ServiceImpl<ProductMapper, ProductDO> implements ProductService {
  32 +
  33 +
  34 + /**
  35 + * 通过ID查询单条数据
  36 + * <p>
  37 + * productQueryVO 主键
  38 + *
  39 + * @return 实例对象
  40 + */
  41 + @Override
  42 + public ServerResult queryById(ProductQueryVO productQueryVO) {
  43 + if (Objects.isNull(productQueryVO.getId())) {
  44 + return ServerResult.fail("id 不能为空");
  45 + }
  46 + ProductDO ProductDo = getById(productQueryVO.getId());
  47 + if (Objects.isNull(ProductDo)) {
  48 + return ServerResult.success(null);
  49 + }
  50 + return ServerResult.success(BeanUtil.copyProperties(ProductDo, ProductVO.class));
  51 + }
  52 +
  53 + /**
  54 + * 分页查询
  55 + *
  56 + * @param productQueryVO 筛选条件
  57 + * @return 查询结果
  58 + */
  59 + @Override
  60 + public ServerResult list(ProductQueryVO productQueryVO) {
  61 +
  62 + LambdaQueryWrapper<ProductDO> queryWapper = new LambdaQueryWrapper<ProductDO>()
  63 + .orderByDesc(ProductDO::getId);
  64 + Page page = new Page<>(productQueryVO.getPageNo(), productQueryVO.getPageSize());
  65 + IPage<ProductDO> iPage = page(page, queryWapper);
  66 + productQueryVO.setTotal(Long.valueOf(iPage.getTotal()).intValue());
  67 +
  68 + return ServerResult.success(PageUtils.getPageReturn(iPage.getRecords(), productQueryVO));
  69 + }
  70 +
  71 + /**
  72 + * 新增数据
  73 + *
  74 + * @param productVO 实例对象
  75 + * @return 实例对象
  76 + */
  77 + @Override
  78 + public ServerResult add(ProductVO productVO) {
  79 + //todo 校验
  80 + if (Objects.nonNull(productVO.getId())) {
  81 + productVO.setId(null);
  82 + }
  83 + ProductDO productDo = BeanUtil.copyProperties(productVO, ProductDO.class);
  84 +
  85 + save(productDo);
  86 +
  87 + return ServerResult.success();
  88 + }
  89 +
  90 + /**
  91 + * 修改数据
  92 + *
  93 + * @param productVO 实例对象
  94 + * @return 实例对象
  95 + */
  96 + @Override
  97 + public ServerResult edit(ProductVO productVO) {
  98 + //todo 校验
  99 + if (Objects.isNull(productVO.getId())) {
  100 + return ServerResult.fail("id 不能为空");
  101 + }
  102 + ProductDO productDo = BeanUtil.copyProperties(productVO, ProductDO.class);
  103 +
  104 + updateById(productDo);
  105 +
  106 + return ServerResult.success();
  107 + }
  108 +
  109 + /**
  110 + * 通过主键删除数据
  111 + *
  112 + * @param productQueryVO 筛选条件
  113 + * @return 是否成功
  114 + */
  115 + @Override
  116 + public ServerResult deleteById(ProductQueryVO productQueryVO) {
  117 + List<Long> ids = productQueryVO.getIds();
  118 + if (CollUtil.isEmpty(ids)) {
  119 + return ServerResult.fail("ids 参数不能为空");
  120 + }
  121 + List<ProductDO> productList = listByIds(ids);
  122 + if (CollUtil.isEmpty(productList)) {
  123 + return ServerResult.success();
  124 + }
  125 + //todo 校验是否可以逻辑删除
  126 + LambdaUpdateWrapper<ProductDO> updateWrapper = new LambdaUpdateWrapper<ProductDO>()
  127 + .in(ProductDO::getId, ids);
  128 + update(updateWrapper);
  129 + return ServerResult.success();
  130 + }
  131 +}
... ...
job/src/main/resources/application-local.yml 0 → 100644
  1 +mybatis-plus:
  2 + configuration:
  3 + cache-enabled: false
  4 + call-setters-on-nulls: true
  5 + jdbc-type-for-null: 'null'
  6 + map-underscore-to-camel-case: true
  7 + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  8 + global-config:
  9 + db-config:
  10 + capital-mode: false
  11 + field-strategy: NOT_NULL
  12 + id-type: AUTO
  13 + logic-delete-field: enable_flag
  14 + logic-delete-value: 20
  15 + logic-not-delete-value: 10
  16 + mapper-locations: classpath:/mapper/**.xml
  17 + type-aliases-package: com.canrd.shop.**.dto
  18 +#spring:
  19 +# datasource:
  20 +# dynamic:
  21 +# primary: overtime #设置默认的数据源或者数据源组,默认值即为master
  22 +# strict: false #设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候会抛出异常,不启动则使用默认数据源.
  23 +# datasource:
  24 +# wms_warehouse:
  25 +# url: jdbc:mysql://127.0.0.1:3306/overtime?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&useSSL=false&autoReconnect=true&failOverReadOnly=false&maxReconnects=10&allowMultiQueries=true&useAffectedRows=true&autoReconnectForPools=true&rewriteBatchedStatements=true
  26 +# username: root
  27 +# password: root
  28 +# driver-class-name: com.mysql.cj.jdbc.Driver # 3.2.0开始支持SPI可省略此配置
  29 +# druid:
  30 +# initial-size: 5
  31 +# max-active: 20
  32 +# max-evictable-idle-time-millis: 300000
  33 +# max-wait: 60000
  34 +# min-evictable-idle-time-millis: 300000
  35 +# min-idle: 5
  36 +# time-between-eviction-runs-millis: 60000
  37 +# type: com.alibaba.druid.pool.DruidDataSource
  38 +spring:
  39 + servlet:
  40 + multipart:
  41 + enabled: true
  42 + max-file-size: 100MB
  43 + max-request-size: 20MB
  44 + file-size-threshold: 20MB
  45 + datasource:
  46 + db-type: com.alibaba.druid.pool.DruidDataSource
  47 + driverClassName: com.mysql.cj.jdbc.Driver
  48 + initial-size: 5
  49 + max-active: 30
  50 + max-wait: 30000
  51 + min-idle: 5
  52 + #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
  53 + timeBetweenEvictionRunsMillis: 30000
  54 + #配置一个连接在池中最小生存的时间,单位是毫秒,30000=30s
  55 + minEvictableIdleTimeMillis: 30000
  56 + validationQuery: SELECT 'x'
  57 + testWhileIdle: true
  58 + testOnBorrow: true
  59 + testOnReturn: true
  60 + password: 123456
  61 + time-between-eviction-runs-millis: 1000
  62 + url: jdbc:mysql://39.108.227.113:3306/jfinalshop?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&useSSL=false&autoReconnect=true&failOverReadOnly=false&maxReconnects=10&allowMultiQueries=true&useAffectedRows=true&autoReconnectForPools=true
  63 + username: root
  64 +
  65 +
  66 +logging:
  67 + config: classpath:log4j2-dev.xml
0 68 \ No newline at end of file
... ...
job/src/main/resources/application-prod.yml 0 → 100644
  1 +mybatis-plus:
  2 + configuration:
  3 + cache-enabled: false
  4 + call-setters-on-nulls: true
  5 + jdbc-type-for-null: 'null'
  6 + map-underscore-to-camel-case: true
  7 + log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
  8 + global-config:
  9 + db-config:
  10 + capital-mode: false
  11 + field-strategy: NOT_NULL
  12 + id-type: AUTO
  13 + logic-delete-field: enable_flag
  14 + logic-delete-value: 20
  15 + logic-not-delete-value: 10
  16 + mapper-locations: classpath:/mapper/**.xml
  17 + type-aliases-package: com.canrd.shop.**.dto
  18 +#spring:
  19 +# datasource:
  20 +# dynamic:
  21 +# primary: overtime #设置默认的数据源或者数据源组,默认值即为master
  22 +# strict: false #设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候会抛出异常,不启动则使用默认数据源.
  23 +# datasource:
  24 +# wms_warehouse:
  25 +# url: jdbc:mysql://127.0.0.1:3306/overtime?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&useSSL=false&autoReconnect=true&failOverReadOnly=false&maxReconnects=10&allowMultiQueries=true&useAffectedRows=true&autoReconnectForPools=true&rewriteBatchedStatements=true
  26 +# username: root
  27 +# password: root
  28 +# driver-class-name: com.mysql.cj.jdbc.Driver # 3.2.0开始支持SPI可省略此配置
  29 +# druid:
  30 +# initial-size: 5
  31 +# max-active: 20
  32 +# max-evictable-idle-time-millis: 300000
  33 +# max-wait: 60000
  34 +# min-evictable-idle-time-millis: 300000
  35 +# min-idle: 5
  36 +# time-between-eviction-runs-millis: 60000
  37 +# type: com.alibaba.druid.pool.DruidDataSource
  38 +spring:
  39 + servlet:
  40 + multipart:
  41 + enabled: true
  42 + max-file-size: 100MB
  43 + max-request-size: 20MB
  44 + file-size-threshold: 20MB
  45 + datasource:
  46 + db-type: com.alibaba.druid.pool.DruidDataSource
  47 + driverClassName: com.mysql.cj.jdbc.Driver
  48 + initial-size: 5
  49 + max-active: 30
  50 + max-wait: 30000
  51 + min-idle: 5
  52 + #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
  53 + timeBetweenEvictionRunsMillis: 30000
  54 + #配置一个连接在池中最小生存的时间,单位是毫秒,30000=30s
  55 + minEvictableIdleTimeMillis: 30000
  56 + validationQuery: SELECT 'x'
  57 + testWhileIdle: true
  58 + testOnBorrow: true
  59 + testOnReturn: true
  60 + password: 123456
  61 + time-between-eviction-runs-millis: 1000
  62 + url: jdbc:mysql://39.108.227.113:3306/jfinalshop?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&useSSL=false&autoReconnect=true&failOverReadOnly=false&maxReconnects=10&allowMultiQueries=true&useAffectedRows=true&autoReconnectForPools=true
  63 + username: root
  64 +
  65 +
  66 +logging:
  67 + config: classpath:log4j2-prod.xml
... ...
job/src/main/resources/application-test.yml 0 → 100644
  1 +mybatis-plus:
  2 + configuration:
  3 + cache-enabled: false
  4 + call-setters-on-nulls: true
  5 + jdbc-type-for-null: 'null'
  6 + map-underscore-to-camel-case: true
  7 + log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
  8 + global-config:
  9 + db-config:
  10 + capital-mode: false
  11 + field-strategy: NOT_NULL
  12 + id-type: AUTO
  13 + logic-delete-field: enable_flag
  14 + logic-delete-value: 20
  15 + logic-not-delete-value: 10
  16 + mapper-locations: classpath:/mapper/**.xml
  17 + type-aliases-package: com.canrd.shop.**.dto
  18 +#spring:
  19 +# datasource:
  20 +# dynamic:
  21 +# primary: overtime #设置默认的数据源或者数据源组,默认值即为master
  22 +# strict: false #设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候会抛出异常,不启动则使用默认数据源.
  23 +# datasource:
  24 +# wms_warehouse:
  25 +# url: jdbc:mysql://127.0.0.1:3306/overtime?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&useSSL=false&autoReconnect=true&failOverReadOnly=false&maxReconnects=10&allowMultiQueries=true&useAffectedRows=true&autoReconnectForPools=true&rewriteBatchedStatements=true
  26 +# username: root
  27 +# password: root
  28 +# driver-class-name: com.mysql.cj.jdbc.Driver # 3.2.0开始支持SPI可省略此配置
  29 +# druid:
  30 +# initial-size: 5
  31 +# max-active: 20
  32 +# max-evictable-idle-time-millis: 300000
  33 +# max-wait: 60000
  34 +# min-evictable-idle-time-millis: 300000
  35 +# min-idle: 5
  36 +# time-between-eviction-runs-millis: 60000
  37 +# type: com.alibaba.druid.pool.DruidDataSource
  38 +spring:
  39 + servlet:
  40 + multipart:
  41 + enabled: true
  42 + max-file-size: 100MB
  43 + max-request-size: 20MB
  44 + file-size-threshold: 20MB
  45 + datasource:
  46 + db-type: com.alibaba.druid.pool.DruidDataSource
  47 + driverClassName: com.mysql.cj.jdbc.Driver
  48 + initial-size: 5
  49 + max-active: 30
  50 + max-wait: 30000
  51 + min-idle: 5
  52 + #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
  53 + timeBetweenEvictionRunsMillis: 30000
  54 + #配置一个连接在池中最小生存的时间,单位是毫秒,30000=30s
  55 + minEvictableIdleTimeMillis: 30000
  56 + validationQuery: SELECT 'x'
  57 + testWhileIdle: true
  58 + testOnBorrow: true
  59 + testOnReturn: true
  60 + password: 123456
  61 + time-between-eviction-runs-millis: 1000
  62 + url: jdbc:mysql://39.108.227.113:3306/jfinalshop?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&useSSL=false&autoReconnect=true&failOverReadOnly=false&maxReconnects=10&allowMultiQueries=true&useAffectedRows=true&autoReconnectForPools=true
  63 + username: root
  64 +
  65 +
  66 +logging:
  67 + config: classpath:log4j2-dev.xml
0 68 \ No newline at end of file
... ...
job/src/main/resources/application.yml 0 → 100644
  1 +server:
  2 + port: 9000
  3 +
  4 +spring:
  5 + # 不占用端口启动
  6 + main:
  7 + allow-bean-definition-overriding: true
  8 + web-application-type: none
  9 + profiles:
  10 + active: local
0 11 \ No newline at end of file
... ...
job/src/main/resources/log4j2-dev.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
  3 +<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出 -->
  4 +<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数 -->
  5 +<configuration status="debug" monitorInterval="30">
  6 + <!--<contextName>log4j2</contextName>-->
  7 + <properties>
  8 + <!--${sys:catalina.home}表示linux中环境变量中的tomcat根目录 用户主目录-->
  9 + <!--原来用logback时候在统一配置中心也配置一个logging.path=/opt/tomcat-log/${spring.application.name} LOG_PATH是内置变量-->
  10 + <!--${sys:user.home} 用户主目录-->
  11 + <!-- <Property name="log_path">${sys:user.home}/logs</Property>-->
  12 +<!-- <Property name="log_path" value="./logs/" />-->
  13 + <property name="console_log_pattern">%d|%t|%traceId|%-5level|%F:%L|%M|%m%n</property>
  14 + <!-- 保留日志天数 D H M S 分别对应天 小时 分钟 秒 -->
  15 + <property name="KEEP_LOG_DAY">60D</property>
  16 + <!-- 日志切割的最小单位 -->
  17 + <property name="EVERY_FILE_SIZE">100M</property>
  18 + </properties>
  19 + <!--先定义所有的appender -->
  20 + <appenders>
  21 + <console name="Console" target="SYSTEM_OUT">
  22 + <!--输出日志的格式 -->
  23 + <PatternLayout charset="UTF-8" pattern="${console_log_pattern}"/>
  24 + <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY" />
  25 + </console>
  26 + <!--这个输出控制台的配置 -->
  27 + <!--<console name="Console" target="SYSTEM_OUT" follow="false">-->
  28 + <!--&lt;!&ndash;输出日志的格式 &ndash;&gt;-->
  29 + <!--<PatternLayout pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} %level [%thread][%file:%line] - %msg%n" />-->
  30 + <!--</console>-->
  31 +
  32 + <!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档 -->
  33 + <RollingFile name="RollingFileInfo" fileName="${sys:logging.path}/logs/overtime.log" filePattern="${sys:logging.path}/logs/$${date:yyyy-MM-dd}/info-%d{yyyy-MM-dd}-%i.log">
  34 + <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
  35 + <ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY" />
  36 + <!--<Filters>-->
  37 + <!--<ThresholdFilter level="INFO"/>-->
  38 + <!--<ThresholdFilter level="WARN" onMatch="DENY"-->
  39 + <!--onMismatch="NEUTRAL"/>-->
  40 + <!--</Filters>-->
  41 + <PatternLayout charset="UTF-8" pattern="${console_log_pattern}"/>
  42 + <Policies>
  43 + <!-- 归档每天的文件 -->
  44 + <!--<TimeBasedTriggeringPolicy interval="1" modulate="true"/>-->
  45 + <TimeBasedTriggeringPolicy />
  46 + <!-- 限制单个文件大小 -->
  47 + <SizeBasedTriggeringPolicy size="${EVERY_FILE_SIZE}"/>
  48 + </Policies>
  49 + <!-- 限制每天文件个数 --> <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了100 -->
  50 + <DefaultRolloverStrategy max="256">
  51 + <Delete basePath="${sys:logging.path}/logs/" maxDepth="3">
  52 + <IfFileName glob="*/*info*.log"/>
  53 + <IfLastModified age="${KEEP_LOG_DAY}"/>
  54 + </Delete>
  55 + </DefaultRolloverStrategy>
  56 + </RollingFile>
  57 + </appenders>
  58 + <!--然后定义logger,只有定义了logger并引入的appender,appender才会生效 -->
  59 + <loggers>
  60 + <!--过滤掉spring和mybatis的一些无用的DEBUG信息 -->
  61 + <logger name="org.springframework" level="debug" >
  62 + <ThresholdFilter level="debug"/>
  63 + <appender-ref ref="RollingFileInfo" />
  64 + </logger>
  65 + <logger name="org.mybatis" level="DEBUG" >
  66 + <ThresholdFilter level="debug"/>
  67 + <appender-ref ref="RollingFileInfo" />
  68 + </logger>
  69 + <logger name="com.canrd.shop" level="DEBUG" >
  70 + <ThresholdFilter level="debug"/>
  71 + <appender-ref ref="RollingFileInfo" />
  72 + </logger>
  73 + <!--<root level="all">-->
  74 + <root level="debug">
  75 + <appender-ref ref="Console" />
  76 + </root>
  77 + </loggers>
  78 +</configuration>
... ...
job/src/main/resources/log4j2-prod.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
  3 +<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出 -->
  4 +<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数 -->
  5 +<configuration status="INFO" monitorInterval="30">
  6 + <!--<contextName>log4j2</contextName>-->
  7 + <properties>
  8 + <!--${sys:catalina.home}表示linux中环境变量中的tomcat根目录 用户主目录-->
  9 + <!--原来用logback时候在统一配置中心也配置一个logging.path=/opt/tomcat-log/${spring.application.name} LOG_PATH是内置变量-->
  10 + <!--${sys:user.home} 用户主目录-->
  11 + <!-- <Property name="log_path">${sys:user.home}/logs</Property>-->
  12 +<!-- <Property name="log_path" value="./logs/" />-->
  13 + <property name="console_log_pattern">%d|%t|%traceId|%-5level|%F:%L|%M|%m%n</property>
  14 + <!-- 保留日志天数 D H M S 分别对应天 小时 分钟 秒 -->
  15 + <property name="KEEP_LOG_DAY">60D</property>
  16 + <!-- 日志切割的最小单位 -->
  17 + <property name="EVERY_FILE_SIZE">100M</property>
  18 + </properties>
  19 + <!--先定义所有的appender -->
  20 + <appenders>
  21 + <console name="Console" target="SYSTEM_OUT">
  22 + <!--输出日志的格式 -->
  23 + <PatternLayout charset="UTF-8" pattern="${console_log_pattern}"/>
  24 + <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY" />
  25 + </console>
  26 + <!--这个输出控制台的配置 -->
  27 + <!--<console name="Console" target="SYSTEM_OUT" follow="false">-->
  28 + <!--&lt;!&ndash;输出日志的格式 &ndash;&gt;-->
  29 + <!--<PatternLayout pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} %level [%thread][%file:%line] - %msg%n" />-->
  30 + <!--</console>-->
  31 +
  32 + <!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档 -->
  33 + <RollingFile name="RollingFileInfo" fileName="${sys:logging.path}/logs/overtime.log" filePattern="${sys:logging.path}/logs/$${date:yyyy-MM-dd}/info-%d{yyyy-MM-dd}-%i.log">
  34 + <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
  35 + <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY" />
  36 + <!--<Filters>-->
  37 + <!--<ThresholdFilter level="INFO"/>-->
  38 + <!--<ThresholdFilter level="WARN" onMatch="DENY"-->
  39 + <!--onMismatch="NEUTRAL"/>-->
  40 + <!--</Filters>-->
  41 + <PatternLayout charset="UTF-8" pattern="${console_log_pattern}"/>
  42 + <Policies>
  43 + <!-- 归档每天的文件 -->
  44 + <!--<TimeBasedTriggeringPolicy interval="1" modulate="true"/>-->
  45 + <TimeBasedTriggeringPolicy />
  46 + <!-- 限制单个文件大小 -->
  47 + <SizeBasedTriggeringPolicy size="${EVERY_FILE_SIZE}"/>
  48 + </Policies>
  49 + <!-- 限制每天文件个数 --> <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了100 -->
  50 + <DefaultRolloverStrategy max="256">
  51 + <Delete basePath="${sys:logging.path}/logs/" maxDepth="3">
  52 + <IfFileName glob="*/*info*.log"/>
  53 + <IfLastModified age="${KEEP_LOG_DAY}"/>
  54 + </Delete>
  55 + </DefaultRolloverStrategy>
  56 + </RollingFile>
  57 + </appenders>
  58 + <!--然后定义logger,只有定义了logger并引入的appender,appender才会生效 -->
  59 + <loggers>
  60 + <logger name="org.springframework" level="info" >
  61 + <ThresholdFilter level="info"/>
  62 + <appender-ref ref="RollingFileInfo" />
  63 + </logger>
  64 + <logger name="org.mybatis" level="info" >
  65 + <ThresholdFilter level="info"/>
  66 + <appender-ref ref="RollingFileInfo" />
  67 + </logger>
  68 + <logger name="com.canrd.shop" level="info" >
  69 + <ThresholdFilter level="info"/>
  70 + <appender-ref ref="RollingFileInfo" />
  71 + </logger>
  72 + </loggers>
  73 +</configuration>
... ...
job/src/test/java/com/canrd/shop/BaseTest.java 0 → 100644
  1 +package com.canrd.shop;
  2 +
  3 +import org.junit.runner.RunWith;
  4 +import org.springframework.boot.test.context.SpringBootTest;
  5 +import org.springframework.test.context.junit4.SpringRunner;
  6 +import org.springframework.transaction.annotation.Transactional;
  7 +
  8 +/**
  9 + * @author fanzhenyu
  10 + * @date 2023-01-15
  11 + */
  12 +@RunWith(SpringRunner.class)
  13 +@SpringBootTest(classes = JobApplication.class)
  14 +//主动回滚测试产生的数据
  15 +@Transactional
  16 +public class BaseTest {
  17 +
  18 +
  19 +}
... ...
job/src/test/java/com/canrd/shop/test/DateTimeUtilTest.java 0 → 100644
  1 +package com.canrd.shop.test;
  2 +
  3 +import org.joda.time.format.DateTimeFormat;
  4 +import org.joda.time.format.DateTimeFormatter;
  5 +import org.junit.Test;
  6 +
  7 +/**
  8 + * @author: xms
  9 + * @description: TODO
  10 + * @date: 2023/2/10 14:09
  11 + * @version: 1.0
  12 + */
  13 +public class DateTimeUtilTest {
  14 +
  15 + @Test
  16 + public void test() {
  17 + DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm");
  18 + System.out.println(fmt.parseDateTime("2023-02-10 12:00").isBefore(fmt.parseDateTime("2023-02-10 13:30")));
  19 + System.out.println(fmt.parseDateTime("2023-02-10 12:00").isBeforeNow());
  20 + }
  21 +}
... ...
... ... @@ -11,6 +11,7 @@
11 11 <modules>
12 12 <module>admin</module>
13 13 <module>shop</module>
  14 + <module>job</module>
14 15 </modules>
15 16  
16 17 <parent>
... ...