Commit 54e88191b3cb0d250ee3a3cfce65523b6f29f28c
0 parents
feat: init项目
Showing
62 changed files
with
8814 additions
and
0 deletions
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 | 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 | 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 | 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 | 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 | +} | ... | ... |
src/main/java/com/canrd/webmagic/common/utils/RedisUtil.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/utils/RedisUtil.java | |
1 | +package com.canrd.webmagic.common.utils; | |
2 | + | |
3 | +import lombok.extern.slf4j.Slf4j; | |
4 | +import org.springframework.data.redis.connection.DataType; | |
5 | +import org.springframework.data.redis.core.*; | |
6 | +import org.springframework.stereotype.Repository; | |
7 | + | |
8 | +import javax.annotation.Resource; | |
9 | +import java.util.*; | |
10 | +import java.util.concurrent.TimeUnit; | |
11 | +import java.util.stream.Collectors; | |
12 | + | |
13 | +/** | |
14 | + * @Date: 2020/9/1 | |
15 | + */ | |
16 | +@Slf4j | |
17 | +@Repository("redisUtil") | |
18 | +public class RedisUtil { | |
19 | + | |
20 | + @Resource(name = "stringRedisTemplate") | |
21 | + private StringRedisTemplate redisTemplate; | |
22 | + | |
23 | + | |
24 | + /* -------------------key相关操作--------------------- */ | |
25 | + | |
26 | + /** | |
27 | + * 删除key | |
28 | + * | |
29 | + * @param key key key | |
30 | + */ | |
31 | + public void delete(String key) { | |
32 | + redisTemplate.delete(key); | |
33 | + } | |
34 | + | |
35 | + /** | |
36 | + * 批量删除key | |
37 | + * | |
38 | + * @param keys keys | |
39 | + */ | |
40 | + public void delete(Collection<String> keys) { | |
41 | + redisTemplate.delete(keys); | |
42 | + } | |
43 | + | |
44 | + /** | |
45 | + * 序列化key | |
46 | + * | |
47 | + * @param key key | |
48 | + * @return | |
49 | + */ | |
50 | + public byte[] dump(String key) { | |
51 | + return redisTemplate.dump(key); | |
52 | + } | |
53 | + | |
54 | + /** | |
55 | + * 是否存在key | |
56 | + * | |
57 | + * @param key key | |
58 | + * @return | |
59 | + */ | |
60 | + public Boolean hasKey(String key) { | |
61 | + return redisTemplate.hasKey(key); | |
62 | + } | |
63 | + | |
64 | + /** | |
65 | + * 设置过期时间 | |
66 | + * | |
67 | + * @param key key | |
68 | + * @param timeout | |
69 | + * @param unit | |
70 | + * @return | |
71 | + */ | |
72 | + public Boolean expire(String key, long timeout, TimeUnit unit) { | |
73 | + return redisTemplate.expire(key, timeout, unit); | |
74 | + } | |
75 | + | |
76 | + /** | |
77 | + * 设置过期时间 | |
78 | + * | |
79 | + * @param key key | |
80 | + * @param date | |
81 | + * @return | |
82 | + */ | |
83 | + public Boolean expireAt(String key, Date date) { | |
84 | + return redisTemplate.expireAt(key, date); | |
85 | + } | |
86 | + | |
87 | + /** | |
88 | + * 查找匹配的key | |
89 | + * | |
90 | + * @param pattern | |
91 | + * @return | |
92 | + */ | |
93 | + public Set<String> keys(String pattern) { | |
94 | + return redisTemplate.keys(pattern); | |
95 | + } | |
96 | + | |
97 | + /** | |
98 | + * 将当前数据库的 key 移动到给定的数据库 db 当中 | |
99 | + * | |
100 | + * @param key key | |
101 | + * @param dbIndex | |
102 | + * @return | |
103 | + */ | |
104 | + public Boolean move(String key, int dbIndex) { | |
105 | + return redisTemplate.move(key, dbIndex); | |
106 | + } | |
107 | + | |
108 | + /** | |
109 | + * 移除 key 的过期时间,key 将持久保持 | |
110 | + * | |
111 | + * @param key key | |
112 | + * @return | |
113 | + */ | |
114 | + public Boolean persist(String key) { | |
115 | + return redisTemplate.persist(key); | |
116 | + } | |
117 | + | |
118 | + /** | |
119 | + * 返回 key 的剩余的过期时间 | |
120 | + * | |
121 | + * @param key key | |
122 | + * @param unit | |
123 | + * @return | |
124 | + */ | |
125 | + public Long getExpire(String key, TimeUnit unit) { | |
126 | + return redisTemplate.getExpire(key, unit); | |
127 | + } | |
128 | + | |
129 | + /** | |
130 | + * 返回 key 的剩余的过期时间 | |
131 | + * | |
132 | + * @param key key | |
133 | + * @return | |
134 | + */ | |
135 | + public Long getExpire(String key) { | |
136 | + return redisTemplate.getExpire(key); | |
137 | + } | |
138 | + | |
139 | + /** | |
140 | + * 从当前数据库中随机返回一个 key | |
141 | + * | |
142 | + * @return | |
143 | + */ | |
144 | + public String randomKey() { | |
145 | + return redisTemplate.randomKey(); | |
146 | + } | |
147 | + | |
148 | + /** | |
149 | + * 修改 key 的名称 | |
150 | + * | |
151 | + * @param oldKey | |
152 | + * @param newKey | |
153 | + */ | |
154 | + public void rename(String oldKey, String newKey) { | |
155 | + redisTemplate.rename(oldKey, newKey); | |
156 | + } | |
157 | + | |
158 | + /** | |
159 | + * 仅当 newkey 不存在时,将 oldKey 改名为 newkey | |
160 | + * | |
161 | + * @param oldKey | |
162 | + * @param newKey | |
163 | + * @return | |
164 | + */ | |
165 | + public Boolean renameIfAbsent(String oldKey, String newKey) { | |
166 | + return redisTemplate.renameIfAbsent(oldKey, newKey); | |
167 | + } | |
168 | + | |
169 | + /** | |
170 | + * 返回 key 所储存的值的类型 | |
171 | + * | |
172 | + * @param key key | |
173 | + * @return | |
174 | + */ | |
175 | + public DataType type(String key) { | |
176 | + return redisTemplate.type(key); | |
177 | + } | |
178 | + | |
179 | + /** | |
180 | + * -------------------string相关操作--------------------- | |
181 | + *//* | |
182 | + | |
183 | + /** | |
184 | + * 设置指定 key 的值 | |
185 | + * @param key key | |
186 | + * @param value val | |
187 | + */ | |
188 | + public void set(String key, String value) { | |
189 | + redisTemplate.opsForValue().set(key, value); | |
190 | + } | |
191 | + | |
192 | + /** | |
193 | + * 设置缓存,指定有效时间 | |
194 | + * 时间单位为 秒 | |
195 | + * | |
196 | + * @param key | |
197 | + * @param value | |
198 | + * @param expireTime | |
199 | + */ | |
200 | + public void set(String key, String value, Long expireTime) { | |
201 | + redisTemplate.opsForValue().set(key, value, expireTime, TimeUnit.SECONDS); | |
202 | + } | |
203 | + | |
204 | + /** | |
205 | + * 设置缓存,指定有效时间 | |
206 | + * 时间单位 自定义 | |
207 | + * | |
208 | + * @param key | |
209 | + * @param value | |
210 | + * @param expireTime | |
211 | + * @param timeUnit | |
212 | + */ | |
213 | + public void set(String key, String value, Long expireTime, TimeUnit timeUnit) { | |
214 | + redisTemplate.opsForValue().set(key, value, expireTime, timeUnit); | |
215 | + } | |
216 | + | |
217 | + /** | |
218 | + * 获取指定 key 的值 | |
219 | + * | |
220 | + * @param key key | |
221 | + * @return | |
222 | + */ | |
223 | + public String get(String key) { | |
224 | + return redisTemplate.opsForValue().get(key); | |
225 | + } | |
226 | + | |
227 | + /** | |
228 | + * 返回 key 中字符串值的子字符 | |
229 | + * | |
230 | + * @param key key | |
231 | + * @param start | |
232 | + * @param end | |
233 | + * @return | |
234 | + */ | |
235 | + public String getRange(String key, long start, long end) { | |
236 | + return redisTemplate.opsForValue().get(key, start, end); | |
237 | + } | |
238 | + | |
239 | + /** | |
240 | + * 将给定 key 的值设为 value ,并返回 key 的旧值(old value) | |
241 | + * | |
242 | + * @param key key | |
243 | + * @param value val | |
244 | + * @return | |
245 | + */ | |
246 | + public String getAndSet(String key, String value) { | |
247 | + return redisTemplate.opsForValue().getAndSet(key, value); | |
248 | + } | |
249 | + | |
250 | + /** | |
251 | + * 对 key 所储存的字符串值,获取指定偏移量上的位(bit) | |
252 | + * | |
253 | + * @param key key | |
254 | + * @param offset | |
255 | + * @return | |
256 | + */ | |
257 | + public Boolean getBit(String key, long offset) { | |
258 | + return redisTemplate.opsForValue().getBit(key, offset); | |
259 | + } | |
260 | + | |
261 | + /** | |
262 | + * 批量获取 | |
263 | + * | |
264 | + * @param keys keys | |
265 | + * @return 多个key的value | |
266 | + */ | |
267 | + public List<String> multiGet(Collection<String> keys) { | |
268 | + return redisTemplate.opsForValue().multiGet(keys); | |
269 | + } | |
270 | + | |
271 | + public List<String> multiGetPip(Collection<String> keys) { | |
272 | + return redisTemplate.executePipelined((RedisCallback<String>) connection -> { | |
273 | + keys.forEach(a -> connection.get(a.getBytes())); | |
274 | + return null; | |
275 | + }).stream() | |
276 | + .filter(Objects::nonNull) | |
277 | + .map(Object::toString) | |
278 | + .collect(Collectors.toList()); | |
279 | + } | |
280 | + | |
281 | + /** | |
282 | + * 设置ASCII码, 字符串'a'的ASCII码是97, 转为二进制是'01100001', 此方法是将二进制第offset位值变为value | |
283 | + * | |
284 | + * @param key key | |
285 | + * @param offset 偏移 | |
286 | + * @param value val | |
287 | + */ | |
288 | + public Boolean setBit(String key, long offset, boolean value) { | |
289 | + return redisTemplate.opsForValue().setBit(key, offset, value); | |
290 | + } | |
291 | + | |
292 | + /** | |
293 | + * 将值 value 关联到 key ,并将 key 的过期时间设为 timeout | |
294 | + * | |
295 | + * @param key key | |
296 | + * @param value val | |
297 | + * @param timeout 过期时间 | |
298 | + * @param unit 时间单位, 天:TimeUnit.DAYS 小时:TimeUnit.HOURS 分钟:TimeUnit.MINUTES | |
299 | + * 秒:TimeUnit.SECONDS 毫秒:TimeUnit.MILLISECONDS | |
300 | + */ | |
301 | + public void setEx(String key, String value, long timeout, TimeUnit unit) { | |
302 | + redisTemplate.opsForValue().set(key, value, timeout, unit); | |
303 | + } | |
304 | + | |
305 | + /** | |
306 | + * 只有在 key 不存在时设置 key 的值 | |
307 | + * | |
308 | + * @param key key | |
309 | + * @param value val | |
310 | + * @return 之前已经存在返回false, 不存在返回true | |
311 | + */ | |
312 | + public Boolean setIfAbsent(String key, String value) { | |
313 | + return redisTemplate.opsForValue().setIfAbsent(key, value); | |
314 | + } | |
315 | + | |
316 | + | |
317 | + /** | |
318 | + * 用 value 参数覆写给定 key 所储存的字符串值,从偏移量 offset 开始 | |
319 | + * | |
320 | + * @param key key | |
321 | + * @param value val | |
322 | + * @param offset 从指定位置开始覆写 | |
323 | + */ | |
324 | + public void setRange(String key, String value, long offset) { | |
325 | + redisTemplate.opsForValue().set(key, value, offset); | |
326 | + } | |
327 | + | |
328 | + /** | |
329 | + * 获取字符串的长度 | |
330 | + * | |
331 | + * @param key key | |
332 | + */ | |
333 | + public Long size(String key) { | |
334 | + return redisTemplate.opsForValue().size(key); | |
335 | + } | |
336 | + | |
337 | + /** | |
338 | + * 批量添加 | |
339 | + */ | |
340 | + public void multiSet(Map<String, String> maps) { | |
341 | + redisTemplate.opsForValue().multiSet(maps); | |
342 | + } | |
343 | + | |
344 | + /** | |
345 | + * 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在 | |
346 | + * | |
347 | + * @return 之前已经存在返回false, 不存在返回true | |
348 | + */ | |
349 | + public Boolean multiSetIfAbsent(Map<String, String> maps) { | |
350 | + return redisTemplate.opsForValue().multiSetIfAbsent(maps); | |
351 | + } | |
352 | + | |
353 | + /** | |
354 | + * 增加(自增长), 负数则为自减 | |
355 | + * | |
356 | + * @param key key | |
357 | + * @param increment 步长 | |
358 | + */ | |
359 | + public Long incrBy(String key, long increment) { | |
360 | + return redisTemplate.opsForValue().increment(key, increment); | |
361 | + } | |
362 | + | |
363 | + /** | |
364 | + * @param key key | |
365 | + * @param increment 步长 | |
366 | + */ | |
367 | + public Double incrByFloat(String key, double increment) { | |
368 | + return redisTemplate.opsForValue().increment(key, increment); | |
369 | + } | |
370 | + | |
371 | + /** | |
372 | + * 增加(自增长), 负数则为自减 | |
373 | + * | |
374 | + * @param key key redisKey | |
375 | + * @param decrement 步长 | |
376 | + */ | |
377 | + public Long decreByLong(String key, long decrement) { | |
378 | + return redisTemplate.opsForValue().decrement(key, decrement); | |
379 | + } | |
380 | + | |
381 | + /** | |
382 | + * @param key key redisKey | |
383 | + */ | |
384 | + public Long decreBy(String key) { | |
385 | + return redisTemplate.opsForValue().decrement(key); | |
386 | + } | |
387 | + | |
388 | + /** | |
389 | + * 追加到末尾 | |
390 | + * | |
391 | + * @param key key | |
392 | + * @param value val | |
393 | + * @return | |
394 | + */ | |
395 | + public Integer append(String key, String value) { | |
396 | + return redisTemplate.opsForValue().append(key, value); | |
397 | + } | |
398 | + | |
399 | + /** -------------------hash相关操作------------------------- */ | |
400 | + | |
401 | + /** | |
402 | + * 获取存储在哈希表中指定字段的值 | |
403 | + * | |
404 | + * @param key key | |
405 | + * @param field | |
406 | + * @return | |
407 | + */ | |
408 | + public Object hGet(String key, String field) { | |
409 | + return redisTemplate.opsForHash().get(key, field); | |
410 | + } | |
411 | + | |
412 | + /** | |
413 | + * 获取所有给定字段的值 | |
414 | + * | |
415 | + * @param key key | |
416 | + * @return | |
417 | + */ | |
418 | + public Map<Object, Object> hGetAll(String key) { | |
419 | + return redisTemplate.opsForHash().entries(key); | |
420 | + } | |
421 | + | |
422 | + /** | |
423 | + * 获取所有给定字段的值 | |
424 | + * | |
425 | + * @param key key | |
426 | + * @param fields | |
427 | + * @return | |
428 | + */ | |
429 | + public List<Object> hMultiGet(String key, Collection<Object> fields) { | |
430 | + return redisTemplate.opsForHash().multiGet(key, fields); | |
431 | + } | |
432 | + | |
433 | + public void hPut(String key, String hashKey, String value) { | |
434 | + redisTemplate.opsForHash().put(key, hashKey, value); | |
435 | + } | |
436 | + | |
437 | + public void hPutAll(String key, Map<String, String> maps) { | |
438 | + redisTemplate.opsForHash().putAll(key, maps); | |
439 | + } | |
440 | + | |
441 | + /** | |
442 | + * 仅当hashKey不存在时才设置 | |
443 | + * | |
444 | + * @param key key | |
445 | + * @param hashKey | |
446 | + * @param value val | |
447 | + * @return | |
448 | + */ | |
449 | + public Boolean hPutIfAbsent(String key, String hashKey, String value) { | |
450 | + return redisTemplate.opsForHash().putIfAbsent(key, hashKey, value); | |
451 | + } | |
452 | + | |
453 | + /** | |
454 | + * 删除一个或多个哈希表字段 | |
455 | + * | |
456 | + * @param key key | |
457 | + * @param fields | |
458 | + * @return | |
459 | + */ | |
460 | + public Long hDelete(String key, Object... fields) { | |
461 | + return redisTemplate.opsForHash().delete(key, fields); | |
462 | + } | |
463 | + | |
464 | + /** | |
465 | + * 查看哈希表 key 中,指定的字段是否存在 | |
466 | + * | |
467 | + * @param key key | |
468 | + * @param field | |
469 | + * @return | |
470 | + */ | |
471 | + public Boolean hExists(String key, String field) { | |
472 | + return redisTemplate.opsForHash().hasKey(key, field); | |
473 | + } | |
474 | + | |
475 | + /** | |
476 | + * 为哈希表 key 中的指定字段的整数值加上增量 increment | |
477 | + * | |
478 | + * @param key key | |
479 | + * @param field | |
480 | + * @param increment | |
481 | + * @return | |
482 | + */ | |
483 | + public Long hIncrBy(String key, Object field, long increment) { | |
484 | + return redisTemplate.opsForHash().increment(key, field, increment); | |
485 | + } | |
486 | + | |
487 | + /** | |
488 | + * 为哈希表 key 中的指定字段的整数值加上增量 increment | |
489 | + * | |
490 | + * @param key key | |
491 | + * @param field | |
492 | + * @param delta | |
493 | + * @return | |
494 | + */ | |
495 | + public Double hIncrByFloat(String key, Object field, double delta) { | |
496 | + return redisTemplate.opsForHash().increment(key, field, delta); | |
497 | + } | |
498 | + | |
499 | + /** | |
500 | + * 获取所有哈希表中的字段 | |
501 | + * | |
502 | + * @param key key | |
503 | + * @return | |
504 | + */ | |
505 | + public Set<Object> hKeys(String key) { | |
506 | + return redisTemplate.opsForHash().keys(key); | |
507 | + } | |
508 | + | |
509 | + /** | |
510 | + * 获取哈希表中字段的数量 | |
511 | + * | |
512 | + * @param key key | |
513 | + * @return | |
514 | + */ | |
515 | + public Long hSize(String key) { | |
516 | + return redisTemplate.opsForHash().size(key); | |
517 | + } | |
518 | + | |
519 | + /** | |
520 | + * 获取哈希表中所有值 | |
521 | + * | |
522 | + * @param key key | |
523 | + * @return | |
524 | + */ | |
525 | + public List<Object> hValues(String key) { | |
526 | + return redisTemplate.opsForHash().values(key); | |
527 | + } | |
528 | + | |
529 | + /** | |
530 | + * 迭代哈希表中的键值对 | |
531 | + * | |
532 | + * @param key key | |
533 | + * @param options | |
534 | + * @return | |
535 | + */ | |
536 | + public Cursor<Map.Entry<Object, Object>> hScan(String key, ScanOptions options) { | |
537 | + return redisTemplate.opsForHash().scan(key, options); | |
538 | + } | |
539 | + | |
540 | + /** ------------------------list相关操作---------------------------- */ | |
541 | + | |
542 | + /** | |
543 | + * 通过索引获取列表中的元素 | |
544 | + * | |
545 | + * @param key key | |
546 | + * @param index | |
547 | + * @return | |
548 | + */ | |
549 | + public String lIndex(String key, long index) { | |
550 | + return redisTemplate.opsForList().index(key, index); | |
551 | + } | |
552 | + | |
553 | + /** | |
554 | + * 获取列表指定范围内的元素 | |
555 | + * | |
556 | + * @param key key | |
557 | + * @param start 开始位置, 0是开始位置 | |
558 | + * @param end 结束位置, -1返回所有 | |
559 | + * @return | |
560 | + */ | |
561 | + public List<String> lRange(String key, long start, long end) { | |
562 | + return redisTemplate.opsForList().range(key, start, end); | |
563 | + } | |
564 | + | |
565 | + /** | |
566 | + * 存储在list头部 | |
567 | + * | |
568 | + * @param key key | |
569 | + * @param value val | |
570 | + * @return | |
571 | + */ | |
572 | + public Long lLeftPush(String key, String value) { | |
573 | + return redisTemplate.opsForList().leftPush(key, value); | |
574 | + } | |
575 | + | |
576 | + /** | |
577 | + * @param key key | |
578 | + * @param value val | |
579 | + * @return | |
580 | + */ | |
581 | + public Long lLeftPushAll(String key, String... value) { | |
582 | + return redisTemplate.opsForList().leftPushAll(key, value); | |
583 | + } | |
584 | + | |
585 | + /** | |
586 | + * @param key key | |
587 | + * @param value val | |
588 | + * @return | |
589 | + */ | |
590 | + public Long lLeftPushAll(String key, Collection<String> value) { | |
591 | + return redisTemplate.opsForList().leftPushAll(key, value); | |
592 | + } | |
593 | + | |
594 | + /** | |
595 | + * 当list存在的时候才加入 | |
596 | + * | |
597 | + * @param key key | |
598 | + * @param value val | |
599 | + * @return | |
600 | + */ | |
601 | + public Long lLeftPushIfPresent(String key, String value) { | |
602 | + return redisTemplate.opsForList().leftPushIfPresent(key, value); | |
603 | + } | |
604 | + | |
605 | + /** | |
606 | + * 如果pivot存在,再pivot前面添加 | |
607 | + * | |
608 | + * @param key key | |
609 | + * @param pivot | |
610 | + * @param value val | |
611 | + * @return | |
612 | + */ | |
613 | + public Long lLeftPush(String key, String pivot, String value) { | |
614 | + return redisTemplate.opsForList().leftPush(key, pivot, value); | |
615 | + } | |
616 | + | |
617 | + /** | |
618 | + * @param key key | |
619 | + * @param value val | |
620 | + * @return | |
621 | + */ | |
622 | + public Long lRightPush(String key, String value) { | |
623 | + return redisTemplate.opsForList().rightPush(key, value); | |
624 | + } | |
625 | + | |
626 | + /** | |
627 | + * @param key key | |
628 | + * @param value val | |
629 | + * @return | |
630 | + */ | |
631 | + public Long lRightPushAll(String key, String... value) { | |
632 | + return redisTemplate.opsForList().rightPushAll(key, value); | |
633 | + } | |
634 | + | |
635 | + /** | |
636 | + * @param key key | |
637 | + * @param value val | |
638 | + * @return | |
639 | + */ | |
640 | + public Long lRightPushAll(String key, Collection<String> value) { | |
641 | + return redisTemplate.opsForList().rightPushAll(key, value); | |
642 | + } | |
643 | + | |
644 | + /** | |
645 | + * 为已存在的列表添加值 | |
646 | + * | |
647 | + * @param key key | |
648 | + * @param value val | |
649 | + * @return | |
650 | + */ | |
651 | + public Long lRightPushIfPresent(String key, String value) { | |
652 | + return redisTemplate.opsForList().rightPushIfPresent(key, value); | |
653 | + } | |
654 | + | |
655 | + /** | |
656 | + * 在pivot元素的右边添加值 | |
657 | + * | |
658 | + * @param key key | |
659 | + * @param pivot | |
660 | + * @param value val | |
661 | + * @return | |
662 | + */ | |
663 | + public Long lRightPush(String key, String pivot, String value) { | |
664 | + return redisTemplate.opsForList().rightPush(key, pivot, value); | |
665 | + } | |
666 | + | |
667 | + /** | |
668 | + * 通过索引设置列表元素的值 | |
669 | + * | |
670 | + * @param key key | |
671 | + * @param index 位置 | |
672 | + * @param value val | |
673 | + */ | |
674 | + public void lSet(String key, long index, String value) { | |
675 | + redisTemplate.opsForList().set(key, index, value); | |
676 | + } | |
677 | + | |
678 | + /** | |
679 | + * 移出并获取列表的第一个元素 | |
680 | + * | |
681 | + * @param key key | |
682 | + * @return 删除的元素 | |
683 | + */ | |
684 | + public String lLeftPop(String key) { | |
685 | + return redisTemplate.opsForList().leftPop(key); | |
686 | + } | |
687 | + | |
688 | + /** | |
689 | + * 移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止 | |
690 | + * | |
691 | + * @param key key | |
692 | + * @param timeout 等待时间 | |
693 | + * @param unit 时间单位 | |
694 | + * @return | |
695 | + */ | |
696 | + public String lbLeftPop(String key, long timeout, TimeUnit unit) { | |
697 | + return redisTemplate.opsForList().leftPop(key, timeout, unit); | |
698 | + } | |
699 | + | |
700 | + /** | |
701 | + * 移除并获取列表最后一个元素 | |
702 | + * | |
703 | + * @param key key | |
704 | + * @return 删除的元素 | |
705 | + */ | |
706 | + public String lRightPop(String key) { | |
707 | + return redisTemplate.opsForList().rightPop(key); | |
708 | + } | |
709 | + | |
710 | + /** | |
711 | + * 移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止 | |
712 | + * | |
713 | + * @param key key | |
714 | + * @param timeout 等待时间 | |
715 | + * @param unit 时间单位 | |
716 | + * @return | |
717 | + */ | |
718 | + public String lbRightPop(String key, long timeout, TimeUnit unit) { | |
719 | + return redisTemplate.opsForList().rightPop(key, timeout, unit); | |
720 | + } | |
721 | + | |
722 | + /** | |
723 | + * 移除列表的最后一个元素,并将该元素添加到另一个列表并返回 | |
724 | + * | |
725 | + * @param sourceKey | |
726 | + * @param destinationKey | |
727 | + * @return | |
728 | + */ | |
729 | + public String lRightPopAndLeftPush(String sourceKey, String destinationKey) { | |
730 | + return redisTemplate.opsForList().rightPopAndLeftPush(sourceKey, destinationKey); | |
731 | + } | |
732 | + | |
733 | + /** | |
734 | + * 从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止 | |
735 | + * | |
736 | + * @param sourceKey | |
737 | + * @param destinationKey | |
738 | + * @param timeout | |
739 | + * @param unit | |
740 | + * @return | |
741 | + */ | |
742 | + public String lbRightPopAndLeftPush(String sourceKey, String destinationKey, | |
743 | + long timeout, TimeUnit unit) { | |
744 | + return redisTemplate.opsForList().rightPopAndLeftPush(sourceKey, destinationKey, timeout, unit); | |
745 | + } | |
746 | + | |
747 | + /** | |
748 | + * 删除集合中值等于value得元素 | |
749 | + * | |
750 | + * @param key key | |
751 | + * @param index index=0, 删除所有值等于value的元素; index>0, 从头部开始删除第一个值等于value的元素; | |
752 | + * index<0, 从尾部开始删除第一个值等于value的元素; | |
753 | + * @param value val | |
754 | + * @return | |
755 | + */ | |
756 | + public Long lRemove(String key, long index, String value) { | |
757 | + return redisTemplate.opsForList().remove(key, index, value); | |
758 | + } | |
759 | + | |
760 | + /** | |
761 | + * 裁剪list | |
762 | + * | |
763 | + * @param key key | |
764 | + * @param start | |
765 | + * @param end | |
766 | + */ | |
767 | + public void lTrim(String key, long start, long end) { | |
768 | + redisTemplate.opsForList().trim(key, start, end); | |
769 | + } | |
770 | + | |
771 | + /** | |
772 | + * 获取列表长度 | |
773 | + * | |
774 | + * @param key key | |
775 | + * @return | |
776 | + */ | |
777 | + public Long lLen(String key) { | |
778 | + return redisTemplate.opsForList().size(key); | |
779 | + } | |
780 | + | |
781 | + /** --------------------set相关操作-------------------------- */ | |
782 | + | |
783 | + /** | |
784 | + * set添加元素 | |
785 | + * | |
786 | + * @param key key | |
787 | + * @param values vals | |
788 | + * @return | |
789 | + */ | |
790 | + public Long sAdd(String key, String... values) { | |
791 | + return redisTemplate.opsForSet().add(key, values); | |
792 | + } | |
793 | + | |
794 | + /** | |
795 | + * set移除元素 | |
796 | + * | |
797 | + * @param key key | |
798 | + * @param values vals | |
799 | + * @return | |
800 | + */ | |
801 | + public Long sRemove(String key, Object... values) { | |
802 | + return redisTemplate.opsForSet().remove(key, values); | |
803 | + } | |
804 | + | |
805 | + /** | |
806 | + * 移除并返回集合的一个随机元素 | |
807 | + * | |
808 | + * @param key key | |
809 | + * @return | |
810 | + */ | |
811 | + public String sPop(String key) { | |
812 | + return redisTemplate.opsForSet().pop(key); | |
813 | + } | |
814 | + | |
815 | + /** | |
816 | + * 移除并返回集合的多个随机元素 | |
817 | + * | |
818 | + * @param key key | |
819 | + * @return | |
820 | + */ | |
821 | + public List<String> sPop(String key, int count) { | |
822 | + return redisTemplate.opsForSet().pop(key, count); | |
823 | + } | |
824 | + | |
825 | + /** | |
826 | + * 将元素value从一个集合移到另一个集合 | |
827 | + * | |
828 | + * @param key key | |
829 | + * @param value val | |
830 | + * @param destKey | |
831 | + * @return | |
832 | + */ | |
833 | + public Boolean sMove(String key, String value, String destKey) { | |
834 | + return redisTemplate.opsForSet().move(key, value, destKey); | |
835 | + } | |
836 | + | |
837 | + /** | |
838 | + * 获取集合的大小 | |
839 | + * | |
840 | + * @param key key | |
841 | + * @return | |
842 | + */ | |
843 | + public Long sSize(String key) { | |
844 | + return redisTemplate.opsForSet().size(key); | |
845 | + } | |
846 | + | |
847 | + /** | |
848 | + * 判断集合是否包含value | |
849 | + * | |
850 | + * @param key key | |
851 | + * @param value val | |
852 | + * @return | |
853 | + */ | |
854 | + public Boolean sIsMember(String key, Object value) { | |
855 | + return redisTemplate.opsForSet().isMember(key, value); | |
856 | + } | |
857 | + | |
858 | + /** | |
859 | + * 获取两个集合的交集 | |
860 | + * | |
861 | + * @param key key | |
862 | + * @param otherKey | |
863 | + * @return | |
864 | + */ | |
865 | + public Set<String> sIntersect(String key, String otherKey) { | |
866 | + return redisTemplate.opsForSet().intersect(key, otherKey); | |
867 | + } | |
868 | + | |
869 | + /** | |
870 | + * 获取key集合与多个集合的交集 | |
871 | + * | |
872 | + * @param key key | |
873 | + * @param otherKeys | |
874 | + * @return | |
875 | + */ | |
876 | + public Set<String> sIntersect(String key, Collection<String> otherKeys) { | |
877 | + return redisTemplate.opsForSet().intersect(key, otherKeys); | |
878 | + } | |
879 | + | |
880 | + /** | |
881 | + * key集合与otherKey集合的交集存储到destKey集合中 | |
882 | + * | |
883 | + * @param key key | |
884 | + * @param otherKey | |
885 | + * @param destKey | |
886 | + * @return | |
887 | + */ | |
888 | + public Long sIntersectAndStore(String key, String otherKey, String destKey) { | |
889 | + return redisTemplate.opsForSet().intersectAndStore(key, otherKey, destKey); | |
890 | + } | |
891 | + | |
892 | + /** | |
893 | + * key集合与多个集合的交集存储到destKey集合中 | |
894 | + * | |
895 | + * @param key key | |
896 | + * @param otherKeys | |
897 | + * @param destKey | |
898 | + * @return | |
899 | + */ | |
900 | + public Long sIntersectAndStore(String key, Collection<String> otherKeys, String destKey) { | |
901 | + return redisTemplate.opsForSet().intersectAndStore(key, otherKeys, destKey); | |
902 | + } | |
903 | + | |
904 | + /** | |
905 | + * 获取两个集合的并集 | |
906 | + * | |
907 | + * @param key key | |
908 | + * @param otherKeys | |
909 | + * @return | |
910 | + */ | |
911 | + public Set<String> sUnion(String key, String otherKeys) { | |
912 | + return redisTemplate.opsForSet().union(key, otherKeys); | |
913 | + } | |
914 | + | |
915 | + /** | |
916 | + * 获取key集合与多个集合的并集 | |
917 | + * | |
918 | + * @param key key | |
919 | + * @param otherKeys | |
920 | + * @return | |
921 | + */ | |
922 | + public Set<String> sUnion(String key, Collection<String> otherKeys) { | |
923 | + return redisTemplate.opsForSet().union(key, otherKeys); | |
924 | + } | |
925 | + | |
926 | + /** | |
927 | + * key集合与otherKey集合的并集存储到destKey中 | |
928 | + * | |
929 | + * @param key key | |
930 | + * @param otherKey | |
931 | + * @param destKey | |
932 | + * @return | |
933 | + */ | |
934 | + public Long sUnionAndStore(String key, String otherKey, String destKey) { | |
935 | + return redisTemplate.opsForSet().unionAndStore(key, otherKey, destKey); | |
936 | + } | |
937 | + | |
938 | + /** | |
939 | + * key集合与多个集合的并集存储到destKey中 | |
940 | + * | |
941 | + * @param key key | |
942 | + * @param otherKeys | |
943 | + * @param destKey | |
944 | + * @return | |
945 | + */ | |
946 | + public Long sUnionAndStore(String key, Collection<String> otherKeys, String destKey) { | |
947 | + return redisTemplate.opsForSet().unionAndStore(key, otherKeys, destKey); | |
948 | + } | |
949 | + | |
950 | + /** | |
951 | + * 获取两个集合的差集 | |
952 | + * | |
953 | + * @param key key | |
954 | + * @param otherKey | |
955 | + * @return | |
956 | + */ | |
957 | + public Set<String> sDifference(String key, String otherKey) { | |
958 | + return redisTemplate.opsForSet().difference(key, otherKey); | |
959 | + } | |
960 | + | |
961 | + /** | |
962 | + * 获取key集合与多个集合的差集 | |
963 | + * | |
964 | + * @param key key | |
965 | + * @param otherKeys | |
966 | + * @return | |
967 | + */ | |
968 | + public Set<String> sDifference(String key, Collection<String> otherKeys) { | |
969 | + return redisTemplate.opsForSet().difference(key, otherKeys); | |
970 | + } | |
971 | + | |
972 | + /** | |
973 | + * key集合与otherKey集合的差集存储到destKey中 | |
974 | + * | |
975 | + * @param key key | |
976 | + * @param otherKey | |
977 | + * @param destKey | |
978 | + * @return | |
979 | + */ | |
980 | + public Long sDifference(String key, String otherKey, String destKey) { | |
981 | + return redisTemplate.opsForSet().differenceAndStore(key, otherKey, destKey); | |
982 | + } | |
983 | + | |
984 | + /** | |
985 | + * key集合与多个集合的差集存储到destKey中 | |
986 | + * | |
987 | + * @param key key | |
988 | + * @param otherKeys | |
989 | + * @param destKey | |
990 | + * @return | |
991 | + */ | |
992 | + public Long sDifference(String key, Collection<String> otherKeys, String destKey) { | |
993 | + return redisTemplate.opsForSet().differenceAndStore(key, otherKeys, destKey); | |
994 | + } | |
995 | + | |
996 | + /** | |
997 | + * 获取集合所有元素 | |
998 | + * | |
999 | + * @param key key | |
1000 | + * @param | |
1001 | + * @param | |
1002 | + * @return | |
1003 | + */ | |
1004 | + public Set<String> setMembers(String key) { | |
1005 | + return redisTemplate.opsForSet().members(key); | |
1006 | + } | |
1007 | + | |
1008 | + /** | |
1009 | + * 随机获取集合中的一个元素 | |
1010 | + * | |
1011 | + * @param key key | |
1012 | + * @return | |
1013 | + */ | |
1014 | + public String sRandomMember(String key) { | |
1015 | + return redisTemplate.opsForSet().randomMember(key); | |
1016 | + } | |
1017 | + | |
1018 | + /** | |
1019 | + * 随机获取集合中count个元素 | |
1020 | + * | |
1021 | + * @param key key | |
1022 | + * @param count | |
1023 | + * @return | |
1024 | + */ | |
1025 | + public List<String> sRandomMembers(String key, long count) { | |
1026 | + return redisTemplate.opsForSet().randomMembers(key, count); | |
1027 | + } | |
1028 | + | |
1029 | + /** | |
1030 | + * 随机获取集合中count个元素并且去除重复的 | |
1031 | + * | |
1032 | + * @param key key | |
1033 | + * @param count | |
1034 | + * @return | |
1035 | + */ | |
1036 | + public Set<String> sDistinctRandomMembers(String key, long count) { | |
1037 | + return redisTemplate.opsForSet().distinctRandomMembers(key, count); | |
1038 | + } | |
1039 | + | |
1040 | + /** | |
1041 | + * @param key key | |
1042 | + * @param options | |
1043 | + * @return | |
1044 | + */ | |
1045 | + public Cursor<String> sScan(String key, ScanOptions options) { | |
1046 | + return redisTemplate.opsForSet().scan(key, options); | |
1047 | + } | |
1048 | + | |
1049 | + /**------------------zSet相关操作--------------------------------*/ | |
1050 | + | |
1051 | + /** | |
1052 | + * 添加元素,有序集合是按照元素的score值由小到大排列 | |
1053 | + * | |
1054 | + * @param key key | |
1055 | + * @param value val | |
1056 | + * @param score | |
1057 | + * @return | |
1058 | + */ | |
1059 | + public Boolean zAdd(String key, String value, double score) { | |
1060 | + return redisTemplate.opsForZSet().add(key, value, score); | |
1061 | + } | |
1062 | + | |
1063 | + /** | |
1064 | + * @param key key | |
1065 | + * @param values val | |
1066 | + * @return | |
1067 | + */ | |
1068 | + public Long zAdd(String key, Set<ZSetOperations.TypedTuple<String>> values) { | |
1069 | + return redisTemplate.opsForZSet().add(key, values); | |
1070 | + } | |
1071 | + | |
1072 | + /** | |
1073 | + * @param key key | |
1074 | + * @param values val | |
1075 | + * @return 已删除元素的数量 | |
1076 | + */ | |
1077 | + public Long zRemove(String key, Object... values) { | |
1078 | + return redisTemplate.opsForZSet().remove(key, values); | |
1079 | + } | |
1080 | + | |
1081 | + /** | |
1082 | + * 增加元素的score值,并返回增加后的值 | |
1083 | + * | |
1084 | + * @param key key | |
1085 | + * @param value val | |
1086 | + * @param delta 分数值 | |
1087 | + * @return 增加后的值 | |
1088 | + */ | |
1089 | + public Double zIncrementScore(String key, String value, double delta) { | |
1090 | + return redisTemplate.opsForZSet().incrementScore(key, value, delta); | |
1091 | + } | |
1092 | + | |
1093 | + /** | |
1094 | + * 返回元素在集合的排名,有序集合是按照元素的score值由小到大排列 | |
1095 | + * | |
1096 | + * @param key key | |
1097 | + * @param value val | |
1098 | + * @return 0表示第一位 | |
1099 | + */ | |
1100 | + public Long zRank(String key, Object value) { | |
1101 | + return redisTemplate.opsForZSet().rank(key, value); | |
1102 | + | |
1103 | + } | |
1104 | + | |
1105 | + /** | |
1106 | + * 返回元素在集合的排名,按元素的score值由大到小排列 | |
1107 | + * | |
1108 | + * @param key key | |
1109 | + * @param value val | |
1110 | + */ | |
1111 | + public Long zReverseRank(String key, Object value) { | |
1112 | + return redisTemplate.opsForZSet().reverseRank(key, value); | |
1113 | + } | |
1114 | + | |
1115 | + /** | |
1116 | + * 获取集合的元素, 从小到大排序 | |
1117 | + * | |
1118 | + * @param key key | |
1119 | + * @param start 开始位置 | |
1120 | + * @param end 结束位置, -1查询所有 | |
1121 | + */ | |
1122 | + public Set<String> zRange(String key, long start, long end) { | |
1123 | + return redisTemplate.opsForZSet().range(key, start, end); | |
1124 | + } | |
1125 | + | |
1126 | + /** | |
1127 | + * 获取集合元素, 并且把score值也获取 | |
1128 | + * | |
1129 | + * @param key key | |
1130 | + * @param start | |
1131 | + * @param end | |
1132 | + * @return | |
1133 | + */ | |
1134 | + public Set<ZSetOperations.TypedTuple<String>> zRangeWithScores(String key, long start, long end) { | |
1135 | + return redisTemplate.opsForZSet().rangeWithScores(key, start, end); | |
1136 | + } | |
1137 | + | |
1138 | + /** | |
1139 | + * 根据Score值查询集合元素 | |
1140 | + * | |
1141 | + * @param key key | |
1142 | + * @param min 最小值 | |
1143 | + * @param max 最大值 | |
1144 | + * @return | |
1145 | + */ | |
1146 | + public Set<String> zRangeByScore(String key, double min, double max) { | |
1147 | + return redisTemplate.opsForZSet().rangeByScore(key, min, max); | |
1148 | + } | |
1149 | + | |
1150 | + /** | |
1151 | + * 根据Score值查询集合元素, 从小到大排序 | |
1152 | + * | |
1153 | + * @param key key | |
1154 | + * @param min 最小值 | |
1155 | + * @param max 最大值 | |
1156 | + * @return | |
1157 | + */ | |
1158 | + public Set<ZSetOperations.TypedTuple<String>> zRangeByScoreWithScores(String key, | |
1159 | + double min, double max) { | |
1160 | + return redisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max); | |
1161 | + } | |
1162 | + | |
1163 | + /** | |
1164 | + * @param key key | |
1165 | + * @param min | |
1166 | + * @param max | |
1167 | + * @param start | |
1168 | + * @param end | |
1169 | + * @return | |
1170 | + */ | |
1171 | + public Set<ZSetOperations.TypedTuple<String>> zRangeByScoreWithScores(String key, double min, double max, long start, long end) { | |
1172 | + return redisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max, start, end); | |
1173 | + } | |
1174 | + | |
1175 | + /** | |
1176 | + * 获取集合的元素, 从大到小排序 | |
1177 | + * | |
1178 | + * @param key key | |
1179 | + * @param start | |
1180 | + * @param end | |
1181 | + * @return | |
1182 | + */ | |
1183 | + public Set<String> zReverseRange(String key, long start, long end) { | |
1184 | + return redisTemplate.opsForZSet().reverseRange(key, start, end); | |
1185 | + } | |
1186 | + | |
1187 | + /** | |
1188 | + * 获取集合的元素, 从大到小排序, 并返回score值 | |
1189 | + * | |
1190 | + * @param key key | |
1191 | + * @param start | |
1192 | + * @param end | |
1193 | + * @return | |
1194 | + */ | |
1195 | + public Set<ZSetOperations.TypedTuple<String>> zReverseRangeWithScores(String key, | |
1196 | + long start, long end) { | |
1197 | + return redisTemplate.opsForZSet().reverseRangeWithScores(key, start, end); | |
1198 | + } | |
1199 | + | |
1200 | + /** | |
1201 | + * 根据Score值查询集合元素, 从大到小排序 | |
1202 | + * | |
1203 | + * @param key key | |
1204 | + * @param min | |
1205 | + * @param max | |
1206 | + * @return | |
1207 | + */ | |
1208 | + public Set<String> zReverseRangeByScore(String key, double min, double max) { | |
1209 | + return redisTemplate.opsForZSet().reverseRangeByScore(key, min, max); | |
1210 | + } | |
1211 | + | |
1212 | + /** | |
1213 | + * 根据Score值查询集合元素, 从大到小排序 | |
1214 | + * | |
1215 | + * @param key key | |
1216 | + * @param min | |
1217 | + * @param max | |
1218 | + * @return | |
1219 | + */ | |
1220 | + public Set<ZSetOperations.TypedTuple<String>> zReverseRangeByScoreWithScores(String key, double min, double max) { | |
1221 | + return redisTemplate.opsForZSet().reverseRangeByScoreWithScores(key, min, max); | |
1222 | + } | |
1223 | + | |
1224 | + /** | |
1225 | + * @param key key | |
1226 | + * @param min | |
1227 | + * @param max | |
1228 | + * @param start | |
1229 | + * @param end | |
1230 | + * @return | |
1231 | + */ | |
1232 | + public Set<String> zReverseRangeByScore(String key, double min, | |
1233 | + double max, long start, long end) { | |
1234 | + return redisTemplate.opsForZSet().reverseRangeByScore(key, min, max, start, end); | |
1235 | + } | |
1236 | + | |
1237 | + /** | |
1238 | + * 根据score值获取集合元素数量 | |
1239 | + * | |
1240 | + * @param key key | |
1241 | + * @param min | |
1242 | + * @param max | |
1243 | + * @return | |
1244 | + */ | |
1245 | + public Long zCount(String key, double min, double max) { | |
1246 | + return redisTemplate.opsForZSet().count(key, min, max); | |
1247 | + } | |
1248 | + | |
1249 | + /** | |
1250 | + * 获取集合大小 | |
1251 | + * | |
1252 | + * @param key key | |
1253 | + * @return | |
1254 | + */ | |
1255 | + public Long zSize(String key) { | |
1256 | + return redisTemplate.opsForZSet().size(key); | |
1257 | + } | |
1258 | + | |
1259 | + /** | |
1260 | + * 获取集合大小 | |
1261 | + * | |
1262 | + * @param key key | |
1263 | + * @return | |
1264 | + */ | |
1265 | + public Long zzCard(String key) { | |
1266 | + return redisTemplate.opsForZSet().zCard(key); | |
1267 | + } | |
1268 | + | |
1269 | + /** | |
1270 | + * 获取集合中value元素的score值 | |
1271 | + * | |
1272 | + * @param key key | |
1273 | + * @param value val | |
1274 | + * @return | |
1275 | + */ | |
1276 | + public Double zScore(String key, Object value) { | |
1277 | + return redisTemplate.opsForZSet().score(key, value); | |
1278 | + } | |
1279 | + | |
1280 | + /** | |
1281 | + * 移除指定索引位置的成员 | |
1282 | + * | |
1283 | + * @param key key | |
1284 | + * @param start | |
1285 | + * @param end | |
1286 | + * @return | |
1287 | + */ | |
1288 | + public Long zRemoveRange(String key, long start, long end) { | |
1289 | + return redisTemplate.opsForZSet().removeRange(key, start, end); | |
1290 | + } | |
1291 | + | |
1292 | + /** | |
1293 | + * 根据指定的score值的范围来移除成员 | |
1294 | + * | |
1295 | + * @param key key | |
1296 | + * @param min | |
1297 | + * @param max | |
1298 | + * @return | |
1299 | + */ | |
1300 | + public Long zRemoveRangeByScore(String key, double min, double max) { | |
1301 | + return redisTemplate.opsForZSet().removeRangeByScore(key, min, max); | |
1302 | + } | |
1303 | + | |
1304 | + /** | |
1305 | + * 获取key和otherKey的并集并存储在destKey中 | |
1306 | + * | |
1307 | + * @param key key | |
1308 | + * @param otherKey | |
1309 | + * @param destKey | |
1310 | + * @return | |
1311 | + */ | |
1312 | + public Long zUnionAndStore(String key, String otherKey, String destKey) { | |
1313 | + return redisTemplate.opsForZSet().unionAndStore(key, otherKey, destKey); | |
1314 | + } | |
1315 | + | |
1316 | + /** | |
1317 | + * @param key key | |
1318 | + * @param otherKeys | |
1319 | + * @param destKey | |
1320 | + * @return | |
1321 | + */ | |
1322 | + public Long zUnionAndStore(String key, Collection<String> otherKeys, String destKey) { | |
1323 | + return redisTemplate.opsForZSet().unionAndStore(key, otherKeys, destKey); | |
1324 | + } | |
1325 | + | |
1326 | + /** | |
1327 | + * 交集 | |
1328 | + * | |
1329 | + * @param key key | |
1330 | + * @param otherKey | |
1331 | + * @param destKey | |
1332 | + * @return | |
1333 | + */ | |
1334 | + public Long zIntersectAndStore(String key, String otherKey, String destKey) { | |
1335 | + return redisTemplate.opsForZSet().intersectAndStore(key, otherKey, destKey); | |
1336 | + } | |
1337 | + | |
1338 | + /** | |
1339 | + * 交集 | |
1340 | + * | |
1341 | + * @param key key | |
1342 | + * @param otherKeys | |
1343 | + * @param destKey | |
1344 | + * @return | |
1345 | + */ | |
1346 | + public Long zIntersectAndStore(String key, Collection<String> otherKeys, String destKey) { | |
1347 | + return redisTemplate.opsForZSet().intersectAndStore(key, otherKeys, destKey); | |
1348 | + } | |
1349 | + | |
1350 | + /** | |
1351 | + * @param key key | |
1352 | + * @param options | |
1353 | + * @return | |
1354 | + */ | |
1355 | + public Cursor<ZSetOperations.TypedTuple<String>> zScan(String key, ScanOptions options) { | |
1356 | + return redisTemplate.opsForZSet().scan(key, options); | |
1357 | + } | |
1358 | + | |
1359 | + /* -------------------锁相关操作--------------------- */ | |
1360 | + | |
1361 | + | |
1362 | + /** | |
1363 | + * 获得锁 | |
1364 | + */ | |
1365 | + public boolean getLock(String lockId, String value, long millisecond) { | |
1366 | + Boolean success = redisTemplate.opsForValue().setIfAbsent(lockId, value, millisecond, TimeUnit.MILLISECONDS); | |
1367 | + return success != null && success; | |
1368 | + } | |
1369 | + | |
1370 | + /** | |
1371 | + * 获得锁,并自旋,返回 | |
1372 | + */ | |
1373 | + public boolean getLock(String lockId, String value, long millisecond, long timeout) { | |
1374 | + long start = System.currentTimeMillis(); | |
1375 | + do { | |
1376 | + boolean success = getLock(lockId, value, millisecond); | |
1377 | + if (success) { | |
1378 | + return true; | |
1379 | + } | |
1380 | + try { | |
1381 | + Thread.sleep(100); | |
1382 | + } catch (InterruptedException e) { | |
1383 | + e.printStackTrace(); | |
1384 | + } | |
1385 | + } while (System.currentTimeMillis() - start < timeout); | |
1386 | + return false; | |
1387 | + } | |
1388 | + | |
1389 | + /** | |
1390 | + * 释放锁 | |
1391 | + */ | |
1392 | + public void releaseLock(String id, String lockValue) { | |
1393 | + if (StringUtils.isNotEmpty(lockValue) && lockValue.equals(this.get(id))) { | |
1394 | + log.debug("RedisUtil releaseLock, key: {}, value: {}", id, lockValue); | |
1395 | + redisTemplate.delete(id); | |
1396 | + } | |
1397 | + } | |
1398 | + | |
1399 | + /* -------------------HyperLogLog相关操作--------------------- */ | |
1400 | + | |
1401 | + /** | |
1402 | + * HyperLogLog 添加元素 | |
1403 | + * <p> key不存在则新增 | |
1404 | + * | |
1405 | + * @param key key | |
1406 | + * @param value value集合 | |
1407 | + * @return true表示加入成功 | |
1408 | + * @author A80080 | |
1409 | + * @createDate 2021/3/26 | |
1410 | + */ | |
1411 | + public boolean pfAdd(String key, String... value) { | |
1412 | + return redisTemplate.opsForHyperLogLog().add(key, value) == 1; | |
1413 | + } | |
1414 | + | |
1415 | + /** | |
1416 | + * HyperLogLog 统计key中元素个数 | |
1417 | + * <p> key 不存在则返回0 | |
1418 | + * | |
1419 | + * @param key key | |
1420 | + * @return key中数据大小(基数统计存在误差) | |
1421 | + * @author A80080 | |
1422 | + * @createDate 2021/3/26 | |
1423 | + */ | |
1424 | + public Long pfCount(String key) { | |
1425 | + return redisTemplate.opsForHyperLogLog().size(key); | |
1426 | + } | |
1427 | + | |
1428 | + /** | |
1429 | + * 合并HyperLogLog key,并统计新key元素个数 | |
1430 | + * <p>不删除参与合并的key; 新key不存在则新增, | |
1431 | + * | |
1432 | + * @param destination 合并后的key名称 | |
1433 | + * @param sourceKeys 参与合并的key | |
1434 | + * @return 合并后的key元素个数 | |
1435 | + * @author A80080 | |
1436 | + * @createDate 2021/3/26 | |
1437 | + */ | |
1438 | + public Long pfMerge(String destination, String... sourceKeys) { | |
1439 | + return redisTemplate.opsForHyperLogLog().union(destination, sourceKeys); | |
1440 | + } | |
1441 | + | |
1442 | + | |
1443 | +} | |
0 | 1444 | \ No newline at end of file | ... | ... |
src/main/java/com/canrd/webmagic/common/utils/RedisUtils.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/utils/RedisUtils.java | |
1 | +package com.canrd.webmagic.common.utils; | |
2 | + | |
3 | +import org.springframework.beans.factory.annotation.Value; | |
4 | +import org.springframework.data.redis.connection.RedisConnection; | |
5 | +import org.springframework.data.redis.connection.RedisConnectionFactory; | |
6 | +import org.springframework.data.redis.core.Cursor; | |
7 | +import org.springframework.data.redis.core.RedisConnectionUtils; | |
8 | +import org.springframework.data.redis.core.RedisTemplate; | |
9 | +import org.springframework.data.redis.core.ScanOptions; | |
10 | +import org.springframework.stereotype.Component; | |
11 | +import org.springframework.util.CollectionUtils; | |
12 | + | |
13 | +import java.util.*; | |
14 | +import java.util.concurrent.TimeUnit; | |
15 | + | |
16 | +/** | |
17 | + * @author / | |
18 | + */ | |
19 | +@Component | |
20 | +@SuppressWarnings({"unchecked", "all"}) | |
21 | +public class RedisUtils { | |
22 | + | |
23 | + private RedisTemplate<Object, Object> redisTemplate; | |
24 | + @Value("${jwt.online-key}") | |
25 | + private String onlineKey; | |
26 | + | |
27 | + public RedisUtils(RedisTemplate<Object, Object> redisTemplate) { | |
28 | + this.redisTemplate = redisTemplate; | |
29 | + } | |
30 | + | |
31 | + // =============================common============================ | |
32 | + | |
33 | + /** | |
34 | + * 指定缓存失效时间 | |
35 | + * | |
36 | + * @param key 键 | |
37 | + * @param time 时间(秒) | |
38 | + */ | |
39 | + public boolean expire(String key, long time) { | |
40 | + try { | |
41 | + if (time > 0) { | |
42 | + redisTemplate.expire(key, time, TimeUnit.SECONDS); | |
43 | + } | |
44 | + } catch (Exception e) { | |
45 | + e.printStackTrace(); | |
46 | + return false; | |
47 | + } | |
48 | + return true; | |
49 | + } | |
50 | + | |
51 | + /** | |
52 | + * 根据 key 获取过期时间 | |
53 | + * | |
54 | + * @param key 键 不能为null | |
55 | + * @return 时间(秒) 返回0代表为永久有效 | |
56 | + */ | |
57 | + public long getExpire(Object key) { | |
58 | + return redisTemplate.getExpire(key, TimeUnit.SECONDS); | |
59 | + } | |
60 | + | |
61 | + /** | |
62 | + * 查找匹配key | |
63 | + * | |
64 | + * @param pattern key | |
65 | + * @return / | |
66 | + */ | |
67 | + public List<String> scan(String pattern) { | |
68 | + ScanOptions options = ScanOptions.scanOptions().match(pattern).build(); | |
69 | + RedisConnectionFactory factory = redisTemplate.getConnectionFactory(); | |
70 | + RedisConnection rc = Objects.requireNonNull(factory).getConnection(); | |
71 | + Cursor<byte[]> cursor = rc.scan(options); | |
72 | + List<String> result = new ArrayList<>(); | |
73 | + while (cursor.hasNext()) { | |
74 | + result.add(new String(cursor.next())); | |
75 | + } | |
76 | + try { | |
77 | + RedisConnectionUtils.releaseConnection(rc, factory); | |
78 | + } catch (Exception e) { | |
79 | + e.printStackTrace(); | |
80 | + } | |
81 | + return result; | |
82 | + } | |
83 | + | |
84 | + /** | |
85 | + * 分页查询 key | |
86 | + * | |
87 | + * @param patternKey key | |
88 | + * @param page 页码 | |
89 | + * @param size 每页数目 | |
90 | + * @return / | |
91 | + */ | |
92 | + public List<String> findKeysForPage(String patternKey, int page, int size) { | |
93 | + ScanOptions options = ScanOptions.scanOptions().match(patternKey).build(); | |
94 | + RedisConnectionFactory factory = redisTemplate.getConnectionFactory(); | |
95 | + RedisConnection rc = Objects.requireNonNull(factory).getConnection(); | |
96 | + Cursor<byte[]> cursor = rc.scan(options); | |
97 | + List<String> result = new ArrayList<>(size); | |
98 | + int tmpIndex = 0; | |
99 | + int fromIndex = page * size; | |
100 | + int toIndex = page * size + size; | |
101 | + while (cursor.hasNext()) { | |
102 | + if (tmpIndex >= fromIndex && tmpIndex < toIndex) { | |
103 | + result.add(new String(cursor.next())); | |
104 | + tmpIndex++; | |
105 | + continue; | |
106 | + } | |
107 | + // 获取到满足条件的数据后,就可以退出了 | |
108 | + if (tmpIndex >= toIndex) { | |
109 | + break; | |
110 | + } | |
111 | + tmpIndex++; | |
112 | + cursor.next(); | |
113 | + } | |
114 | + try { | |
115 | + RedisConnectionUtils.releaseConnection(rc, factory); | |
116 | + } catch (Exception e) { | |
117 | + e.printStackTrace(); | |
118 | + } | |
119 | + return result; | |
120 | + } | |
121 | + | |
122 | + /** | |
123 | + * 判断key是否存在 | |
124 | + * | |
125 | + * @param key 键 | |
126 | + * @return true 存在 false不存在 | |
127 | + */ | |
128 | + public boolean hasKey(String key) { | |
129 | + try { | |
130 | + return redisTemplate.hasKey(key); | |
131 | + } catch (Exception e) { | |
132 | + e.printStackTrace(); | |
133 | + return false; | |
134 | + } | |
135 | + } | |
136 | + | |
137 | + /** | |
138 | + * 删除缓存 | |
139 | + * | |
140 | + * @param key 可以传一个值 或多个 | |
141 | + */ | |
142 | + public void del(String... key) { | |
143 | + if (key != null && key.length > 0) { | |
144 | + if (key.length == 1) { | |
145 | + redisTemplate.delete(key[0]); | |
146 | + } else { | |
147 | + redisTemplate.delete(CollectionUtils.arrayToList(key)); | |
148 | + } | |
149 | + } | |
150 | + } | |
151 | + | |
152 | + // ============================String============================= | |
153 | + | |
154 | + /** | |
155 | + * 普通缓存获取 | |
156 | + * | |
157 | + * @param key 键 | |
158 | + * @return 值 | |
159 | + */ | |
160 | + public Object get(String key) { | |
161 | + return key == null ? null : redisTemplate.opsForValue().get(key); | |
162 | + } | |
163 | + | |
164 | + /** | |
165 | + * 批量获取 | |
166 | + * | |
167 | + * @param keys | |
168 | + * @return | |
169 | + */ | |
170 | + public List<Object> multiGet(List<String> keys) { | |
171 | + Object obj = redisTemplate.opsForValue().multiGet(Collections.singleton(keys)); | |
172 | + return null; | |
173 | + } | |
174 | + | |
175 | + /** | |
176 | + * 普通缓存放入 | |
177 | + * | |
178 | + * @param key 键 | |
179 | + * @param value 值 | |
180 | + * @return true成功 false失败 | |
181 | + */ | |
182 | + public boolean set(String key, Object value) { | |
183 | + try { | |
184 | + redisTemplate.opsForValue().set(key, value); | |
185 | + return true; | |
186 | + } catch (Exception e) { | |
187 | + e.printStackTrace(); | |
188 | + return false; | |
189 | + } | |
190 | + } | |
191 | + | |
192 | + /** | |
193 | + * 普通缓存放入并设置时间 | |
194 | + * | |
195 | + * @param key 键 | |
196 | + * @param value 值 | |
197 | + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 | |
198 | + * @return true成功 false 失败 | |
199 | + */ | |
200 | + public boolean set(String key, Object value, long time) { | |
201 | + try { | |
202 | + if (time > 0) { | |
203 | + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); | |
204 | + } else { | |
205 | + set(key, value); | |
206 | + } | |
207 | + return true; | |
208 | + } catch (Exception e) { | |
209 | + e.printStackTrace(); | |
210 | + return false; | |
211 | + } | |
212 | + } | |
213 | + | |
214 | + /** | |
215 | + * 普通缓存放入并设置时间 | |
216 | + * | |
217 | + * @param key 键 | |
218 | + * @param value 值 | |
219 | + * @param time 时间 | |
220 | + * @param timeUnit 类型 | |
221 | + * @return true成功 false 失败 | |
222 | + */ | |
223 | + public boolean set(String key, Object value, long time, TimeUnit timeUnit) { | |
224 | + try { | |
225 | + if (time > 0) { | |
226 | + redisTemplate.opsForValue().set(key, value, time, timeUnit); | |
227 | + } else { | |
228 | + set(key, value); | |
229 | + } | |
230 | + return true; | |
231 | + } catch (Exception e) { | |
232 | + e.printStackTrace(); | |
233 | + return false; | |
234 | + } | |
235 | + } | |
236 | + | |
237 | + // ================================Map================================= | |
238 | + | |
239 | + /** | |
240 | + * HashGet | |
241 | + * | |
242 | + * @param key 键 不能为null | |
243 | + * @param item 项 不能为null | |
244 | + * @return 值 | |
245 | + */ | |
246 | + public Object hget(String key, String item) { | |
247 | + return redisTemplate.opsForHash().get(key, item); | |
248 | + } | |
249 | + | |
250 | + /** | |
251 | + * 获取hashKey对应的所有键值 | |
252 | + * | |
253 | + * @param key 键 | |
254 | + * @return 对应的多个键值 | |
255 | + */ | |
256 | + public Map<Object, Object> hmget(String key) { | |
257 | + return redisTemplate.opsForHash().entries(key); | |
258 | + | |
259 | + } | |
260 | + | |
261 | + /** | |
262 | + * HashSet | |
263 | + * | |
264 | + * @param key 键 | |
265 | + * @param map 对应多个键值 | |
266 | + * @return true 成功 false 失败 | |
267 | + */ | |
268 | + public boolean hmset(String key, Map<String, Object> map) { | |
269 | + try { | |
270 | + redisTemplate.opsForHash().putAll(key, map); | |
271 | + return true; | |
272 | + } catch (Exception e) { | |
273 | + e.printStackTrace(); | |
274 | + return false; | |
275 | + } | |
276 | + } | |
277 | + | |
278 | + /** | |
279 | + * HashSet 并设置时间 | |
280 | + * | |
281 | + * @param key 键 | |
282 | + * @param map 对应多个键值 | |
283 | + * @param time 时间(秒) | |
284 | + * @return true成功 false失败 | |
285 | + */ | |
286 | + public boolean hmset(String key, Map<String, Object> map, long time) { | |
287 | + try { | |
288 | + redisTemplate.opsForHash().putAll(key, map); | |
289 | + if (time > 0) { | |
290 | + expire(key, time); | |
291 | + } | |
292 | + return true; | |
293 | + } catch (Exception e) { | |
294 | + e.printStackTrace(); | |
295 | + return false; | |
296 | + } | |
297 | + } | |
298 | + | |
299 | + /** | |
300 | + * 向一张hash表中放入数据,如果不存在将创建 | |
301 | + * | |
302 | + * @param key 键 | |
303 | + * @param item 项 | |
304 | + * @param value 值 | |
305 | + * @return true 成功 false失败 | |
306 | + */ | |
307 | + public boolean hset(String key, String item, Object value) { | |
308 | + try { | |
309 | + redisTemplate.opsForHash().put(key, item, value); | |
310 | + return true; | |
311 | + } catch (Exception e) { | |
312 | + e.printStackTrace(); | |
313 | + return false; | |
314 | + } | |
315 | + } | |
316 | + | |
317 | + /** | |
318 | + * 向一张hash表中放入数据,如果不存在将创建 | |
319 | + * | |
320 | + * @param key 键 | |
321 | + * @param item 项 | |
322 | + * @param value 值 | |
323 | + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 | |
324 | + * @return true 成功 false失败 | |
325 | + */ | |
326 | + public boolean hset(String key, String item, Object value, long time) { | |
327 | + try { | |
328 | + redisTemplate.opsForHash().put(key, item, value); | |
329 | + if (time > 0) { | |
330 | + expire(key, time); | |
331 | + } | |
332 | + return true; | |
333 | + } catch (Exception e) { | |
334 | + e.printStackTrace(); | |
335 | + return false; | |
336 | + } | |
337 | + } | |
338 | + | |
339 | + /** | |
340 | + * 删除hash表中的值 | |
341 | + * | |
342 | + * @param key 键 不能为null | |
343 | + * @param item 项 可以使多个 不能为null | |
344 | + */ | |
345 | + public void hdel(String key, Object... item) { | |
346 | + redisTemplate.opsForHash().delete(key, item); | |
347 | + } | |
348 | + | |
349 | + /** | |
350 | + * 判断hash表中是否有该项的值 | |
351 | + * | |
352 | + * @param key 键 不能为null | |
353 | + * @param item 项 不能为null | |
354 | + * @return true 存在 false不存在 | |
355 | + */ | |
356 | + public boolean hHasKey(String key, String item) { | |
357 | + return redisTemplate.opsForHash().hasKey(key, item); | |
358 | + } | |
359 | + | |
360 | + /** | |
361 | + * hash递增 如果不存在,就会创建一个 并把新增后的值返回 | |
362 | + * | |
363 | + * @param key 键 | |
364 | + * @param item 项 | |
365 | + * @param by 要增加几(大于0) | |
366 | + * @return | |
367 | + */ | |
368 | + public double hincr(String key, String item, double by) { | |
369 | + return redisTemplate.opsForHash().increment(key, item, by); | |
370 | + } | |
371 | + | |
372 | + /** | |
373 | + * hash递减 | |
374 | + * | |
375 | + * @param key 键 | |
376 | + * @param item 项 | |
377 | + * @param by 要减少记(小于0) | |
378 | + * @return | |
379 | + */ | |
380 | + public double hdecr(String key, String item, double by) { | |
381 | + return redisTemplate.opsForHash().increment(key, item, -by); | |
382 | + } | |
383 | + | |
384 | + // ============================set============================= | |
385 | + | |
386 | + /** | |
387 | + * 根据key获取Set中的所有值 | |
388 | + * | |
389 | + * @param key 键 | |
390 | + * @return | |
391 | + */ | |
392 | + public Set<Object> sGet(String key) { | |
393 | + try { | |
394 | + return redisTemplate.opsForSet().members(key); | |
395 | + } catch (Exception e) { | |
396 | + e.printStackTrace(); | |
397 | + return null; | |
398 | + } | |
399 | + } | |
400 | + | |
401 | + /** | |
402 | + * 根据value从一个set中查询,是否存在 | |
403 | + * | |
404 | + * @param key 键 | |
405 | + * @param value 值 | |
406 | + * @return true 存在 false不存在 | |
407 | + */ | |
408 | + public boolean sHasKey(String key, Object value) { | |
409 | + try { | |
410 | + return redisTemplate.opsForSet().isMember(key, value); | |
411 | + } catch (Exception e) { | |
412 | + e.printStackTrace(); | |
413 | + return false; | |
414 | + } | |
415 | + } | |
416 | + | |
417 | + /** | |
418 | + * 将数据放入set缓存 | |
419 | + * | |
420 | + * @param key 键 | |
421 | + * @param values 值 可以是多个 | |
422 | + * @return 成功个数 | |
423 | + */ | |
424 | + public long sSet(String key, Object... values) { | |
425 | + try { | |
426 | + return redisTemplate.opsForSet().add(key, values); | |
427 | + } catch (Exception e) { | |
428 | + e.printStackTrace(); | |
429 | + return 0; | |
430 | + } | |
431 | + } | |
432 | + | |
433 | + /** | |
434 | + * 将set数据放入缓存 | |
435 | + * | |
436 | + * @param key 键 | |
437 | + * @param time 时间(秒) | |
438 | + * @param values 值 可以是多个 | |
439 | + * @return 成功个数 | |
440 | + */ | |
441 | + public long sSetAndTime(String key, long time, Object... values) { | |
442 | + try { | |
443 | + Long count = redisTemplate.opsForSet().add(key, values); | |
444 | + if (time > 0) { | |
445 | + expire(key, time); | |
446 | + } | |
447 | + return count; | |
448 | + } catch (Exception e) { | |
449 | + e.printStackTrace(); | |
450 | + return 0; | |
451 | + } | |
452 | + } | |
453 | + | |
454 | + /** | |
455 | + * 获取set缓存的长度 | |
456 | + * | |
457 | + * @param key 键 | |
458 | + * @return | |
459 | + */ | |
460 | + public long sGetSetSize(String key) { | |
461 | + try { | |
462 | + return redisTemplate.opsForSet().size(key); | |
463 | + } catch (Exception e) { | |
464 | + e.printStackTrace(); | |
465 | + return 0; | |
466 | + } | |
467 | + } | |
468 | + | |
469 | + /** | |
470 | + * 移除值为value的 | |
471 | + * | |
472 | + * @param key 键 | |
473 | + * @param values 值 可以是多个 | |
474 | + * @return 移除的个数 | |
475 | + */ | |
476 | + public long setRemove(String key, Object... values) { | |
477 | + try { | |
478 | + Long count = redisTemplate.opsForSet().remove(key, values); | |
479 | + return count; | |
480 | + } catch (Exception e) { | |
481 | + e.printStackTrace(); | |
482 | + return 0; | |
483 | + } | |
484 | + } | |
485 | + | |
486 | + // ===============================list================================= | |
487 | + | |
488 | + /** | |
489 | + * 获取list缓存的内容 | |
490 | + * | |
491 | + * @param key 键 | |
492 | + * @param start 开始 | |
493 | + * @param end 结束 0 到 -1代表所有值 | |
494 | + * @return | |
495 | + */ | |
496 | + public List<Object> lGet(String key, long start, long end) { | |
497 | + try { | |
498 | + return redisTemplate.opsForList().range(key, start, end); | |
499 | + } catch (Exception e) { | |
500 | + e.printStackTrace(); | |
501 | + return null; | |
502 | + } | |
503 | + } | |
504 | + | |
505 | + /** | |
506 | + * 获取list缓存的长度 | |
507 | + * | |
508 | + * @param key 键 | |
509 | + * @return | |
510 | + */ | |
511 | + public long lGetListSize(String key) { | |
512 | + try { | |
513 | + return redisTemplate.opsForList().size(key); | |
514 | + } catch (Exception e) { | |
515 | + e.printStackTrace(); | |
516 | + return 0; | |
517 | + } | |
518 | + } | |
519 | + | |
520 | + /** | |
521 | + * 通过索引 获取list中的值 | |
522 | + * | |
523 | + * @param key 键 | |
524 | + * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 | |
525 | + * @return | |
526 | + */ | |
527 | + public Object lGetIndex(String key, long index) { | |
528 | + try { | |
529 | + return redisTemplate.opsForList().index(key, index); | |
530 | + } catch (Exception e) { | |
531 | + e.printStackTrace(); | |
532 | + return null; | |
533 | + } | |
534 | + } | |
535 | + | |
536 | + /** | |
537 | + * 将list放入缓存 | |
538 | + * | |
539 | + * @param key 键 | |
540 | + * @param value 值 | |
541 | + * @return | |
542 | + */ | |
543 | + public boolean lSet(String key, Object value) { | |
544 | + try { | |
545 | + redisTemplate.opsForList().rightPush(key, value); | |
546 | + return true; | |
547 | + } catch (Exception e) { | |
548 | + e.printStackTrace(); | |
549 | + return false; | |
550 | + } | |
551 | + } | |
552 | + | |
553 | + /** | |
554 | + * 将list放入缓存 | |
555 | + * | |
556 | + * @param key 键 | |
557 | + * @param value 值 | |
558 | + * @param time 时间(秒) | |
559 | + * @return | |
560 | + */ | |
561 | + public boolean lSet(String key, Object value, long time) { | |
562 | + try { | |
563 | + redisTemplate.opsForList().rightPush(key, value); | |
564 | + if (time > 0) { | |
565 | + expire(key, time); | |
566 | + } | |
567 | + return true; | |
568 | + } catch (Exception e) { | |
569 | + e.printStackTrace(); | |
570 | + return false; | |
571 | + } | |
572 | + } | |
573 | + | |
574 | + /** | |
575 | + * 将list放入缓存 | |
576 | + * | |
577 | + * @param key 键 | |
578 | + * @param value 值 | |
579 | + * @return | |
580 | + */ | |
581 | + public boolean lSet(String key, List<Object> value) { | |
582 | + try { | |
583 | + redisTemplate.opsForList().rightPushAll(key, value); | |
584 | + return true; | |
585 | + } catch (Exception e) { | |
586 | + e.printStackTrace(); | |
587 | + return false; | |
588 | + } | |
589 | + } | |
590 | + | |
591 | + /** | |
592 | + * 将list放入缓存 | |
593 | + * | |
594 | + * @param key 键 | |
595 | + * @param value 值 | |
596 | + * @param time 时间(秒) | |
597 | + * @return | |
598 | + */ | |
599 | + public boolean lSet(String key, List<Object> value, long time) { | |
600 | + try { | |
601 | + redisTemplate.opsForList().rightPushAll(key, value); | |
602 | + if (time > 0) { | |
603 | + expire(key, time); | |
604 | + } | |
605 | + return true; | |
606 | + } catch (Exception e) { | |
607 | + e.printStackTrace(); | |
608 | + return false; | |
609 | + } | |
610 | + } | |
611 | + | |
612 | + /** | |
613 | + * 根据索引修改list中的某条数据 | |
614 | + * | |
615 | + * @param key 键 | |
616 | + * @param index 索引 | |
617 | + * @param value 值 | |
618 | + * @return / | |
619 | + */ | |
620 | + public boolean lUpdateIndex(String key, long index, Object value) { | |
621 | + try { | |
622 | + redisTemplate.opsForList().set(key, index, value); | |
623 | + return true; | |
624 | + } catch (Exception e) { | |
625 | + e.printStackTrace(); | |
626 | + return false; | |
627 | + } | |
628 | + } | |
629 | + | |
630 | + /** | |
631 | + * 移除N个值为value | |
632 | + * | |
633 | + * @param key 键 | |
634 | + * @param count 移除多少个 | |
635 | + * @param value 值 | |
636 | + * @return 移除的个数 | |
637 | + */ | |
638 | + public long lRemove(String key, long count, Object value) { | |
639 | + try { | |
640 | + return redisTemplate.opsForList().remove(key, count, value); | |
641 | + } catch (Exception e) { | |
642 | + e.printStackTrace(); | |
643 | + return 0; | |
644 | + } | |
645 | + } | |
646 | +} | ... | ... |
src/main/java/com/canrd/webmagic/common/utils/RequestContextUtil.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/utils/RequestContextUtil.java | |
1 | +package com.canrd.webmagic.common.utils; | |
2 | + | |
3 | +import org.springframework.web.context.ContextLoader; | |
4 | +import org.springframework.web.context.request.RequestContextHolder; | |
5 | +import org.springframework.web.context.request.ServletRequestAttributes; | |
6 | + | |
7 | +import javax.servlet.ServletContext; | |
8 | +import javax.servlet.http.HttpServletRequest; | |
9 | +import javax.servlet.http.HttpServletResponse; | |
10 | +import javax.servlet.http.HttpSession; | |
11 | + | |
12 | + | |
13 | +public class RequestContextUtil { | |
14 | + | |
15 | + public static HttpServletRequest getRequest() { | |
16 | + return getRequestAttributes().getRequest(); | |
17 | + } | |
18 | + | |
19 | + public static HttpServletResponse getResponse() { | |
20 | + return getRequestAttributes().getResponse(); | |
21 | + } | |
22 | + | |
23 | + public static HttpSession getSession() { | |
24 | + return getRequest().getSession(); | |
25 | + } | |
26 | + | |
27 | + public static ServletRequestAttributes getRequestAttributes() { | |
28 | + return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()); | |
29 | + } | |
30 | + | |
31 | + public static ServletContext getServletContext() { | |
32 | + return ContextLoader.getCurrentWebApplicationContext().getServletContext(); | |
33 | + } | |
34 | + | |
35 | +} | ... | ... |
src/main/java/com/canrd/webmagic/common/utils/RequestHolder.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/utils/RequestHolder.java | |
1 | +package com.canrd.webmagic.common.utils; | |
2 | + | |
3 | +import org.springframework.web.context.request.RequestContextHolder; | |
4 | +import org.springframework.web.context.request.ServletRequestAttributes; | |
5 | + | |
6 | +import javax.servlet.http.HttpServletRequest; | |
7 | +import java.util.Objects; | |
8 | + | |
9 | +/** | |
10 | + * 获取 HttpServletRequest | |
11 | + * | |
12 | + * @date 2018-11-24 | |
13 | + */ | |
14 | +public class RequestHolder { | |
15 | + | |
16 | + public static HttpServletRequest getHttpServletRequest() { | |
17 | + return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest(); | |
18 | + } | |
19 | +} | ... | ... |
src/main/java/com/canrd/webmagic/common/utils/RequestStringUtils.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/utils/RequestStringUtils.java | |
1 | +package com.canrd.webmagic.common.utils; | |
2 | + | |
3 | +import cn.hutool.core.io.resource.ClassPathResource; | |
4 | +import com.canrd.webmagic.common.constant.ElAdminConstant; | |
5 | +import eu.bitwalker.useragentutils.Browser; | |
6 | +import eu.bitwalker.useragentutils.UserAgent; | |
7 | +import org.lionsoul.ip2region.DataBlock; | |
8 | +import org.lionsoul.ip2region.DbConfig; | |
9 | +import org.lionsoul.ip2region.DbSearcher; | |
10 | + | |
11 | +import javax.servlet.http.HttpServletRequest; | |
12 | +import java.io.File; | |
13 | +import java.io.IOException; | |
14 | +import java.lang.reflect.Method; | |
15 | +import java.net.InetAddress; | |
16 | +import java.net.UnknownHostException; | |
17 | +import java.util.Calendar; | |
18 | +import java.util.Date; | |
19 | + | |
20 | +/** | |
21 | + * 字符串工具类, 继承org.apache.commons.lang3.StringUtils类 | |
22 | + */ | |
23 | +public class RequestStringUtils extends org.apache.commons.lang3.StringUtils { | |
24 | + | |
25 | + private static final char SEPARATOR = '_'; | |
26 | + | |
27 | + private static final String UNKNOWN = "unknown"; | |
28 | + | |
29 | + /** | |
30 | + * 驼峰命名法工具 | |
31 | + * | |
32 | + * @return toCamelCase(" hello_world ") == "helloWorld" | |
33 | + * toCapitalizeCamelCase("hello_world") == "HelloWorld" | |
34 | + * toUnderScoreCase("helloWorld") = "hello_world" | |
35 | + */ | |
36 | + public static String toCamelCase(String s) { | |
37 | + if (s == null) { | |
38 | + return null; | |
39 | + } | |
40 | + | |
41 | + s = s.toLowerCase(); | |
42 | + | |
43 | + StringBuilder sb = new StringBuilder(s.length()); | |
44 | + boolean upperCase = false; | |
45 | + for (int i = 0; i < s.length(); i++) { | |
46 | + char c = s.charAt(i); | |
47 | + | |
48 | + if (c == SEPARATOR) { | |
49 | + upperCase = true; | |
50 | + } else if (upperCase) { | |
51 | + sb.append(Character.toUpperCase(c)); | |
52 | + upperCase = false; | |
53 | + } else { | |
54 | + sb.append(c); | |
55 | + } | |
56 | + } | |
57 | + | |
58 | + return sb.toString(); | |
59 | + } | |
60 | + | |
61 | + /** | |
62 | + * 驼峰命名法工具 | |
63 | + * | |
64 | + * @return toCamelCase(" hello_world ") == "helloWorld" | |
65 | + * toCapitalizeCamelCase("hello_world") == "HelloWorld" | |
66 | + * toUnderScoreCase("helloWorld") = "hello_world" | |
67 | + */ | |
68 | + public static String toCapitalizeCamelCase(String s) { | |
69 | + if (s == null) { | |
70 | + return null; | |
71 | + } | |
72 | + s = toCamelCase(s); | |
73 | + return s.substring(0, 1).toUpperCase() + s.substring(1); | |
74 | + } | |
75 | + | |
76 | + /** | |
77 | + * 驼峰命名法工具 | |
78 | + * | |
79 | + * @return toCamelCase(" hello_world ") == "helloWorld" | |
80 | + * toCapitalizeCamelCase("hello_world") == "HelloWorld" | |
81 | + * toUnderScoreCase("helloWorld") = "hello_world" | |
82 | + */ | |
83 | + static String toUnderScoreCase(String s) { | |
84 | + if (s == null) { | |
85 | + return null; | |
86 | + } | |
87 | + | |
88 | + StringBuilder sb = new StringBuilder(); | |
89 | + boolean upperCase = false; | |
90 | + for (int i = 0; i < s.length(); i++) { | |
91 | + char c = s.charAt(i); | |
92 | + | |
93 | + boolean nextUpperCase = true; | |
94 | + | |
95 | + if (i < (s.length() - 1)) { | |
96 | + nextUpperCase = Character.isUpperCase(s.charAt(i + 1)); | |
97 | + } | |
98 | + | |
99 | + if ((i > 0) && Character.isUpperCase(c)) { | |
100 | + if (!upperCase || !nextUpperCase) { | |
101 | + sb.append(SEPARATOR); | |
102 | + } | |
103 | + upperCase = true; | |
104 | + } else { | |
105 | + upperCase = false; | |
106 | + } | |
107 | + | |
108 | + sb.append(Character.toLowerCase(c)); | |
109 | + } | |
110 | + | |
111 | + return sb.toString(); | |
112 | + } | |
113 | + | |
114 | + /** | |
115 | + * 获取ip地址 | |
116 | + */ | |
117 | + public static String getIp(HttpServletRequest request) { | |
118 | + String ip = request.getHeader("x-forwarded-for"); | |
119 | + if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { | |
120 | + ip = request.getHeader("Proxy-Client-IP"); | |
121 | + } | |
122 | + if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { | |
123 | + ip = request.getHeader("WL-Proxy-Client-IP"); | |
124 | + } | |
125 | + if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { | |
126 | + ip = request.getRemoteAddr(); | |
127 | + } | |
128 | + String comma = ","; | |
129 | + String localhost = "127.0.0.1"; | |
130 | + if (ip.contains(comma)) { | |
131 | + ip = ip.split(",")[0]; | |
132 | + } | |
133 | + if (localhost.equals(ip)) { | |
134 | + // 获取本机真正的ip地址 | |
135 | + try { | |
136 | + ip = InetAddress.getLocalHost().getHostAddress(); | |
137 | + } catch (UnknownHostException e) { | |
138 | + e.printStackTrace(); | |
139 | + } | |
140 | + } | |
141 | + return ip; | |
142 | + } | |
143 | + | |
144 | + /** | |
145 | + * 根据ip获取详细地址 | |
146 | + */ | |
147 | + public static String getCityInfo(String ip) { | |
148 | + DbSearcher searcher = null; | |
149 | + try { | |
150 | + String path = "ip2region/ip2region.db"; | |
151 | + String name = "ip2region.db"; | |
152 | + DbConfig config = new DbConfig(); | |
153 | + File file = FileUtil.inputStreamToFile(new ClassPathResource(path).getStream(), name); | |
154 | + searcher = new DbSearcher(config, file.getPath()); | |
155 | + Method method; | |
156 | + method = searcher.getClass().getMethod("btreeSearch", String.class); | |
157 | + DataBlock dataBlock; | |
158 | + dataBlock = (DataBlock) method.invoke(searcher, ip); | |
159 | + String address = dataBlock.getRegion().replace("0|", ""); | |
160 | + char symbol = '|'; | |
161 | + if (address.charAt(address.length() - 1) == symbol) { | |
162 | + address = address.substring(0, address.length() - 1); | |
163 | + } | |
164 | + return address.equals(ElAdminConstant.REGION) ? "内网IP" : address; | |
165 | + } catch (Exception e) { | |
166 | + e.printStackTrace(); | |
167 | + } finally { | |
168 | + if (searcher != null) { | |
169 | + try { | |
170 | + searcher.close(); | |
171 | + } catch (IOException ignored) { | |
172 | + } | |
173 | + } | |
174 | + | |
175 | + } | |
176 | + return ""; | |
177 | + } | |
178 | + | |
179 | + public static String getBrowser(HttpServletRequest request) { | |
180 | + UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent")); | |
181 | + Browser browser = userAgent.getBrowser(); | |
182 | + return browser.getName(); | |
183 | + } | |
184 | + | |
185 | + /** | |
186 | + * 获得当天是周几 | |
187 | + */ | |
188 | + public static String getWeekDay() { | |
189 | + String[] weekDays = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; | |
190 | + Calendar cal = Calendar.getInstance(); | |
191 | + cal.setTime(new Date()); | |
192 | + | |
193 | + int w = cal.get(Calendar.DAY_OF_WEEK) - 1; | |
194 | + if (w < 0) { | |
195 | + w = 0; | |
196 | + } | |
197 | + return weekDays[w]; | |
198 | + } | |
199 | +} | ... | ... |
src/main/java/com/canrd/webmagic/common/utils/ServletUtils.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/utils/ServletUtils.java | |
1 | +package com.canrd.webmagic.common.utils; | |
2 | + | |
3 | +import com.canrd.webmagic.common.constant.ServerResult; | |
4 | +import lombok.extern.slf4j.Slf4j; | |
5 | +import org.springframework.http.HttpStatus; | |
6 | + | |
7 | +import javax.servlet.http.HttpServletResponse; | |
8 | +import java.io.IOException; | |
9 | + | |
10 | +/** | |
11 | + * @date 2023-02-02 | |
12 | + */ | |
13 | +@Slf4j | |
14 | +public class ServletUtils { | |
15 | + | |
16 | + | |
17 | + public static void renderServerResult(HttpServletResponse response, ServerResult serverResult, HttpStatus httpStatus) { | |
18 | + try { | |
19 | + response.setStatus(httpStatus.value()); | |
20 | + response.setContentType("application/json"); | |
21 | + response.setCharacterEncoding("utf-8"); | |
22 | + response.getWriter().print(JsonUtil.toJsonString(serverResult)); | |
23 | + } catch (IOException e) { | |
24 | + log.error("ServletUtils#renderServerResult:", e); | |
25 | + } | |
26 | + } | |
27 | + | |
28 | + | |
29 | + public static void renderExcelFileNotFound(HttpServletResponse response) { | |
30 | + try { | |
31 | + response.setStatus(404); | |
32 | + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"); | |
33 | + //test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码 | |
34 | + response.setHeader("Content-Disposition", "attachment;filename=file.xlsx"); | |
35 | + response.sendError(HttpStatus.NOT_FOUND.value(), "下载失败,资源不存在"); | |
36 | + } catch (IOException e) { | |
37 | + log.error("ServletUtils#renderWithResourceNotFound:", e); | |
38 | + } | |
39 | + } | |
40 | +} | ... | ... |
src/main/java/com/canrd/webmagic/common/utils/SpringContextHolder.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/utils/SpringContextHolder.java | |
1 | +package com.canrd.webmagic.common.utils; | |
2 | + | |
3 | +import lombok.extern.slf4j.Slf4j; | |
4 | +import org.springframework.beans.BeansException; | |
5 | +import org.springframework.beans.factory.DisposableBean; | |
6 | +import org.springframework.context.ApplicationContext; | |
7 | +import org.springframework.context.ApplicationContextAware; | |
8 | + | |
9 | +/** | |
10 | + * @author Jie | |
11 | + * @date 2019-01-07 | |
12 | + */ | |
13 | +@Slf4j | |
14 | +public class SpringContextHolder implements ApplicationContextAware, DisposableBean { | |
15 | + | |
16 | + private static ApplicationContext applicationContext = null; | |
17 | + | |
18 | + /** | |
19 | + * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. | |
20 | + */ | |
21 | + @SuppressWarnings("unchecked") | |
22 | + public static <T> T getBean(String name) { | |
23 | + assertContextInjected(); | |
24 | + return (T) applicationContext.getBean(name); | |
25 | + } | |
26 | + | |
27 | + /** | |
28 | + * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. | |
29 | + */ | |
30 | + public static <T> T getBean(Class<T> requiredType) { | |
31 | + assertContextInjected(); | |
32 | + return applicationContext.getBean(requiredType); | |
33 | + } | |
34 | + | |
35 | + /** | |
36 | + * 检查ApplicationContext不为空. | |
37 | + */ | |
38 | + private static void assertContextInjected() { | |
39 | + if (applicationContext == null) { | |
40 | + throw new IllegalStateException("applicaitonContext属性未注入, 请在applicationContext" + | |
41 | + ".xml中定义SpringContextHolder或在SpringBoot启动类中注册SpringContextHolder."); | |
42 | + } | |
43 | + } | |
44 | + | |
45 | + /** | |
46 | + * 清除SpringContextHolder中的ApplicationContext为Null. | |
47 | + */ | |
48 | + private static void clearHolder() { | |
49 | + log.debug("清除SpringContextHolder中的ApplicationContext:" | |
50 | + + applicationContext); | |
51 | + applicationContext = null; | |
52 | + } | |
53 | + | |
54 | + @Override | |
55 | + public void destroy() { | |
56 | + SpringContextHolder.clearHolder(); | |
57 | + } | |
58 | + | |
59 | + @Override | |
60 | + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { | |
61 | + if (SpringContextHolder.applicationContext != null) { | |
62 | + log.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext); | |
63 | + } | |
64 | + SpringContextHolder.applicationContext = applicationContext; | |
65 | + } | |
66 | +} | ... | ... |
src/main/java/com/canrd/webmagic/common/utils/StringUtils.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/utils/StringUtils.java | |
1 | +package com.canrd.webmagic.common.utils; | |
2 | + | |
3 | +import com.canrd.webmagic.common.constant.Constant; | |
4 | +import lombok.extern.slf4j.Slf4j; | |
5 | +import org.springframework.util.CollectionUtils; | |
6 | + | |
7 | +import java.math.BigDecimal; | |
8 | +import java.nio.charset.StandardCharsets; | |
9 | +import java.util.*; | |
10 | +import java.util.regex.Matcher; | |
11 | +import java.util.regex.Pattern; | |
12 | +import java.util.regex.PatternSyntaxException; | |
13 | +import java.util.stream.Collectors; | |
14 | +import java.util.stream.Stream; | |
15 | + | |
16 | +/** | |
17 | + * @param | |
18 | + * @version 0.1.0 | |
19 | + * @Description | |
20 | + * @return | |
21 | + * @date 2021/4/16 17:44 | |
22 | + * @since 0.1.0 | |
23 | + */ | |
24 | +@Slf4j | |
25 | +public class StringUtils { | |
26 | + /** | |
27 | + * 首字母变小写 | |
28 | + * | |
29 | + * @param str | |
30 | + * @return | |
31 | + */ | |
32 | + public static String firstCharToLowerCase(String str) { | |
33 | + char firstChar = str.charAt(0); | |
34 | + if (firstChar >= 'A' && firstChar <= 'Z') { | |
35 | + char[] arr = str.toCharArray(); | |
36 | + arr[0] += ('a' - 'A'); | |
37 | + return new String(arr); | |
38 | + } | |
39 | + return str; | |
40 | + } | |
41 | + | |
42 | + /** | |
43 | + * 首字母变大写 | |
44 | + * | |
45 | + * @param str | |
46 | + * @return | |
47 | + */ | |
48 | + public static String firstCharToUpperCase(String str) { | |
49 | + char firstChar = str.charAt(0); | |
50 | + if (firstChar >= 'a' && firstChar <= 'z') { | |
51 | + char[] arr = str.toCharArray(); | |
52 | + arr[0] -= ('a' - 'A'); | |
53 | + return new String(arr); | |
54 | + } | |
55 | + return str; | |
56 | + } | |
57 | + | |
58 | + /** | |
59 | + * 判断是否为空 | |
60 | + * | |
61 | + * @param str | |
62 | + * @return | |
63 | + */ | |
64 | + public static boolean isEmpty(final String str) { | |
65 | + return (str == null) || (str.length() == 0); | |
66 | + } | |
67 | + | |
68 | + /** | |
69 | + * 判断是否不为空 | |
70 | + * | |
71 | + * @param str | |
72 | + * @return | |
73 | + */ | |
74 | + public static boolean isNotEmpty(final String str) { | |
75 | + return !isEmpty(str); | |
76 | + } | |
77 | + | |
78 | + /** | |
79 | + * 判断是否空白 | |
80 | + * | |
81 | + * @param str | |
82 | + * @return | |
83 | + */ | |
84 | + public static boolean isBlank(final String str) { | |
85 | + int strLen; | |
86 | + if ((str == null) || ((strLen = str.length()) == 0)) { | |
87 | + return true; | |
88 | + } | |
89 | + for (int i = 0; i < strLen; i++) { | |
90 | + if (!Character.isWhitespace(str.charAt(i))) { | |
91 | + return false; | |
92 | + } | |
93 | + } | |
94 | + return true; | |
95 | + } | |
96 | + | |
97 | + /** | |
98 | + * 判断是否不是空白 | |
99 | + * | |
100 | + * @param str | |
101 | + * @return | |
102 | + */ | |
103 | + public static boolean isNotBlank(final String str) { | |
104 | + return !isBlank(str); | |
105 | + } | |
106 | + | |
107 | + /** | |
108 | + * 判断多个字符串全部是否为空 | |
109 | + * | |
110 | + * @param strings | |
111 | + * @return | |
112 | + */ | |
113 | + public static boolean isAllEmpty(String... strings) { | |
114 | + if (strings == null) { | |
115 | + return true; | |
116 | + } | |
117 | + for (String str : strings) { | |
118 | + if (isNotEmpty(str)) { | |
119 | + return false; | |
120 | + } | |
121 | + } | |
122 | + return true; | |
123 | + } | |
124 | + | |
125 | + /** | |
126 | + * 判断多个字符串其中任意一个是否为空 | |
127 | + * | |
128 | + * @param strings | |
129 | + * @return | |
130 | + */ | |
131 | + public static boolean isHasEmpty(String... strings) { | |
132 | + if (strings == null) { | |
133 | + return true; | |
134 | + } | |
135 | + for (String str : strings) { | |
136 | + if (isEmpty(str)) { | |
137 | + return true; | |
138 | + } | |
139 | + } | |
140 | + return false; | |
141 | + } | |
142 | + | |
143 | + /** | |
144 | + * 判断多个字符串是否都为blank | |
145 | + * | |
146 | + * @param strings | |
147 | + * @return | |
148 | + */ | |
149 | + public static boolean isAllBlank(String... strings) { | |
150 | + if (strings == null) { | |
151 | + return true; | |
152 | + } | |
153 | + for (String str : strings) { | |
154 | + if (isNotBlank(str)) { | |
155 | + return false; | |
156 | + } | |
157 | + } | |
158 | + return true; | |
159 | + } | |
160 | + | |
161 | + /** | |
162 | + * checkValue为 null 或者为 "" 时返回 defaultValue | |
163 | + * | |
164 | + * @param checkValue | |
165 | + * @param defaultValue | |
166 | + * @return | |
167 | + */ | |
168 | + public static String isEmpty(String checkValue, String defaultValue) { | |
169 | + return isEmpty(checkValue) ? defaultValue : checkValue; | |
170 | + } | |
171 | + | |
172 | + /** | |
173 | + * 字符串不为 null 而且不为 "" 并且等于other | |
174 | + * | |
175 | + * @param str | |
176 | + * @param other | |
177 | + * @return | |
178 | + */ | |
179 | + public static boolean isNotEmptyAndEqualsOther(String str, String other) { | |
180 | + return !isEmpty(str) && str.equals(other); | |
181 | + } | |
182 | + | |
183 | + /** | |
184 | + * 字符串不为 null 而且不为 "" 并且不等于other | |
185 | + * | |
186 | + * @param str | |
187 | + * @param other | |
188 | + * @return | |
189 | + */ | |
190 | + public static boolean isNotEmptyAndNotEqualsOther(String str, String... other) { | |
191 | + if (isEmpty(str)) { | |
192 | + return false; | |
193 | + } | |
194 | + for (String s : other) { | |
195 | + if (str.equals(s)) { | |
196 | + return false; | |
197 | + } | |
198 | + } | |
199 | + return true; | |
200 | + } | |
201 | + | |
202 | + /** | |
203 | + * 字符串不等于other | |
204 | + * | |
205 | + * @param str | |
206 | + * @param other | |
207 | + * @return | |
208 | + */ | |
209 | + public static boolean isNotEqualsOther(String str, String... other) { | |
210 | + for (String s : other) { | |
211 | + if (s.equals(str)) { | |
212 | + return false; | |
213 | + } | |
214 | + } | |
215 | + return true; | |
216 | + } | |
217 | + | |
218 | + /** | |
219 | + * 判断字符串不为空 | |
220 | + * | |
221 | + * @param strings | |
222 | + * @return | |
223 | + */ | |
224 | + public static boolean isNotEmpty(String... strings) { | |
225 | + if (strings == null || strings.length == 0) { | |
226 | + return false; | |
227 | + } | |
228 | + for (String str : strings) { | |
229 | + if (str == null || "".equals(str.trim())) { | |
230 | + return false; | |
231 | + } | |
232 | + } | |
233 | + return true; | |
234 | + } | |
235 | + | |
236 | + /** | |
237 | + * 比较字符相等 | |
238 | + * | |
239 | + * @param value | |
240 | + * @param equals | |
241 | + * @return | |
242 | + */ | |
243 | + public static boolean equals(String value, String equals) { | |
244 | + if (isAllEmpty(value, equals)) { | |
245 | + return true; | |
246 | + } | |
247 | + //进一步判断value是不是空,如果是空,要直接equals会报NPE异常 | |
248 | + if (value == null) { | |
249 | + return false; | |
250 | + } | |
251 | + return value.equals(equals); | |
252 | + } | |
253 | + | |
254 | + /** | |
255 | + * @description 将字符串转换为数字数组 | |
256 | + * @author 黄楷涵 | |
257 | + * @date 2020/9/15 | |
258 | + */ | |
259 | + public static int[] stringParseToInt(String str, String regex) { | |
260 | + return stringParseToInt(str.split(regex)); | |
261 | + } | |
262 | + | |
263 | + /** | |
264 | + * @description 将字符串数组转换为数字数组 | |
265 | + * @author dengbin | |
266 | + * @date 2020/9/15 | |
267 | + */ | |
268 | + public static int[] stringParseToInt(String[] str) { | |
269 | + int[] num = new int[str.length]; | |
270 | + for (int i = 0; i < str.length; i++) { | |
271 | + num[i] = Integer.parseInt(str[i]); | |
272 | + } | |
273 | + return num; | |
274 | + } | |
275 | + | |
276 | + /** | |
277 | + * 比较字符串不相等 | |
278 | + * | |
279 | + * @param value | |
280 | + * @param equals | |
281 | + * @return | |
282 | + */ | |
283 | + public static boolean isNotEquals(String value, String equals) { | |
284 | + return !equals(value, equals); | |
285 | + } | |
286 | + | |
287 | + public static String[] split(String content, String separatorChars) { | |
288 | + return splitWorker(content, separatorChars, -1, false); | |
289 | + } | |
290 | + | |
291 | + public static String[] split(String str, String separatorChars, int max) { | |
292 | + return splitWorker(str, separatorChars, max, false); | |
293 | + } | |
294 | + | |
295 | + public static final String[] EMPTY_STRING_ARRAY = new String[0]; | |
296 | + | |
297 | + private static String[] splitWorker(String str, String separatorChars, int max, boolean preserveAllTokens) { | |
298 | + if (str == null) { | |
299 | + return null; | |
300 | + } | |
301 | + int len = str.length(); | |
302 | + if (len == 0) { | |
303 | + return EMPTY_STRING_ARRAY; | |
304 | + } | |
305 | + List<String> list = new ArrayList<String>(); | |
306 | + int sizePlus1 = 1; | |
307 | + int i = 0, start = 0; | |
308 | + boolean match = false; | |
309 | + boolean lastMatch = false; | |
310 | + if (separatorChars == null) { | |
311 | + while (i < len) { | |
312 | + if (Character.isWhitespace(str.charAt(i))) { | |
313 | + if (match || preserveAllTokens) { | |
314 | + lastMatch = true; | |
315 | + if (sizePlus1++ == max) { | |
316 | + i = len; | |
317 | + lastMatch = false; | |
318 | + } | |
319 | + list.add(str.substring(start, i)); | |
320 | + match = false; | |
321 | + } | |
322 | + start = ++i; | |
323 | + continue; | |
324 | + } | |
325 | + lastMatch = false; | |
326 | + match = true; | |
327 | + i++; | |
328 | + } | |
329 | + } else if (separatorChars.length() == 1) { | |
330 | + char sep = separatorChars.charAt(0); | |
331 | + while (i < len) { | |
332 | + if (str.charAt(i) == sep) { | |
333 | + if (match || preserveAllTokens) { | |
334 | + lastMatch = true; | |
335 | + if (sizePlus1++ == max) { | |
336 | + i = len; | |
337 | + lastMatch = false; | |
338 | + } | |
339 | + list.add(str.substring(start, i)); | |
340 | + match = false; | |
341 | + } | |
342 | + start = ++i; | |
343 | + continue; | |
344 | + } | |
345 | + lastMatch = false; | |
346 | + match = true; | |
347 | + i++; | |
348 | + } | |
349 | + } else { | |
350 | + while (i < len) { | |
351 | + if (separatorChars.indexOf(str.charAt(i)) >= 0) { | |
352 | + if (match || preserveAllTokens) { | |
353 | + lastMatch = true; | |
354 | + if (sizePlus1++ == max) { | |
355 | + i = len; | |
356 | + lastMatch = false; | |
357 | + } | |
358 | + list.add(str.substring(start, i)); | |
359 | + match = false; | |
360 | + } | |
361 | + start = ++i; | |
362 | + continue; | |
363 | + } | |
364 | + lastMatch = false; | |
365 | + match = true; | |
366 | + i++; | |
367 | + } | |
368 | + } | |
369 | + if (match || (preserveAllTokens && lastMatch)) { | |
370 | + list.add(str.substring(start, i)); | |
371 | + } | |
372 | + return list.toArray(EMPTY_STRING_ARRAY); | |
373 | + } | |
374 | + | |
375 | + /** | |
376 | + * 消除转义字符 | |
377 | + * | |
378 | + * @param str | |
379 | + * @return | |
380 | + */ | |
381 | + public static String escapeXml(String str) { | |
382 | + if (str == null) { | |
383 | + return ""; | |
384 | + } | |
385 | + StringBuilder sb = new StringBuilder(); | |
386 | + for (int i = 0; i < str.length(); ++i) { | |
387 | + char c = str.charAt(i); | |
388 | + switch (c) { | |
389 | + case '\u00FF': | |
390 | + case '\u0024': | |
391 | + break; | |
392 | + case '&': | |
393 | + sb.append("&"); | |
394 | + break; | |
395 | + case '<': | |
396 | + sb.append("<"); | |
397 | + break; | |
398 | + case '>': | |
399 | + sb.append(">"); | |
400 | + break; | |
401 | + case '\"': | |
402 | + sb.append("""); | |
403 | + break; | |
404 | + case '\'': | |
405 | + sb.append("'"); | |
406 | + break; | |
407 | + default: | |
408 | + if (c <= '\u001F') { | |
409 | + break; | |
410 | + } | |
411 | + if (c >= '\uE000' && c <= '\uF8FF') { | |
412 | + break; | |
413 | + } | |
414 | + if (c >= '\uFFF0') { | |
415 | + break; | |
416 | + } | |
417 | + sb.append(c); | |
418 | + break; | |
419 | + } | |
420 | + } | |
421 | + return sb.toString(); | |
422 | + } | |
423 | + | |
424 | + /** | |
425 | + * 将字符串中特定模式的字符转换成map中对应的值 | |
426 | + * | |
427 | + * @param s 需要转换的字符串 | |
428 | + * @param map 转换所需的键值对集合 | |
429 | + * @return 转换后的字符串 | |
430 | + */ | |
431 | + public static String replace(String s, Map<String, Object> map) { | |
432 | + StringBuilder ret = new StringBuilder((int) (s.length() * 1.5)); | |
433 | + int cursor = 0; | |
434 | + for (int start, end; (start = s.indexOf("${", cursor)) != -1 && (end = s.indexOf("}", start)) != -1; ) { | |
435 | + ret.append(s.substring(cursor, start)).append(map.get(s.substring(start + 2, end))); | |
436 | + cursor = end + 1; | |
437 | + } | |
438 | + ret.append(s.substring(cursor, s.length())); | |
439 | + return ret.toString(); | |
440 | + } | |
441 | + | |
442 | + public static String replace(String s, Object... objs) { | |
443 | + if (objs == null || objs.length == 0) { | |
444 | + return s; | |
445 | + } | |
446 | + if (!s.contains("{}")) { | |
447 | + return s; | |
448 | + } | |
449 | + StringBuilder ret = new StringBuilder((int) (s.length() * 1.5)); | |
450 | + int cursor = 0; | |
451 | + int index = 0; | |
452 | + for (int start; (start = s.indexOf("{}", cursor)) != -1; ) { | |
453 | + ret.append(s.substring(cursor, start)); | |
454 | + if (index < objs.length) { | |
455 | + ret.append(objs[index]); | |
456 | + } else { | |
457 | + ret.append("{}"); | |
458 | + } | |
459 | + cursor = start + 2; | |
460 | + index++; | |
461 | + } | |
462 | + ret.append(s.substring(cursor, s.length())); | |
463 | + return ret.toString(); | |
464 | + } | |
465 | + | |
466 | + | |
467 | + /** | |
468 | + * 转换为字节数组 | |
469 | + * | |
470 | + * @param bytes | |
471 | + * @return | |
472 | + */ | |
473 | + public static String toString(byte[] bytes) { | |
474 | + return new String(bytes, StandardCharsets.UTF_8); | |
475 | + } | |
476 | + | |
477 | + /** | |
478 | + * 转换为字节数组 | |
479 | + * | |
480 | + * @param str | |
481 | + * @return | |
482 | + */ | |
483 | + public static byte[] getBytes(String str) { | |
484 | + return str != null ? str.getBytes(StandardCharsets.UTF_8) : null; | |
485 | + } | |
486 | + | |
487 | + public static boolean isNumeric(String cs) { | |
488 | + if (isEmpty(cs)) { | |
489 | + return false; | |
490 | + } | |
491 | + for (int i = 0, sz = cs.length(); i < sz; ++i) { | |
492 | + if (!Character.isDigit(cs.charAt(i))) { | |
493 | + return false; | |
494 | + } | |
495 | + } | |
496 | + return true; | |
497 | + | |
498 | + } | |
499 | + | |
500 | + /** | |
501 | + * 手机号脱敏 | |
502 | + * | |
503 | + * @param phoneNumber | |
504 | + * @return | |
505 | + */ | |
506 | + public static String desensitizedPhoneNumber(String phoneNumber) { | |
507 | + if (StringUtils.isNotEmpty(phoneNumber)) { | |
508 | + phoneNumber = phoneNumber.replaceAll("(\\w{3})\\w*(\\w{4})", "$1****$2"); | |
509 | + } | |
510 | + return phoneNumber; | |
511 | + } | |
512 | + | |
513 | + /** | |
514 | + * 校验3位小数 | |
515 | + * | |
516 | + * @param str | |
517 | + * @return | |
518 | + */ | |
519 | + public static boolean checkDecimal(String str) { | |
520 | + return Pattern.compile(Constant.DICMAL_REGEXP).matcher(str).find(); | |
521 | + } | |
522 | + | |
523 | + /** | |
524 | + * 校验11位国内手机号 | |
525 | + * <p>规则: 11位数,首位必须为1,第二位可以是3-9;其他位数不限制 | |
526 | + * | |
527 | + * @param phone 手机号 | |
528 | + * @return 格式正确则返回false; 反之为true | |
529 | + * @author A80080 | |
530 | + * @createDate 2020/12/19 | |
531 | + */ | |
532 | + public static boolean checkPhoneNum(String phone) { | |
533 | + return StringUtils.isEmpty(phone) || !Pattern.compile("^1([3-9])[0-9]{9}$").matcher(phone).find(); | |
534 | + } | |
535 | + | |
536 | + /** | |
537 | + * @param str | |
538 | + * @return boolean | |
539 | + * @Description 判断字符串是否含有空格 | |
540 | + * @version 0.1.0 | |
541 | + * @author 邓彬 | |
542 | + * @date 2021/1/13 18:10 | |
543 | + * @since 0.1.0 | |
544 | + */ | |
545 | + public static boolean checkStringContainEmpty(String str) { | |
546 | + return !StringUtils.isEmpty(str) && str.contains(" "); | |
547 | + } | |
548 | + | |
549 | + /** | |
550 | + * 字符串切分 | |
551 | + * | |
552 | + * @param splitStr | |
553 | + * @param splitFlag | |
554 | + * @return | |
555 | + */ | |
556 | + public static List<String> splitTag(String splitStr, String splitFlag) { | |
557 | + return StringUtils.isBlank(splitStr) || StringUtils.isBlank(splitFlag) ? | |
558 | + new ArrayList<>() : | |
559 | + Arrays.stream(splitStr.split(splitFlag)).collect(Collectors.toList()); | |
560 | + } | |
561 | + | |
562 | + /** | |
563 | + * @param name | |
564 | + * @return true代表全是汉字 | |
565 | + * @Description 校验String是否全是中文 | |
566 | + * @version 0.1.0 | |
567 | + * @author 邓彬 | |
568 | + * @date 2021/1/18 19:54 | |
569 | + * @since 0.1.0 | |
570 | + */ | |
571 | + public static boolean checkNameChina(String name) { | |
572 | + boolean res = true; | |
573 | + char[] cTemp = name.toCharArray(); | |
574 | + for (int i = 0; i < name.length(); i++) { | |
575 | + if (!isChinese(cTemp[i])) { | |
576 | + res = false; | |
577 | + break; | |
578 | + } | |
579 | + } | |
580 | + return res; | |
581 | + } | |
582 | + | |
583 | + /** | |
584 | + * @param c | |
585 | + * @return true代表是汉字 | |
586 | + * @Description 判定输入的是否是汉字 | |
587 | + * @version 0.1.0 | |
588 | + * @author 邓彬 | |
589 | + * @date 2021/1/18 19:53 | |
590 | + * @since 0.1.0 | |
591 | + */ | |
592 | + public static boolean isChinese(char c) { | |
593 | + Character.UnicodeBlock ub = Character.UnicodeBlock.of(c); | |
594 | + if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS | |
595 | + || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS | |
596 | + || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A | |
597 | + || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION | |
598 | + || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION | |
599 | + || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) { | |
600 | + return true; | |
601 | + } | |
602 | + return false; | |
603 | + } | |
604 | + | |
605 | + /** | |
606 | + * @param c | |
607 | + * @return true代表符合条件 | |
608 | + * @Description 校验某个字符是否是a-z、A-Z、_、0-9 | |
609 | + * @version 0.1.0 | |
610 | + * @author 邓彬 | |
611 | + * @date 2021/1/18 19:56 | |
612 | + * @since 0.1.0 | |
613 | + */ | |
614 | + public static boolean isWord(char c) { | |
615 | + return Pattern.compile("[\\w]").matcher("" + c).matches(); | |
616 | + } | |
617 | + | |
618 | + /** | |
619 | + * @param str | |
620 | + * @return boolean | |
621 | + * @Description 字符串是否仅包含数字和字母 | |
622 | + * @version 0.1.0 | |
623 | + * @author 邓彬 | |
624 | + * @date 2021/1/18 20:00 | |
625 | + * @since 0.1.0 | |
626 | + */ | |
627 | + public static boolean isLetterDigit(String str) { | |
628 | + return str.matches("^[a-z0-9A-Z]+$"); | |
629 | + } | |
630 | + | |
631 | + /** | |
632 | + * @param str | |
633 | + * @return boolean | |
634 | + * @Description 判断是否是纯数字 | |
635 | + * @version 0.1.0 | |
636 | + * @author 邓彬 | |
637 | + * @date 2021/1/23 16:33 | |
638 | + * @since 0.1.0 | |
639 | + */ | |
640 | + public static boolean isDigit(String str) { | |
641 | + return str.matches("^[0-9]+$"); | |
642 | + } | |
643 | + | |
644 | + /** | |
645 | + * 是否合法手机号 | |
646 | + * | |
647 | + * @param phone | |
648 | + * @return | |
649 | + */ | |
650 | + public static boolean isMobilePhone(String phone) { | |
651 | + return Pattern.compile(Constant.PHONE_REGEXP).matcher(phone).matches(); | |
652 | + } | |
653 | + | |
654 | + /** | |
655 | + * 是否脱敏手机号 | |
656 | + * | |
657 | + * @param phone | |
658 | + * @return | |
659 | + */ | |
660 | + public static boolean isDesensitizationMobilePhone(String phone) { | |
661 | + return Pattern.compile(Constant.PHONE_DESENSITIZATION_REGEXP).matcher(phone).matches(); | |
662 | + } | |
663 | + | |
664 | + /** | |
665 | + * 判断String是否是整数<br> | |
666 | + * 支持10进制 | |
667 | + * | |
668 | + * @param s String | |
669 | + * @return 是否为整数 | |
670 | + */ | |
671 | + public static boolean isInteger(String s) { | |
672 | + try { | |
673 | + Integer.parseInt(s); | |
674 | + } catch (NumberFormatException e) { | |
675 | + return false; | |
676 | + } | |
677 | + return true; | |
678 | + } | |
679 | + | |
680 | + /** | |
681 | + * 判断对象能否转 | |
682 | + * | |
683 | + * @param o Object | |
684 | + * @return 是否为Integer | |
685 | + */ | |
686 | + public static boolean isInteger(Object o) { | |
687 | + try { | |
688 | + Integer.parseInt(String.valueOf(o)); | |
689 | + return true; | |
690 | + } catch (NumberFormatException e) { | |
691 | + return false; | |
692 | + } | |
693 | + } | |
694 | + | |
695 | + public static String escapeCharacter(String str) { | |
696 | + if (!isEmpty(str)) { | |
697 | + if (str.contains("\\")) { | |
698 | + str = str.replaceAll("\\\\", "\\\\\\\\"); | |
699 | + } | |
700 | + } | |
701 | + return str; | |
702 | + } | |
703 | + | |
704 | + /** | |
705 | + * @param str | |
706 | + * @return boolean | |
707 | + * @Description 匹配字符串是,数字、26个英文字母、下划线组成的8-16位的字符串组合 | |
708 | + * @version 0.1.0 | |
709 | + * @author A80077-刘始达 | |
710 | + * @date 2021/04/06 | |
711 | + * @since 0.1.0 | |
712 | + */ | |
713 | + public static boolean checkPWD(String str) { | |
714 | + return str.matches("^(?=.*([a-zA-Z].*))(?=.*[0-9].*)[a-zA-Z0-9-_]{8,16}+$"); | |
715 | + } | |
716 | + | |
717 | + /** | |
718 | + * 判断是否包含特殊字符 | |
719 | + * | |
720 | + * @param str | |
721 | + * @return | |
722 | + */ | |
723 | + public static boolean checkSpecificSymbol(String str) { | |
724 | + String regEx = "[ _`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~!@#¥%……&*()——+|{}【】‘;:”“’。,、?]|\n|\r|\t"; | |
725 | + Pattern p = Pattern.compile(regEx); | |
726 | + Matcher m = p.matcher(str); | |
727 | + return m.find(); | |
728 | + } | |
729 | + | |
730 | + /** | |
731 | + * 拼接图片标签url | |
732 | + * | |
733 | + * @param str | |
734 | + * @param ossDomain | |
735 | + * @return | |
736 | + */ | |
737 | + public static String replaceHtmlTag(String str, String ossDomain) { | |
738 | + if (StringUtils.isEmpty(str)) { | |
739 | + return ""; | |
740 | + } | |
741 | + if (StringUtils.isEmpty(ossDomain)) { | |
742 | + return str; | |
743 | + } | |
744 | + return replaceHtmlTag(str, "img", "src", "src=\"" + ossDomain, "\""); | |
745 | + } | |
746 | + | |
747 | + /** | |
748 | + * html格式处理:替换指定标签的属性和值 | |
749 | + * | |
750 | + * @param str 需要处理的字符串 | |
751 | + * @param tag 标签名称 | |
752 | + * @param tagAttrib 要替换的标签属性值 | |
753 | + * @param startTag 新标签开始标记 | |
754 | + * @param endTag 新标签结束标记 | |
755 | + * @return | |
756 | + */ | |
757 | + public static String replaceHtmlTag(String str, String tag, String tagAttrib, String startTag, String endTag) { | |
758 | + String regxpForTag = "<\\s*" + tag + "\\s+([^>]*)\\s*"; | |
759 | + String regxpForTagAttrib = tagAttrib + "=\\s*\"([^\"]+)\""; | |
760 | + Pattern patternForTag = Pattern.compile(regxpForTag, Pattern.CASE_INSENSITIVE); | |
761 | + Pattern patternForAttrib = Pattern.compile(regxpForTagAttrib, Pattern.CASE_INSENSITIVE); | |
762 | + Matcher matcherForTag = patternForTag.matcher(str); | |
763 | + StringBuffer sb = new StringBuffer(); | |
764 | + boolean result = matcherForTag.find(); | |
765 | + while (result) { | |
766 | + StringBuffer stringBuffer = new StringBuffer("<" + tag + " "); | |
767 | + Matcher matcherForAttrib = patternForAttrib.matcher(matcherForTag.group(1)); | |
768 | + if (matcherForAttrib.find()) { | |
769 | + String attributeStr = matcherForAttrib.group(1); | |
770 | + if (!attributeStr.contains("https") && !attributeStr.contains("http")) { | |
771 | + matcherForAttrib.appendReplacement(stringBuffer, startTag + attributeStr + endTag); | |
772 | + } | |
773 | + } | |
774 | + matcherForAttrib.appendTail(stringBuffer); | |
775 | + matcherForTag.appendReplacement(sb, stringBuffer.toString()); | |
776 | + result = matcherForTag.find(); | |
777 | + } | |
778 | + matcherForTag.appendTail(sb); | |
779 | + return sb.toString(); | |
780 | + } | |
781 | + | |
782 | + /** | |
783 | + * @param str | |
784 | + * @return java.util.Map<String, List < String>> | |
785 | + * @Description 字符串的连续切割 返回中文词组 数字和字母的集合 | |
786 | + * @version 0.1.0 | |
787 | + * @author 邓彬 | |
788 | + * @date 2021/4/15 13:53 | |
789 | + * @since 0.1.0 | |
790 | + */ | |
791 | + public static Map<String, List<String>> convertStrToChineseList(String str) { | |
792 | + if (StringUtils.isEmpty(str)) { | |
793 | + return null; | |
794 | + } | |
795 | + Map<String, List<String>> resultMap = new HashMap<>(); | |
796 | + List<String> chineseList; | |
797 | + List<String> charList; | |
798 | + char[] list = str.toCharArray(); | |
799 | + StringBuilder chineseStr = new StringBuilder(); | |
800 | + StringBuilder charStr = new StringBuilder(); | |
801 | + for (char c : list) { | |
802 | + if (StringUtils.isChinese(c)) { | |
803 | + chineseStr.append(c); | |
804 | + charStr.append(Constant.SLASH_MARK_CHARACTER); | |
805 | + } else if (Character.isLetterOrDigit(c)) { | |
806 | + charStr.append(c); | |
807 | + chineseStr.append(Constant.SLASH_MARK_CHARACTER); | |
808 | + } else { | |
809 | + charStr.append(Constant.SLASH_MARK_CHARACTER); | |
810 | + chineseStr.append(Constant.SLASH_MARK_CHARACTER); | |
811 | + } | |
812 | + | |
813 | + } | |
814 | + chineseList = Arrays.stream(chineseStr.toString() | |
815 | + .split(Constant.SLASH_MARK_CHARACTER)) | |
816 | + .filter(StringUtils::isNotEmpty).collect(Collectors.toList()); | |
817 | + charList = Arrays.stream(charStr.toString() | |
818 | + .split(Constant.SLASH_MARK_CHARACTER)) | |
819 | + .filter(StringUtils::isNotEmpty).map(String::toLowerCase).collect(Collectors.toList()); | |
820 | + | |
821 | + resultMap.put("chineseKey", chineseList); | |
822 | + resultMap.put("charKey", charList); | |
823 | + return resultMap; | |
824 | + } | |
825 | + | |
826 | + /** | |
827 | + * 单个字符转换为小写 | |
828 | + * | |
829 | + * @param c | |
830 | + * @return | |
831 | + */ | |
832 | + public static char singleCharToLowerCase(char c) { | |
833 | + if (c >= 'A' && c <= 'Z') { | |
834 | + c += ('a' - 'A'); | |
835 | + return c; | |
836 | + } | |
837 | + return c; | |
838 | + } | |
839 | + | |
840 | + public static boolean isLong(String shopId) { | |
841 | + try { | |
842 | + Long.parseLong(shopId); | |
843 | + } catch (NumberFormatException e) { | |
844 | + return false; | |
845 | + } | |
846 | + return true; | |
847 | + } | |
848 | + | |
849 | + public static String priceFormatting(String price) { | |
850 | + if (StringUtils.isEmpty(price)) { | |
851 | + return Constant.EMPTY_STRING; | |
852 | + } | |
853 | + | |
854 | + String newPrice = ""; | |
855 | + // 价格不存在小数点,则直接返回,无需处理 | |
856 | + if (!price.contains(Constant.POINT_BAR_CHARACTER)) { | |
857 | + newPrice = price; | |
858 | + return newPrice; | |
859 | + } | |
860 | + | |
861 | + // 有小数点,则分割字符串 | |
862 | + String[] s = price.split("\\."); | |
863 | + | |
864 | + // 小数位数大于0 且小于2 且存在非0字符 | |
865 | + if (s[1].length() > 0 && s[1].length() <= 2 && !judgeIsNumeric(s[1])) { | |
866 | + BigDecimal bigDecimal = new BigDecimal(price).setScale(2, BigDecimal.ROUND_HALF_UP); | |
867 | + newPrice = bigDecimal.toPlainString(); | |
868 | + } | |
869 | + // 【保留这个else if】小数位数大于0 且大于2 且存在非0字符,理论上不会存在,因为新增商品时已经限定最多输入2个小数点 | |
870 | + else if (s[1].length() > 0 && s[1].length() > 2 && !judgeIsNumeric(s[1])) { | |
871 | + BigDecimal bigDecimal = new BigDecimal(price).setScale(2, BigDecimal.ROUND_HALF_UP); | |
872 | + String[] split = bigDecimal.toPlainString().split("\\."); | |
873 | + if (split[1].length() > 0 && judgeIsNumeric(split[1])) { | |
874 | + newPrice = new BigDecimal(bigDecimal.toPlainString()).setScale(0, BigDecimal.ROUND_HALF_UP).toPlainString(); | |
875 | + } else { | |
876 | + newPrice = bigDecimal.toPlainString(); | |
877 | + } | |
878 | + } else { | |
879 | + // 小数位数大于0 且小于2 且小数点都是0 | |
880 | + newPrice = new BigDecimal(price).setScale(0, BigDecimal.ROUND_HALF_UP).toPlainString(); | |
881 | + } | |
882 | + return newPrice; | |
883 | + } | |
884 | + | |
885 | + /** | |
886 | + * 判断字符串是否只包含0 | |
887 | + * | |
888 | + * @param str | |
889 | + * @return | |
890 | + */ | |
891 | + private static boolean judgeIsNumeric(String str) { | |
892 | + return Pattern.compile("[0]*").matcher(str).matches(); | |
893 | + } | |
894 | + | |
895 | + /** | |
896 | + * 字符串以","分隔后转为String[] | |
897 | + * | |
898 | + * @param s | |
899 | + * @return | |
900 | + */ | |
901 | + public static String[] string2ArraySplitByComma(String s) { | |
902 | + if (s == null || s.length() == 0) { | |
903 | + return new String[]{}; | |
904 | + } | |
905 | + return s.split(Constant.COMMA_CHARACTER); | |
906 | + } | |
907 | + | |
908 | + public static boolean isStringArrayContainsSpecifiedValue(String[] strings, String value) { | |
909 | + if (null == strings || strings.length <= 0 || value == null || value.length() == 0) { | |
910 | + return false; | |
911 | + } | |
912 | + boolean isContainsSpecifiedValue = false; | |
913 | + for (String s : strings) { | |
914 | + if (s.equals(value)) { | |
915 | + isContainsSpecifiedValue = true; | |
916 | + break; | |
917 | + } | |
918 | + } | |
919 | + return isContainsSpecifiedValue; | |
920 | + } | |
921 | + | |
922 | + /** | |
923 | + * 字符串以","分隔后转为list | |
924 | + * | |
925 | + * @param s | |
926 | + * @return | |
927 | + */ | |
928 | + public static List<String> string2ListSplitByComma(String s) { | |
929 | + List<String> stringList = new ArrayList<>(); | |
930 | + if (s == null || s.length() == 0) { | |
931 | + return stringList; | |
932 | + } | |
933 | + String[] strArray = string2ArraySplitByComma(s); | |
934 | + | |
935 | + for (String st : strArray) { | |
936 | + if (null != st && st.trim() != null || st.trim().length() != 0) { | |
937 | + stringList.add(st.trim()); | |
938 | + } | |
939 | + } | |
940 | + | |
941 | + return stringList; | |
942 | + } | |
943 | + | |
944 | + /** | |
945 | + * 字符串按照特殊符号 | |
946 | + * ".*[`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~!@#¥%……&*()——+|{}【】‘;:”“’。,、?\\\\]+.*" | |
947 | + * 截取转成字符串集合 | |
948 | + * | |
949 | + * @param str | |
950 | + * @return | |
951 | + */ | |
952 | + public static List<String> splitStringBySpecificSymbol(String str) throws PatternSyntaxException { | |
953 | + String regEx = "[`~!@#$%^&*()\\-+=|{}':;,\\[\\].<>/?!¥…()—【】‘;:”“’。,、?\\\\]"; | |
954 | + Pattern p = Pattern.compile(regEx); | |
955 | + Matcher m = p.matcher(str); | |
956 | + return Stream.of(m.replaceAll("_").split("_")).map(String::trim).filter(StringUtils::isNotBlank).collect(Collectors.toList()); | |
957 | + } | |
958 | + | |
959 | + /** | |
960 | + * 将list转为字符串,用逗号隔开 | |
961 | + * | |
962 | + * @param list | |
963 | + * @return | |
964 | + */ | |
965 | + public static String listTransToStr(List<String> list) { | |
966 | + if (CollectionUtils.isEmpty(list)) return null; | |
967 | + StringBuilder sb = new StringBuilder(); | |
968 | + list.forEach(x -> { | |
969 | + sb.append(x); | |
970 | + sb.append(","); | |
971 | + }); | |
972 | + String str = sb.toString(); | |
973 | + return str.substring(0, str.length() - 1); | |
974 | + } | |
975 | + | |
976 | + /** | |
977 | + * 是否包含中英文 | |
978 | + * | |
979 | + * @param str | |
980 | + * @return | |
981 | + */ | |
982 | + public static boolean checkCnAndEn(String str) { | |
983 | + String regEx = Constant.CHI_EN_REGEXP; | |
984 | + Pattern p = Pattern.compile(regEx); | |
985 | + Matcher m = p.matcher(str); | |
986 | + return m.find(); | |
987 | + } | |
988 | + | |
989 | + | |
990 | + /** | |
991 | + * @param code 要隐藏显示的字符串 | |
992 | + * @param head 前面保留的位数 | |
993 | + * @param tail 后面保留的位数 | |
994 | + * @return 处理后的字符串 | |
995 | + */ | |
996 | + public static String getEncryptCode(String code, int head, int tail) { | |
997 | + int body = code.length() - head - tail; | |
998 | + String regexVar = "(\\w{%d})(\\w{%d})(\\w{%d})"; | |
999 | + String regex = String.format(regexVar, head, body, tail); | |
1000 | + String bodyPart = code.replaceAll(regex, "$2"); | |
1001 | + String bodyEncrypt = bodyPart.replaceAll("\\w", "*"); | |
1002 | + String replacement = String.format("$1%s$3", bodyEncrypt); | |
1003 | + return code.replaceAll(regex, replacement); | |
1004 | + } | |
1005 | +} | ... | ... |
src/main/java/com/canrd/webmagic/common/utils/TemplateFormatUtils.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/utils/TemplateFormatUtils.java | |
1 | +package com.canrd.webmagic.common.utils; | |
2 | + | |
3 | +import java.util.Map; | |
4 | +import java.util.regex.Matcher; | |
5 | +import java.util.regex.Pattern; | |
6 | + | |
7 | +/** | |
8 | + * | |
9 | + * 消息模板占位符替换工具 | |
10 | + * | |
11 | + * @author fanzhenyu | |
12 | + * @date 2022-04-20 | |
13 | + */ | |
14 | +public class TemplateFormatUtils { | |
15 | + | |
16 | + | |
17 | + /** | |
18 | + * 正则 匹配 { + "多个任意字符" + } | |
19 | + */ | |
20 | + private static final String DEFAULT_REG = "\\{[\\w]+\\}"; | |
21 | + | |
22 | + /** | |
23 | + * | |
24 | + * @param text 原模板 占位符格式必须为:{fieldName} | |
25 | + * @param map 模板参数 | |
26 | + * @return | |
27 | + */ | |
28 | + public static String replaceTemplateContent(String text, Map<String, String> map){ | |
29 | + return replaceTemplateContent(text,map,DEFAULT_REG); | |
30 | + } | |
31 | + | |
32 | + /** | |
33 | + * | |
34 | + * @param text 原模板 占位符格式必须为:{fieldName} | |
35 | + * @param map 模板参数 | |
36 | + * @param reg 自定义占位符样式 - 正则匹配 | |
37 | + * @return | |
38 | + */ | |
39 | + public static String replaceTemplateContent(String text,Map<String,String> map,String reg){ | |
40 | + | |
41 | + if(StringUtils.isBlank(reg)){ | |
42 | + reg = DEFAULT_REG; | |
43 | + } | |
44 | + | |
45 | + Pattern pattern = Pattern.compile(reg); | |
46 | + Matcher m = pattern.matcher(text); | |
47 | + while(m.find()){ | |
48 | + String currentGroup = m.group(); | |
49 | + String currentPattern = currentGroup.replaceAll("^\\{", "").replaceAll("\\}$", "").trim(); | |
50 | + String mapValue = map.get(currentPattern); | |
51 | + if (mapValue != null){ | |
52 | + text = text.replace(currentGroup, mapValue); | |
53 | + } | |
54 | + } | |
55 | + return text; | |
56 | + } | |
57 | +} | ... | ... |
src/main/java/com/canrd/webmagic/common/utils/ThrowableUtil.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/utils/ThrowableUtil.java | |
1 | +package com.canrd.webmagic.common.utils; | |
2 | + | |
3 | +import com.canrd.webmagic.common.exception.BusinessException; | |
4 | + | |
5 | +import javax.validation.ConstraintViolationException; | |
6 | +import java.io.PrintWriter; | |
7 | +import java.io.StringWriter; | |
8 | + | |
9 | +/** | |
10 | + * 异常工具 2019-01-06 | |
11 | + */ | |
12 | +public class ThrowableUtil { | |
13 | + | |
14 | + /** | |
15 | + * 获取堆栈信息 | |
16 | + */ | |
17 | + public static String getStackTrace(Throwable throwable) { | |
18 | + StringWriter sw = new StringWriter(); | |
19 | + try (PrintWriter pw = new PrintWriter(sw)) { | |
20 | + throwable.printStackTrace(pw); | |
21 | + return sw.toString(); | |
22 | + } | |
23 | + } | |
24 | + | |
25 | + public static void throwForeignKeyException(Throwable e, String msg) { | |
26 | + Throwable t = e.getCause(); | |
27 | + while ((t != null) && !(t instanceof ConstraintViolationException)) { | |
28 | + t = t.getCause(); | |
29 | + } | |
30 | + if (t != null) { | |
31 | + throw new BusinessException(msg); | |
32 | + } | |
33 | + assert false; | |
34 | + throw new BusinessException("删除失败:" + t.getMessage()); | |
35 | + } | |
36 | +} | ... | ... |
src/main/java/com/canrd/webmagic/common/utils/TransactionHelper.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/common/utils/TransactionHelper.java | |
1 | +package com.canrd.webmagic.common.utils; | |
2 | + | |
3 | +import org.springframework.stereotype.Component; | |
4 | +import org.springframework.transaction.annotation.Propagation; | |
5 | +import org.springframework.transaction.annotation.Transactional; | |
6 | + | |
7 | +import java.util.function.Supplier; | |
8 | + | |
9 | +/** | |
10 | + * @author: | |
11 | + * @date: 2021/12/21 | |
12 | + */ | |
13 | +@Component | |
14 | +public class TransactionHelper { | |
15 | + | |
16 | + @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) | |
17 | + public <T> T run(Supplier<T> command) { | |
18 | + return command.get(); | |
19 | + } | |
20 | + | |
21 | + @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) | |
22 | + public void run(Runnable command) { | |
23 | + command.run(); | |
24 | + } | |
25 | + | |
26 | + | |
27 | +} | ... | ... |
src/main/java/com/canrd/webmagic/config/AdminMetaObjectHandler.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/config/AdminMetaObjectHandler.java | |
1 | +package com.canrd.webmagic.config; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; | |
4 | +import com.canrd.webmagic.common.constant.Constant; | |
5 | +import lombok.extern.slf4j.Slf4j; | |
6 | +import org.apache.ibatis.reflection.MetaObject; | |
7 | +import org.springframework.stereotype.Component; | |
8 | + | |
9 | +import java.time.LocalDateTime; | |
10 | + | |
11 | + | |
12 | +@Slf4j | |
13 | +@Component | |
14 | +public class AdminMetaObjectHandler implements MetaObjectHandler { | |
15 | + | |
16 | + | |
17 | + private static final String CREATE_TIME = "createTime"; | |
18 | + private static final String MODIFY_TIME = "modifyTime"; | |
19 | + private static final String CREATE_BY = "createBy"; | |
20 | + private static final String MODIFY_BY = "modifyBy"; | |
21 | + private static final String ENABLE_FLAG = "enableFlag"; | |
22 | + private static final String STRING_CLASS_NAME = "java.lang.String"; | |
23 | + private static final String LONG_CLASS_NAME = "java.lang.Long"; | |
24 | + | |
25 | + @Override | |
26 | + public void insertFill(MetaObject metaObject) { | |
27 | + LocalDateTime now = LocalDateTime.now(); | |
28 | + this.strictInsertFill(metaObject, CREATE_TIME, LocalDateTime.class, now); | |
29 | + this.strictInsertFill(metaObject, MODIFY_TIME, LocalDateTime.class, now); | |
30 | + this.strictInsertFill(metaObject, ENABLE_FLAG, Integer.class, Constant.ENABLE_TEN); | |
31 | + try { | |
32 | +// UserDetails loginUser = SecurityUtils.getUserDetails(); | |
33 | + this.strictInsertFill(metaObject, CREATE_BY, String.class, "system"); | |
34 | + this.strictInsertFill(metaObject, MODIFY_BY, String.class, "system"); | |
35 | + | |
36 | +// this.strictInsertFill(metaObject, CREATE_BY, String.class, loginUser.getUsername()); | |
37 | +// this.strictInsertFill(metaObject, MODIFY_BY, String.class, loginUser.getUsername()); | |
38 | + } catch (Exception e) { | |
39 | + this.strictInsertFill(metaObject, CREATE_BY, String.class, "system"); | |
40 | + | |
41 | + this.strictInsertFill(metaObject, MODIFY_BY, String.class, "system"); | |
42 | + } | |
43 | + | |
44 | + | |
45 | + } | |
46 | + | |
47 | + @Override | |
48 | + public void updateFill(MetaObject metaObject) { | |
49 | + | |
50 | + this.strictUpdateFill(metaObject, MODIFY_TIME, LocalDateTime.class, LocalDateTime.now()); | |
51 | + | |
52 | + | |
53 | + try { | |
54 | +// UserDetails loginUser = SecurityUtils.getUserDetails(); | |
55 | +// if (null == loginUser) { | |
56 | +// return; | |
57 | +// } | |
58 | +// this.strictUpdateFill(metaObject, MODIFY_BY, String.class, loginUser.getUsername()); | |
59 | + this.strictUpdateFill(metaObject, MODIFY_BY, String.class, "system"); | |
60 | + | |
61 | + } catch (Exception e) { | |
62 | + this.strictUpdateFill(metaObject, MODIFY_BY, String.class, "system"); | |
63 | + } | |
64 | + | |
65 | + } | |
66 | +} | ... | ... |
src/main/java/com/canrd/webmagic/config/ConfigurerAdapter.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/config/ConfigurerAdapter.java | |
1 | +package com.canrd.webmagic.config; | |
2 | + | |
3 | +import org.springframework.context.annotation.Bean; | |
4 | +import org.springframework.context.annotation.Configuration; | |
5 | +import org.springframework.web.cors.CorsConfiguration; | |
6 | +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; | |
7 | +import org.springframework.web.filter.CorsFilter; | |
8 | +import org.springframework.web.servlet.config.annotation.EnableWebMvc; | |
9 | +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | |
10 | + | |
11 | +/** | |
12 | + * WebMvcConfigurer | |
13 | + * | |
14 | + * @date 2018-11-30 | |
15 | + */ | |
16 | +@Configuration | |
17 | +@EnableWebMvc | |
18 | +public class ConfigurerAdapter implements WebMvcConfigurer { | |
19 | + | |
20 | + | |
21 | + @Bean | |
22 | + public CorsFilter corsFilter() { | |
23 | + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); | |
24 | + CorsConfiguration config = new CorsConfiguration(); | |
25 | + config.setAllowCredentials(true); | |
26 | + config.addAllowedOrigin("*"); | |
27 | + config.addAllowedHeader("*"); | |
28 | + config.addAllowedMethod("*"); | |
29 | + source.registerCorsConfiguration("/**", config); | |
30 | + return new CorsFilter(source); | |
31 | + } | |
32 | +} | ... | ... |
src/main/java/com/canrd/webmagic/config/MybatisPlusConfig.java
0 → 100644
src/main/java/com/canrd/webmagic/config/RedisConfig.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/config/RedisConfig.java | |
1 | +package com.canrd.webmagic.config; | |
2 | + | |
3 | +import org.springframework.context.annotation.Bean; | |
4 | +import org.springframework.data.redis.connection.RedisConnectionFactory; | |
5 | +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; | |
6 | +import org.springframework.data.redis.core.RedisTemplate; | |
7 | +import org.springframework.data.redis.core.StringRedisTemplate; | |
8 | +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; | |
9 | +import org.springframework.data.redis.serializer.StringRedisSerializer; | |
10 | + | |
11 | +import javax.annotation.Resource; | |
12 | + | |
13 | + | |
14 | +public class RedisConfig { | |
15 | + | |
16 | + | |
17 | + @Resource | |
18 | + private LettuceConnectionFactory lqlcfactory; | |
19 | + | |
20 | + /** | |
21 | + * @param connectionFactory | |
22 | + * @return | |
23 | + */ | |
24 | + @Bean | |
25 | + public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { | |
26 | + RedisTemplate template = new RedisTemplate(); | |
27 | + template.setConnectionFactory(connectionFactory); | |
28 | + return template; | |
29 | + } | |
30 | + | |
31 | + /** | |
32 | + * 配置该bean是为了获取logistics 1.0存入redis的数据 | |
33 | + * 序列化方式保持跟logistics 1.0统一 | |
34 | + * | |
35 | + * @param factory | |
36 | + * @return | |
37 | + */ | |
38 | + @Bean(name = "logisticsRedisTemplate") | |
39 | + public RedisTemplate<String, Object> logisticsRedisTemplate(RedisConnectionFactory factory) { | |
40 | + RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); | |
41 | + redisTemplate.setConnectionFactory(lqlcfactory); | |
42 | + redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); | |
43 | + redisTemplate.setKeySerializer(new StringRedisSerializer()); | |
44 | + return redisTemplate; | |
45 | + } | |
46 | + | |
47 | + @Bean | |
48 | + public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) { | |
49 | + StringRedisTemplate stringRedisTemplate = new StringRedisTemplate(); | |
50 | + // lqlcfactory.setShareNativeConnection(true); | |
51 | + stringRedisTemplate.setConnectionFactory(lqlcfactory); | |
52 | + return stringRedisTemplate; | |
53 | + | |
54 | + } | |
55 | +} | ... | ... |
src/main/java/com/canrd/webmagic/config/RestTemplateConfig.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/config/RestTemplateConfig.java | |
1 | +package com.canrd.webmagic.config; | |
2 | + | |
3 | +import org.springframework.context.annotation.Bean; | |
4 | +import org.springframework.context.annotation.Configuration; | |
5 | +import org.springframework.http.client.ClientHttpRequestFactory; | |
6 | +import org.springframework.http.client.SimpleClientHttpRequestFactory; | |
7 | +import org.springframework.web.client.RestTemplate; | |
8 | + | |
9 | + | |
10 | +@Configuration | |
11 | +public class RestTemplateConfig { | |
12 | + | |
13 | + @Bean | |
14 | + public RestTemplate restTemplate(ClientHttpRequestFactory factory) { | |
15 | + return new RestTemplate(factory); | |
16 | + } | |
17 | + | |
18 | + @Bean | |
19 | + public ClientHttpRequestFactory simpleClientHttpRequestFactory() { | |
20 | + SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); | |
21 | + factory.setReadTimeout(3000); | |
22 | + factory.setConnectTimeout(5000); | |
23 | + return factory; | |
24 | + } | |
25 | + | |
26 | +} | ... | ... |
src/main/java/com/canrd/webmagic/config/WebConfig.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/config/WebConfig.java | |
1 | +package com.canrd.webmagic.config; | |
2 | + | |
3 | +import com.alibaba.fastjson.support.config.FastJsonConfig; | |
4 | +import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; | |
5 | +import lombok.extern.slf4j.Slf4j; | |
6 | +import org.springframework.context.annotation.Configuration; | |
7 | +import org.springframework.http.MediaType; | |
8 | +import org.springframework.http.converter.HttpMessageConverter; | |
9 | +import org.springframework.http.converter.StringHttpMessageConverter; | |
10 | +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; | |
11 | +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | |
12 | + | |
13 | +import java.nio.charset.StandardCharsets; | |
14 | +import java.util.ArrayList; | |
15 | +import java.util.Collections; | |
16 | +import java.util.List; | |
17 | +import java.util.stream.Collectors; | |
18 | + | |
19 | + | |
20 | +@Slf4j | |
21 | +@Configuration | |
22 | +public class WebConfig implements WebMvcConfigurer { | |
23 | + | |
24 | + | |
25 | + @Override | |
26 | + public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { | |
27 | + FastJsonHttpMessageConverter fastConverter = getFastJsonHttpMessageConverter(); | |
28 | + | |
29 | + StringHttpMessageConverter stringHttpMessageConverter = getStringHttpMessageConverter(); | |
30 | + | |
31 | + /** | |
32 | + * 添加StringHttpMessageConverter ,让其转化String。注意顺序,StringHttpMessageConverter 要在FastJsonHttpMessageConverter 之前。 | |
33 | + * | |
34 | + * https://www.cnblogs.com/slankka/p/11437034.html | |
35 | + */ | |
36 | + converters.add(0, fastConverter); | |
37 | + converters.add(0, stringHttpMessageConverter); | |
38 | + log.info("HttpMessageConverter顺序\n{}", converters.stream().map(c -> c.getClass().getName()).collect(Collectors.joining("\n"))); | |
39 | + } | |
40 | + | |
41 | + private static StringHttpMessageConverter getStringHttpMessageConverter() { | |
42 | + StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(); | |
43 | + stringHttpMessageConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.TEXT_PLAIN)); | |
44 | + return stringHttpMessageConverter; | |
45 | + } | |
46 | + | |
47 | + private static FastJsonHttpMessageConverter getFastJsonHttpMessageConverter() { | |
48 | + FastJsonConfig fastJsonConfig = new FastJsonConfig(); | |
49 | + //解决空值序列化的问题,改为不序列化 | |
50 | + /*fastJsonConfig.setSerializeFilters(new PropertyFilter() { | |
51 | + @Override | |
52 | + public boolean apply(Object source,String name, Object value) { | |
53 | + //if(value.getClass().isPrimitive() == null){ | |
54 | + if(value == null){ | |
55 | + return false; | |
56 | + } | |
57 | + return true; | |
58 | + } | |
59 | + });*/ | |
60 | + fastJsonConfig.setCharset(StandardCharsets.UTF_8); | |
61 | + FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter(); | |
62 | + List<MediaType> supportedMediaTypes = new ArrayList<>(); | |
63 | + supportedMediaTypes.add(MediaType.APPLICATION_JSON); | |
64 | + supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8); | |
65 | + supportedMediaTypes.add(MediaType.APPLICATION_ATOM_XML); | |
66 | +// supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED); | |
67 | + supportedMediaTypes.add(MediaType.APPLICATION_OCTET_STREAM); | |
68 | + supportedMediaTypes.add(MediaType.APPLICATION_PDF); | |
69 | + supportedMediaTypes.add(MediaType.APPLICATION_RSS_XML); | |
70 | + supportedMediaTypes.add(MediaType.APPLICATION_XHTML_XML); | |
71 | +// supportedMediaTypes.add(MediaType.APPLICATION_XML); | |
72 | + supportedMediaTypes.add(MediaType.IMAGE_GIF); | |
73 | + supportedMediaTypes.add(MediaType.IMAGE_JPEG); | |
74 | + supportedMediaTypes.add(MediaType.IMAGE_PNG); | |
75 | + supportedMediaTypes.add(MediaType.TEXT_EVENT_STREAM); | |
76 | + supportedMediaTypes.add(MediaType.TEXT_HTML); | |
77 | + supportedMediaTypes.add(MediaType.TEXT_MARKDOWN); | |
78 | + supportedMediaTypes.add(MediaType.TEXT_PLAIN); | |
79 | +// supportedMediaTypes.add(MediaType.TEXT_XML); | |
80 | + fastConverter.setSupportedMediaTypes(supportedMediaTypes); | |
81 | + fastConverter.setFastJsonConfig(fastJsonConfig); | |
82 | + fastConverter.setDefaultCharset(StandardCharsets.UTF_8); | |
83 | + return fastConverter; | |
84 | + } | |
85 | + | |
86 | + @Override | |
87 | + public void addResourceHandlers(ResourceHandlerRegistry registry) { | |
88 | + registry.addResourceHandler("/**").addResourceLocations( | |
89 | + "classpath:/static/"); | |
90 | + registry.addResourceHandler("swagger-ui.html").addResourceLocations( | |
91 | + "classpath:/META-INF/resources/"); | |
92 | + registry.addResourceHandler("/webjars/**").addResourceLocations( | |
93 | + "classpath:/META-INF/resources/webjars/"); | |
94 | + WebMvcConfigurer.super.addResourceHandlers(registry); | |
95 | + } | |
96 | +} | ... | ... |
src/main/java/com/canrd/webmagic/controller/TestController.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/controller/TestController.java | |
1 | +package com.canrd.webmagic.controller; | |
2 | + | |
3 | + | |
4 | +import com.canrd.webmagic.common.constant.ServerResult; | |
5 | +import com.canrd.webmagic.common.jsr303.OperateGroup; | |
6 | +import com.canrd.webmagic.domain.vo.TestQueryVO; | |
7 | +import com.canrd.webmagic.domain.vo.TestVO; | |
8 | +import com.canrd.webmagic.service.TestService; | |
9 | +import org.springframework.validation.annotation.Validated; | |
10 | +import org.springframework.web.bind.annotation.PostMapping; | |
11 | +import org.springframework.web.bind.annotation.RequestBody; | |
12 | +import org.springframework.web.bind.annotation.RequestMapping; | |
13 | +import org.springframework.web.bind.annotation.RestController; | |
14 | + | |
15 | +import javax.annotation.Resource; | |
16 | + | |
17 | +/** | |
18 | + * (Test)表控制层 | |
19 | + * | |
20 | + * @author makejava | |
21 | + * @since 2024-01-12 14:36:56 | |
22 | + */ | |
23 | +@RestController | |
24 | +@RequestMapping("/lift-hub/test") | |
25 | +public class TestController { | |
26 | + /** | |
27 | + * 服务对象 | |
28 | + */ | |
29 | + @Resource | |
30 | + private TestService testService; | |
31 | + | |
32 | + /** | |
33 | + * 分页查询 | |
34 | + * | |
35 | + * @param testQueryVO 查询条件 | |
36 | + * @return 查询结果 | |
37 | + */ | |
38 | + @PostMapping("/list") | |
39 | + public ServerResult list(@RequestBody @Validated({OperateGroup.List.class}) TestQueryVO testQueryVO) { | |
40 | + return testService.list(testQueryVO); | |
41 | + } | |
42 | + | |
43 | + /** | |
44 | + * 通过主键查询单条数据 | |
45 | + * | |
46 | + * @param testQueryVO 查询条件 | |
47 | + * @return 单条数据 | |
48 | + */ | |
49 | + @PostMapping("/query_by_id") | |
50 | + public ServerResult queryById(@RequestBody TestQueryVO testQueryVO) { | |
51 | + return testService.queryById(testQueryVO); | |
52 | + } | |
53 | + | |
54 | + /** | |
55 | + * 新增数据 | |
56 | + * | |
57 | + * @param testVO 数据VO | |
58 | + * @return 新增结果 | |
59 | + */ | |
60 | + @PostMapping("/add") | |
61 | + public ServerResult add(@RequestBody TestVO testVO) { | |
62 | + return testService.add(testVO); | |
63 | + } | |
64 | + | |
65 | + /** | |
66 | + * 编辑数据 | |
67 | + * | |
68 | + * @param testVO 数据VO | |
69 | + * @return 编辑结果 | |
70 | + */ | |
71 | + @PostMapping("/edit") | |
72 | + public ServerResult edit(@RequestBody TestVO testVO) { | |
73 | + return testService.edit(testVO); | |
74 | + } | |
75 | + | |
76 | + /** | |
77 | + * 删除数据 | |
78 | + * | |
79 | + * @param testQueryVO 查询条件 | |
80 | + * @return 删除是否成功 | |
81 | + */ | |
82 | + @PostMapping("/delete_by_id") | |
83 | + public ServerResult deleteById(@RequestBody TestQueryVO testQueryVO) { | |
84 | + return testService.deleteById(testQueryVO); | |
85 | + } | |
86 | + | |
87 | +} | |
88 | + | ... | ... |
src/main/java/com/canrd/webmagic/domain/dto/BaseDO.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/domain/dto/BaseDO.java | |
1 | +package com.canrd.webmagic.domain.dto; | |
2 | + | |
3 | +import com.alibaba.fastjson.annotation.JSONField; | |
4 | +import com.baomidou.mybatisplus.annotation.FieldFill; | |
5 | +import com.baomidou.mybatisplus.annotation.TableField; | |
6 | +import com.baomidou.mybatisplus.annotation.TableLogic; | |
7 | +import com.canrd.webmagic.common.utils.DateUtil; | |
8 | +import com.fasterxml.jackson.annotation.JsonFormat; | |
9 | +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; | |
10 | +import com.fasterxml.jackson.databind.annotation.JsonSerialize; | |
11 | +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; | |
12 | +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; | |
13 | +import lombok.AllArgsConstructor; | |
14 | +import lombok.Data; | |
15 | +import lombok.NoArgsConstructor; | |
16 | +import lombok.experimental.SuperBuilder; | |
17 | +import org.apache.ibatis.type.LocalDateTimeTypeHandler; | |
18 | +import org.springframework.format.annotation.DateTimeFormat; | |
19 | + | |
20 | +import java.io.Serializable; | |
21 | +import java.time.LocalDateTime; | |
22 | + | |
23 | + | |
24 | +@Data | |
25 | +@SuperBuilder(toBuilder = true) | |
26 | +@NoArgsConstructor | |
27 | +@AllArgsConstructor | |
28 | +public class BaseDO implements Serializable { | |
29 | + | |
30 | + /** | |
31 | + * 创建时间 | |
32 | + */ | |
33 | + @TableField(fill = FieldFill.INSERT, typeHandler = LocalDateTimeTypeHandler.class) | |
34 | + @JsonFormat(pattern = DateUtil.DATE_TIME, timezone = DateUtil.Zone.GMT8) | |
35 | + @DateTimeFormat(pattern = DateUtil.DATE_TIME) | |
36 | + @JSONField(format = DateUtil.DATE_TIME) | |
37 | + @JsonDeserialize(using = LocalDateTimeDeserializer.class) | |
38 | + @JsonSerialize(using = LocalDateTimeSerializer.class) | |
39 | + private LocalDateTime createTime; | |
40 | + | |
41 | + /** | |
42 | + * 创建人 | |
43 | + */ | |
44 | + @TableField(fill = FieldFill.INSERT) | |
45 | + private String createBy; | |
46 | + | |
47 | + /** | |
48 | + * 修改时间 | |
49 | + */ | |
50 | + @TableField(fill = FieldFill.INSERT_UPDATE, typeHandler = LocalDateTimeTypeHandler.class) | |
51 | + @JsonFormat(pattern = DateUtil.DATE_TIME, timezone = DateUtil.Zone.GMT8) | |
52 | + @DateTimeFormat(pattern = DateUtil.DATE_TIME) | |
53 | + @JSONField(format = DateUtil.DATE_TIME) | |
54 | + @JsonDeserialize(using = LocalDateTimeDeserializer.class) | |
55 | + @JsonSerialize(using = LocalDateTimeSerializer.class) | |
56 | + private LocalDateTime modifyTime; | |
57 | + | |
58 | + /** | |
59 | + * 修改人 | |
60 | + */ | |
61 | + @TableField(fill = FieldFill.INSERT_UPDATE) | |
62 | + private String modifyBy; | |
63 | + | |
64 | + /** | |
65 | + * 是否可用 10-可用 20-删除 30-禁用 | |
66 | + */ | |
67 | + @TableLogic | |
68 | + @TableField(fill = FieldFill.INSERT) | |
69 | + private Integer enableFlag; | |
70 | + | |
71 | + /** | |
72 | + * 版本号--乐观锁预留字段 | |
73 | + */ | |
74 | + private Integer version; | |
75 | +} | ... | ... |
src/main/java/com/canrd/webmagic/domain/dto/TestDO.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/domain/dto/TestDO.java | |
1 | +package com.canrd.webmagic.domain.dto; | |
2 | + | |
3 | + | |
4 | +import com.baomidou.mybatisplus.annotation.TableName; | |
5 | +import lombok.*; | |
6 | +import lombok.experimental.SuperBuilder; | |
7 | + | |
8 | +import java.io.Serializable; | |
9 | + | |
10 | +/** | |
11 | + * (Test)实体类 | |
12 | + * | |
13 | + * @author makejava | |
14 | + * @since 2024-01-12 14:36:56 | |
15 | + */ | |
16 | +@TableName("test") | |
17 | +@Data | |
18 | +@AllArgsConstructor | |
19 | +@ToString | |
20 | +@NoArgsConstructor | |
21 | +@EqualsAndHashCode(callSuper = false) | |
22 | +@SuperBuilder | |
23 | +public class TestDO extends BaseDO implements Serializable { | |
24 | + private static final long serialVersionUID = 856841241099412904L; | |
25 | + | |
26 | + private Integer id; | |
27 | + | |
28 | + private String username; | |
29 | + | |
30 | + private String email; | |
31 | + | |
32 | +} | ... | ... |
src/main/java/com/canrd/webmagic/domain/vo/BasePageVO.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/domain/vo/BasePageVO.java | |
1 | +package com.canrd.webmagic.domain.vo; | |
2 | + | |
3 | +import com.canrd.webmagic.common.constant.Constant; | |
4 | +import com.canrd.webmagic.common.jsr303.OperateGroup; | |
5 | +import com.fasterxml.jackson.annotation.JsonInclude; | |
6 | +import lombok.AllArgsConstructor; | |
7 | +import lombok.Data; | |
8 | +import lombok.NoArgsConstructor; | |
9 | +import lombok.experimental.SuperBuilder; | |
10 | + | |
11 | +import javax.validation.constraints.Max; | |
12 | +import javax.validation.constraints.Min; | |
13 | +import javax.validation.constraints.NotNull; | |
14 | + | |
15 | + | |
16 | +@SuperBuilder(toBuilder = true) | |
17 | +@Data | |
18 | +@NoArgsConstructor | |
19 | +@AllArgsConstructor | |
20 | +public class BasePageVO { | |
21 | + | |
22 | + /** | |
23 | + * 页码 | |
24 | + */ | |
25 | + @JsonInclude(JsonInclude.Include.NON_NULL) | |
26 | + @NotNull(message = "页码不能为空", groups = {OperateGroup.List.class}) | |
27 | + @Min(value = Constant.ONE, message = "页码不能小于1", groups = {OperateGroup.List.class}) | |
28 | + private Integer current = 1; | |
29 | + /** | |
30 | + * 页 | |
31 | + */ | |
32 | + @JsonInclude(JsonInclude.Include.NON_NULL) | |
33 | + @NotNull(message = "每页大小不能为空", groups = {OperateGroup.List.class}) | |
34 | + @Min(value = 1, message = "每页大小不能小于1", groups = {OperateGroup.List.class}) | |
35 | + @Max(value = 5000, message = "每页大小不能大于5000", groups = {OperateGroup.List.class}) | |
36 | + private Integer size = 10; | |
37 | + | |
38 | + /** | |
39 | + * 总数 | |
40 | + */ | |
41 | + @JsonInclude(JsonInclude.Include.NON_NULL) | |
42 | + private Integer total; | |
43 | +} | ... | ... |
src/main/java/com/canrd/webmagic/domain/vo/TestQueryVO.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/domain/vo/TestQueryVO.java | |
1 | +package com.canrd.webmagic.domain.vo; | |
2 | + | |
3 | +import lombok.*; | |
4 | +import lombok.experimental.SuperBuilder; | |
5 | + | |
6 | +import java.io.Serializable; | |
7 | +import java.util.List; | |
8 | + | |
9 | +/** | |
10 | + * @author makejava | |
11 | + * @since 2024-01-12 14:36:56 | |
12 | + */ | |
13 | +@Data | |
14 | +@AllArgsConstructor | |
15 | +@ToString | |
16 | +@NoArgsConstructor | |
17 | +@EqualsAndHashCode(callSuper = false) | |
18 | +@SuperBuilder | |
19 | +public class TestQueryVO extends BasePageVO implements Serializable { | |
20 | + private static final long serialVersionUID = 542072710112757366L; | |
21 | + | |
22 | + private List<Long> ids; | |
23 | + | |
24 | + | |
25 | + private Integer id; | |
26 | + | |
27 | + private String username; | |
28 | + | |
29 | + private String email; | |
30 | + | |
31 | + | |
32 | +} | |
33 | + | ... | ... |
src/main/java/com/canrd/webmagic/domain/vo/TestVO.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/domain/vo/TestVO.java | |
1 | +package com.canrd.webmagic.domain.vo; | |
2 | + | |
3 | + | |
4 | +import lombok.*; | |
5 | +import lombok.experimental.SuperBuilder; | |
6 | + | |
7 | +import java.io.Serializable; | |
8 | + | |
9 | +/** | |
10 | + * (Test)实体类 | |
11 | + * | |
12 | + * @author makejava | |
13 | + * @since 2024-01-12 14:36:56 | |
14 | + */ | |
15 | +@Data | |
16 | +@AllArgsConstructor | |
17 | +@ToString | |
18 | +@NoArgsConstructor | |
19 | +@EqualsAndHashCode(callSuper = false) | |
20 | +@SuperBuilder | |
21 | +public class TestVO implements Serializable { | |
22 | + private static final long serialVersionUID = 257625796831027116L; | |
23 | + | |
24 | + private Integer id; | |
25 | + | |
26 | + private String username; | |
27 | + | |
28 | + private String email; | |
29 | + | |
30 | + | |
31 | +} | ... | ... |
src/main/java/com/canrd/webmagic/mapper/TestMapper.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/mapper/TestMapper.java | |
1 | +package com.canrd.webmagic.mapper; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
4 | +import com.canrd.webmagic.domain.dto.TestDO; | |
5 | + | |
6 | +/** | |
7 | + * (Test)表数据库访问层 | |
8 | + * | |
9 | + * @author makejava | |
10 | + * @since 2024-01-12 14:36:56 | |
11 | + */ | |
12 | +public interface TestMapper extends BaseMapper<TestDO> { | |
13 | + | |
14 | + | |
15 | +} | |
16 | + | ... | ... |
src/main/java/com/canrd/webmagic/processor/BaiduHotSearchPageProcessor.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/processor/BaiduHotSearchPageProcessor.java | |
1 | +package com.canrd.webmagic.processor; | |
2 | + | |
3 | +import us.codecraft.webmagic.Page; | |
4 | +import us.codecraft.webmagic.Site; | |
5 | +import us.codecraft.webmagic.Spider; | |
6 | +import us.codecraft.webmagic.processor.PageProcessor; | |
7 | +import us.codecraft.webmagic.selector.Selectable; | |
8 | +import us.codecraft.webmagic.selector.XpathSelector; | |
9 | + | |
10 | +import java.util.List; | |
11 | + | |
12 | +/** | |
13 | + * @author: xms | |
14 | + * @description: TODO | |
15 | + * @date: 2024/4/1 14:19 | |
16 | + * @version: 1.0 | |
17 | + */ | |
18 | +public class BaiduHotSearchPageProcessor implements PageProcessor { | |
19 | + | |
20 | + // 抓取网站的相关配置,包括编码、抓取间隔、重试次数等 | |
21 | + private Site site = Site.me().setRetryTimes(3).setSleepTime(100); | |
22 | + | |
23 | + /** | |
24 | + * 定制爬虫逻辑的核心接口,在这里编写抽取逻辑 | |
25 | + * | |
26 | + * @param page | |
27 | + */ | |
28 | + @Override | |
29 | + public void process(Page page) { | |
30 | + | |
31 | + System.out.println(page.getHtml()); | |
32 | + /** | |
33 | + * 通过page.getHtml()可以获取到main函数中Spider.create(new BaiduHotSearchPageProcessor()).addUrl中的地址的网页内容 | |
34 | + * 1、通过$或css()方法获取到该page html下某元素dom | |
35 | + */ | |
36 | + Selectable selectable = page.getHtml().$(".theme-hot").select( | |
37 | + new XpathSelector("a[@class='item-wrap_2oCLZ']") | |
38 | + ); | |
39 | + List<Selectable> nodes = selectable.nodes(); | |
40 | + | |
41 | + /** | |
42 | + * 获取到指定的dom后,从这些dom中提取元素内容。 | |
43 | + */ | |
44 | + System.out.println("今日百度热搜:"); | |
45 | + for (int i = 1; i <= nodes.size() - 1; i++) { | |
46 | + Selectable node = nodes.get(i); | |
47 | + String link = node.$(".item-wrap_2oCLZ", "href").get(); | |
48 | + String title = node.$(".c-single-text-ellipsis", "text").get(); | |
49 | + System.out.printf("%d、%s,访问地址:%s%n", i, title, link); | |
50 | + } | |
51 | + } | |
52 | + | |
53 | + @Override | |
54 | + public Site getSite() { | |
55 | + return site; | |
56 | + } | |
57 | + | |
58 | + public static void main(String[] args) { | |
59 | + // 创建一个Spider,并把我们的处理器放进去 | |
60 | + Spider.create(new BaiduHotSearchPageProcessor()) | |
61 | + // 添加这个Spider要爬取的网页地址 | |
62 | + .addUrl("https://top.baidu.com/board?platform=pc&sa=pcindex_entry") | |
63 | + // 开启5个线程执行,并开始爬取 | |
64 | + .thread(5).run(); | |
65 | + } | |
66 | +} | |
0 | 67 | \ No newline at end of file | ... | ... |
src/main/java/com/canrd/webmagic/processor/GithubRepoPageProcessor.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/processor/GithubRepoPageProcessor.java | |
1 | +package com.canrd.webmagic.processor; | |
2 | + | |
3 | +import us.codecraft.webmagic.Page; | |
4 | +import us.codecraft.webmagic.Site; | |
5 | +import us.codecraft.webmagic.Spider; | |
6 | +import us.codecraft.webmagic.processor.PageProcessor; | |
7 | + | |
8 | +/** | |
9 | + * @author: xms | |
10 | + * @description: TODO | |
11 | + * @date: 2024/4/1 12:11 | |
12 | + * @version: 1.0 | |
13 | + */ | |
14 | +public class GithubRepoPageProcessor implements PageProcessor { | |
15 | + | |
16 | + private Site site = Site.me().setRetryTimes(3).setSleepTime(1000); | |
17 | + | |
18 | + @Override | |
19 | + public void process(Page page) { | |
20 | + page.addTargetRequests(page.getHtml().links().regex("(https://github\\.com/\\w+/\\w+)").all()); | |
21 | + page.putField("author", page.getUrl().regex("https://github\\.com/(\\w+)/.*").toString()); | |
22 | + page.putField("name", page.getHtml().xpath("//h1[@class='public']/strong/a/text()").toString()); | |
23 | + if (page.getResultItems().get("name")==null){ | |
24 | + //skip this page | |
25 | + page.setSkip(true); | |
26 | + } | |
27 | + page.putField("readme", page.getHtml().xpath("//div[@id='readme']/tidyText()")); | |
28 | + } | |
29 | + | |
30 | + @Override | |
31 | + public Site getSite() { | |
32 | + return site; | |
33 | + } | |
34 | + | |
35 | + public static void main(String[] args) { | |
36 | + Spider.create(new GithubRepoPageProcessor()).addUrl("https://github.com/code4craft").thread(5).run(); | |
37 | + } | |
38 | +} | |
0 | 39 | \ No newline at end of file | ... | ... |
src/main/java/com/canrd/webmagic/processor/NatureSearchPageProcessor.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/processor/NatureSearchPageProcessor.java | |
1 | +package com.canrd.webmagic.processor; | |
2 | + | |
3 | +import org.jsoup.nodes.Element; | |
4 | +import org.jsoup.nodes.TextNode; | |
5 | +import us.codecraft.webmagic.Page; | |
6 | +import us.codecraft.webmagic.Site; | |
7 | +import us.codecraft.webmagic.Spider; | |
8 | +import us.codecraft.webmagic.processor.PageProcessor; | |
9 | +import us.codecraft.webmagic.selector.HtmlNode; | |
10 | +import us.codecraft.webmagic.selector.Selectable; | |
11 | +import us.codecraft.webmagic.selector.XpathSelector; | |
12 | + | |
13 | +import java.util.List; | |
14 | + | |
15 | +/** | |
16 | + * @author: xms | |
17 | + * @description: TODO | |
18 | + * @date: 2024/4/1 14:19 | |
19 | + * @version: 1.0 | |
20 | + */ | |
21 | +public class NatureSearchPageProcessor implements PageProcessor { | |
22 | + | |
23 | + // 抓取网站的相关配置,包括编码、抓取间隔、重试次数等 | |
24 | + private Site site = Site.me().setRetryTimes(3).setSleepTime(100); | |
25 | + | |
26 | + /** | |
27 | + * 定制爬虫逻辑的核心接口,在这里编写抽取逻辑 | |
28 | + * | |
29 | + * @param page | |
30 | + */ | |
31 | + @Override | |
32 | + public void process(Page page) { | |
33 | + | |
34 | + System.out.println(page.getHtml()); | |
35 | + /** | |
36 | + * 通过page.getHtml()可以获取到main函数中Spider.create(new BaiduHotSearchPageProcessor()).addUrl中的地址的网页内容 | |
37 | + * 1、通过$或css()方法获取到该page html下某元素dom | |
38 | + */ | |
39 | + Selectable selectable = page.getHtml().$(".app-article-list-row").select( | |
40 | + new XpathSelector("li[@class='app-article-list-row__item']") | |
41 | + ); | |
42 | + List<Selectable> nodes = selectable.nodes(); | |
43 | + | |
44 | + /** | |
45 | + * 获取到指定的dom后,从这些dom中提取元素内容。 | |
46 | + */ | |
47 | + System.out.println("今日百度热搜:"); | |
48 | + for (int i = 1; i <= nodes.size() - 1; i++) { | |
49 | + Selectable node = nodes.get(i).$(".u-full-height").nodes().get(2).nodes().get(0).$(".u-full-height").select(new XpathSelector("a[@class='c-card__link u-link-inherit']")).nodes().get(0); | |
50 | + String link = node.$("a","href").get(); | |
51 | + String title = node.$("a","text").get(); | |
52 | + System.out.printf("%d、%s,访问地址:%s%n", i, title, link); | |
53 | + } | |
54 | + } | |
55 | + | |
56 | + @Override | |
57 | + public Site getSite() { | |
58 | + return site; | |
59 | + } | |
60 | + | |
61 | + public static void main(String[] args) { | |
62 | + // 创建一个Spider,并把我们的处理器放进去 | |
63 | + Spider.create(new NatureSearchPageProcessor()) | |
64 | + // 添加这个Spider要爬取的网页地址 | |
65 | + .addUrl("https://www.nature.com/search?q=battery&page=1") | |
66 | + // 开启5个线程执行,并开始爬取 | |
67 | + .thread(5).run(); | |
68 | + } | |
69 | +} | |
0 | 70 | \ No newline at end of file | ... | ... |
src/main/java/com/canrd/webmagic/service/TestService.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/service/TestService.java | |
1 | +package com.canrd.webmagic.service; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.extension.service.IService; | |
4 | +import com.canrd.webmagic.common.constant.ServerResult; | |
5 | +import com.canrd.webmagic.domain.dto.TestDO; | |
6 | +import com.canrd.webmagic.domain.vo.TestQueryVO; | |
7 | +import com.canrd.webmagic.domain.vo.TestVO; | |
8 | + | |
9 | +/** | |
10 | + * (Test)表服务接口 | |
11 | + * | |
12 | + * @author makejava | |
13 | + * @since 2024-01-12 14:36:57 | |
14 | + */ | |
15 | +public interface TestService extends IService<TestDO> { | |
16 | + | |
17 | + /** | |
18 | + * 通过ID查询单条数据 | |
19 | + * | |
20 | + * @param testQueryVO 主键 | |
21 | + * @return 实例对象 | |
22 | + */ | |
23 | + ServerResult queryById(TestQueryVO testQueryVO); | |
24 | + | |
25 | + /** | |
26 | + * 分页查询 | |
27 | + * | |
28 | + * @param testQueryVO 筛选条件 | |
29 | + * @return 查询结果 | |
30 | + */ | |
31 | + ServerResult list(TestQueryVO testQueryVO); | |
32 | + | |
33 | + /** | |
34 | + * 新增数据 | |
35 | + * | |
36 | + * @param testVO 数据VO | |
37 | + * @return 新增结果 | |
38 | + */ | |
39 | + ServerResult add(TestVO testVO); | |
40 | + | |
41 | + /** | |
42 | + * 修改数据 | |
43 | + * | |
44 | + * @param testVO 数据VO | |
45 | + * @return 编辑结果 | |
46 | + */ | |
47 | + ServerResult edit(TestVO testVO); | |
48 | + | |
49 | + /** | |
50 | + * 通过主键删除数据 | |
51 | + * | |
52 | + * @param testQueryVO 筛选条件 | |
53 | + * @return 是否成功 | |
54 | + */ | |
55 | + ServerResult deleteById(TestQueryVO testQueryVO); | |
56 | + | |
57 | +} | ... | ... |
src/main/java/com/canrd/webmagic/service/impl/TestServiceImpl.java
0 → 100644
1 | +++ a/src/main/java/com/canrd/webmagic/service/impl/TestServiceImpl.java | |
1 | +package com.canrd.webmagic.service.impl; | |
2 | + | |
3 | +import cn.hutool.core.bean.BeanUtil; | |
4 | +import cn.hutool.core.collection.CollUtil; | |
5 | +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |
6 | +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | |
7 | +import com.baomidou.mybatisplus.core.metadata.IPage; | |
8 | +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | |
9 | +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | |
10 | +import com.canrd.webmagic.common.constant.Constant; | |
11 | +import com.canrd.webmagic.common.constant.ServerResult; | |
12 | +import com.canrd.webmagic.common.utils.PageUtils; | |
13 | +import com.canrd.webmagic.domain.dto.TestDO; | |
14 | +import com.canrd.webmagic.domain.vo.TestQueryVO; | |
15 | +import com.canrd.webmagic.domain.vo.TestVO; | |
16 | +import com.canrd.webmagic.mapper.TestMapper; | |
17 | +import com.canrd.webmagic.service.TestService; | |
18 | +import lombok.extern.slf4j.Slf4j; | |
19 | +import org.springframework.stereotype.Service; | |
20 | + | |
21 | +import java.util.List; | |
22 | +import java.util.Objects; | |
23 | + | |
24 | +/** | |
25 | + * (Test)表服务实现类 | |
26 | + * | |
27 | + * @author makejava | |
28 | + * @since 2024-01-12 14:36:57 | |
29 | + */ | |
30 | +@Slf4j | |
31 | +@Service | |
32 | +public class TestServiceImpl extends ServiceImpl<TestMapper, TestDO> implements TestService { | |
33 | + | |
34 | + | |
35 | + /** | |
36 | + * 通过ID查询单条数据 | |
37 | + * <p> | |
38 | + * testQueryVO 主键 | |
39 | + * | |
40 | + * @return 实例对象 | |
41 | + */ | |
42 | + @Override | |
43 | + public ServerResult queryById(TestQueryVO testQueryVO) { | |
44 | + if (Objects.isNull(testQueryVO.getId())) { | |
45 | + return ServerResult.fail("id 不能为空"); | |
46 | + } | |
47 | + TestDO TestDo = getById(testQueryVO.getId()); | |
48 | + if (Objects.isNull(TestDo)) { | |
49 | + return ServerResult.success(null); | |
50 | + } | |
51 | + return ServerResult.success(BeanUtil.copyProperties(TestDo, TestVO.class)); | |
52 | + } | |
53 | + | |
54 | + /** | |
55 | + * 分页查询 | |
56 | + * | |
57 | + * @param testQueryVO 筛选条件 | |
58 | + * @return 查询结果 | |
59 | + */ | |
60 | + @Override | |
61 | + public ServerResult list(TestQueryVO testQueryVO) { | |
62 | + | |
63 | + LambdaQueryWrapper<TestDO> queryWapper = new LambdaQueryWrapper<TestDO>() | |
64 | + .eq(TestDO::getEnableFlag, Constant.ENABLE_TEN) | |
65 | + .orderByDesc(TestDO::getId); | |
66 | + Page page = new Page<>(testQueryVO.getCurrent(), testQueryVO.getSize()); | |
67 | + IPage<TestDO> iPage = page(page, queryWapper); | |
68 | + testQueryVO.setTotal(Long.valueOf(iPage.getTotal()).intValue()); | |
69 | + return ServerResult.success(PageUtils.getPageReturn(iPage.getRecords(), testQueryVO)); | |
70 | + } | |
71 | + | |
72 | + /** | |
73 | + * 新增数据 | |
74 | + * | |
75 | + * @param testVO 实例对象 | |
76 | + * @return 实例对象 | |
77 | + */ | |
78 | + @Override | |
79 | + public ServerResult add(TestVO testVO) { | |
80 | + //todo 校验 | |
81 | + if (Objects.nonNull(testVO.getId())) { | |
82 | + testVO.setId(null); | |
83 | + } | |
84 | + TestDO testDo = BeanUtil.copyProperties(testVO, TestDO.class); | |
85 | + | |
86 | + save(testDo); | |
87 | + | |
88 | + return ServerResult.success(); | |
89 | + } | |
90 | + | |
91 | + /** | |
92 | + * 修改数据 | |
93 | + * | |
94 | + * @param testVO 实例对象 | |
95 | + * @return 实例对象 | |
96 | + */ | |
97 | + @Override | |
98 | + public ServerResult edit(TestVO testVO) { | |
99 | + //todo 校验 | |
100 | + if (Objects.isNull(testVO.getId())) { | |
101 | + return ServerResult.fail("id 不能为空"); | |
102 | + } | |
103 | + TestDO testDo = BeanUtil.copyProperties(testVO, TestDO.class); | |
104 | + | |
105 | + updateById(testDo); | |
106 | + | |
107 | + return ServerResult.success(); | |
108 | + } | |
109 | + | |
110 | + /** | |
111 | + * 通过主键删除数据 | |
112 | + * | |
113 | + * @param testQueryVO 筛选条件 | |
114 | + * @return 是否成功 | |
115 | + */ | |
116 | + @Override | |
117 | + public ServerResult deleteById(TestQueryVO testQueryVO) { | |
118 | + List<Long> ids = testQueryVO.getIds(); | |
119 | + if (CollUtil.isEmpty(ids)) { | |
120 | + return ServerResult.fail("ids 参数不能为空"); | |
121 | + } | |
122 | + List<TestDO> testList = listByIds(ids); | |
123 | + if (CollUtil.isEmpty(testList)) { | |
124 | + return ServerResult.success(); | |
125 | + } | |
126 | + //todo 校验是否可以逻辑删除 | |
127 | + LambdaUpdateWrapper<TestDO> updateWrapper = new LambdaUpdateWrapper<TestDO>() | |
128 | + .in(TestDO::getId, ids) | |
129 | + .set(TestDO::getEnableFlag, Constant.UNABLE_TWENTY); | |
130 | + update(updateWrapper); | |
131 | + return ServerResult.success(); | |
132 | + } | |
133 | +} | ... | ... |
src/main/resources/application-local.yml
0 → 100644
1 | +++ a/src/main/resources/application-local.yml | |
1 | +mybatis-plus: | |
2 | + configuration: | |
3 | + cache-enabled: false | |
4 | + call-setters-on-nulls: true | |
5 | + jdbc-type-for-null: 'null' | |
6 | + map-underscore-to-camel-case: true | |
7 | + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl | |
8 | + global-config: | |
9 | + db-config: | |
10 | + capital-mode: false | |
11 | + field-strategy: NOT_NULL | |
12 | + id-type: AUTO | |
13 | + logic-delete-field: enable_flag | |
14 | + logic-delete-value: 20 | |
15 | + logic-not-delete-value: 10 | |
16 | + mapper-locations: classpath:/mapper/**.xml | |
17 | + type-aliases-package: com.order.erp.**.dto | |
18 | +#spring: | |
19 | +# datasource: | |
20 | +# dynamic: | |
21 | +# primary: overtime #设置默认的数据源或者数据源组,默认值即为master | |
22 | +# strict: false #设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候会抛出异常,不启动则使用默认数据源. | |
23 | +# datasource: | |
24 | +# wms_warehouse: | |
25 | +# url: jdbc:mysql://127.0.0.1:3306/overtime?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&useSSL=false&autoReconnect=true&failOverReadOnly=false&maxReconnects=10&allowMultiQueries=true&useAffectedRows=true&autoReconnectForPools=true&rewriteBatchedStatements=true | |
26 | +# username: root | |
27 | +# password: root | |
28 | +# driver-class-name: com.mysql.cj.jdbc.Driver # 3.2.0开始支持SPI可省略此配置 | |
29 | +# druid: | |
30 | +# initial-size: 5 | |
31 | +# max-active: 20 | |
32 | +# max-evictable-idle-time-millis: 300000 | |
33 | +# max-wait: 60000 | |
34 | +# min-evictable-idle-time-millis: 300000 | |
35 | +# min-idle: 5 | |
36 | +# time-between-eviction-runs-millis: 60000 | |
37 | +# type: com.alibaba.druid.pool.DruidDataSource | |
38 | +spring: | |
39 | + servlet: | |
40 | + multipart: | |
41 | + enabled: true | |
42 | + max-file-size: 100MB | |
43 | + max-request-size: 20MB | |
44 | + file-size-threshold: 20MB | |
45 | + datasource: | |
46 | + db-type: com.alibaba.druid.pool.DruidDataSource | |
47 | + driverClassName: com.mysql.cj.jdbc.Driver | |
48 | + initial-size: 5 | |
49 | + max-active: 30 | |
50 | + max-wait: 30000 | |
51 | + min-idle: 5 | |
52 | + #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 | |
53 | + timeBetweenEvictionRunsMillis: 30000 | |
54 | + #配置一个连接在池中最小生存的时间,单位是毫秒,30000=30s | |
55 | + minEvictableIdleTimeMillis: 30000 | |
56 | + validationQuery: SELECT 'x' | |
57 | + testWhileIdle: true | |
58 | + testOnBorrow: true | |
59 | + testOnReturn: true | |
60 | + password: canrd@2024 | |
61 | + time-between-eviction-runs-millis: 1000 | |
62 | + url: jdbc:mysql://39.108.227.113:3307/order-erp1?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&useSSL=false&autoReconnect=true&failOverReadOnly=false&maxReconnects=10&allowMultiQueries=true&useAffectedRows=true&autoReconnectForPools=true | |
63 | + username: root | |
64 | + redis: | |
65 | + database: 0 | |
66 | + host: 39.108.227.113 | |
67 | + lettuce: | |
68 | + pool: | |
69 | + max-active: 2000 | |
70 | + max-idle: 10 | |
71 | + max-wait: -1 | |
72 | + min-idle: 3 | |
73 | + time-between-eviction-runs: 100 | |
74 | + password: '' | |
75 | + port: 6379 | |
76 | + timeout: 2000 | |
77 | + mail: | |
78 | + # 配置 SMTP 服务器地址 | |
79 | + host: smtp.mxhichina.com | |
80 | + # 发送者邮箱,已开通POP3/SMTP服务的邮箱,也就是你自己的 | |
81 | + username: system@canrd.com | |
82 | + # 配置密码,注意不是真正的密码,而是刚刚申请到的授权码 | |
83 | + password: Kelude2015 | |
84 | + # 邮件接收者 | |
85 | + mailRecipient: #邮件接收者邮箱 | |
86 | + # 端口号465或587(QQ邮箱发送邮件仅支持587端口协议) | |
87 | + port: 587 | |
88 | + # 默认的邮件编码为UTF-8 | |
89 | + default-encoding: UTF-8 | |
90 | + # 配置SSL 加密工厂 | |
91 | + properties: | |
92 | + mail: | |
93 | + smtp: | |
94 | + socketFactoryClass: javax.net.ssl.SSLSocketFactory | |
95 | + #表示开启 DEBUG 模式,这样,邮件发送过程的日志会在控制台打印出来,方便排查错误 | |
96 | + debug: true | |
97 | + | |
98 | + freemarker: | |
99 | + template-loader-path: classpath:/template/ | |
100 | + suffix: .flt | |
101 | + enabled: true | |
102 | + cache: false | |
103 | + charset: UTF-8 | |
104 | + content-type: text/html | |
105 | + allow-request-override: false | |
106 | + check-template-location: true | |
107 | + expose-request-attributes: false | |
108 | + expose-session-attributes: false | |
109 | + expose-spring-macro-helpers: false | |
110 | + | |
111 | + | |
112 | +logging: | |
113 | + config: classpath:log4j2-dev.xml | |
114 | + | |
115 | +#登录图形验证码有效时间/分钟 | |
116 | +loginCode: | |
117 | + expiration: 2 | |
118 | + | |
119 | +#密码加密传输,前端公钥加密,后端私钥解密 | |
120 | +rsa: | |
121 | + private_key: MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A== | |
122 | + | |
123 | + | |
124 | +#jwt | |
125 | +jwt: | |
126 | + header: Authorization | |
127 | + # 令牌前缀 | |
128 | + token-start-with: Bearer | |
129 | + # 必须使用最少88位的Base64对该令牌进行编码 | |
130 | + base64-secret: ZmQ0ZGI5NjQ0MDQwY2I4MjMxY2Y3ZmI3MjdhN2ZmMjNhODViOTg1ZGE0NTBjMGM4NDA5NzYxMjdjOWMwYWRmZTBlZjlhNGY3ZTg4Y2U3YTE1ODVkZDU5Y2Y3OGYwZWE1NzUzNWQ2YjFjZDc0NGMxZWU2MmQ3MjY1NzJmNTE0MzI= | |
131 | + # 令牌过期时间 此处单位/毫秒 ,默认2小时,可在此网站生成 https://www.convertworld.com/zh-hans/time/milliseconds.html | |
132 | + token-validity-in-seconds: 720000000 | |
133 | + # 在线用户key | |
134 | + online-key: online-token | |
135 | + # 验证码 | |
136 | + code-key: code-key | |
137 | + | |
138 | +outsys: | |
139 | + sms: | |
140 | + regionId: cn-hangzhou | |
141 | + accessKeyId: LTAIZCPI7OaWud0m | |
142 | + secret: nvtGeScBwRztGeoj8WSp5OWalalgpK | |
143 | + domain: dysmsapi.aliyuncs.com | |
144 | + version: 2017-05-25 | |
145 | + action: SendSms | |
146 | + signName: canrd | |
147 | + templateCode: SMS_173005236 | |
148 | + email: | |
149 | + host: http://core.canrd.com | |
150 | + passwordRecoverKey: http://www.canrd.com/canrd/shop/member/passwordModify | |
151 | + | |
152 | + | |
153 | + | |
154 | +system: | |
155 | + isLoginFailureLock: true | |
156 | + loginFailureLockTime: 5 | |
157 | + loginFailureLockCount: 3 | |
158 | + | |
159 | +openai: | |
160 | + token: Bearer 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 | |
161 | + | |
162 | +# 文件存储路径 | |
163 | +file: | |
164 | + path: /home/canrd/order-erp/files/ | |
165 | + host: http://39.108.227.113 | |
166 | + avatar: /home/order-erp/avatar/ | |
167 | + # 文件大小 /M | |
168 | + maxSize: 100 | |
169 | + avatarMaxSize: 5 | |
170 | + | |
171 | +# 阿里pss图片服务 | |
172 | +oss: | |
173 | + endpoint: https://oss-cn-qingdao.aliyuncs.com | |
174 | + accessKeyId: LTAIZCPI7OaWud0m | |
175 | + accessKeySecret: nvtGeScBwRztGeoj8WSp5OWalalgpK | |
176 | + bucket: order-erp | |
177 | + | |
178 | + | |
179 | +db: | |
180 | + mysql: | |
181 | + ip: 39.108.227.113 | |
182 | + port: 3307 | |
183 | + user: root | |
184 | + password: 123456 | |
185 | + databaseName: order-erp | |
186 | + savePath: /home/canrd/order-erp/files/backup/ | ... | ... |
src/main/resources/application-prod.yml
0 → 100644
1 | +++ a/src/main/resources/application-prod.yml | |
1 | +mybatis-plus: | |
2 | + configuration: | |
3 | + cache-enabled: false | |
4 | + call-setters-on-nulls: true | |
5 | + jdbc-type-for-null: 'null' | |
6 | + map-underscore-to-camel-case: true | |
7 | + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl | |
8 | + global-config: | |
9 | + db-config: | |
10 | + capital-mode: false | |
11 | + field-strategy: NOT_NULL | |
12 | + id-type: AUTO | |
13 | + logic-delete-field: enable_flag | |
14 | + logic-delete-value: 20 | |
15 | + logic-not-delete-value: 10 | |
16 | + mapper-locations: classpath:/mapper/**.xml | |
17 | + type-aliases-package: com.order.erp.**.dto | |
18 | +#spring: | |
19 | +# datasource: | |
20 | +# dynamic: | |
21 | +# primary: overtime #设置默认的数据源或者数据源组,默认值即为master | |
22 | +# strict: false #设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候会抛出异常,不启动则使用默认数据源. | |
23 | +# datasource: | |
24 | +# wms_warehouse: | |
25 | +# url: jdbc:mysql://127.0.0.1:3306/overtime?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&useSSL=false&autoReconnect=true&failOverReadOnly=false&maxReconnects=10&allowMultiQueries=true&useAffectedRows=true&autoReconnectForPools=true&rewriteBatchedStatements=true | |
26 | +# username: root | |
27 | +# password: root | |
28 | +# driver-class-name: com.mysql.cj.jdbc.Driver # 3.2.0开始支持SPI可省略此配置 | |
29 | +# druid: | |
30 | +# initial-size: 5 | |
31 | +# max-active: 20 | |
32 | +# max-evictable-idle-time-millis: 300000 | |
33 | +# max-wait: 60000 | |
34 | +# min-evictable-idle-time-millis: 300000 | |
35 | +# min-idle: 5 | |
36 | +# time-between-eviction-runs-millis: 60000 | |
37 | +# type: com.alibaba.druid.pool.DruidDataSource | |
38 | +spring: | |
39 | + servlet: | |
40 | + multipart: | |
41 | + enabled: true | |
42 | + max-file-size: 100MB | |
43 | + max-request-size: 20MB | |
44 | + file-size-threshold: 20MB | |
45 | + datasource: | |
46 | + db-type: com.alibaba.druid.pool.DruidDataSource | |
47 | + driverClassName: com.mysql.cj.jdbc.Driver | |
48 | + initial-size: 5 | |
49 | + max-active: 30 | |
50 | + max-wait: 30000 | |
51 | + min-idle: 5 | |
52 | + #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 | |
53 | + timeBetweenEvictionRunsMillis: 30000 | |
54 | + #配置一个连接在池中最小生存的时间,单位是毫秒,30000=30s | |
55 | + minEvictableIdleTimeMillis: 30000 | |
56 | + validationQuery: SELECT 'x' | |
57 | + testWhileIdle: true | |
58 | + testOnBorrow: true | |
59 | + testOnReturn: true | |
60 | + password: 123456 | |
61 | + time-between-eviction-runs-millis: 1000 | |
62 | + url: jdbc:mysql://172.17.0.1:3306/order-erp?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&useSSL=false&autoReconnect=true&failOverReadOnly=false&maxReconnects=10&allowMultiQueries=true&useAffectedRows=true&autoReconnectForPools=true | |
63 | + username: root | |
64 | + redis: | |
65 | + database: 0 | |
66 | + host: 172.17.0.1 | |
67 | + lettuce: | |
68 | + pool: | |
69 | + max-active: 2000 | |
70 | + max-idle: 10 | |
71 | + max-wait: -1 | |
72 | + min-idle: 3 | |
73 | + time-between-eviction-runs: 100 | |
74 | + password: '' | |
75 | + port: 6379 | |
76 | + timeout: 2000 | |
77 | + mail: | |
78 | + # 配置 SMTP 服务器地址 | |
79 | + host: xxx | |
80 | + # 发送者邮箱,已开通POP3/SMTP服务的邮箱,也就是你自己的 | |
81 | + username: xxxx | |
82 | + # 配置密码,注意不是真正的密码,而是刚刚申请到的授权码 | |
83 | + password: xxx | |
84 | + # 邮件接收者 | |
85 | + mailRecipient: #邮件接收者邮箱 | |
86 | + # 端口号465或587(QQ邮箱发送邮件仅支持587端口协议) | |
87 | + port: 587 | |
88 | + # 默认的邮件编码为UTF-8 | |
89 | + default-encoding: UTF-8 | |
90 | + # 配置SSL 加密工厂 | |
91 | + properties: | |
92 | + mail: | |
93 | + smtp: | |
94 | + socketFactoryClass: javax.net.ssl.SSLSocketFactory | |
95 | + #表示开启 DEBUG 模式,这样,邮件发送过程的日志会在控制台打印出来,方便排查错误 | |
96 | + debug: true | |
97 | + | |
98 | + freemarker: | |
99 | + template-loader-path: classpath:/template/ | |
100 | + suffix: .flt | |
101 | + enabled: true | |
102 | + cache: false | |
103 | + charset: UTF-8 | |
104 | + content-type: text/html | |
105 | + allow-request-override: false | |
106 | + check-template-location: true | |
107 | + expose-request-attributes: false | |
108 | + expose-session-attributes: false | |
109 | + expose-spring-macro-helpers: false | |
110 | + | |
111 | + | |
112 | +logging: | |
113 | + config: classpath:log4j2-prod.xml | |
114 | + | |
115 | +#登录图形验证码有效时间/分钟 | |
116 | +loginCode: | |
117 | + expiration: 2 | |
118 | + | |
119 | +#密码加密传输,前端公钥加密,后端私钥解密 | |
120 | +rsa: | |
121 | + private_key: MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A== | |
122 | + | |
123 | + | |
124 | +#jwt | |
125 | +jwt: | |
126 | + header: Authorization | |
127 | + # 令牌前缀 | |
128 | + token-start-with: Bearer | |
129 | + # 必须使用最少88位的Base64对该令牌进行编码 | |
130 | + base64-secret: ZmQ0ZGI5NjQ0MDQwY2I4MjMxY2Y3ZmI3MjdhN2ZmMjNhODViOTg1ZGE0NTBjMGM4NDA5NzYxMjdjOWMwYWRmZTBlZjlhNGY3ZTg4Y2U3YTE1ODVkZDU5Y2Y3OGYwZWE1NzUzNWQ2YjFjZDc0NGMxZWU2MmQ3MjY1NzJmNTE0MzI= | |
131 | + # 令牌过期时间 此处单位/毫秒 ,默认2小时,可在此网站生成 https://www.convertworld.com/zh-hans/time/milliseconds.html | |
132 | + token-validity-in-seconds: 720000000 | |
133 | + # 在线用户key | |
134 | + online-key: online-token | |
135 | + # 验证码 | |
136 | + code-key: code-key | |
137 | + | |
138 | +outsys: | |
139 | + sms: | |
140 | + regionId: cn-hangzhou | |
141 | + accessKeyId: LTAIZCPI7OaWud0m | |
142 | + secret: nvtGeScBwRztGeoj8WSp5OWalalgpK | |
143 | + domain: dysmsapi.aliyuncs.com | |
144 | + version: 2017-05-25 | |
145 | + action: SendSms | |
146 | + signName: canrd | |
147 | + templateCode: SMS_173005236 | |
148 | + email: | |
149 | + host: xxxx | |
150 | + passwordRecoverKey: xxxxx | |
151 | + | |
152 | + | |
153 | + | |
154 | +system: | |
155 | + isLoginFailureLock: true | |
156 | + loginFailureLockTime: 5 | |
157 | + loginFailureLockCount: 3 | |
158 | + | |
159 | +openai: | |
160 | + token: Bearer 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 | |
161 | + | |
162 | +# 文件存储路径 | |
163 | +file: | |
164 | + path: /home/canrd/order-erp/files/ | |
165 | + host: http://47.104.8.35 | |
166 | + avatar: /home/order-erp/avatar/ | |
167 | + # 文件大小 /M | |
168 | + maxSize: 100 | |
169 | + avatarMaxSize: 5 | |
170 | + | |
171 | +# 阿里pss图片服务 | |
172 | +oss: | |
173 | + endpoint: https://oss-cn-qingdao.aliyuncs.com | |
174 | + accessKeyId: LTAI5t7u1gXR2vm82sd6CkVz | |
175 | + accessKeySecret: m4NzHZZsZiauKmRO8y7DihmcGNdQk4 | |
176 | + bucket: alterego | |
177 | + | |
178 | + | |
179 | +db: | |
180 | + mysql: | |
181 | + ip: 172.17.0.1 | |
182 | + port: 3306 | |
183 | + user: root | |
184 | + password: 123456 | |
185 | + databaseName: order-erp | |
186 | + savePath: /home/canrd/order-erp/files/backup/ | ... | ... |
src/main/resources/application-test.yml
0 → 100644
1 | +++ a/src/main/resources/application-test.yml | |
1 | +mybatis-plus: | |
2 | + configuration: | |
3 | + cache-enabled: false | |
4 | + call-setters-on-nulls: true | |
5 | + jdbc-type-for-null: 'null' | |
6 | + map-underscore-to-camel-case: true | |
7 | + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl | |
8 | + global-config: | |
9 | + db-config: | |
10 | + capital-mode: false | |
11 | + field-strategy: NOT_NULL | |
12 | + id-type: AUTO | |
13 | + logic-delete-field: enable_flag | |
14 | + logic-delete-value: 20 | |
15 | + logic-not-delete-value: 10 | |
16 | + mapper-locations: classpath:/mapper/**.xml | |
17 | + type-aliases-package: com.order.erp.**.dto | |
18 | +#spring: | |
19 | +# datasource: | |
20 | +# dynamic: | |
21 | +# primary: overtime #设置默认的数据源或者数据源组,默认值即为master | |
22 | +# strict: false #设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候会抛出异常,不启动则使用默认数据源. | |
23 | +# datasource: | |
24 | +# wms_warehouse: | |
25 | +# url: jdbc:mysql://127.0.0.1:3306/overtime?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&useSSL=false&autoReconnect=true&failOverReadOnly=false&maxReconnects=10&allowMultiQueries=true&useAffectedRows=true&autoReconnectForPools=true&rewriteBatchedStatements=true | |
26 | +# username: root | |
27 | +# password: root | |
28 | +# driver-class-name: com.mysql.cj.jdbc.Driver # 3.2.0开始支持SPI可省略此配置 | |
29 | +# druid: | |
30 | +# initial-size: 5 | |
31 | +# max-active: 20 | |
32 | +# max-evictable-idle-time-millis: 300000 | |
33 | +# max-wait: 60000 | |
34 | +# min-evictable-idle-time-millis: 300000 | |
35 | +# min-idle: 5 | |
36 | +# time-between-eviction-runs-millis: 60000 | |
37 | +# type: com.alibaba.druid.pool.DruidDataSource | |
38 | +spring: | |
39 | + servlet: | |
40 | + multipart: | |
41 | + enabled: true | |
42 | + max-file-size: 100MB | |
43 | + max-request-size: 20MB | |
44 | + file-size-threshold: 20MB | |
45 | + datasource: | |
46 | + db-type: com.alibaba.druid.pool.DruidDataSource | |
47 | + driverClassName: com.mysql.cj.jdbc.Driver | |
48 | + initial-size: 5 | |
49 | + max-active: 30 | |
50 | + max-wait: 30000 | |
51 | + min-idle: 5 | |
52 | + #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 | |
53 | + timeBetweenEvictionRunsMillis: 30000 | |
54 | + #配置一个连接在池中最小生存的时间,单位是毫秒,30000=30s | |
55 | + minEvictableIdleTimeMillis: 30000 | |
56 | + validationQuery: SELECT 'x' | |
57 | + testWhileIdle: true | |
58 | + testOnBorrow: true | |
59 | + testOnReturn: true | |
60 | + password: 123456 | |
61 | + time-between-eviction-runs-millis: 1000 | |
62 | + url: jdbc:mysql://39.108.227.113:3307/order-erp?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&useSSL=false&autoReconnect=true&failOverReadOnly=false&maxReconnects=10&allowMultiQueries=true&useAffectedRows=true&autoReconnectForPools=true | |
63 | + username: root | |
64 | + redis: | |
65 | + database: 0 | |
66 | + host: 39.108.227.113 | |
67 | + lettuce: | |
68 | + pool: | |
69 | + max-active: 2000 | |
70 | + max-idle: 10 | |
71 | + max-wait: -1 | |
72 | + min-idle: 3 | |
73 | + time-between-eviction-runs: 100 | |
74 | + password: '' | |
75 | + port: 6379 | |
76 | + timeout: 2000 | |
77 | + mail: | |
78 | + # 配置 SMTP 服务器地址 | |
79 | + host: smtp.mxhichina.com | |
80 | + # 发送者邮箱,已开通POP3/SMTP服务的邮箱,也就是你自己的 | |
81 | + username: system@canrd.com | |
82 | + # 配置密码,注意不是真正的密码,而是刚刚申请到的授权码 | |
83 | + password: Kelude2015 | |
84 | + # 邮件接收者 | |
85 | + mailRecipient: #邮件接收者邮箱 | |
86 | + # 端口号465或587(QQ邮箱发送邮件仅支持587端口协议) | |
87 | + port: 587 | |
88 | + # 默认的邮件编码为UTF-8 | |
89 | + default-encoding: UTF-8 | |
90 | + # 配置SSL 加密工厂 | |
91 | + properties: | |
92 | + mail: | |
93 | + smtp: | |
94 | + socketFactoryClass: javax.net.ssl.SSLSocketFactory | |
95 | + #表示开启 DEBUG 模式,这样,邮件发送过程的日志会在控制台打印出来,方便排查错误 | |
96 | + debug: true | |
97 | + | |
98 | + freemarker: | |
99 | + template-loader-path: classpath:/template/ | |
100 | + suffix: .flt | |
101 | + enabled: true | |
102 | + cache: false | |
103 | + charset: UTF-8 | |
104 | + content-type: text/html | |
105 | + allow-request-override: false | |
106 | + check-template-location: true | |
107 | + expose-request-attributes: false | |
108 | + expose-session-attributes: false | |
109 | + expose-spring-macro-helpers: false | |
110 | + | |
111 | + | |
112 | +logging: | |
113 | + config: classpath:log4j2-dev.xml | |
114 | + | |
115 | +#登录图形验证码有效时间/分钟 | |
116 | +loginCode: | |
117 | + expiration: 2 | |
118 | + | |
119 | +#密码加密传输,前端公钥加密,后端私钥解密 | |
120 | +rsa: | |
121 | + private_key: MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A== | |
122 | + | |
123 | + | |
124 | +#jwt | |
125 | +jwt: | |
126 | + header: Authorization | |
127 | + # 令牌前缀 | |
128 | + token-start-with: Bearer | |
129 | + # 必须使用最少88位的Base64对该令牌进行编码 | |
130 | + base64-secret: ZmQ0ZGI5NjQ0MDQwY2I4MjMxY2Y3ZmI3MjdhN2ZmMjNhODViOTg1ZGE0NTBjMGM4NDA5NzYxMjdjOWMwYWRmZTBlZjlhNGY3ZTg4Y2U3YTE1ODVkZDU5Y2Y3OGYwZWE1NzUzNWQ2YjFjZDc0NGMxZWU2MmQ3MjY1NzJmNTE0MzI= | |
131 | + # 令牌过期时间 此处单位/毫秒 ,默认2小时,可在此网站生成 https://www.convertworld.com/zh-hans/time/milliseconds.html | |
132 | + token-validity-in-seconds: 720000000 | |
133 | + # 在线用户key | |
134 | + online-key: online-token | |
135 | + # 验证码 | |
136 | + code-key: code-key | |
137 | + | |
138 | +outsys: | |
139 | + sms: | |
140 | + regionId: cn-hangzhou | |
141 | + accessKeyId: LTAIZCPI7OaWud0m | |
142 | + secret: nvtGeScBwRztGeoj8WSp5OWalalgpK | |
143 | + domain: dysmsapi.aliyuncs.com | |
144 | + version: 2017-05-25 | |
145 | + action: SendSms | |
146 | + signName: canrd | |
147 | + templateCode: SMS_173005236 | |
148 | + email: | |
149 | + host: http://core.canrd.com | |
150 | + passwordRecoverKey: http://www.canrd.com/canrd/shop/member/passwordModify | |
151 | + | |
152 | + | |
153 | + | |
154 | +system: | |
155 | + isLoginFailureLock: true | |
156 | + loginFailureLockTime: 5 | |
157 | + loginFailureLockCount: 3 | |
158 | + | |
159 | +openai: | |
160 | + token: Bearer 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 | |
161 | + | |
162 | +# 文件存储路径 | |
163 | +file: | |
164 | + path: /home/canrd/order-erp/files/ | |
165 | + host: http://39.108.227.113 | |
166 | + avatar: /home/order-erp/avatar/ | |
167 | + # 文件大小 /M | |
168 | + maxSize: 100 | |
169 | + avatarMaxSize: 5 | |
170 | + | |
171 | +# 阿里pss图片服务 | |
172 | +oss: | |
173 | + endpoint: https://oss-cn-qingdao.aliyuncs.com | |
174 | + accessKeyId: LTAIZCPI7OaWud0m | |
175 | + accessKeySecret: nvtGeScBwRztGeoj8WSp5OWalalgpK | |
176 | + bucket: order-erp | |
177 | + | |
178 | + | |
179 | +db: | |
180 | + mysql: | |
181 | + ip: 39.108.227.113 | |
182 | + port: 3307 | |
183 | + user: root | |
184 | + password: 123456 | |
185 | + databaseName: order-erp | |
186 | + savePath: /home/canrd/order-erp/files/backup/ | ... | ... |
src/main/resources/application.yml
0 → 100644
src/main/resources/ip2region/ip2region.db
0 → 100644
No preview for this file type
src/main/resources/log4j2-dev.xml
0 → 100644
1 | +++ a/src/main/resources/log4j2-dev.xml | |
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL --> | |
3 | +<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出 --> | |
4 | +<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数 --> | |
5 | +<configuration status="debug" monitorInterval="30"> | |
6 | + <!--<contextName>log4j2</contextName>--> | |
7 | + <properties> | |
8 | + <!--${sys:catalina.home}表示linux中环境变量中的tomcat根目录 用户主目录--> | |
9 | + <!--原来用logback时候在统一配置中心也配置一个logging.path=/opt/tomcat-log/${spring.application.name} LOG_PATH是内置变量--> | |
10 | + <!--${sys:user.home} 用户主目录--> | |
11 | + <!-- <Property name="log_path">${sys:user.home}/logs</Property>--> | |
12 | +<!-- <Property name="log_path" value="./logs/" />--> | |
13 | + <property name="console_log_pattern">%d|%t|%traceId|%-5level|%F:%L|%M|%m%n</property> | |
14 | + <!-- 保留日志天数 D H M S 分别对应天 小时 分钟 秒 --> | |
15 | + <property name="KEEP_LOG_DAY">60D</property> | |
16 | + <!-- 日志切割的最小单位 --> | |
17 | + <property name="EVERY_FILE_SIZE">100M</property> | |
18 | + </properties> | |
19 | + <!--先定义所有的appender --> | |
20 | + <appenders> | |
21 | + <console name="Console" target="SYSTEM_OUT"> | |
22 | + <!--输出日志的格式 --> | |
23 | + <PatternLayout charset="UTF-8" pattern="${console_log_pattern}"/> | |
24 | + <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY" /> | |
25 | + </console> | |
26 | + <!--这个输出控制台的配置 --> | |
27 | + <!--<console name="Console" target="SYSTEM_OUT" follow="false">--> | |
28 | + <!--<!–输出日志的格式 –>--> | |
29 | + <!--<PatternLayout pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} %level [%thread][%file:%line] - %msg%n" />--> | |
30 | + <!--</console>--> | |
31 | + | |
32 | + <!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档 --> | |
33 | + <RollingFile name="RollingFileInfo" fileName="${sys:logging.path}/logs/overtime.log" filePattern="${sys:logging.path}/logs/$${date:yyyy-MM-dd}/info-%d{yyyy-MM-dd}-%i.log"> | |
34 | + <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) --> | |
35 | + <ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY" /> | |
36 | + <!--<Filters>--> | |
37 | + <!--<ThresholdFilter level="INFO"/>--> | |
38 | + <!--<ThresholdFilter level="WARN" onMatch="DENY"--> | |
39 | + <!--onMismatch="NEUTRAL"/>--> | |
40 | + <!--</Filters>--> | |
41 | + <PatternLayout charset="UTF-8" pattern="${console_log_pattern}"/> | |
42 | + <Policies> | |
43 | + <!-- 归档每天的文件 --> | |
44 | + <!--<TimeBasedTriggeringPolicy interval="1" modulate="true"/>--> | |
45 | + <TimeBasedTriggeringPolicy /> | |
46 | + <!-- 限制单个文件大小 --> | |
47 | + <SizeBasedTriggeringPolicy size="${EVERY_FILE_SIZE}"/> | |
48 | + </Policies> | |
49 | + <!-- 限制每天文件个数 --> <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了100 --> | |
50 | + <DefaultRolloverStrategy max="256"> | |
51 | + <Delete basePath="${sys:logging.path}/logs/" maxDepth="3"> | |
52 | + <IfFileName glob="*/*info*.log"/> | |
53 | + <IfLastModified age="${KEEP_LOG_DAY}"/> | |
54 | + </Delete> | |
55 | + </DefaultRolloverStrategy> | |
56 | + </RollingFile> | |
57 | + </appenders> | |
58 | + <!--然后定义logger,只有定义了logger并引入的appender,appender才会生效 --> | |
59 | + <loggers> | |
60 | + <!--过滤掉spring和mybatis的一些无用的DEBUG信息 --> | |
61 | + <logger name="org.springframework" level="debug" > | |
62 | + <ThresholdFilter level="debug"/> | |
63 | + <appender-ref ref="RollingFileInfo" /> | |
64 | + </logger> | |
65 | + <logger name="org.mybatis" level="DEBUG" > | |
66 | + <ThresholdFilter level="debug"/> | |
67 | + <appender-ref ref="RollingFileInfo" /> | |
68 | + </logger> | |
69 | + <logger name="com.canrd.shop" level="DEBUG" > | |
70 | + <ThresholdFilter level="debug"/> | |
71 | + <appender-ref ref="RollingFileInfo" /> | |
72 | + </logger> | |
73 | + <!--<root level="all">--> | |
74 | + <root level="debug"> | |
75 | + <appender-ref ref="Console" /> | |
76 | + </root> | |
77 | + </loggers> | |
78 | +</configuration> | ... | ... |
src/main/resources/log4j2-prod.xml
0 → 100644
1 | +++ a/src/main/resources/log4j2-prod.xml | |
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL --> | |
3 | +<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出 --> | |
4 | +<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数 --> | |
5 | +<configuration status="INFO" monitorInterval="30"> | |
6 | + <!--<contextName>log4j2</contextName>--> | |
7 | + <properties> | |
8 | + <!--${sys:catalina.home}表示linux中环境变量中的tomcat根目录 用户主目录--> | |
9 | + <!--原来用logback时候在统一配置中心也配置一个logging.path=/opt/tomcat-log/${spring.application.name} LOG_PATH是内置变量--> | |
10 | + <!--${sys:user.home} 用户主目录--> | |
11 | + <!-- <Property name="log_path">${sys:user.home}/logs</Property>--> | |
12 | +<!-- <Property name="log_path" value="./logs/" />--> | |
13 | + <property name="console_log_pattern">%d|%t|%traceId|%-5level|%F:%L|%M|%m%n</property> | |
14 | + <!-- 保留日志天数 D H M S 分别对应天 小时 分钟 秒 --> | |
15 | + <property name="KEEP_LOG_DAY">60D</property> | |
16 | + <!-- 日志切割的最小单位 --> | |
17 | + <property name="EVERY_FILE_SIZE">100M</property> | |
18 | + </properties> | |
19 | + <!--先定义所有的appender --> | |
20 | + <appenders> | |
21 | + <console name="Console" target="SYSTEM_OUT"> | |
22 | + <!--输出日志的格式 --> | |
23 | + <PatternLayout charset="UTF-8" pattern="${console_log_pattern}"/> | |
24 | + <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY" /> | |
25 | + </console> | |
26 | + <!--这个输出控制台的配置 --> | |
27 | + <!--<console name="Console" target="SYSTEM_OUT" follow="false">--> | |
28 | + <!--<!–输出日志的格式 –>--> | |
29 | + <!--<PatternLayout pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} %level [%thread][%file:%line] - %msg%n" />--> | |
30 | + <!--</console>--> | |
31 | + | |
32 | + <!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档 --> | |
33 | + <RollingFile name="RollingFileInfo" fileName="${sys:logging.path}/logs/overtime.log" filePattern="${sys:logging.path}/logs/$${date:yyyy-MM-dd}/info-%d{yyyy-MM-dd}-%i.log"> | |
34 | + <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) --> | |
35 | + <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY" /> | |
36 | + <!--<Filters>--> | |
37 | + <!--<ThresholdFilter level="INFO"/>--> | |
38 | + <!--<ThresholdFilter level="WARN" onMatch="DENY"--> | |
39 | + <!--onMismatch="NEUTRAL"/>--> | |
40 | + <!--</Filters>--> | |
41 | + <PatternLayout charset="UTF-8" pattern="${console_log_pattern}"/> | |
42 | + <Policies> | |
43 | + <!-- 归档每天的文件 --> | |
44 | + <!--<TimeBasedTriggeringPolicy interval="1" modulate="true"/>--> | |
45 | + <TimeBasedTriggeringPolicy /> | |
46 | + <!-- 限制单个文件大小 --> | |
47 | + <SizeBasedTriggeringPolicy size="${EVERY_FILE_SIZE}"/> | |
48 | + </Policies> | |
49 | + <!-- 限制每天文件个数 --> <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了100 --> | |
50 | + <DefaultRolloverStrategy max="256"> | |
51 | + <Delete basePath="${sys:logging.path}/logs/" maxDepth="3"> | |
52 | + <IfFileName glob="*/*info*.log"/> | |
53 | + <IfLastModified age="${KEEP_LOG_DAY}"/> | |
54 | + </Delete> | |
55 | + </DefaultRolloverStrategy> | |
56 | + </RollingFile> | |
57 | + </appenders> | |
58 | + <!--然后定义logger,只有定义了logger并引入的appender,appender才会生效 --> | |
59 | + <loggers> | |
60 | + <logger name="org.springframework" level="info" > | |
61 | + <ThresholdFilter level="info"/> | |
62 | + <appender-ref ref="RollingFileInfo" /> | |
63 | + </logger> | |
64 | + <logger name="org.mybatis" level="info" > | |
65 | + <ThresholdFilter level="info"/> | |
66 | + <appender-ref ref="RollingFileInfo" /> | |
67 | + </logger> | |
68 | + <logger name="com.canrd.shop" level="info" > | |
69 | + <ThresholdFilter level="info"/> | |
70 | + <appender-ref ref="RollingFileInfo" /> | |
71 | + </logger> | |
72 | + </loggers> | |
73 | +</configuration> | ... | ... |