Cookie操作工具类
此工具是对网页请求Cookie的操作。
添加依赖:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
/**
* @ClassName CookieUtils
* @Describe Cookie工具类
* @Date 2020-05-20 11:42
* @Author Demon
**/
public final class CookieUtils {
/**
* 得到Cookie的值, 不编码
*
* @param request
* @param cookieName
* @return
*/
public static String getCookieValue(HttpServletRequest request, String cookieName) {
return getCookieValue(request, cookieName, false);
}
/**
* 得到Cookie的值,
*
* @param request
* @param cookieName
* @return
*/
public static String getCookieValue(HttpServletRequest request, String cookieName, boolean isDecoder) {
Cookie[] cookieList = request.getCookies();
if (cookieList == null || cookieName == null) {
return null;
}
String retValue = null;
try {
for (int i = 0; i < cookieList.length; i++) {
if (cookieList[i].getName().equals(cookieName)) {
if (isDecoder) {
retValue = URLDecoder.decode(cookieList[i].getValue(), "UTF-8");
} else {
retValue = cookieList[i].getValue();
}
break;
}
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return retValue;
}
/**
* 得到Cookie的值,
*
* @param request
* @param cookieName
* @return
*/
public static String getCookieValue(HttpServletRequest request, String cookieName, String encodeString) {
Cookie[] cookieList = request.getCookies();
if (cookieList == null || cookieName == null) {
return null;
}
String retValue = null;
try {
for (int i = 0; i < cookieList.length; i++) {
if (cookieList[i].getName().equals(cookieName)) {
retValue = URLDecoder.decode(cookieList[i].getValue(), encodeString);
break;
}
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return retValue;
}
/**
* 设置Cookie的值 不设置生效时间默认浏览器关闭即失效,也不编码
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
String cookieValue) {
setCookie(request, response, cookieName, cookieValue, -1);
}
/**
* 设置Cookie的值 在指定时间内生效,但不编码
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
String cookieValue, int cookieMaxage) {
setCookie(request, response, cookieName, cookieValue, cookieMaxage, false);
}
/**
* 设置Cookie的值 不设置生效时间,但编码
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
String cookieValue, boolean isEncode) {
setCookie(request, response, cookieName, cookieValue, -1, isEncode);
}
/**
* 设置Cookie的值 在指定时间内生效, 编码参数
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
String cookieValue, int cookieMaxage, boolean isEncode) {
doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, isEncode);
}
/**
* 设置Cookie的值 在指定时间内生效, 编码参数(指定编码)
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
String cookieValue, int cookieMaxage, String encodeString) {
doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, encodeString);
}
/**
* 删除Cookie带cookie域名
*/
public static void deleteCookie(HttpServletRequest request, HttpServletResponse response,
String cookieName) {
doSetCookie(request, response, cookieName, "", -1, false);
}
/**
* 设置Cookie的值,并使其在指定时间内生效
*
* @param cookieMaxage cookie生效的最大秒数
*/
private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response,
String cookieName, String cookieValue, int cookieMaxage, boolean isEncode) {
try {
if (cookieValue == null) {
cookieValue = "";
} else if (isEncode) {
cookieValue = URLEncoder.encode(cookieValue, "utf-8");
}
Cookie cookie = new Cookie(cookieName, cookieValue);
if (cookieMaxage > 0)
cookie.setMaxAge(cookieMaxage);
if (null != request) {// 设置域名的cookie
String domainName = getDomainName(request);
// System.out.println(domainName);
if (!"localhost".equals(domainName)) {
cookie.setDomain(domainName);
}
}
cookie.setPath("/");
response.addCookie(cookie);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 设置Cookie的值,并使其在指定时间内生效
*
* @param cookieMaxage cookie生效的最大秒数
*/
private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response,
String cookieName, String cookieValue, int cookieMaxage, String encodeString) {
try {
if (cookieValue == null) {
cookieValue = "";
} else {
cookieValue = URLEncoder.encode(cookieValue, encodeString);
}
Cookie cookie = new Cookie(cookieName, cookieValue);
if (cookieMaxage > 0)
cookie.setMaxAge(cookieMaxage);
if (null != request) {// 设置域名的cookie
String domainName = getDomainName(request);
// System.out.println(domainName);
if (!"localhost".equals(domainName)) {
cookie.setDomain(domainName);
}
}
cookie.setPath("/");
response.addCookie(cookie);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 得到cookie的域名
*/
private static final String getDomainName(HttpServletRequest request) {
String domainName = null;
String serverName = request.getRequestURL().toString();
if (serverName == null || serverName.equals("")) {
domainName = "";
} else {
serverName = serverName.toLowerCase();
serverName = serverName.substring(7);
final int end = serverName.indexOf("/");
serverName = serverName.substring(0, end);
final String[] domains = serverName.split("\\.");
int len = domains.length;
if (len > 3) {
// www.xxx.com.cn
domainName = "." + domains[len - 3] + "." + domains[len - 2] + "." + domains[len - 1];
} else if (len <= 3 && len > 1) {
// xxx.com or xxx.cn
domainName = "." + domains[len - 2] + "." + domains[len - 1];
} else {
domainName = serverName;
}
}
if (domainName != null && domainName.indexOf(":") > 0) {
String[] ary = domainName.split("\\:");
domainName = ary[0];
}
return domainName;
}
}
正则表达式工具类
/**
* @ClassName RegexpUtils
* @Describe 正则表达式工具类
* @Date 2020-05-20
* @Author Demon
**/
public class RegexpUtils {
/**
* 验证手机号
*/
public static final String PHONE = "^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$";
/**
* 验证邮箱地址
*/
public static final String EMAIL = "\\w+(\\.\\w)*@\\w+(\\.\\w{2,3}){1,3}";
/**
* 验证手机号
* @param phone
* @return
*/
public static boolean checkPhone(String phone) {
return phone.matches(PHONE);
}
/**
* 验证邮箱
* @param email
* @return
*/
public static boolean checkEmail(String email) {
return email.matches(EMAIL);
}
}
Json处理工具类
添加依赖:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.5</version>
</dependency>
package com.vv.finance.investment.pc.utils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.List;
import java.util.Map;
public class JsonUtils {
public static final ObjectMapper mapper = new ObjectMapper();
private static final Logger logger = LoggerFactory.getLogger(JsonUtils.class);
public static String toString(Object obj) {
if (obj == null) {
return null;
}
if (obj.getClass() == String.class) {
return (String) obj;
}
try {
return mapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
logger.error("json序列化出错:" + obj, e);
return null;
}
}
public static <T> T toBean(String json, Class<T> tClass) {
try {
return mapper.readValue(json, tClass);
} catch (IOException e) {
logger.error("json解析出错:" + json, e);
return null;
}
}
public static <T, E> T toGeneralizedBean(String json, Class<T> tClass, Class<E> eClass) {
try {
return mapper.readValue(json, mapper.getTypeFactory().constructParametricType(tClass, eClass));
} catch (IOException e) {
logger.error("json解析出错:" + json, e);
return null;
}
}
public static <E> List<E> toList(String json, Class<E> eClass) {
try {
return mapper.readValue(json, mapper.getTypeFactory().constructCollectionType(List.class, eClass));
} catch (IOException e) {
logger.error("json解析出错:" + json, e);
return null;
}
}
public static <K, V> Map<K, V> toMap(String json, Class<K> kClass, Class<V> vClass) {
try {
return mapper.readValue(json, mapper.getTypeFactory().constructMapType(Map.class, kClass, vClass));
} catch (IOException e) {
logger.error("json解析出错:" + json, e);
return null;
}
}
public static <T> T nativeRead(String json, TypeReference<T> type) {
try {
return mapper.readValue(json, type);
} catch (IOException e) {
logger.error("json解析出错:" + json, e);
return null;
}
}
}
手机号地区校验工具类
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
public class PhoneFormatCheckUtils {
/**
* 大陆号码或香港号码均可
*/
public static boolean isPhoneLegal(String str)throws PatternSyntaxException {
return isChinaPhoneLegal(str) || isHKPhoneLegal(str);
}
/**
* 大陆手机号码11位数,匹配格式:前三位固定格式+后8位任意数
* 此方法中前三位格式有:
* 13+任意数
* 15+除4的任意数
* 18+除1和4的任意数
* 17+除9的任意数
* 147
*/
public static boolean isChinaPhoneLegal(String str) throws PatternSyntaxException {
String regExp = "^((13[0-9])|(15[^4])|(18[0,2,3,5-9])|(17[0-8])|(147))\\d{8}$";
Pattern p = Pattern.compile(regExp);
Matcher m = p.matcher(str);
return m.matches();
}
/**
* 香港手机号码8位数,5|6|8|9开头+7位任意数
*/
public static boolean isHKPhoneLegal(String str)throws PatternSyntaxException {
String regExp = "^(5|6|8|9)\\d{7}$";
Pattern p = Pattern.compile(regExp);
Matcher m = p.matcher(str);
return m.matches();
}
}
HttpClient工具类
添加依赖:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.5</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>fluent-hc</artifactId>
<version>4.5.5</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.5</version>
</dependency>
import org.apache.http.HttpEntity;
import org.apache.http.client.entity.UrlEncodedFormEntity;
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.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.util.Arrays;
/**
* HttpClient 工具类
* <p>Title: HttpClientUtils</p>
* <p>Description: </p>
*
* @author Demon
* @version 1.0.0
* @date 2018/7/4 14:04
*/
public class HttpClientUtils {
public static final String GET = "get";
public static final String POST = "post";
public static final String REQUEST_HEADER_CONNECTION = "keep-alive";
public static final String REQUEST_HEADER_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36";
/**
* GET 请求
*
* @param url 请求地址
* @return
*/
public static String doGet(String url) {
return createRequest(url, GET, null);
}
/**
* GET 请求
*
* @param url 请求地址
* @param cookie cookie
* @return
*/
public static String doGet(String url, String cookie) {
return createRequest(url, GET, cookie);
}
/**
* POST 请求
*
* @param url 请求地址
* @param params 请求参数(可选)
* @return
*/
public static String doPost(String url, BasicNameValuePair... params) {
return createRequest(url, POST, null, params);
}
/**
* POST 请求
*
* @param url 请求地址
* @param cookie cookie
* @param params 请求参数(可选)
* @return
*/
public static String doPost(String url, String cookie, BasicNameValuePair... params) {
return createRequest(url, POST, cookie, params);
}
/**
* 创建请求
*
* @param url 请求地址
* @param requestMethod 请求方式 GET/POST
* @param cookie cookie
* @param params 请求参数 仅限于 POST 请求用
* @return
*/
private static String createRequest(String url, String requestMethod, String cookie, BasicNameValuePair... params) {
CloseableHttpClient httpClient = HttpClients.createDefault();
String result = null;
try {
// 请求结果
result = null;
// 请求方式
HttpGet httpGet = null;
HttpPost httpPost = null;
// 响应
CloseableHttpResponse httpResponse = null;
// GET 请求
if (GET.equals(requestMethod)) {
httpGet = new HttpGet(url);
httpGet.setHeader("Connection", REQUEST_HEADER_CONNECTION);
httpGet.setHeader("Cookie", cookie);
httpGet.setHeader("User-Agent", REQUEST_HEADER_USER_AGENT);
httpResponse = httpClient.execute(httpGet);
}
// POST 请求
else if (POST.equals(requestMethod)) {
httpPost = new HttpPost(url);
httpPost.setHeader("Connection", REQUEST_HEADER_CONNECTION);
httpPost.setHeader("Cookie", cookie);
httpPost.setHeader("User-Agent", REQUEST_HEADER_USER_AGENT);
// 有参数进来
if (params != null && params.length > 0) {
httpPost.setEntity(new UrlEncodedFormEntity(Arrays.asList(params), "UTF-8"));
}
httpResponse = httpClient.execute(httpPost);
}
HttpEntity httpEntity = httpResponse.getEntity();
result = EntityUtils.toString(httpEntity);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (httpClient != null) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
}
SocketClient工具类
import java.io.*;
import java.net.Socket;
/**
* @ClassName Socket.MySocketClient
* @Describe
* @Date 2020-06-03 15:43
* @Author Demon
**/
public class MySocketClient {
private Socket soc = null;
private String server = "";
private int port = 0;
public MySocketClient(String server, int port) {
this.server = server;
this.port = port;
try {
soc = new Socket(server, port);
} catch (Exception e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
//给服务器发送消息
public void sendMsgToServer(String msg) {
try {
DataOutputStream out = new DataOutputStream(soc.getOutputStream());
System.out.println(msg);
out.writeUTF(msg);
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
//从服务器接收消息
public void recMsgFromServer() {
byte[] b = null;
StringBuilder text = null;
while (true) {
try {
InputStream in = soc.getInputStream();
b = new byte[1024];
int len = 0;
while ((len = in.read(b)) != -1) {
String strText = new String(b, 0, len);
System.out.println(strText);
writeDataToTxt(strText);
}
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
public void writeDataToTxt(String strText) {
String fileName = "E:\\Desktop\\Temp\\01.txt";
File f = new File(fileName);
FileOutputStream out = null;
try {
out = new FileOutputStream(f, f.exists());
strText = "\n" + strText;
out.write(strText.getBytes());
out.close();
} catch (Exception e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
try {
out.close();
} catch (IOException e1) {
// TODO 自动生成的 catch 块
e1.printStackTrace();
}
}
}
}
实体类数据校验工具类
添加依赖:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.3.4.Final</version>
</dependency>
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* JSR303 Validator(Hibernate Validator)工具类.
* <p>
* ConstraintViolation 中包含 propertyPath, message 和 invalidValue 等信息.
* 提供了各种 convert 方法,适合不同的 i18n 需求:
* 1. List<String>, String 内容为 message
* 2. List<String>, String 内容为 propertyPath + separator + message
* 3. Map<propertyPath, message>
* <p>
* 详情见wiki: https://github.com/springside/springside4/wiki/HibernateValidator
*
* <p>Title: BeanValidator</p>
* <p>Description: </p>
*
* @author Demon
* @version 1.0.0
* @date 2018/6/26 17:21
*/
public class BeanValidator {
private static Validator validator;
public static void setValidator(Validator validator) {
BeanValidator.validator = validator;
}
/**
* 调用 JSR303 的 validate 方法, 验证失败时抛出 ConstraintViolationException.
*/
private static void validateWithException(Validator validator, Object object, Class<?>... groups) throws ConstraintViolationException {
Set constraintViolations = validator.validate(object, groups);
if (!constraintViolations.isEmpty()) {
throw new ConstraintViolationException(constraintViolations);
}
}
/**
* 辅助方法, 转换 ConstraintViolationException 中的 Set<ConstraintViolations> 中为 List<message>.
*/
private static List<String> extractMessage(ConstraintViolationException e) {
return extractMessage(e.getConstraintViolations());
}
/**
* 辅助方法, 转换 Set<ConstraintViolation> 为 List<message>
*/
private static List<String> extractMessage(Set<? extends ConstraintViolation> constraintViolations) {
List<String> errorMessages = new ArrayList<>();
for (ConstraintViolation violation : constraintViolations) {
errorMessages.add(violation.getMessage());
}
return errorMessages;
}
/**
* 辅助方法, 转换 ConstraintViolationException 中的 Set<ConstraintViolations> 为 Map<property, message>.
*/
private static Map<String, String> extractPropertyAndMessage(ConstraintViolationException e) {
return extractPropertyAndMessage(e.getConstraintViolations());
}
/**
* 辅助方法, 转换 Set<ConstraintViolation> 为 Map<property, message>.
*/
private static Map<String, String> extractPropertyAndMessage(Set<? extends ConstraintViolation> constraintViolations) {
Map<String, String> errorMessages = new HashMap<>();
for (ConstraintViolation violation : constraintViolations) {
errorMessages.put(violation.getPropertyPath().toString(), violation.getMessage());
}
return errorMessages;
}
/**
* 辅助方法, 转换 ConstraintViolationException 中的 Set<ConstraintViolations> 为 List<propertyPath message>.
*/
private static List<String> extractPropertyAndMessageAsList(ConstraintViolationException e) {
return extractPropertyAndMessageAsList(e.getConstraintViolations(), " ");
}
/**
* 辅助方法, 转换 Set<ConstraintViolations> 为 List<propertyPath message>.
*/
private static List<String> extractPropertyAndMessageAsList(Set<? extends ConstraintViolation> constraintViolations) {
return extractPropertyAndMessageAsList(constraintViolations, " ");
}
/**
* 辅助方法, 转换 ConstraintViolationException 中的 Set<ConstraintViolations> 为 List<propertyPath + separator + message>.
*/
private static List<String> extractPropertyAndMessageAsList(ConstraintViolationException e, String separator) {
return extractPropertyAndMessageAsList(e.getConstraintViolations(), separator);
}
/**
* 辅助方法, 转换 Set<ConstraintViolation> 为 List<propertyPath + separator + message>.
*/
private static List<String> extractPropertyAndMessageAsList(Set<? extends ConstraintViolation> constraintViolations, String separator) {
List<String> errorMessages = new ArrayList<>();
for (ConstraintViolation violation : constraintViolations) {
errorMessages.add(violation.getPropertyPath() + separator + violation.getMessage());
}
return errorMessages;
}
/**
* 服务端参数有效性验证
*
* @param object 验证的实体对象
* @param groups 验证组
* @return 验证成功:返回 null;验证失败:返回错误信息
*/
public static String validator(Object object, Class<?>... groups) {
try {
validateWithException(validator, object, groups);
} catch (ConstraintViolationException ex) {
List<String> list = extractMessage(ex);
list.add(0, "数据验证失败:");
// 封装错误消息为字符串
StringBuilder sb = new StringBuilder();
for (int i = 0; i < list.size(); i++) {
String exMsg = list.get(i);
if (i != 0) {
sb.append(String.format("%s. %s", i, exMsg)).append(list.size() > 1 ? "<br/>" : "");
} else {
sb.append(exMsg).append(list.size() > 1 ? "<br/>" : "");
}
}
return sb.toString();
}
return null;
}
}
雪花算法ID生成器(snowflake算法)
/**
* Twitter_Snowflake<br>
* SnowFlake的结构如下(每部分用-分开):<br>
* 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 <br>
* 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0<br>
* 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截)
* 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69<br>
* 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId<br>
* 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号<br>
* 加起来刚好64位,为一个Long型。<br>
* SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。
*/
public class SnowflakeIdWorker {
// ==============================Fields===========================================
/**
* 开始时间截 (2015-01-01)
*/
private final long twepoch = 1420041600000L;
/**
* 机器id所占的位数
*/
private final long workerIdBits = 5L;
/**
* 数据标识id所占的位数
*/
private final long datacenterIdBits = 5L;
/**
* 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数)
*/
private final long maxWorkerId = ~(-1L << workerIdBits);
/**
* 支持的最大数据标识id,结果是31
*/
private final long maxDatacenterId = ~(-1L << datacenterIdBits);
/**
* 序列在id中占的位数
*/
private final long sequenceBits = 12L;
/**
* 机器ID向左移12位
*/
private final long workerIdShift = sequenceBits;
/**
* 数据标识id向左移17位(12+5)
*/
private final long datacenterIdShift = sequenceBits + workerIdBits;
/**
* 时间截向左移22位(5+5+12)
*/
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
/**
* 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095)
*/
private final long sequenceMask = ~(-1L << sequenceBits);
/**
* 工作机器ID(0~31)
*/
private final long workerId;
/**
* 数据中心ID(0~31)
*/
private final long datacenterId;
/**
* 毫秒内序列(0~4095)
*/
private long sequence = 0L;
/**
* 上次生成ID的时间截
*/
private long lastTimestamp = -1L;
//==============================Constructors=====================================
/**
* 构造函数
*
* @param workerId 工作ID (0~31)
* @param datacenterId 数据中心ID (0~31)
*/
public SnowflakeIdWorker(long workerId, long datacenterId) {
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
}
if (datacenterId > maxDatacenterId || datacenterId < 0) {
throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
}
this.workerId = workerId;
this.datacenterId = datacenterId;
}
// ==============================Methods==========================================
/**
* 获得下一个ID (该方法是线程安全的)
*
* @return SnowflakeId
*/
public synchronized long nextId() {
long timestamp = timeGen();
//如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
if (timestamp < lastTimestamp) {
throw new RuntimeException(
String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
}
//如果是同一时间生成的,则进行毫秒内序列
if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & sequenceMask;
//毫秒内序列溢出
if (sequence == 0) {
//阻塞到下一个毫秒,获得新的时间戳
timestamp = tilNextMillis(lastTimestamp);
}
}
//时间戳改变,毫秒内序列重置
else {
sequence = 0L;
}
//上次生成ID的时间截
lastTimestamp = timestamp;
//移位并通过或运算拼到一起组成64位的ID
return ((timestamp - twepoch) << timestampLeftShift)
| (datacenterId << datacenterIdShift)
| (workerId << workerIdShift)
| sequence;
}
/**
* 阻塞到下一个毫秒,直到获得新的时间戳
*
* @param lastTimestamp 上次生成ID的时间截
* @return 当前时间戳
*/
protected long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}
/**
* 返回以毫秒为单位的当前时间
*
* @return 当前时间(毫秒)
*/
protected long timeGen() {
return System.currentTimeMillis();
}
//==============================Test=============================================
/**
* 测试
*/
public static void main(String[] args) {
long start = System.currentTimeMillis();
SnowflakeIdWorker idWorker = new SnowflakeIdWorker(1, 3);
for (int i = 0; i < 50; i++) {
long id = idWorker.nextId();
System.out.println(Long.toBinaryString(id));
System.out.println(id);
}
long end = System.currentTimeMillis();
System.out.println(end - start);
}
}
RestTemplate 工具类
/**
* RestTemplate 工具类
* @author: Demon
**/
public class RestTemplateUtil {
private static class SingletonRestTemplate {
static final RestTemplate INSTANCE = new RestTemplate();
}
private RestTemplateUtil() {
}
public static RestTemplate getInstance() {
return SingletonRestTemplate.INSTANCE;
}
/**
* post 请求
* @param url 请求路径
* @param data body数据
* @param token JWT所需的Token,不需要的可去掉
* @return
*/
public static String post(String url, String data, String token) {
HttpHeaders headers = new HttpHeaders();
headers.add("Accept", "application/json");
headers.add("Content-Encoding", "UTF-8");
headers.add("Content-Type", "application/json; charset=UTF-8");
if (token != null) {
headers.add("Authorization", token);
}
HttpEntity<String> requestEntity = new HttpEntity<>(data, headers);
return RestTemplateUtil.getInstance().postForObject(url, requestEntity, String.class);
}
/**
* get 请求
* @param url 请求路径
* @param token JWT所需的Token,不需要的可去掉
* @return
*/
public static String get(String url, String token) {
HttpHeaders headers = new HttpHeaders();
headers.add("Accept", "application/json");
headers.add("Content-Encoding", "UTF-8");
headers.add("Content-Type", "application/json; charset=UTF-8");
if (token != null) {
headers.add("Authorization", token);
}
HttpEntity<String> requestEntity = new HttpEntity<>(null, headers);
ResponseEntity<String> response = RestTemplateUtil.getInstance().exchange(url, HttpMethod.GET, requestEntity, String.class);
String responseBody = response.getBody();
return responseBody;
}
/**
* 发送文件请求
* @param url
* @param token
* @return
*/
public static String file(String url, MultipartFile file, String token) {
// 生成临时文件
String tempFilePath = System.getProperty("java.io.tmpdir") + file.getOriginalFilename();
File tmpFile = new File(tempFilePath);
// 结果,抛异常就是 null
String result = null;
try {
// 保存为文件
file.transferTo(tmpFile);
HttpHeaders headers = new HttpHeaders();
headers.add("Accept",MediaType.APPLICATION_JSON.toString());
headers.setContentType(MediaType.parseMediaType("multipart/form-data;charset=UTF-8"));
if (token != null) {
headers.add("Authorization", token);
}
MultiValueMap<String,Object> param = new LinkedMultiValueMap<>();
// 把临时文件变成 FileSystemResource
FileSystemResource resource = new FileSystemResource(tempFilePath);
param.add("file",resource);
HttpEntity<MultiValueMap<String,Object>> formEntity = new HttpEntity<>(param,headers);
result = RestTemplateUtil.getInstance().postForObject(url, formEntity, String.class);
//删除临时文件文件
tmpFile.delete();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
}
通配符URL处理工具
import java.util.regex.Pattern;
public class URLHelper {
/**
* 检验是否在非过滤地址
*
* @param excludedPaths
* @param reqUrl
* @return
*/
public static boolean checkWhiteList(String excludedPaths, String reqUrl) {
String[] excludeUrls = excludedPaths.split(",");
for (String url : excludeUrls) {
if (filterUrls(url, reqUrl)) {
return true;
}
}
return false;
}
/**
* 将通配符表达式转化为正则表达式
*
* @param path
* @return
*/
private static String getRegPath(String path) {
char[] chars = path.toCharArray();
int len = chars.length;
StringBuilder sb = new StringBuilder();
boolean preX = false;
for (int i = 0; i < len; i++) {
if (chars[i] == '*') {//遇到*字符
if (preX) {//如果是第二次遇到*,则将**替换成.*
sb.append(".*");
preX = false;
} else if (i + 1 == len) {//如果是遇到单星,且单星是最后一个字符,则直接将*转成[^/]*
sb.append("[^/]*");
} else {//否则单星后面还有字符,则不做任何动作,下一把再做动作
preX = true;
continue;
}
} else {//遇到非*字符
if (preX) {//如果上一把是*,则先把上一把的*对应的[^/]*添进来
sb.append("[^/]*");
preX = false;
}
if (chars[i] == '?') {//接着判断当前字符是不是?,是的话替换成.
sb.append('.');
} else {//不是?的话,则就是普通字符,直接添进来
sb.append(chars[i]);
}
}
}
return sb.toString();
}
/**
* 通配符模式
*
* @param excludePath - 不过滤地址
* @param reqUrl - 请求地址
* @return
*/
private static boolean filterUrls(String excludePath, String reqUrl) {
String regPath = getRegPath(excludePath);
return Pattern.compile(regPath).matcher(reqUrl).matches();
}
}
验证码工具
import java.util.Random;
/**
* @ClassName: ValidCodeUtils
* @Description:
* @Author: Demon
* @Datetime: 2021/6/8 17:26
*/
public class ValidCodeUtils {
private static final char[] NUMBERS = "0123456789".toCharArray();
private static final char[] WORDS = "23456789abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ".toCharArray();
private static final int MIN_LEN = 4;
private static final int MAX_LEN = 8;
/**
* @param len
* @return
* @description: 返回数字验证码
*/
public static String generateNumberCode(int len) {
return generateCode(NUMBERS, len);
}
/**
* @param len
* @return
* @description: 返回字符数字混合型验证码
*/
public static String generateWordCode(int len) {
return generateCode(WORDS, len);
}
/**
* 生成验证码
*
* @param array
* @param len
* @return
*/
private static String generateCode(char[] array, int len) {
len = len < MIN_LEN ? MIN_LEN : Math.min(len, MAX_LEN);
Random random = new Random();
char[] cs = new char[len];
for (int i = 0; i < cs.length; i++) {
cs[i] = array[random.nextInt(array.length)];
}
return new String(cs);
}
}
Redis工具类
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* @author Demon
* @className RedisClient
* @description TODO
* @date 2021/6/24 15:29
*/
@Component
public final class RedisClient {
private final Logger logger = LoggerFactory.getLogger(RedisClient.class);
@Resource
private RedisTemplate<String, Object> redisTemplate;
// =============================common============================
/**
* 指定缓存失效时间
*
* @param key 键
* @param time 时间(秒)
* @return
*/
public Boolean expire(String key, long time) {
try {
if (time > 0) {
return redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
} catch (Exception e) {
logger.error("", e);
}
return false;
}
/**
* 根据key 获取过期时间
*
* @param key 键 不能为null
* @return 时间(秒) 返回0代表为永久有效
*/
public Long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
/**
* 判断key是否存在
*
* @param key 键
* @return true 存在 false不存在
*/
public Boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
logger.error("", e);
return false;
}
}
/**
* 删除缓存
*
* @param key 可以传一个值 或多个
*/
@SuppressWarnings("unchecked")
public void del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete(CollectionUtils.arrayToList(key));
}
}
}
/**
* 普通缓存放入
*
* @param key 键
* @param value 值
*/
public <T> Boolean set(String key, T value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
logger.error("", e);
return false;
}
}
/**
* 普通缓存获取
*
* @param key 键
* @return 值
*/
public <T> T get(String key) {
Object value = redisTemplate.opsForValue().get(key);
return value == null ? null : (T) value;
}
/**
* 普通缓存放入并设置时间
*
* @param key 键
* @param value 值
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
public <T> Boolean set(String key, T value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
logger.error("", e);
return false;
}
}
/**
* 递增
*
* @param key 键
* @param delta 要增加几(大于0)
* @return
*/
public Long incr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递增因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, delta);
}
/**
* 递减
*
* @param key 键
* @param delta 要减少几(小于0)
* @return
*/
public Long decr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递减因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, -delta);
}
/**
* HashSet
*
* @param key 键
* @param map 对应多个键值
* @return true 成功 false 失败
*/
public <K, V> boolean hmSet(String key, Map<K, V> map) {
try {
redisTemplate.opsForHash().putAll(key, map);
return true;
} catch (Exception e) {
logger.error("", e);
return false;
}
}
/**
* HashSet 并设置时间
*
* @param key 键
* @param map 对应多个键值
* @param time 时间(秒)
* @return true成功 false失败
*/
public <K, V> boolean hmSet(String key, Map<K, V> map, long time) {
try {
redisTemplate.opsForHash().putAll(key, map);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
logger.error("", e);
return false;
}
}
/**
* 获取hashKey对应的所有键值
*
* @param key 键
* @return 对应的多个键值
*/
public <K, V> Map<K, V> hmGet(String key) {
return (Map<K, V>) redisTemplate.opsForHash().entries(key);
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @return true 成功 false失败
*/
public <K, V> boolean hSet(String key, K item, V value) {
try {
redisTemplate.opsForHash().put(key, item, value);
return true;
} catch (Exception e) {
logger.error("", e);
return false;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
* @return true 成功 false失败
*/
public <K, V> boolean hSet(String key, K item, V value, long time) {
try {
redisTemplate.opsForHash().put(key, item, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
logger.error("", e);
return false;
}
}
/**
* HashGet
*
* @param key 键 不能为null
* @param item 项 不能为null
* @return 值
*/
public <K, V> V hGet(String key, K item) {
Object value = redisTemplate.opsForHash().get(key, item);
return value == null ? null : (V) value;
}
/**
* 删除hash表中的值
*
* @param key 键 不能为null
* @param item 项 可以使多个 不能为null
*/
public Long hDel(String key, Object... item) {
return redisTemplate.opsForHash().delete(key, item);
}
/**
* 判断hash表中是否有该项的值
*
* @param key 键 不能为null
* @param item 项 不能为null
* @return true 存在 false不存在
*/
public <K> Boolean hHasKey(String key, K item) {
return redisTemplate.opsForHash().hasKey(key, item);
}
/**
* hash递增 如果不存在,就会创建一个 并把新增后的值返回
*
* @param key 键
* @param item 项
* @param by 要增加几(大于0)
* @return
*/
public <K> Double hIncr(String key, K item, double by) {
return redisTemplate.opsForHash().increment(key, item, by);
}
/**
* hash递减
*
* @param key 键
* @param item 项
* @param by 要减少记(小于0)
* @return
*/
public <K> Double hDecr(String key, K item, double by) {
return redisTemplate.opsForHash().increment(key, item, -by);
}
/**
* 将数据放入set缓存
*
* @param key 键
* @param values 值 可以是多个
* @return 成功个数
*/
public <V> Long sSet(String key, V... values) {
try {
return redisTemplate.opsForSet().add(key, values);
} catch (Exception e) {
logger.error("", e);
return 0L;
}
}
/**
* 将set数据放入缓存
*
* @param key 键
* @param time 时间(秒)
* @param values 值 可以是多个
* @return 成功个数
*/
public <V> Long sSet(String key, long time, V... values) {
try {
Long count = redisTemplate.opsForSet().add(key, values);
if (time > 0) {
expire(key, time);
}
return count;
} catch (Exception e) {
logger.error("", e);
return 0L;
}
}
/**
* 根据key获取Set中的所有值
*
* @param key 键
* @return
*/
public <T> Set<T> sGet(String key) {
try {
return (Set<T>) redisTemplate.opsForSet().members(key);
} catch (Exception e) {
logger.error("", e);
return null;
}
}
/**
* 根据value从一个set中查询,是否存在
*
* @param key 键
* @param value 值
* @return true 存在 false不存在
*/
public <V> Boolean sHasKey(String key, V value) {
try {
return redisTemplate.opsForSet().isMember(key, value);
} catch (Exception e) {
logger.error("", e);
return false;
}
}
/**
* 获取set缓存的长度
*
* @param key 键
* @return
*/
public Long sGetSize(String key) {
try {
return redisTemplate.opsForSet().size(key);
} catch (Exception e) {
logger.error("", e);
return 0L;
}
}
/**
* 移除值为value的
*
* @param key 键
* @param values 值 可以是多个
* @return 移除的个数
*/
public Long sRemove(String key, Object... values) {
try {
return redisTemplate.opsForSet().remove(key, values);
} catch (Exception e) {
logger.error("", e);
return 0L;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @return
*/
public <V> Long lSet(String key, V value) {
try {
return redisTemplate.opsForList().rightPush(key, value);
} catch (Exception e) {
logger.error("", e);
return 0L;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public <V> Long lSet(String key, V value, long time) {
try {
Long count = redisTemplate.opsForList().rightPush(key, value);
if (time > 0) {
expire(key, time);
}
return count;
} catch (Exception e) {
logger.error("", e);
return 0L;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @return
*/
public <V> Long lSet(String key, List<V> value) {
try {
return redisTemplate.opsForList().rightPushAll(key, value);
} catch (Exception e) {
logger.error("", e);
return 0L;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public <V> Long lSet(String key, List<V> value, long time) {
try {
Long count = redisTemplate.opsForList().rightPushAll(key, value);
if (time > 0) {
expire(key, time);
}
return count;
} catch (Exception e) {
logger.error("", e);
return 0L;
}
}
/**
* 获取list缓存的内容
*
* @param key 键
* @param start 开始
* @param end 结束 0 到 -1代表所有值
* @return
*/
public <V> List<V> lGet(String key, long start, long end) {
try {
return (List<V>) redisTemplate.opsForList().range(key, start, end);
} catch (Exception e) {
logger.error("", e);
return null;
}
}
/**
* 获取list缓存的长度
*
* @param key 键
* @return
*/
public Long lGetSize(String key) {
try {
return redisTemplate.opsForList().size(key);
} catch (Exception e) {
logger.error("", e);
return 0L;
}
}
/**
* 通过索引 获取list中的值
*
* @param key 键
* @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
* @return
*/
public <V> V lGetIndex(String key, long index) {
try {
return (V) redisTemplate.opsForList().index(key, index);
} catch (Exception e) {
logger.error("", e);
return null;
}
}
/**
* 根据索引修改list中的某条数据
*
* @param key 键
* @param index 索引
* @param value 值
* @return
*/
public <V> boolean lUpdateIndex(String key, long index, V value) {
try {
redisTemplate.opsForList().set(key, index, value);
return true;
} catch (Exception e) {
logger.error("", e);
return false;
}
}
/**
* 移除N个值为value
*
* @param key 键
* @param count 移除多少个
* @param value 值
* @return 移除的个数
*/
public <V> Long lRemove(String key, long count, V value) {
try {
return redisTemplate.opsForList().remove(key, count, value);
} catch (Exception e) {
logger.error("", e);
return 0L;
}
}
/**
* 订阅发布
*
* @param channel
* @param message
*/
public <T> void convertAndSend(String channel, T message) {
try {
redisTemplate.convertAndSend(channel, message);
} catch (Exception e) {
logger.error("", e);
}
}
/**
* 匹配获取Redis的keys
*
* @return
*/
public Set<String> getKeys(String pattern) {
return redisTemplate.keys(pattern);
}
}
网友评论