Commit 54e88191b3cb0d250ee3a3cfce65523b6f29f28c
0 parents
feat: init项目
Showing
26 changed files
with
3526 additions
and
0 deletions
Too many changes to show.
To preserve performance only 26 of 62 files are displayed.
pom.xml
0 → 100644
1 | +++ a/pom.xml | ||
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 | + <groupId>org.springframework.boot</groupId> | ||
7 | + <artifactId>spring-boot-starter-parent</artifactId> | ||
8 | + <version>2.2.5.RELEASE</version> | ||
9 | + <relativePath/> <!-- lookup parent from repository --> | ||
10 | + </parent> | ||
11 | + <modelVersion>4.0.0</modelVersion> | ||
12 | + | ||
13 | + <groupId>org.canrd</groupId> | ||
14 | + <artifactId>webmagic-canrd-service</artifactId> | ||
15 | + <version>1.0-SNAPSHOT</version> | ||
16 | + | ||
17 | + <properties> | ||
18 | + <maven-compiler-plugin>3.7.0</maven-compiler-plugin> | ||
19 | + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
20 | + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> | ||
21 | + <java.version>1.8</java.version> | ||
22 | + <joda-time.version>2.9.9</joda-time.version> | ||
23 | + <springboot.version>2.2.5.RELEASE</springboot.version> | ||
24 | + <lombok.version>1.18.12</lombok.version> | ||
25 | + <baomidou.version>3.4.0</baomidou.version> | ||
26 | + <hutool-crypto.version>5.6.1</hutool-crypto.version> | ||
27 | + <hutool-all.version>5.0.6</hutool-all.version> | ||
28 | + <mysql-connector.version>8.0.11</mysql-connector.version> | ||
29 | + <druid.version>1.1.23</druid.version> | ||
30 | + <fastjson.version>1.2.28</fastjson.version> | ||
31 | + <poi.version>3.17</poi.version> | ||
32 | + <poi-ooxml.version>3.17</poi-ooxml.version> | ||
33 | + <poi-excel.version>poi-317.8</poi-excel.version> | ||
34 | + <commons-csv.version>1.6</commons-csv.version> | ||
35 | + <commons-lang3.version>3.8.1</commons-lang3.version> | ||
36 | + <commons-pool2.version>2.11.1</commons-pool2.version> | ||
37 | + <ip2region.version>1.7.2</ip2region.version> | ||
38 | + <userAgentUtils.version>1.20</userAgentUtils.version> | ||
39 | + <swagger.version>2.9.2</swagger.version> | ||
40 | + <swagger-annotations.version>1.5.21</swagger-annotations.version> | ||
41 | + <swagger-models.version>1.5.21</swagger-models.version> | ||
42 | + <guava.version>20.0</guava.version> | ||
43 | + <easy-captcha.version>1.6.2</easy-captcha.version> | ||
44 | + <aliyun-java-sdk-core.version>4.0.3</aliyun-java-sdk-core.version> | ||
45 | + <aliyun-sdk-oss.version>3.15.0</aliyun-sdk-oss.version> | ||
46 | + <thumbnailator.version>0.4.8</thumbnailator.version> | ||
47 | + <jjwt.version>0.10.6</jjwt.version> | ||
48 | + <easyexcel.version>2.2.3</easyexcel.version> | ||
49 | + <webmagic.version>0.10.0</webmagic.version> | ||
50 | + </properties> | ||
51 | + | ||
52 | + <dependencies> | ||
53 | + | ||
54 | + <dependency> | ||
55 | + <groupId>org.springframework.boot</groupId> | ||
56 | + <artifactId>spring-boot-starter-web</artifactId> | ||
57 | + <version>2.2.5.RELEASE</version> | ||
58 | + <exclusions> | ||
59 | + <exclusion> | ||
60 | + <groupId>org.springframework.boot</groupId> | ||
61 | + <artifactId>spring-boot-starter-logging</artifactId> | ||
62 | + </exclusion> | ||
63 | + </exclusions> | ||
64 | + </dependency> | ||
65 | + | ||
66 | + <!-- webmagic核心库 --> | ||
67 | + <dependency> | ||
68 | + <groupId>us.codecraft</groupId> | ||
69 | + <artifactId>webmagic-core</artifactId> | ||
70 | + <version>${webmagic.version}</version> | ||
71 | + </dependency> | ||
72 | + | ||
73 | + | ||
74 | + <!-- webmagic扩展库 --> | ||
75 | + <dependency> | ||
76 | + <groupId>us.codecraft</groupId> | ||
77 | + <artifactId>webmagic-extension</artifactId> | ||
78 | + <version>${webmagic.version}</version> | ||
79 | + </dependency> | ||
80 | + | ||
81 | + | ||
82 | + <!-- Lombok 依赖--> | ||
83 | + <dependency> | ||
84 | + <groupId>org.projectlombok</groupId> | ||
85 | + <artifactId>lombok</artifactId> | ||
86 | + <version>${lombok.version}</version> | ||
87 | + <optional>true</optional> | ||
88 | + </dependency> | ||
89 | + <dependency> | ||
90 | + <groupId>org.springframework.boot</groupId> | ||
91 | + <artifactId>spring-boot-starter-aop</artifactId> | ||
92 | + <version>${springboot.version}</version> | ||
93 | + </dependency> | ||
94 | + <dependency> | ||
95 | + <groupId>org.springframework.boot</groupId> | ||
96 | + <artifactId>spring-boot-starter-test</artifactId> | ||
97 | + <version>${springboot.version}</version> | ||
98 | + <scope>test</scope> | ||
99 | + </dependency> | ||
100 | + | ||
101 | + <dependency> | ||
102 | + <groupId>com.baomidou</groupId> | ||
103 | + <artifactId>mybatis-plus-boot-starter</artifactId> | ||
104 | + <version>${baomidou.version}</version> | ||
105 | + </dependency> | ||
106 | + <!-- <dependency>--> | ||
107 | + <!-- <groupId>com.baomidou</groupId>--> | ||
108 | + <!-- <artifactId>dynamic-datasource-spring-boot-starter</artifactId>--> | ||
109 | + <!-- </dependency>--> | ||
110 | + <dependency> | ||
111 | + <groupId>mysql</groupId> | ||
112 | + <artifactId>mysql-connector-java</artifactId> | ||
113 | + <version>${mysql-connector.version}</version> | ||
114 | + </dependency> | ||
115 | + <dependency> | ||
116 | + <groupId>com.alibaba</groupId> | ||
117 | + <artifactId>druid-spring-boot-starter</artifactId> | ||
118 | + <version>${druid.version}</version> | ||
119 | + </dependency> | ||
120 | + | ||
121 | + <dependency> | ||
122 | + <groupId>org.springframework.boot</groupId> | ||
123 | + <artifactId>spring-boot-starter-log4j2</artifactId> | ||
124 | + <version>${springboot.version}</version> | ||
125 | + </dependency> | ||
126 | + | ||
127 | + | ||
128 | + <dependency> | ||
129 | + <groupId>com.alibaba</groupId> | ||
130 | + <artifactId>fastjson</artifactId> | ||
131 | + <version>${fastjson.version}</version> | ||
132 | + </dependency> | ||
133 | + | ||
134 | + <dependency> | ||
135 | + <groupId>cn.hutool</groupId> | ||
136 | + <artifactId>hutool-crypto</artifactId> | ||
137 | + <version>${hutool-crypto.version}</version> | ||
138 | + </dependency> | ||
139 | + | ||
140 | + <dependency> | ||
141 | + <groupId>org.springframework.boot</groupId> | ||
142 | + <artifactId>spring-boot-starter-data-redis</artifactId> | ||
143 | + <version>${springboot.version}</version> | ||
144 | + </dependency> | ||
145 | + | ||
146 | + <dependency> | ||
147 | + <groupId>org.apache.commons</groupId> | ||
148 | + <artifactId>commons-pool2</artifactId> | ||
149 | + <version>${commons-pool2.version}</version> | ||
150 | + </dependency> | ||
151 | + | ||
152 | + | ||
153 | + <dependency> | ||
154 | + <groupId>org.apache.commons</groupId> | ||
155 | + <artifactId>commons-lang3</artifactId> | ||
156 | + <version>${commons-lang3.version}</version> | ||
157 | + </dependency> | ||
158 | + <dependency> | ||
159 | + <groupId>org.lionsoul</groupId> | ||
160 | + <artifactId>ip2region</artifactId> | ||
161 | + <version>${ip2region.version}</version> | ||
162 | + </dependency> | ||
163 | + <dependency> | ||
164 | + <groupId>eu.bitwalker</groupId> | ||
165 | + <artifactId>UserAgentUtils</artifactId> | ||
166 | + <version>${userAgentUtils.version}</version> | ||
167 | + </dependency> | ||
168 | + | ||
169 | + <!--工具包--> | ||
170 | + <dependency> | ||
171 | + <groupId>cn.hutool</groupId> | ||
172 | + <artifactId>hutool-all</artifactId> | ||
173 | + <version>${hutool-all.version}</version> | ||
174 | + </dependency> | ||
175 | + <dependency> | ||
176 | + <groupId>org.apache.poi</groupId> | ||
177 | + <artifactId>poi</artifactId> | ||
178 | + <version>${poi.version}</version> | ||
179 | + </dependency> | ||
180 | + <dependency> | ||
181 | + <groupId>org.apache.poi</groupId> | ||
182 | + <artifactId>poi-ooxml</artifactId> | ||
183 | + <version>${poi-ooxml.version}</version> | ||
184 | + </dependency> | ||
185 | + | ||
186 | + <dependency> | ||
187 | + <groupId>joda-time</groupId> | ||
188 | + <artifactId>joda-time</artifactId> | ||
189 | + <version>${joda-time.version}</version> | ||
190 | + </dependency> | ||
191 | + | ||
192 | + | ||
193 | + | ||
194 | + </dependencies> | ||
195 | + <build> | ||
196 | + <finalName>webmagic-canrd.service-1.0-SNAPSHOT</finalName> | ||
197 | + <plugins> | ||
198 | + <plugin> | ||
199 | + <groupId>org.apache.maven.plugins</groupId> | ||
200 | + <artifactId>maven-source-plugin</artifactId> | ||
201 | + </plugin> | ||
202 | + | ||
203 | + <plugin> | ||
204 | + <groupId>org.springframework.boot</groupId> | ||
205 | + <artifactId>spring-boot-maven-plugin</artifactId> | ||
206 | + <configuration> | ||
207 | + <executable>true</executable> | ||
208 | + </configuration> | ||
209 | + </plugin> | ||
210 | + | ||
211 | + </plugins> | ||
212 | + </build> | ||
213 | +</project> | ||
0 | \ No newline at end of file | 214 | \ No newline at end of file |
src/main/java/com/canrd/webmagic/Application.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/Application.java | ||
1 | +package com.canrd.webmagic; | ||
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.webmagic.common.directory.Path; | ||
7 | +import com.canrd.webmagic.common.utils.SpringContextHolder; | ||
8 | +import org.mybatis.spring.annotation.MapperScan; | ||
9 | +import org.springframework.boot.SpringApplication; | ||
10 | +import org.springframework.boot.autoconfigure.SpringBootApplication; | ||
11 | +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; | ||
12 | +import org.springframework.context.annotation.Bean; | ||
13 | +import org.springframework.scheduling.annotation.EnableAsync; | ||
14 | +import org.springframework.scheduling.annotation.EnableScheduling; | ||
15 | +import org.springframework.transaction.annotation.EnableTransactionManagement; | ||
16 | + | ||
17 | +/** | ||
18 | + * @author: xms | ||
19 | + * @description: | ||
20 | + * @date: 2024/1/12 14:00 | ||
21 | + * @version: 1.0 | ||
22 | + */ | ||
23 | +@EnableAsync | ||
24 | +@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}, scanBasePackages = {"com.canrd.webmagic"}) | ||
25 | +@MapperScan("com.canrd.webmagic.**.mapper") | ||
26 | +@EnableScheduling | ||
27 | +@EnableTransactionManagement | ||
28 | +public class Application { | ||
29 | + | ||
30 | + private static void setLogPath() { | ||
31 | + String appPath = Path.getAppPath(Application.class); | ||
32 | + System.setProperty("logging.path", appPath); | ||
33 | + } | ||
34 | + | ||
35 | + @Bean | ||
36 | + public SpringContextHolder springContextHolder() { | ||
37 | + return new SpringContextHolder(); | ||
38 | + } | ||
39 | + | ||
40 | + public static void main(String[] args) { | ||
41 | + setLogPath(); | ||
42 | + SpringApplication.run(Application.class, args); | ||
43 | + } | ||
44 | + | ||
45 | + /** | ||
46 | + * 分页插件 | ||
47 | + * | ||
48 | + * @return | ||
49 | + */ | ||
50 | + @Bean | ||
51 | + public MybatisPlusInterceptor mybatisPlusInterceptor() { | ||
52 | + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); | ||
53 | + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.POSTGRE_SQL)); | ||
54 | + return interceptor; | ||
55 | + } | ||
56 | +} |
src/main/java/com/canrd/webmagic/common/annotation/AnonymousAccess.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/annotation/AnonymousAccess.java | ||
1 | +package com.canrd.webmagic.common.annotation; | ||
2 | + | ||
3 | +import java.lang.annotation.ElementType; | ||
4 | +import java.lang.annotation.Retention; | ||
5 | +import java.lang.annotation.RetentionPolicy; | ||
6 | +import java.lang.annotation.Target; | ||
7 | + | ||
8 | +/** | ||
9 | + * 用于标记匿名访问方法 | ||
10 | + */ | ||
11 | +@Target(ElementType.METHOD) | ||
12 | +@Retention(RetentionPolicy.RUNTIME) | ||
13 | +public @interface AnonymousAccess { | ||
14 | + | ||
15 | +} |
src/main/java/com/canrd/webmagic/common/constant/Constant.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/constant/Constant.java | ||
1 | +package com.canrd.webmagic.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 | +} |
src/main/java/com/canrd/webmagic/common/constant/ElAdminConstant.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/constant/ElAdminConstant.java | ||
1 | +package com.canrd.webmagic.common.constant; | ||
2 | + | ||
3 | +/** | ||
4 | + * 常用静态常量 | ||
5 | + * | ||
6 | + * @date 2018-12-26 | ||
7 | + */ | ||
8 | +public class ElAdminConstant { | ||
9 | + | ||
10 | + public static final String RESET_PASS = "重置密码"; | ||
11 | + | ||
12 | + public static final String RESET_MAIL = "重置邮箱"; | ||
13 | + | ||
14 | + /** | ||
15 | + * 用于IP定位转换 | ||
16 | + */ | ||
17 | + public static final String REGION = "内网IP|内网IP"; | ||
18 | + | ||
19 | + /** | ||
20 | + * 常用接口 | ||
21 | + */ | ||
22 | + public static class Url { | ||
23 | + public static final String SM_MS_URL = "https://sm.ms/api"; | ||
24 | + } | ||
25 | +} |
src/main/java/com/canrd/webmagic/common/constant/ServerResult.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/constant/ServerResult.java | ||
1 | +package com.canrd.webmagic.common.constant; | ||
2 | + | ||
3 | + | ||
4 | +import java.io.Serializable; | ||
5 | +import java.util.HashMap; | ||
6 | +import java.util.Map; | ||
7 | + | ||
8 | +/** | ||
9 | + * @Date: 2020/9/5 | ||
10 | + * 统一的返回结果实体 | ||
11 | + */ | ||
12 | +public class ServerResult<T> implements Serializable { | ||
13 | + /** | ||
14 | + * 序列化ID | ||
15 | + */ | ||
16 | + private static final long serialVersionUID = -5809782578272943999L; | ||
17 | + /** | ||
18 | + * 返回的状态码 | ||
19 | + */ | ||
20 | + private int result = ServerResultCode.SUCCESS.getErrorCode(); | ||
21 | + /** | ||
22 | + * 返回的消息 | ||
23 | + */ | ||
24 | + private String message = ServerResultCode.SUCCESS.getErrorDesc(); | ||
25 | + /** | ||
26 | + * 返回的数据实体 | ||
27 | + */ | ||
28 | + private T data = null; | ||
29 | + /** | ||
30 | + * | ||
31 | + */ | ||
32 | + final int INIT_SIZE = 128; | ||
33 | + | ||
34 | + /** | ||
35 | + * | ||
36 | + */ | ||
37 | + public ServerResult() { | ||
38 | + } | ||
39 | + | ||
40 | + @Override | ||
41 | + public String toString() { | ||
42 | + StringBuilder buffer = new StringBuilder(INIT_SIZE); | ||
43 | + buffer.append("{\"result\":").append(this.result); | ||
44 | + buffer.append(",\"message\":\"").append(this.message != null ? message : "").append("\""); | ||
45 | + buffer.append(",\"data\":").append(data).append("}"); | ||
46 | + return buffer.toString(); | ||
47 | + } | ||
48 | + | ||
49 | + public int getResult() { | ||
50 | + return result; | ||
51 | + } | ||
52 | + | ||
53 | + public ServerResult setResult(int result) { | ||
54 | + this.result = result; | ||
55 | + return this; | ||
56 | + } | ||
57 | + | ||
58 | + public ServerResult setResult(ServerResultCode serverResultCode) { | ||
59 | + this.result = serverResultCode.getErrorCode(); | ||
60 | + this.message = serverResultCode.getErrorDesc(); | ||
61 | + return this; | ||
62 | + } | ||
63 | + | ||
64 | + public ServerResult setResult(int errorCode, String errorDesc) { | ||
65 | + this.result = errorCode; | ||
66 | + this.message = errorDesc; | ||
67 | + return this; | ||
68 | + } | ||
69 | + | ||
70 | + public String getMessage() { | ||
71 | + return message; | ||
72 | + } | ||
73 | + | ||
74 | + public ServerResult<T> setMessage(String message) { | ||
75 | + this.message = message; | ||
76 | + return this; | ||
77 | + } | ||
78 | + | ||
79 | + public T getData() { | ||
80 | + return data; | ||
81 | + } | ||
82 | + | ||
83 | + public ServerResult setData(T data) { | ||
84 | + this.data = data; | ||
85 | + return this; | ||
86 | + } | ||
87 | + | ||
88 | + public static <T> ServerResult<T> success() { | ||
89 | + return new ServerResult() | ||
90 | + .setResult(ServerResultCode.SUCCESS) | ||
91 | + .setMessage(ServerResultCode.SUCCESS.getErrorDesc()) | ||
92 | + .setData(defaultResult(ServerResultCode.SUCCESS)); | ||
93 | + } | ||
94 | + | ||
95 | + public static <T> ServerResult<T> success(T data) { | ||
96 | + return new ServerResult() | ||
97 | + .setResult(ServerResultCode.SUCCESS) | ||
98 | + .setMessage(ServerResultCode.SUCCESS.getErrorDesc()) | ||
99 | + .setData(data); | ||
100 | + } | ||
101 | + | ||
102 | + public static <T> ServerResult<T> success(T data, String message) { | ||
103 | + return new ServerResult() | ||
104 | + .setResult(ServerResultCode.SUCCESS) | ||
105 | + .setMessage(message) | ||
106 | + .setData(data); | ||
107 | + } | ||
108 | + | ||
109 | + /** | ||
110 | + * @description 错误码使用系统错误 1000 错误类型自定义 | ||
111 | + * @author dengbin | ||
112 | + * @date 2020/9/12 | ||
113 | + */ | ||
114 | + public static <T> ServerResult<T> fail(String message) { | ||
115 | + return new ServerResult() | ||
116 | + .setResult(ServerResultCode.FAIL) | ||
117 | + .setMessage(message) | ||
118 | + .setData(defaultResult(Constant.RESULT_FAIL)); | ||
119 | + } | ||
120 | + | ||
121 | + /** | ||
122 | + * 错误时需要返回相关数据时使用 | ||
123 | + * | ||
124 | + * @param data | ||
125 | + * @param <T> | ||
126 | + * @return | ||
127 | + */ | ||
128 | + public static <T> ServerResult<T> fail(T data, ServerResultCode serverResultCode) { | ||
129 | + return new ServerResult() | ||
130 | + .setData(data) | ||
131 | + .setResult(serverResultCode) | ||
132 | + .setMessage(serverResultCode.getErrorDesc()); | ||
133 | + } | ||
134 | + | ||
135 | + /** | ||
136 | + * 错误时需要返回相关数据时使用(不设值 data) | ||
137 | + * | ||
138 | + * @param sr | ||
139 | + * @param | ||
140 | + * @return | ||
141 | + */ | ||
142 | + public static <T> ServerResult<T> fail(ServerResult<?> sr) { | ||
143 | + return new ServerResult<>() | ||
144 | + .setMessage(sr.getMessage()) | ||
145 | + .setResult(sr.getResult()); | ||
146 | + | ||
147 | + } | ||
148 | + | ||
149 | + /** | ||
150 | + * @description 错误码使用上面的枚举定义的,错误信息重新定义 | ||
151 | + * @author dengbin | ||
152 | + * @date 2020/9/12 | ||
153 | + */ | ||
154 | + public static <T> ServerResult<T> fail(ServerResultCode serverResultCode, String msg) { | ||
155 | + return new ServerResult() | ||
156 | + .setResult(serverResultCode) | ||
157 | + .setMessage(msg) | ||
158 | + .setData(defaultResult(Constant.RESULT_FAIL)); | ||
159 | + } | ||
160 | + | ||
161 | + /** | ||
162 | + * @return | ||
163 | + * @description 直接选用上面的枚举错误码,输出定义的错误信息 | ||
164 | + * @author dengbin | ||
165 | + * @date 2020/9/12 | ||
166 | + */ | ||
167 | + public static <T> ServerResult<T> fail(ServerResultCode serverResultCode) { | ||
168 | + return new ServerResult() | ||
169 | + .setResult(serverResultCode) | ||
170 | + .setMessage(serverResultCode.getErrorDesc()) | ||
171 | + .setData(defaultResult(Constant.RESULT_FAIL)); | ||
172 | + } | ||
173 | + | ||
174 | + /** | ||
175 | + * 错误时需要返回相关数据时使用 | ||
176 | + * | ||
177 | + * @param data | ||
178 | + * @param <T> | ||
179 | + * @return | ||
180 | + */ | ||
181 | + public static <T> ServerResult<T> fail(T data, int errorCode, String errorDesc) { | ||
182 | + return new ServerResult() | ||
183 | + .setData(data) | ||
184 | + .setResult(errorCode, errorDesc); | ||
185 | + } | ||
186 | + | ||
187 | + | ||
188 | + public static <T> ServerResult<T> fail() { | ||
189 | + return new ServerResult() | ||
190 | + .setResult(ServerResultCode.FAIL.getErrorCode()) | ||
191 | + .setMessage(ServerResultCode.FAIL.getErrorDesc()) | ||
192 | + .setData(defaultResult(Constant.RESULT_FAIL)); | ||
193 | + } | ||
194 | + | ||
195 | + | ||
196 | + /** | ||
197 | + * @description 直接选用上面的枚举错误码,输出定义的错误信息 | ||
198 | + * @author dengbin | ||
199 | + * @date 2020/9/12 | ||
200 | + */ | ||
201 | + public ServerResult failEnum(ServerResultCode serverResultCode) { | ||
202 | + setResult(serverResultCode); | ||
203 | + setMessage(serverResultCode.getErrorDesc()); | ||
204 | + return this; | ||
205 | + } | ||
206 | + | ||
207 | + public static <T> ServerResult<T> fail(int errorCode, String errorDesc) { | ||
208 | + return new ServerResult() | ||
209 | + .setResult(errorCode, errorDesc) | ||
210 | + .setData(defaultResult(Constant.RESULT_FAIL)); | ||
211 | + | ||
212 | + } | ||
213 | + | ||
214 | + /** | ||
215 | + * 判断当前的状态码是否是SUCCESS | ||
216 | + * | ||
217 | + * @return 结果 ture or false | ||
218 | + */ | ||
219 | + public boolean checkSuccess() { | ||
220 | + return result == ServerResultCode.SUCCESS.getErrorCode(); | ||
221 | + } | ||
222 | + | ||
223 | + public boolean checkNotSuccess() { | ||
224 | + return !checkSuccess(); | ||
225 | + } | ||
226 | + | ||
227 | + private static Map<String, Object> defaultResult(Object object) { | ||
228 | + Map<String, Object> map = new HashMap<>(Constant.ONE); | ||
229 | + map.put(Constant.RESULT_CHARACTER, null); | ||
230 | + return map; | ||
231 | + } | ||
232 | +} |
src/main/java/com/canrd/webmagic/common/constant/ServerResultCode.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/constant/ServerResultCode.java | ||
1 | +package com.canrd.webmagic.common.constant; | ||
2 | + | ||
3 | + | ||
4 | +import com.canrd.webmagic.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 | + UNAUTHORIZED(401, "登录状态过期"), | ||
18 | + | ||
19 | + //空指针异常 | ||
20 | + NULL_POINT(1001, "空指针异常"), | ||
21 | + | ||
22 | + //校验异常 | ||
23 | + RUN_ERROR(1002, "程序运行报错"), | ||
24 | + ILLEGAL_ARGUMENT(1003, "参数非法"), | ||
25 | + FILED_ERROR(1004, "传入参数错误"), | ||
26 | + PARAM_ERROR(1005, "入参为空"), | ||
27 | + EMPTY_RESULT(1006, "数据不存在"), | ||
28 | + EMPTY_LIST(1007, "查询结果为空"), | ||
29 | + IMG_CAPTCHA_ERROR(1008, "图片验证码错误"), | ||
30 | + IMG_CAPTCHA_EXPIRE_ERROR(1009, "图片验证码不存在或已过期"), | ||
31 | + SMS_CAPTCHA_ERROR(1010, "短信验证码错误"), | ||
32 | + SMS_CAPTCHA_EXPIRE_ERROR(1011, "短信验证码不存在或已过期"), | ||
33 | + | ||
34 | + //认证授权异常 | ||
35 | + UNAUTHENTICATION(401, "未登录"), | ||
36 | + | ||
37 | + | ||
38 | + //用户 | ||
39 | + USER_NOT_EXIT(20001, "用户不存在"), | ||
40 | + USER_UN_ENABLE(20002, "用户未激活"), | ||
41 | + | ||
42 | + | ||
43 | + // 公司 | ||
44 | + COMPANY_NOT_EXIT(30001, "公司不存在"), | ||
45 | + | ||
46 | + // 短信 | ||
47 | + SMS_SEND_OVER_LIMIT_ERROR(40001, "发送频次过高,请一分钟后再发送"), | ||
48 | + EMAIL_SEND_OVER_LIMIT_ERROR(40002, "发送频次过高(一天最多修改三次),请第二天后再发送"), | ||
49 | + | ||
50 | + // 会员 | ||
51 | + MEMBER_PHONE_REGISTER_ERROR(50001, "手机已经被注册使用!"), | ||
52 | + MEMBER_AGREE_AGREEMENT_CHOOSE_ERROR(50002, "必须同意注册协议才可进行注册操作!"), | ||
53 | + MEMBER_CONFIRM_PASSWORD_ERROR(50003, "两次密码输入不一致!"), | ||
54 | + MEMBER_LOGIN_PHONE_ERROR(50004, "手机号没有注册,请注册后登录!"), | ||
55 | + MEMBER_LOGIN_LOCKED_TIME_ERROR(50005, "账号被锁定,请稍后再试试!"), | ||
56 | + MEMBER_RECOVER_PASSWORD_ERROR(50006, "对不起,此密码找回链接已失效!"), | ||
57 | + MEMBER_RECOVER_PASSWORD_EXPIRE_ERROR(50007, "对不起,此密码找回链接已过期!"), | ||
58 | + | ||
59 | + //产品 | ||
60 | + PRODUCT_NOT_EXIST_ERROR(60001, "此商品已下架!"), | ||
61 | + PRODUCT_NOT_MORE_STORE_ERROR(60002, "添加购物车失败,商品库存不足!"), | ||
62 | + | ||
63 | + //订单 | ||
64 | + ORDER_BASE_INFO_EMPTY(70001, "订单基础信息不能为空!"), | ||
65 | + | ||
66 | + //申请 | ||
67 | + APPLY_UNLOCK_FIELD_EXIST(80001, "还有未审批完结的申请,请等上一个申请单完结!"), | ||
68 | + APPLY_NOT_EXIST(80002, "申请单不存在!"), | ||
69 | + | ||
70 | + //上传图片 | ||
71 | + UPLOAD_IMAGES_ERROR(900021, "上传图片失败!"), | ||
72 | + ; | ||
73 | + | ||
74 | + | ||
75 | + ServerResultCode(Integer errorCode, String errorDesc) { | ||
76 | + this.errorCode = errorCode; | ||
77 | + this.errorDesc = errorDesc; | ||
78 | + } | ||
79 | + | ||
80 | + @Setter | ||
81 | + private Integer errorCode; | ||
82 | + @Setter | ||
83 | + private String errorDesc; | ||
84 | + | ||
85 | + @Override | ||
86 | + public Integer getErrorCode() { | ||
87 | + return this.errorCode; | ||
88 | + } | ||
89 | + | ||
90 | + @Override | ||
91 | + public String getErrorDesc() { | ||
92 | + return this.errorDesc; | ||
93 | + } | ||
94 | + | ||
95 | + /** | ||
96 | + * 根据errorCode获得枚举 | ||
97 | + * | ||
98 | + * @param errorCode | ||
99 | + * @return | ||
100 | + */ | ||
101 | + public static String getDescByCode(Integer errorCode) { | ||
102 | + if (errorCode == null) { | ||
103 | + return null; | ||
104 | + } | ||
105 | + ServerResultCode[] serverResults = values(); | ||
106 | + for (ServerResultCode serverResult : serverResults) { | ||
107 | + if (serverResult.getErrorCode().equals(errorCode)) { | ||
108 | + return serverResult.getErrorDesc(); | ||
109 | + } | ||
110 | + } | ||
111 | + return null; | ||
112 | + } | ||
113 | + | ||
114 | +} | ||
0 | \ No newline at end of file | 115 | \ No newline at end of file |
src/main/java/com/canrd/webmagic/common/directory/Path.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/directory/Path.java | ||
1 | +package com.canrd.webmagic.common.directory; | ||
2 | + | ||
3 | +import com.canrd.webmagic.common.constant.Constant; | ||
4 | + | ||
5 | +/** | ||
6 | + * @author xms | ||
7 | + */ | ||
8 | +public class Path { | ||
9 | + /** | ||
10 | + * 获取程序启动路径 | ||
11 | + * | ||
12 | + * @param cls,建议直接传 ServiceApplication.class | ||
13 | + * @return 应用启动路径 | ||
14 | + */ | ||
15 | + public static String getAppPath(Class cls) { | ||
16 | + String path = cls.getResource(Constant.SLASH_MARK_CHARACTER).getPath(); | ||
17 | + String os = System.getProperty("os.name").toLowerCase(); | ||
18 | + final String OSWINDOW = "windows"; | ||
19 | + if (os.indexOf(OSWINDOW) != -1 && path.length() > 1) { | ||
20 | + //windows路径样例: /D:/work/code/shop-services/online-shop-oss/target/classes/ | ||
21 | + return path.substring(1); | ||
22 | + } | ||
23 | + | ||
24 | + //linux 路径样例 file:/opt/target/online-shop-oss-SNAPSHOT.jar!/BOOT-INF/classes!/"; | ||
25 | + final String FILE = "file:"; | ||
26 | + if (path.indexOf(FILE) != -1) { | ||
27 | + path = path.substring(FILE.length()); | ||
28 | + } | ||
29 | + | ||
30 | + int pos = -1; | ||
31 | + if ((pos = path.indexOf(Constant.EXCLAMATION_MARK_CHARACTER)) != -1) { | ||
32 | + if (-1 != (pos = path.lastIndexOf(Constant.SLASH_MARK_CHARACTER, pos))) { | ||
33 | + path = path.substring(0, pos + 1); | ||
34 | + } | ||
35 | + } | ||
36 | + | ||
37 | + return path; | ||
38 | + } | ||
39 | +} |
src/main/java/com/canrd/webmagic/common/exception/BadRequestException.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/exception/BadRequestException.java | ||
1 | +package com.canrd.webmagic.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 | +} |
src/main/java/com/canrd/webmagic/common/exception/BusinessException.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/exception/BusinessException.java | ||
1 | +package com.canrd.webmagic.common.exception; | ||
2 | + | ||
3 | +import com.canrd.webmagic.common.constant.ServerResult; | ||
4 | +import com.canrd.webmagic.common.constant.ServerResultCode; | ||
5 | +import lombok.Getter; | ||
6 | +import lombok.Setter; | ||
7 | +import lombok.extern.slf4j.Slf4j; | ||
8 | + | ||
9 | +/** | ||
10 | + * <p>基础异常类,所有自定义异常类都需要继承本类</p> | ||
11 | + */ | ||
12 | +@Slf4j | ||
13 | +public class BusinessException extends RuntimeException { | ||
14 | + | ||
15 | + private static final long serialVersionUID = 3152549963899218489L; | ||
16 | + @Setter | ||
17 | + @Getter | ||
18 | + private String errorDesc; | ||
19 | + @Setter | ||
20 | + @Getter | ||
21 | + private Integer errorCode; | ||
22 | + @Setter | ||
23 | + @Getter | ||
24 | + private Object data; | ||
25 | + | ||
26 | + public BusinessException() { | ||
27 | + super(ServerResultCode.FAIL.getErrorDesc()); | ||
28 | + this.errorCode = ServerResultCode.FAIL.getErrorCode(); | ||
29 | + this.errorDesc = ServerResultCode.FAIL.getErrorDesc(); | ||
30 | + } | ||
31 | + | ||
32 | + public BusinessException(int errorCode, String errorDesc) { | ||
33 | + super(errorDesc); | ||
34 | + this.errorCode = errorCode; | ||
35 | + this.errorDesc = errorDesc; | ||
36 | + } | ||
37 | + | ||
38 | + public BusinessException(ServerResultCode serverResultCode) { | ||
39 | + super(serverResultCode.getErrorDesc()); | ||
40 | + this.errorCode = serverResultCode.getErrorCode(); | ||
41 | + this.errorDesc = serverResultCode.getErrorDesc(); | ||
42 | + log.error("业务异常: ", this); | ||
43 | + } | ||
44 | + | ||
45 | + public BusinessException(ErrorInfo errorInfo) { | ||
46 | + super(errorInfo.getErrorDesc()); | ||
47 | + this.errorCode = errorInfo.getErrorCode(); | ||
48 | + this.errorDesc = errorInfo.getErrorDesc(); | ||
49 | + log.error("业务异常: ", this); | ||
50 | + } | ||
51 | + | ||
52 | + public BusinessException(ServerResult<?> serverResult) { | ||
53 | + super(serverResult == null ? ServerResultCode.FAIL.getErrorDesc() : serverResult.getMessage()); | ||
54 | + if (serverResult == null) { | ||
55 | + this.errorCode = ServerResultCode.FAIL.getErrorCode(); | ||
56 | + this.errorDesc = ServerResultCode.FAIL.getErrorDesc(); | ||
57 | + } else { | ||
58 | + this.errorCode = serverResult.getResult(); | ||
59 | + this.errorDesc = serverResult.getMessage(); | ||
60 | + this.data = serverResult.getData(); | ||
61 | + } | ||
62 | + log.error("业务异常: ", this); | ||
63 | + } | ||
64 | + | ||
65 | + public BusinessException(String message) { | ||
66 | + super(message); | ||
67 | + } | ||
68 | + | ||
69 | + public BusinessException(Throwable cause) { | ||
70 | + super(cause); | ||
71 | + log.error("业务异常: ", this); | ||
72 | + } | ||
73 | + | ||
74 | + public BusinessException(String message, Throwable cause) { | ||
75 | + super(message, cause); | ||
76 | + log.error("业务异常: ", this); | ||
77 | + } | ||
78 | +} |
src/main/java/com/canrd/webmagic/common/exception/BusinessExceptionHandlerAdvice.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/exception/BusinessExceptionHandlerAdvice.java | ||
1 | +package com.canrd.webmagic.common.exception; | ||
2 | + | ||
3 | +import com.canrd.webmagic.common.constant.ServerResult; | ||
4 | +import com.canrd.webmagic.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 | + * @date 2021/1/11 | ||
18 | + */ | ||
19 | +@ControllerAdvice | ||
20 | +@Order(5) | ||
21 | +public class BusinessExceptionHandlerAdvice { | ||
22 | + | ||
23 | + | ||
24 | + @ExceptionHandler(value = {BusinessException.class}) | ||
25 | + @ResponseStatus(value = HttpStatus.OK) | ||
26 | + public ResponseEntity<Object> handleException(BusinessException exception) throws Exception { | ||
27 | + return new ResponseEntity<Object>(handleBusinessException(exception), HttpStatus.OK); | ||
28 | + } | ||
29 | + | ||
30 | + private ServerResult handleBusinessException(BusinessException exception) { | ||
31 | + Integer code = Optional.ofNullable(exception.getErrorCode()).orElse(ServerResultCode.FAIL.getErrorCode()); | ||
32 | + String msg = Optional.ofNullable(exception.getMessage()).orElse(ServerResultCode.FAIL.getErrorDesc()); | ||
33 | + Object data = Optional.ofNullable(exception.getData()).orElse(null); | ||
34 | + return ServerResult.fail(data, code, msg); | ||
35 | + } | ||
36 | +} |
src/main/java/com/canrd/webmagic/common/exception/EntityExistException.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/exception/EntityExistException.java | ||
1 | +package com.canrd.webmagic.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 | \ No newline at end of file | 20 | \ No newline at end of file |
src/main/java/com/canrd/webmagic/common/exception/EntityNotFoundException.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/exception/EntityNotFoundException.java | ||
1 | +package com.canrd.webmagic.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 | \ No newline at end of file | 20 | \ No newline at end of file |
src/main/java/com/canrd/webmagic/common/exception/ErrorInfo.java
0 → 100644
src/main/java/com/canrd/webmagic/common/exception/handler/ApiError.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/exception/handler/ApiError.java | ||
1 | +package com.canrd.webmagic.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 | + |
src/main/java/com/canrd/webmagic/common/exception/handler/GlobalExceptionHandler.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/exception/handler/GlobalExceptionHandler.java | ||
1 | +package com.canrd.webmagic.common.exception.handler; | ||
2 | + | ||
3 | +import com.canrd.webmagic.common.constant.ServerResult; | ||
4 | +import com.canrd.webmagic.common.constant.ServerResultCode; | ||
5 | +import com.canrd.webmagic.common.exception.BusinessException; | ||
6 | +import com.canrd.webmagic.common.exception.EntityExistException; | ||
7 | +import com.canrd.webmagic.common.exception.EntityNotFoundException; | ||
8 | +import com.canrd.webmagic.common.utils.ThrowableUtil; | ||
9 | +import lombok.extern.slf4j.Slf4j; | ||
10 | +import org.springframework.http.HttpStatus; | ||
11 | +import org.springframework.http.ResponseEntity; | ||
12 | +import org.springframework.web.bind.MethodArgumentNotValidException; | ||
13 | +import org.springframework.web.bind.annotation.ExceptionHandler; | ||
14 | +import org.springframework.web.bind.annotation.ResponseStatus; | ||
15 | +import org.springframework.web.bind.annotation.RestControllerAdvice; | ||
16 | +import org.springframework.web.multipart.MaxUploadSizeExceededException; | ||
17 | + | ||
18 | +import java.util.Objects; | ||
19 | + | ||
20 | +/** | ||
21 | + * @date 2018-11-23 | ||
22 | + */ | ||
23 | +@Slf4j | ||
24 | +@RestControllerAdvice | ||
25 | +public class GlobalExceptionHandler { | ||
26 | + /** | ||
27 | + * @param exception | ||
28 | + * @return | ||
29 | + * @throws Exception | ||
30 | + */ | ||
31 | + @ExceptionHandler(value = RuntimeException.class) | ||
32 | + public ResponseEntity<Object> handleServiceException(Exception exception) throws Exception { | ||
33 | + return new ResponseEntity(translateException(exception), HttpStatus.OK); | ||
34 | + } | ||
35 | + | ||
36 | + /** | ||
37 | + * @param exception | ||
38 | + * @return | ||
39 | + * @throws Exception | ||
40 | + */ | ||
41 | + @ExceptionHandler(value = Exception.class) | ||
42 | + @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) | ||
43 | + public ResponseEntity<Object> handleException(Exception exception) throws Exception { | ||
44 | + return new ResponseEntity<Object>(translateException(exception), HttpStatus.OK); | ||
45 | + } | ||
46 | + | ||
47 | + | ||
48 | + /** | ||
49 | + * 处理所有接口数据验证异常 | ||
50 | + * | ||
51 | + * @param e | ||
52 | + * @return | ||
53 | + */ | ||
54 | + @ExceptionHandler(MethodArgumentNotValidException.class) | ||
55 | + public ResponseEntity<ServerResult> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { | ||
56 | + // 打印堆栈信息 | ||
57 | + log.error(ThrowableUtil.getStackTrace(e)); | ||
58 | + String[] str = Objects.requireNonNull(e.getBindingResult().getAllErrors().get(0).getCodes())[1].split("\\."); | ||
59 | + String message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage(); | ||
60 | + String msg = "不能为空"; | ||
61 | + if (msg.equals(message)) { | ||
62 | + message = str[1] + ":" + message; | ||
63 | + } | ||
64 | + return buildResponseEntity(ServerResult.fail(message)); | ||
65 | + } | ||
66 | + | ||
67 | + /** | ||
68 | + * 处理自定义异常 | ||
69 | + * | ||
70 | + * @param e | ||
71 | + * @return | ||
72 | + */ | ||
73 | + @ExceptionHandler(value = BusinessException.class) | ||
74 | + public ResponseEntity<ServerResult> badRequestException(BusinessException e) { | ||
75 | + // 打印堆栈信息 | ||
76 | + log.error(ThrowableUtil.getStackTrace(e)); | ||
77 | + return buildResponseEntity(ServerResult.fail(e.getErrorCode(), e.getMessage())); | ||
78 | + } | ||
79 | + | ||
80 | + /** | ||
81 | + * 处理 EntityExist | ||
82 | + */ | ||
83 | + @ExceptionHandler(value = EntityExistException.class) | ||
84 | + public ResponseEntity<ServerResult> entityExistException(EntityExistException e) { | ||
85 | + // 打印堆栈信息 | ||
86 | + log.error(ThrowableUtil.getStackTrace(e)); | ||
87 | + return buildResponseEntity(ServerResult.fail(e.getMessage())); | ||
88 | + } | ||
89 | + | ||
90 | + /** | ||
91 | + * 处理 EntityNotFound | ||
92 | + * | ||
93 | + * @param e | ||
94 | + * @return | ||
95 | + */ | ||
96 | + @ExceptionHandler(value = EntityNotFoundException.class) | ||
97 | + public ResponseEntity<ServerResult> entityNotFoundException(EntityNotFoundException e) { | ||
98 | + // 打印堆栈信息 | ||
99 | + log.error(ThrowableUtil.getStackTrace(e)); | ||
100 | + return buildResponseEntity(ServerResult.fail(HttpStatus.NOT_FOUND.value(), e.getMessage())); | ||
101 | + } | ||
102 | + | ||
103 | + /** | ||
104 | + * @param serverResult | ||
105 | + * @return | ||
106 | + */ | ||
107 | + private ResponseEntity<ServerResult> buildResponseEntity(ServerResult serverResult) { | ||
108 | + return new ResponseEntity<>(serverResult, HttpStatus.valueOf(200)); | ||
109 | + } | ||
110 | + | ||
111 | + /** | ||
112 | + * @param e | ||
113 | + * @return | ||
114 | + * @throws Exception | ||
115 | + */ | ||
116 | + private Object translateException(Exception e) throws Exception { | ||
117 | + ServerResult serverResult = null; | ||
118 | + if (e instanceof NullPointerException) { | ||
119 | + serverResult = ServerResult.fail(ServerResultCode.NULL_POINT); | ||
120 | + } else if (e instanceof IllegalArgumentException) { | ||
121 | + serverResult = ServerResult.fail(ServerResultCode.FAIL); | ||
122 | + } else if (e instanceof MaxUploadSizeExceededException) { | ||
123 | + serverResult = ServerResult.fail(ServerResultCode.FIlE_UPLOAD_TOO_LARGE); | ||
124 | + } else if (e instanceof BusinessException) { | ||
125 | + serverResult = ServerResult.fail(((BusinessException) e).getErrorCode(), ((BusinessException) e).getErrorDesc()); | ||
126 | + } else { | ||
127 | + serverResult = ServerResult.fail(ServerResultCode.FAIL); | ||
128 | + serverResult.setMessage(serverResult.getMessage() + "|,业务异常:" + e.getMessage()); | ||
129 | + } | ||
130 | + | ||
131 | + log.error("业务异常", e); | ||
132 | + return serverResult; | ||
133 | + } | ||
134 | +} |
src/main/java/com/canrd/webmagic/common/jsr303/ListValueConstraintValidator.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/jsr303/ListValueConstraintValidator.java | ||
1 | +package com.canrd.webmagic.common.jsr303; | ||
2 | + | ||
3 | + | ||
4 | +import com.canrd.webmagic.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 | +} |
src/main/java/com/canrd/webmagic/common/jsr303/OperateGroup.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/jsr303/OperateGroup.java | ||
1 | +package com.canrd.webmagic.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 | +} |
src/main/java/com/canrd/webmagic/common/jsr303/annotation/ListIntValue.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/jsr303/annotation/ListIntValue.java | ||
1 | +package com.canrd.webmagic.common.jsr303.annotation; | ||
2 | + | ||
3 | + | ||
4 | +import com.canrd.webmagic.common.jsr303.ListValueConstraintValidator; | ||
5 | + | ||
6 | +import javax.validation.Constraint; | ||
7 | +import javax.validation.Payload; | ||
8 | +import java.lang.annotation.*; | ||
9 | + | ||
10 | +/** | ||
11 | + * @date 2023-01-15 | ||
12 | + */ | ||
13 | +@Constraint(validatedBy = {ListValueConstraintValidator.class}) | ||
14 | +@Documented | ||
15 | +@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE}) | ||
16 | +@Retention(RetentionPolicy.RUNTIME) | ||
17 | +public @interface ListIntValue { | ||
18 | + | ||
19 | + | ||
20 | + // 配置文件中错误提示信息的名称 | ||
21 | + String message() default "非法的类型"; | ||
22 | + | ||
23 | + Class<?>[] groups() default {}; | ||
24 | + | ||
25 | + Class<? extends Payload>[] payload() default {}; | ||
26 | + | ||
27 | + // 自定义值的类型 | ||
28 | + int[] enumValue() default {}; | ||
29 | + | ||
30 | + // 是否必填,默认允许为空 | ||
31 | + boolean require() default false; | ||
32 | +} |
src/main/java/com/canrd/webmagic/common/utils/DateUtil.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/utils/DateUtil.java | ||
1 | +package com.canrd.webmagic.common.utils; | ||
2 | + | ||
3 | + | ||
4 | +import java.text.DateFormat; | ||
5 | +import java.text.ParseException; | ||
6 | +import java.text.SimpleDateFormat; | ||
7 | +import java.time.*; | ||
8 | +import java.time.format.DateTimeFormatter; | ||
9 | +import java.time.temporal.ChronoField; | ||
10 | +import java.time.temporal.TemporalAdjusters; | ||
11 | +import java.util.Date; | ||
12 | +import java.util.Locale; | ||
13 | +import java.util.TimeZone; | ||
14 | + | ||
15 | +/** | ||
16 | + * @Date: 2020/9/1 | ||
17 | + * 基于Java8的时间工具类 | ||
18 | + */ | ||
19 | +public class DateUtil { | ||
20 | + /** | ||
21 | + * 例如:2018-12-28 | ||
22 | + */ | ||
23 | + public static final String DATE = "yyyy-MM-dd"; | ||
24 | + /** | ||
25 | + * 例如:2018.12.28 | ||
26 | + */ | ||
27 | + public static final String DATE_WITH_POINT = "yyyy.MM.dd"; | ||
28 | + /** | ||
29 | + * 例如:2018-12-28 10:00:00 | ||
30 | + */ | ||
31 | + public static final String DATE_TIME = "yyyy-MM-dd HH:mm:ss"; | ||
32 | + /** | ||
33 | + * 例如:2018-12-28 10:00:00:215 | ||
34 | + */ | ||
35 | + public static final String DATE_TIME_MS = "yyyy-MM-dd HH:mm:ss.SSS"; | ||
36 | + /** | ||
37 | + * 例如:10:00:00 | ||
38 | + */ | ||
39 | + public static final String TIME = "HHmmss"; | ||
40 | + /** | ||
41 | + * 例如:10:00:00 | ||
42 | + */ | ||
43 | + public static final String TIME_HAVE_SECOND = "HH:mm:ss"; | ||
44 | + /** | ||
45 | + * 例如:10:00 | ||
46 | + */ | ||
47 | + public static final String TIME_WITHOUT_SECOND = "HH:mm"; | ||
48 | + | ||
49 | + /** | ||
50 | + * 例如:2018-12-28 10:00 | ||
51 | + */ | ||
52 | + public static final String DATE_TIME_WITHOUT_SECONDS = "yyyy-MM-dd HH:mm"; | ||
53 | + | ||
54 | + /** | ||
55 | + * 例如 2020/04/16 12:23:0 | ||
56 | + */ | ||
57 | + public static final String DATE_TIME_WITHOUT_SECONDS_OTHER = "yyyy/MM/dd HH:mm:ss"; | ||
58 | + | ||
59 | + /** | ||
60 | + * 例如:2020年04月23日 10:00 | ||
61 | + */ | ||
62 | + public static final String DATE_CHINESE_TIME = "yyyy年MM月dd日 HH:mm"; | ||
63 | + | ||
64 | + /** | ||
65 | + * 例如:20181228100000215 | ||
66 | + */ | ||
67 | + public static final String MAX_DATE = "9999-12-31 59:59:59"; | ||
68 | + | ||
69 | + /** | ||
70 | + * 例如:20210822082134 | ||
71 | + */ | ||
72 | + public static final String DATE_TIME_HMS = "yyyyMMddHHmmssSSS"; | ||
73 | + | ||
74 | + public static final String YYMMDD = "yyyyMMdd"; | ||
75 | + | ||
76 | + public static final String YMMDD = "yyMMdd"; | ||
77 | + | ||
78 | + public static final String YYMMDDHHMMSS = "yyMMddHHmmss"; | ||
79 | + | ||
80 | + public static final String MONTH_TIME = "MM-dd HH:mm:ss"; | ||
81 | + | ||
82 | + /** | ||
83 | + * 例如:2018-12-28 10:00 | ||
84 | + */ | ||
85 | + public static final String DDMMYYYYHHMMSS = "dd/MM/yyyy HH:mm:ss"; | ||
86 | + | ||
87 | + public static LocalDateTime getCurrentTime() { | ||
88 | + LocalDateTime now = LocalDateTime.now(); | ||
89 | + return now; | ||
90 | + } | ||
91 | + | ||
92 | + public static Date getNextDay() { | ||
93 | + LocalDateTime now = LocalDateTime.now(); | ||
94 | + LocalDateTime tomorrow = now.minusDays(-1); | ||
95 | + return Date.from(tomorrow.atZone(ZoneId.systemDefault()).toInstant()); | ||
96 | + } | ||
97 | + | ||
98 | + public static Date getAppointDay(Integer count) { | ||
99 | + LocalDateTime now = LocalDateTime.now(); | ||
100 | + LocalDateTime tomorrow = now.minusDays(count); | ||
101 | + return Date.from(tomorrow.atZone(ZoneId.systemDefault()).toInstant()); | ||
102 | + } | ||
103 | + | ||
104 | + /** | ||
105 | + * 获取年 | ||
106 | + * | ||
107 | + * @return 年 | ||
108 | + */ | ||
109 | + public static int getYear() { | ||
110 | + LocalDateTime localDateTime = LocalDateTime.now(); | ||
111 | + return localDateTime.get(ChronoField.YEAR); | ||
112 | + } | ||
113 | + | ||
114 | + /** | ||
115 | + * 获取月份 | ||
116 | + * | ||
117 | + * @return 月份 | ||
118 | + */ | ||
119 | + public static int getMonth() { | ||
120 | + LocalDateTime localDateTime = LocalDateTime.now(); | ||
121 | + return localDateTime.get(ChronoField.MONTH_OF_YEAR); | ||
122 | + } | ||
123 | + | ||
124 | + /** | ||
125 | + * 获取某月的第几天 | ||
126 | + * | ||
127 | + * @return 几号 | ||
128 | + */ | ||
129 | + public static int getMonthOfDay() { | ||
130 | + LocalDateTime localDateTime = LocalDateTime.now(); | ||
131 | + return localDateTime.get(ChronoField.DAY_OF_MONTH); | ||
132 | + } | ||
133 | + | ||
134 | + /** | ||
135 | + * 格式化日期为字符串 | ||
136 | + * | ||
137 | + * @param date date | ||
138 | + * @param pattern 格式 | ||
139 | + * @return 日期字符串 | ||
140 | + */ | ||
141 | + public static String formatOrElseBlank(Date date, String pattern) { | ||
142 | + if (date == null || pattern == null) { | ||
143 | + return ""; | ||
144 | + } | ||
145 | + Instant instant = date.toInstant(); | ||
146 | + | ||
147 | + LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); | ||
148 | + | ||
149 | + return localDateTime.format(DateTimeFormatter.ofPattern(pattern)); | ||
150 | + } | ||
151 | + | ||
152 | + /** | ||
153 | + * 格式化日期为字符串 | ||
154 | + * | ||
155 | + * @param date date | ||
156 | + * @param pattern 格式 | ||
157 | + * @return 日期字符串 | ||
158 | + */ | ||
159 | + public static String format(Date date, String pattern) { | ||
160 | + | ||
161 | + Instant instant = date.toInstant(); | ||
162 | + | ||
163 | + LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); | ||
164 | + | ||
165 | + return localDateTime.format(DateTimeFormatter.ofPattern(pattern)); | ||
166 | + } | ||
167 | + | ||
168 | + public static String formatNow(String pattern) { | ||
169 | + LocalDateTime localDateTime = LocalDateTime.now(); | ||
170 | + | ||
171 | + return localDateTime.format(DateTimeFormatter.ofPattern(pattern)); | ||
172 | + } | ||
173 | + | ||
174 | + | ||
175 | + public static String format(LocalDateTime date, String pattern) { | ||
176 | + return date.format(DateTimeFormatter.ofPattern(pattern)); | ||
177 | + } | ||
178 | + | ||
179 | + public static String format(LocalDate date, String pattern) { | ||
180 | + return date.format(DateTimeFormatter.ofPattern(pattern)); | ||
181 | + } | ||
182 | + | ||
183 | + /** | ||
184 | + * 解析字符串日期为LocalDateTime | ||
185 | + * | ||
186 | + * @param dateStr 日期字符串 | ||
187 | + * @param pattern 格式 | ||
188 | + * @return Date | ||
189 | + */ | ||
190 | + public static LocalDateTime parse(String dateStr, String pattern) { | ||
191 | + return LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(pattern)); | ||
192 | + } | ||
193 | + | ||
194 | + /** | ||
195 | + * 解析字符串日期为LocalDateTime | ||
196 | + * | ||
197 | + * @param dateStr 日期字符串 | ||
198 | + * @param pattern 格式 | ||
199 | + * @return Date | ||
200 | + */ | ||
201 | + public static LocalDateTime parseStrByPattern(String dateStr, String pattern) { | ||
202 | + try { | ||
203 | + return parse(dateStr, pattern); | ||
204 | + } catch (Exception e) { | ||
205 | + return getCurrentTime(); | ||
206 | + } | ||
207 | + } | ||
208 | + | ||
209 | + /** | ||
210 | + * 解析字符串日期为LocalDate | ||
211 | + * | ||
212 | + * @param dateStr | ||
213 | + * @param pattern | ||
214 | + * @return | ||
215 | + */ | ||
216 | + public static LocalDate parseDate(String dateStr, String pattern) { | ||
217 | + return LocalDate.parse(dateStr, DateTimeFormatter.ofPattern(pattern)); | ||
218 | + } | ||
219 | + | ||
220 | + /** | ||
221 | + * @param dateTimeStr | ||
222 | + * @param prePattern | ||
223 | + * @param expectPattern | ||
224 | + * @return | ||
225 | + */ | ||
226 | + public static String format(String dateTimeStr, String prePattern, String expectPattern) { | ||
227 | + LocalDateTime localDateTime = parseDate(dateTimeStr, prePattern).atStartOfDay(); | ||
228 | + return localDateTime.format(DateTimeFormatter.ofPattern(expectPattern)); | ||
229 | + } | ||
230 | + | ||
231 | + /** | ||
232 | + * String -> Date | ||
233 | + * | ||
234 | + * @param date | ||
235 | + * @return | ||
236 | + */ | ||
237 | + public static Date parseStringToDate(String date, String pattern) { | ||
238 | + SimpleDateFormat sdf = new SimpleDateFormat(pattern); | ||
239 | + try { | ||
240 | + return sdf.parse(date); | ||
241 | + } catch (ParseException e) { | ||
242 | + return null; | ||
243 | + } | ||
244 | + } | ||
245 | + | ||
246 | + /** | ||
247 | + * 为Date增加分钟,减传负数 | ||
248 | + * | ||
249 | + * @param date 日期 | ||
250 | + * @param plusMinutes 要增加的分钟数 | ||
251 | + * @return 新的日期 | ||
252 | + */ | ||
253 | + public static Date addMinutes(Date date, Long plusMinutes) { | ||
254 | + LocalDateTime dateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); | ||
255 | + LocalDateTime newDateTime = dateTime.plusMinutes(plusMinutes); | ||
256 | + return Date.from(newDateTime.atZone(ZoneId.systemDefault()).toInstant()); | ||
257 | + } | ||
258 | + | ||
259 | + /** | ||
260 | + * 增加时间 | ||
261 | + * | ||
262 | + * @param date date | ||
263 | + * @param hour 要增加的小时数 | ||
264 | + * @return new date | ||
265 | + */ | ||
266 | + public static Date addHour(Date date, Long hour) { | ||
267 | + LocalDateTime dateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); | ||
268 | + LocalDateTime localDateTime = dateTime.plusHours(hour); | ||
269 | + return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); | ||
270 | + } | ||
271 | + | ||
272 | + /** | ||
273 | + * @return 返回当天的起始时间 | ||
274 | + */ | ||
275 | + public static Date getStartTime() { | ||
276 | + | ||
277 | + LocalDateTime now = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0); | ||
278 | + return localDateTime2Date(now); | ||
279 | + } | ||
280 | + | ||
281 | + | ||
282 | + /** | ||
283 | + * @return 返回当天的结束时间 | ||
284 | + */ | ||
285 | + public static Date getEndTime() { | ||
286 | + LocalDateTime now = LocalDateTime.now().withHour(23).withMinute(59).withSecond(59).withNano(999999999); | ||
287 | + return localDateTime2Date(now); | ||
288 | + } | ||
289 | + | ||
290 | + /** | ||
291 | + * @return 获取入参当天结束时间 | ||
292 | + */ | ||
293 | + public static LocalDateTime getEndTime(LocalDate localDate) { | ||
294 | + return localDate.atTime(23, 59, 59, 999999999); | ||
295 | + } | ||
296 | + | ||
297 | + /** | ||
298 | + * 减月份 | ||
299 | + * | ||
300 | + * @param monthsToSubtract 月份 | ||
301 | + * @return Date | ||
302 | + */ | ||
303 | + public static Date minusMonths(long monthsToSubtract) { | ||
304 | + LocalDate localDate = LocalDate.now().minusMonths(monthsToSubtract); | ||
305 | + | ||
306 | + return localDate2Date(localDate); | ||
307 | + } | ||
308 | + | ||
309 | + /** | ||
310 | + * LocalDate类型转为Date | ||
311 | + * | ||
312 | + * @param localDate LocalDate object | ||
313 | + * @return Date object | ||
314 | + */ | ||
315 | + public static Date localDate2Date(LocalDate localDate) { | ||
316 | + | ||
317 | + ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault()); | ||
318 | + | ||
319 | + return Date.from(zonedDateTime.toInstant()); | ||
320 | + } | ||
321 | + | ||
322 | + /** | ||
323 | + * Date类型转为LocalDateTime | ||
324 | + * | ||
325 | + * @param date Date object | ||
326 | + * @return localDate LocalDateTime | ||
327 | + */ | ||
328 | + public static LocalDateTime date2LocalDateTime(Date date) { | ||
329 | + | ||
330 | + Instant instant = date.toInstant(); | ||
331 | + ZoneId zoneId = ZoneId.systemDefault(); | ||
332 | + LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime(); | ||
333 | + return localDateTime; | ||
334 | + } | ||
335 | + | ||
336 | + | ||
337 | + /** | ||
338 | + * LocalDateTime类型转为Date | ||
339 | + * | ||
340 | + * @param localDateTime LocalDateTime object | ||
341 | + * @return Date object | ||
342 | + */ | ||
343 | + public static Date localDateTime2Date(LocalDateTime localDateTime) { | ||
344 | + return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); | ||
345 | + } | ||
346 | + | ||
347 | + /** | ||
348 | + * 查询当前年的第一天 | ||
349 | + * | ||
350 | + * @param pattern 格式,默认格式yyyyMMdd | ||
351 | + * @return 20190101 | ||
352 | + */ | ||
353 | + public static String getFirstDayOfCurrentYear(String pattern) { | ||
354 | + LocalDateTime localDateTime = LocalDateTime.now().withMonth(1).withDayOfMonth(1); | ||
355 | + | ||
356 | + if (StringUtils.isEmpty(pattern)) { | ||
357 | + pattern = "yyyyMMdd"; | ||
358 | + } | ||
359 | + | ||
360 | + return format(localDateTime2Date(localDateTime), pattern); | ||
361 | + } | ||
362 | + | ||
363 | + /** | ||
364 | + * 查询前一年最后一个月第一天 | ||
365 | + * | ||
366 | + * @param pattern 格式,默认格式yyyyMMdd | ||
367 | + * @return 20190101 | ||
368 | + */ | ||
369 | + public static String getLastMonthFirstDayOfPreviousYear(String pattern) { | ||
370 | + LocalDateTime localDateTime = LocalDateTime.now().minusYears(1L).withMonth(12).withDayOfMonth(1); | ||
371 | + | ||
372 | + if (StringUtils.isEmpty(pattern)) { | ||
373 | + pattern = "yyyyMMdd"; | ||
374 | + } | ||
375 | + | ||
376 | + return format(localDateTime2Date(localDateTime), pattern); | ||
377 | + } | ||
378 | + | ||
379 | + /** | ||
380 | + * 查询前一年最后一个月第一天 | ||
381 | + * | ||
382 | + * @param pattern 格式,默认格式yyyyMMdd | ||
383 | + * @return 20190101 | ||
384 | + */ | ||
385 | + public static String getLastMonthLastDayOfPreviousYear(String pattern) { | ||
386 | + LocalDateTime localDateTime = LocalDateTime.now().minusYears(1L).with(TemporalAdjusters.lastDayOfYear()); | ||
387 | + | ||
388 | + if (StringUtils.isEmpty(pattern)) { | ||
389 | + pattern = "yyyyMMdd"; | ||
390 | + } | ||
391 | + | ||
392 | + return format(localDateTime2Date(localDateTime), pattern); | ||
393 | + } | ||
394 | + | ||
395 | + /** | ||
396 | + * 获取当前日期 | ||
397 | + * | ||
398 | + * @param pattern 格式,默认格式yyyyMMdd | ||
399 | + * @return 20190101 | ||
400 | + */ | ||
401 | + public static String getCurrentDay(String pattern) { | ||
402 | + LocalDateTime localDateTime = LocalDateTime.now(); | ||
403 | + | ||
404 | + if (StringUtils.isEmpty(pattern)) { | ||
405 | + pattern = "yyyyMMdd"; | ||
406 | + } | ||
407 | + | ||
408 | + return format(localDateTime2Date(localDateTime), pattern); | ||
409 | + } | ||
410 | + | ||
411 | + public static String getTransitionTime(LocalDateTime time, String pattern) { | ||
412 | + if (StringUtils.isEmpty(pattern)) { | ||
413 | + pattern = "yyyyMMdd"; | ||
414 | + } | ||
415 | + return format(localDateTime2Date(time), pattern); | ||
416 | + } | ||
417 | + | ||
418 | + | ||
419 | + /** | ||
420 | + * 用于判断两个时间段有没有重合, 重合: true,未重合: false | ||
421 | + * | ||
422 | + * @param aStartTime | ||
423 | + * @param aEndTime | ||
424 | + * @param bStartTime | ||
425 | + * @param bEndTime | ||
426 | + * @return | ||
427 | + * @author A80068 | ||
428 | + */ | ||
429 | + public static boolean judgeTimeSlotCoincidence(LocalDateTime aStartTime, LocalDateTime aEndTime, LocalDateTime bStartTime, LocalDateTime bEndTime) { | ||
430 | + /** | ||
431 | + * 旧版 | ||
432 | + */ | ||
433 | + //boolean flag; | ||
434 | + //if(aStartTime.isAfter(bStartTime)){ | ||
435 | + // if (aStartTime.isBefore(bEndTime) || aStartTime.isEqual(bEndTime)){ | ||
436 | + // flag = true; | ||
437 | + // }else{ | ||
438 | + // flag = false; | ||
439 | + // } | ||
440 | + //}else if(aStartTime.isBefore(bStartTime)){ | ||
441 | + // if(aEndTime.isAfter(bStartTime) || aEndTime.isEqual(bStartTime)){ | ||
442 | + // flag = true; | ||
443 | + // }else{ | ||
444 | + // flag = false; | ||
445 | + // } | ||
446 | + //}else{ | ||
447 | + // flag = true; | ||
448 | + //} | ||
449 | + //return flag; | ||
450 | + /** | ||
451 | + * 优化版 | ||
452 | + */ | ||
453 | + boolean flag = false; | ||
454 | + if ((aStartTime.isBefore(bEndTime) || aStartTime.isEqual(bEndTime))) { | ||
455 | + if ((aEndTime.isAfter(bStartTime)) || aEndTime.isEqual(bStartTime)) { | ||
456 | + flag = true; | ||
457 | + } | ||
458 | + } | ||
459 | + return flag; | ||
460 | + } | ||
461 | + | ||
462 | + /** | ||
463 | + * @param aStartTimeStr | ||
464 | + * @param aEndTimeStr | ||
465 | + * @param bStartTimeStr | ||
466 | + * @param bEndTimeStr | ||
467 | + * @return | ||
468 | + * @author A80068 | ||
469 | + */ | ||
470 | + public static boolean judgeTimeSlotCoincidenceString(String aStartTimeStr, String aEndTimeStr, String bStartTimeStr, String bEndTimeStr) { | ||
471 | + | ||
472 | + LocalDateTime aStartTime = parse(aStartTimeStr, DATE_TIME); | ||
473 | + LocalDateTime aEndTime = parse(aEndTimeStr, DATE_TIME); | ||
474 | + LocalDateTime bStartTime = parse(bStartTimeStr, DATE_TIME); | ||
475 | + LocalDateTime bEndTime = parse(bEndTimeStr, DATE_TIME); | ||
476 | + | ||
477 | + return judgeTimeSlotCoincidence(aStartTime, aEndTime, bStartTime, bEndTime); | ||
478 | + } | ||
479 | + | ||
480 | + /** | ||
481 | + * @param strGMT | ||
482 | + * @return | ||
483 | + * @throws ParseException | ||
484 | + * @throws ParseException | ||
485 | + */ | ||
486 | + public static Date getCST(String strGMT) throws ParseException, ParseException { | ||
487 | + DateFormat df = new SimpleDateFormat("EEE, d-MMM-yyyy HH:mm:ss z", Locale.ENGLISH); | ||
488 | + return df.parse(strGMT); | ||
489 | + } | ||
490 | + | ||
491 | + /** | ||
492 | + * @param dateCST | ||
493 | + * @return | ||
494 | + */ | ||
495 | + public static Date getGMT(Date dateCST) throws ParseException { | ||
496 | + DateFormat df = new SimpleDateFormat("EEE, d-MMM-yyyy HH:mm:ss z", Locale.ENGLISH); | ||
497 | + df.setTimeZone(TimeZone.getTimeZone("GMT")); // modify Time Zone. | ||
498 | + return df.parse(df.format(dateCST)); | ||
499 | + } | ||
500 | + | ||
501 | + /** | ||
502 | + * LocalDateTime转化为cron表达式 | ||
503 | + * | ||
504 | + * @param dateTime | ||
505 | + * @return | ||
506 | + */ | ||
507 | + public static String dateToCron(LocalDateTime dateTime) { | ||
508 | + if (dateTime == null) { | ||
509 | + return ""; | ||
510 | + } | ||
511 | + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("ss mm HH dd MM ? yyyy"); | ||
512 | + return formatter.format(dateTime); | ||
513 | + } | ||
514 | + | ||
515 | + /** | ||
516 | + * cron表达式转为LocalDateTime | ||
517 | + * | ||
518 | + * @param cron | ||
519 | + * @return | ||
520 | + */ | ||
521 | + public static LocalDateTime cronToDate(String cron) { | ||
522 | + if (StringUtils.isNotBlank(cron)) { | ||
523 | + return null; | ||
524 | + } | ||
525 | + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("ss mm HH dd MM ? yyyy"); | ||
526 | + return LocalDateTime.parse(cron, formatter); | ||
527 | + } | ||
528 | + | ||
529 | + public static String timeToString(long time) { | ||
530 | + DateTimeFormatter ftf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); | ||
531 | + return ftf.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneId.systemDefault())); | ||
532 | + } | ||
533 | + | ||
534 | + public static String timeToString(String time) { | ||
535 | + try { | ||
536 | + return timeToString(Long.parseLong(time)); | ||
537 | + } catch (Exception e) { | ||
538 | + } | ||
539 | + return time; | ||
540 | + } | ||
541 | + | ||
542 | + /** | ||
543 | + * 比较时间大小 | ||
544 | + * | ||
545 | + * @param date1 | ||
546 | + * @param date2 | ||
547 | + * @return | ||
548 | + */ | ||
549 | + public static int compareDate(Date date1, Date date2) { | ||
550 | + if (date1 == null || date2 == null) { | ||
551 | + return -2; | ||
552 | + } | ||
553 | + if (date1.getTime() < date2.getTime()) { | ||
554 | + return -1; | ||
555 | + } else if (date1.getTime() > date2.getTime()) { | ||
556 | + return 1; | ||
557 | + } | ||
558 | + return 0; | ||
559 | + } | ||
560 | + | ||
561 | + /** | ||
562 | + * 判斷两个时间是否在同一分钟 | ||
563 | + */ | ||
564 | + public static boolean isMinuteIdentical(LocalDateTime date1, LocalDateTime date2) { | ||
565 | + return date1.getYear() == date2.getYear() && date1.getMonth() == date2.getMonth() && date1.getMinute() == date2.getMinute(); | ||
566 | + } | ||
567 | + | ||
568 | + /** | ||
569 | + * 时区 | ||
570 | + */ | ||
571 | + public static class Zone { | ||
572 | + public static final String GMT8 = "GMT+8"; | ||
573 | + } | ||
574 | + | ||
575 | + public static LocalDateTime parseProductDate(String dateStr) { | ||
576 | + if (StringUtils.isBlank(dateStr)) { | ||
577 | + return null; | ||
578 | + } | ||
579 | + if (dateStr.length() == 8) { | ||
580 | + dateStr = dateStr + " 00:00:00"; | ||
581 | + } | ||
582 | + if (dateStr.contains("/")) { | ||
583 | + dateStr = dateStr.replaceAll("/", "-"); | ||
584 | + } | ||
585 | + try { | ||
586 | + return LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); | ||
587 | + } catch (Exception e) { | ||
588 | + return null; | ||
589 | + } | ||
590 | + } | ||
591 | +} |
src/main/java/com/canrd/webmagic/common/utils/DateUtils.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/utils/DateUtils.java | ||
1 | +package com.canrd.webmagic.common.utils; | ||
2 | + | ||
3 | + | ||
4 | +import java.text.DateFormat; | ||
5 | +import java.text.ParseException; | ||
6 | +import java.text.SimpleDateFormat; | ||
7 | +import java.time.*; | ||
8 | +import java.time.format.DateTimeFormatter; | ||
9 | +import java.time.temporal.ChronoField; | ||
10 | +import java.time.temporal.TemporalAdjusters; | ||
11 | +import java.util.Date; | ||
12 | +import java.util.Locale; | ||
13 | +import java.util.TimeZone; | ||
14 | + | ||
15 | +/** | ||
16 | + * @Date: 2020/9/1 | ||
17 | + * 基于Java8的时间工具类 | ||
18 | + */ | ||
19 | +public class DateUtils { | ||
20 | + /** | ||
21 | + * 例如:2018-12-28 | ||
22 | + */ | ||
23 | + public static final String DATE = "yyyy-MM-dd"; | ||
24 | + /** | ||
25 | + * 例如:2018.12.28 | ||
26 | + */ | ||
27 | + public static final String DATE_WITH_POINT = "yyyy.MM.dd"; | ||
28 | + /** | ||
29 | + * 例如:2018-12-28 10:00:00 | ||
30 | + */ | ||
31 | + public static final String DATE_TIME = "yyyy-MM-dd HH:mm:ss"; | ||
32 | + /** | ||
33 | + * 例如:2018-12-28 10:00:00:215 | ||
34 | + */ | ||
35 | + public static final String DATE_TIME_MS = "yyyy-MM-dd HH:mm:ss.SSS"; | ||
36 | + /** | ||
37 | + * 例如:10:00:00 | ||
38 | + */ | ||
39 | + public static final String TIME = "HHmmss"; | ||
40 | + /** | ||
41 | + * 例如:10:00:00 | ||
42 | + */ | ||
43 | + public static final String TIME_HAVE_SECOND = "HH:mm:ss"; | ||
44 | + /** | ||
45 | + * 例如:10:00 | ||
46 | + */ | ||
47 | + public static final String TIME_WITHOUT_SECOND = "HH:mm"; | ||
48 | + | ||
49 | + /** | ||
50 | + * 例如:2018-12-28 10:00 | ||
51 | + */ | ||
52 | + public static final String DATE_TIME_WITHOUT_SECONDS = "yyyy-MM-dd HH:mm"; | ||
53 | + | ||
54 | + /** | ||
55 | + * 例如 2020/04/16 12:23:0 | ||
56 | + */ | ||
57 | + public static final String DATE_TIME_WITHOUT_SECONDS_OTHER = "yyyy/MM/dd HH:mm:ss"; | ||
58 | + | ||
59 | + /** | ||
60 | + * 例如:2020年04月23日 10:00 | ||
61 | + */ | ||
62 | + public static final String DATE_CHINESE_TIME = "yyyy年MM月dd日 HH:mm"; | ||
63 | + | ||
64 | + /** | ||
65 | + * 例如:20181228100000215 | ||
66 | + */ | ||
67 | + public static final String MAX_DATE = "9999-12-31 59:59:59"; | ||
68 | + | ||
69 | + /** | ||
70 | + * 例如:20210822082134 | ||
71 | + */ | ||
72 | + public static final String DATE_TIME_HMS = "yyyyMMddHHmmssSSS"; | ||
73 | + | ||
74 | + public static final String YYMMDD = "yyyyMMdd"; | ||
75 | + | ||
76 | + public static final String YMMDD = "yyMMdd"; | ||
77 | + | ||
78 | + public static final String YYMMDDHHMMSS = "yyMMddHHmmss"; | ||
79 | + | ||
80 | + public static final String MONTH_TIME = "MM-dd HH:mm:ss"; | ||
81 | + | ||
82 | + public static LocalDateTime getCurrentTime() { | ||
83 | + LocalDateTime now = LocalDateTime.now(); | ||
84 | + return now; | ||
85 | + } | ||
86 | + | ||
87 | + public static Date getNextDay() { | ||
88 | + LocalDateTime now = LocalDateTime.now(); | ||
89 | + LocalDateTime tomorrow = now.minusDays(-1); | ||
90 | + return Date.from(tomorrow.atZone(ZoneId.systemDefault()).toInstant()); | ||
91 | + } | ||
92 | + | ||
93 | + public static Date getAppointDay(Integer count) { | ||
94 | + LocalDateTime now = LocalDateTime.now(); | ||
95 | + LocalDateTime tomorrow = now.minusDays(count); | ||
96 | + return Date.from(tomorrow.atZone(ZoneId.systemDefault()).toInstant()); | ||
97 | + } | ||
98 | + | ||
99 | + /** | ||
100 | + * 获取年 | ||
101 | + * | ||
102 | + * @return 年 | ||
103 | + */ | ||
104 | + public static int getYear() { | ||
105 | + LocalDateTime localDateTime = LocalDateTime.now(); | ||
106 | + return localDateTime.get(ChronoField.YEAR); | ||
107 | + } | ||
108 | + | ||
109 | + /** | ||
110 | + * 获取月份 | ||
111 | + * | ||
112 | + * @return 月份 | ||
113 | + */ | ||
114 | + public static int getMonth() { | ||
115 | + LocalDateTime localDateTime = LocalDateTime.now(); | ||
116 | + return localDateTime.get(ChronoField.MONTH_OF_YEAR); | ||
117 | + } | ||
118 | + | ||
119 | + /** | ||
120 | + * 获取某月的第几天 | ||
121 | + * | ||
122 | + * @return 几号 | ||
123 | + */ | ||
124 | + public static int getMonthOfDay() { | ||
125 | + LocalDateTime localDateTime = LocalDateTime.now(); | ||
126 | + return localDateTime.get(ChronoField.DAY_OF_MONTH); | ||
127 | + } | ||
128 | + | ||
129 | + /** | ||
130 | + * 格式化日期为字符串 | ||
131 | + * | ||
132 | + * @param date date | ||
133 | + * @param pattern 格式 | ||
134 | + * @return 日期字符串 | ||
135 | + */ | ||
136 | + public static String formatOrElseBlank(Date date, String pattern) { | ||
137 | + if (date == null || pattern == null) { | ||
138 | + return ""; | ||
139 | + } | ||
140 | + Instant instant = date.toInstant(); | ||
141 | + | ||
142 | + LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); | ||
143 | + | ||
144 | + return localDateTime.format(DateTimeFormatter.ofPattern(pattern)); | ||
145 | + } | ||
146 | + | ||
147 | + /** | ||
148 | + * 格式化日期为字符串 | ||
149 | + * | ||
150 | + * @param date date | ||
151 | + * @param pattern 格式 | ||
152 | + * @return 日期字符串 | ||
153 | + */ | ||
154 | + public static String format(Date date, String pattern) { | ||
155 | + | ||
156 | + Instant instant = date.toInstant(); | ||
157 | + | ||
158 | + LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); | ||
159 | + | ||
160 | + return localDateTime.format(DateTimeFormatter.ofPattern(pattern)); | ||
161 | + } | ||
162 | + | ||
163 | + public static String formatNow(String pattern) { | ||
164 | + LocalDateTime localDateTime = LocalDateTime.now(); | ||
165 | + | ||
166 | + return localDateTime.format(DateTimeFormatter.ofPattern(pattern)); | ||
167 | + } | ||
168 | + | ||
169 | + | ||
170 | + public static String format(LocalDateTime date, String pattern) { | ||
171 | + return date.format(DateTimeFormatter.ofPattern(pattern)); | ||
172 | + } | ||
173 | + | ||
174 | + public static String format(LocalDate date, String pattern) { | ||
175 | + return date.format(DateTimeFormatter.ofPattern(pattern)); | ||
176 | + } | ||
177 | + | ||
178 | + /** | ||
179 | + * 解析字符串日期为LocalDateTime | ||
180 | + * | ||
181 | + * @param dateStr 日期字符串 | ||
182 | + * @param pattern 格式 | ||
183 | + * @return Date | ||
184 | + */ | ||
185 | + public static LocalDateTime parse(String dateStr, String pattern) { | ||
186 | + return LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(pattern)); | ||
187 | + } | ||
188 | + | ||
189 | + /** | ||
190 | + * 解析字符串日期为LocalDateTime | ||
191 | + * | ||
192 | + * @param dateStr 日期字符串 | ||
193 | + * @param pattern 格式 | ||
194 | + * @return Date | ||
195 | + */ | ||
196 | + public static LocalDateTime parseStrByPattern(String dateStr, String pattern) { | ||
197 | + try { | ||
198 | + return parse(dateStr, pattern); | ||
199 | + } catch (Exception e) { | ||
200 | + return getCurrentTime(); | ||
201 | + } | ||
202 | + } | ||
203 | + | ||
204 | + /** | ||
205 | + * 解析字符串日期为LocalDate | ||
206 | + * | ||
207 | + * @param dateStr | ||
208 | + * @param pattern | ||
209 | + * @return | ||
210 | + */ | ||
211 | + public static LocalDate parseDate(String dateStr, String pattern) { | ||
212 | + return LocalDate.parse(dateStr, DateTimeFormatter.ofPattern(pattern)); | ||
213 | + } | ||
214 | + | ||
215 | + /** | ||
216 | + * @param dateTimeStr | ||
217 | + * @param prePattern | ||
218 | + * @param expectPattern | ||
219 | + * @return | ||
220 | + */ | ||
221 | + public static String format(String dateTimeStr, String prePattern, String expectPattern) { | ||
222 | + LocalDateTime localDateTime = parseDate(dateTimeStr, prePattern).atStartOfDay(); | ||
223 | + return localDateTime.format(DateTimeFormatter.ofPattern(expectPattern)); | ||
224 | + } | ||
225 | + | ||
226 | + /** | ||
227 | + * String -> Date | ||
228 | + * | ||
229 | + * @param date | ||
230 | + * @return | ||
231 | + */ | ||
232 | + public static Date parseStringToDate(String date, String pattern) { | ||
233 | + SimpleDateFormat sdf = new SimpleDateFormat(pattern); | ||
234 | + try { | ||
235 | + return sdf.parse(date); | ||
236 | + } catch (ParseException e) { | ||
237 | + return null; | ||
238 | + } | ||
239 | + } | ||
240 | + | ||
241 | + /** | ||
242 | + * 为Date增加分钟,减传负数 | ||
243 | + * | ||
244 | + * @param date 日期 | ||
245 | + * @param plusMinutes 要增加的分钟数 | ||
246 | + * @return 新的日期 | ||
247 | + */ | ||
248 | + public static Date addMinutes(Date date, Long plusMinutes) { | ||
249 | + LocalDateTime dateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); | ||
250 | + LocalDateTime newDateTime = dateTime.plusMinutes(plusMinutes); | ||
251 | + return Date.from(newDateTime.atZone(ZoneId.systemDefault()).toInstant()); | ||
252 | + } | ||
253 | + | ||
254 | + /** | ||
255 | + * 增加时间 | ||
256 | + * | ||
257 | + * @param date date | ||
258 | + * @param hour 要增加的小时数 | ||
259 | + * @return new date | ||
260 | + */ | ||
261 | + public static Date addHour(Date date, Long hour) { | ||
262 | + LocalDateTime dateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); | ||
263 | + LocalDateTime localDateTime = dateTime.plusHours(hour); | ||
264 | + return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); | ||
265 | + } | ||
266 | + | ||
267 | + /** | ||
268 | + * @return 返回当天的起始时间 | ||
269 | + */ | ||
270 | + public static Date getStartTime() { | ||
271 | + | ||
272 | + LocalDateTime now = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0); | ||
273 | + return localDateTime2Date(now); | ||
274 | + } | ||
275 | + | ||
276 | + | ||
277 | + /** | ||
278 | + * @return 返回当天的结束时间 | ||
279 | + */ | ||
280 | + public static Date getEndTime() { | ||
281 | + LocalDateTime now = LocalDateTime.now().withHour(23).withMinute(59).withSecond(59).withNano(999999999); | ||
282 | + return localDateTime2Date(now); | ||
283 | + } | ||
284 | + | ||
285 | + /** | ||
286 | + * @return 获取入参当天结束时间 | ||
287 | + */ | ||
288 | + public static LocalDateTime getEndTime(LocalDate localDate) { | ||
289 | + return localDate.atTime(23, 59, 59, 999999999); | ||
290 | + } | ||
291 | + | ||
292 | + /** | ||
293 | + * 减月份 | ||
294 | + * | ||
295 | + * @param monthsToSubtract 月份 | ||
296 | + * @return Date | ||
297 | + */ | ||
298 | + public static Date minusMonths(long monthsToSubtract) { | ||
299 | + LocalDate localDate = LocalDate.now().minusMonths(monthsToSubtract); | ||
300 | + | ||
301 | + return localDate2Date(localDate); | ||
302 | + } | ||
303 | + | ||
304 | + /** | ||
305 | + * LocalDate类型转为Date | ||
306 | + * | ||
307 | + * @param localDate LocalDate object | ||
308 | + * @return Date object | ||
309 | + */ | ||
310 | + public static Date localDate2Date(LocalDate localDate) { | ||
311 | + | ||
312 | + ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault()); | ||
313 | + | ||
314 | + return Date.from(zonedDateTime.toInstant()); | ||
315 | + } | ||
316 | + | ||
317 | + /** | ||
318 | + * Date类型转为LocalDateTime | ||
319 | + * | ||
320 | + * @param date Date object | ||
321 | + * @return localDate LocalDateTime | ||
322 | + */ | ||
323 | + public static LocalDateTime date2LocalDateTime(Date date) { | ||
324 | + | ||
325 | + Instant instant = date.toInstant(); | ||
326 | + ZoneId zoneId = ZoneId.systemDefault(); | ||
327 | + LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime(); | ||
328 | + return localDateTime; | ||
329 | + } | ||
330 | + | ||
331 | + | ||
332 | + /** | ||
333 | + * LocalDateTime类型转为Date | ||
334 | + * | ||
335 | + * @param localDateTime LocalDateTime object | ||
336 | + * @return Date object | ||
337 | + */ | ||
338 | + public static Date localDateTime2Date(LocalDateTime localDateTime) { | ||
339 | + return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); | ||
340 | + } | ||
341 | + | ||
342 | + /** | ||
343 | + * 查询当前年的第一天 | ||
344 | + * | ||
345 | + * @param pattern 格式,默认格式yyyyMMdd | ||
346 | + * @return 20190101 | ||
347 | + */ | ||
348 | + public static String getFirstDayOfCurrentYear(String pattern) { | ||
349 | + LocalDateTime localDateTime = LocalDateTime.now().withMonth(1).withDayOfMonth(1); | ||
350 | + | ||
351 | + if (StringUtils.isEmpty(pattern)) { | ||
352 | + pattern = "yyyyMMdd"; | ||
353 | + } | ||
354 | + | ||
355 | + return format(localDateTime2Date(localDateTime), pattern); | ||
356 | + } | ||
357 | + | ||
358 | + /** | ||
359 | + * 查询前一年最后一个月第一天 | ||
360 | + * | ||
361 | + * @param pattern 格式,默认格式yyyyMMdd | ||
362 | + * @return 20190101 | ||
363 | + */ | ||
364 | + public static String getLastMonthFirstDayOfPreviousYear(String pattern) { | ||
365 | + LocalDateTime localDateTime = LocalDateTime.now().minusYears(1L).withMonth(12).withDayOfMonth(1); | ||
366 | + | ||
367 | + if (StringUtils.isEmpty(pattern)) { | ||
368 | + pattern = "yyyyMMdd"; | ||
369 | + } | ||
370 | + | ||
371 | + return format(localDateTime2Date(localDateTime), pattern); | ||
372 | + } | ||
373 | + | ||
374 | + /** | ||
375 | + * 查询前一年最后一个月第一天 | ||
376 | + * | ||
377 | + * @param pattern 格式,默认格式yyyyMMdd | ||
378 | + * @return 20190101 | ||
379 | + */ | ||
380 | + public static String getLastMonthLastDayOfPreviousYear(String pattern) { | ||
381 | + LocalDateTime localDateTime = LocalDateTime.now().minusYears(1L).with(TemporalAdjusters.lastDayOfYear()); | ||
382 | + | ||
383 | + if (StringUtils.isEmpty(pattern)) { | ||
384 | + pattern = "yyyyMMdd"; | ||
385 | + } | ||
386 | + | ||
387 | + return format(localDateTime2Date(localDateTime), pattern); | ||
388 | + } | ||
389 | + | ||
390 | + /** | ||
391 | + * 获取当前日期 | ||
392 | + * | ||
393 | + * @param pattern 格式,默认格式yyyyMMdd | ||
394 | + * @return 20190101 | ||
395 | + */ | ||
396 | + public static String getCurrentDay(String pattern) { | ||
397 | + LocalDateTime localDateTime = LocalDateTime.now(); | ||
398 | + | ||
399 | + if (StringUtils.isEmpty(pattern)) { | ||
400 | + pattern = "yyyyMMdd"; | ||
401 | + } | ||
402 | + | ||
403 | + return format(localDateTime2Date(localDateTime), pattern); | ||
404 | + } | ||
405 | + | ||
406 | + public static String getTransitionTime(LocalDateTime time, String pattern) { | ||
407 | + if (StringUtils.isEmpty(pattern)) { | ||
408 | + pattern = "yyyyMMdd"; | ||
409 | + } | ||
410 | + return format(localDateTime2Date(time), pattern); | ||
411 | + } | ||
412 | + | ||
413 | + | ||
414 | + /** | ||
415 | + * 用于判断两个时间段有没有重合, 重合: true,未重合: false | ||
416 | + * | ||
417 | + * @param aStartTime | ||
418 | + * @param aEndTime | ||
419 | + * @param bStartTime | ||
420 | + * @param bEndTime | ||
421 | + * @return | ||
422 | + * @author A80068 | ||
423 | + */ | ||
424 | + public static boolean judgeTimeSlotCoincidence(LocalDateTime aStartTime, LocalDateTime aEndTime, LocalDateTime bStartTime, LocalDateTime bEndTime) { | ||
425 | + /** | ||
426 | + * 旧版 | ||
427 | + */ | ||
428 | + //boolean flag; | ||
429 | + //if(aStartTime.isAfter(bStartTime)){ | ||
430 | + // if (aStartTime.isBefore(bEndTime) || aStartTime.isEqual(bEndTime)){ | ||
431 | + // flag = true; | ||
432 | + // }else{ | ||
433 | + // flag = false; | ||
434 | + // } | ||
435 | + //}else if(aStartTime.isBefore(bStartTime)){ | ||
436 | + // if(aEndTime.isAfter(bStartTime) || aEndTime.isEqual(bStartTime)){ | ||
437 | + // flag = true; | ||
438 | + // }else{ | ||
439 | + // flag = false; | ||
440 | + // } | ||
441 | + //}else{ | ||
442 | + // flag = true; | ||
443 | + //} | ||
444 | + //return flag; | ||
445 | + /** | ||
446 | + * 优化版 | ||
447 | + */ | ||
448 | + boolean flag = false; | ||
449 | + if ((aStartTime.isBefore(bEndTime) || aStartTime.isEqual(bEndTime))) { | ||
450 | + if ((aEndTime.isAfter(bStartTime)) || aEndTime.isEqual(bStartTime)) { | ||
451 | + flag = true; | ||
452 | + } | ||
453 | + } | ||
454 | + return flag; | ||
455 | + } | ||
456 | + | ||
457 | + /** | ||
458 | + * @param aStartTimeStr | ||
459 | + * @param aEndTimeStr | ||
460 | + * @param bStartTimeStr | ||
461 | + * @param bEndTimeStr | ||
462 | + * @return | ||
463 | + * @author A80068 | ||
464 | + */ | ||
465 | + public static boolean judgeTimeSlotCoincidenceString(String aStartTimeStr, String aEndTimeStr, String bStartTimeStr, String bEndTimeStr) { | ||
466 | + | ||
467 | + LocalDateTime aStartTime = parse(aStartTimeStr, DATE_TIME); | ||
468 | + LocalDateTime aEndTime = parse(aEndTimeStr, DATE_TIME); | ||
469 | + LocalDateTime bStartTime = parse(bStartTimeStr, DATE_TIME); | ||
470 | + LocalDateTime bEndTime = parse(bEndTimeStr, DATE_TIME); | ||
471 | + | ||
472 | + return judgeTimeSlotCoincidence(aStartTime, aEndTime, bStartTime, bEndTime); | ||
473 | + } | ||
474 | + | ||
475 | + /** | ||
476 | + * @param strGMT | ||
477 | + * @return | ||
478 | + * @throws ParseException | ||
479 | + * @throws ParseException | ||
480 | + */ | ||
481 | + public static Date getCST(String strGMT) throws ParseException, ParseException { | ||
482 | + DateFormat df = new SimpleDateFormat("EEE, d-MMM-yyyy HH:mm:ss z", Locale.ENGLISH); | ||
483 | + return df.parse(strGMT); | ||
484 | + } | ||
485 | + | ||
486 | + /** | ||
487 | + * @param dateCST | ||
488 | + * @return | ||
489 | + */ | ||
490 | + public static Date getGMT(Date dateCST) throws ParseException { | ||
491 | + DateFormat df = new SimpleDateFormat("EEE, d-MMM-yyyy HH:mm:ss z", Locale.ENGLISH); | ||
492 | + df.setTimeZone(TimeZone.getTimeZone("GMT")); // modify Time Zone. | ||
493 | + return df.parse(df.format(dateCST)); | ||
494 | + } | ||
495 | + | ||
496 | + /** | ||
497 | + * LocalDateTime转化为cron表达式 | ||
498 | + * | ||
499 | + * @param dateTime | ||
500 | + * @return | ||
501 | + */ | ||
502 | + public static String dateToCron(LocalDateTime dateTime) { | ||
503 | + if (dateTime == null) { | ||
504 | + return ""; | ||
505 | + } | ||
506 | + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("ss mm HH dd MM ? yyyy"); | ||
507 | + return formatter.format(dateTime); | ||
508 | + } | ||
509 | + | ||
510 | + /** | ||
511 | + * cron表达式转为LocalDateTime | ||
512 | + * | ||
513 | + * @param cron | ||
514 | + * @return | ||
515 | + */ | ||
516 | + public static LocalDateTime cronToDate(String cron) { | ||
517 | + if (StringUtils.isNotBlank(cron)) { | ||
518 | + return null; | ||
519 | + } | ||
520 | + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("ss mm HH dd MM ? yyyy"); | ||
521 | + return LocalDateTime.parse(cron, formatter); | ||
522 | + } | ||
523 | + | ||
524 | + public static String timeToString(long time) { | ||
525 | + DateTimeFormatter ftf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); | ||
526 | + return ftf.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneId.systemDefault())); | ||
527 | + } | ||
528 | + | ||
529 | + public static String timeToString(String time) { | ||
530 | + try { | ||
531 | + return timeToString(Long.parseLong(time)); | ||
532 | + } catch (Exception e) { | ||
533 | + } | ||
534 | + return time; | ||
535 | + } | ||
536 | + | ||
537 | + /** | ||
538 | + * 比较时间大小 | ||
539 | + * | ||
540 | + * @param date1 | ||
541 | + * @param date2 | ||
542 | + * @return | ||
543 | + */ | ||
544 | + public static int compareDate(Date date1, Date date2) { | ||
545 | + if (date1 == null || date2 == null) { | ||
546 | + return -2; | ||
547 | + } | ||
548 | + if (date1.getTime() < date2.getTime()) { | ||
549 | + return -1; | ||
550 | + } else if (date1.getTime() > date2.getTime()) { | ||
551 | + return 1; | ||
552 | + } | ||
553 | + return 0; | ||
554 | + } | ||
555 | + | ||
556 | + /** | ||
557 | + * 判斷两个时间是否在同一分钟 | ||
558 | + */ | ||
559 | + public static boolean isMinuteIdentical(LocalDateTime date1, LocalDateTime date2) { | ||
560 | + return date1.getYear() == date2.getYear() && date1.getMonth() == date2.getMonth() && date1.getMinute() == date2.getMinute(); | ||
561 | + } | ||
562 | + | ||
563 | + /** | ||
564 | + * 时区 | ||
565 | + */ | ||
566 | + public static class Zone { | ||
567 | + public static final String GMT8 = "GMT+8"; | ||
568 | + } | ||
569 | +} |
src/main/java/com/canrd/webmagic/common/utils/EncryptUtils.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/utils/EncryptUtils.java | ||
1 | +package com.canrd.webmagic.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 | +} |
src/main/java/com/canrd/webmagic/common/utils/FileUtil.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/utils/FileUtil.java | ||
1 | +package com.canrd.webmagic.common.utils; | ||
2 | + | ||
3 | +import cn.hutool.core.codec.Base64; | ||
4 | +import cn.hutool.core.io.IoUtil; | ||
5 | +import cn.hutool.core.util.IdUtil; | ||
6 | +import cn.hutool.poi.excel.BigExcelWriter; | ||
7 | +import cn.hutool.poi.excel.ExcelUtil; | ||
8 | +import org.apache.poi.util.IOUtils; | ||
9 | +import org.springframework.web.multipart.MultipartFile; | ||
10 | + | ||
11 | +import javax.activation.MimetypesFileTypeMap; | ||
12 | +import javax.servlet.ServletOutputStream; | ||
13 | +import javax.servlet.http.HttpServletRequest; | ||
14 | +import javax.servlet.http.HttpServletResponse; | ||
15 | +import java.io.*; | ||
16 | +import java.security.MessageDigest; | ||
17 | +import java.text.DecimalFormat; | ||
18 | +import java.text.SimpleDateFormat; | ||
19 | +import java.util.Date; | ||
20 | +import java.util.List; | ||
21 | +import java.util.Map; | ||
22 | + | ||
23 | +/** | ||
24 | + * File工具类,扩展 hutool 工具包 | ||
25 | + * | ||
26 | + * @date 2018-12-27 | ||
27 | + */ | ||
28 | +public class FileUtil extends cn.hutool.core.io.FileUtil { | ||
29 | + | ||
30 | + /** | ||
31 | + * 定义GB的计算常量 | ||
32 | + */ | ||
33 | + private static final int GB = 1024 * 1024 * 1024; | ||
34 | + /** | ||
35 | + * 定义MB的计算常量 | ||
36 | + */ | ||
37 | + private static final int MB = 1024 * 1024; | ||
38 | + /** | ||
39 | + * 定义KB的计算常量 | ||
40 | + */ | ||
41 | + private static final int KB = 1024; | ||
42 | + | ||
43 | + /** | ||
44 | + * 格式化小数 | ||
45 | + */ | ||
46 | + private static final DecimalFormat DF = new DecimalFormat("0.00"); | ||
47 | + | ||
48 | + /** | ||
49 | + * MultipartFile转File | ||
50 | + */ | ||
51 | + public static File toFile(MultipartFile multipartFile) { | ||
52 | + // 获取文件名 | ||
53 | + String fileName = multipartFile.getOriginalFilename(); | ||
54 | + // 获取文件后缀 | ||
55 | + String prefix = "." + getExtensionName(fileName); | ||
56 | + File file = null; | ||
57 | + try { | ||
58 | + // 用uuid作为文件名,防止生成的临时文件重复 | ||
59 | + file = File.createTempFile(IdUtil.simpleUUID(), prefix); | ||
60 | + // MultipartFile to File | ||
61 | + multipartFile.transferTo(file); | ||
62 | + } catch (IOException e) { | ||
63 | + e.printStackTrace(); | ||
64 | + } | ||
65 | + return file; | ||
66 | + } | ||
67 | + | ||
68 | + /** | ||
69 | + * 获取文件扩展名,不带 . | ||
70 | + */ | ||
71 | + public static String getExtensionName(String filename) { | ||
72 | + if ((filename != null) && (filename.length() > 0)) { | ||
73 | + int dot = filename.lastIndexOf('.'); | ||
74 | + if ((dot > -1) && (dot < (filename.length() - 1))) { | ||
75 | + return filename.substring(dot + 1); | ||
76 | + } | ||
77 | + } | ||
78 | + return filename; | ||
79 | + } | ||
80 | + | ||
81 | + /** | ||
82 | + * Java文件操作 获取不带扩展名的文件名 | ||
83 | + */ | ||
84 | + public static String getFileNameNoEx(String filename) { | ||
85 | + if ((filename != null) && (filename.length() > 0)) { | ||
86 | + int dot = filename.lastIndexOf('.'); | ||
87 | + if ((dot > -1) && (dot < (filename.length()))) { | ||
88 | + return filename.substring(0, dot); | ||
89 | + } | ||
90 | + } | ||
91 | + return filename; | ||
92 | + } | ||
93 | + | ||
94 | + /** | ||
95 | + * 文件大小转换 | ||
96 | + */ | ||
97 | + public static String getSize(long size) { | ||
98 | + String resultSize; | ||
99 | + if (size / GB >= 1) { | ||
100 | + //如果当前Byte的值大于等于1GB | ||
101 | + resultSize = DF.format(size / (float) GB) + "GB "; | ||
102 | + } else if (size / MB >= 1) { | ||
103 | + //如果当前Byte的值大于等于1MB | ||
104 | + resultSize = DF.format(size / (float) MB) + "MB "; | ||
105 | + } else if (size / KB >= 1) { | ||
106 | + //如果当前Byte的值大于等于1KB | ||
107 | + resultSize = DF.format(size / (float) KB) + "KB "; | ||
108 | + } else { | ||
109 | + resultSize = size + "B "; | ||
110 | + } | ||
111 | + return resultSize; | ||
112 | + } | ||
113 | + | ||
114 | + /** | ||
115 | + * inputStream 转 File | ||
116 | + */ | ||
117 | + public static File inputStreamToFile(InputStream ins, String name) throws Exception { | ||
118 | + File file = new File(System.getProperty("java.io.tmpdir") + File.separator + name); | ||
119 | + if (file.exists()) { | ||
120 | + return file; | ||
121 | + } | ||
122 | + OutputStream os = new FileOutputStream(file); | ||
123 | + int bytesRead; | ||
124 | + int len = 8192; | ||
125 | + byte[] buffer = new byte[len]; | ||
126 | + while ((bytesRead = ins.read(buffer, 0, len)) != -1) { | ||
127 | + os.write(buffer, 0, bytesRead); | ||
128 | + } | ||
129 | + os.close(); | ||
130 | + ins.close(); | ||
131 | + return file; | ||
132 | + } | ||
133 | + | ||
134 | + /** | ||
135 | + * 将文件转换为byte数组,作为图片数据导入 | ||
136 | + * | ||
137 | + * @param file | ||
138 | + * @return byte[] | ||
139 | + */ | ||
140 | + public static byte[] imageParseBytes(File file) { | ||
141 | + FileInputStream fileInputStream = null; | ||
142 | + try { | ||
143 | + fileInputStream = new FileInputStream(file); | ||
144 | + } catch (FileNotFoundException e) { | ||
145 | + e.printStackTrace(); | ||
146 | + } | ||
147 | + return imageParseBytes(fileInputStream); | ||
148 | + } | ||
149 | + | ||
150 | + /** | ||
151 | + * 将流转换为byte数组,作为图片数据导入 | ||
152 | + * | ||
153 | + * @param fis | ||
154 | + * @return byte[] | ||
155 | + */ | ||
156 | + public static byte[] imageParseBytes(InputStream fis) { | ||
157 | + byte[] buffer = null; | ||
158 | + ByteArrayOutputStream bos = null; | ||
159 | + try { | ||
160 | + bos = new ByteArrayOutputStream(1024); | ||
161 | + byte[] b = new byte[1024]; | ||
162 | + int n; | ||
163 | + while ((n = fis.read(b)) != -1) { | ||
164 | + bos.write(b, 0, n); | ||
165 | + } | ||
166 | + buffer = bos.toByteArray(); | ||
167 | + } catch (Exception e) { | ||
168 | + e.printStackTrace(); | ||
169 | + } finally { | ||
170 | + try { | ||
171 | + fis.close(); | ||
172 | + bos.close(); | ||
173 | + } catch (IOException e) { | ||
174 | + e.printStackTrace(); | ||
175 | + } | ||
176 | + } | ||
177 | + return buffer; | ||
178 | + } | ||
179 | + | ||
180 | + /** | ||
181 | + * 将文件名解析成文件的上传路径 | ||
182 | + */ | ||
183 | + public static File upload(MultipartFile file, String filePath) { | ||
184 | + Date date = new Date(); | ||
185 | + SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmssS"); | ||
186 | + String name = getFileNameNoEx(file.getOriginalFilename()); | ||
187 | + String suffix = getExtensionName(file.getOriginalFilename()); | ||
188 | + String nowStr = "-" + format.format(date); | ||
189 | + try { | ||
190 | + String fileName = name + nowStr + "." + suffix; | ||
191 | + String path = filePath + fileName; | ||
192 | + // getCanonicalFile 可解析正确各种路径 | ||
193 | + File dest = new File(path).getCanonicalFile(); | ||
194 | + // 检测是否存在目录 | ||
195 | + if (!dest.getParentFile().exists()) { | ||
196 | + dest.getParentFile().mkdirs(); | ||
197 | + } | ||
198 | + // 文件写入 | ||
199 | + file.transferTo(dest); | ||
200 | + return dest; | ||
201 | + } catch (Exception e) { | ||
202 | + e.printStackTrace(); | ||
203 | + } | ||
204 | + return null; | ||
205 | + } | ||
206 | + | ||
207 | + public static String fileToBase64(File file) throws Exception { | ||
208 | + FileInputStream inputFile = new FileInputStream(file); | ||
209 | + String base64; | ||
210 | + byte[] buffer = new byte[(int) file.length()]; | ||
211 | + inputFile.read(buffer); | ||
212 | + inputFile.close(); | ||
213 | + base64 = Base64.encode(buffer); | ||
214 | + return base64.replaceAll("[\\s*\t\n\r]", ""); | ||
215 | + } | ||
216 | + | ||
217 | + /** | ||
218 | + * 导出excel | ||
219 | + */ | ||
220 | + public static void downloadExcel(List<Map<String, Object>> list, HttpServletResponse response) throws IOException { | ||
221 | + String tempPath = System.getProperty("java.io.tmpdir") + IdUtil.fastSimpleUUID() + ".xlsx"; | ||
222 | + File file = new File(tempPath); | ||
223 | + BigExcelWriter writer = ExcelUtil.getBigWriter(file); | ||
224 | + // 一次性写出内容,使用默认样式,强制输出标题 | ||
225 | + writer.write(list, true); | ||
226 | + //response为HttpServletResponse对象 | ||
227 | + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"); | ||
228 | + //test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码 | ||
229 | + response.setHeader("Content-Disposition", "attachment;filename=file.xlsx"); | ||
230 | + ServletOutputStream out = response.getOutputStream(); | ||
231 | + // 终止后删除临时文件 | ||
232 | + file.deleteOnExit(); | ||
233 | + writer.flush(out, true); | ||
234 | + //此处记得关闭输出Servlet流 | ||
235 | + IoUtil.close(out); | ||
236 | + } | ||
237 | + | ||
238 | + public static String getFileType(String type) { | ||
239 | + String documents = "txt doc pdf ppt pps xlsx xls docx"; | ||
240 | + String music = "mp3 wav wma mpa ram ra aac aif m4a"; | ||
241 | + String video = "avi mpg mpe mpeg asf wmv mov qt rm mp4 flv m4v webm ogv ogg"; | ||
242 | + String image = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg"; | ||
243 | + if (image.contains(type)) { | ||
244 | + return "images"; | ||
245 | + } else if (documents.contains(type)) { | ||
246 | + return "docs"; | ||
247 | + } else if (music.contains(type)) { | ||
248 | + return "musics"; | ||
249 | + } else if (video.contains(type)) { | ||
250 | + return "videos"; | ||
251 | + } else { | ||
252 | + return "others"; | ||
253 | + } | ||
254 | + } | ||
255 | + | ||
256 | + public static String getFileTypeByMimeType(String type) { | ||
257 | + String mimeType = new MimetypesFileTypeMap().getContentType("." + type); | ||
258 | + return mimeType.split("/")[0]; | ||
259 | + } | ||
260 | + | ||
261 | + public static void checkSize(long maxSize, long size) { | ||
262 | + // 1M | ||
263 | + int len = 1024 * 1024; | ||
264 | + if (size > (maxSize * len)) { | ||
265 | + throw new RuntimeException("文件超出规定大小"); | ||
266 | + } | ||
267 | + } | ||
268 | + | ||
269 | + /** | ||
270 | + * 判断两个文件是否相同 | ||
271 | + */ | ||
272 | + public static boolean check(File file1, File file2) { | ||
273 | + String img1Md5 = getMd5(file1); | ||
274 | + String img2Md5 = getMd5(file2); | ||
275 | + return img1Md5.equals(img2Md5); | ||
276 | + } | ||
277 | + | ||
278 | + /** | ||
279 | + * 判断两个文件是否相同 | ||
280 | + */ | ||
281 | + public static boolean check(String file1Md5, String file2Md5) { | ||
282 | + return file1Md5.equals(file2Md5); | ||
283 | + } | ||
284 | + | ||
285 | + private static byte[] getByte(File file) { | ||
286 | + // 得到文件长度 | ||
287 | + byte[] b = new byte[(int) file.length()]; | ||
288 | + try { | ||
289 | + InputStream in = new FileInputStream(file); | ||
290 | + try { | ||
291 | + in.read(b); | ||
292 | + } catch (IOException e) { | ||
293 | + e.printStackTrace(); | ||
294 | + } | ||
295 | + } catch (FileNotFoundException e) { | ||
296 | + e.printStackTrace(); | ||
297 | + return null; | ||
298 | + } | ||
299 | + return b; | ||
300 | + } | ||
301 | + | ||
302 | + private static String getMd5(byte[] bytes) { | ||
303 | + // 16进制字符 | ||
304 | + char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; | ||
305 | + try { | ||
306 | + MessageDigest mdTemp = MessageDigest.getInstance("MD5"); | ||
307 | + mdTemp.update(bytes); | ||
308 | + byte[] md = mdTemp.digest(); | ||
309 | + int j = md.length; | ||
310 | + char[] str = new char[j * 2]; | ||
311 | + int k = 0; | ||
312 | + // 移位 输出字符串 | ||
313 | + for (byte byte0 : md) { | ||
314 | + str[k++] = hexDigits[byte0 >>> 4 & 0xf]; | ||
315 | + str[k++] = hexDigits[byte0 & 0xf]; | ||
316 | + } | ||
317 | + return new String(str); | ||
318 | + } catch (Exception e) { | ||
319 | + e.printStackTrace(); | ||
320 | + } | ||
321 | + return null; | ||
322 | + } | ||
323 | + | ||
324 | + /** | ||
325 | + * 下载文件 | ||
326 | + * | ||
327 | + * @param request / | ||
328 | + * @param response / | ||
329 | + * @param file / | ||
330 | + */ | ||
331 | + public static void downloadFile(HttpServletRequest request, HttpServletResponse response, File file, boolean deleteOnExit) { | ||
332 | + response.setCharacterEncoding(request.getCharacterEncoding()); | ||
333 | + response.setContentType("application/octet-stream"); | ||
334 | + FileInputStream fis = null; | ||
335 | + try { | ||
336 | + fis = new FileInputStream(file); | ||
337 | + response.setHeader("Content-Disposition", "attachment; filename=" + file.getName()); | ||
338 | + IOUtils.copy(fis, response.getOutputStream()); | ||
339 | + response.flushBuffer(); | ||
340 | + } catch (Exception e) { | ||
341 | + e.printStackTrace(); | ||
342 | + } finally { | ||
343 | + if (fis != null) { | ||
344 | + try { | ||
345 | + fis.close(); | ||
346 | + if (deleteOnExit) { | ||
347 | + file.deleteOnExit(); | ||
348 | + } | ||
349 | + } catch (IOException e) { | ||
350 | + e.printStackTrace(); | ||
351 | + } | ||
352 | + } | ||
353 | + } | ||
354 | + } | ||
355 | + | ||
356 | + public static String getMd5(File file) { | ||
357 | + return getMd5(getByte(file)); | ||
358 | + } | ||
359 | + | ||
360 | +} |
src/main/java/com/canrd/webmagic/common/utils/JsonUtil.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/utils/JsonUtil.java | ||
1 | +package com.canrd.webmagic.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 | +} |
src/main/java/com/canrd/webmagic/common/utils/LocalDateTimeUtil.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/utils/LocalDateTimeUtil.java | ||
1 | +package com.canrd.webmagic.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 | +} |
src/main/java/com/canrd/webmagic/common/utils/PageUtils.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/utils/PageUtils.java | ||
1 | +package com.canrd.webmagic.common.utils; | ||
2 | + | ||
3 | +import com.baomidou.mybatisplus.core.metadata.IPage; | ||
4 | +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | ||
5 | +import com.canrd.webmagic.domain.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.getCurrent(), pageVO.getSize()); | ||
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.getCurrent()), Math.toIntExact(pageVO.getSize())); | ||
102 | + } | ||
103 | + Map<String, Object> resultMap = new HashMap<>(DEFAULT_MAP_CAPACITY); | ||
104 | + resultMap.put(PAGE_INDEX, pageVO.getCurrent()); | ||
105 | + resultMap.put(PAGE_SIZE, pageVO.getSize()); | ||
106 | + resultMap.put(RECORDS, records); | ||
107 | + resultMap.put(TOTAL_PAGES, (pageVO.getTotal() + pageVO.getSize() - 1) / pageVO.getSize()); | ||
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 | +} |