[common]公共校验和工具

This commit is contained in:
tomsun28
2022-01-30 09:54:59 +08:00
parent def62ce0a9
commit cf2731a1a1
14 changed files with 350 additions and 16 deletions

View File

@@ -19,6 +19,24 @@
<artifactId>spring-boot-starter-web</artifactId>
<scope>provided</scope>
</dependency>
<!-- jpa -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<scope>provided</scope>
</dependency>
<!-- validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<scope>provided</scope>
</dependency>
<!-- jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<scope>provided</scope>
</dependency>
<!-- swagger -->
<dependency>
<groupId>io.springfox</groupId>

View File

@@ -0,0 +1,48 @@
package com.usthe.common.support;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* Spring的ApplicationContext的持有者,可以用静态方法的方式获取spring容器中的bean
* @author tomsun28
* @date 21:07 2018/4/18
*/
@Component
public class SpringContextHolder implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
set(applicationContext);
}
private static void set(ApplicationContext applicationContext) {
SpringContextHolder.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
assertApplicationContext();
return applicationContext;
}
@SuppressWarnings("unchecked")
public static <T> T getBean(String beanName) {
assertApplicationContext();
return (T) applicationContext.getBean(beanName);
}
public static <T> T getBean(Class<T> tClass) {
assertApplicationContext();
return (T) applicationContext.getBean(tClass);
}
private static void assertApplicationContext() {
if (null == SpringContextHolder.applicationContext) {
throw new RuntimeException("applicationContext为空,请检查是否注入springContextHolder");
}
}
}

View File

@@ -0,0 +1,20 @@
package com.usthe.common.support.valid;
import com.usthe.common.util.CommonUtil;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
/**
* email注解数据自定义校验器
* @author tomsun28
* @date 2021/11/17 19:44
*/
public class EmailParamValidator implements ConstraintValidator<EmailValid, String> {
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
// 判断value是否满足ipv4 ipv5 域名 格式
return CommonUtil.validateEmail(value);
}
}

View File

@@ -0,0 +1,29 @@
package com.usthe.common.support.valid;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* email注解数据自定义校验器注解
* @author tomsun28
* @date 2021/11/17 19:42
*/
@Target({ FIELD, PARAMETER })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = EmailParamValidator.class)
public @interface EmailValid {
String message() default "Email value is invalid";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}

View File

@@ -0,0 +1,20 @@
package com.usthe.common.support.valid;
import com.usthe.common.util.IpDomainUtil;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
/**
* host注解数据自定义校验器
* @author tomsun28
* @date 2021/11/17 19:44
*/
public class HostParamValidator implements ConstraintValidator<HostValid, String> {
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
// 判断value是否满足ipv4 ipv5 域名 格式
return IpDomainUtil.validateIpDomain(value);
}
}

View File

@@ -0,0 +1,29 @@
package com.usthe.common.support.valid;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* host注解数据自定义校验器注解
* @author tomsun28
* @date 2021/11/17 19:42
*/
@Target({ FIELD, PARAMETER })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = HostParamValidator.class)
public @interface HostValid {
String message() default "Host value is invalid,must ipv4, ipv6 or domain";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}

View File

@@ -0,0 +1,20 @@
package com.usthe.common.support.valid;
import com.usthe.common.util.CommonUtil;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
/**
* PhoneNum注解数据自定义校验器
* @author tomsun28
* @date 2021/11/17 19:44
*/
public class PhoneNumParamValidator implements ConstraintValidator<PhoneNumValid, String> {
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
// 判断value是否满足ipv4 ipv5 域名 格式
return CommonUtil.validatePhoneNum(value);
}
}

View File

@@ -0,0 +1,29 @@
package com.usthe.common.support.valid;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* phoneNum注解数据自定义校验器注解
* @author tomsun28
* @date 2021/11/17 19:42
*/
@Target({ FIELD, PARAMETER })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = PhoneNumParamValidator.class)
public @interface PhoneNumValid {
String message() default "Phone num value is invalid";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}

View File

