文章

ft工具类

ft工具类

配置文件读取

PropertiesUtil

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
import java.util.Properties;

public class PropertiesUtil {

    private static final Logger logger = LoggerFactory.getLogger(PropertiesUtil.class);

    private static Properties p = new Properties();

    static{
        init();
    }

    private static void init(){
        try {
            p.load(new InputStreamReader(Objects.requireNonNull(PropertiesUtil.class.getClassLoader().getResourceAsStream("env_config.properties")), StandardCharsets.UTF_8));
        } catch (IOException e) {
            logger.error("Loading properties file error:", e);
        }
    }

    /**
     * Fetch value by key
     * @param key key
     * @return String
     */
    public static String getValue(String key) {
        return p.getProperty(key);
    }

    /**
     * Put new value into file
     * @param key key
     * @param value value
     */
    public static void writeProperty(String key, String value) {
        p.setProperty(key.trim(), value.trim());
    }

    public static void main(String[] args) {
        
    }
}

自定义异常

BusinessException

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public class BusinessException extends RuntimeException {

	private static final long serialVersionUID = 2874510430549463213L;

	public BusinessException() {
		super();
	}

	public BusinessException(String message, Throwable cause) {
		super(message, cause);
	}

	public BusinessException(String message) {
		super(message);
	}

	public BusinessException(Throwable cause) {
		super(cause);
	}

	private int returnCode;

	public BusinessException(int returnCode) {
		super();
		this.returnCode = returnCode;
	}

	public BusinessException(Exception e, int returnCode) {
		super(e);
		this.returnCode = returnCode;
	}

	public BusinessException(String message, int returnCode) {
		super(message);
		this.returnCode = returnCode;
	}

	public BusinessException(String message, Exception e, int returnCode) {
		super(message, e);
		this.returnCode = returnCode;
	}

	public int getReturnCode() {
		return returnCode;
	}

	public void setReturnCode(int returnCode) {
		this.returnCode = returnCode;
	}
}

redis相关

分布式锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.UUID;

@Component
public class RedisDistributedLock {

