fix: 码全代码添加
This commit is contained in:
38
template/cvbp/cvbp-public/cvbp-common-core/.gitignore
vendored
Normal file
38
template/cvbp/cvbp-public/cvbp-common-core/.gitignore
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
91
template/cvbp/cvbp-public/cvbp-common-core/pom.xml
Normal file
91
template/cvbp/cvbp-public/cvbp-common-core/pom.xml
Normal file
@@ -0,0 +1,91 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright (c) 2023 codvision.com All Rights Reserved.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>com.codvision</groupId>
|
||||
<artifactId>cvbp-public</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>cvbp-common-core</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-crypto</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-extra</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-json</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>easyexcel</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.codvision.commoncore.bean;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author codvision
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class CoordinatePoint {
|
||||
|
||||
Double lng;
|
||||
|
||||
Double lat;
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
package com.codvision.commoncore.common;
|
||||
|
||||
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ExpiryMap<K, V> implements Map<K, V> {
|
||||
|
||||
private boolean isRefresh = false;
|
||||
private ScheduledExecutorService scheduledExecutorService;
|
||||
private static final ConcurrentHashMap WORK_MAP = new ConcurrentHashMap();
|
||||
private static final ConcurrentHashMap<Object, Long> EXPIRY_MAP = new ConcurrentHashMap<>();
|
||||
|
||||
public ExpiryMap() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ExpiryMap(boolean isRefresh) {
|
||||
this.isRefresh = isRefresh;
|
||||
startClearKey();
|
||||
}
|
||||
|
||||
public void closeMap() {
|
||||
scheduledExecutorService.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* 定时清除失效key
|
||||
*/
|
||||
public void startClearKey() {
|
||||
scheduledExecutorService = new ScheduledThreadPoolExecutor(1, new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build());
|
||||
scheduledExecutorService.scheduleAtFixedRate(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("===" + Thread.currentThread().getName() + "===");
|
||||
removeInvalidKeys();
|
||||
}
|
||||
}
|
||||
, 0, 3600, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
private static void removeInvalidKeys() {
|
||||
EXPIRY_MAP.keySet().forEach(key -> {
|
||||
if (EXPIRY_MAP.get(key) < System.currentTimeMillis()) {
|
||||
EXPIRY_MAP.remove(key);
|
||||
WORK_MAP.remove(key);
|
||||
}
|
||||
});
|
||||
System.gc();
|
||||
}
|
||||
|
||||
/**
|
||||
* put方法,需要设置key 的有效期!单位为:毫秒
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @param expiry key的有效期,单位:毫秒
|
||||
* @return
|
||||
*/
|
||||
public V put(K key, V value, long expiry) {
|
||||
if (!containsKey(key) || isRefresh) {//更新value,只有需要刷新时间时才需要操作expiryMap
|
||||
EXPIRY_MAP.put(key, System.currentTimeMillis() + expiry);
|
||||
}
|
||||
WORK_MAP.put(key, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return keySet().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(Object key) {
|
||||
if (key != null && EXPIRY_MAP.containsKey(key)) {
|
||||
boolean flag = EXPIRY_MAP.get(key) > System.currentTimeMillis();
|
||||
return flag;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(Object value) {
|
||||
Collection values = WORK_MAP.values();
|
||||
if (values != null) {
|
||||
return values.contains(value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get(Object key) {
|
||||
if (containsKey(key)) {
|
||||
return (V) WORK_MAP.get(key);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public V put(K key, V value) {
|
||||
throw new RuntimeException("此方法已废弃!请加上key失效时间");
|
||||
}
|
||||
|
||||
@Override
|
||||
public V remove(Object key) {
|
||||
boolean containKey = containsKey(key);
|
||||
EXPIRY_MAP.remove(key);
|
||||
if (containKey) {
|
||||
return (V) WORK_MAP.remove(key);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public void putAll(Map<? extends K, ? extends V> m) {
|
||||
throw new RuntimeException("此方法已废弃!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
EXPIRY_MAP.clear();
|
||||
WORK_MAP.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<K> keySet() {
|
||||
removeInvalidKeys();
|
||||
return WORK_MAP.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<V> values() {
|
||||
removeInvalidKeys();
|
||||
return WORK_MAP.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Entry<K, V>> entrySet() {
|
||||
removeInvalidKeys();
|
||||
return WORK_MAP.entrySet();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
//ExpiryMap emap=new ExpiryMap();
|
||||
ExpiryMap emap = new ExpiryMap(true);
|
||||
emap.put("key1", "value1", 2 * 1000);
|
||||
emap.put("key2", "value2", 5 * 1000);
|
||||
emap.put("key3", "value3", 15 * 1000);
|
||||
System.out.println(emap.size());
|
||||
try {
|
||||
Thread.sleep(10 * 1000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
System.out.println(emap.size());
|
||||
System.out.println(emap.keySet());
|
||||
System.out.println(emap.values());
|
||||
System.out.println(emap.entrySet());
|
||||
emap.put("key4", "value4", 8 * 1000);
|
||||
System.out.println(emap.size());
|
||||
try {
|
||||
Thread.sleep(10 * 1000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
System.out.println(emap.size());
|
||||
System.out.println(emap.keySet());
|
||||
System.out.println(emap.values());
|
||||
System.out.println(emap.entrySet());
|
||||
|
||||
emap.closeMap();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
package com.codvision.commoncore.common;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
|
||||
/**
|
||||
* @author codvision
|
||||
*/
|
||||
@ApiModel(description = "返回响应数据")
|
||||
public class ResponseEntity<T> {
|
||||
|
||||
@ApiModelProperty(value = "编码")
|
||||
private int code = 200;
|
||||
|
||||
@ApiModelProperty(value = "基本信息")
|
||||
private String message = "成功";
|
||||
|
||||
@ApiModelProperty(value = "返回对象")
|
||||
private T data;
|
||||
|
||||
|
||||
private static final HashMap<Integer, String> ERROR_CODE = new HashMap<Integer, String>() {
|
||||
{
|
||||
put(100, "暂无数据");
|
||||
put(200, "成功");
|
||||
put(10000, "通用错误");
|
||||
///用户类
|
||||
put(10001, "用户名或密码错误");
|
||||
put(10002, "登录状态已过期");
|
||||
put(10003, "注册用户已存在");
|
||||
put(10004, "账号已被锁定,请在一小时后重试");
|
||||
|
||||
///操作权限类
|
||||
put(20001, "无操作权限");
|
||||
///参数类
|
||||
put(30001, "非法参数");
|
||||
put(30002, "缺少必要参数");
|
||||
put(30003, "文件内容为空");
|
||||
put(30004, "不支持的文件格式");
|
||||
put(30005, "获取参数失败");
|
||||
////数据操作类
|
||||
put(40001, "添加数据失败");
|
||||
put(40002, "更新数据失败");
|
||||
put(40003, "删除数据失败");
|
||||
put(50001, "不存在的对象");
|
||||
put(50002, "文件上传超过最大限制!");
|
||||
put(50003, "文件上传失败!");
|
||||
|
||||
put(110000, "获取用户失败或用户不存在!");
|
||||
put(100001, "钉钉获取用户信息失败,请稍后再试");
|
||||
put(110002, "小程序授权获取手机号失败");
|
||||
|
||||
put(990000, "系统错误");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public ResponseEntity() {
|
||||
}
|
||||
|
||||
public ResponseEntity(T data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public ResponseEntity setCode(int code) {
|
||||
this.code = code;
|
||||
if (ERROR_CODE.containsKey(code)) {
|
||||
setMessage(ERROR_CODE.get(code));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public ResponseEntity setData(T data) {
|
||||
this.data = data;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static <T> ResponseEntity<T> def(Class<T> clazz) {
|
||||
return new ResponseEntity<>();
|
||||
}
|
||||
|
||||
public ResponseEntity<T> ok() {
|
||||
setCode(200);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResponseEntity<T> error(int code) {
|
||||
setCode(code);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResponseEntity<T> error(int code, String message) {
|
||||
setCode(code);
|
||||
setMessage(message);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResponseEntity<T> message(String message) {
|
||||
setMessage(message);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResponseEntity<T> data(T data) {
|
||||
setData(data);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResponseEntity<T> back(int code, String message, T data) {
|
||||
setCode(code);
|
||||
setMessage(message);
|
||||
setData(data);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.codvision.commoncore.enums;
|
||||
|
||||
/**
|
||||
* @author codvision
|
||||
*/
|
||||
|
||||
public enum NetworkData {
|
||||
|
||||
/**
|
||||
* 月的天数
|
||||
*/
|
||||
MONTH(30, "月"),
|
||||
/**
|
||||
* 周的天数
|
||||
*/
|
||||
WEEK(7, "周"),
|
||||
|
||||
/**
|
||||
* NET_WORK_ID
|
||||
*/
|
||||
NET_WORK_ID(0, "0:0:0:0:0:0:0:1"),
|
||||
|
||||
/**
|
||||
* 成功
|
||||
*/
|
||||
OK(200, "ok");
|
||||
|
||||
private final int code;
|
||||
private final String desc;
|
||||
|
||||
NetworkData(int code, String desc) {
|
||||
this.code = code;
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.codvision.commoncore.enums;
|
||||
|
||||
/**
|
||||
* where 条件操作符号
|
||||
*
|
||||
* @author lingee
|
||||
* @date 2022/5/9
|
||||
*/
|
||||
public enum SqlOperator {
|
||||
/**
|
||||
* like
|
||||
*/
|
||||
LIKE("LIKE"),
|
||||
/**
|
||||
* =
|
||||
*/
|
||||
EQ("="),
|
||||
/**
|
||||
* 不等于
|
||||
*/
|
||||
NE("<>"),
|
||||
/**
|
||||
* 大于
|
||||
*/
|
||||
GT(">"),
|
||||
/**
|
||||
* 大于等于
|
||||
*/
|
||||
GE(">="),
|
||||
/**
|
||||
* 小于
|
||||
*/
|
||||
LT("<"),
|
||||
/**
|
||||
* 小于等于
|
||||
*/
|
||||
LE("<="),
|
||||
/**
|
||||
* 为空
|
||||
*/
|
||||
IS_NULL("IS NULL"),
|
||||
/**
|
||||
* 不为空
|
||||
*/
|
||||
IS_NOT_NULL("IS NOT NULL"),
|
||||
/**
|
||||
* 范围查找
|
||||
*/
|
||||
BETWEEN("BETWEEN"),
|
||||
/**
|
||||
* 多数据查找
|
||||
*/
|
||||
IN("IN");
|
||||
|
||||
private final String operator;
|
||||
|
||||
SqlOperator(String operator) {
|
||||
this.operator = operator;
|
||||
}
|
||||
|
||||
public String getOperator() {
|
||||
return operator;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2023 codvision.com All Rights Reserved.
|
||||
*/
|
||||
|
||||
package com.codvision.commoncore.enums;
|
||||
|
||||
/**
|
||||
* TrueOrFalse
|
||||
*
|
||||
* @author lingee
|
||||
* @since 2024/4/29
|
||||
*/
|
||||
public enum TrueOrFalse {
|
||||
|
||||
FALSE("0", 0, false),
|
||||
|
||||
TRUE("1", 1, true);
|
||||
private final String key;
|
||||
private final int intVal;
|
||||
private final boolean val;
|
||||
|
||||
TrueOrFalse(String key, int intVal, boolean val) {
|
||||
this.key = key;
|
||||
this.intVal = intVal;
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public int getIntVal() {
|
||||
return intVal;
|
||||
}
|
||||
|
||||
public boolean isVal() {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.codvision.commoncore.exception;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* 认证异常
|
||||
*
|
||||
* @author hxl
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class AuthException extends RuntimeException {
|
||||
|
||||
private Integer code;
|
||||
|
||||
private String message;
|
||||
|
||||
public AuthException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public AuthException(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public AuthException(String message) {
|
||||
super(message);
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public AuthException(int code, String message) {
|
||||
super(message);
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.codvision.commoncore.exception;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* 业务异常
|
||||
*
|
||||
* @author hxl
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class BusinessException extends RuntimeException {
|
||||
|
||||
private Integer code;
|
||||
private String message;
|
||||
|
||||
public BusinessException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public BusinessException(String message) {
|
||||
super(message);
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public BusinessException(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public BusinessException(int code, String message) {
|
||||
super(message);
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.codvision.commoncore.exception;
|
||||
|
||||
/**
|
||||
* @Author huxb
|
||||
* @description:
|
||||
* @create 2023/2/7 16:16
|
||||
*/
|
||||
public class IdempotentException extends RuntimeException {
|
||||
public IdempotentException() {
|
||||
}
|
||||
|
||||
public IdempotentException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.codvision.commoncore.exception;
|
||||
|
||||
/**
|
||||
* @Author huxb
|
||||
* @description:
|
||||
* @create 2022/11/22 10:28
|
||||
*/
|
||||
public class LimitException extends RuntimeException{
|
||||
public LimitException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LimitException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.codvision.commoncore.exception;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* 权限异常
|
||||
*
|
||||
* @author hxl
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class PermissionException extends RuntimeException {
|
||||
|
||||
private Integer code;
|
||||
|
||||
private String message;
|
||||
|
||||
public PermissionException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public PermissionException(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public PermissionException(String message) {
|
||||
super(message);
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public PermissionException(int code, String message) {
|
||||
super(message);
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2023 codvision.com All Rights Reserved.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 公共模块
|
||||
*
|
||||
* @author lingee
|
||||
* @date 2023/7/14
|
||||
*/
|
||||
package com.codvision.commoncore;
|
||||
@@ -0,0 +1,139 @@
|
||||
package com.codvision.commoncore.utils;
|
||||
|
||||
import javax.crypto.*;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import javax.management.openmbean.InvalidKeyException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
* @author zjm
|
||||
* @version V1.0
|
||||
* @Package com.codvision.xlwzl.util
|
||||
* @date 2020/7/3 10:59
|
||||
* @Copyright © 2017-2020 杭州码全科技有限公司
|
||||
* @Description 使用ECB模式加密
|
||||
*/
|
||||
public class AES {
|
||||
/**
|
||||
* 偏移量字符串必须是16位 当模式是CBC的时候必须设置偏移量
|
||||
*/
|
||||
private static final String iv = "0123456789ABCDEF";
|
||||
private static final String Algorithm = "AES";
|
||||
/**
|
||||
* 算法/模式/补码方式
|
||||
*/
|
||||
private static final String AlgorithmProvider = "AES/ECB/PKCS5Padding";
|
||||
|
||||
public static byte[] generatorKey() throws NoSuchAlgorithmException {
|
||||
KeyGenerator keyGenerator = KeyGenerator.getInstance(Algorithm);
|
||||
//默认128,获得无政策权限后可为192或256
|
||||
keyGenerator.init(256);
|
||||
SecretKey secretKey = keyGenerator.generateKey();
|
||||
return secretKey.getEncoded();
|
||||
}
|
||||
|
||||
public static IvParameterSpec getIv() throws UnsupportedEncodingException {
|
||||
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
|
||||
System.out.println("偏移量:" + byteToHexString(ivParameterSpec.getIV()));
|
||||
return ivParameterSpec;
|
||||
}
|
||||
|
||||
public static byte[] encrypt(String src) throws NoSuchPaddingException, NoSuchAlgorithmException, java.security.InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException {
|
||||
return encrypt(src, "codvision@2020YH".getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
public static byte[] encrypt(String src, byte[] key) throws NoSuchPaddingException, NoSuchAlgorithmException, java.security.InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
|
||||
SecretKey secretKey = new SecretKeySpec(key, Algorithm);
|
||||
//IvParameterSpec ivParameterSpec = getIv();
|
||||
Cipher cipher = Cipher.getInstance(AlgorithmProvider);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
|
||||
byte[] cipherBytes = cipher.doFinal(src.getBytes(StandardCharsets.UTF_8));
|
||||
return cipherBytes;
|
||||
}
|
||||
|
||||
public static String decrypt(String src) throws Exception {
|
||||
return decrypt(src, "codvision@2020YH".getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
public static String decrypt(String src, byte[] key) throws Exception {
|
||||
SecretKey secretKey = new SecretKeySpec(key, Algorithm);
|
||||
|
||||
//IvParameterSpec ivParameterSpec = getIv();
|
||||
Cipher cipher = Cipher.getInstance(AlgorithmProvider);
|
||||
cipher.init(Cipher.DECRYPT_MODE, secretKey);
|
||||
byte[] hexBytes = hexStringToBytes(src);
|
||||
byte[] plainBytes = cipher.doFinal(hexBytes);
|
||||
return new String(plainBytes, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将byte转换为16进制字符串
|
||||
*
|
||||
* @param src
|
||||
* @return
|
||||
*/
|
||||
public static String byteToHexString(byte[] src) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < src.length; i++) {
|
||||
int v = src[i] & 0xff;
|
||||
String hv = Integer.toHexString(v);
|
||||
if (hv.length() < 2) {
|
||||
sb.append("0");
|
||||
}
|
||||
sb.append(hv);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将16进制字符串装换为byte数组
|
||||
*
|
||||
* @param hexString
|
||||
* @return
|
||||
*/
|
||||
public static byte[] hexStringToBytes(String hexString) {
|
||||
hexString = hexString.toUpperCase();
|
||||
int length = hexString.length() / 2;
|
||||
char[] hexChars = hexString.toCharArray();
|
||||
byte[] b = new byte[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
int pos = i * 2;
|
||||
b[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
private static byte charToByte(char c) {
|
||||
return (byte) "0123456789ABCDEF".indexOf(c);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
// byte key[] = generatorKey();
|
||||
// 密钥必须是16的倍数
|
||||
String src = "6ea40c84b3fe7c6c3033e59bd59643a3";
|
||||
System.out.println("原字符串:" + src);
|
||||
|
||||
String enc = byteToHexString(encrypt(src));
|
||||
System.out.println("加密:" + enc);
|
||||
System.out.println("解密:" + decrypt(enc));
|
||||
} catch (InvalidKeyException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchPaddingException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalBlockSizeException e) {
|
||||
e.printStackTrace();
|
||||
} catch (BadPaddingException e) {
|
||||
e.printStackTrace();
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.codvision.commoncore.utils;
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.util.HexUtil;
|
||||
import cn.hutool.crypto.CryptoException;
|
||||
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* @author hxl
|
||||
*/
|
||||
public class AesUtil {
|
||||
/**
|
||||
* Cipher负责完成加密或解密工作
|
||||
*/
|
||||
private Cipher cipher;
|
||||
/**
|
||||
* 密钥
|
||||
*/
|
||||
private SecretKey secretKey;
|
||||
|
||||
/**
|
||||
* @param key 密钥 转为为字节后:支持三种密钥长度:128、192、256位
|
||||
*/
|
||||
public AesUtil(String key) {
|
||||
this(new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), SymmetricAlgorithm.AES.getValue()));
|
||||
}
|
||||
|
||||
public AesUtil(SecretKey secretKey) {
|
||||
try {
|
||||
this.cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||
} catch (Exception e) {
|
||||
throw new CryptoException(e);
|
||||
}
|
||||
this.secretKey = secretKey;
|
||||
}
|
||||
|
||||
public byte[] encrypt(byte[] data) {
|
||||
try {
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(new byte[cipher.getBlockSize()]));
|
||||
return cipher.doFinal(data);
|
||||
} catch (Exception e) {
|
||||
throw new CryptoException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] decrypt(byte[] data) {
|
||||
try {
|
||||
cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(new byte[cipher.getBlockSize()]));
|
||||
return cipher.doFinal(data);
|
||||
} catch (Exception e) {
|
||||
throw new CryptoException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String encryptHex(byte[] data) {
|
||||
return HexUtil.encodeHexStr(encrypt(data));
|
||||
}
|
||||
|
||||
public byte[] decryptHex(String data) {
|
||||
return decrypt(HexUtil.decodeHex(data));
|
||||
}
|
||||
|
||||
public String encryptBase64(byte[] data) {
|
||||
return Base64.encode(encrypt(data));
|
||||
}
|
||||
|
||||
public byte[] decryptBase64(String data) {
|
||||
return decrypt(Base64.decode(data));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.codvision.commoncore.utils;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @Author huxb
|
||||
* @description: 随机生成appKey,appSecret
|
||||
* @create 2021/12/21 16:44
|
||||
*/
|
||||
public class AppUtils {
|
||||
|
||||
//生成 app_secret 密钥
|
||||
private final static String SERVER_NAME = "maquan_codvision";
|
||||
private final static String[] chars = new String[]{"a", "b", "c", "d", "e", "f",
|
||||
"g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
|
||||
"t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5",
|
||||
"6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I",
|
||||
"J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
|
||||
"W", "X", "Y", "Z"};
|
||||
|
||||
/**
|
||||
* 短8位UUID思想其实借鉴微博短域名的生成方式,但是其重复概率过高,而且每次生成4个,需要随即选取一个。
|
||||
* 本算法利用62个可打印字符,通过随机生成32位UUID,由于UUID都为十六进制,所以将UUID分成8组,每4个为一组,然后通过模62操作,结果作为索引取出字符,
|
||||
* 这样重复率大大降低。
|
||||
* 经测试,在生成一千万个数据也没有出现重复,完全满足大部分需求。
|
||||
*/
|
||||
public static String getAppId() {
|
||||
StringBuffer shortBuffer = new StringBuffer();
|
||||
String uuid = UUID.randomUUID().toString().replace("-", "");
|
||||
for (int i = 0; i < 8; i++) {
|
||||
String str = uuid.substring(i * 4, i * 4 + 4);
|
||||
int x = Integer.parseInt(str, 16);
|
||||
shortBuffer.append(chars[x % 0x3E]);
|
||||
}
|
||||
return shortBuffer.toString();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过appId和内置关键词生成APP Secret
|
||||
*/
|
||||
public static String getAppSecret(String appId) {
|
||||
try {
|
||||
String[] array = new String[]{appId, SERVER_NAME};
|
||||
StringBuffer sb = new StringBuffer();
|
||||
// 字符串排序
|
||||
Arrays.sort(array);
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
sb.append(array[i]);
|
||||
}
|
||||
String str = sb.toString();
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-1");
|
||||
md.update(str.getBytes());
|
||||
byte[] digest = md.digest();
|
||||
|
||||
StringBuffer hexstr = new StringBuffer();
|
||||
String shaHex = "";
|
||||
for (int i = 0; i < digest.length; i++) {
|
||||
shaHex = Integer.toHexString(digest[i] & 0xFF);
|
||||
if (shaHex.length() < 2) {
|
||||
hexstr.append(0);
|
||||
}
|
||||
hexstr.append(shaHex);
|
||||
}
|
||||
return hexstr.toString();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
package com.codvision.commoncore.utils;
|
||||
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* 对象工具类
|
||||
*
|
||||
* @author lingee
|
||||
* @since 2023-7-20
|
||||
*/
|
||||
public class BeanUtil extends cn.hutool.core.bean.BeanUtil {
|
||||
|
||||
/**
|
||||
* 获取属性名数组
|
||||
*
|
||||
* @param o 获取字段的对象
|
||||
* @return 返回各个字段
|
||||
*/
|
||||
public static Field[] getFields(Object o) {
|
||||
Field[] fields = o.getClass().getDeclaredFields();
|
||||
Field[] superFields = o.getClass().getSuperclass().getDeclaredFields();
|
||||
Field[] allFields = new Field[fields.length + superFields.length];
|
||||
int index = 0;
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
if ("serialVersionUID".equals(fields[i].getName())) {
|
||||
continue;
|
||||
}
|
||||
Field field = fields[i];
|
||||
if (ObjectUtil.isNotEmpty(field)) {
|
||||
allFields[index] = field;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
for (int i = 0; i < superFields.length; i++) {
|
||||
if ("id".equals(superFields[i].getName())
|
||||
|| "serialVersionUID".equals(superFields[i].getName())) {
|
||||
continue;
|
||||
}
|
||||
Field field = superFields[i];
|
||||
if (ObjectUtil.isNotEmpty(field)) {
|
||||
allFields[index] = field;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
return allFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取属性名数组
|
||||
*
|
||||
* @param o 获取字段的对象
|
||||
* @return 返回各个字段
|
||||
*/
|
||||
public static String[] getFieldName(Object o) {
|
||||
Field[] fields = o.getClass().getDeclaredFields();
|
||||
Field[] superFields = o.getClass().getSuperclass().getDeclaredFields();
|
||||
String[] fieldNames = new String[fields.length + superFields.length];
|
||||
int index = 0;
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
fieldNames[index] = fields[i].getName();
|
||||
index++;
|
||||
}
|
||||
for (int i = 0; i < superFields.length; i++) {
|
||||
if ("id".equals(superFields[i].getName())) {
|
||||
continue;
|
||||
}
|
||||
fieldNames[index] = superFields[i].getName();
|
||||
index++;
|
||||
}
|
||||
return fieldNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据属性名获取属性值
|
||||
*
|
||||
* @param fieldName 属性名
|
||||
* @param o 对象
|
||||
* @return 属性值
|
||||
*/
|
||||
public static Object getFieldValueByName(String fieldName, Object o) {
|
||||
try {
|
||||
String firstLetter = fieldName.substring(0, 1).toUpperCase();
|
||||
String getter = "get" + firstLetter + fieldName.substring(1);
|
||||
Method method = o.getClass().getMethod(getter, new Class[]{});
|
||||
Object value = method.invoke(o, new Object[]{});
|
||||
return value;
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将对象转换为key value
|
||||
* A=a&B=b&C=c 格式
|
||||
*
|
||||
* @param object 对象
|
||||
* @return 格式化结果
|
||||
*/
|
||||
public static String formatKeyValuePair(Object object) {
|
||||
//准备接受的字符串
|
||||
StringBuilder stringBuffer = new StringBuilder();
|
||||
//获取对象字段
|
||||
String[] fieldNames = BeanUtil.getFieldName(object);
|
||||
//遍历所有属性
|
||||
for (int j = 0; j < fieldNames.length; j++) {
|
||||
//不是第一个并且不是最后一个,拼接&
|
||||
if (j != 0) {
|
||||
stringBuffer.append("&");
|
||||
}
|
||||
//获取属性的名字
|
||||
String key = fieldNames[j];
|
||||
//获取值
|
||||
Object value = BeanUtil.getFieldValueByName(key, object);
|
||||
assert value != null;
|
||||
stringBuffer.append(key).append("=").append(value.toString());
|
||||
}
|
||||
return stringBuffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* key value键值对 转换为 对象
|
||||
* A=a&B=b&C=c 格式 转换为对象
|
||||
*
|
||||
* @param str 对象字符串
|
||||
* @param t 范型
|
||||
* @param <T> 范型
|
||||
* @return 格式化结果
|
||||
*/
|
||||
public static <T> T formatKeyValuePair(String str, T t) {
|
||||
//填写对参数键值对
|
||||
String[] params = str.split("&");
|
||||
|
||||
//获取对象字段
|
||||
String[] fieldNames = BeanUtil.getFieldName(t);
|
||||
|
||||
try {
|
||||
//循环每个参数
|
||||
for (String param : params) {
|
||||
String[] keyValues = param.split("=");
|
||||
for (int i = 0; i < fieldNames.length; i++) {
|
||||
if (fieldNames[i].equals(keyValues[0])) {
|
||||
Field f = t.getClass().getDeclaredField(fieldNames[i]);
|
||||
f.setAccessible(true);
|
||||
//长度为2 才转换,否则不转
|
||||
if (keyValues.length == 2) {
|
||||
f.set(t, keyValues[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2023 codvision.com All Rights Reserved.
|
||||
*/
|
||||
|
||||
package com.codvision.commoncore.utils;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* 强密码校验:包含数字、大小写字母和特殊符号,长度要求8-15位且不与用户名相同
|
||||
* @author hxl
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class CheckPwdUtil {
|
||||
|
||||
// 数字
|
||||
public static final String REG_NUMBER = ".*\\d+.*";
|
||||
// 小写字母
|
||||
public static final String REG_UPPERCASE = ".*[A-Z]+.*";
|
||||
// 大写字母
|
||||
public static final String REG_LOWERCASE = ".*[a-z]+.*";
|
||||
// 特殊符号(~!@#$%^&*()_+|<>,.?/:;'[]{}\)
|
||||
public static final String REG_SYMBOL = ".*[~!@#$%^&*()_+|<>,.?/:;'\\[\\]{}\"]+.*";
|
||||
|
||||
|
||||
public static boolean checkPasswordRule(String username, String password) {
|
||||
if (StringUtils.isBlank(password) || password.length() < 8 || password.length() > 15) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
if (password.matches(REG_NUMBER)) { i++; }
|
||||
if (password.matches(REG_LOWERCASE)) { i++; }
|
||||
if (password.matches(REG_UPPERCASE)) { i++; }
|
||||
if (password.matches(REG_SYMBOL)) { i++; }
|
||||
|
||||
boolean contains = password.equals(username);
|
||||
if (i < 4 || contains) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
package com.codvision.commoncore.utils;
|
||||
|
||||
|
||||
import com.codvision.commoncore.bean.CoordinatePoint;
|
||||
|
||||
/**
|
||||
* 坐标工具类
|
||||
*
|
||||
* @author codvision
|
||||
*/
|
||||
public class CoordinateUtil {
|
||||
|
||||
public static final String BAIDU_LBS_TYPE = "bd09ll";
|
||||
|
||||
public static double pi = 3.1415926535897932384626;
|
||||
public static double a = 6378245.0;
|
||||
public static double ee = 0.00669342162296594323;
|
||||
|
||||
/**
|
||||
* 84 to 火星坐标系 (GCJ-02)
|
||||
*
|
||||
* @param lat
|
||||
* @param lon
|
||||
* @return
|
||||
*/
|
||||
public static CoordinatePoint wgs84ToGcj02(double lon, double lat) {
|
||||
if (outOfChina(lon, lat)) {
|
||||
return null;
|
||||
}
|
||||
double dLat = transformLat(lon - 105.0, lat - 35.0);
|
||||
double dLon = transformLon(lon - 105.0, lat - 35.0);
|
||||
double radLat = lat / 180.0 * pi;
|
||||
double magic = Math.sin(radLat);
|
||||
magic = 1 - ee * magic * magic;
|
||||
double sqrtMagic = Math.sqrt(magic);
|
||||
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
|
||||
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
|
||||
double mgLat = lat + dLat;
|
||||
double mgLon = lon + dLon;
|
||||
return new CoordinatePoint(mgLon, mgLat);
|
||||
}
|
||||
|
||||
/**
|
||||
* * 火星坐标系 (GCJ-02) to 84 * * @param lon * @param lat * @return
|
||||
*/
|
||||
public static CoordinatePoint gcj02ToWgs84(double lon, double lat) {
|
||||
CoordinatePoint gps = transform(lon, lat);
|
||||
double lontitude = lon * 2 - gps.getLng();
|
||||
double latitude = lat * 2 - gps.getLat();
|
||||
return new CoordinatePoint(lontitude, latitude);
|
||||
}
|
||||
|
||||
/**
|
||||
* 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 将 GCJ-02 坐标转换成 BD-09 坐标
|
||||
*
|
||||
* @param ggLat
|
||||
* @param ggLat
|
||||
*/
|
||||
public static CoordinatePoint gcj02ToBd09(double ggLng, double ggLat) {
|
||||
double x = ggLng, y = ggLat;
|
||||
double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * pi);
|
||||
double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * pi);
|
||||
double bdLng = z * Math.cos(theta) + 0.0065;
|
||||
double bdLat = z * Math.sin(theta) + 0.006;
|
||||
return new CoordinatePoint(bdLng, bdLat);
|
||||
}
|
||||
|
||||
/**
|
||||
* * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 * * 将 BD-09 坐标转换成GCJ-02 坐标 * * @param
|
||||
* bd_lat * @param bd_lon * @return
|
||||
*/
|
||||
public static CoordinatePoint bd09ToGcj02(double bdLng, double bdLat) {
|
||||
double x = bdLng - 0.0065, y = bdLat - 0.006;
|
||||
double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * pi);
|
||||
double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * pi);
|
||||
double ggLng = z * Math.cos(theta);
|
||||
double ggLat = z * Math.sin(theta);
|
||||
return new CoordinatePoint(ggLng, ggLat);
|
||||
}
|
||||
|
||||
/**
|
||||
* (BD-09)-->84
|
||||
*
|
||||
* @param bdLng
|
||||
* @param bdLat
|
||||
* @return
|
||||
*/
|
||||
public static CoordinatePoint bd09ToWgs84(double bdLng, double bdLat) {
|
||||
|
||||
CoordinatePoint gcj02 = bd09ToGcj02(bdLng, bdLat);
|
||||
CoordinatePoint map84 = gcj02ToWgs84(gcj02.getLng(),
|
||||
gcj02.getLat());
|
||||
return map84;
|
||||
|
||||
}
|
||||
|
||||
public static boolean outOfChina(double lon, double lat) {
|
||||
if (lon < 72.004 || lon > 137.8347) {
|
||||
return true;
|
||||
}
|
||||
return lat < 0.8293 || lat > 55.8271;
|
||||
}
|
||||
|
||||
public static CoordinatePoint transform(double lon, double lat) {
|
||||
if (outOfChina(lon, lat)) {
|
||||
return new CoordinatePoint(lat, lon);
|
||||
}
|
||||
double dLat = transformLat(lon - 105.0, lat - 35.0);
|
||||
double dLon = transformLon(lon - 105.0, lat - 35.0);
|
||||
double radLat = lat / 180.0 * pi;
|
||||
double magic = Math.sin(radLat);
|
||||
magic = 1 - ee * magic * magic;
|
||||
double sqrtMagic = Math.sqrt(magic);
|
||||
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
|
||||
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
|
||||
double mgLat = lat + dLat;
|
||||
double mgLon = lon + dLon;
|
||||
return new CoordinatePoint(mgLon, mgLat);
|
||||
}
|
||||
|
||||
public static double transformLat(double x, double y) {
|
||||
double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y
|
||||
+ 0.2 * Math.sqrt(Math.abs(x));
|
||||
ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
|
||||
ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;
|
||||
ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static double transformLon(double x, double y) {
|
||||
double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1
|
||||
* Math.sqrt(Math.abs(x));
|
||||
ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
|
||||
ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;
|
||||
ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0
|
||||
* pi)) * 2.0 / 3.0;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,564 @@
|
||||
package com.codvision.commoncore.utils;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author codvision
|
||||
*/
|
||||
public class DateUtil extends cn.hutool.core.date.DateUtil {
|
||||
public static final String STANDARD_FORMAT = "yyyy-MM-dd HH:mm:ss";
|
||||
|
||||
public static final String STANDARD_DATE_FORMAT = "yyyy-MM-dd";
|
||||
|
||||
public static final String STANDARD_DATE_NO_UNDERLINE_FORMAT = "yyyyMMdd";
|
||||
|
||||
public static final String FULL_DATE = "yyyyMMddHHmmss";
|
||||
|
||||
|
||||
public static Date getSomeWeekAgoDate(Date date, int weeks) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
calendar.add(Calendar.WEEK_OF_YEAR, -weeks);
|
||||
Date someWeeksAgo = calendar.getTime();
|
||||
return someWeeksAgo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取N个月前日期
|
||||
*
|
||||
* @param date
|
||||
* @param month
|
||||
* @return
|
||||
*/
|
||||
public static Date getSomeMonthAgoDate(Date date, int month) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
calendar.add(Calendar.MONTH, -month);
|
||||
Date someMonthAgo = calendar.getTime();
|
||||
return someMonthAgo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取N年前日期
|
||||
*
|
||||
* @param date
|
||||
* @return
|
||||
*/
|
||||
public static Date getSomeYearAgoDate(Date date, int year) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
calendar.add(Calendar.YEAR, -year);
|
||||
Date someYearAgo = calendar.getTime();
|
||||
return someYearAgo;
|
||||
}
|
||||
|
||||
public static String strToStr(String strDate) {
|
||||
Date date = new Date();
|
||||
try {
|
||||
//先按照原格式转换为时间
|
||||
date = new SimpleDateFormat("yyyyMMddHHmmss").parse(strDate);
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//再将时间转换为对应格式字符串
|
||||
String str = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据系统时间返回一串无符号字符串
|
||||
*/
|
||||
public static String toString(Date date) {
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
|
||||
return simpleDateFormat.format(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据系统时间返回一串无符号字符串
|
||||
*/
|
||||
public static String monthToString(Date date) {
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMM");
|
||||
return simpleDateFormat.format(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据系统时间返回一串无符号字符串
|
||||
*/
|
||||
public static String dayToString(Date date) {
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
|
||||
return simpleDateFormat.format(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据系统时间返回一串无符号字符串
|
||||
*/
|
||||
public static String toStringFor16(Date date, String value) {
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
|
||||
String data = simpleDateFormat.format(date);
|
||||
Random rome = new Random();
|
||||
int last = rome.nextInt(90000000) + 10000000;
|
||||
return value + data + last;
|
||||
}
|
||||
|
||||
public static Date toDate(String date) {
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
try {
|
||||
return simpleDateFormat.parse(date);
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将一个字符串转换成日期格式
|
||||
*
|
||||
* @param date 字符串日期
|
||||
* @param pattern 日期格式
|
||||
* @return date
|
||||
*/
|
||||
public static Date toDate(String date, String pattern) {
|
||||
if ("".equals("" + date)) {
|
||||
return null;
|
||||
}
|
||||
if (pattern == null) {
|
||||
pattern = STANDARD_DATE_FORMAT;
|
||||
}
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(pattern, Locale.ENGLISH);
|
||||
Date newDate = new Date();
|
||||
try {
|
||||
newDate = sdf.parse(date);
|
||||
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return newDate;
|
||||
}
|
||||
|
||||
|
||||
public static String sdf(Date date) {
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
return simpleDateFormat.format(date);
|
||||
}
|
||||
|
||||
public static String getMonthBeginTime() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.add(Calendar.MONTH, 0);
|
||||
//设置为1号,当前日期既为本月第一天
|
||||
c.set(Calendar.DAY_OF_MONTH, 1);
|
||||
return sdf.format(c.getTime());
|
||||
}
|
||||
|
||||
|
||||
public static String getMonthEndTime() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd 23:59:59");
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.add(Calendar.MONTH, 0);
|
||||
c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
|
||||
return sdf.format(c.getTime());
|
||||
}
|
||||
|
||||
public static String getMonthBeginTimeOfLastYear() {
|
||||
|
||||
Calendar c = Calendar.getInstance();
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
|
||||
c.add(Calendar.MONTH, 0);
|
||||
c.add(Calendar.YEAR, -1);
|
||||
//设置为1号,当前日期既为本月第一天
|
||||
c.set(Calendar.DAY_OF_MONTH, 1);
|
||||
return sdf.format(c.getTime());
|
||||
}
|
||||
|
||||
|
||||
public static String getMonthEndTimeOfLastYear() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd 23:59:59");
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.add(Calendar.MONTH, 0);
|
||||
c.add(Calendar.YEAR, -1);
|
||||
c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
|
||||
return sdf.format(c.getTime());
|
||||
}
|
||||
|
||||
|
||||
public static String getToday() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
||||
return sdf.format(new Date());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获得昨天日期:yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
public static String getYesterdayBeginTime() {
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.add(Calendar.DATE, -1);
|
||||
SimpleDateFormat startSdf = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
|
||||
return startSdf.format(c.getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得昨天日期:yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
public static String getYesterdayEndTime() {
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.add(Calendar.DATE, -1);
|
||||
SimpleDateFormat startSdf = new SimpleDateFormat("yyyy-MM-dd 23:59:59");
|
||||
return startSdf.format(c.getTime());
|
||||
}
|
||||
|
||||
public static String getTodayBeginTime() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
|
||||
return sdf.format(new Date());
|
||||
}
|
||||
|
||||
|
||||
public static String getTodayEndTime() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd 23:59:59");
|
||||
return sdf.format(new Date());
|
||||
}
|
||||
|
||||
public static String getNowDateTime() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
return sdf.format(new Date());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得明天日期:yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
public static String getTomorrowBeginTime() {
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.add(Calendar.DATE, 1);
|
||||
SimpleDateFormat startSdf = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
|
||||
return startSdf.format(c.getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得明天日期:yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
public static String getTomorrowEndTime() {
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.add(Calendar.DATE, 1);
|
||||
SimpleDateFormat startSdf = new SimpleDateFormat("yyyy-MM-dd 23:59:59");
|
||||
return startSdf.format(c.getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得明天日期:yyyy-MM-dd time
|
||||
*/
|
||||
public static String getTomorrowTime(String time) {
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.add(Calendar.DATE, 1);
|
||||
SimpleDateFormat startSdf = new SimpleDateFormat(String.format("yyyy-MM-dd %s", time));
|
||||
return startSdf.format(c.getTime());
|
||||
}
|
||||
|
||||
|
||||
public static String getYearBeginTime() {
|
||||
Calendar c = Calendar.getInstance();
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-01-01 00:00:00");
|
||||
return sdf.format(c.getTime());
|
||||
}
|
||||
|
||||
|
||||
public static String getYearEndTime() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-12-31 23:59:59");
|
||||
Calendar c = Calendar.getInstance();
|
||||
return sdf.format(c.getTime());
|
||||
}
|
||||
|
||||
public static String getYearBeginTimeOfLastYear() {
|
||||
|
||||
Calendar c = Calendar.getInstance();
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-01-01 00:00:00");
|
||||
c.add(Calendar.YEAR, -1);
|
||||
return sdf.format(c.getTime());
|
||||
}
|
||||
|
||||
|
||||
public static String getYearEndTimeOfLastYear() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-12-31 23:59:59");
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.add(Calendar.YEAR, -1);
|
||||
return sdf.format(c.getTime());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 默认当天
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static Map<String, Integer> getWeekOfMonth() {
|
||||
return DateUtil.getWeekOfMonth(DateUtil.getToday());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 当前时间所属周,一周占用两个月的情况下属于上个月
|
||||
*
|
||||
* @param time
|
||||
* @return
|
||||
*/
|
||||
public static Map<String, Integer> getWeekOfMonth(String time) {
|
||||
//Calendar周日为一周的第一天
|
||||
//1.当月的1号为周日:
|
||||
//日期是否为周日 是,周数-1 第一个周日属于上个月最后一周
|
||||
//2.当月的1号为周一:
|
||||
//日期是否为周日 是,周数-1
|
||||
//3.当月的1号为周二--六:
|
||||
//日期是否为周日 是,周数-2 否,周数-1 为0属于上个月最后一周
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
||||
int resultYear;
|
||||
int resultMonth;
|
||||
int resultWeekOfMonth;
|
||||
Map<String, Integer> resultMap = new HashMap<>(16);
|
||||
try {
|
||||
Date parse = sdf.parse(time);
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(parse);
|
||||
int year = calendar.get(Calendar.YEAR);
|
||||
int month = calendar.get(Calendar.MONTH);
|
||||
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
|
||||
int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
|
||||
int weekOfMonth = calendar.get(Calendar.WEEK_OF_MONTH);
|
||||
resultYear = year;
|
||||
resultMonth = month + 1;
|
||||
|
||||
Calendar monthCalendar = Calendar.getInstance();
|
||||
monthCalendar.set(Calendar.YEAR, year);
|
||||
monthCalendar.set(Calendar.MONTH, month);
|
||||
monthCalendar.set(Calendar.DAY_OF_MONTH, 1);
|
||||
int monthDayOfWeek = monthCalendar.get(Calendar.DAY_OF_WEEK);
|
||||
|
||||
if (monthDayOfWeek == Calendar.SUNDAY) {
|
||||
if (dayOfWeek == Calendar.SUNDAY) {
|
||||
if (dayOfMonth == 1) {
|
||||
if (month == 0) {
|
||||
resultWeekOfMonth = getLastWeekOfMonth(year - 1, 11);
|
||||
resultYear = year - 1;
|
||||
resultMonth = 12;
|
||||
} else {
|
||||
resultWeekOfMonth = getLastWeekOfMonth(year, month - 1);
|
||||
resultMonth = month;
|
||||
}
|
||||
} else {
|
||||
resultWeekOfMonth = weekOfMonth - 1;
|
||||
}
|
||||
} else {
|
||||
resultWeekOfMonth = weekOfMonth;
|
||||
}
|
||||
} else if (monthDayOfWeek == Calendar.MONDAY) {
|
||||
if (dayOfWeek == Calendar.SUNDAY) {
|
||||
resultWeekOfMonth = weekOfMonth - 1;
|
||||
} else {
|
||||
resultWeekOfMonth = weekOfMonth;
|
||||
}
|
||||
} else {
|
||||
if (dayOfWeek == Calendar.SUNDAY) {
|
||||
resultWeekOfMonth = weekOfMonth - 2;
|
||||
} else {
|
||||
resultWeekOfMonth = weekOfMonth - 1;
|
||||
}
|
||||
if (resultWeekOfMonth == 0) {
|
||||
if (month == 0) {
|
||||
resultWeekOfMonth = getLastWeekOfMonth(year - 1, 11);
|
||||
resultYear = year - 1;
|
||||
resultMonth = 12;
|
||||
} else {
|
||||
resultWeekOfMonth = getLastWeekOfMonth(year, month - 1);
|
||||
resultMonth = month;
|
||||
}
|
||||
}
|
||||
}
|
||||
resultMap.put("year", resultYear);
|
||||
resultMap.put("month", resultMonth);
|
||||
resultMap.put("weekOfMonth", resultWeekOfMonth);
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 按月度获取当月最后一周是第几周
|
||||
*
|
||||
* @param year
|
||||
* @param month
|
||||
* @return
|
||||
*/
|
||||
private static int getLastWeekOfMonth(int year, int month) {
|
||||
int result;
|
||||
//当月1号
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.set(Calendar.YEAR, year);
|
||||
calendar.set(Calendar.MONTH, month);
|
||||
calendar.set(Calendar.DAY_OF_MONTH, 1);
|
||||
|
||||
//当月最后一天
|
||||
Calendar lastDayOfMonth = Calendar.getInstance();
|
||||
lastDayOfMonth.set(Calendar.YEAR, year);
|
||||
lastDayOfMonth.set(Calendar.MONTH, month);
|
||||
lastDayOfMonth.set(Calendar.DAY_OF_MONTH, 1);
|
||||
lastDayOfMonth.roll(Calendar.DAY_OF_MONTH, -1);
|
||||
|
||||
//
|
||||
int lastWeekOfMonth = lastDayOfMonth.get(Calendar.WEEK_OF_MONTH);
|
||||
//
|
||||
int lastDayOfWeek = lastDayOfMonth.get(Calendar.DAY_OF_WEEK);
|
||||
//当月1号是周几
|
||||
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
|
||||
//如果1号是周日或周一,那么这个月的所有除了周日的日期用Calendar获取的周数与需要的周数是一致的;
|
||||
if (dayOfWeek == Calendar.SUNDAY || dayOfWeek == Calendar.MONDAY) {
|
||||
//如果最后一天是周日需要的周数要-1
|
||||
if (lastDayOfWeek == Calendar.SUNDAY) {
|
||||
result = lastWeekOfMonth - 1;
|
||||
} else {
|
||||
result = lastWeekOfMonth;
|
||||
}
|
||||
} else {//1号是周二,三,四,五,六的情况下,这个月的所有除了周日的日期用Calendar获取的周数-1后与需要的周数是一致的;
|
||||
//是周日的日期需要-2
|
||||
if (lastDayOfWeek == Calendar.SUNDAY) {
|
||||
result = lastWeekOfMonth - 2;
|
||||
} else {
|
||||
result = lastWeekOfMonth - 1;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String getWeekBeginTime() {
|
||||
Date date = new Date();
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTime(date);
|
||||
int dayofweek = cal.get(Calendar.DAY_OF_WEEK);
|
||||
if (dayofweek == 1) {
|
||||
dayofweek += 7;
|
||||
}
|
||||
cal.add(Calendar.DATE, 2 - dayofweek);
|
||||
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
|
||||
return sdf.format(cal.getTime());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取本周的结束时间
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String getWeekEndTime() {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTime(new Date());
|
||||
int dayofweek = cal.get(Calendar.DAY_OF_WEEK);
|
||||
if (dayofweek == 1) {
|
||||
dayofweek += 7;
|
||||
}
|
||||
cal.add(Calendar.DATE, 2 - dayofweek);
|
||||
|
||||
cal.setTime(cal.getTime());
|
||||
cal.add(Calendar.DAY_OF_WEEK, 6);
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd 23:59:59");
|
||||
return sdf.format(cal.getTime());
|
||||
}
|
||||
|
||||
public static String getSomeHoursAgo(int hours) {
|
||||
Date date = new Date(System.currentTimeMillis() - hours * 3600 * 1000L);
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
return sdf.format(date);
|
||||
}
|
||||
|
||||
public static String getSomeHoursLater(int hours) {
|
||||
Date date = new Date(System.currentTimeMillis() + hours * 3600 * 1000L);
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
return sdf.format(date);
|
||||
}
|
||||
|
||||
|
||||
public static String getSomeDaysAgo(int days) {
|
||||
Date date = new Date(System.currentTimeMillis() - days * 86400 * 1000L);
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
return sdf.format(date);
|
||||
}
|
||||
|
||||
public static String getSomeDaysLater(int days) {
|
||||
Date date = new Date(System.currentTimeMillis() + days * 86400 * 1000L);
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
return sdf.format(date);
|
||||
}
|
||||
|
||||
public static long getHourLeftMilliseconds() {
|
||||
Date now = new Date();
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:59:59");
|
||||
try {
|
||||
Date end = sdf.parse(sdf2.format(now));
|
||||
|
||||
return end.getTime() - now.getTime();
|
||||
} catch (Exception ex) {
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static long getDayLeftMilliseconds() {
|
||||
Date now = new Date();
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
String endTime = getTodayEndTime();
|
||||
try {
|
||||
Date end = sdf.parse(endTime);
|
||||
return end.getTime() - now.getTime();
|
||||
} catch (Exception ex) {
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static long getWeekLeftMilliseconds() {
|
||||
Date now = new Date();
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
String endTime = getWeekEndTime();
|
||||
try {
|
||||
Date end = sdf.parse(endTime);
|
||||
return end.getTime() - now.getTime();
|
||||
} catch (Exception ex) {
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static long getMonthLeftMilliseconds() {
|
||||
Date now = new Date();
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
String endTime = getMonthEndTime();
|
||||
try {
|
||||
Date end = sdf.parse(endTime);
|
||||
return end.getTime() - now.getTime();
|
||||
} catch (Exception ex) {
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
public static long getYearLeftMilliseconds() {
|
||||
Date now = new Date();
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
String endTime = getYearEndTime();
|
||||
try {
|
||||
Date end = sdf.parse(endTime);
|
||||
return end.getTime() - now.getTime();
|
||||
} catch (Exception ex) {
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2023 codvision.com All Rights Reserved.
|
||||
*/
|
||||
|
||||
package com.codvision.commoncore.utils;
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.crypto.Mode;
|
||||
import cn.hutool.crypto.Padding;
|
||||
import cn.hutool.crypto.symmetric.AES;
|
||||
import com.codvision.commoncore.exception.BusinessException;
|
||||
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* 登陆密码解密
|
||||
*
|
||||
* @author hxl
|
||||
*/
|
||||
public class DecPwdUtil {
|
||||
|
||||
/**
|
||||
* AES数据块长度为128位,IV(偏移量)长度需要为16个字符(ECB模式不用IV)
|
||||
* 密钥(SECRET_KEY)根据指定密钥位数分别为16、24、32个字符,IV与密钥超过长度则截取,不足则在末尾填充'\0'补足
|
||||
*/
|
||||
private static final String SECRET_KEY = "8237909036518327";
|
||||
private static final String IV = "4a3f824766747c27";
|
||||
|
||||
public static String encryptAes(String password) {
|
||||
AES aes = new AES(Mode.CBC, Padding.ZeroPadding, new SecretKeySpec(SECRET_KEY.getBytes(), "AES"), new IvParameterSpec(IV.getBytes()));
|
||||
try {
|
||||
return Base64.encode(aes.encrypt(password, StandardCharsets.UTF_8));
|
||||
} catch (Exception e) {
|
||||
throw new BusinessException(30001, "密码加密失败!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static String decryptAes(String password) {
|
||||
AES aes = new AES(Mode.CBC, Padding.ZeroPadding, new SecretKeySpec(SECRET_KEY.getBytes(), "AES"), new IvParameterSpec(IV.getBytes()));
|
||||
try {
|
||||
byte[] decrypt = aes.decrypt(Base64.decode(password.getBytes(StandardCharsets.UTF_8)));
|
||||
return new String(decrypt, StandardCharsets.UTF_8);
|
||||
} catch (Exception e) {
|
||||
throw new BusinessException(30001, "密码解密失败!");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(encryptAes("Jcpt@2023"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package com.codvision.commoncore.utils;
|
||||
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Formatter;
|
||||
|
||||
/**
|
||||
* 加解密工具类
|
||||
*
|
||||
* @author codvision
|
||||
*/
|
||||
public class Encryption {
|
||||
private static final String chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
private static final int scale = 62;
|
||||
|
||||
/**
|
||||
* 进行加密
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String encoding(String password) {
|
||||
String md5 = "";
|
||||
try {
|
||||
// 创建一个md5算法对象
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
byte[] messageByte = ("Codvision" + password).getBytes(StandardCharsets.UTF_8);
|
||||
// 获得MD5字节数组,16*8=128位
|
||||
byte[] md5Byte = md.digest(messageByte);
|
||||
// 转换为16进制字符串
|
||||
md5 = bytesToHex(md5Byte);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return md5;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 二进制转十六进制
|
||||
*
|
||||
* @param bytes
|
||||
* @return
|
||||
*/
|
||||
public static String bytesToHex(byte[] bytes) {
|
||||
StringBuffer hexStr = new StringBuffer();
|
||||
int num;
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
num = bytes[i];
|
||||
if (num < 0) {
|
||||
num += 256;
|
||||
}
|
||||
if (num < 16) {
|
||||
hexStr.append("0");
|
||||
}
|
||||
hexStr.append(Integer.toHexString(num));
|
||||
}
|
||||
return hexStr.toString().toUpperCase();
|
||||
}
|
||||
|
||||
|
||||
public static String getSign(String jsTicket, String nonceStr, long timeStamp, String url) throws Exception {
|
||||
|
||||
String planTex = "jsapi_ticket=" + jsTicket + "&noncestr=" + nonceStr + "×tamp=" + timeStamp + "&url=" + url;
|
||||
MessageDigest crypt = null;
|
||||
try {
|
||||
crypt = MessageDigest.getInstance("SHA-1");
|
||||
crypt.reset();
|
||||
crypt.update(planTex.getBytes(StandardCharsets.UTF_8));
|
||||
return byteToHex(crypt.digest());
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new Exception(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将bytes类型的数据转化为16进制类型
|
||||
*
|
||||
* @param digest
|
||||
* @return
|
||||
*/
|
||||
private static String byteToHex(byte[] digest) {
|
||||
Formatter formatter = new Formatter();
|
||||
for (byte b : digest) {
|
||||
formatter.format("%02x", Byte.valueOf(b));
|
||||
}
|
||||
String result = formatter.toString();
|
||||
formatter.close();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 10进制转62进制
|
||||
*
|
||||
* @param num
|
||||
* @return
|
||||
*/
|
||||
public static String encode(int num) {
|
||||
java.util.Random random = new java.util.Random();
|
||||
StringBuffer sbf = new StringBuffer();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int a = random.nextInt(10);
|
||||
sbf.append(a);
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int remainder = 0;
|
||||
while (num > scale - 1) {
|
||||
/**
|
||||
* 对 scale 进行求余,然后将余数追加至 sb 中,由于是从末位开始追加的,因此最后需要反转(reverse)字符串
|
||||
*/
|
||||
remainder = Long.valueOf(num % scale).intValue();
|
||||
sb.append(chars.charAt(remainder));
|
||||
|
||||
num = num / scale;
|
||||
}
|
||||
|
||||
sb.append(chars.charAt(Long.valueOf(num).intValue()));
|
||||
String value = sb.reverse().toString() + sbf;
|
||||
return value;
|
||||
}
|
||||
|
||||
public static int decode(String str) {
|
||||
str = str.substring(0, str.length() - 4);
|
||||
int num = 0;
|
||||
int index = 0;
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
/**
|
||||
* 查找字符的索引位置
|
||||
*/
|
||||
index = chars.indexOf(str.charAt(i));
|
||||
/**
|
||||
* 索引位置代表字符的数值
|
||||
*/
|
||||
num += (long) (index * (Math.pow(scale, str.length() - i - 1)));
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,346 @@
|
||||
package com.codvision.commoncore.utils;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.http.HttpEntityEnclosingRequest;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.NoHttpResponseException;
|
||||
import org.apache.http.client.HttpRequestRetryHandler;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.protocol.HttpClientContext;
|
||||
import org.apache.http.client.utils.URIBuilder;
|
||||
import org.apache.http.config.Registry;
|
||||
import org.apache.http.config.RegistryBuilder;
|
||||
import org.apache.http.conn.routing.HttpRoute;
|
||||
import org.apache.http.conn.socket.ConnectionSocketFactory;
|
||||
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
|
||||
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
|
||||
import org.apache.http.conn.ssl.NoopHostnameVerifier;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
||||
import javax.net.ssl.*;
|
||||
import java.io.IOException;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.net.URI;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* HttpClientUtils
|
||||
*
|
||||
* @author Bulbasaur
|
||||
* @since 2021/7/9 1:40 上午
|
||||
*/
|
||||
@Slf4j
|
||||
public class HttpClientUtils {
|
||||
|
||||
/**
|
||||
* org.apache.http.impl.client.CloseableHttpClient
|
||||
*/
|
||||
private static CloseableHttpClient httpClient = null;
|
||||
|
||||
private static CloseableHttpClient httpsClient = null;
|
||||
|
||||
//这里就直接默认固定了,因为以下三个参数在新建的method中仍然可以重新配置并被覆盖.
|
||||
/**
|
||||
* ms毫秒,从池中获取链接超时时间
|
||||
*/
|
||||
static final int CONNECTION_REQUEST_TIMEOUT = 30000;
|
||||
/**
|
||||
* ms毫秒,建立链接超时时间
|
||||
*/
|
||||
static final int CONNECT_TIMEOUT = 60000;
|
||||
/**
|
||||
* ms毫秒,读取超时时间
|
||||
*/
|
||||
static final int SOCKET_TIMEOUT = 60000;
|
||||
|
||||
/**
|
||||
* 总配置,主要涉及是以下两个参数,如果要作调整没有用到properties会比较后麻烦,但鉴于一经粘贴,随处可用的特点,就不再做依赖性配置化处理了.
|
||||
* 而且这个参数同一家公司基本不会变动.
|
||||
* 最大总并发,很重要的参数
|
||||
*/
|
||||
static final int MAX_TOTAL = 500;
|
||||
/**
|
||||
* 每路并发,很重要的参数
|
||||
*/
|
||||
static final int MAX_PER_ROUTE = 100;
|
||||
|
||||
/**
|
||||
* 正常情况这里应该配成MAP或LIST
|
||||
* 细化配置参数,用来对每路参数做精细化处理,可以管控各ip的流量,比如默认配置请求baidu:80端口最大100个并发链接,
|
||||
* 每个细化配置之ip(不重要,在特殊场景很有用)
|
||||
*/
|
||||
static final String DETAIL_HOST_NAME = "http://www.baidu.com";
|
||||
|
||||
/**
|
||||
* 每个细化配置之port(不重要,在特殊场景很有用)
|
||||
*/
|
||||
static final int DETAIL_PORT = 80;
|
||||
/**
|
||||
* 每个细化配置之最大并发数(不重要,在特殊场景很有用)
|
||||
*/
|
||||
static final int DETAIL_MAX_PER_ROUTE = 100;
|
||||
|
||||
private synchronized static CloseableHttpClient getHttpClient() {
|
||||
if (null == httpClient) {
|
||||
httpClient = initHttp();
|
||||
}
|
||||
return httpClient;
|
||||
}
|
||||
|
||||
private synchronized static CloseableHttpClient getHttpsClient() {
|
||||
if (null == httpsClient) {
|
||||
httpsClient = initHttps();
|
||||
}
|
||||
return httpsClient;
|
||||
}
|
||||
|
||||
//绕过证书
|
||||
public static CloseableHttpClient initHttps() {
|
||||
try {
|
||||
SSLContext ctx = SSLContext.getInstance("TLS");
|
||||
X509TrustManager tm = new X509TrustManager() {
|
||||
@Override
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkClientTrusted(X509Certificate[] arg0,
|
||||
String arg1) throws CertificateException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(X509Certificate[] arg0,
|
||||
String arg1) throws CertificateException {
|
||||
}
|
||||
};
|
||||
ctx.init(null, new TrustManager[]{tm}, null);
|
||||
SSLConnectionSocketFactory ssf = new SSLConnectionSocketFactory(
|
||||
ctx, NoopHostnameVerifier.INSTANCE);
|
||||
httpsClient = HttpClients.custom()
|
||||
.setSSLSocketFactory(ssf).build();
|
||||
return httpsClient;
|
||||
} catch (Exception e) {
|
||||
return HttpClients.createDefault();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 链接池初始化 这里最重要的一点理解就是. 让CloseableHttpClient 一直活在池的世界里, 但是HttpPost却一直用完就消掉.
|
||||
* 这样可以让链接一直保持着.
|
||||
*/
|
||||
private static CloseableHttpClient initHttp() {
|
||||
CloseableHttpClient newHotpoint;
|
||||
|
||||
//设置连接池
|
||||
ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory();
|
||||
LayeredConnectionSocketFactory sslsf = SSLConnectionSocketFactory.getSocketFactory();
|
||||
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", plainsf).register("https", sslsf).build();
|
||||
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
|
||||
//将最大连接数增加
|
||||
cm.setMaxTotal(MAX_TOTAL);
|
||||
//将每个路由基础的连接增加
|
||||
cm.setDefaultMaxPerRoute(MAX_PER_ROUTE);
|
||||
|
||||
//细化配置开始,其实这里用Map或List的for循环来配置每个链接,在特殊场景很有用.
|
||||
//将每个路由基础的连接做特殊化配置,一般用不着
|
||||
HttpHost httpHost = new HttpHost(DETAIL_HOST_NAME, DETAIL_PORT);
|
||||
//将目标主机的最大连接数增加
|
||||
cm.setMaxPerRoute(new HttpRoute(httpHost), DETAIL_MAX_PER_ROUTE);
|
||||
//细化配置结束
|
||||
|
||||
//请求重试处理
|
||||
HttpRequestRetryHandler httpRequestRetryHandler = (exception, executionCount, context) -> {
|
||||
if (executionCount >= 2) {//如果已经重试了2次,就放弃
|
||||
return false;
|
||||
}
|
||||
if (exception instanceof NoHttpResponseException) {//如果服务器丢掉了连接,那么就重试
|
||||
return true;
|
||||
}
|
||||
if (exception instanceof SSLHandshakeException) {//不要重试SSL握手异常
|
||||
return false;
|
||||
}
|
||||
if (exception instanceof InterruptedIOException) {//超时
|
||||
return false;
|
||||
}
|
||||
if (exception instanceof UnknownHostException) {//目标服务器不可达
|
||||
return false;
|
||||
}
|
||||
if (exception instanceof SSLException) {//SSL握手异常
|
||||
return false;
|
||||
}
|
||||
|
||||
HttpClientContext clientContext = HttpClientContext.adapt(context);
|
||||
HttpRequest request = clientContext.getRequest();
|
||||
//如果请求是幂等的,就再次尝试
|
||||
return !(request instanceof HttpEntityEnclosingRequest);
|
||||
};
|
||||
|
||||
//配置请求的超时设置
|
||||
RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT).setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build();
|
||||
newHotpoint = HttpClients.custom().setConnectionManager(cm).setDefaultRequestConfig(requestConfig).setRetryHandler(httpRequestRetryHandler).build();
|
||||
return newHotpoint;
|
||||
}
|
||||
|
||||
public static String doGet(String url, Map<String, Object> param) {
|
||||
//httpClient
|
||||
CloseableHttpClient httpClient;
|
||||
if (url.startsWith("https://")) {
|
||||
httpClient = getHttpsClient();
|
||||
} else {
|
||||
httpClient = getHttpClient();
|
||||
}
|
||||
|
||||
String resultString = "";
|
||||
CloseableHttpResponse response = null;
|
||||
try {
|
||||
//创建uri
|
||||
URIBuilder builder = new URIBuilder(url);
|
||||
if (param != null) {
|
||||
for (String key : param.keySet()) {
|
||||
builder.addParameter(key, (String) param.get(key));
|
||||
}
|
||||
}
|
||||
URI uri = builder.build();
|
||||
|
||||
//创建http GET请求
|
||||
HttpGet httpGet = new HttpGet(uri);
|
||||
log.info(httpGet.toString());
|
||||
//执行请求
|
||||
response = httpClient.execute(httpGet);
|
||||
//判断返回状态是否为200
|
||||
if (response.getStatusLine().getStatusCode() == 200) {
|
||||
resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
|
||||
log.info(resultString);
|
||||
} else {
|
||||
log.error(url + "请求失败:" + response);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(url + "get请求错误:", e);
|
||||
throw new RuntimeException(e.getMessage());
|
||||
} finally {
|
||||
try {
|
||||
if (response != null) {
|
||||
response.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("Get错误", e);
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
}
|
||||
return resultString;
|
||||
}
|
||||
|
||||
public static String doPost(String url, Map<String, String> headers, String body) {
|
||||
//httpClient
|
||||
CloseableHttpClient httpClient;
|
||||
if (url.startsWith("https://")) {
|
||||
httpClient = getHttpsClient();
|
||||
} else {
|
||||
httpClient = getHttpClient();
|
||||
}
|
||||
|
||||
String resultString = "";
|
||||
CloseableHttpResponse response = null;
|
||||
try {
|
||||
//创建http GET请求
|
||||
HttpPost httpPost = new HttpPost(url);
|
||||
log.info(httpPost.toString());
|
||||
httpPost.addHeader("Content-Type", "application/json;charset=utf-8");
|
||||
if (CollectionUtil.isNotEmpty(headers)) {
|
||||
for (Map.Entry<String, String> entry : headers.entrySet()) {
|
||||
httpPost.addHeader(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
StringEntity stringEntity = new StringEntity(body, "UTF-8");
|
||||
httpPost.setEntity(stringEntity);
|
||||
//执行请求
|
||||
response = httpClient.execute(httpPost);
|
||||
//判断返回状态是否为200
|
||||
if (response.getStatusLine().getStatusCode() == 200) {
|
||||
resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
|
||||
log.info(resultString);
|
||||
} else {
|
||||
log.error(url + "请求失败:" + response);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(url + "post请求错误:", e);
|
||||
throw new RuntimeException(e.getMessage());
|
||||
} finally {
|
||||
try {
|
||||
if (response != null) {
|
||||
response.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("Post错误", e);
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
}
|
||||
return resultString;
|
||||
}
|
||||
|
||||
public static String doPost(String url, Map<String, String> headers, Map<String, String> params) {
|
||||
//httpClient
|
||||
CloseableHttpClient httpClient;
|
||||
if (url.startsWith("https://")) {
|
||||
httpClient = getHttpsClient();
|
||||
} else {
|
||||
httpClient = getHttpClient();
|
||||
}
|
||||
|
||||
String resultString = "";
|
||||
CloseableHttpResponse response = null;
|
||||
try {
|
||||
//创建uri
|
||||
URIBuilder builder = new URIBuilder(url);
|
||||
if (params != null) {
|
||||
for (String key : params.keySet()) {
|
||||
builder.addParameter(key, (String) params.get(key));
|
||||
}
|
||||
}
|
||||
URI uri = builder.build();
|
||||
HttpPost httpPost = new HttpPost(uri);
|
||||
log.info(httpPost.toString());
|
||||
if (CollectionUtil.isNotEmpty(headers)) {
|
||||
for (Map.Entry<String, String> entry : headers.entrySet()) {
|
||||
httpPost.addHeader(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
//执行请求
|
||||
response = httpClient.execute(httpPost);
|
||||
//判断返回状态是否为200
|
||||
if (response.getStatusLine().getStatusCode() == 200) {
|
||||
resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
|
||||
log.info(resultString);
|
||||
} else {
|
||||
log.error(url + "请求失败:" + response);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(url + "post请求错误:", e);
|
||||
throw new RuntimeException(e.getMessage());
|
||||
} finally {
|
||||
try {
|
||||
if (response != null) {
|
||||
response.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("Post错误", e);
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
}
|
||||
return resultString;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,339 @@
|
||||
package com.codvision.commoncore.utils;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 身份证号码的格式:610821-20061222-612-X 由18位数字组成:前6位为地址码,第7至14位为出生日期码,第15至17位为顺序码,
|
||||
* 第18位为校验码。检验码分别是0-10共11个数字,当检验码为“10”时,为了保证公民身份证号码18位,所以用“X”表示。虽然校验码为“X”不能更换,但若需全用数字表示,只需将18位公民身份号码转换成15位居民身份证号码,去掉第7至8位和最后1位3个数码。
|
||||
* 当今的身份证号码有15位和18位之分。1985年我国实行居民身份证制度,当时签发的身份证号码是15位的,1999年签发的身份证由于年份的扩展(由两位变为四位)和末尾加了效验码,就成了18位。
|
||||
* (1)前1、2位数字表示:所在省份的代码;
|
||||
* (2)第3、4位数字表示:所在城市的代码;
|
||||
* (3)第5、6位数字表示:所在区县的代码;
|
||||
* (4)第7~14位数字表示:出生年、月、日;
|
||||
* (5)第15、16位数字表示:所在地的派出所的代码;
|
||||
* (6)第17位数字表示性别:奇数表示男性,偶数表示女性
|
||||
* (7)第18位数字是校检码:根据一定算法生成
|
||||
*
|
||||
* @author codvision
|
||||
*/
|
||||
public class IdCardUtil {
|
||||
|
||||
/**
|
||||
* 身份证有效
|
||||
*/
|
||||
public static final String VALIDITY = "该身份证有效!";
|
||||
/**
|
||||
* 位数不足
|
||||
*/
|
||||
public static final String LACKDIGITS = "身份证号码长度应该为15位或18位。请检查是否有多余的空格";
|
||||
/**
|
||||
* 最后一位应为数字
|
||||
*/
|
||||
public static final String LASTOFNUMBER = "身份证15位号码都应为数字 ; 18位号码除最后一位外,都应为数字。";
|
||||
/**
|
||||
* 出生日期无效
|
||||
*/
|
||||
public static final String INVALIDBIRTH = "身份证出生日期无效。";
|
||||
/**
|
||||
* 生日不在有效范围
|
||||
*/
|
||||
public static final String INVALIDSCOPE = "身份证生日不在有效范围。";
|
||||
/**
|
||||
* 月份无效
|
||||
*/
|
||||
public static final String INVALIDMONTH = "身份证月份无效";
|
||||
/**
|
||||
* 日期无效
|
||||
*/
|
||||
public static final String INVALIDDAY = "身份证日期无效";
|
||||
/**
|
||||
* 身份证地区编码错误
|
||||
*/
|
||||
public static final String CODINGERROR = "身份证地区编码错误。";
|
||||
/**
|
||||
* 身份证校验码无效
|
||||
*/
|
||||
public static final String INVALIDCALIBRATION = "身份证校验码无效,不是合法的身份证号码";
|
||||
|
||||
private static final Pattern pattern = Pattern.compile("[0-9]*");
|
||||
private static final Pattern idCardPattern = Pattern.compile("^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))?$");
|
||||
|
||||
public static Integer getCardSex(String cardCode) {
|
||||
int sex = 0;
|
||||
if (StringUtils.isNotEmpty(cardCode)) {
|
||||
if (cardCode.length() == 18) {
|
||||
if (Integer.parseInt(cardCode.substring(16).substring(0, 1)) % 2 == 0) {
|
||||
sex = 2;
|
||||
} else {
|
||||
sex = 1;
|
||||
}
|
||||
} else if (cardCode.length() == 15) {
|
||||
if (Integer.parseInt(cardCode.substring(14, 15)) % 2 == 0) {
|
||||
sex = 2;
|
||||
} else {
|
||||
sex = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return sex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检验身份证号码是否符合规范
|
||||
*
|
||||
* @param idStr 身份证号码
|
||||
* @return 错误信息或成功信息
|
||||
*/
|
||||
public static String cardCodeVerifySimple(String idStr) {
|
||||
//记录错误信息
|
||||
String tipInfo = VALIDITY;
|
||||
String ai = "";
|
||||
idStr = idStr.trim();
|
||||
// 判断号码的长度 15位或18位
|
||||
if (idStr.length() != 15 && idStr.length() != 18) {
|
||||
tipInfo = LACKDIGITS;
|
||||
return tipInfo;
|
||||
}
|
||||
|
||||
// 18位身份证前17位位数字,如果是15位的身份证则所有号码都为数字
|
||||
if (idStr.length() == 18) {
|
||||
ai = idStr.substring(0, 17);
|
||||
} else if (idStr.length() == 15) {
|
||||
ai = idStr.substring(0, 6) + "19" + idStr.substring(6, 15);
|
||||
}
|
||||
if (isNumeric(ai) == false) {
|
||||
tipInfo = LASTOFNUMBER;
|
||||
return tipInfo;
|
||||
}
|
||||
|
||||
// 判断出生年月是否有效
|
||||
//年份
|
||||
String strYear = ai.substring(6, 10);
|
||||
// 月份
|
||||
String strMonth = ai.substring(10, 12);
|
||||
// 日期
|
||||
String strDay = ai.substring(12, 14);
|
||||
if (isDate(strYear + "-" + strMonth + "-" + strDay) == false) {
|
||||
tipInfo = INVALIDBIRTH;
|
||||
return tipInfo;
|
||||
}
|
||||
GregorianCalendar gc = new GregorianCalendar();
|
||||
SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd");
|
||||
try {
|
||||
if ((gc.get(Calendar.YEAR) - Integer.parseInt(strYear)) > 150
|
||||
|| (gc.getTime().getTime() - s.parse(strYear + "-" + strMonth + "-" + strDay).getTime()) < 0) {
|
||||
tipInfo = INVALIDSCOPE;
|
||||
return tipInfo;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (Integer.parseInt(strMonth) > 12 || Integer.parseInt(strMonth) == 0) {
|
||||
tipInfo = INVALIDMONTH;
|
||||
return tipInfo;
|
||||
}
|
||||
if (Integer.parseInt(strDay) > 31 || Integer.parseInt(strDay) == 0) {
|
||||
tipInfo = INVALIDDAY;
|
||||
return tipInfo;
|
||||
}
|
||||
|
||||
// 判断地区码是否有效
|
||||
Hashtable<String, String> areacode = getAreaCode();
|
||||
// 如果身份证前两位的地区码不在Hashtable,则地区码有误
|
||||
if (areacode.get(ai.substring(0, 2)) == null) {
|
||||
tipInfo = CODINGERROR;
|
||||
return tipInfo;
|
||||
}
|
||||
|
||||
if (isVarifyCode(ai, idStr) == false) {
|
||||
tipInfo = INVALIDCALIBRATION;
|
||||
return tipInfo;
|
||||
}
|
||||
|
||||
return tipInfo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据身份证的号码算出当前身份证持有者的性别和年龄 18位身份证
|
||||
*
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static Map<String, Object> getCarInfo18W(String cardCode)
|
||||
throws Exception {
|
||||
Map<String, Object> map = new HashMap<String, Object>(16);
|
||||
// 得到年份
|
||||
String year = cardCode.substring(6).substring(0, 4);
|
||||
// 得到月份
|
||||
String yue = cardCode.substring(10).substring(0, 2);
|
||||
String sex;
|
||||
// 判断性别
|
||||
if (Integer.parseInt(cardCode.substring(16).substring(0, 1)) % 2 == 0) {
|
||||
sex = "女";
|
||||
} else {
|
||||
sex = "男";
|
||||
}
|
||||
// 得到当前的系统时间
|
||||
Date date = new Date();
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
|
||||
// 当前年份
|
||||
String fyear = format.format(date).substring(0, 4);
|
||||
// 月份
|
||||
String fyue = format.format(date).substring(5, 7);
|
||||
int age = 0;
|
||||
// 当前月份大于用户出身的月份表示已过生
|
||||
if (Integer.parseInt(yue) <= Integer.parseInt(fyue)) {
|
||||
age = Integer.parseInt(fyear) - Integer.parseInt(year) + 1;
|
||||
// 当前用户还没过生
|
||||
} else {
|
||||
age = Integer.parseInt(fyear) - Integer.parseInt(year);
|
||||
}
|
||||
map.put("sex", sex);
|
||||
map.put("age", age);
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 15位身份证的验证
|
||||
*
|
||||
* @param
|
||||
* @throws Exception
|
||||
*/
|
||||
public static Map<String, Object> getCarInfo15W(String card)
|
||||
throws Exception {
|
||||
Map<String, Object> map = new HashMap<String, Object>(16);
|
||||
// 年份
|
||||
String uyear = "19" + card.substring(6, 8);
|
||||
// 月份
|
||||
String uyue = card.substring(8, 10);
|
||||
// 用户的性别
|
||||
String usex = card.substring(14, 15);
|
||||
String sex;
|
||||
if (Integer.parseInt(usex) % 2 == 0) {
|
||||
sex = "女";
|
||||
} else {
|
||||
sex = "男";
|
||||
}
|
||||
// 得到当前的系统时间
|
||||
Date date = new Date();
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
|
||||
// 当前年份
|
||||
String fyear = format.format(date).substring(0, 4);
|
||||
// 月份
|
||||
String fyue = format.format(date).substring(5, 7);
|
||||
int age = 0;
|
||||
// 当前月份大于用户出身的月份表示已过生
|
||||
if (Integer.parseInt(uyue) <= Integer.parseInt(fyue)) {
|
||||
age = Integer.parseInt(fyear) - Integer.parseInt(uyear) + 1;
|
||||
// 当前用户还没过生
|
||||
} else {
|
||||
age = Integer.parseInt(fyear) - Integer.parseInt(uyear);
|
||||
}
|
||||
map.put("sex", sex);
|
||||
map.put("age", age);
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断第18位校验码是否正确 第18位校验码的计算方式:
|
||||
* 1. 对前17位数字本体码加权求和 公式为:S = Sum(Ai * Wi), i =
|
||||
* 0, ... , 16 其中Ai表示第i个位置上的身份证号码数字值,Wi表示第i位置上的加权因子,其各位对应的值依次为: 7 9 10 5 8 4
|
||||
* 2 1 6 3 7 9 10 5 8 4 2
|
||||
* 2. 用11对计算结果取模 Y = mod(S, 11)
|
||||
* 3. 根据模的值得到对应的校验码
|
||||
* 对应关系为: Y值: 0 1 2 3 4 5 6 7 8 9 10 校验码: 1 0 X 9 8 7 6 5 4 3 2
|
||||
*/
|
||||
private static boolean isVarifyCode(String ai, String idStr) {
|
||||
String[] varifyCode = {"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"};
|
||||
String[] wi = {"7", "9", "10", "5", "8", "4", "2", "1", "6", "3", "7", "9", "10", "5", "8", "4", "2"};
|
||||
int sum = 0;
|
||||
for (int i = 0; i < 17; i++) {
|
||||
sum = sum + Integer.parseInt(String.valueOf(ai.charAt(i))) * Integer.parseInt(wi[i]);
|
||||
}
|
||||
int modValue = sum % 11;
|
||||
String strVerifyCode = varifyCode[modValue];
|
||||
ai = ai + strVerifyCode;
|
||||
if (idStr.length() == 18) {
|
||||
return ai.equals(idStr) != false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将所有地址编码保存在一个Hashtable中
|
||||
*
|
||||
* @return Hashtable 对象
|
||||
*/
|
||||
|
||||
private static Hashtable<String, String> getAreaCode() {
|
||||
Hashtable<String, String> hashtable = new Hashtable<String, String>();
|
||||
hashtable.put("11", "北京");
|
||||
hashtable.put("12", "天津");
|
||||
hashtable.put("13", "河北");
|
||||
hashtable.put("14", "山西");
|
||||
hashtable.put("15", "内蒙古");
|
||||
hashtable.put("21", "辽宁");
|
||||
hashtable.put("22", "吉林");
|
||||
hashtable.put("23", "黑龙江");
|
||||
hashtable.put("31", "上海");
|
||||
hashtable.put("32", "江苏");
|
||||
hashtable.put("33", "浙江");
|
||||
hashtable.put("34", "安徽");
|
||||
hashtable.put("35", "福建");
|
||||
hashtable.put("36", "江西");
|
||||
hashtable.put("37", "山东");
|
||||
hashtable.put("41", "河南");
|
||||
hashtable.put("42", "湖北");
|
||||
hashtable.put("43", "湖南");
|
||||
hashtable.put("44", "广东");
|
||||
hashtable.put("45", "广西");
|
||||
hashtable.put("46", "海南");
|
||||
hashtable.put("50", "重庆");
|
||||
hashtable.put("51", "四川");
|
||||
hashtable.put("52", "贵州");
|
||||
hashtable.put("53", "云南");
|
||||
hashtable.put("54", "西藏");
|
||||
hashtable.put("61", "陕西");
|
||||
hashtable.put("62", "甘肃");
|
||||
hashtable.put("63", "青海");
|
||||
hashtable.put("64", "宁夏");
|
||||
hashtable.put("65", "新疆");
|
||||
hashtable.put("71", "台湾");
|
||||
hashtable.put("81", "香港");
|
||||
hashtable.put("82", "澳门");
|
||||
hashtable.put("91", "国外");
|
||||
return hashtable;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断字符串是否为数字,0-9重复0次或者多次
|
||||
*
|
||||
* @param strnum
|
||||
* @return true, 符合; false, 不符合。
|
||||
*/
|
||||
private static boolean isNumeric(String strnum) {
|
||||
|
||||
Matcher isNum = pattern.matcher(strnum);
|
||||
return isNum.matches();
|
||||
}
|
||||
|
||||
/**
|
||||
* 功能:判断字符串出生日期是否符合正则表达式:包括年月日,闰年、平年和每月31天、30天和闰月的28天或者29天
|
||||
*
|
||||
* @param strDate
|
||||
* @return true, 符合; false, 不符合。
|
||||
*/
|
||||
public static boolean isDate(String strDate) {
|
||||
Matcher m = idCardPattern.matcher(strDate);
|
||||
return m.matches();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.codvision.commoncore.utils;
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.util.HexUtil;
|
||||
import cn.hutool.crypto.CryptoException;
|
||||
import cn.hutool.crypto.KeyUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import cn.hutool.crypto.asymmetric.SignAlgorithm;
|
||||
|
||||
import java.security.*;
|
||||
|
||||
/**
|
||||
* @author hxl
|
||||
*/
|
||||
public class LySign {
|
||||
|
||||
/**
|
||||
* 算法
|
||||
*/
|
||||
protected String algorithm;
|
||||
|
||||
protected String algorithmAfterWith;
|
||||
/**
|
||||
* 公钥
|
||||
*/
|
||||
protected PublicKey publicKey;
|
||||
/**
|
||||
* 私钥
|
||||
*/
|
||||
protected PrivateKey privateKey;
|
||||
|
||||
/**
|
||||
* 签名,用于签名和验证
|
||||
*/
|
||||
protected Signature signature;
|
||||
|
||||
public LySign(SignAlgorithm algorithmE, byte[] privateKey, byte[] publicKey) {
|
||||
this.algorithm = algorithmE.getValue();
|
||||
this.algorithmAfterWith = KeyUtil.getAlgorithmAfterWith(this.algorithm);
|
||||
this.privateKey = SecureUtil.generatePrivateKey(this.algorithmAfterWith, privateKey);
|
||||
this.publicKey = SecureUtil.generatePublicKey(this.algorithmAfterWith, publicKey);
|
||||
try {
|
||||
this.signature = Signature.getInstance(algorithm);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new CryptoException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static LySign of(SignAlgorithm algorithm, String privateKey, String publicKey, boolean hexStr) {
|
||||
byte[] privateBytes;
|
||||
byte[] publicBytes;
|
||||
if (hexStr) {
|
||||
privateBytes = HexUtil.decodeHex(privateKey);
|
||||
publicBytes = HexUtil.decodeHex(publicKey);
|
||||
} else {
|
||||
privateBytes = Base64.decode(privateKey);
|
||||
publicBytes = Base64.decode(publicKey);
|
||||
}
|
||||
return new LySign(algorithm, privateBytes, publicBytes);
|
||||
}
|
||||
|
||||
public String sign(String data) {
|
||||
try {
|
||||
signature.initSign(privateKey);
|
||||
signature.update(data.getBytes());
|
||||
byte[] sign = signature.sign();
|
||||
return HexUtil.encodeHexStr(sign, false);
|
||||
} catch (InvalidKeyException | SignatureException e) {
|
||||
throw new CryptoException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean verify(String data, String sign) {
|
||||
try {
|
||||
signature.initVerify(publicKey);
|
||||
signature.update(data.getBytes());
|
||||
return signature.verify(HexUtil.decodeHex(sign));
|
||||
} catch (InvalidKeyException | SignatureException e) {
|
||||
throw new CryptoException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
package com.codvision.commoncore.utils;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
* @author zjm
|
||||
* @version V1.0
|
||||
* @Package com.codvision.serverboot.util
|
||||
* @date 2020/3/4 10:00
|
||||
* @Copyright © 2017-2020 杭州码全科技有限公司
|
||||
*/
|
||||
public class Md5Utils {
|
||||
|
||||
/**
|
||||
* md5加密
|
||||
*
|
||||
* @param message 内容
|
||||
* @return 摘要
|
||||
*/
|
||||
public static String md5Encode(String message) {
|
||||
String temp = "";
|
||||
try {
|
||||
MessageDigest md5Digest = MessageDigest.getInstance("MD5");
|
||||
byte[] d = md5Digest.digest(message.getBytes());
|
||||
temp = converByteToHexString(d);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换byte到16进制
|
||||
*
|
||||
* @param b 要转换的byte
|
||||
* @return 16进制对应的字符
|
||||
*/
|
||||
private static String converByteToHexString(byte[] b) {
|
||||
String result = "";
|
||||
for (int i = 1; i < b.length; i++) {
|
||||
int temp = b[i] & 0xff;
|
||||
String tempHex = Integer.toHexString(temp);
|
||||
if (tempHex.length() < 2) {
|
||||
|
||||
result += "" + tempHex;
|
||||
} else {
|
||||
result += tempHex;
|
||||
}
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取摘要
|
||||
*
|
||||
* @param str 内容
|
||||
* @return 摘要
|
||||
*/
|
||||
public static String getMd5(String str) {
|
||||
try {
|
||||
// 生成一个MD5加密计算摘要
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
// 计算md5函数
|
||||
md.update(str.getBytes());
|
||||
String md5 = new BigInteger(1, md.digest()).toString(16);
|
||||
return fillMd5(md5);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("MD5加密错误:" + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充摘要
|
||||
*
|
||||
* @param md5 摘要
|
||||
* @return 填充后的摘要
|
||||
*/
|
||||
public static String fillMd5(String md5) {
|
||||
return md5.length() == 32 ? md5 : fillMd5("0" + md5);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 使用指定哈希算法计算摘要信息
|
||||
*
|
||||
* @param content 内容
|
||||
* @param algorithm 哈希算法
|
||||
* @return 内容摘要
|
||||
*/
|
||||
public static String getMd5Digest(String content, String algorithm) {
|
||||
try {
|
||||
MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
|
||||
messageDigest.update(content.getBytes(StandardCharsets.UTF_8));
|
||||
return bytesToHexString(messageDigest.digest());
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字节数组转换成16进制字符串
|
||||
*
|
||||
* @param bytes 即将转换的数据
|
||||
* @return 16进制字符串
|
||||
*/
|
||||
private static String bytesToHexString(byte[] bytes) {
|
||||
StringBuffer sb = new StringBuffer(bytes.length);
|
||||
String temp = null;
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
temp = Integer.toHexString(0xFF & bytes[i]);
|
||||
if (temp.length() < 2) {
|
||||
sb.append(0);
|
||||
}
|
||||
sb.append(temp);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String md532Encode(String s) {
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
byte[] bytes = md.digest(s.getBytes(StandardCharsets.UTF_8));
|
||||
return toHex(bytes);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String toHex(byte[] bytes) {
|
||||
|
||||
final char[] HEX_DIGITS = "0123456789abcdef".toCharArray();
|
||||
StringBuilder ret = new StringBuilder(bytes.length * 2);
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
ret.append(HEX_DIGITS[(bytes[i] >> 4) & 0x0f]);
|
||||
ret.append(HEX_DIGITS[bytes[i] & 0x0f]);
|
||||
}
|
||||
return ret.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.codvision.commoncore.utils;
|
||||
|
||||
import com.codvision.commoncore.enums.NetworkData;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 网络工具类
|
||||
* Created by mrhe on 2018/2/17.
|
||||
*/
|
||||
public class NetworkUtils {
|
||||
|
||||
/**
|
||||
* 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址;
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public static String getIpAddress(HttpServletRequest request) throws IOException {
|
||||
// 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址
|
||||
|
||||
String ip = request.getHeader("X-Forwarded-For");
|
||||
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("Proxy-Client-IP");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("WL-Proxy-Client-IP");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("HTTP_CLIENT_IP");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getRemoteAddr();
|
||||
}
|
||||
} else if (ip.length() > 15) {
|
||||
String[] ips = ip.split(",");
|
||||
for (int index = 0; index < ips.length; index++) {
|
||||
String strIp = ips[index];
|
||||
if (!("unknown".equalsIgnoreCase(strIp))) {
|
||||
ip = strIp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ip.equals(NetworkData.NET_WORK_ID.getDesc()) ? "127.0.0.1" : ip;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.codvision.commoncore.utils;
|
||||
|
||||
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author zjm
|
||||
* @version V1.0
|
||||
* @Package com.codvision.serverboot.util
|
||||
* @date 2020/3/4 9:48
|
||||
* @Copyright © 2017-2020 杭州码全科技有限公司
|
||||
*/
|
||||
public class ParamUtil {
|
||||
|
||||
public static boolean isKeyExist(Map<String, Object> params, String key) {
|
||||
return isKeyExist(params, key, true);
|
||||
}
|
||||
|
||||
public static boolean isKeyExist(Map<String, Object> params, String key, boolean ignoreEmptyValue) {
|
||||
if (ignoreEmptyValue) {
|
||||
return params.containsKey(key) && null != params.get(key) && StringUtils.isNotEmpty(params.get(key).toString());
|
||||
} else {
|
||||
return params.containsKey(key) && null != params.get(key);
|
||||
}
|
||||
}
|
||||
|
||||
public static Map<String, String> objectToMap(Object obj) throws IllegalAccessException {
|
||||
Map<String, String> map = new HashMap<String, String>(16);
|
||||
Class<?> clazz = obj.getClass();
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
field.setAccessible(true);
|
||||
String fieldName = field.getName();
|
||||
if (!(ObjectUtils.isEmpty(field.get(obj)))) {
|
||||
Object value = field.get(obj);
|
||||
map.put(fieldName, String.valueOf(value));
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.codvision.commoncore.utils;
|
||||
|
||||
|
||||
import com.codvision.commoncore.common.ResponseEntity;
|
||||
import com.codvision.commoncore.exception.BusinessException;
|
||||
import lombok.NonNull;
|
||||
|
||||
/**
|
||||
* @author hxl
|
||||
*/
|
||||
public final class Preconditions {
|
||||
|
||||
/**
|
||||
* @param expression 布尔表达式
|
||||
* @param code 自定义响应状态码
|
||||
* @param errorMsg 检查失败时使用的异常消息
|
||||
* @throws BusinessException if {@code expression} is false
|
||||
*/
|
||||
public static void checkArgument(boolean expression, int code, @NonNull Object errorMsg) {
|
||||
if (!expression) {
|
||||
throw new BusinessException(code, String.valueOf(errorMsg));
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkArgument(boolean expression, @NonNull Object errorMsg) {
|
||||
if (!expression) {
|
||||
throw new BusinessException(String.valueOf(errorMsg));
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkArgument(boolean expression, int code) {
|
||||
if (!expression) {
|
||||
throw new BusinessException(code, new ResponseEntity<>().setCode(code).getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.codvision.commoncore.utils;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* @author: fuyuaaaaa
|
||||
* @description: 随机数 工具 类
|
||||
* @program: smart-rear
|
||||
* @creat: 2018-09-21 10:10
|
||||
**/
|
||||
public class RandomUtil {
|
||||
|
||||
/**
|
||||
* 获取6位数验证码
|
||||
*
|
||||
* @return 验证码
|
||||
*/
|
||||
public static String getVerificationCode() {
|
||||
Random random = new Random();
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (int i = 0; i < 6; i++) {
|
||||
int a = random.nextInt(10);
|
||||
sb.append(a);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定长度验证码
|
||||
*
|
||||
* @param length 长度
|
||||
* @return 验证码
|
||||
*/
|
||||
public static String getRandomStr(int length) {
|
||||
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
Random random = new Random();
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (int i = 0; i < length; i++) {
|
||||
int number = random.nextInt(26);
|
||||
stringBuilder.append(str.charAt(number));
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2023 codvision.com All Rights Reserved.
|
||||
*/
|
||||
|
||||
package com.codvision.commoncore.utils;
|
||||
|
||||
import com.codvision.commoncore.common.ResponseEntity;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
|
||||
/**
|
||||
* 响应工具类
|
||||
*
|
||||
* @author lingee
|
||||
* @date 2023/7/18
|
||||
*/
|
||||
public class ResponseUtil {
|
||||
|
||||
/**
|
||||
* 判断请求是否成功
|
||||
*
|
||||
* @param response
|
||||
* @return
|
||||
*/
|
||||
public static boolean isSuccess(ResponseEntity response) {
|
||||
if (ObjectUtils.isNotEmpty(response)
|
||||
&& response.getCode() == 200
|
||||
&& ObjectUtils.isNotEmpty(response.getData())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isSuccessNotData(ResponseEntity response) {
|
||||
if (ObjectUtils.isNotEmpty(response)
|
||||
&& response.getCode() == 200) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.codvision.commoncore.utils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* 树节点父类
|
||||
* <p>
|
||||
* 所有需要使用{@linkplain TreeUtils}工具类形成树形结构等操作的节点都需要实现该接口
|
||||
*
|
||||
* @author lingee
|
||||
* @date 2024/04/24
|
||||
*/
|
||||
public interface TreeNode<T> {
|
||||
/**
|
||||
* 获取节点id
|
||||
*
|
||||
* @return 树节点id
|
||||
*/
|
||||
T id();
|
||||
|
||||
/**
|
||||
* 获取该节点的父节点id
|
||||
*
|
||||
* @return 父节点id
|
||||
*/
|
||||
T parentId();
|
||||
|
||||
/**
|
||||
* 是否是根节点
|
||||
*
|
||||
* @return true:根节点
|
||||
*/
|
||||
boolean root();
|
||||
|
||||
/**
|
||||
* 设置节点的子节点列表
|
||||
*
|
||||
* @param children 子节点
|
||||
*/
|
||||
void setChildren(List<? extends TreeNode<T>> children);
|
||||
|
||||
/**
|
||||
* 获取所有子节点
|
||||
*
|
||||
* @return 子节点列表
|
||||
*/
|
||||
List<? extends TreeNode<T>> getChildren();
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package com.codvision.commoncore.utils;
|
||||
|
||||
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 树形结构工具类
|
||||
*
|
||||
* @author lingee
|
||||
* @date 2024/04/24
|
||||
*/
|
||||
public class TreeUtils {
|
||||
|
||||
/**
|
||||
* 根据所有树节点列表,生成含有所有树形结构的列表
|
||||
*
|
||||
* @param nodes 树形节点列表
|
||||
* @param <T> 节点类型
|
||||
* @return 树形结构列表
|
||||
*/
|
||||
public static <T extends TreeNode<?>> List<T> generateTrees(List<T> nodes) {
|
||||
List<T> roots = new ArrayList<>();
|
||||
for (Iterator<T> ite = nodes.iterator(); ite.hasNext(); ) {
|
||||
T node = ite.next();
|
||||
if (node.root()) {
|
||||
roots.add(node);
|
||||
// 从所有节点列表中删除该节点,以免后续重复遍历该节点
|
||||
ite.remove();
|
||||
}
|
||||
}
|
||||
|
||||
if (CollectionUtils.isEmpty(roots)) {
|
||||
roots.addAll(nodes);
|
||||
}
|
||||
|
||||
roots.forEach(r -> {
|
||||
setChildren(r, nodes);
|
||||
});
|
||||
|
||||
return roots;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从所有节点列表中查找并设置parent的所有子节点
|
||||
*
|
||||
* @param parent 父节点
|
||||
* @param nodes 所有树节点列表
|
||||
*/
|
||||
public static <T extends TreeNode> void setChildren(T parent, List<T> nodes) {
|
||||
List<T> children = new ArrayList<>();
|
||||
Object parentId = parent.id();
|
||||
for (Iterator<T> ite = nodes.iterator(); ite.hasNext(); ) {
|
||||
T node = ite.next();
|
||||
if (Objects.equals(node.parentId(), parentId)) {
|
||||
children.add(node);
|
||||
// 从所有节点列表中删除该节点,以免后续重复遍历该节点
|
||||
ite.remove();
|
||||
}
|
||||
}
|
||||
// 如果孩子为空,则直接返回,否则继续递归设置孩子的孩子
|
||||
if (children.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
parent.setChildren(children);
|
||||
children.forEach(m -> {
|
||||
// 递归设置子节点
|
||||
setChildren(m, nodes);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除父节点下的所有子节点
|
||||
*
|
||||
* @param parentId 父级id
|
||||
* @param nodes 节点列表
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T extends TreeNode> List<Integer> removeChildren(Integer parentId, List<T> nodes) {
|
||||
|
||||
List<Integer> removeIds = new ArrayList<>();
|
||||
for (Iterator<T> ite = nodes.iterator(); ite.hasNext(); ) {
|
||||
T node = ite.next();
|
||||
if (Objects.equals(node.parentId(), parentId)) {
|
||||
removeIds.add((Integer) node.id());
|
||||
ite.remove();
|
||||
}
|
||||
}
|
||||
return removeIds;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将parent的所有叶子节点填充至leafs列表中
|
||||
*
|
||||
* @param parent 父节点
|
||||
* @param leafs 叶子节点列表
|
||||
* @param <T> 实际节点类型
|
||||
*/
|
||||
public static <T extends TreeNode> void fillLeaf(T parent, List<T> leafs) {
|
||||
List<T> children = parent.getChildren();
|
||||
// 如果节点没有子节点则说明为叶子节点
|
||||
if (CollectionUtils.isEmpty(children)) {
|
||||
leafs.add(parent);
|
||||
return;
|
||||
}
|
||||
// 递归调用子节点,查找叶子节点
|
||||
for (T child : children) {
|
||||
fillLeaf(child, leafs);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user