@@ -1,7 +1,6 @@
package com.usthe.common.util;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
@@ -9,6 +8,7 @@ import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
/**
* AES 对称加密解密工具
@@ -58,7 +58,7 @@ public class AesUtil {
//根据密码器的初始化方式--加密:将数据加密
byte[] byteAes = cipher.doFinal(byteEncode);
//将加密后的byte[]数据转换为Base64字符串
return new String(Base64.encodeBase64(byteAes),StandardCharsets.UTF_8);
return new String(Base64.getEncoder().encode(byteAes),StandardCharsets.UTF_8);
//将字符串返回
} catch (Exception e) {
log.error("密文加密失败"+e.getMessage(),e);
@@ -85,27 +85,22 @@ public class AesUtil {
//初始化密码器,第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作第二个参数为使用的KEY
cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(decryptKey.getBytes(StandardCharsets.UTF_8)));
//8.将加密并编码base64后的字符串内容base64解码成字节数组
byte[] bytesContent = Base64.decodeBase64(content);
byte[] bytesContent = Base64.getDecoder().decode(content);
/*
* 解密
*/
byte[] byteDecode = cipher.doFinal(bytesContent);
return new String(byteDecode, StandardCharsets.UTF_8);
} catch (NoSuchAlgorithmException e) {
log.error("没有指定的加密算法::"+e.getMessage(),e);
log.error("没有指定的加密算法::{}", e.getMessage(),e);
} catch (IllegalBlockSizeException e) {
log.error("非法的块大小"+"::"+e.getMessage(),e);
throw new RuntimeException("密文解密失败");
log.error("非法的块大小::{}", e.getMessage(),e);
} catch (NullPointerException e) {
log.error("秘钥解析空指针异常"+"::"+e.getMessage(),e);
throw new RuntimeException("秘钥解析空指针异常");
log.error("秘钥解析空指针异常::{}", e.getMessage(),e);
} catch (Exception e) {
log.error("秘钥AES解析出现未知错误"+"::"+e.getMessage(),e);
throw new RuntimeException("密文解密失败");
log.error("秘钥AES解析出现未知错误::{}", e.getMessage(),e);
}
//如果有错就返null
return null;
return content;
}
/**
@@ -115,6 +110,6 @@ public class AesUtil {
*/
public static boolean isCiphertext(String text) {
// 根据是否被base64来判断是否已经被加密
return Base64.isBase64(text);
return Base64Util.isBase64(text);
}
}

View File

@@ -0,0 +1,19 @@
package com.usthe.common.util;
import java.util.Base64;
/**
* base64工具类
* @author tom
* @date 2022/1/12 12:12
*/
public class Base64Util {
public static boolean isBase64(String base64) {
try {
return Base64.getDecoder().decode(base64) != null;
} catch (Exception e) {
return false;
}
}
}

View File

@@ -8,10 +8,15 @@ package com.usthe.common.util;
public interface CommonConstants {
/**
* 响应状态码: 成功
* 响应状态码: 通用成功
*/
byte SUCCESS_CODE = 0x00;
/**
* 响应状态码: 通用失败
*/
byte FAIL_CODE = 0x0F;
/**
* 响应状态码: 参数校验失败
*/
@@ -37,6 +42,13 @@ public interface CommonConstants {
*/
byte MONITOR_LOGIN_FAILED_CODE = 0x05;
/**
* 响应状态码: 注册失败异常
*/
byte MONITOR_REGISTER_FAILED_CODE = 0x06;
/**
* 监控状态码: 未管理
*/
@@ -126,4 +138,39 @@ public interface CommonConstants {
* 可达性对象
*/
String REACHABLE = "reachable";
/**
* 参数类型 数字
*/
byte PARAM_TYPE_NUMBER = 0;
/**
* 参数类型 字符串
*/
byte PARAM_TYPE_STRING = 1;
/**
* 参数类型 密码
*/
byte PARAM_TYPE_PASSWORD = 2;
/**
* 认证类型 账户密码
*/
byte AUTH_TYPE_PASSWORD = 1;
/**
* 认证类型 GITHUB三方登陆
*/
byte AUTH_TYPE_GITHUB = 2;
/**
* 认证类型 微信三方登陆
*/
byte AUTH_TYPE_WEIXIN = 3;
/**
* 认证类型 GITEE三方登陆
*/
byte AUTH_TYPE_GITEE = 5;
}

View File

@@ -2,6 +2,9 @@ package com.usthe.common.util;
import lombok.extern.slf4j.Slf4j;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 公共工具类
* @author tomsun28
@@ -10,6 +13,12 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
public class CommonUtil {
private static final Pattern EMAIL_PATTERN = Pattern.compile("\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*");
private static final Pattern PHONE_PATTERN = Pattern.compile("^(((13[0-9])|(15[0-9])|(18[0-9])|(17[0-9]))+\\d{8})?$");
private static final int PHONE_LENGTH = 11;
/**
* 将字符串str转换为double数字类型
* @param str string
@@ -27,4 +36,30 @@ public class CommonUtil {
}
}
/**
* 邮箱格式校验
* @param email 邮箱
* @return 是否校验成功
*/
public static boolean validateEmail(String email) {
if (email == null || "".equals(email)) {
return false;
}
Matcher m = EMAIL_PATTERN.matcher(email);
return m.find();
}
/**
* 手机号格式校验
* @param phoneNum 手机号
* @return 是否校验成功
*/
public static boolean validatePhoneNum(String phoneNum) {
if (phoneNum == null || "".equals(phoneNum) || phoneNum.length() != PHONE_LENGTH) {
return false;
}
Matcher m = PHONE_PATTERN.matcher(phoneNum);
return m.find();
}
}

View File

@@ -0,0 +1,25 @@
package com.usthe.common.util;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* 最近最少使用淘汰算法map
* @author tom
* @date 2021/12/27 14:13
*/
public class LruHashMap<K, V> extends LinkedHashMap<K, V> {
private int threshold;
public LruHashMap(int threshold) {
super(16, 0.75f, true);
this.threshold = threshold;
}
@Override
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > threshold;
}
}

View File

@@ -10,7 +10,7 @@ resourceRole:
# load api resource which do not need protected, means them need be excluded.
# these api resource can be access by everyone
excludedResource:
- /account/auth/form===post
- /account/auth/**===*
- /i18n/**===get
# web ui 静态资源
- /console/**===get