    private static final String LUA_SCRIPT_LOCK = "return redis.call('set',KEYS[1],ARGV[1],'NX','PX',ARGV[2])";
    private static final RedisScript<String> SCRIPT_LOCK = new DefaultRedisScript<String>(LUA_SCRIPT_LOCK, String.class);
    private static final String LUA_SCRIPT_UNLOCK = "if redis.call('get',KEYS[1]) == ARGV[1] then return tostring(redis.call('del', KEYS[1])) else return '0' end";
    private static final RedisScript<String> SCRIPT_UNLOCK = new DefaultRedisScript<String>(LUA_SCRIPT_UNLOCK, String.class);
    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 加锁
     *
     * @param redisKey   缓存KEY
     * @param expire     到期时间 毫秒
     * @param tryTimeout 尝试获取锁超时时间 毫秒
     * @return redis锁信息
     */
    public RedisLockInfo tryLock(String redisKey, long expire, long tryTimeout) {
        Assert.isTrue(tryTimeout > 0, "tryTimeout必须大于0");
        long timestamp = System.currentTimeMillis();
        int tryCount = 0;
        String lockId = UUID.randomUUID().toString();
        while ((System.currentTimeMillis() - timestamp) < tryTimeout) {
            try {
                Object lockResult = redisTemplate.execute(SCRIPT_LOCK,
                        redisTemplate.getStringSerializer(),
                        redisTemplate.getStringSerializer(),
                        Collections.singletonList(redisKey),
                        lockId, String.valueOf(expire));
                tryCount++;
                if ("OK".equals(lockResult)) {
                    return new RedisLockInfo(lockId, redisKey, expire, tryTimeout, tryCount);
                } else {
                    Thread.sleep(50);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 解锁
     *
     * @param redisLockInfo 获取锁返回的对象
     * @return 是释放成功
     */
    public boolean releaseLock(RedisLockInfo redisLockInfo) {
        Object releaseResult = null;
        try {
            releaseResult = redisTemplate.execute(SCRIPT_UNLOCK,
                    redisTemplate.getStringSerializer(),
                    redisTemplate.getStringSerializer(),
                    Collections.singletonList(redisLockInfo.getRedisKey()),
                    redisLockInfo.getLockId());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null != releaseResult && releaseResult.equals(1);
    }
}

  • 锁信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class RedisLockInfo {

    /**
     * 锁ID UUID
     */
    private String lockId;

    /**
     * REDIS KEY
     */
    private String redisKey;

    /**
     * 过期时间
     */
    private Long expire;

    /**
     * 尝试获取锁超时时间
     */
    private Long tryTimeout;

    /**
     * 尝试获取锁次数
     */
    private int tryCount;

}

RedisCacheManager

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @description: redis 工具类
 */
public class RedisCacheManager {

     /**
     * LOCK Result-成功标记
     */
    private static final String LOCK_SUCCESS = "OK";
    /**
     * 当key不存在,进行set操作;若key已存在,则不做任何操作
     */
    private static final String SET_IF_NOT_EXIST = "NX";
    /**
     * key加一个过期的设置
     */
    private static final String SET_WITH_EXPIRE_TIME = "PX";

    /**
     * 锁的超时时间(毫秒)
     */
    private static final Long TIMEOUT = 5000L;

    /**
     * RELEASE Result-成功标记
     */
    private static final Long RELEASE_SUCCESS = 1L;

    /**
     * 单个节点相关requestId
     * 可以用UUID.randomUUID().toString()
     */
    public static final String REQUESTID_DEFAULT="fittime_requestId";

    /**
     * redisTemplate 对象
     */
    private RedisTemplate<String, Object> redisTemplate;

    public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 尝试获取分布式锁
     * @param lockKey 锁(即key)
     * @param requestId 请求标识,解锁时使用(即value或者UUID.randomUUID().toString()生成)
     * @param expireTime 超期时间(单位毫秒)
     * @return 是否获取成功
     */
    public boolean tryGetDistributedLock(String lockKey, String requestId,Long expireTime) {
       return redisTemplate.execute((RedisCallback<Boolean>) connection -> {
           String timeoutStr;
           if(expireTime!=null){
               timeoutStr=expireTime.toString();
           }else {
               timeoutStr=TIMEOUT.toString();
           }
           //加锁命令
           Object obj = connection.execute("SET", lockKey.getBytes(), requestId.getBytes(),
                   SET_WITH_EXPIRE_TIME.getBytes(), timeoutStr.getBytes(), SET_IF_NOT_EXIST.getBytes());
           return Arrays.equals(LOCK_SUCCESS.getBytes(), (byte[]) obj);
       });
    }

    /**
     * 释放分布式锁
     * @param lockKey 锁(即key)
     * @param requestId 请求标识,解锁时使用(即value)
     * @return 是否释放成功
     */
    public boolean releaseDistributedLock(String lockKey, String requestId) {
        return redisTemplate.execute((RedisCallback<Boolean>) connection -> {
            //Lua脚本代码(原子性):先获取锁对应的value值,检查是否与requestId相等,如果相等则删除锁(解锁)
            String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
            List<String> keys=Collections.singletonList(lockKey);
            List<String> args=Collections.singletonList(requestId);

            Object nativeConnection = connection.getNativeConnection();
            Long result=0L;
            if (nativeConnection instanceof JedisCluster) {
                // 集群模式
                result= (Long) ((JedisCluster) nativeConnection).eval(script, keys, args);
            } else if (nativeConnection instanceof Jedis) {
                // 单机模式
                result= (Long) ((Jedis) nativeConnection).eval(script, keys, args);
            }

            if(RELEASE_SUCCESS.equals(result)) {
                return true;
            }
            return false;
        });
    }
    //=============================common============================
    /**
     * 指定缓存失效时间
     * @param key 键
     * @param time 时间(秒)
     * @return
     */
    public boolean expire(String key,long time){
        try {
            if(time>0){
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据key 获取过期时间
     * @param key 键 不能为null
     * @return 时间(秒) 返回0代表为永久有效
     */
    public long getExpire(String key){
        return redisTemplate.getExpire(key,TimeUnit.SECONDS);
    }

    /**
     * 判断key是否存在
     * @param key 键
     * @return true 存在 false不存在
     */
    public boolean hasKey(String key){
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除缓存
     * @param key 可以传一个值 或多个
     */
    @SuppressWarnings("unchecked")
    public void del(String ... key){
        if(key!=null&&key.length>0){
            if(key.length==1){
                redisTemplate.delete(key[0]);
            }else{
                redisTemplate.delete(CollectionUtils.arrayToList(key));
            }
        }
    }

    //============================String=============================
    /**
     * 普通缓存获取
     * @param key 键
     * @return 值
     */
    public Object get(String key){
        return key==null?null:redisTemplate.opsForValue().get(key);
    }

    /**
     * 普通缓存放入
     * @param key 键
     * @param value 值
     * @return true成功 false失败
     */
    public boolean set(String key,Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }

    /**
     * 普通缓存放入并设置时间
     * @param key 键
     * @param value 值
     * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
     * @return true成功 false 失败
     */
    public boolean set(String key,Object value,long time){
        try {
            if(time>0){
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            }else{
                set(key, value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 递增
     * @param key 键
     * @param delta 要增加几(大于0)
     * @return
     */
    public long incr(String key, long delta){
        if(delta<0){
            throw new RuntimeException("递增因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 递减
     * @param key 键
     * @param delta 要减少几(小于0)
     * @return
     */
    public long decr(String key, long delta){
        if(delta<0){
            throw new RuntimeException("递减因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, -delta);
    }

    //================================Map=================================
    /**
     * HashGet
     * @param key 键 不能为null
     * @param item 项 不能为null
     * @return 值
     */
    public Object hget(String key,String item){
        return redisTemplate.opsForHash().get(key, item);
    }

    /**
     * 获取hashKey对应的所有键值
     * @param key 键
     * @return 对应的多个键值
     */
    public Map<Object,Object> hmget(String key){
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * HashSet
     * @param key 键
     * @param map 对应多个键值
     * @return true 成功 false 失败
     */
    public boolean hmset(String key, Map<String,Object> map){
        try {
            redisTemplate.opsForHash().putAll(key, map);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * HashSet 并设置时间
     * @param key 键
     * @param map 对应多个键值
     * @param time 时间(秒)
     * @return true成功 false失败
     */
    public boolean hmset(String key, Map<String,Object> map, long time){
        try {
            redisTemplate.opsForHash().putAll(key, map);
            if(time>0){
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 向一张hash表中放入数据,如果不存在将创建
     * @param key 键
     * @param item 项
     * @param value 值
     * @return true 成功 false失败
     */
    public boolean hset(String key,String item,Object value) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 向一张hash表中放入数据,如果不存在将创建
     * @param key 键
     * @param item 项
     * @param value 值
     * @param time 时间(秒)  注意:如果已存在的hash表有时间,这里将会替换原有的时间
     * @return true 成功 false失败
     */
    public boolean hset(String key,String item,Object value,long time) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            if(time>0){
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除hash表中的值
     * @param key 键 不能为null
     * @param item 项 可以使多个 不能为null
     */
    public void hdel(String key, Object... item){
        redisTemplate.opsForHash().delete(key,item);
    }

    /**
     * 判断hash表中是否有该项的值
     * @param key 键 不能为null
     * @param item 项 不能为null
     * @return true 存在 false不存在
     */
    public boolean hHasKey(String key, String item){
        return redisTemplate.opsForHash().hasKey(key, item);
    }

    /**
     * hash递增 如果不存在,就会创建一个 并把新增后的值返回
     * @param key 键
     * @param item 项
     * @param by 要增加几(大于0)
     * @return
     */
    public double hincr(String key, String item,double by){
        return redisTemplate.opsForHash().increment(key, item, by);
    }

    /**
     * hash递减
     * @param key 键
     * @param item 项
     * @param by 要减少记(小于0)
     * @return
     */
    public double hdecr(String key, String item,double by){
        return redisTemplate.opsForHash().increment(key, item,-by);
    }

    //============================set=============================
    /**
     * 根据key获取Set中的所有值
     * @param key 键
     * @return
     */
    public Set<Object> sGet(String key){
        try {
            return redisTemplate.opsForSet().members(key);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 根据value从一个set中查询,是否存在
     * @param key 键
     * @param value 值
     * @return true 存在 false不存在
     */
    public boolean sHasKey(String key,Object value){
        try {
            return redisTemplate.opsForSet().isMember(key, value);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将数据放入set缓存
     * @param key 键
     * @param values 值 可以是多个
     * @return 成功个数
     */
    public long sSet(String key, Object...values) {
        try {
            return redisTemplate.opsForSet().add(key, values);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 将set数据放入缓存
     * @param key 键
     * @param time 时间(秒)
     * @param values 值 可以是多个
     * @return 成功个数
     */
    public long sSetAndTime(String key,long time,Object...values) {
        try {
            Long count = redisTemplate.opsForSet().add(key, values);
            if(time>0) {
                expire(key, time);
            }
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 获取set缓存的长度
     * @param key 键
     * @return
     */
    public long sGetSetSize(String key){
        try {
            return redisTemplate.opsForSet().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 移除值为value的
     * @param key 键
     * @param values 值 可以是多个
     * @return 移除的个数
     */
    public long setRemove(String key, Object ...values) {
        try {
            Long count = redisTemplate.opsForSet().remove(key, values);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
    //===============================list=================================

    /**
     * 获取list缓存的内容
     * @param key 键
     * @param start 开始
     * @param end 结束  0 到 -1代表所有值
     * @return
     */
    public List<Object> lGet(String key,long start, long end){
        try {
            return redisTemplate.opsForList().range(key, start, end);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取list缓存的长度
     * @param key 键
     * @return
     */
    public long lGetListSize(String key){
        try {
            return redisTemplate.opsForList().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 通过索引 获取list中的值
     * @param key 键
     * @param index 索引  index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
     * @return
     */
    public Object lGetIndex(String key,long index){
        try {
            return redisTemplate.opsForList().index(key, index);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将list放入缓存
     * @param key 键
     * @param value 值
     * @return
     */
    public boolean lSet(String key, Object value) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     * @param key 键
     * @param value 值
     * @param time 时间(秒)
     * @return
     */
    public boolean lSet(String key, Object value, long time) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     * @param key 键
     * @param value 值
     * @return
     */
    public boolean lSet(String key, List<Object> value) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     * @param key 键
     * @param value 值
     * @param time 时间(秒)
     * @return
     */
    public boolean lSet(String key, List<Object> value, long time) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据索引修改list中的某条数据
     * @param key 键
     * @param index 索引
     * @param value 值
     * @return
     */
    public boolean lUpdateIndex(String key, long index,Object value) {
        try {
            redisTemplate.opsForList().set(key, index, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 移除N个值为value
     * @param key 键
     * @param count 移除多少个
     * @param value 值
     * @return 移除的个数
     */
    public long lRemove(String key,long count,Object value) {
        try {
            Long remove = redisTemplate.opsForList().remove(key, count, value);
            return remove;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }


    /**
     * 获取redis中以某些字符串为前缀的KEY列表
     * @param prefix key 前缀
     * @return 移除的个数
     */
    public Set<String> keySet(String prefix){
        Set<String> keys = redisTemplate.keys(prefix);
        return keys;
    }

}

RedisLock

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Component
public class RedisLock {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * Redis 加锁
     * @param key  KEY
     * @param value 超时时间
     * @return boolean 加锁是否成功 true是  false否
     */
    public boolean lock(String key, String value) {
        // 先获取当前值
        Object currentValue = redisTemplate.opsForValue().get(key);
        if (null != currentValue) {
            // 锁过期/重新设置值
            if (Long.parseLong(String.valueOf(currentValue)) < System.currentTimeMillis()) {
                redisTemplate.opsForValue().set(key, value);
                return false;
            } else {
                return true;
            }
        }
        redisTemplate.opsForValue().set(key, value);
        return false;
//        // 避免死锁,且只让一个线程拿到锁
//        String currentValue = String.valueOf(redisTemplate.opsForValue().get(key));
//
//        // 如果锁过期了
//        if (!StringUtils.isEmpty(currentValue) && Long.parseLong(currentValue) < System.currentTimeMillis()) {
//
//            // 获取上一个锁的时间
//            String oldValues = String.valueOf(redisTemplate.opsForValue().getAndSet(key, value));
//
//            // 如果旧的value和currentValue相等,只会有一个线程达成条件,因为第二个线程拿到的oldValue已经和currentValue不一样了
//            return !StringUtils.isEmpty(oldValues) && oldValues.equals(currentValue);
//        }
//        return false;
    }


    /**
     * Redis 解锁
     * @param key KEY
     * @param value VALUE
     */
    public void unlock(String key, String value) {
        try {
            String currentValue = String.valueOf(redisTemplate.opsForValue().get(key));
            if (!StringUtils.isEmpty(currentValue) && currentValue.equals(value)) {
                redisTemplate.opsForValue().getOperations().delete(key);
            }
        } catch (Exception e) {
            logger.error("[Redis分布式锁] 解锁异常: ", e);
        }
    }
}

RedisCacheUtil

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;


@Service("redisCacheUtil")
public class RedisCacheUtil {
//    @Qualifier("jedisTemplate")

    @Resource
    public RedisTemplate redisTemplate;

    /**
     * 缓存基本的对象,Integer、String、实体类等
     * @param key    缓存的键值
     * @param value    缓存的值
     * @return        缓存的对象
     */
    public <T> ValueOperations<String,T> setCacheObject(String key, T value) {
        ValueOperations<String,T> operation = redisTemplate.opsForValue();
        operation.set(key,value);
        return operation;
    }

//    public <T> ValueOperations<String,T> setCacheObject(String key, T value, Double timeout) {
//        ValueOperations<String,T> operation = redisTemplate.opsForValue();
//        operation.set.set().set(key,value, timeout);
//        return operation;
//    }

    /**
     * 获得缓存的基本对象。
     * @param key        缓存键值
     * @return            缓存键值对应的数据
     */
    public <T> T getCacheObject(String key) {
        ValueOperations<String,T> operation = redisTemplate.opsForValue();
        return operation.get(key);
    }

    /**
     * 缓存List数据
     * @param key        缓存的键值
     * @param dataList    待缓存的List数据
     * @return            缓存的对象
     */
    public <T> ListOperations<String, T> setCacheList(String key, List<T> dataList) {
        ListOperations listOperation = redisTemplate.opsForList();
        if(null != dataList) {
            int size = dataList.size();

            for(int i = 0; i < size ; i ++) {
                listOperation.rightPush(key,dataList.get(i));
            }
        }

        return listOperation;
    }

    /**
     * 获得缓存的list对象
     * @param key    缓存的键值
     * @return        缓存键值对应的数据
     */
    public <T> List<T> getCacheList(String key) {
        List<T> dataList = new ArrayList<T>();

        try {
            ListOperations<String, T> listOperation = redisTemplate.opsForList();
            Long size = listOperation.size(key);

            for (int i = 0; i < size; i++) {
                dataList.add((T) listOperation.leftPop(key));
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return dataList;
    }

    /**
     * 缓存Set
     * @param key        缓存键值
     * @param dataSet    缓存的数据
     * @return            缓存数据的对象
     */
    public <T> BoundSetOperations<String,T> setCacheSet(String key, Set<T> dataSet) {
        BoundSetOperations<String,T> setOperation = redisTemplate.boundSetOps(key);
        /*T[] t = (T[]) dataSet.toArray();
             setOperation.add(t);*/

        Iterator<T> it = dataSet.iterator();
        while(it.hasNext()) {
            setOperation.add(it.next());
        }

        return setOperation;
    }

//    /**
//     * 获得缓存的set
//     * @param key
//     * @return
//     */
//    public Set<T> getCacheSet(String key) {
//        Set<T> dataSet = new HashSet<T>();
//        BoundSetOperations<String,T> operation = redisTemplate.boundSetOps(key);
//
//        Long size = operation.size();
//
//        for(int i = 0 ; i < size ; i++) {
//            dataSet.add(operation.pop());
//        }
//        return dataSet;
//    }
//
//    /**
//     * 缓存Map
//     * @param key
//     * @param dataMap
//     * @return
//     */
//    public <T> HashOperations<String,String,T> setCacheMap(String key, Map<String,T> dataMap) {
//
//        HashOperations hashOperations = redisTemplate.opsForHash();
//        if(null != dataMap) {
//
//            for (Map.Entry<String, T> entry : dataMap.entrySet()) {
//                /*System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());  */
//                hashOperations.put(key,entry.getKey(),entry.getValue());
//            }
//        }
//
//        return hashOperations;
//    }

    /**
     * 获得缓存的Map
     * @param key
     * @return
     * ,HashOperations<String,String,T> hashOperation
     */
    public <T> Map<String,T> getCacheMap(String key) {
        Map<String, T> map = redisTemplate.opsForHash().entries(key);
        /*Map<String, T> map = hashOperation.entries(key);*/
        return map;
    }

    /**
     * 缓存Map
     * @param key
     * @param dataMap
     * @return
     */
    public <T> HashOperations<String,Integer,T> setCacheIntegerMap(String key,Map<Integer,T> dataMap) {
        HashOperations hashOperations = redisTemplate.opsForHash();

        if(null != dataMap) {
            for (Map.Entry<Integer, T> entry : dataMap.entrySet()) {
                /*System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());  */
                hashOperations.put(key,entry.getKey(),entry.getValue());
            }
        }

        return hashOperations;
    }

    /**
     * 获得缓存的Map
     * @param key
     * @return
     * ,HashOperations<String,String,T> hashOperation
     */
    public <T> Map<Integer,T> getCacheIntegerMap(String key) {
        Map<Integer, T> map = redisTemplate.opsForHash().entries(key);
        /*Map<String, T> map = hashOperation.entries(key);*/
        return map;
    }

    /**
     * 获取redis中以某些字符串为前缀的KEY列表
     * @param prefix key 前缀
     * @return 移除的个数
     */
    public Set<String> keySet(String prefix){
        Set<String> keys = redisTemplate.keys(prefix);
        return keys;
    }
}

返回信息

ResponseBean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
public class ResponseBean<T> {

    private Integer code = 0;

    private String msg = null;

    private T data = null;


    public ResponseBean() {
    }

    public ResponseBean(T data) {
        this.data = data;
    }

    public ResponseBean(String info, T data) {
        this.msg = info;
        this.data = data;
    }

    public ResponseBean(Integer code, String info, T data) {
        super();
        this.code = code;
        this.msg = info;
        this.data = data;
    }

    public ResponseBean(Integer code, String info) {
        super();
        this.code = code;
        this.msg = info;
    }

    public static <T> ResponseBean onSuccess() {
        ResponseBean<T> responseBean = new ResponseBean<>();
        responseBean.fillResponse(ResponseCode.Common.SUCCESS, null);
        return responseBean;
    }

    public static <T> ResponseBean onSuccess(ResponseCode.IResponseCode responseCode) {
        ResponseBean<T> responseBean = new ResponseBean<>();
        responseBean.fillResponse(responseCode, null);
        return responseBean;
    }


    public static <T> ResponseBean onSuccess(T data) {
        ResponseBean<T> result = new ResponseBean<>();
        result.fillResponse(ResponseCode.Common.SUCCESS, data);
        return result;
    }

    public static <T> ResponseBean onSuccess(ResponseCode.IResponseCode responseCode, T data) {
        ResponseBean<T> result = new ResponseBean<>();
        result.fillResponse(responseCode, data);
        return result;
    }


    public static ResponseBean onFailure(ResponseCode.IResponseCode responseCode) {
        return onFailure(responseCode, null);
    }

    public static <T> ResponseBean<T> onFailure(ResponseCode.IResponseCode responseCode, T data) {
        ResponseBean<T> responseBean = new ResponseBean<>();
        responseBean.fillResponse(responseCode, data);
        return responseBean;
    }

    public static <T> ResponseBean<T> onFailureMessage( String message) {
        ResponseBean<T> responseBean = new ResponseBean<>();
        responseBean.fillResponse(ResponseCode.Common.FAILURE, null);
        responseBean.setMsg(message);
        return responseBean;
    }

    public static <T> ResponseBean<T> onFailureMessage(ResponseCode.IResponseCode responseCode, String message) {
        ResponseBean<T> responseBean = new ResponseBean<>();
        responseBean.fillResponse(responseCode, null);
        responseBean.setMsg(message);
        return responseBean;
}



    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    private void fillResponse(ResponseCode.IResponseCode responseCode, T data) {
        setCode(responseCode.getCode());
        setMsg(responseCode.getMsg());
        setData(data);
    }

}

ResponseCode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import com.fasterxml.jackson.annotation.JsonFormat;

/**
 * 系统错误码: 16 01 001
 * 系统 模块 详细错误
 */
public class ResponseCode {

    @JsonFormat(shape = JsonFormat.Shape.OBJECT)
    public enum Common implements IResponseCode {
        /* 返回Code码 */
        SUCCESS(0, "成功"),
        FAILURE(-1, "失败"),
        INVALID_PARAMETER(400, "参数非法"),
        UNAUTHORIZED(401, "无权访问"),
        INTERFACE_EXCEPTION(402, "调用接口异常"),
        PARAM_EXCEED_LIMIT(403, "超过字数限制");

        private int code;
        private String msg;

        Common(int code, String msg) {
            this.code = code;
            this.msg = msg;
        }

        @Override
        public int getCode() {
            return code;
        }

        @Override
        public String getMsg() {
            return msg;
        }
    }

    @JsonFormat(shape = JsonFormat.Shape.OBJECT)
    public enum PreSaleQn implements IResponseCode {
        /* 返回Code码 */
        RECORD_ALREADY_EXISTS(1601001, "不可重复插入");

        private int code;
        private String msg;

        PreSaleQn(int code, String msg) {
            this.code = code;
            this.msg = msg;
        }

        @Override
        public int getCode() {
            return code;
        }

        @Override
        public String getMsg() {
            return msg;
        }
    }

    public interface IResponseCode {

        int getCode();

        String getMsg();

    }
}

ResultJson

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import com.alibaba.fastjson.JSONObject;
import com.fittime.common.util.DateUtils;
import com.fittime.common.util.enums.ResponseCodeEnums;
import lombok.Data;

import java.util.Date;

/**
 * @description: ResultJson
 */
@Data
public class ResultJson {

	private Integer returnCode;

    private Object object;

    private String returnDesc;

    private String currentTime;

    public ResultJson() {}

    private ResultJson(Integer returnCode, Object object, String returnDesc) {
        this.returnCode = returnCode;
        this.object = object;
        this.returnDesc = returnDesc;
        this.currentTime = DateUtils.dateToStr(new Date(), DateUtils.DEFAULTPATTERN);
    }

    /**
     * 成功操作返回数据
     * @param data data
     * @param <E> E
     * @return E
     */
    public static ResultJson success(Object data) {
        JSONObject jsonSucess = new JSONObject();
        jsonSucess.put("data", data);
        return new ResultJson(ResponseCodeEnums.SUCCESS.getReturnCode(), jsonSucess, ResponseCodeEnums.SUCCESS.getChMessage());
    }

    /**
     * 错误操作返回数据
     * @param returnCode 状态码
     * @param message 信息
     * @param <E> 泛型
     * @return ResultJson
     */
    public static ResultJson badRequest(int returnCode, String message) {
        JSONObject jsonBad = new JSONObject();
        jsonBad.put("data", null);
        return new ResultJson(returnCode, jsonBad, message);
    }

    /**
     * 错误操作返回数据
     * @return ResultJson
     */
    public static ResultJson badRequest() {
        JSONObject jsonBad = new JSONObject();
        jsonBad.put("data", null);
        return new ResultJson(ResponseCodeEnums.ERROR.getReturnCode(), jsonBad, ResponseCodeEnums.ERROR.getChMessage());
    }

    /**
     * 设置结果数据
     * @param resultJson ResultJson
     * @param data 数据
     */
    public static void setResultJson(ResultJson resultJson, Object data) {
        if (null != resultJson) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("data", null == data ? "" : data);
            resultJson.setObject(jsonObject);
            resultJson.setCurrentTime(DateUtils.dateToStr(new Date(), DateUtils.DEFAULTPATTERN));
        }
    }

}

枚举

ResponseCodeEnums

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/**
 * 服务返回状态枚举
 */
public enum ResponseCodeEnums {

    SUCCESS(200, "成功", "success"),
    ERROR(500, "系统异常", "error"),
    NAUTHORIZED(401, "未授权", "unauthorized"),
    ACCESSFORBIDDEN(403, "禁止访问", "access forbidden"),
    NOTFOUND(404, "您访问的资源不存在", "not found"),

    // 自定义的错误码建议从10000开始
    PLEASE_OPEN_IN_WEIXIN(10000, "请在微信中打开链接", ""),
    USERID_IS_NOT_NULL(10001, "userId不能为空", ""),
    SOURCE_IS_NULL(10002, "渠道码为空", ""),
    CLUETYPE_IS_NULL(10003, "clueType不能为空", ""),
    CLUETYPE_IS_ERROR(10004, "clueType只能为1或2", ""),
    QUESTIONNAIREAGE_NULL(10005, "questionnaireAge不能为空", ""),
    QUESTIONNAIREAGE_ERROR(10006, "questionnaireAge应为1~99整数", ""),
    YOU_ARE_BUSYING(10007, "不能操作太频繁哦!", ""),

    ;

    // 状态码
    private Integer returnCode;

    // 中文信息
    private String chMessage;

    // 英文信息
    private String enMessage;

    private ResponseCodeEnums(int returnCode, String chMessage, String enMessage) {
        this.returnCode = returnCode;
        this.chMessage = chMessage;
        this.enMessage = enMessage;
    }

    public Integer getReturnCode() {
        return returnCode;
    }

    public void setReturnCode(Integer returnCode) {
        this.returnCode = returnCode;
    }

    public String getChMessage() {
        return chMessage;
    }

    public void setChMessage(String chMessage) {
        this.chMessage = chMessage;
    }

    public String getEnMessage() {
        return enMessage;
    }

    public void setEnMessage(String enMessage) {
        this.enMessage = enMessage;
    }
}

跨域

CrossDomainFilter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 处理跨域
 */
@Configuration
public class CrossDomainFilter extends OncePerRequestFilter {

    private Logger log = LoggerFactory.getLogger(getClass());

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {
        log.info("跨域处理初始化......");
        response.setHeader("Access-Control-Allow-Origin", "*");
        //response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE, PATCH");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization, x-rjft-request");
        //response.setHeader("Access-Control-Expose-Headers", "Location");
        filterChain.doFilter(request, response);
	}

}

日期

DateUtils

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Stream;

/**
 * 日期工具类
 */
public class DateUtils {

    public static final String DEFAULTPATTERN = "yyyy-MM-dd HH:mm:ss";
    public static final String PATTERN_YYYY_MM_DD = "yyyy-MM-dd";
    public static final SimpleDateFormat NORMAL_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");

    /**
     * Date convert to string
     *
     * @param date    日期
     * @param pattern 时间规则
     * @return StringDate
     */
    public static String dateToStr(Date date, String pattern) {
        if (null != date) {
            SimpleDateFormat format = new SimpleDateFormat(pattern);
            return format.format(date);
        } else {
            return null;
        }
    }

    /**
     * 功能描述: LocalDateTime实现date2string(推荐)
     *
     * @param: [date, pattern]
     * @return: java.lang.String
     */
    public static String dateToStrByLocalDateTime(Date date, String pattern) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern);
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDate = instant.atZone(zoneId).toLocalDateTime();
        return df.format(localDate);
    }

    /**
     * 功能描述: LocalDate实现date2string(推荐)
     *
     * @param: [date, pattern]
     * @return: java.lang.String
     */
    public static String dateToStrByLocalDate(Date date, String pattern) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern);
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDate localDate = instant.atZone(zoneId).toLocalDate();
        return df.format(localDate);
    }

    /**
     * String to date
     *
     * @param str String
     * @return Date
     */
    public static Date stringToDate(String str) {
        DateFormat df = new SimpleDateFormat(DateUtils.PATTERN_YYYY_MM_DD);
        Date date = null;
        try {
            date = df.parse(str);
        } catch (ParseException e) {
        }
        return date;
    }


    /**
     * 功能描述: LocalDateTime实现string2date(推荐)
     *
     * @param: [dateStr]
     * @return: java.util.Date
     */
    public static Date stringToDateByLocalDateTime(String dateStr) {
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.parse(dateStr);
        ZonedDateTime zdt = localDateTime.atZone(zoneId);
        return Date.from(zdt.toInstant());
    }

    /**
     * 功能描述: LocalDate实现string2date(推荐)
     *
     * @param: [dateStr]
     * @return: java.util.Date
     */
    public static Date stringToDateByLocalDate(String dateStr) {
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDate localDate = LocalDate.parse(dateStr);
        ZonedDateTime zdt = localDate.atStartOfDay(zoneId);
        return Date.from(zdt.toInstant());
    }

    /**
     * 将时间字符串转换成时间戳
     *
     * @param dataStr
     * @return
     */
    public static long dataStr2Timestamp(String dataStr) {
        return Timestamp.valueOf(dataStr).getTime() / 1000;
    }

    /**
     * 给定一个时间计算距离现在的时间差精准到毫秒
     *
     * @param date 字符串时间
     * @return 相差时间毫秒数
     */
    public static long differentDateToNowsms(String date) {
        try {
            Date d = new SimpleDateFormat(DateUtils.DEFAULTPATTERN).parse(date);
            long daysms = System.currentTimeMillis() - d.getTime();
            return daysms;
        } catch (Exception e) {
        }
        return 0;
    }

    /**
     * 两个日期之间差值(毫秒)
     *
     * @param strDate1
     * @param strDate2
     * @param formatStr
     * @return -1 异常
     */
    public static long different2DateSms(String strDate1, String strDate2, String formatStr) {
        SimpleDateFormat format = new SimpleDateFormat(formatStr);
        try {
            Date dt1 = format.parse(strDate1);
            Date dt2 = format.parse(strDate2);
            return dt1.getTime() - dt2.getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return -1L;
    }

    /**
     * 计算两个日期相差的天数
     *
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @return
     */
    public static int different2DateDays(Date startDate, Date endDate) {
        return (int) ((endDate.getTime() - startDate.getTime()) / (3600 * 1000 * 24));
    }

    /**
     * 日期相差的周数
     *
     * @param source
     * @param date
     * @return
     */
    public static int different2DateWeek(Date source, Date date) {
        if (source.after(date)) {
            return 1;
        }
        int week = 0;
        Calendar cal = Calendar.getInstance();
        cal.setTime(source);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        while (true) {
            if (!calendar.before(cal)) {
                cal.add(Calendar.DAY_OF_YEAR, 7);
                week++;
            } else {
                break;
            }
        }
        return week;
    }


    /**
     * 功能描述: 当前日期
     *
     * @param: [dateStr]
     * @return: java.util.Date
     */
    public static Date localDate() {
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDate localDate = LocalDate.now();
        ZonedDateTime zdt = localDate.atStartOfDay(zoneId);
        return Date.from(zdt.toInstant());
    }


    /**
     * 功能描述: 计算2个日期是否为同一天
     *
     * @date: 2019/3/21 下午7:42
     * @param: [date1, date2]
     * @return: boolean
     */
    public static boolean isSameDate(Date date1, Date date2) {
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);

        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);

        //年月日都相同就是同一天
        boolean isSameYear = cal1.get(Calendar.YEAR) == cal2
                .get(Calendar.YEAR);
        boolean isSameMonth = isSameYear
                && cal1.get(Calendar.MONTH) == cal2.get(Calendar.MONTH);
        boolean isSameDate = isSameMonth
                && cal1.get(Calendar.DAY_OF_MONTH) == cal2
                .get(Calendar.DAY_OF_MONTH);
        return isSameDate;
    }


    /**
     * 获取当前时间的前n天或后n天
     *
     * @param format 格式化
     * @param day    -n 表示前 +n 表示后
     * @return String
     */
    public static String getBeforeOrAfterCurrentTime(String format, int day) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Date date = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, day);
        date = calendar.getTime();
        return sdf.format(date);
    }

    /**
     * 功能描述: 获得某个时间前几天的时间
     *
     * @param time     当前时间
     * @param num      前几天
     * @param haveTime true显示时间
     * @return java.util.String
     */
    public static String beforeDayByPoint(Date time, int num, boolean isBefore, boolean haveTime) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        if (isBefore) {
            // * 00:00:00
            calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
                    calendar.get(Calendar.DAY_OF_MONTH) - num, 0, 0, 0);
        } else {
            // * 23:59:59
            calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
                    calendar.get(Calendar.DAY_OF_MONTH) - num, 23, 59, 59);
        }
        if (haveTime) {
            // 生成时间带毫秒数如*.233,这里作用是去掉
            return dateToStr(calendar.getTime(), DEFAULTPATTERN);
        } else {
            return dateToStr(calendar.getTime(), PATTERN_YYYY_MM_DD);
        }
    }

    /**
     * 得到一个时间延后或前移几天的时间
     *
     * @param nowdate 日期
     * @param delay   delay为前移或后延的天数 正数为后推 负数为前推
     * @return
     */
    public static Date getNextOrPreDayByDate(Date nowdate, int delay) {
        try {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            long myTime = (nowdate.getTime() / 1000) + delay * 24 * 60 * 60;
            nowdate.setTime(myTime * 1000);
            return nowdate;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 获得起始日期和终止日期的所有区间内日期
     *
     * @param startLocalDate 开始日期
     * @param endLocalDate   截止日期
     * @return 区间内所有日期集合
     */
    public static List<LocalDate> getAllDateBetweenStartAndEnd(LocalDate startLocalDate, LocalDate endLocalDate) {
        List<LocalDate> resultList = new ArrayList();
        long betweenDays = ChronoUnit.DAYS.between(startLocalDate, endLocalDate);
        if (betweenDays < 1) {
            return resultList;
        }
        Stream.iterate(startLocalDate, localDate -> localDate.plusDays(1)).limit(betweenDays + 1).forEach(resultList::add);
        return resultList;
    }

    /**
     * 两个日期之间的比较
     *
     * @param dt1
     * @param dt2
     * @return 1 小于 2大于 0等于
     */
    public static int compareDate(Date dt1, Date dt2) {
        if (dt1.getTime() < dt2.getTime()) {
            return 1;
        } else if (dt1.getTime() > dt2.getTime()) {
            return 2;
        } else {
            return 0;
        }
    }

    /**
     * 两个日期之间的比较
     *
     * @param strDate1
     * @param strDate2
     * @param formatStr
     * @return 1 小于; 2 大于; 0 等于 ;-1 异常
     */
    public static int compare2Date(String strDate1, String strDate2, String formatStr) {
        SimpleDateFormat format = new SimpleDateFormat(formatStr);
        try {
            Date dt1 = format.parse(strDate1);
            Date dt2 = format.parse(strDate2);
            return compareDate(dt1, dt2);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return -1;
    }


    /**
     * 由出生日期获得年龄
     *
     * @param birthDay
     * @return
     * @throws Exception
     */
    public static int getAgeByBirthDay(Date birthDay) throws Exception {
        Calendar cal = Calendar.getInstance();

        if (cal.before(birthDay)) {
            throw new IllegalArgumentException(
                    "The birthDay is before Now.It's unbelievable!");
        }
        int yearNow = cal.get(Calendar.YEAR);
        int monthNow = cal.get(Calendar.MONTH);
        int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH);
        cal.setTime(birthDay);

        int yearBirth = cal.get(Calendar.YEAR);
        int monthBirth = cal.get(Calendar.MONTH);
        int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);

        int age = yearNow - yearBirth;

        if (monthNow <= monthBirth) {
            if (monthNow == monthBirth) {
                if (dayOfMonthNow < dayOfMonthBirth) {
                    age--;
                }
            } else {
                age--;
            }
        }
        return age;
    }

    /**
     * 功能描述: 根据年龄算生日
     * <p>
     * 当然这个时间是不准确的
     *
     * @auther: zemin.liu
     * @date: 2018/11/7 下午4:42
     * @param: [age, createtime]
     * @return: java.lang.String
     */
    public static Date getBirthdayByAge(int age) {

        Calendar c3 = Calendar.getInstance();
        c3.add(Calendar.YEAR, -age);
        return c3.getTime();
    }


    /**
     * 给定时间段和星期几,计算该时间段内共有多少个给定的星期几
     *
     * @param start 开始时间,格式yyyy-MM-dd
     * @param end   结束时间,格式yyyy-MM-dd
     * @param a     星期几,从星期一到星期天,分别用数字0-6表示,包含起始终止日期
     * @return 星期几统计数
     */
    public static long weekend(String start, String end, int a) {
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        long sunDay = 0;//计数
        try {
            Calendar startDate = Calendar.getInstance(); //开始时间
            startDate.setTime(format.parse(start));

            Calendar endDate = Calendar.getInstance();//结束时间
            endDate.setTime(format.parse(end));

            int SW = startDate.get(Calendar.DAY_OF_WEEK) - 1;//开始日期是星期几
            int EW = endDate.get(Calendar.DAY_OF_WEEK) - 1;//结束日期是星期几

            long diff = endDate.getTimeInMillis() - startDate.getTimeInMillis();
            long days = diff / (1000 * 60 * 60 * 24);//给定时间段内一共有多少天
            long w = Math.round(Math.ceil(((days + SW + (7 - EW)) / 7.0)));//给定时间内,共有多少个星期
            sunDay = w;//总的星期几统计数
            if (a < SW)//给定的星期几小于起始日期的星期几,需要减少一天
            {
                sunDay--;
            }
            if (a > EW)//给定的星期几大于结束日期的星期几,需要减少一天
            {
                sunDay--;
            }
        } catch (Exception se) {
            se.printStackTrace();
        }
        return sunDay;
    }

    /**
     * @description 计算两个日期间的日子
     * @Date: 2020/5/22 3:33 下午
     * @param: [begin, end]
     * @return: java.util.List<java.lang.String>
     */
    public static List<String> getDayListBetween(String begin, String end) throws ParseException {

        List<String> strDate = new ArrayList<>();
        strDate.add(begin);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(NORMAL_DATE_FORMAT.parse(begin));
        while (true) {
            calendar.add(Calendar.DAY_OF_MONTH, 1);
            if (NORMAL_DATE_FORMAT.parse(end).after(calendar.getTime())) {
                strDate.add(NORMAL_DATE_FORMAT.format(calendar.getTime()).toString());
            } else {
                break;
            }
        }
        if (!begin.equals(end)) {
            strDate.add(end);
        }
        return strDate;
    }

    /**
     * 判断日期是星期几
     *
     * @description
     * @Date: 2020/5/22 3:53 下午
     * @param: [dateStr]
     * @return: java.lang.String
     */
    public static String getWeekStr(String dateStr) throws ParseException {
        Date date = NORMAL_DATE_FORMAT.parse(dateStr);
        Calendar cal = Calendar.getInstance();
        if (date != null) {
            cal.setTime(date);
        }
        int week = cal.get(Calendar.DAY_OF_WEEK);
        switch (week) {
            case 1:
                return "星期日";
            case 2:
                return "星期一";
            case 3:
                return "星期二";
            case 4:
                return "星期三";
            case 5:
                return "星期四";
            case 6:
                return "星期五";
            case 7:
                return "星期六";
            default:
                return "";
        }
    }

    /**
     * 功能描述: 获得指定时间
     *
     * @param time      当前时间
     * @param hourOfDay 时
     * @param minute    分
     * @param second    秒
     * @return java.util.String
     */
    public static String dayTimePoint(Date time, int hourOfDay, int minute, int second) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
                calendar.get(Calendar.DAY_OF_MONTH), hourOfDay, minute, second);
        return dateToStr(calendar.getTime(), DEFAULTPATTERN);
    }

    /**
     * 判断当前时间是否在某个时间范围
     *
     * @param date    判断时间点
     * @param start   开始始时间,例如:yyyy-MM-dd HH:mm:ss
     * @param end     结束时间,例如:yyyy-MM-dd HH:mm:ss
     * @param pattern 时间格式化格式,例如:yyyy-MM-dd HH:mm:ss
     * @return boolean
     */
    public static boolean currentTimeInTime(Date date, String start, String end, String pattern) {
        try {
            SimpleDateFormat format = new SimpleDateFormat(pattern);
            Date startTime = format.parse(start);
            Date endTime = format.parse(end);
            return startTime.before(date) && endTime.after(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return false;
    }

}

国际日期

1
2
3
4
5
6
7
8
9
10
11
12
13
14
String x = "Mon Mar 02 13:57:49 CST 2015";
       SimpleDateFormat sdf1 = new SimpleDateFormat ("EEE MMM dd HH:mm:ss Z yyyy", Locale.UK);
       try
       {
       	    Date date=sdf1.parse(x);
           SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
           String sDate=sdf.format(date);
           System.out.println(sDate);
       }
       catch (ParseException e)
       {
           e.printStackTrace();
       }
//先把字符串转化成Date,再把Date转换成你想要的格式

IP地址

IpAddressUtil

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 */
public class IpAddressUtil {
    public static String getIpAddr(HttpServletRequest request) {
        String ipAddress = request.getHeader("x-forwarded-for");
        if (ipAddress == null || ipAddress.length() == 0 || CommonConstants.UNKNOWN.equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || CommonConstants.UNKNOWN.equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || CommonConstants.UNKNOWN.equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
            if (CommonConstants.LOCAL_HOST.equals(ipAddress) || CommonConstants.MAC_ADDR.equals(ipAddress)) {
                //根据网卡取本机配置的IP  
                InetAddress inet = null;
                try {
                    inet = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
                assert inet != null;
                ipAddress = inet.getHostAddress();
            }
        }
        // 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
        if (ipAddress != null && ipAddress.length() > CommonConstants.N15) {
            if (ipAddress.indexOf(CommonConstants.DOU_HAO) > 0) {
                ipAddress = ipAddress.substring(0, ipAddress.indexOf(CommonConstants.DOU_HAO));
            }
        }
        return ipAddress;
    }
}

IpUtil

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import com.alibaba.fastjson.JSON;
import com.fittime.common.constant.CommonConstants;
import lombok.extern.slf4j.Slf4j;
import org.lionsoul.ip2region.DataBlock;
import org.lionsoul.ip2region.DbConfig;
import org.lionsoul.ip2region.DbSearcher;
import org.lionsoul.ip2region.Util;

import java.io.File;
import java.lang.reflect.Method;
import java.util.Objects;


/**
 * 查询算法
 * DbSearcher.BINARY_ALGORITHM //Binary
 * DbSearcher.MEMORY_ALGORITYM //Memory
 * @createdate 2020-07-30 15:17
 */
@Slf4j
public class IpUtil {

    private static final String DBPATH = Objects.requireNonNull(IpUtil.class.getClassLoader().getResource("ip2region.db")).getPath();

    private static String getCityInfo(String ip) {

        File file = new File(DBPATH);

        if (!file.exists()) {
            log.info("[Error: Invalid ip2region.db file] {}", ip);
        }

        try {

            DbConfig config = new DbConfig();

            DbSearcher searcher = new DbSearcher(config, DBPATH);

            Method method = searcher.getClass().getMethod("btreeSearch", String.class);

            DataBlock dataBlock;
            if (!Util.isIpAddress(ip)) {
                log.info("[Error: Invalid ip address] {}", ip);
            }

            dataBlock = (DataBlock) method.invoke(searcher, ip);

            return dataBlock.getRegion();

        } catch (Exception e) {
            log.error("[IP获取地域错误]", e);
        }

        return null;
    }

    /**
     * 获取IP信息数组
     * 上海IP:114.80.166.240 ["中国","0","上海","上海市","电信"]
     * 北京IP:210.51.167.169 ["中国","0","北京","北京市","联通"]
     * 广州IP:192.168.1.157  ["中国","0","广东省","广州市","电信"]
     * 深圳IP:116.76.73.232 ["中国","0","广东省","深圳市","天威"]
     * 其它省份:["中国","0","山西省","临汾市","电信"]
     * 无效IP:["0","0","0","内网IP","内网IP"]
     * @param ip IP
     * @return String[]
     */
    public static String[] getIpInfos(String ip) {
        String ipStr = IpUtil.getCityInfo(ip);
        log.info("[根据IP获取到到地址信息] {}, {}", ip, ipStr);
        return Objects.requireNonNull(ipStr).split(CommonConstants.FEN_GE_FU);
    }

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        String ip = "116.76.73.233";
        System.out.println(JSON.toJSONString(IpUtil.getIpInfos(ip)));
        System.out.println("耗时:"+ (System.currentTimeMillis() - start));
    }

}

json相关

JacksonUtil

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class JacksonUtil {
	
	private static Logger log = LoggerFactory.getLogger(JacksonUtil.class);

	private static ObjectMapper objectMapper = new ObjectMapper();
	static {
		objectMapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);// 允许字段名不带引号
		objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
	}

	private static XmlMapper xmlMapper = new XmlMapper();

	/**
	 * map convert to xml string
	 * 
	 * @param obj
	 * @return
	 */
	public static String map2xml(Map<String, Object> map) {
		try {
			return xmlMapper.writeValueAsString(map);
		} catch (JsonProcessingException e) {
			log.error("map2xml error. map=" + map, e);
			return null;
		}
	}

	/**
	 * javabean,list,array convert to xml string
	 * 
	 * @param obj
	 * @return
	 */
	public static String obj2xml(Object obj) {
		try {
			return xmlMapper.writeValueAsString(obj);
		} catch (JsonProcessingException e) {
			// log.error("obj2xml error. obj=" + ToStringBuilder.reflectionToString(obj), e);
			return null;
		}
	}

	/**
	 * javaBean,list,array convert to json string
	 */
	public static String obj2json(Object obj) {
		try {
			return objectMapper.writeValueAsString(obj);
		} catch (JsonProcessingException e) {
			// log.error("obj2json error. obj=" + ToStringBuilder.reflectionToString(obj), e);
			return null;
		}
	}

	/**
	 * xml string convert to java bean
	 * 
	 * @param xmlStr
	 * @param clazz
	 * @return
	 */
	public static <T> T xml2pojo(String xmlStr, Class<T> clazz) {
		try {
			return xmlMapper.readValue(xmlStr, clazz);
		} catch (IOException e) {
			log.error("xml2pojo error. xml=" + xmlStr + "clazz=" + clazz, e);
			return null;
		}
	}

	/**
	 * json string convert to javaBean
	 */
	public static <T> T json2pojo(String jsonStr, Class<T> clazz) {
		try {
			return objectMapper.readValue(jsonStr, clazz);
		} catch (IOException e) {
			log.error("json2pojo error. json=" + jsonStr + ", clazz=" + clazz, e);
			return null;
		}
	}

	/**
	 * xml string convert to map
	 * 
	 * @param xmlStr
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static Map<String, Object> xml2map(String xmlStr) {
		try {
			return xmlMapper.readValue(xmlStr, Map.class);
		} catch (IOException e) {
			log.error("xml2map error. xml=" + xmlStr, e);
			return null;
		}
	}

	/**
	 * json string convert to map
	 */
	@SuppressWarnings("unchecked")
	public static <T> Map<String, Object> json2map(String jsonStr) {
		try {
			return objectMapper.readValue(jsonStr, Map.class);
		} catch (IOException e) {
			log.error("json2map error, json=" + jsonStr, e);
			return null;
		}
	}

	/**
	 * json string convert to map with javaBean
	 */
	public static <T> Map<String, T> json2map(String jsonStr, Class<T> clazz) {
		try {
			Map<String, Map<String, Object>> map = objectMapper.readValue(jsonStr, new TypeReference<Map<String, T>>() {
			});
			Map<String, T> result = new HashMap<String, T>();
			for (Entry<String, Map<String, Object>> entry : map.entrySet()) {
				result.put(entry.getKey(), objectMapper.convertValue(entry.getValue(), clazz));
			}
			return result;
		} catch (Exception e) {
			log.error("json2map error, json=" + jsonStr + ", clazz=" + clazz, e);
			return null;
		}
	}

	/**
	 * json array string convert to list with javaBean
	 */
	public static <T> List<T> json2list(String jsonArrayStr, Class<T> clazz) throws Exception {
		List<Map<String, Object>> list = objectMapper.readValue(jsonArrayStr, new TypeReference<List<T>>() {
		});
		List<T> result = new ArrayList<T>();
		for (Map<String, Object> map : list) {
			result.add(map2pojo(map, clazz));
		}
		return result;
	}

	/**
	 * map convert to javaBean
	 */
	@SuppressWarnings("rawtypes")
	public static <T> T map2pojo(Map map, Class<T> clazz) {
		return objectMapper.convertValue(map, clazz);
	}

	/**
	 * json string convert to xml string
	 */
	public static String json2xml(String jsonStr) throws Exception {
		JsonNode root = objectMapper.readTree(jsonStr);
		String xml = xmlMapper.writeValueAsString(root);
		return xml;
	}

	/**
	 * xml string convert to json string
	 */
	public static String xml2json(String xml) throws Exception {
		StringWriter w = new StringWriter();
		JsonParser jp = xmlMapper.getFactory().createParser(xml);
		JsonGenerator jg = objectMapper.getFactory().createGenerator(w);
		while (jp.nextToken() != null) {
			jg.copyCurrentEvent(jp);
		}
		jp.close();
		jg.close();
		return w.toString();
	}

}

JSONUtils

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class JSONUtils {

    private static final ObjectMapper MAPPER = new ObjectMapper();

    private JSONUtils() {
    }

    public static String writeString(Object o) {
        if (o != null) {
            try {
                return MAPPER.writeValueAsString(o);
            } catch (JsonProcessingException ignored) {
                log.error("JSONUtils writeString exception {}", ignored);
            }
        }
        return "";
    }

    public static <T> T readValue(String json, JavaType javaType) {
        if (StringUtils.isNotEmpty(json)) {
            try {
                return MAPPER.readValue(json, javaType);
            } catch (IOException ignored) {
                log.error("JSONUtils readValue exception {}", ignored);
            }
        }
        return null;
    }

    public static <T> T readValue(String json, Class<T> clazz) {
        if (StringUtils.isNotEmpty(json)) {
            try {
                return MAPPER.readValue(json, clazz);
            } catch (IOException ignored) {
                log.error("JSONUtils readValue exception {}", ignored);
            }
        }
        return null;
    }

    public static <T> List<T> readListValue(String json, Class<T> clazz) {
        if (StringUtils.isNotEmpty(json)) {
            JavaType javaType = MAPPER.getTypeFactory().constructParametricType(ArrayList.class, clazz);
            try {
                return  MAPPER.readValue(json, javaType);
            } catch (IOException ignored) {
                log.error("JSONUtils readListValue exception {}", ignored);
            }
        }
        return null;
    }
}

JsonSerializationUtil

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.List;

/**
 * Jackson json序列化和反序列化工具类
 * Created by macro on 2018/4/26.
 */
public class JsonUtil {

    // 定义jackson对象
    private static final ObjectMapper MAPPER = new ObjectMapper();

    /**
     * 将对象转换成json字符串。
     */
    public static String objectToJson(Object data) {
        try {
            String string = MAPPER.writeValueAsString(data);
            return string;
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 将json结果集转化为对象
     *
     * @param jsonData json数据
     * @param beanType 对象中的object类型
     */
    public static <T> T jsonToPojo(String jsonData, Class<T> beanType) {
        try {
            T t = MAPPER.readValue(jsonData, beanType);
            return t;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 将json数据转换成pojo对象list
     */
    public static <T> List<T> jsonToList(String jsonData, Class<T> beanType) {
        JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
        try {
            List<T> list = MAPPER.readValue(jsonData, javaType);
            return list;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

}

ReadJsonFileUtil

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ClassPathResource;

import java.io.InputStreamReader;
import java.io.Reader;
import java.util.List;
import java.util.Map;

/**
 * 对json文件的读操作
 */
public class LocalJSONFileUtil {
    /**
     * 根据key获取json
     * @param filepath 文件路径
     * @param key json的key
     * @return
     */
    public static Object getJSONByKey(String filepath, String key){
       String text =  LocalJSONFileUtil.getFileText(filepath);
        JSONObject object = new JSONObject();
       if (StringUtils.isNoneBlank(text)){
            object = parseObject(text);
       }
        return object.get(key);
    }

    /**
     * 将json 字符串转换为json对象
     */
    public static JSONObject parseObject(String text) {
        return JSONObject.parseObject(text);
    }

    /**
     * 获取文件内文本
     * @param filepath
     * @return
     */
    public static String getFileText(String filepath){
        StringBuffer sb = new StringBuffer();
        try{
            ClassPathResource classPathResource = new ClassPathResource(filepath);
            Reader reader = new InputStreamReader(classPathResource.getInputStream());
            int ch = 0;
            while ((ch = reader.read())!=-1){
                sb.append((char)ch);
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString().replaceAll("\r\n","").replaceAll(" ", "");
    }

}

class Text{

    public static void main(String[] args) {
        System.out.println("获取json文本,也可以获取txt文本");
        String textJOSN = LocalJSONFileUtil.getFileText("templates/localJSON.json");
        System.out.println(textJOSN); //{  "key1": "value1",  "key2": "value2",  "key3": [{"key1": "value1"},{"key2": "value2"}]}
        String txt = LocalJSONFileUtil.getFileText("templates/localJSON.txt"); // 测试文本
        System.out.println(txt);
//        LocalJSONFileUtil.getJSONByKey()
        System.out.println("=============通过key获取对象=================");
        String key2 = (String) LocalJSONFileUtil.getJSONByKey("templates/localJSON.json","key2");
        System.out.println("key2:"+key2); // key2:value2
        List<Map<String,Object>> key3 = (List<Map<String, Object>>) LocalJSONFileUtil.getJSONByKey("templates/localJSON.json","key3");
        System.out.println(key3); // [{"key1":"value1"},{"key2":"value2"}]
        Map<String,Object> key4 = (Map<String, Object>) LocalJSONFileUtil.getJSONByKey("templates/localJSON.json","key4");
        System.out.println(key4); //{"key1":"value1"}

        System.out.println("=========获取整体json对象=============");
        Map<String,Object> objectMap = LocalJSONFileUtil.parseObject(LocalJSONFileUtil.getFileText("templates/localJSON.json"));
        System.out.println(objectMap.get("key1")); // value1

        Map<String,Object> objectMap2 = JSONObject.parseObject(LocalJSONFileUtil.getFileText("templates/localJSON.json"));
        System.out.println(objectMap2.get("key1"));

        System.out.println("向文本内写入值,一般工作中没有这个需求,思路也很简单,封装个方法,参数为,路径,key,value, 通过路径读取JSON到程序,通过map的put方法向json中put值,最后将数据再次写入到JSON文件内就行了");

    }
}

线程池相关

ThreadPoolUtils

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import java.util.Collection;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 线程工具类
 */
public class ThreadPoolUtils {

    public static AtomicInteger ai = new AtomicInteger(0);

    /** 线程池基本参数*/
    private static int corePoolSize = Runtime.getRuntime().availableProcessors(),
    		maxPoolSize = 200,keepAliveTime = 30,queueCapacity = 100;
    
    
    private static ThreadPoolExecutor threadPool = new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveTime,
            TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(queueCapacity),
            new ThreadPoolExecutor.CallerRunsPolicy());

    public static void addProcess(Runnable runnable){
        try {
            threadPool.execute(runnable);
        } catch (Exception e) {
        //	log.error("调用线程池的addProcess方法出错", e);
        }
    }

    public static <T> Future<T> addTask(Callable<T> task){
        return threadPool.submit(task);
    }

    public static <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks){
        try {
			return threadPool.invokeAll(tasks);
		} catch (InterruptedException e) {
			e.printStackTrace();
		//	log.error("调用线程池的invokeAll方法出错", e);
		}
        return null;
    }

    public static <T> T invokeAny(Collection<? extends Callable<T>> tasks){
        try {
			return threadPool.invokeAny(tasks);
		} catch (Exception e) {
			e.printStackTrace();
		//	log.error("调用线程池的invokeAny方法出错", e);
		}
        return null;
    }

}

拦截器相关

InterfaceLoggerFilter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fittime.ecom.common.constants.CommonConstant;
import com.fittime.ecom.common.util.IpAddressUtil;

/**
 * 项目接口拦截器处理
 */
public class InterfaceLoggerFilter implements Filter {

	private Logger logger = LoggerFactory.getLogger(InterfaceLoggerFilter.class);


	@Override
	public void init(FilterConfig filter) throws ServletException {

	}
	
	@Override
	public void destroy() {

	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		long startTime, endTime;
		Map<String,String[]> params = new HashMap<String,String[]>(request.getParameterMap());
		
		StringBuffer sbParams = new StringBuffer();
		sbParams.append("?");
		
		for (String key : params.keySet()) {
			if(null == key || null == params.get(key) || null == params.get(key)[0]){  continue;}
			sbParams.append(key).append("=").append(params.get(key)[0]).append("&");
        }
		
		if(sbParams.length() > 1) {sbParams = sbParams.delete(sbParams.length() - 1, sbParams.length());}
		
		String fullUrl = ((HttpServletRequest)request).getRequestURL().toString();
		String token = getToken((HttpServletRequest)request);
		String requestType = ((HttpServletRequest)request).getMethod();
		String userId = request.getParameter("userId");

		//前置条件:将不符合条件的URL地址予以过滤
		if(null == fullUrl) {
			chain.doFilter(request, response);
			return;
		}
		int re1=fullUrl.indexOf(".json");
		int re2=fullUrl.indexOf(".html");
		int re3=fullUrl.indexOf("index.html");
		if((re1 == -1 && re2 == -1) || re3 != -1){
			chain.doFilter(request, response);
			return;
		}
		
		//前置条件:token为空情况处理
		if(null == token) {
			logger.info(formMapKey(userId, "token is null url=" + fullUrl, requestType,
					IpAddressUtil.getIpAddr((HttpServletRequest)request), sbParams.toString(), "null") 
					+ ",\"cost\":\"" + 0 + "ms\"");
			chain.doFilter(request, response);
			return;
		}
		
		//前置条件:所有异常统一捕捉处理
		try {
			startTime = System.currentTimeMillis();
			chain.doFilter(request, response);
			endTime = System.currentTimeMillis();

			int startIntercept = fullUrl.lastIndexOf("/") + 1;
			int endIntercept = fullUrl.lastIndexOf(".json");

			String interfaceName = fullUrl.substring(startIntercept, endIntercept) + ".json";

			logger.info(formMapKey(userId, interfaceName, requestType,
					IpAddressUtil.getIpAddr((HttpServletRequest) request), sbParams.toString(), token)
					+ ",\"cost\":\"" + (endTime - startTime) + "ms\"");
		} catch (Exception ex) {
			chain.doFilter(request, response);
			logger.info("项目接口监控异常fullUrl:" + fullUrl + " message:" + ex.getMessage());
		}
	}
	
	private String formMapKey(Object userId, String mothedName, String requestType, 
			String ip, String params, String token) {
		return "\"time\"" + ":\"" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").format(new Date()) 
				+ "\",\"name\"" + ":\"" + mothedName + "\",\"uid\":\"" + userId 
				+ "\",\"type\":\"" + requestType + "\",\"ip\":\"" + ip 
				+ "\",\"token\":\"" + token + "\",\"params\":\"" + params + "\"";
	}
	
	private String getRequestType(HttpServletRequest request) {
		String ajaxHeader = request.getHeader(CommonConstant.AJAX_REQUEST_HEADER_KEY);
		if (ajaxHeader != null && ajaxHeader.equalsIgnoreCase(CommonConstant.AJAX_REQUEST_HEADER_VALUE)) {
			return "ajax";
		}
		String nativeValue = request.getHeader(CommonConstant.AJAX_NATIVE_HEADER_KEY);
		if (nativeValue != null && nativeValue.equalsIgnoreCase(CommonConstant.AJAX_NATIVE_HEADER_VALUE)) {
			return "native";
		}

		return "web";
	}
	
	private String getToken(HttpServletRequest request) {
		String token = request.getHeader(CommonConstant.AJAX_REQUEST_TOKEN_KEY);
		if(StringUtils.isNotBlank(token)){
			//Bearer xxxxxx  (xxxxxx 是 token)
			String[] temp = token.split(" ");
			if(temp.length > 1){
				return temp[1];
			}
		}
		return null;
	}

}

数字运算相关

Arith

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import java.math.BigDecimal;

public class Arith {
    private static final int DEF_DIV_SCALE = 10;

    /**
     * * 两个Double数相加 *
     *
     * @param v1 *
     * @param v2 *
     * @return Double
     */
    public static Double add(Double v1, Double v2) {
        BigDecimal b1 = new BigDecimal(v1.toString());
        BigDecimal b2 = new BigDecimal(v2.toString());
        return new Double(b1.add(b2).doubleValue());
    }

    public static Double add(Double v1, Double v2, Double v3) {
        BigDecimal b1 = new BigDecimal(v1.toString());
        BigDecimal b2 = new BigDecimal(v2.toString());
        BigDecimal b3 = new BigDecimal(v3.toString());
        return new Double(b1.add(b2).add(b3).doubleValue());
    }

    /**
     * * 两个Double数相减 *
     *
     * @param v1 *
     * @param v2 *
     * @return Double
     */
    public static Double sub(Double v1, Double v2) {
        BigDecimal b1 = new BigDecimal(v1.toString());
        BigDecimal b2 = new BigDecimal(v2.toString());
        return new Double(b1.subtract(b2).doubleValue());
    }

    /**
     * * 两个Double数相乘 *
     *
     * @param v1 *
     * @param v2 *
     * @return Double
     */
    public static Double mul(Double v1, Double v2) {
        BigDecimal b1 = new BigDecimal(v1.toString());
        BigDecimal b2 = new BigDecimal(v2.toString());
        return new Double(b1.multiply(b2).doubleValue());
    }

    /**
     * * 两个Double数相除 *
     *
     * @param v1 *
     * @param v2 *
     * @return Double
     */
    public static Double div(Double v1, Double v2) {
        BigDecimal b1 = new BigDecimal(v1.toString());
        BigDecimal b2 = new BigDecimal(v2.toString());
        return new Double(b1.divide(b2, DEF_DIV_SCALE, BigDecimal.ROUND_HALF_UP)
                .doubleValue());
    }

    /**
     * * 两个Double数相除,并保留scale位小数 *
     *
     * @param v1    *
     * @param v2    *
     * @param scale *
     * @return Double
     */
    public static Double div(Double v1, Double v2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(v1.toString());
        BigDecimal b2 = new BigDecimal(v2.toString());
        return new Double(b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue());
    }
}  

图片相关

CompressorUtil

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import javax.imageio.stream.MemoryCacheImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Iterator;

/**
 * @description: 图片压缩工具类
 */
public class CompressorUtil {

    /**
     * 	This ratio that indicating the desired quality level, it is between 0 and 1
     */
    private static final float IMAGE_QUALITY_LEVEL = 0.6f;

    /**
     * 方式1:根据文件方式操作
     *
     * @param src 原文件地址
     * @param dest 生成图片地址
     * @return void
     */
    public static void resize(String src, String dest) throws IOException {
        // file转为图片对象
        Image img = ImageIO.read(new File(src));
        BufferedImage tempPNG = resizeImage(img);
        // 裁剪不压缩,存储
        // ImageIO.write(tempPNG, "png", new File(dest));
        // 压缩后输出
        compress(tempPNG, dest);
    }

    /**
     * 方式1:根据文件方式操作
     *
     * @param byteArrayDoc 原文件字节数组
     * @return byte[] 生成图片字节数组
     */
    public static byte[] resize(byte[] byteArrayDoc) throws IOException {
        // 字节数组转为图片对象
        Image img = ImageIO.read(new ByteArrayInputStream(byteArrayDoc));
        BufferedImage tempPNG = resizeImage(img);
        // 裁剪不压缩,存储
        // ImageIO.write(tempPNG, "png", new File(dest));
        // 压缩后输出
        return compress(tempPNG);
    }

    /**
     * 压缩图片逻辑(操作字节数组)
     *
     * @param image BufferedImage对象
     * @return 返回字节数组
     */
    private static byte[] compress(BufferedImage image) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        MemoryCacheImageOutputStream imageOutput = new MemoryCacheImageOutputStream(output);

        // 必须写此参数
        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
        ImageWriter writer = writers.next();
        // 建立输出通道
        writer.setOutput(imageOutput);

        // 设置压缩参数
        ImageWriteParam param = writer.getDefaultWriteParam();
        // 必须写此参数
        param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        param.setCompressionQuality(IMAGE_QUALITY_LEVEL);

        // 写入流数据
        writer.write(null, new IIOImage(image, null, null), param);
        if(output != null){
            output.close();
        }
        if(imageOutput != null){
            imageOutput.close();
        }
        if(writer != null){
            writer.dispose();
        }

        return output.toByteArray();
    }

    /**
     * 压缩图片逻辑(操作文件)
     *
     * @param image BufferedImage对象
     * @param dest 生成图片保存地址
     */
    private static void compress(BufferedImage image, String dest) throws IOException {
        OutputStream output = new FileOutputStream(new File(dest));
        ImageOutputStream imageOutput = ImageIO.createImageOutputStream(output);

        // 必须写此参数
        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
        ImageWriter writer = writers.next();
        // 建立输出通道
        writer.setOutput(imageOutput);

        // 设置压缩参数
        ImageWriteParam param = writer.getDefaultWriteParam();
        // 必须写此参数
        param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        param.setCompressionQuality(IMAGE_QUALITY_LEVEL);

        // 写入流数据
        writer.write(null, new IIOImage(image, null, null), param);
        if(output != null){
            output.close();
        }
        if(imageOutput != null){
            imageOutput.close();
        }
        if(writer != null){
            writer.dispose();
        }
    }

    /**
     * 设置生成图片大小
     * @param image
     * @return java.awt.image.BufferedImage
     */
    private static BufferedImage resizeImage(Image image) {
        // 可设置生成图片大小,这里与原图一样
        int width = ((BufferedImage) image).getWidth();
        int height = ((BufferedImage) image).getHeight();

        BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        // 创建graph2D,用来将image写入bufferedImage
        Graphics2D graphics2D = bufferedImage.createGraphics();
        graphics2D.setComposite(AlphaComposite.Src);
        // below three lines are for RenderingHints for better image quality at cost of higher processing time
        graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        graphics2D.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        graphics2D.drawImage(image, 0, 0, width, height, null);
        graphics2D.dispose();
        return bufferedImage;
    }

}

DownImage

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * @description: 从网络下载图片
 */
public class DownImage {

    private static Logger log = LoggerFactory.getLogger(DownImage.class);

    private final static String OSS_URL = "fop-hotcamp-resource.rjfittime.com";
    private final static String OSS_URL_INTERNAL = "fop-hotcamp-resource.oss-cn-beijing-internal.aliyuncs.com";

    /**
     * 从网络下载图片到本地
     * @param imageUrl : 网络图片URL
     */
    public void saveToFile(String imageUrl) {
        FileOutputStream fos = null;
        BufferedInputStream bis = null;
        HttpURLConnection httpUrl = null;
        URL url;
        int bufferSize = 1024;
        byte[] buf = new byte[bufferSize];
        int size;
        try {
            url = new URL(imageUrl);
            httpUrl = (HttpURLConnection) url.openConnection();
            httpUrl.connect();
            bis = new BufferedInputStream(httpUrl.getInputStream());
            fos = new FileOutputStream("/Users/guiping.liang/1.png");
            while ((size = bis.read(buf)) != -1) {
                fos.write(buf, 0, size);
            }
            fos.flush();
        } catch (IOException | ClassCastException ignored) {
        } finally {
            try {
                assert fos != null;
                fos.close();
                bis.close();
                httpUrl.disconnect();
            } catch (IOException | NullPointerException ignored) {
            }
        }
    }

    /**
     * 网络图片url 转 BufferedImage 对象
     * @param imageUrl :网络图片URL
     * @param applyId  :报名记录号
     * @return         :BufferedImage
     */
    public static BufferedImage getBufferedImageByUrl(String imageUrl, long applyId) {
        String pic = getOssUrlInternal(imageUrl);
        log.info("[从客户端传过来的饼图片RUL] {}, {}, {}", imageUrl, applyId, pic);
        BufferedInputStream bis = null;
        URL url;
        HttpURLConnection httpUrl = null;
        try {
            url = new URL(pic);
            httpUrl = (HttpURLConnection) url.openConnection();
            httpUrl.connect();
            bis = new BufferedInputStream(httpUrl.getInputStream());
            return ImageIO.read(bis);
        } catch (Exception e) {
            log.error("[网络图片url 转 BufferedImage 对象出错] {}, {}", e, applyId);
            return null;
        } finally {
            try {
                if (bis != null) {
                    bis.close();
                }
                if (httpUrl != null) {
                    httpUrl.disconnect();
                }
            } catch (Exception ex) {
                log.error("[关闭对象出错] {}, {}", ex, applyId);
            }
        }
    }

    /**
     * 网络图片url 转 BufferedImage 对象走内网地址
     * @param imageUrl :网络图片URL
     * @param applyId  :报名记录号
     * @return         :BufferedImage
     */
    private static BufferedImage getBufferedImageByUrlAgain(String imageUrl, long applyId) {

        log.info("[走内网地址] {}, {}", imageUrl, applyId);

        if (imageUrl.contains(OSS_URL)) {
            imageUrl = imageUrl.replace(OSS_URL, OSS_URL_INTERNAL);
        }

        BufferedInputStream bis = null;
        URL url;
        HttpURLConnection httpUrl = null;
        try {
            url = new URL(imageUrl);
            httpUrl = (HttpURLConnection) url.openConnection();
            httpUrl.connect();
            bis = new BufferedInputStream(httpUrl.getInputStream());
            return ImageIO.read(bis);
        } catch (Exception e) {
            log.error("[getBufferedImageByUrlAgain.error] {}, {}", applyId, e);
        } finally {
            try {
                if (bis != null) {
                    bis.close();
                }
                if (httpUrl != null) {
                    httpUrl.disconnect();
                }
            } catch (Exception ex) {
                log.error("[getBufferedImageByUrlAgain.source.error] {}, {}", applyId, ex);
            }
        }
        return null;
    }

    public static String getOssUrlInternal(String imageUrl) {
        if (imageUrl.contains(OSS_URL)) {
            imageUrl = imageUrl.replace(OSS_URL, OSS_URL_INTERNAL);
        }
        return imageUrl;
    }


    public static void main(String[] args) {
        String a = "https://fop-hotcamp-resource.rjfittime.com/158755074291609685229851377883";
//        BufferedImage pieChart = getBufferedImageByUrlAgain(a, 66078);
//        assert pieChart != null;
//        System.out.println(pieChart.getWidth());
//        System.out.println(pieChart.getHeight());

        System.out.println(getOssUrlInternal(a));

    }


}

对象拷贝相关

CopyUtils

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

import java.util.HashSet;
import java.util.Set;

/**
 * @description 重写BeanUtils.copyProperties方法
 */
public class CopyUtils {
    /**
     *
     * 功能描述: BeanUtils.copyProperties默认没有提供设置忽略null属性
     *
     * @param source
     * @return java.lang.String[]
     */
    private static String[] getNullPropertyNames (Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();

        Set<String> emptyNames = new HashSet<String>();
        for(java.beans.PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null) {
                emptyNames.add(pd.getName());
            }
        }
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }
  
  

    /**
     *
     * 功能描述: 工具入口
     *
     * @param src
     * @param target
     * @return void
     */
    public static void copyProperties(Object src, Object target) {
        BeanUtils.copyProperties(src, target, getNullPropertyNames(src));
    }
}

表情相关

EmojiUtil

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import org.apache.commons.lang3.StringUtils;

/**
 * 表情符号工具类定义

 */
public class EmojiUtil {
    private static boolean isEmojiCharacter(char codePoint) {
        return (codePoint == 0x0) || (codePoint == 0x9) || (codePoint == 0xA)
                || (codePoint == 0xD)
                || ((codePoint >= 0x20) && (codePoint <= 0xD7FF))
                || ((codePoint >= 0xE000) && (codePoint <= 0xFFFD))
                || ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF));
    }

    /**
     * 过滤emoji 或者 其他非文字类型的字符
     *
     * @param source
     * @return
     */
    public static String filterEmoji(String source) {
        if (StringUtils.isBlank(source)) {
            return source;
        }
        StringBuilder buf = null;
        int len = source.length();
        for (int i = 0; i < len; i++) {
            char codePoint = source.charAt(i);
            if (isEmojiCharacter(codePoint)) {
                if (buf == null) {
                    buf = new StringBuilder(source.length());
                }
                buf.append(codePoint);
            }
        }
        if (buf == null) {
            return source;
        } else {
            if (buf.length() == len) {
                buf = null;
                return source;
            } else {
                return buf.toString();
            }
        }
    }
}

Excel相关

ExcelUtil

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;

public class ExcelUtil {

    private static Logger log = LoggerFactory.getLogger(ExcelUtil.class);

    public static final String EXCEL_2003_SUFFIX = ".xls";
    public static final String EXCEL_2007_SUFFIX = ".xlsx";



    public static Workbook createWorkBookUsingAnnotation(String fileName, String sheetName, List<?> excelBeanList) {
        long startTime = System.currentTimeMillis();
        log.info("导出订单createWorkBookUsingAnnotation start" + startTime + "ms");
        Workbook workbook = null;
        if (fileName.toLowerCase().endsWith(EXCEL_2003_SUFFIX)) {
            workbook = new HSSFWorkbook();
        }
        if (fileName.toLowerCase().endsWith(EXCEL_2007_SUFFIX)) {
            workbook = new XSSFWorkbook();
        }
        // 创建sheet对象
        Sheet sheet = workbook.createSheet(sheetName);
        Row headRow = sheet.createRow(0);

        // 设置样式
        // 行首各个列的样式
        CellStyle topStyle = workbook.createCellStyle();
        topStyle.setAlignment(CellStyle.ALIGN_CENTER);
        // 设置字体
        Font font = workbook.createFont();
        // 设置字体大小
        font.setFontHeightInPoints((short) 11);
        // 字体加粗
        font.setBoldweight(Font.BOLDWEIGHT_BOLD);
        // 设置字体名字
        font.setFontName("黑体");
        topStyle.setFont(font);

        // 列内容样式
        CellStyle style = workbook.createCellStyle();
        style.setAlignment(CellStyle.ALIGN_CENTER);

        List<Field> columnNameList = new ArrayList<>();
        if (excelBeanList != null && excelBeanList.size() != 0) {
            Field[] declaredFields = excelBeanList.get(0).getClass().getDeclaredFields();
            for (Field field : declaredFields) {
                field.setAccessible(true);

                ExcelColumn column = field.getAnnotation(ExcelColumn.class);
                if (column != null) {
                    columnNameList.add(field);
                    Cell cell = headRow.createCell(column.odinal());
                    try {
                        cell.setCellStyle(topStyle);
                        // 设置excel表格首行中各个列名
                        cell.setCellValue(column.columnName());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            Collections.sort(columnNameList, (a, b) -> {
                return a.getAnnotation(ExcelColumn.class).odinal() - b.getAnnotation(ExcelColumn.class).odinal();
            });
            Map<Field, Method> getMethodMap = new HashMap<>();
            CreationHelper createHelper = workbook.getCreationHelper();
            CellStyle hlinkStyle = workbook.createCellStyle();
            Font hlinkFont = workbook.createFont();
            hlinkFont.setUnderline(Font.U_SINGLE);
            hlinkFont.setColor(IndexedColors.BLUE.getIndex());
            hlinkStyle.setFont(hlinkFont);

            Row row = null;
            Method getMethod = null;
            String getMethodName = null;
            Object fieldVal = null;
            Cell cell = null;
            Hyperlink link = null;

            for (int i = 0; i < excelBeanList.size(); i++) {
                row = sheet.createRow(i + 1);
                for (Field field : columnNameList) {
                    try {
                        getMethod = getMethodMap.get(field);
                        if (getMethod == null) {
                            getMethodName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
                            getMethod = excelBeanList.get(i).getClass().getMethod(getMethodName);
                            getMethod.setAccessible(true);
                            getMethodMap.put(field, getMethod);
                        }
                        fieldVal = getMethod.invoke(excelBeanList.get(i));
                        cell = row.createCell(field.getAnnotation(ExcelColumn.class).odinal());
                        if (fieldVal != null) {
                            //如果cell内容是链接,则生成超链接样式
                            if (fieldVal.toString().startsWith("http")) {
                                link = createHelper.createHyperlink(Hyperlink.LINK_URL);
                                link.setAddress(fieldVal.toString());
                                cell.setHyperlink(link);
                                cell.setCellStyle(hlinkStyle);
                            } else {
                                cell.setCellStyle(style);
                            }
                            cell.setCellValue(fieldVal.toString());
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }

            // 让列宽随着导出的列长自动适应
            processColumnWidth(sheet, columnNameList.size());
            System.err.println("导出订单createWorkBookUsingAnnotation total cost:" + (System.currentTimeMillis() - startTime) + "ms");
        }
        return workbook;
    }





    /**
     * 根据输入的值获取合法的值(非空,浮点到string)
     *
     * @param value 输入的值对象
     * @return
     */
    public static String getLegalValue(Object value) {
        if (null == value) {
            return "";
        }

        return String.valueOf(value);
    }

    public static void processColumnWidth(Sheet sheet, int columns) {
        int columnWidth = 0;
        Row currentRow = null;
        Cell currentCell = null;
        int length = 0;

        for (int colNum = 0; colNum < columns; colNum++) {
            columnWidth = sheet.getColumnWidth(colNum) / 256;
            for (int rowNum = 0; rowNum < sheet.getLastRowNum(); rowNum++) {
                // 当前行未被使用过
                if (sheet.getRow(rowNum) == null) {
                    currentRow = sheet.createRow(rowNum);
                } else {
                    currentRow = sheet.getRow(rowNum);
                }

                if (currentRow.getCell(colNum) != null) {
                    currentCell = currentRow.getCell(colNum);
                    if (currentCell.getCellType() == HSSFCell.CELL_TYPE_STRING) {
                        length = currentCell.getStringCellValue().length();
                        if (columnWidth < length) {
                            columnWidth = length;
                        }
                    }
                }
            }

            if (colNum == 0) {
                sheet.setColumnWidth(colNum, (columnWidth - 2) * 256);
            } else {
                if (columnWidth > 250) {
                    columnWidth = 250;
                }
                sheet.setColumnWidth(colNum, (columnWidth + 4) * 256);
            }
        }
    }

    /**
     * 解决不同浏览器下载文件时,中文文件名乱码问题
     *
     * @param request
     * @param fileNames
     * @return
     */
    public static String processFileName(HttpServletRequest request, String fileNames) {
        String codedfilename = null;
        try {
            String agent = request.getHeader("User-Agent");
            if (agent != null) {
                // ie edge
                if (agent.indexOf("MSIE") != -1 || agent.indexOf("Trident") != -1 || agent.indexOf("Edge") != -1) {
                    codedfilename = java.net.URLEncoder.encode(fileNames, "UTF8");
                } else if (agent.indexOf("Firefox") != -1 || agent.indexOf("Chrome") != -1 || agent.indexOf("Safari") != -1) {
                    // 火狐,chrome等
                    codedfilename = new String(fileNames.getBytes("UTF-8"), "iso-8859-1");
                } else {
                    codedfilename = fileNames;
                }
            }
        } catch (Exception e) {
            log.error("processFileName error.", e);
        }
        return codedfilename;
    }

    public static void main(String[] args) {

    }
}

随机数

RandomUtils

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
/**
 * @ClassName: RandomUtil
 * @Description: 随机数工具类
 * qinfen
 * (分别使用java.util.Random、Apache Common Math3、Apache Common Lang3、TreadLocalRandom)
 */
public class RandomUtil {
    /**
     * 随机数生成无边界的Int
     */
    public static int getRandomForIntegerUnbounded() {
        int intUnbounded = new Random().nextInt();
        System.out.println(intUnbounded);
        return intUnbounded;
    }

    /**
     * 生成有边界的Int
     */
    public static int getRandomForIntegerBounded(int min, int max) {
        int intBounded = min + ((int) (new Random().nextFloat() * (max - min)));
        System.out.println(intBounded);
        return intBounded;
    }


    /**
     * 使用Apache Common Math3来生成有边界的Int,包含1而不包含10
     * @param min
     * @param max
     * @return
     */
    public static int getRandomForIntegerBounded2(int min, int max) {
        int intBounded = new RandomDataGenerator().nextInt(min, max);
        System.out.println(intBounded);
        return intBounded;
    }


    /**
     * 用Apache Common Lang3的工具类来生成有边界的Int,包含1且包含10
     * @param min
     * @param max
     * @return
     */
    public static int getRandomForIntegerBounded3(int min, int max) {
        int intBounded = RandomUtils.nextInt(min, max);
        System.out.println(intBounded);
        return intBounded;
    }


    /**
     * 使用TreadLocalRandom来生成有边界的Int,包含min而不包含max
     * @param min
     * @param max
     * @return
     */
    public static int getRandomForIntegerBounded4(int min, int max) {
        int threadIntBound = ThreadLocalRandom.current().nextInt(min, max);
        System.out.println(threadIntBound);
        return threadIntBound;
    }

    /**
     * 随机数生成无边界的Long
     */
    public static long getRandomForLongUnbounded() {
        long unboundedLong = new Random().nextLong();
        System.out.println(unboundedLong);
        return unboundedLong;
    }


    /**
     * 使用Random生成有边界的Long
     * 因为Random类使用的种子是48bits,所以nextLong不能返回所有可能的long值,long是64bits
     * @param min
     * @param max
     * @return
     */
    public static long getRandomForLongBounded(long min, long max) {
        long rangeLong = min + (((long) (new Random().nextDouble() * (max - min))));
        System.out.println(rangeLong);
        return rangeLong;
    }


    /**
     * 使用Apache Commons Math3来生成有边界的Long(RandomDataGenerator类提供的生成随机数的方法)
     * @param min
     * @param max
     * @return
     */
    public static long getRandomForLongBounded2(long min, long max) {
        long rangeLong = new RandomDataGenerator().nextLong(min, max);
        System.out.println(rangeLong);
        return rangeLong;
    }


    /**
     * 使用Apache Commons Lang3的工具类来生成有边界的Long(RandomUtils提供了对java.util.Random的补充)
     * @param min
     * @param max
     * @return
     */
    public static long getRandomForLongBounded3(long min, long max) {
        long longBounded = RandomUtils.nextLong(min, max);
        System.out.println(longBounded);
        return longBounded;
    }


    /**
     * 使用ThreadLocalRandom生成有边界的Long
     * @param min
     * @param max
     * @return
     */
    public static long getRandomForLongBounded4(long min, long max) {
        long threadLongBound = ThreadLocalRandom.current().nextLong(min, max);
        System.out.println(threadLongBound);
        return threadLongBound;
    }

    /**
     * 随机数Float的生成生成0.0-1.0之间的Float随机数
     */
    public static float getRandomForFloat0To1() {
        float floatUnbounded = new Random().nextFloat();
        System.out.println(floatUnbounded);
        return floatUnbounded;
    }


    /**
     * 以上只会生成包含0.0而不包括1.0的float类型随机数生成有边界的Float随机数
     * @param min
     * @param max
     * @return
     */
    public static float getRandomForFloatBounded(float min, float max) {
        float floatBounded = min + new Random().nextFloat() * (max - min);
        System.out.println(floatBounded);
        return floatBounded;
    }


    /**
     * 使用Apache Common Math来生成有边界的Float随机数
     * @param min
     * @param max
     * @return
     */
    public static float getRandomForFloatBounded2(float min, float max) {
        float randomFloat = new RandomDataGenerator().getRandomGenerator().nextFloat();
        float generatedFloat = min + randomFloat * (max - min);
        System.out.println(generatedFloat);
        return generatedFloat;
    }


    /**
     * 使用Apache Common Lang来生成有边界的Float随机数
     * @param min
     * @param max
     * @return
     */
    public static float getRandomForFloatBounded3(float min, float max) {
        float generatedFloat = RandomUtils.nextFloat(min, max);
        System.out.println(generatedFloat);
        return generatedFloat;
    }

    // 使用ThreadLocalRandom生成有边界的Float随机数
    // ThreadLocalRandom类没有提供

    /**
     * 生成0.0d-1.0d之间的Double随机数
     */
    public static double getRandomForDouble0To1() {
        double generatorDouble = new Random().nextDouble();
        System.out.println(generatorDouble);
        return generatorDouble;
    }


    /**
     * 与Float相同,以上方法只会生成包含0.0d而不包含1.0d的随机数生成带有边界的Double随机数
     * @param min
     * @param max
     * @return
     */
    public static double getRandomForDoubleBounded(double min, double max) {
        double boundedDouble = min + new Random().nextDouble() * (max - min);
        System.out.println(boundedDouble);
        return boundedDouble;
    }


    /**
     * 使用Apache Common Math来生成有边界的Double随机数
     * @param min
     * @param max
     * @return
     */
    public static double getRandomForDoubleBounded2(double min, double max) {
        double boundedDouble = new RandomDataGenerator().getRandomGenerator().nextDouble();
        double generatorDouble = min + boundedDouble * (max - min);
        System.out.println(generatorDouble);
        return generatorDouble;
    }

    /**
     * 使用Apache Common Lang生成有边界的Double随机数
     * @param min
     * @param max
     * @return
     */
    public static double getRandomForDoubleBounded3(double min, double max) {
        double generatedDouble = RandomUtils.nextDouble(min, max);
        System.out.println(generatedDouble);
        return generatedDouble;
    }

    /**
     * 使用ThreadLocalRandom生成有边界的Double随机数
     * @param min
     * @param max
     * @return
     */
    public static double getRandomForDoubleBounded4(double min, double max) {
        double generatedDouble = ThreadLocalRandom.current().nextDouble(min, max);
        System.out.println(generatedDouble);
        return generatedDouble;
    }
}
本文由作者按照 CC BY 4.0 进行授权