初始化代码
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
package additive;
|
||||
|
||||
public class ValidTool {
|
||||
|
||||
public static void assertIsTrue(boolean expression, String message) {
|
||||
if (!expression) {
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package entity;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* 验证码属性设值对象
|
||||
*/
|
||||
public class CaptchaItem {
|
||||
|
||||
/**
|
||||
* 验证码图片高度
|
||||
*/
|
||||
private double height;
|
||||
|
||||
/**
|
||||
* 验证码图片宽度
|
||||
*/
|
||||
private double width;
|
||||
|
||||
/**
|
||||
* 验证码长度
|
||||
*/
|
||||
private int codeLength;
|
||||
|
||||
/**
|
||||
* 验证码从这里面进行取值
|
||||
*/
|
||||
private String codeValue;
|
||||
|
||||
/**
|
||||
* 是否使用随机背景颜色
|
||||
*/
|
||||
private boolean backgroundRandom;
|
||||
|
||||
/**
|
||||
* 是否使用随机验证码颜色
|
||||
*/
|
||||
private boolean captchaColorRandom;
|
||||
|
||||
/**
|
||||
* 背景颜色
|
||||
*/
|
||||
private int backgroundColor;
|
||||
|
||||
/**
|
||||
* 验证码颜色
|
||||
*/
|
||||
private int captchaColor;
|
||||
|
||||
/**
|
||||
* 字体属性
|
||||
*/
|
||||
private Font font;
|
||||
|
||||
public CaptchaItem() {
|
||||
//直接进行默认值的处理
|
||||
this.captchaColorRandom = true;
|
||||
this.backgroundRandom = true;
|
||||
this.codeLength = 4;
|
||||
this.height = 100;
|
||||
this.width = 200;
|
||||
this.codeValue = "abcdefghijklmnopqrstuvwxyz1234567890";
|
||||
this.font = new Font("Algerian", Font.ITALIC, (int)this.height - 4);
|
||||
}
|
||||
|
||||
public Font getFont() {
|
||||
return font;
|
||||
}
|
||||
|
||||
public void setFont(Font font) {
|
||||
this.font = font;
|
||||
}
|
||||
|
||||
public double getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public void setHeight(double height) {
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public double getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public void setWidth(double width) {
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
public int getCodeLength() {
|
||||
return codeLength;
|
||||
}
|
||||
|
||||
public void setCodeLength(int codeLength) {
|
||||
this.codeLength = codeLength;
|
||||
}
|
||||
|
||||
public String getCodeValue() {
|
||||
return codeValue;
|
||||
}
|
||||
|
||||
public void setCodeValue(String codeValue) {
|
||||
this.codeValue = codeValue;
|
||||
}
|
||||
|
||||
public boolean isBackgroundRandom() {
|
||||
return backgroundRandom;
|
||||
}
|
||||
|
||||
public void setBackgroundRandom(boolean backgroundRandom) {
|
||||
this.backgroundRandom = backgroundRandom;
|
||||
}
|
||||
|
||||
public boolean isCaptchaColorRandom() {
|
||||
return captchaColorRandom;
|
||||
}
|
||||
|
||||
public void setCaptchaColorRandom(boolean captchaColorRandom) {
|
||||
this.captchaColorRandom = captchaColorRandom;
|
||||
}
|
||||
|
||||
public int getBackgroundColor() {
|
||||
return backgroundColor;
|
||||
}
|
||||
|
||||
public void setBackgroundColor(int backgroundColor) {
|
||||
this.backgroundColor = backgroundColor;
|
||||
}
|
||||
|
||||
public int getCaptchaColor() {
|
||||
return captchaColor;
|
||||
}
|
||||
|
||||
public void setCaptchaColor(int captchaColor) {
|
||||
this.captchaColor = captchaColor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* @(#) PagingQueryResp
|
||||
* 版权声明 网宿科技, 版权所有 违者必究
|
||||
*
|
||||
* <br> Copyright: Copyright (c) 2018
|
||||
* <br> Company:网宿科技
|
||||
* <br> @author Administrator
|
||||
* <br> @description 功能描述
|
||||
* <br> 2018-11-24 19:57:07
|
||||
*/
|
||||
|
||||
package entity;
|
||||
|
||||
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分页返回数据
|
||||
*
|
||||
* @author yexr
|
||||
*/
|
||||
public class CommonPageResp<T> {
|
||||
/**
|
||||
* 页数
|
||||
*/
|
||||
@Min(0)
|
||||
@NotNull
|
||||
private Integer pageIndex;
|
||||
/**
|
||||
* 页面大小
|
||||
*/
|
||||
@NotNull
|
||||
@Min(1)
|
||||
private Integer pageSize;
|
||||
|
||||
|
||||
public Integer getPageIndex() {
|
||||
return pageIndex;
|
||||
}
|
||||
|
||||
public void setPageIndex(Integer pageIndex) {
|
||||
this.pageIndex = pageIndex;
|
||||
}
|
||||
|
||||
public Integer getPageSize() {
|
||||
return pageSize;
|
||||
}
|
||||
|
||||
public void setPageSize(Integer pageSize) {
|
||||
this.pageSize = pageSize;
|
||||
}
|
||||
|
||||
private Integer total;
|
||||
|
||||
private List<T> resultList;
|
||||
|
||||
public Integer getTotal() {
|
||||
return total;
|
||||
}
|
||||
|
||||
public void setTotal(Integer total) {
|
||||
this.total = total;
|
||||
}
|
||||
|
||||
public List<T> getResultList() {
|
||||
return resultList;
|
||||
}
|
||||
|
||||
public void setResultList(List<T> resultList) {
|
||||
this.resultList = resultList;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
|
||||
package entity;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
public class FileItem {
|
||||
|
||||
private String fileName;
|
||||
|
||||
private InputStream inputStream;
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public void setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() {
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
public void setInputStream(InputStream inputStream) {
|
||||
this.inputStream = inputStream;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
|
||||
|
||||
package entity;
|
||||
|
||||
/**
|
||||
* 原始的时间点
|
||||
* @author huangzj
|
||||
*/
|
||||
public class OriginTimeValue {
|
||||
|
||||
/**
|
||||
* 时间
|
||||
*/
|
||||
private long time;
|
||||
|
||||
/**
|
||||
* 数值
|
||||
*/
|
||||
private long value;
|
||||
|
||||
public OriginTimeValue(long time, long value) {
|
||||
this.time = time;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(long time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public long getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(long value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
package entity;
|
||||
|
||||
import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class QRCodeItem {
|
||||
|
||||
|
||||
/**
|
||||
* 二维码上面的文字内容
|
||||
*/
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 文字颜色
|
||||
*/
|
||||
private Color contentColor;
|
||||
|
||||
/**
|
||||
* 文字字体
|
||||
*/
|
||||
private Font contentFont;
|
||||
|
||||
/**
|
||||
* 宽度
|
||||
*/
|
||||
private int width;
|
||||
|
||||
/**
|
||||
* 高度
|
||||
*/
|
||||
private int height;
|
||||
|
||||
/**
|
||||
* 图片后缀
|
||||
*/
|
||||
private String suffix;
|
||||
|
||||
/**
|
||||
* logo的文件地址
|
||||
*/
|
||||
private String logoPath;
|
||||
|
||||
/**
|
||||
* 二维码参数,这边会有默认的配置.具体配置可以参考:
|
||||
* @see EncodeHintType
|
||||
*/
|
||||
private Map<EncodeHintType,Object> hints = new HashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* 二维码背景颜色
|
||||
*/
|
||||
private Color backgroundColor;
|
||||
|
||||
/**
|
||||
* 二维码条纹颜色
|
||||
*/
|
||||
private Color stripeColor;
|
||||
|
||||
|
||||
/**
|
||||
* 是否自定义文字位置,如果false,直接按照程序里面的设定处理
|
||||
*/
|
||||
private boolean isDiyContentPosition;
|
||||
|
||||
/**
|
||||
* 文字的x轴位置
|
||||
*/
|
||||
private int contentX;
|
||||
|
||||
|
||||
/**
|
||||
* 文字的Y轴位置
|
||||
*/
|
||||
private int contentY;
|
||||
|
||||
|
||||
/**
|
||||
* 是否自定义logo位置,如果false,直接按照程序里面的设定处理
|
||||
*/
|
||||
private boolean isDiyLogoPosition;
|
||||
|
||||
/**
|
||||
* logo的X轴位置
|
||||
*/
|
||||
private int logoX;
|
||||
|
||||
/**
|
||||
* logo的Y轴位置
|
||||
*/
|
||||
private int logoY;
|
||||
|
||||
public QRCodeItem() {
|
||||
this.width= this.height = 300;
|
||||
this.content = " ";
|
||||
this.contentColor =Color.BLACK;
|
||||
this.suffix = "png";
|
||||
//设置字符集
|
||||
this.hints.put(EncodeHintType.CHARACTER_SET,"UTF-8");
|
||||
//设置纠错等级,分为四级
|
||||
this.hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.Q);
|
||||
//设置边框空白边距
|
||||
this.hints.put(EncodeHintType.MARGIN,0);
|
||||
this.contentFont= new Font("宋体",Font.BOLD, 12);
|
||||
this.logoPath = "F:\\Java个人代码\\Java_Utils\\src\\main\\test\\util\\image\\QRCode\\log.png";
|
||||
this.backgroundColor = Color.WHITE;
|
||||
this.stripeColor = Color.BLACK;
|
||||
this.isDiyContentPosition = false;
|
||||
this.isDiyLogoPosition = false;
|
||||
}
|
||||
|
||||
public String getLogoPath() {
|
||||
return logoPath;
|
||||
}
|
||||
|
||||
public void setLogoPath(String logoPath) {
|
||||
this.logoPath = logoPath;
|
||||
}
|
||||
|
||||
public String getSuffix() {
|
||||
return suffix;
|
||||
}
|
||||
|
||||
public void setSuffix(String suffix) {
|
||||
this.suffix = suffix;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public void setWidth(int width) {
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public void setHeight(int height) {
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public Font getContentFont() {
|
||||
return contentFont;
|
||||
}
|
||||
|
||||
public void setContentFont(Font contentFont) {
|
||||
this.contentFont = contentFont;
|
||||
}
|
||||
|
||||
public Color getContentColor() {
|
||||
return contentColor;
|
||||
}
|
||||
|
||||
public void setContentColor(Color contentColor) {
|
||||
this.contentColor = contentColor;
|
||||
}
|
||||
|
||||
public Map<EncodeHintType,Object> getHints() {
|
||||
return hints;
|
||||
}
|
||||
|
||||
public void setHints(Map<EncodeHintType,Object> hints) {
|
||||
this.hints = hints;
|
||||
}
|
||||
|
||||
public Color getBackgroundColor() {
|
||||
return backgroundColor;
|
||||
}
|
||||
|
||||
public void setBackgroundColor(Color backgroundColor) {
|
||||
this.backgroundColor = backgroundColor;
|
||||
}
|
||||
|
||||
public Color getStripeColor() {
|
||||
return stripeColor;
|
||||
}
|
||||
|
||||
public void setStripeColor(Color stripeColor) {
|
||||
this.stripeColor = stripeColor;
|
||||
}
|
||||
|
||||
public boolean isDiyContentPosition() {
|
||||
return isDiyContentPosition;
|
||||
}
|
||||
|
||||
public void setDiyContentPosition(boolean diyContentPosition) {
|
||||
isDiyContentPosition = diyContentPosition;
|
||||
}
|
||||
|
||||
public int getContentX() {
|
||||
return contentX;
|
||||
}
|
||||
|
||||
public void setContentX(int contentX) {
|
||||
this.contentX = contentX;
|
||||
}
|
||||
|
||||
public int getContentY() {
|
||||
return contentY;
|
||||
}
|
||||
|
||||
public void setContentY(int contentY) {
|
||||
this.contentY = contentY;
|
||||
}
|
||||
|
||||
public boolean isDiyLogoPosition() {
|
||||
return isDiyLogoPosition;
|
||||
}
|
||||
|
||||
public void setDiyLogoPosition(boolean diyLogoPosition) {
|
||||
isDiyLogoPosition = diyLogoPosition;
|
||||
}
|
||||
|
||||
public int getLogoX() {
|
||||
return logoX;
|
||||
}
|
||||
|
||||
public void setLogoX(int logoX) {
|
||||
this.logoX = logoX;
|
||||
}
|
||||
|
||||
public int getLogoY() {
|
||||
return logoY;
|
||||
}
|
||||
|
||||
public void setLogoY(int logoY) {
|
||||
this.logoY = logoY;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
|
||||
|
||||
package entity;
|
||||
|
||||
/**
|
||||
* 补时间点后的对象
|
||||
*/
|
||||
public class TargetTimeValue {
|
||||
private long time;
|
||||
/**
|
||||
* 统计值,其中null值表示没有数据
|
||||
*/
|
||||
private Long value;
|
||||
|
||||
public void setTime(long time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public void setValue(Long value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public Long getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* @(#) BeanCloneException
|
||||
* 版权声明 网宿科技, 版权所有 违者必究
|
||||
*
|
||||
* <br> Copyright: Copyright (c) 2018
|
||||
* <br> Company:网宿科技
|
||||
* <br> @author Administrator
|
||||
* <br> @description 功能描述
|
||||
* <br> 2018-10-07 17:13:13
|
||||
*/
|
||||
|
||||
package exception;
|
||||
|
||||
public class BeanCloneException extends RuntimeException {
|
||||
public BeanCloneException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public BeanCloneException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public BeanCloneException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public BeanCloneException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
protected BeanCloneException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* @(#) BeanPropertiesCopyException
|
||||
* 版权声明 网宿科技, 版权所有 违者必究
|
||||
*
|
||||
* <br> Copyright: Copyright (c) 2018
|
||||
* <br> Company:网宿科技
|
||||
* <br> @author Administrator
|
||||
* <br> @description 功能描述
|
||||
* <br> 2018-10-07 17:13:13
|
||||
*/
|
||||
|
||||
package exception;
|
||||
|
||||
public class BeanPropertiesCopyException extends RuntimeException {
|
||||
|
||||
public BeanPropertiesCopyException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public BeanPropertiesCopyException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public BeanPropertiesCopyException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public BeanPropertiesCopyException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
protected BeanPropertiesCopyException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* @(#) SerializableDeepCloneException
|
||||
* 版权声明 网宿科技, 版权所有 违者必究
|
||||
*
|
||||
* <br> Copyright: Copyright (c) 2018
|
||||
* <br> Company:网宿科技
|
||||
* <br> @author Administrator
|
||||
* <br> @description 功能描述
|
||||
* <br> 2018-10-07 17:13:13
|
||||
*/
|
||||
|
||||
package exception;
|
||||
|
||||
public class SerializableDeepCloneException extends RuntimeException {
|
||||
|
||||
public SerializableDeepCloneException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public SerializableDeepCloneException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public SerializableDeepCloneException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public SerializableDeepCloneException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
protected SerializableDeepCloneException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* @(#) CloneType
|
||||
* 版权声明 网宿科技, 版权所有 违者必究
|
||||
*
|
||||
* <br> Copyright: Copyright (c) 2018
|
||||
* <br> Company:网宿科技
|
||||
* <br> @author Administrator
|
||||
* <br> @description 功能描述
|
||||
* <br> 2018-10-07 17:13:13
|
||||
*/
|
||||
|
||||
package type;
|
||||
|
||||
/**
|
||||
* @author selfImpr
|
||||
*/
|
||||
public enum CloneType {
|
||||
|
||||
/**
|
||||
* 基本类型和final的不需要复制的类型
|
||||
*/
|
||||
SIMPLE_TYPE,
|
||||
|
||||
/**
|
||||
* 数组
|
||||
*/
|
||||
ARRAY,
|
||||
|
||||
/**
|
||||
* 需要深度克隆的类
|
||||
*/
|
||||
DEEP_CLONE_CLASS
|
||||
}
|
||||
@@ -0,0 +1,293 @@
|
||||
package util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Writer;
|
||||
|
||||
/**
|
||||
* 该工具是很久之前在网上找的,现在已经忘记了对应的代码地址
|
||||
*/
|
||||
public class Base64Util {
|
||||
private static final char[] S_BASE64CHAR = new char[]{'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', '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', '+', '/'};
|
||||
private static final char S_BASE64PAD = '=';
|
||||
private static final byte[] S_DECODETABLE = new byte[128];
|
||||
private static final char EQUAL_SIGN = '=';
|
||||
|
||||
public Base64Util() {
|
||||
}
|
||||
|
||||
private static int decode0(char[] ibuf, byte[] obuf, int wp) {
|
||||
int outlen = 3;
|
||||
if (ibuf[3] == EQUAL_SIGN) {
|
||||
outlen = 2;
|
||||
}
|
||||
|
||||
if (ibuf[2] ==EQUAL_SIGN ) {
|
||||
outlen = 1;
|
||||
}
|
||||
|
||||
int b0 = S_DECODETABLE[ibuf[0]];
|
||||
int b1 = S_DECODETABLE[ibuf[1]];
|
||||
int b2 = S_DECODETABLE[ibuf[2]];
|
||||
int b3 = S_DECODETABLE[ibuf[3]];
|
||||
switch (outlen) {
|
||||
case 1:
|
||||
obuf[wp] = (byte) (b0 << 2 & 252 | b1 >> 4 & 3);
|
||||
return 1;
|
||||
case 2:
|
||||
obuf[wp++] = (byte) (b0 << 2 & 252 | b1 >> 4 & 3);
|
||||
obuf[wp] = (byte) (b1 << 4 & 240 | b2 >> 2 & 15);
|
||||
return 2;
|
||||
case 3:
|
||||
obuf[wp++] = (byte) (b0 << 2 & 252 | b1 >> 4 & 3);
|
||||
obuf[wp++] = (byte) (b1 << 4 & 240 | b2 >> 2 & 15);
|
||||
obuf[wp] = (byte) (b2 << 6 & 192 | b3 & 63);
|
||||
return 3;
|
||||
default:
|
||||
throw new RuntimeException("Internal Errror");
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] decode(char[] data, int off, int len) {
|
||||
char[] ibuf = new char[4];
|
||||
int ibufcount = 0;
|
||||
byte[] obuf = new byte[len / 4 * 3 + 3];
|
||||
int obufcount = 0;
|
||||
|
||||
for (int i = off; i < off + len; ++i) {
|
||||
char ch = data[i];
|
||||
if (ch == '=' || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != 127) {
|
||||
ibuf[ibufcount++] = ch;
|
||||
if (ibufcount == ibuf.length) {
|
||||
ibufcount = 0;
|
||||
obufcount += decode0(ibuf, obuf, obufcount);
|
||||
}
|
||||
}
|
||||
}
|
||||
return decodeResult(obufcount,obuf);
|
||||
}
|
||||
|
||||
private static byte[] decodeResult(int obufcount, byte[] obuf) {
|
||||
if (obufcount == obuf.length) {
|
||||
return obuf;
|
||||
} else {
|
||||
byte[] ret = new byte[obufcount];
|
||||
System.arraycopy(obuf, 0, ret, 0, obufcount);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] decode(String data) {
|
||||
char[] ibuf = new char[4];
|
||||
int ibufcount = 0;
|
||||
byte[] obuf = new byte[data.length() / 4 * 3 + 3];
|
||||
int obufcount = 0;
|
||||
|
||||
for (int i = 0; i < data.length(); ++i) {
|
||||
char ch = data.charAt(i);
|
||||
if (ch == '=' || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != 127) {
|
||||
ibuf[ibufcount++] = ch;
|
||||
if (ibufcount == ibuf.length) {
|
||||
ibufcount = 0;
|
||||
obufcount += decode0(ibuf, obuf, obufcount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return decodeResult(obufcount,obuf);
|
||||
}
|
||||
|
||||
public static void decode(char[] data, int off, int len, OutputStream ostream) throws IOException {
|
||||
char[] ibuf = new char[4];
|
||||
int ibufcount = 0;
|
||||
byte[] obuf = new byte[3];
|
||||
|
||||
for (int i = off; i < off + len; ++i) {
|
||||
char ch = data[i];
|
||||
decodeProcess(ch,ibuf,ibufcount,ostream,obuf);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void decodeProcess(char ch, char[] ibuf, int ibufcount, OutputStream ostream, byte[] obuf) throws IOException {
|
||||
if (ch == '=' || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != 127) {
|
||||
ibuf[ibufcount++] = ch;
|
||||
if (ibufcount == ibuf.length) {
|
||||
ibufcount = 0;
|
||||
int obufcount = decode0(ibuf, obuf, 0);
|
||||
ostream.write(obuf, 0, obufcount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void decode(String data, OutputStream ostream) throws IOException {
|
||||
char[] ibuf = new char[4];
|
||||
int ibufcount = 0;
|
||||
byte[] obuf = new byte[3];
|
||||
|
||||
for (int i = 0; i < data.length(); ++i) {
|
||||
char ch = data.charAt(i);
|
||||
decodeProcess(ch,ibuf,ibufcount,ostream,obuf);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static String encode(byte[] data) {
|
||||
return encode(data, 0, data.length);
|
||||
}
|
||||
|
||||
public static String encode(byte[] data, int off, int len) {
|
||||
if (len <= 0) {
|
||||
return "";
|
||||
} else {
|
||||
char[] out = new char[len / 3 * 4 + 4];
|
||||
int rindex = off;
|
||||
int windex = 0;
|
||||
|
||||
int rest;
|
||||
int i;
|
||||
for (rest = len; rest >= 3; rest -= 3) {
|
||||
i = ((data[rindex] & 255) << 16) + ((data[rindex + 1] & 255) << 8) + (data[rindex + 2] & 255);
|
||||
out[windex++] = S_BASE64CHAR[i >> 18];
|
||||
out[windex++] = S_BASE64CHAR[i >> 12 & 63];
|
||||
out[windex++] = S_BASE64CHAR[i >> 6 & 63];
|
||||
out[windex++] = S_BASE64CHAR[i & 63];
|
||||
rindex += 3;
|
||||
}
|
||||
|
||||
if (rest == 1) {
|
||||
i = data[rindex] & 255;
|
||||
out[windex++] = S_BASE64CHAR[i >> 2];
|
||||
out[windex++] = S_BASE64CHAR[i << 4 & 63];
|
||||
out[windex++] = '=';
|
||||
out[windex++] = '=';
|
||||
} else if (rest == 2) {
|
||||
i = ((data[rindex] & 255) << 8) + (data[rindex + 1] & 255);
|
||||
out[windex++] = S_BASE64CHAR[i >> 10];
|
||||
out[windex++] = S_BASE64CHAR[i >> 4 & 63];
|
||||
out[windex++] = S_BASE64CHAR[i << 2 & 63];
|
||||
out[windex++] = '=';
|
||||
}
|
||||
|
||||
return new String(out, 0, windex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void encode(byte[] data, int off, int len, OutputStream ostream) throws IOException {
|
||||
if (len > 0) {
|
||||
byte[] out = new byte[4];
|
||||
int rindex = off;
|
||||
|
||||
int rest;
|
||||
int i;
|
||||
for (rest = len; rest >= 3; rest -= 3) {
|
||||
i = ((data[rindex] & 255) << 16) + ((data[rindex + 1] & 255) << 8) + (data[rindex + 2] & 255);
|
||||
out[0] = (byte) S_BASE64CHAR[i >> 18];
|
||||
out[1] = (byte) S_BASE64CHAR[i >> 12 & 63];
|
||||
out[2] = (byte) S_BASE64CHAR[i >> 6 & 63];
|
||||
out[3] = (byte) S_BASE64CHAR[i & 63];
|
||||
ostream.write(out, 0, 4);
|
||||
rindex += 3;
|
||||
}
|
||||
|
||||
if (rest == 1) {
|
||||
i = data[rindex] & 255;
|
||||
out[0] = (byte) S_BASE64CHAR[i >> 2];
|
||||
out[1] = (byte) S_BASE64CHAR[i << 4 & 63];
|
||||
out[2] = 61;
|
||||
out[3] = 61;
|
||||
ostream.write(out, 0, 4);
|
||||
} else if (rest == 2) {
|
||||
i = ((data[rindex] & 255) << 8) + (data[rindex + 1] & 255);
|
||||
out[0] = (byte) S_BASE64CHAR[i >> 10];
|
||||
out[1] = (byte) S_BASE64CHAR[i >> 4 & 63];
|
||||
out[2] = (byte) S_BASE64CHAR[i << 2 & 63];
|
||||
out[3] = 61;
|
||||
ostream.write(out, 0, 4);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static void encode(byte[] data, int off, int len, Writer writer) throws IOException {
|
||||
if (len > 0) {
|
||||
char[] out = new char[4];
|
||||
int rindex = off;
|
||||
int rest = len;
|
||||
int output = 0;
|
||||
|
||||
int i;
|
||||
while (rest >= 3) {
|
||||
i = ((data[rindex] & 255) << 16) + ((data[rindex + 1] & 255) << 8) + (data[rindex + 2] & 255);
|
||||
out[0] = S_BASE64CHAR[i >> 18];
|
||||
out[1] = S_BASE64CHAR[i >> 12 & 63];
|
||||
out[2] = S_BASE64CHAR[i >> 6 & 63];
|
||||
out[3] = S_BASE64CHAR[i & 63];
|
||||
writer.write(out, 0, 4);
|
||||
rindex += 3;
|
||||
rest -= 3;
|
||||
output += 4;
|
||||
if (output % 76 == 0) {
|
||||
writer.write("\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (rest == 1) {
|
||||
i = data[rindex] & 255;
|
||||
out[0] = S_BASE64CHAR[i >> 2];
|
||||
out[1] = S_BASE64CHAR[i << 4 & 63];
|
||||
out[2] = '=';
|
||||
out[3] = '=';
|
||||
writer.write(out, 0, 4);
|
||||
} else if (rest == 2) {
|
||||
i = ((data[rindex] & 255) << 8) + (data[rindex + 1] & 255);
|
||||
out[0] = S_BASE64CHAR[i >> 10];
|
||||
out[1] = S_BASE64CHAR[i >> 4 & 63];
|
||||
out[2] = S_BASE64CHAR[i << 2 & 63];
|
||||
out[3] = '=';
|
||||
writer.write(out, 0, 4);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
int i;
|
||||
for (i = 0; i < S_DECODETABLE.length; ++i) {
|
||||
S_DECODETABLE[i] = 127;
|
||||
}
|
||||
|
||||
for (i = 0; i < S_BASE64CHAR.length; ++i) {
|
||||
S_DECODETABLE[S_BASE64CHAR[i]] = (byte) i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static byte[] decodeByte(String data) {
|
||||
|
||||
char[] ibuf = new char[4];
|
||||
int ibufcount = 0;
|
||||
byte[] obuf = new byte[data.length() / 4 * 3 + 3];
|
||||
int obufcount = 0;
|
||||
for (int i = 0; i < data.length(); i++) {
|
||||
char ch = data.charAt(i);
|
||||
if (ch == S_BASE64PAD || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) {
|
||||
ibuf[ibufcount++] = ch;
|
||||
if (ibufcount == ibuf.length) {
|
||||
ibufcount = 0;
|
||||
obufcount += decode0(ibuf, obuf, obufcount);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (obufcount == obuf.length) {
|
||||
return obuf;
|
||||
}
|
||||
byte[] ret = new byte[obufcount];
|
||||
System.arraycopy(obuf, 0, ret, 0, obufcount);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
|
||||
|
||||
package util;
|
||||
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import entity.FileItem;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author 志军
|
||||
*/
|
||||
public class FileUtil {
|
||||
|
||||
private static final byte[] BUF = new byte[1024];
|
||||
|
||||
private static final int BUF_SIZE = 1024;
|
||||
|
||||
public static void deleteFile(String filePath) {
|
||||
File file = new File(filePath);
|
||||
if (!file.exists()) {
|
||||
throw new RuntimeException("文件不存在");
|
||||
}
|
||||
|
||||
file.delete();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 支持输入流存储到对应文件夹下,仅对文件夹有效
|
||||
* @param fileItems 输入流、文件名 数组
|
||||
* @param dirPath 文件夹路径
|
||||
*/
|
||||
public static void storeFiles(List<FileItem> fileItems, String dirPath) {
|
||||
File file = new File(dirPath);
|
||||
if (!file.exists() && !file.isDirectory()) {
|
||||
file.mkdir();
|
||||
}
|
||||
|
||||
fileItems.forEach(fileItem -> {
|
||||
File fileItemFile = new File(dirPath + File.separator + fileItem.getFileName());
|
||||
FileOutputStream fileOutputStream;
|
||||
|
||||
try {
|
||||
//创建文件
|
||||
fileItemFile.createNewFile();
|
||||
fileOutputStream = new FileOutputStream(fileItemFile);
|
||||
int len;
|
||||
while ((len = fileItem.getInputStream().read(BUF, 0, BUF_SIZE)) != -1) {
|
||||
fileOutputStream.write(BUF, 0, len);
|
||||
}
|
||||
|
||||
fileOutputStream.close();
|
||||
fileItem.getInputStream().close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("生成文件错误");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean fileExist(String filePath){
|
||||
File file = new File(filePath);
|
||||
return file.exists();
|
||||
}
|
||||
|
||||
public static boolean isFile(String filePath){
|
||||
File file = new File(filePath);
|
||||
if ( file.exists()){
|
||||
return file.isFile();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isDir(String filePath){
|
||||
File file = new File(filePath);
|
||||
if ( file.exists()){
|
||||
return file.isDirectory();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件已存在或者创建成功返回true
|
||||
* 文件不存在或者非文件(文件夹)或者创建失败,返回false
|
||||
*/
|
||||
public static boolean createFile(String filePath){
|
||||
if(fileExist(filePath)){
|
||||
return isFile(filePath);
|
||||
}
|
||||
File file = new File(filePath);
|
||||
try {
|
||||
return file.createNewFile();
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建并获取一个File对象
|
||||
* 如果是文件、创建成功返回对应的文件对象
|
||||
* 其他情况直接返回null.
|
||||
*/
|
||||
public static File createGetFile(String filePath){
|
||||
if(fileExist(filePath)){
|
||||
if ( isFile(filePath)){
|
||||
return new File(filePath);
|
||||
}
|
||||
}
|
||||
File file = new File(filePath);
|
||||
try {
|
||||
boolean result = file.createNewFile();
|
||||
if (result){
|
||||
return file;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件转换成byte数组
|
||||
*/
|
||||
public static byte[] fileToByte(String filePath) {
|
||||
FileInputStream in = null;
|
||||
try {
|
||||
in = new FileInputStream(new File(filePath));
|
||||
byte[] bytes = new byte[in.available()];
|
||||
in.read(bytes);
|
||||
return bytes;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("转换失败",e);
|
||||
} finally {
|
||||
if (in != null) {
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* byte数组写入文件
|
||||
*/
|
||||
public static void bytesToFile(String filePath,byte[] content){
|
||||
FileOutputStream out = null;
|
||||
try {
|
||||
out = new FileOutputStream(new File(filePath));
|
||||
out.write(content);
|
||||
out.flush();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("写入失败",e);
|
||||
} finally {
|
||||
if (out != null) {
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 拿到文件夹下面的所有文件夹(包括它自己)
|
||||
*/
|
||||
public static List<File> findAllDirFromDir(String dirPath){
|
||||
File dir = new File(dirPath);
|
||||
if(!dir.exists() || !dir.isDirectory()){
|
||||
throw new RuntimeException("非文件夹或者文件夹位置错误");
|
||||
}
|
||||
List<File> result = findDir(dir);
|
||||
result.add(dir);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<File> findDir(File file ){
|
||||
List<File> list = Lists.newArrayList();
|
||||
for(File child : Objects.requireNonNull(file.listFiles())){
|
||||
if(child.isDirectory()){
|
||||
list.add(child);
|
||||
List<File> tempList = findDir(child);
|
||||
if(!CollectionUtils.isEmpty(tempList)){
|
||||
list.addAll(tempList);
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 拿到文件夹下面的所有空文件夹
|
||||
*/
|
||||
public static List<File> findAllEmptyDirFromDir( String dirPath){
|
||||
List<File> list = Lists.newArrayList();
|
||||
File dir = new File(dirPath);
|
||||
if(!dir.exists() || !dir.isDirectory()){
|
||||
throw new RuntimeException("非文件夹或者文件夹位置错误");
|
||||
}
|
||||
List<File> allList = findAllDirFromDir(dirPath);
|
||||
for(File dirFile:allList){
|
||||
if(isEmptyFile(dirFile)){
|
||||
list.add(dirFile);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过目录获取目录下所有的文件
|
||||
*/
|
||||
public static List<File> findAllFile(File dir){
|
||||
List<File> list = Lists.newArrayList();
|
||||
for (File file : Objects.requireNonNull(dir.listFiles())){
|
||||
if(file.isFile()){
|
||||
list.add(file);
|
||||
}else{
|
||||
List<File> tempList = findAllFile(file);
|
||||
if(!CollectionUtils.isEmpty(tempList)){
|
||||
list.addAll(tempList);
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private static boolean isEmptyFile(File dir) {
|
||||
List<File> child = findAllFile(dir);
|
||||
return CollectionUtils.isEmpty(child);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 拿到文件夹下面的所有非空文件夹
|
||||
*/
|
||||
public static List<File> findAllNotEmptyDirFromDir( String dirPath){
|
||||
List<File> list = Lists.newArrayList();
|
||||
File dir = new File(dirPath);
|
||||
if(!dir.exists() || !dir.isDirectory()){
|
||||
throw new RuntimeException("非文件夹或者文件夹位置错误");
|
||||
}
|
||||
List<File> allList = findAllDirFromDir(dirPath);
|
||||
for(File dirFile:allList){
|
||||
if(!isEmptyFile(dir)){
|
||||
list.add(dirFile);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package util;
|
||||
|
||||
import org.slf4j.helpers.MessageFormatter;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
/**
|
||||
* Created by huangzj on 2017/8/21.
|
||||
* @author 志军
|
||||
*/
|
||||
public class MessageUtils {
|
||||
/**
|
||||
* 格式化信息,支持message={0}或message={}格式的信息模板。
|
||||
*
|
||||
* @param pattern 信息模板
|
||||
* @param parameters 参数值
|
||||
* @return 格式化后的信息
|
||||
*/
|
||||
public static String format(String pattern, Object... parameters) {
|
||||
try {
|
||||
return MessageFormat.format(pattern, parameters);
|
||||
} catch (IllegalArgumentException e) {
|
||||
//上面的MessageFormat报错进来这边的,这边的测试只测试出当格式不正确的情况才会进来
|
||||
return MessageFormatter.arrayFormat(pattern, parameters).getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* @(#) PageUtil
|
||||
* 版权声明 网宿科技, 版权所有 违者必究
|
||||
*
|
||||
* <br> Copyright: Copyright (c) 2018
|
||||
* <br> Company:网宿科技
|
||||
* <br> @author Administrator
|
||||
* <br> @description 功能描述
|
||||
* <br> 2018-11-24 19:55:37
|
||||
*/
|
||||
|
||||
package util;
|
||||
|
||||
|
||||
import entity.CommonPageResp;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static additive.ValidTool.assertIsTrue;
|
||||
import static java.lang.Math.min;
|
||||
|
||||
|
||||
/**
|
||||
* 分页工具类
|
||||
*
|
||||
* @author 志军
|
||||
* @date
|
||||
*/
|
||||
public class PageUtil {
|
||||
|
||||
private static final int ZERO = 0;
|
||||
|
||||
/**
|
||||
* 前端传,从0开始分页(对list进行分页)
|
||||
* @param list 列表
|
||||
* @param pageIndex 页码
|
||||
* @param pageSize 页数
|
||||
* @param <T> T
|
||||
* @return 分页通用对象
|
||||
*/
|
||||
public static <T> CommonPageResp<T> pagingListFromZero(List<T> list, int pageIndex, int pageSize) {
|
||||
assertIsTrue(pageIndex >= 0, "pageIndex必需大于等于0");
|
||||
|
||||
if (list == null ) {
|
||||
return nullPage(pageSize);
|
||||
}
|
||||
CommonPageResp<T> pagingQueryResp = new CommonPageResp<>();
|
||||
int index = min(((list.size() - 1) / pageSize), pageIndex);
|
||||
pagingQueryResp.setPageIndex(index);
|
||||
pagingQueryResp.setPageSize(pageSize);
|
||||
pagingQueryResp.setTotal(list.size());
|
||||
pagingQueryResp.setResultList(list.subList(index * pageSize, min((index + 1) * pageSize, list.size())));
|
||||
return pagingQueryResp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 前端传,从1开始分页(对list进行分页)
|
||||
* @param list 列表
|
||||
* @param pageIndex 页码
|
||||
* @param pageSize 页数
|
||||
* @param <T> T
|
||||
* @return 分页通用对象
|
||||
*/
|
||||
static <T> CommonPageResp<T> pagingListFromOne(List<T> list, int pageIndex, int pageSize) {
|
||||
if ( pageIndex<1){
|
||||
pageIndex = 1;
|
||||
}
|
||||
CommonPageResp<T> pagingQueryResp = new CommonPageResp<>();
|
||||
|
||||
if (list == null) {
|
||||
return nullPage(pageSize);
|
||||
}
|
||||
int index = min(((list.size() - 1 )/ pageSize + 1), pageIndex);
|
||||
pagingQueryResp.setPageIndex(index);
|
||||
pagingQueryResp.setPageSize(pageSize);
|
||||
pagingQueryResp.setTotal(list.size());
|
||||
pagingQueryResp.setResultList(list.subList((index - 1) * pageSize, min(index * pageSize, list.size())));
|
||||
return pagingQueryResp;
|
||||
}
|
||||
|
||||
private static <T> CommonPageResp<T> nullPage(int pageSize) {
|
||||
CommonPageResp<T> pagingQueryResp = new CommonPageResp<>();
|
||||
pagingQueryResp.setResultList(Collections.emptyList());
|
||||
pagingQueryResp.setTotal(ZERO);
|
||||
pagingQueryResp.setPageIndex(ZERO);
|
||||
pagingQueryResp.setPageSize(pageSize);
|
||||
return pagingQueryResp;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package util;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 这个就是一个储备的工作工具,不具备学习的用处,反正我是学不来
|
||||
* 参考网上的地址:http://tools.jb51.net/regex/create_reg
|
||||
* https://www.jb51.net/article/115170.htm
|
||||
*
|
||||
* @author 志军
|
||||
*/
|
||||
public class PatternUtils {
|
||||
|
||||
/**
|
||||
* 全是中文
|
||||
*/
|
||||
private static final String ALL_CHINESS_PATTERN = "[\\u4e00-\\u9fa5]+";
|
||||
|
||||
/**
|
||||
* 是不是E-mail地址
|
||||
*/
|
||||
private static final String EMAIL_ADDRESS_PATTERN = "\\w[-\\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\\.)+[A-Za-z]{2,14}";
|
||||
|
||||
/**
|
||||
* 是不是网址
|
||||
*
|
||||
*/
|
||||
private static final String INTERNET_URL_PATTERN = "^((https|http|ftp|rtsp|mms)?:\\/\\/)[^\\s]+";
|
||||
|
||||
/**
|
||||
* 2018目前国内的手机
|
||||
*/
|
||||
private static final String MOBILE_PHONE_PATTERN = "/^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\\d{8}$/";
|
||||
|
||||
/**
|
||||
* 2018目前国内的电话
|
||||
*/
|
||||
private static final String TEL_PHONE_PATTERN = "[0-9-()()]{7,18}";
|
||||
|
||||
/**
|
||||
* qq号码
|
||||
*/
|
||||
private static final String QQ_PATTERN = "[1-9]([0-9]{5,11})";
|
||||
|
||||
/**
|
||||
* 邮政编码
|
||||
*/
|
||||
private static final String POSTAL_CODE_PATTERN = "\\d{6}";
|
||||
|
||||
/**
|
||||
* 身份证,验证15位和18位
|
||||
* https://www.jb51.net/article/109384.htm
|
||||
*/
|
||||
private static final String ID_CARD_PATTERN = " ^[1-9]\\d{5}(18|19|([23]\\d))\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)"
|
||||
+ "\\d{3}[0-9Xx]$)|(^[1-9]\\d{5}\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{2}$";
|
||||
|
||||
/**
|
||||
* IPv4地址正则
|
||||
*/
|
||||
private static final String IPV4_PATTERN = "/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}"
|
||||
+ "(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/";
|
||||
|
||||
/**
|
||||
* 微信号,6至20位,以字母开头,字母,数字,减号,下划线
|
||||
*/
|
||||
private static final String WEIXIN_PATTERN = "/^[a-zA-Z]([-_a-zA-Z0-9]{5,19})+$/";
|
||||
|
||||
/**
|
||||
* 车牌号
|
||||
*/
|
||||
private static final String LICENSE_PLATE_PATTERN = " /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-Z0-9]{4}[A-Z0-9挂学警港澳]{1}$/";
|
||||
|
||||
/**
|
||||
* 日期正则,复杂判定
|
||||
*/
|
||||
private static final String DATE_PATTERN = "/^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-"
|
||||
+ "(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$/";
|
||||
|
||||
/**
|
||||
* 用户名正则,,4到16位(字母,数字,下划线,减号)
|
||||
*/
|
||||
private static final String USER_NAME_PATTERN = "/^[a-zA-Z0-9_-]{4,16}$/";
|
||||
|
||||
/**
|
||||
* 密码正则 最少6位,包括至少1个大写字母,1个小写字母,1个数字,1个特殊字符
|
||||
*/
|
||||
private static final String PASSWORD_PATTERN = "/^.*(?=.{6,})(?=.*\\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*? ]).*$/";
|
||||
|
||||
/**
|
||||
* 文件路径及拓展名校验
|
||||
*/
|
||||
private static final String FILE_PATH_PATTERN = "([a-zA-Z]\\\\:|\\\\\\\\)\\\\\\\\([^\\\\\\\\]+\\\\\\\\)*[^\\\\/:*?\"<>|]+\\\\.txt(l)?$";
|
||||
|
||||
/**
|
||||
* 这边就不一一写出来了,以后要用的时候再说
|
||||
*
|
||||
*/
|
||||
private static boolean commonPattern(String pattern, String str) {
|
||||
Pattern r = Pattern.compile(pattern);
|
||||
Matcher m = r.matcher(str);
|
||||
return m.matches();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
|
||||
|
||||
package util;
|
||||
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
/**
|
||||
* 调用shell命令
|
||||
* @author 志军
|
||||
*/
|
||||
public class ShellUtils {
|
||||
|
||||
|
||||
/**
|
||||
* 压缩文件
|
||||
* @param originPath 源文件位置
|
||||
* @param tarPath 新文件位置
|
||||
*/
|
||||
public void compressFile(String originPath, String tarPath) {
|
||||
InputStream in = null;
|
||||
try {
|
||||
Process cd = Runtime.getRuntime().exec(new String[]{"cd", " ", originPath});
|
||||
cd.waitFor();
|
||||
Process pro = Runtime.getRuntime().exec(new String[]{"tar", " -czf", tarPath, "*.tar.gz"});
|
||||
pro.waitFor();
|
||||
in = pro.getInputStream();
|
||||
BufferedReader read = new BufferedReader(new InputStreamReader(in));
|
||||
String result = read.readLine();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteFile(String tempPathOnTime) {
|
||||
InputStream in = null;
|
||||
try {
|
||||
Process pro = Runtime.getRuntime().exec(new String[]{"rm", "-rf", " ", tempPathOnTime});
|
||||
pro.waitFor();
|
||||
in = pro.getInputStream();
|
||||
BufferedReader read = new BufferedReader(new InputStreamReader(in));
|
||||
String result = read.readLine();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* @(#) StringUtils
|
||||
* 版权声明 网宿科技, 版权所有 违者必究
|
||||
*
|
||||
* <br> Copyright: Copyright (c) 2018
|
||||
* <br> Company:网宿科技
|
||||
* <br> @author Administrator
|
||||
* <br> @description 功能描述
|
||||
* <br> 2018-10-07 17:13:13
|
||||
*/
|
||||
|
||||
package util;
|
||||
|
||||
import net.sourceforge.pinyin4j.PinyinHelper;
|
||||
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
|
||||
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
|
||||
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
|
||||
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
|
||||
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author 志军
|
||||
* 补充Strings的缺失
|
||||
*/
|
||||
class StringUtils {
|
||||
|
||||
private static char A_LETTER = 'a';
|
||||
private static char Z_LETTER = 'z';
|
||||
private static Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
|
||||
|
||||
/**
|
||||
* 首字母小写
|
||||
*/
|
||||
static String lowerFirstLetter(String word) {
|
||||
char[] chars = word.toCharArray();
|
||||
if (chars[0] >= A_LETTER && chars[0] <= Z_LETTER) {
|
||||
chars[0] += 32;
|
||||
}
|
||||
|
||||
return String.valueOf(chars);
|
||||
}
|
||||
|
||||
/**
|
||||
* 首字母大写
|
||||
*/
|
||||
static String upperFirstLetter(String word) {
|
||||
char[] chars = word.toCharArray();
|
||||
if (chars[0] >= A_LETTER && chars[0] <= Z_LETTER) {
|
||||
chars[0] -= 32;
|
||||
}
|
||||
|
||||
return String.valueOf(chars);
|
||||
}
|
||||
|
||||
static String upperAllLetter(String word){
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
char[] chars = word.toCharArray();
|
||||
for( int i= 0;i<chars.length;i++){
|
||||
if (chars[0] >= A_LETTER && chars[0] <= Z_LETTER) {
|
||||
chars[0] -= 32;
|
||||
}
|
||||
stringBuilder.append(chars[i]);
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
static String lowerAllLetter(String word) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
char[] chars = word.toCharArray();
|
||||
for( int i= 0;i<chars.length;i++){
|
||||
if (chars[0] >= A_LETTER && chars[0] <= Z_LETTER) {
|
||||
chars[0] += 32;
|
||||
}
|
||||
stringBuilder.append(chars[i]);
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
|
||||
static String appendAll(String... word){
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (String aWord : word) {
|
||||
stringBuilder.append(aWord);
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 判断字符串中是否包含中文
|
||||
*/
|
||||
static boolean isContainChinese(String str) {
|
||||
Matcher m = p.matcher(str);
|
||||
return m.find();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 校验一个字符是否是汉字
|
||||
*/
|
||||
static boolean isChineseChar(char c) {
|
||||
try {
|
||||
return String.valueOf(c).getBytes(StandardCharsets.UTF_8).length > 1;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static String toPinyinUpper(String word) throws BadHanyuPinyinOutputFormatCombination {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
|
||||
format.setCaseType(HanyuPinyinCaseType.UPPERCASE);
|
||||
format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
|
||||
char[] chars = word.toCharArray();
|
||||
buildChars(chars,stringBuilder,format);
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
static String toPinyinLower(String word) throws BadHanyuPinyinOutputFormatCombination {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
|
||||
format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
|
||||
format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
|
||||
char[] chars = word.toCharArray();
|
||||
buildChars(chars,stringBuilder,format);
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
|
||||
private static void buildChars(char[] chars,StringBuilder stringBuilder,HanyuPinyinOutputFormat format) throws BadHanyuPinyinOutputFormatCombination {
|
||||
for (char aChar : chars) {
|
||||
if (isChineseChar(aChar)) {
|
||||
String[] result = PinyinHelper.toHanyuPinyinStringArray(aChar, format);
|
||||
for(String s : result){
|
||||
stringBuilder.append(s);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
//处理非中文的部分
|
||||
stringBuilder.append(aChar);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static String toPinyinPhoneticSignUpper(String word ) throws BadHanyuPinyinOutputFormatCombination {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
|
||||
format.setToneType(HanyuPinyinToneType.WITH_TONE_MARK);
|
||||
format.setCaseType(HanyuPinyinCaseType.UPPERCASE);
|
||||
format.setVCharType(HanyuPinyinVCharType.WITH_U_UNICODE);
|
||||
char[] chars = word.toCharArray();
|
||||
buildChars(chars,stringBuilder,format);
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
static String toPinyinPhoneticSignLower(String word ) throws BadHanyuPinyinOutputFormatCombination {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
|
||||
format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
|
||||
format.setToneType(HanyuPinyinToneType.WITH_TONE_MARK);
|
||||
format.setVCharType(HanyuPinyinVCharType.WITH_U_UNICODE);
|
||||
char[] chars = word.toCharArray();
|
||||
buildChars(chars,stringBuilder,format);
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过正则表达式进行替换
|
||||
*/
|
||||
static String replacePattern(String word,String pattern){
|
||||
if (word != null) {
|
||||
Pattern p = Pattern.compile(pattern);
|
||||
Matcher m = p.matcher(word);
|
||||
word = m.replaceAll("");
|
||||
}
|
||||
return word;
|
||||
}
|
||||
|
||||
static String replacePattern(String word,String replace,String pattern){
|
||||
if (word != null) {
|
||||
Pattern p = Pattern.compile(pattern);
|
||||
Matcher m = p.matcher(word);
|
||||
word = m.replaceAll(replace);
|
||||
}
|
||||
return word;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,356 @@
|
||||
package util.clazz;
|
||||
|
||||
|
||||
import exception.BeanCloneException;
|
||||
import jdk.internal.org.objectweb.asm.ClassReader;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
import jdk.internal.org.objectweb.asm.Type;
|
||||
import type.CloneType;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
* 类操作的工具类
|
||||
*
|
||||
* @author selfImpr
|
||||
*/
|
||||
public class ClassUtils {
|
||||
|
||||
/**
|
||||
* final基本类型对象
|
||||
*/
|
||||
private static List<Class> basicWrapType;
|
||||
|
||||
|
||||
static {
|
||||
basicWrapType = Arrays.asList(new Class[]{Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, Boolean
|
||||
.class, Character.class, String.class});
|
||||
}
|
||||
|
||||
public static CloneType getCloneType(Object object) {
|
||||
//判断是不是基本类型
|
||||
if (object.getClass().isPrimitive()) {
|
||||
return CloneType.SIMPLE_TYPE;
|
||||
}
|
||||
|
||||
if (basicWrapType.contains(object.getClass())) {
|
||||
return CloneType.SIMPLE_TYPE;
|
||||
}
|
||||
|
||||
if (object.getClass().isArray()) {
|
||||
return CloneType.ARRAY;
|
||||
}
|
||||
|
||||
return CloneType.DEEP_CLONE_CLASS;
|
||||
}
|
||||
|
||||
public static List<Field> getAllField(Object object) {
|
||||
List<Field> fields = new ArrayList<>();
|
||||
if (object == null) {
|
||||
return fields;
|
||||
}
|
||||
|
||||
//TODO 这边的这个类型会不会有问题
|
||||
return Arrays.asList(object.getClass().getDeclaredFields());
|
||||
}
|
||||
|
||||
public static List<String> getAllFieldName(Object object) {
|
||||
List<String> attributes = new ArrayList<>();
|
||||
Field[] fields = object.getClass().getDeclaredFields();
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
attributes.add(fields[i].getName());
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取类层面上的泛型类型
|
||||
* 但是这边应该是有一个限制条件:因为java是泛型擦出,所以是拿不到具体的类型的....
|
||||
* 这边做一个变通就是说去拿里面数据的类型,如果没有数据的话,就统一返回Object
|
||||
* <p>
|
||||
* <p>
|
||||
* 并且还不能判断自定义的泛型类型。
|
||||
*
|
||||
* @param object
|
||||
*/
|
||||
public static List<Class> getGenericParamType(Object object) {
|
||||
List<Class> genericParamType = new ArrayList<>();
|
||||
|
||||
|
||||
java.lang.reflect.Type type = object.getClass().getGenericSuperclass();
|
||||
if (type instanceof ParameterizedType) {
|
||||
if (Collection.class.isAssignableFrom(object.getClass())) {
|
||||
if (((Collection) object).size() == 0) {
|
||||
genericParamType.add(Object.class);
|
||||
return genericParamType;
|
||||
}
|
||||
|
||||
genericParamType.add(((Collection) object).iterator().next().getClass());
|
||||
}
|
||||
|
||||
if (Map.class.isAssignableFrom(object.getClass())) {
|
||||
if (((Map) object).size() == 0) {
|
||||
genericParamType.add(Object.class);
|
||||
genericParamType.add(Object.class);
|
||||
return genericParamType;
|
||||
}
|
||||
|
||||
//设置key和value的值
|
||||
genericParamType.add(((Map) object).keySet().iterator().next().getClass());
|
||||
genericParamType.add(((Map) object).values().iterator().next().getClass());
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
//TODO 怎么判断自定义的类型是不是存在泛型?
|
||||
}
|
||||
|
||||
return genericParamType;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过Field去获取泛型的类型
|
||||
*/
|
||||
public static List<Class> getGenericParamTypeInField(Field field) {
|
||||
List<Class> genericParamType = new ArrayList<>();
|
||||
if (field.getGenericType() instanceof ParameterizedType) {
|
||||
java.lang.reflect.Type[] types = ((ParameterizedType) field.getGenericType()).getActualTypeArguments();
|
||||
for (java.lang.reflect.Type type : types) {
|
||||
genericParamType.add(type.getClass());
|
||||
}
|
||||
|
||||
return genericParamType;
|
||||
}
|
||||
|
||||
//TODO 这边还是没有解决自定义拥有泛型类型参数的问题啊...
|
||||
|
||||
genericParamType.add(field.getType());
|
||||
|
||||
return genericParamType;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 如果有一个的某个参数为空是处理不了泛型的....
|
||||
*
|
||||
*/
|
||||
public static boolean isParamterTypeSame(Object originBean, Object newObject) {
|
||||
//第一个条件就是:两个类型都相同
|
||||
if (ClassUtils.getCloneType(originBean) == ClassUtils.getCloneType(newObject)) {
|
||||
switch (ClassUtils.getCloneType(originBean)) {
|
||||
case SIMPLE_TYPE:
|
||||
return isSimpleTypeSame(originBean, newObject);
|
||||
case ARRAY:
|
||||
return isArrayTypeSame(originBean, newObject);
|
||||
case DEEP_CLONE_CLASS:
|
||||
return isClassTypeSame(originBean, newObject);
|
||||
default:
|
||||
throw new BeanCloneException("判断参数类型的时候出错了");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isSimpleTypeSame(Object originBean, Object newObject) {
|
||||
if (originBean.getClass() == Class.class || newObject.getClass() == Class.class) {
|
||||
return originBean == newObject;
|
||||
}
|
||||
return originBean.getClass() == newObject.getClass();
|
||||
}
|
||||
|
||||
private static boolean isArrayTypeSame(Object originBean, Object newObject) {
|
||||
if (originBean.getClass() == Class.class || newObject.getClass() == Class.class) {
|
||||
return originBean == newObject;
|
||||
}
|
||||
return originBean.getClass() == newObject.getClass();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 不处理泛型的问题了,这个太复杂了
|
||||
* 这个方法有严重bug...
|
||||
*
|
||||
*/
|
||||
private static boolean isClassTypeSame(Object originBean, Object newObject) {
|
||||
//这边是为了判断如果传进来的是集合的泛型或者是参数中的域的类型
|
||||
if (ClassUtils.getCloneType(originBean) == ClassUtils.getCloneType(newObject)) {
|
||||
|
||||
if (originBean.getClass() == Class.class || newObject.getClass() == Class.class) {
|
||||
return originBean == newObject;
|
||||
}
|
||||
|
||||
if (ClassUtils.getCloneType(originBean) == CloneType.SIMPLE_TYPE) {
|
||||
return isSimpleTypeSame(originBean, newObject);
|
||||
}
|
||||
|
||||
if (ClassUtils.getCloneType(originBean) == CloneType.ARRAY) {
|
||||
return isArrayTypeSame(originBean, newObject);
|
||||
}
|
||||
|
||||
if (Collection.class.isAssignableFrom(originBean.getClass())) {
|
||||
return isClassTypeSame(ClassUtils.getGenericParamType(originBean).get(0), ClassUtils.getGenericParamType(newObject).get(0));
|
||||
}
|
||||
|
||||
if (Map.class.isAssignableFrom(originBean.getClass())) {
|
||||
return isClassTypeSame(ClassUtils.getGenericParamType(originBean).get(0), ClassUtils.getGenericParamType(newObject).get
|
||||
(0)) && isClassTypeSame(ClassUtils.getGenericParamType(originBean).get(1), ClassUtils.getGenericParamType(newObject)
|
||||
.get(1));
|
||||
}
|
||||
|
||||
return originBean.getClass() == newObject.getClass();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Set<Class> getClassesByInterface(String[] filePath, Class interfaceClass) {
|
||||
Set<Class> interfaceImpClasses = new HashSet<>();
|
||||
Set<Class> classes = new HashSet<>();
|
||||
|
||||
for (String path : filePath) {
|
||||
//把前面那个"/"去掉
|
||||
Set<Class> set = getAllClass(new File(interfaceClass.getResource("/" + path.replaceAll("\\.", "/")).getPath()),
|
||||
path);
|
||||
interfaceImpClasses.addAll(set);
|
||||
}
|
||||
|
||||
for (Class clazz : interfaceImpClasses) {
|
||||
if (!interfaceClass.isAssignableFrom(clazz)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!clazz.isInterface() && !clazz.isAnnotation() && !Modifier.isAbstract(clazz.getModifiers())) {
|
||||
classes.add(clazz);
|
||||
}
|
||||
}
|
||||
return classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param file 查找路径的File对象 -- 不区分是不是抽象类或者是借口
|
||||
* @param packageName 查找的路径(根)
|
||||
*/
|
||||
public static Set<Class> getAllClass(File file, String packageName) {
|
||||
Set<Class> classSet = new HashSet<>();
|
||||
for (File f : Objects.requireNonNull(file.listFiles())) {
|
||||
|
||||
if (f.isDirectory()) {
|
||||
String packageName1 = packageName + "." + f.getName();
|
||||
classSet.addAll(getAllClass(f, packageName1));
|
||||
} else if (f.getPath().endsWith(".class")) {
|
||||
try {
|
||||
classSet.add(Class.forName(packageName + "." + f.getName().replaceAll(".class", "")));
|
||||
} catch (ClassNotFoundException e) {
|
||||
//TODO 内部类也会单独生成一个.class文件,也被加入这里面。怎么办?
|
||||
throw new RuntimeException("初始化出错了");
|
||||
}
|
||||
}
|
||||
}
|
||||
return classSet;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 我在做方法的反射的时候会遇到就是说去反射java自定义的那些方法的时候,出错。
|
||||
* 那这个方法就是说返回所有父类的java的类的方法,我不去反射他们
|
||||
*/
|
||||
public static List<Method> getSuperClassMethod(Class clazz) {
|
||||
List<Method> methods = new ArrayList<>();
|
||||
if (clazz.getSuperclass() == null) {
|
||||
//java自带的类加载器是null
|
||||
if (clazz.getClassLoader() == null) {
|
||||
methods.addAll(Arrays.asList(clazz.getMethods()));
|
||||
return methods;
|
||||
} else {
|
||||
return methods;
|
||||
}
|
||||
} else {
|
||||
return getSuperClassMethod(clazz.getSuperclass());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过这个方法,拿到方法的参数的名称(用户自己定义的)
|
||||
* 参考地址:https://blog.csdn.net/mhmyqn/article/details/47294485
|
||||
*/
|
||||
public static String[] getParameterNames(Class<?> clazz, Method method) {
|
||||
final Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
System.out.println("method name : " + method.getName());
|
||||
if (parameterTypes.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//应该还要排除一种情况就是说java自带的方法。我们不处理这类的方法
|
||||
List<Method> methods = getSuperClassMethod(clazz);
|
||||
if (methods.contains(method)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
//这边有一个需要注意的就是说如果是static的方法,这边的param的数组数量是正常的,非static方法数量要加一
|
||||
String[] parameterNames;
|
||||
parameterNames = new String[parameterTypes.length];
|
||||
// if (Modifier.isStatic(method.getModifiers())) {
|
||||
// } else {
|
||||
// parameterNames = new String[parameterTypes.length + 1];
|
||||
// }
|
||||
|
||||
final Type[] types = new Type[parameterTypes.length];
|
||||
for (int i = 0; i < parameterTypes.length; i++) {
|
||||
types[i] = Type.getType(parameterTypes[i]);
|
||||
}
|
||||
|
||||
//拿到类名 比如 org.framework.abc 拿到 abc.class
|
||||
String className = clazz.getName().substring(clazz.getName().lastIndexOf(".") + 1) + ".class";
|
||||
InputStream is = clazz.getResourceAsStream(className);
|
||||
|
||||
try {
|
||||
ClassReader classReader = new ClassReader(is);
|
||||
//我们重写了这下面的方法
|
||||
classReader.accept(new ClassVisitorUtils(Opcodes.ASM4, method, types, parameterNames), 0);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("读取类的信息出错了");
|
||||
}
|
||||
|
||||
return parameterNames;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T newInstance(String className,Class<T> superClass){
|
||||
Class<?> classType = null;
|
||||
try {
|
||||
classType = Class.forName(className);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException("生成Class出错",e);
|
||||
}
|
||||
|
||||
if(!superClass.isAssignableFrom(classType)){
|
||||
throw new RuntimeException("类必须继承" + superClass.getName());
|
||||
}
|
||||
|
||||
Class<T> classes = (Class<T>) classType;
|
||||
|
||||
try {
|
||||
return classes.newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
throw new RuntimeException("类实例化出错"+e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException("类实例化出错了" + e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* @(#) ClassVisitorUtils
|
||||
* 版权声明 网宿科技, 版权所有 违者必究
|
||||
*
|
||||
* <br> Copyright: Copyright (c) 2018
|
||||
* <br> Company:网宿科技
|
||||
* <br> @author Administrator
|
||||
* <br> @description 功能描述
|
||||
* <br> 2018-10-07 22:38:38
|
||||
*/
|
||||
|
||||
package util.clazz;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.ClassVisitor;
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
import jdk.internal.org.objectweb.asm.Type;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class ClassVisitorUtils extends ClassVisitor {
|
||||
|
||||
/**需要获取到参数名称的方法*/
|
||||
private Method method;
|
||||
|
||||
/***/
|
||||
private Type[] types;
|
||||
|
||||
/**存放参数名称的数组*/
|
||||
private String[] parameterNames;
|
||||
|
||||
public ClassVisitorUtils(int i) {
|
||||
super(i);
|
||||
}
|
||||
|
||||
public ClassVisitorUtils(int i, ClassVisitor classVisitor) {
|
||||
super(i, classVisitor);
|
||||
}
|
||||
|
||||
public ClassVisitorUtils(int i, Method method, Type[] types, String[] parameterNames) {
|
||||
super(i);
|
||||
this.method = method;
|
||||
this.types = types;
|
||||
this.parameterNames = parameterNames;
|
||||
}
|
||||
|
||||
/**我们重写这个方法在我们的ClassUtils里面去使用*/
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
|
||||
Type[] argumentTypes = Type.getArgumentTypes(desc);
|
||||
if (!method.getName().equals(name) || !Arrays.equals(argumentTypes, types)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**这个地方注意每次调用结束的重置*/
|
||||
MethodVisitorUtils methodVisitorUtils = new MethodVisitorUtils(Opcodes.ASM4, argumentTypes, method, parameterNames);
|
||||
methodVisitorUtils.resetParamLocation();
|
||||
return methodVisitorUtils;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* @(#) MethodVisitorUtils
|
||||
* 版权声明 网宿科技, 版权所有 违者必究
|
||||
*
|
||||
* <br> Copyright: Copyright (c) 2018
|
||||
* <br> Company:网宿科技
|
||||
* <br> @author Administrator
|
||||
* <br> @description 功能描述
|
||||
* <br> 2018-10-07 22:55:01
|
||||
*/
|
||||
|
||||
package util.clazz;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.Label;
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
import jdk.internal.org.objectweb.asm.Type;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class MethodVisitorUtils extends MethodVisitor {
|
||||
|
||||
/**方法的参数的位置,因为asm返回的参数有一些没看懂,所以这边使用这个方式来标记位置*/
|
||||
private int paramLocation = 0;
|
||||
|
||||
private Type[] argumentTypes;
|
||||
|
||||
/**需要获取到参数名称的方法*/
|
||||
private Method method;
|
||||
|
||||
/**存放参数名称的数组*/
|
||||
private String[] parameterNames;
|
||||
|
||||
public MethodVisitorUtils(int i) {
|
||||
super(i);
|
||||
}
|
||||
|
||||
public MethodVisitorUtils(int i, MethodVisitor methodVisitor) {
|
||||
super(i, methodVisitor);
|
||||
}
|
||||
|
||||
public MethodVisitorUtils(int i, Type[] argumentTypes, Method method, String[] parameterNames) {
|
||||
super(i);
|
||||
this.parameterNames = parameterNames;
|
||||
this.method = method;
|
||||
this.argumentTypes = argumentTypes;
|
||||
}
|
||||
|
||||
/**这个方法好像不需要...其实他每次都是new一下这个玩意。*/
|
||||
public void resetParamLocation() {
|
||||
this.paramLocation = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
|
||||
|
||||
//这里还要注意的就是他比较完 ,全部以后还会去比较
|
||||
if (paramLocation > argumentTypes.length - 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
//他这里会返回一些奇怪的参数,具体我也不知道为什么,所以这边以我们拿到匹配的参数开始计算
|
||||
if (argumentTypes[paramLocation].toString().equals(desc)) {
|
||||
// 静态方法第一个参数就是方法的参数,如果是实例方法,第一个参数是this
|
||||
// if (Modifier.isStatic(method.getModifiers())) {
|
||||
parameterNames[paramLocation] = name;
|
||||
System.out.println(name);
|
||||
// } else if (index > 0) {
|
||||
// parameterNames[paramLocation + 1] = name;
|
||||
// System.out.println(name);
|
||||
// }
|
||||
paramLocation++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
|
||||
package util.http;
|
||||
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.File;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Spring 返回前端对象,主要用于文件下载
|
||||
* @author huangzj
|
||||
*/
|
||||
public class ResponseEntityUtil {
|
||||
|
||||
public static ResponseEntity getResponseEntity(File file, String fileName) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=\"" + fileName + "\";");
|
||||
headers.add(HttpHeaders.EXPIRES, "0");
|
||||
headers.add(HttpHeaders.LAST_MODIFIED, new Date().toString());
|
||||
headers.add(HttpHeaders.ETAG, String.valueOf(System.currentTimeMillis()));
|
||||
|
||||
return ResponseEntity.ok().headers(headers).contentLength(file.length()).contentType(MediaType.APPLICATION_OCTET_STREAM).body(new
|
||||
FileSystemResource(file));
|
||||
}
|
||||
|
||||
|
||||
public static String processFileName(HttpServletRequest request, String fileName) throws UnsupportedEncodingException {
|
||||
//火狐和其他浏览器好像有区别
|
||||
if (request.getHeader(HttpHeaders.USER_AGENT).toUpperCase().indexOf("MSIE") > 0) {
|
||||
fileName = URLEncoder.encode(fileName, "UTF-8");
|
||||
} else {
|
||||
fileName = new String(fileName.getBytes(StandardCharsets.UTF_8), "ISO8859-1");
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
|
||||
// headers.add("Pragma", "no-cache");
|
||||
// headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
package util.image;
|
||||
|
||||
import entity.CaptchaItem;
|
||||
import util.FileUtil;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* 验证码生成工具
|
||||
* 参考地址:http://blog.csdn.net/ruixue0117/article/details/22829557
|
||||
* 参考地址:http://www.iteye.com/topic/573456
|
||||
*/
|
||||
public class CaptchaUtil {
|
||||
/**
|
||||
* 验证码处理对象,这边直接采用默认的配置,可以通过set方式进行设置
|
||||
*/
|
||||
private CaptchaItem captchaItem = new CaptchaItem();
|
||||
|
||||
|
||||
/**
|
||||
* 可支持生成随机验证码
|
||||
*/
|
||||
public String generalCode() {
|
||||
StringBuilder generalCode = new StringBuilder();
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < captchaItem.getCodeLength(); i++) {
|
||||
int position = random.nextInt(captchaItem.getCodeValue().length()-1);
|
||||
generalCode.append(captchaItem.getCodeValue().charAt(position));
|
||||
}
|
||||
return generalCode.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成验证码图片.这边可支持自定义的code传入
|
||||
* @param imagePath 图片地址
|
||||
* @param captchaCode 验证码数值
|
||||
*/
|
||||
public void generateCaptchaImage(String imagePath, String captchaCode){
|
||||
File imageFile = FileUtil.createGetFile(imagePath);
|
||||
if(imageFile == null){
|
||||
throw new RuntimeException("文件不存在或者生成失败");
|
||||
}
|
||||
BufferedImage image = generateBufferedImage(captchaCode);
|
||||
try {
|
||||
ImageIO.write(image, "jpg", new FileOutputStream(imageFile));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("文件生成失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成验证码图片.code按照设定的方式进行处理
|
||||
* @param imagePath 图片地址
|
||||
*/
|
||||
public void generateCaptchaImage(String imagePath){
|
||||
File imageFile = FileUtil.createGetFile(imagePath);
|
||||
if(imageFile == null){
|
||||
throw new RuntimeException("文件不存在或者生成失败");
|
||||
}
|
||||
BufferedImage image = generateBufferedImage(generalCode());
|
||||
try {
|
||||
ImageIO.write(image, "jpg", new FileOutputStream(imageFile));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("文件生成失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置BufferedImage对象,实现图片流的处理
|
||||
*/
|
||||
private BufferedImage generateBufferedImage(String captchaCode){
|
||||
BufferedImage bi = new BufferedImage((int)captchaItem.getWidth(), (int)captchaItem.getHeight() , BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D g2 = bi.createGraphics();
|
||||
//判断是否生成随机颜色还是通过设置的颜色进行处理
|
||||
Color backColor =captchaItem.isBackgroundRandom()? getColor(new Random().nextInt(100), new Random().nextInt(200)+100): getColor(captchaItem.getCaptchaColor(),captchaItem.getCaptchaColor());
|
||||
//设置背景色
|
||||
setColorTone(g2,backColor);
|
||||
//设置干扰线
|
||||
setVictimLine(g2);
|
||||
// 添加噪点
|
||||
setHotPixel(bi);
|
||||
// 使图片扭曲
|
||||
shear(g2, (int)captchaItem.getWidth(), (int)captchaItem.getHeight(), backColor);
|
||||
//设置写入文字的属性以及验证码
|
||||
setCaptchaCode(g2,captchaCode);
|
||||
g2.dispose();
|
||||
return bi;
|
||||
}
|
||||
|
||||
private void setCaptchaCode(Graphics2D g2, String captchaCode) {
|
||||
Color fontColor =captchaItem.isCaptchaColorRandom()? getColor(new Random().nextInt(100), new Random().nextInt(200)+100): getColor(captchaItem.getCaptchaColor(),captchaItem.getCaptchaColor());
|
||||
g2.setColor(fontColor);
|
||||
double fontSize = captchaItem.getHeight() - 4;
|
||||
g2.setFont(captchaItem.getFont());
|
||||
char[] chars = captchaCode.toCharArray();
|
||||
|
||||
for (int i = 0; i < captchaCode.length(); i++) {
|
||||
AffineTransform transform = new AffineTransform();
|
||||
transform.setToRotation(Math.PI / 4 * new Random().nextDouble() * (new Random().nextBoolean() ? 1 : -1),
|
||||
(captchaItem.getWidth() / captchaCode.length()) * i + fontSize / 2, captchaItem.getHeight() / 2);
|
||||
g2.setTransform(transform);
|
||||
g2.drawChars(chars, i, 1, (int)((captchaItem.getWidth() - 10) / captchaCode.length()) * i + 5, (int)(captchaItem.getHeight() / 2 + fontSize / 2 - 10));
|
||||
}
|
||||
}
|
||||
|
||||
private void setHotPixel(BufferedImage bi) {
|
||||
Random random = new Random();
|
||||
// 噪声率
|
||||
float yawpRate = 0.05f;
|
||||
int area = (int) (yawpRate * captchaItem.getWidth() * captchaItem.getHeight());
|
||||
for (int i = 0; i < area; i++) {
|
||||
int x = random.nextInt((int)captchaItem.getWidth());
|
||||
int y = random.nextInt((int)captchaItem.getHeight());
|
||||
int rgb = getRandomIntColor();
|
||||
bi.setRGB(x, y, rgb);
|
||||
}
|
||||
}
|
||||
|
||||
private void setVictimLine(Graphics2D g2) {
|
||||
//绘制干扰线 设置线条的颜色
|
||||
Random random = new Random();
|
||||
g2.setColor(getColor(160, 200));
|
||||
for (int i = 0; i < 20; i++) {
|
||||
int x = random.nextInt((int)captchaItem.getWidth() - 1);
|
||||
int y = random.nextInt((int)captchaItem.getHeight() - 1);
|
||||
int xl = random.nextInt(6) + 1;
|
||||
int yl = random.nextInt(12) + 1;
|
||||
g2.drawLine(x, y, x + xl + 40, y + yl + 20);
|
||||
}
|
||||
}
|
||||
|
||||
private void setColorTone(Graphics2D g2,Color backColor) {
|
||||
//设置色调
|
||||
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
// 设置边框色
|
||||
g2.setColor(Color.GRAY);
|
||||
g2.fillRect(0, 0,(int)captchaItem.getWidth(), (int)captchaItem.getHeight() );
|
||||
// 设置背景色
|
||||
g2.setColor(backColor);
|
||||
g2.fillRect(0, 2,(int)captchaItem.getWidth(), (int)captchaItem.getHeight() - 4);
|
||||
}
|
||||
|
||||
private int getRandomIntColor() {
|
||||
int[] rgb = getRandomRgb();
|
||||
int color = 0;
|
||||
for (int c : rgb) {
|
||||
color = color << 8;
|
||||
color = color | c;
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
private int[] getRandomRgb() {
|
||||
int[] rgb = new int[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
rgb[i] = new Random().nextInt(255);
|
||||
}
|
||||
return rgb;
|
||||
}
|
||||
|
||||
|
||||
//图片扭曲
|
||||
private void shear(Graphics g, int w1, int h1, Color color) {
|
||||
shearX(g, w1, h1, color);
|
||||
shearY(g, w1, h1, color);
|
||||
}
|
||||
|
||||
private void shearX(Graphics g, int w1, int h1, Color color) {
|
||||
int period = new Random().nextInt(2);
|
||||
int frames = 1;
|
||||
int phase = new Random().nextInt(2);
|
||||
for (int i = 0; i < h1; i++) {
|
||||
double d = (double) (period >> 1)
|
||||
* Math.sin((double) i / (double) period
|
||||
+ (6.2831853071795862D * (double) phase)
|
||||
/ (double) frames);
|
||||
g.copyArea(0, i, w1, 1, (int) d, 0);
|
||||
g.setColor(color);
|
||||
g.drawLine((int) d, i, 0, i);
|
||||
g.drawLine((int) d + w1, i, w1, i);
|
||||
}
|
||||
}
|
||||
|
||||
private void shearY(Graphics g, int w1, int h1, Color color) {
|
||||
int period = new Random().nextInt(40) + 10;
|
||||
int frames = 20;
|
||||
int phase = 7;
|
||||
for (int i = 0; i < w1; i++) {
|
||||
double d = (double) (period >> 1)
|
||||
* Math.sin((double) i / (double) period
|
||||
+ (6.2831853071795862D * (double) phase)
|
||||
/ (double) frames);
|
||||
g.copyArea(i, 0, 1, h1, 0, (int) d);
|
||||
g.setColor(color);
|
||||
g.drawLine(i, (int) d, i, 0);
|
||||
g.drawLine(i, (int) d + h1, i, h1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成随机背景颜色
|
||||
*/
|
||||
private Color getColor(int fc, int bc) {
|
||||
if (fc > 255){
|
||||
fc = 254;
|
||||
}
|
||||
if (bc > 255){
|
||||
bc = 255;
|
||||
}
|
||||
int r = fc + new Random().nextInt(bc - fc);
|
||||
int g = fc + new Random().nextInt(bc - fc);
|
||||
int b = fc + new Random().nextInt(bc - fc);
|
||||
return new Color(r, g, b);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* -------------------------------对验证码对象进行查看和设置值----------------------
|
||||
*/
|
||||
public CaptchaItem getCaptchaItem() {
|
||||
return captchaItem;
|
||||
}
|
||||
|
||||
public void setCaptchaItem(CaptchaItem captchaItem1) {
|
||||
captchaItem = captchaItem1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package util.image;
|
||||
|
||||
import net.coobird.thumbnailator.Thumbnails;
|
||||
import util.FileUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class PicturesCompressUtil {
|
||||
/**
|
||||
* 设置压缩之后的图片比例(默认比例是50%)
|
||||
*/
|
||||
private float scale = (float)0.5;
|
||||
|
||||
public float getScale() {
|
||||
return scale;
|
||||
}
|
||||
|
||||
public void setScale(float scale) {
|
||||
this.scale = scale;
|
||||
}
|
||||
|
||||
public void compress(String srcPath, String desPath) throws IOException {
|
||||
if ( !FileUtil.fileExist(srcPath)){
|
||||
throw new RuntimeException("文件路径不存在");
|
||||
}
|
||||
Thumbnails.of(srcPath).scale(scale).toFile(desPath);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package util.image;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.MultiFormatWriter;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import entity.QRCodeItem;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import util.FileUtil;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author 黄志军
|
||||
* 二维码生成工具
|
||||
* 参考地址:http://blog.csdn.net/fly_to_the_winds/article/details/62042142
|
||||
*/
|
||||
public class QRCodeUtil {
|
||||
|
||||
private QRCodeItem qrCodeItem = new QRCodeItem();
|
||||
|
||||
/**
|
||||
* 生成一个最原始的二维码图片对象,后面的方法可以用于自由组合或者直接该方法输出图片
|
||||
*/
|
||||
public BufferedImage createQrCodeImage(){
|
||||
BufferedImage image;
|
||||
try {
|
||||
MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
|
||||
//这边如果内容为""或者为空会报错,如果没有内容用" "给他
|
||||
String content = StringUtils.isBlank(qrCodeItem.getContent())?" ":qrCodeItem.getContent();
|
||||
// 参数顺序分别为:编码内容,编码类型,生成图片宽度,生成图片高度,设置参数 (这边会设置参数但是如果不调用logo和content相关的代码,依然不会生成对应的图片和文字)
|
||||
BitMatrix bm = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, qrCodeItem.getWidth(), qrCodeItem.getHeight(), qrCodeItem.getHints());
|
||||
int w = bm.getWidth();
|
||||
int h = bm.getHeight();
|
||||
image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
|
||||
// 开始利用二维码数据创建Bitmap图片,分别设为黑(0xFFFFFFFF)白(0xFF000000)两色
|
||||
for (int x = 0; x < w; x++) {
|
||||
for (int y = 0; y < h; y++) {
|
||||
image.setRGB(x, y, bm.get(x, y) ? qrCodeItem.getStripeColor().getRGB() : qrCodeItem.getBackgroundColor().getRGB());
|
||||
}
|
||||
}
|
||||
} catch (WriterException e) {
|
||||
throw new RuntimeException("生成BufferedImage失败");
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过BufferedImage进行logo绘制,这边返回一个携带logo信息的BufferedImage对象
|
||||
*/
|
||||
public BufferedImage drawLogo(BufferedImage image){
|
||||
try {
|
||||
Graphics2D g2 = image.createGraphics();
|
||||
//logo
|
||||
File logoPic = new File(qrCodeItem.getLogoPath());
|
||||
BufferedImage logo = ImageIO.read(logoPic);
|
||||
//设置logo大小
|
||||
int widthLogo = logo.getWidth(null)>image.getWidth()*3/10?(image.getWidth()*3/10):logo.getWidth(null),
|
||||
heightLogo = logo.getHeight(null)>image.getHeight()*3/10?(image.getHeight()*3/10):logo.getWidth(null);
|
||||
//开始绘制图片
|
||||
if (qrCodeItem.isDiyLogoPosition()){
|
||||
g2.drawImage(logo, qrCodeItem.getLogoX(),qrCodeItem.getLogoY() ,widthLogo, heightLogo, null);
|
||||
}else{
|
||||
g2.drawImage(logo, (image.getWidth() - widthLogo) / 2, (image.getHeight() - heightLogo) / 2, widthLogo, heightLogo, null);
|
||||
}
|
||||
g2.dispose();
|
||||
logo.flush();
|
||||
return image;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("画logo失败了");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过BufferedImage进行内容的绘制,这边返回一个携带内容的BufferedImage对象
|
||||
* 这边只是提供一个简单的模板写法,如果需要根据文字内容进行自适应需要修改这么方法的写法
|
||||
*/
|
||||
public BufferedImage drawContent(BufferedImage image){
|
||||
BufferedImage image1 = null;
|
||||
//在文字内容不为空的情况下进行处理
|
||||
if(StringUtils.isNotBlank(qrCodeItem.getContent())){
|
||||
//生成新的画板
|
||||
image1 = new BufferedImage(qrCodeItem.getWidth(),qrCodeItem.getHeight(),BufferedImage.TYPE_4BYTE_ABGR);
|
||||
Graphics2D g2 = image1.createGraphics();
|
||||
//将二维码画在新画板上
|
||||
g2.drawImage(image,0,0, qrCodeItem.getWidth(),qrCodeItem.getHeight(),null);
|
||||
//设置画笔信息
|
||||
g2.setColor(qrCodeItem.getContentColor());
|
||||
g2.setFont(qrCodeItem.getContentFont());
|
||||
//这里不判断文字的长度,只设置书写一行的文字。
|
||||
if(qrCodeItem.isDiyContentPosition()){
|
||||
g2.drawString(qrCodeItem.getContent(),qrCodeItem.getContentX(),qrCodeItem.getContentY());
|
||||
}else{
|
||||
int strWidth = g2.getFontMetrics().stringWidth(qrCodeItem.getContent());
|
||||
g2.drawString(qrCodeItem.getContent(),(qrCodeItem.getWidth()-strWidth)/2,image.getHeight()-g2.getFont().getSize() -10);
|
||||
}
|
||||
g2.dispose();
|
||||
image1.flush();
|
||||
}
|
||||
return image1==null? image : image1;
|
||||
}
|
||||
|
||||
public void createQrCodeWithImage(String filePath, BufferedImage image){
|
||||
File file = FileUtil.createGetFile(filePath);
|
||||
if (file == null){
|
||||
throw new RuntimeException("文件不存在或者创建失败");
|
||||
}
|
||||
try {
|
||||
ImageIO.write(image,qrCodeItem.getSuffix(),file);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("文件创建失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* -------------------------------对二维码对象进行查看和设置值----------------------
|
||||
*/
|
||||
public QRCodeItem getQrCodeItem() {
|
||||
return qrCodeItem;
|
||||
}
|
||||
|
||||
public void setQrCodeItem(QRCodeItem qrCodeItem) {
|
||||
this.qrCodeItem = qrCodeItem;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* @(#) FillTemplateHelper
|
||||
* 版权声明 网宿科技, 版权所有 违者必究
|
||||
*
|
||||
* <br> Copyright: Copyright (c) 2018
|
||||
* <br> Company:网宿科技
|
||||
* <br> @author Administrator
|
||||
* <br> @description 功能描述
|
||||
* <br> 2018-11-13 20:19:49
|
||||
*/
|
||||
|
||||
package util.itext;
|
||||
|
||||
import com.itextpdf.text.*;
|
||||
import com.itextpdf.text.pdf.*;
|
||||
import com.itextpdf.tool.xml.ElementList;
|
||||
import com.itextpdf.tool.xml.XMLWorker;
|
||||
import com.itextpdf.tool.xml.XMLWorkerHelper;
|
||||
import com.itextpdf.tool.xml.css.CssFile;
|
||||
import com.itextpdf.tool.xml.css.StyleAttrCSSResolver;
|
||||
import com.itextpdf.tool.xml.html.TagProcessorFactory;
|
||||
import com.itextpdf.tool.xml.parser.XMLParser;
|
||||
import com.itextpdf.tool.xml.pipeline.css.CSSResolver;
|
||||
import com.itextpdf.tool.xml.pipeline.css.CssResolverPipeline;
|
||||
import com.itextpdf.tool.xml.pipeline.end.ElementHandlerPipeline;
|
||||
import com.itextpdf.tool.xml.pipeline.html.HtmlPipeline;
|
||||
import com.itextpdf.tool.xml.pipeline.html.HtmlPipelineContext;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* @author iText
|
||||
*/
|
||||
public class FillTemplateHelper extends PdfPageEventHelper {
|
||||
|
||||
// initialized in constructor
|
||||
protected PdfReader reader;
|
||||
protected Rectangle pageSize;
|
||||
protected Rectangle body;
|
||||
protected float mLeft, mRight, mTop, mBottom;
|
||||
protected Rectangle to;
|
||||
protected Rectangle from;
|
||||
protected Rectangle date;
|
||||
protected Rectangle footer;
|
||||
protected BaseFont basefont;
|
||||
protected Font font;
|
||||
// initialized with setter
|
||||
protected String sender = "";
|
||||
protected String receiver = "";
|
||||
// initialized upon opening the document
|
||||
protected PdfTemplate background;
|
||||
protected PdfTemplate total;
|
||||
|
||||
public FillTemplateHelper(String stationery) throws IOException, DocumentException {
|
||||
reader = new PdfReader(stationery);
|
||||
AcroFields fields = reader.getAcroFields();
|
||||
pageSize = reader.getPageSize(1);
|
||||
body = fields.getFieldPositions("body").get(0).position;
|
||||
mLeft = body.getLeft() - pageSize.getLeft();
|
||||
mRight = pageSize.getRight() - body.getRight();
|
||||
mTop = pageSize.getTop() - body.getTop();
|
||||
mBottom = body.getBottom() - pageSize.getBottom();
|
||||
footer = fields.getFieldPositions("footer").get(0).position;
|
||||
basefont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
|
||||
font = new Font(basefont, 12);
|
||||
|
||||
}
|
||||
|
||||
public static ElementList parseHtml(String content, String style, TagProcessorFactory tagProcessors) throws IOException {
|
||||
// CSS
|
||||
CSSResolver cssResolver = new StyleAttrCSSResolver();
|
||||
CssFile cssFile = XMLWorkerHelper.getCSS(new FileInputStream(style));
|
||||
cssResolver.addCss(cssFile);
|
||||
// HTML
|
||||
HtmlPipelineContext htmlContext = new HtmlPipelineContext(null);
|
||||
htmlContext.setTagFactory(tagProcessors);
|
||||
htmlContext.autoBookmark(false);
|
||||
// Pipelines
|
||||
ElementList elements = new ElementList();
|
||||
ElementHandlerPipeline end = new ElementHandlerPipeline(elements, null);
|
||||
HtmlPipeline html = new HtmlPipeline(htmlContext, end);
|
||||
CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);
|
||||
// XML Worker
|
||||
XMLWorker worker = new XMLWorker(css, true);
|
||||
XMLParser p = new XMLParser(worker);
|
||||
p.parse(new FileInputStream(content), Charset.forName("utf8"));
|
||||
return elements;
|
||||
}
|
||||
|
||||
public static ElementList parseHtmlContent(String content, String style, TagProcessorFactory tagProcessors) throws IOException {
|
||||
// CSS
|
||||
CSSResolver cssResolver = new StyleAttrCSSResolver();
|
||||
CssFile cssFile = XMLWorkerHelper.getCSS(new FileInputStream(style));
|
||||
cssResolver.addCss(cssFile);
|
||||
// HTML
|
||||
HtmlPipelineContext htmlContext = new HtmlPipelineContext(null);
|
||||
htmlContext.setTagFactory(tagProcessors);
|
||||
htmlContext.autoBookmark(false);
|
||||
// Pipelines
|
||||
ElementList elements = new ElementList();
|
||||
ElementHandlerPipeline end = new ElementHandlerPipeline(elements, null);
|
||||
HtmlPipeline html = new HtmlPipeline(htmlContext, end);
|
||||
CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);
|
||||
// XML Worker
|
||||
XMLWorker worker = new XMLWorker(css, true);
|
||||
XMLParser p = new XMLParser(worker);
|
||||
try {
|
||||
p.parse(getStringStream(content), Charset.forName("utf8"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
public static InputStream getStringStream(String sInputString) {
|
||||
if (sInputString != null && !sInputString.trim().equals("")) {
|
||||
try {
|
||||
ByteArrayInputStream tInputStringStream = new ByteArrayInputStream(sInputString.getBytes("UTF-8"));
|
||||
return tInputStringStream;
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setSender(String sender) {
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
public void setReceiver(String receiver) {
|
||||
this.receiver = receiver;
|
||||
}
|
||||
|
||||
public Rectangle getPageSize() {
|
||||
return pageSize;
|
||||
}
|
||||
|
||||
public float getmLeft() {
|
||||
return mLeft;
|
||||
}
|
||||
|
||||
public float getmRight() {
|
||||
return mRight;
|
||||
}
|
||||
|
||||
public float getmTop() {
|
||||
return mTop;
|
||||
}
|
||||
|
||||
public float getmBottom() {
|
||||
return mBottom;
|
||||
}
|
||||
|
||||
public Rectangle getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpenDocument(PdfWriter writer, Document document) {
|
||||
background = writer.getImportedPage(reader, 1);
|
||||
total = writer.getDirectContent().createTemplate(30, 15);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEndPage(PdfWriter writer, Document document) {
|
||||
PdfContentByte canvas = writer.getDirectContentUnder();
|
||||
// background
|
||||
canvas.addTemplate(background, 0, 0);
|
||||
try {
|
||||
ColumnText ct = new ColumnText(canvas);
|
||||
ct.setSimpleColumn(footer);
|
||||
ct.addText(new Chunk(" " + writer.getPageNumber(), font));
|
||||
ct.addText(new Chunk(Image.getInstance(total), 0, 0));
|
||||
ct.go();
|
||||
} catch (DocumentException e) {
|
||||
// can never happen, but if it does, we want to know!
|
||||
throw new ExceptionConverter(e);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCloseDocument(PdfWriter writer, Document document) {
|
||||
// 关闭时可以知道总页数,写入页码
|
||||
String s = "/ " + (writer.getPageNumber());
|
||||
Phrase p = new Phrase(12, s, font);
|
||||
ColumnText.showTextAligned(total, Element.ALIGN_LEFT, p, 0.5f, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
|
||||
|
||||
package util.itext;
|
||||
|
||||
import com.itextpdf.text.*;
|
||||
import com.itextpdf.text.pdf.*;
|
||||
import com.itextpdf.tool.xml.ElementList;
|
||||
import com.itextpdf.tool.xml.html.Tags;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Created by huangzhijun on 2017/8/22.
|
||||
* itext 用于生成pdf的工具类
|
||||
*/
|
||||
public class PDFUtils {
|
||||
/**
|
||||
* 通过模板生成pdf文件
|
||||
*
|
||||
* @param templatePath 模板路径
|
||||
* @param resultPath 生成路径
|
||||
* @param cssPath css路径
|
||||
* @param content 生成pdf的内容
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void generalPDF(String templatePath, String resultPath, String cssPath, String content) throws Exception {
|
||||
// 读取模板
|
||||
FillTemplateHelper template = new FillTemplateHelper(templatePath);
|
||||
Document document = new Document(template.getPageSize(),
|
||||
template.getmLeft(), template.getmRight(), template.getmTop(), template.getmBottom());
|
||||
// 创建pdf写对象
|
||||
PdfWriter writer = null;
|
||||
FileOutputStream outputStream = new FileOutputStream(resultPath);
|
||||
try {
|
||||
writer = PdfWriter.getInstance(document, outputStream);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
writer.setPageEvent(template);
|
||||
//打开文件
|
||||
document.open();
|
||||
// 填充数据到文件中
|
||||
ElementList elements = FillTemplateHelper.parseHtmlContent(content, cssPath, Tags.getHtmlTagProcessorFactory());
|
||||
for (Element e : elements) {
|
||||
document.add(e);
|
||||
}
|
||||
writer.setPageEmpty(false);
|
||||
//关闭流操作
|
||||
document.close();
|
||||
writer.close();
|
||||
outputStream.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* PDF盖章操作
|
||||
* 在PDF文档的最后一页盖章
|
||||
* @param RES 需要盖章的pdf文件地址
|
||||
* @param DEST 生成的新pdf文件地址
|
||||
* @param SEAL 印章图片的地址
|
||||
* @param company 落款名称及部门
|
||||
* @param dateName 落款时间名称
|
||||
* @throws DocumentException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void sealDocument(String RES, String DEST, String SEAL, String company, String dateName, String time) throws DocumentException, IOException {
|
||||
|
||||
PdfReader reader = new PdfReader(RES);
|
||||
int numberOfPages = reader.getNumberOfPages();
|
||||
Rectangle pageSize = reader.getPageSize(1);
|
||||
Document doc = new Document(pageSize);
|
||||
PdfWriter writer_ = PdfWriter.getInstance(doc, new FileOutputStream(DEST));
|
||||
// 打开文档
|
||||
doc.open();
|
||||
PdfContentByte cb = writer_.getDirectContent();
|
||||
for (int i = 0; i < numberOfPages; ) {
|
||||
{
|
||||
i++;
|
||||
//设置指定页的PagSize 包含Rotation(页面旋转度)
|
||||
// doc.setPageSize(reader.getPageSizeWithRotation(i));
|
||||
//创建一个新的页面,需要注意的调用NewPage() ,PdfContentByte cb 对象会默认清空
|
||||
doc.newPage();
|
||||
// //获取指定页面的旋转度
|
||||
// int rotation = reader.getPageRotation(i);
|
||||
//获取加载PDF的指定页内容
|
||||
PdfImportedPage page1 = writer_.getImportedPage(reader, i);
|
||||
|
||||
//添加内容页到新的页面,并更加旋转度设置对应的旋转
|
||||
/* switch (rotation) {
|
||||
case 90:
|
||||
cb.addTemplate(page1, 0, -1, 1, 0, 0, reader.getPageSizeWithRotation(i).getHeight());
|
||||
break;
|
||||
case 180:
|
||||
cb.addTemplate(page1, -1, 0, 0, -1, reader.getPageSizeWithRotation(i).getWidth(), reader.getPageSizeWithRotation(i).getHeight());
|
||||
break;
|
||||
case 270:
|
||||
cb.addTemplate(page1, 0, 1, -1, 0, reader.getPageSizeWithRotation(i).getWidth(), 0);
|
||||
break;
|
||||
default:
|
||||
cb.addTemplate(page1, 1, 0, 0, 1, 0, 0);//等同于 cb.AddTemplate(page1, 0,0)
|
||||
break;
|
||||
}*/
|
||||
cb.addTemplate(page1, 0, 0);
|
||||
|
||||
if (i == numberOfPages)//如果是最后一页加入指定的图片
|
||||
{
|
||||
//创建一个图片对象
|
||||
Image img = Image.getInstance(SEAL);
|
||||
//设置图片的指定大小
|
||||
//img.ScaleToFit(140F, 320F);
|
||||
//按比例缩放
|
||||
img.scalePercent(100);
|
||||
BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", com.itextpdf.text.pdf.BaseFont.NOT_EMBEDDED);
|
||||
cb.beginText();
|
||||
//设置字体 大小
|
||||
cb.setFontAndSize(bf, 13);
|
||||
//指定添加文字的绝对位置
|
||||
cb.setTextMatrix(350, 75);
|
||||
//增加文本
|
||||
cb.showText(company);
|
||||
//结束
|
||||
cb.endText();
|
||||
cb.beginText();
|
||||
//设置字体 大小
|
||||
cb.setFontAndSize(bf, 13);
|
||||
//指定添加文字的绝对位置
|
||||
cb.setTextMatrix(350, 55);
|
||||
if (org.apache.commons.lang3.StringUtils.isBlank(time)) {
|
||||
Date date = new Date();
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
|
||||
time = format.format(date);
|
||||
}
|
||||
//增加文本
|
||||
cb.showText(dateName + ":" + time);
|
||||
//结束
|
||||
cb.endText();
|
||||
//把图片增加到内容页的指定位子 b width c height e bottom f left
|
||||
// use addImage(image, image_width, 0, 0, image_height, x, y)
|
||||
cb.addImage(img, 130, 0, 0, 130, 400, 55);
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("盖章成功");
|
||||
doc.close();
|
||||
writer_.close();
|
||||
reader.close();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 将页面传过来的内容重新组装为html
|
||||
* @param content
|
||||
* @return
|
||||
*/
|
||||
public String transToHtml(String content) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append("<html>");
|
||||
sb.append("<head>");
|
||||
sb.append("<meta charset=\"UTF-8\" />");
|
||||
sb.append("</head>");
|
||||
sb.append("<body style='font-family:SimSun;'>");
|
||||
sb.append("<div class=\"executed-report\">");
|
||||
sb.append("<div class=\"report-box clearfix\">");
|
||||
sb.append(content);
|
||||
sb.append("</div>");
|
||||
sb.append("</div>");
|
||||
sb.append("</body>");
|
||||
sb.append("</html>");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,527 @@
|
||||
|
||||
package util.redis;
|
||||
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 网上copy的别人写的redis的工具
|
||||
* @author QLQ
|
||||
* 基于spring和redis的redisTemplate工具类
|
||||
* 针对所有的hash 都是以h开头的方法
|
||||
* 针对所有的Set 都是以s开头的方法 不含通用方法
|
||||
* 针对所有的List 都是以l开头的方法
|
||||
*/
|
||||
public class RedisUtil {
|
||||
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
|
||||
this.redisTemplate = redisTemplate;
|
||||
}
|
||||
//=============================common============================
|
||||
|
||||
/**
|
||||
* 指定缓存失效时间
|
||||
* @param key 键
|
||||
* @param time 时间(秒)
|
||||
*/
|
||||
public boolean expire(String key, long time) {
|
||||
try {
|
||||
if (time > 0) {
|
||||
redisTemplate.expire(key, time, TimeUnit.SECONDS);
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据key 获取过期时间
|
||||
* @param key 键 不能为null
|
||||
* @return 时间(秒) 返回0代表为永久有效
|
||||
*/
|
||||
public long getExpire(String key) {
|
||||
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断key是否存在
|
||||
* @param key 键
|
||||
* @return true 存在 false不存在
|
||||
*/
|
||||
public boolean hasKey(String key) {
|
||||
try {
|
||||
return redisTemplate.hasKey(key);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除缓存
|
||||
* @param key 可以传一个值 或多个
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void del(String... key) {
|
||||
if (key != null && key.length > 0) {
|
||||
if (key.length == 1) {
|
||||
redisTemplate.delete(key[0]);
|
||||
} else {
|
||||
redisTemplate.delete(CollectionUtils.arrayToList(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//============================String=============================
|
||||
|
||||
/**
|
||||
* 普通缓存获取
|
||||
* @param key 键
|
||||
* @return 值
|
||||
*/
|
||||
public Object get(String key) {
|
||||
return key == null ? null : redisTemplate.opsForValue().get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 普通缓存放入
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
* @return true成功 false失败
|
||||
*/
|
||||
public boolean set(String key, Object value) {
|
||||
try {
|
||||
redisTemplate.opsForValue().set(key, value);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 普通缓存放入并设置时间
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
|
||||
* @return true成功 false 失败
|
||||
*/
|
||||
public boolean set(String key, Object value, long time) {
|
||||
try {
|
||||
if (time > 0) {
|
||||
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
|
||||
} else {
|
||||
set(key, value);
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 递增
|
||||
* @param key 键
|
||||
*/
|
||||
public long incr(String key, long delta) {
|
||||
if (delta < 0) {
|
||||
throw new RuntimeException("递增因子必须大于0");
|
||||
}
|
||||
return redisTemplate.opsForValue().increment(key, delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* 递减
|
||||
* @param key 键
|
||||
*/
|
||||
public long decr(String key, long delta) {
|
||||
if (delta < 0) {
|
||||
throw new RuntimeException("递减因子必须大于0");
|
||||
}
|
||||
return redisTemplate.opsForValue().increment(key, -delta);
|
||||
}
|
||||
|
||||
//================================Map=================================
|
||||
|
||||
/**
|
||||
* HashGet
|
||||
* @param key 键 不能为null
|
||||
* @param item 项 不能为null
|
||||
* @return 值
|
||||
*/
|
||||
public Object hget(String key, String item) {
|
||||
return redisTemplate.opsForHash().get(key, item);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取hashKey对应的所有键值
|
||||
* @param key 键
|
||||
* @return 对应的多个键值
|
||||
*/
|
||||
public Map<Object, Object> hmget(String key) {
|
||||
return redisTemplate.opsForHash().entries(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* HashSet
|
||||
* @param key 键
|
||||
* @param map 对应多个键值
|
||||
* @return true 成功 false 失败
|
||||
*/
|
||||
public boolean hmset(String key, Map<String, Object> map) {
|
||||
try {
|
||||
redisTemplate.opsForHash().putAll(key, map);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* HashSet 并设置时间
|
||||
* @param key 键
|
||||
* @param map 对应多个键值
|
||||
* @param time 时间(秒)
|
||||
* @return true成功 false失败
|
||||
*/
|
||||
public boolean hmset(String key, Map<String, Object> map, long time) {
|
||||
try {
|
||||
redisTemplate.opsForHash().putAll(key, map);
|
||||
if (time > 0) {
|
||||
expire(key, time);
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 向一张hash表中放入数据,如果不存在将创建
|
||||
* @param key 键
|
||||
* @param item 项
|
||||
* @param value 值
|
||||
* @return true 成功 false失败
|
||||
*/
|
||||
public boolean hset(String key, String item, Object value) {
|
||||
try {
|
||||
redisTemplate.opsForHash().put(key, item, value);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 向一张hash表中放入数据,如果不存在将创建
|
||||
* @param key 键
|
||||
* @param item 项
|
||||
* @param value 值
|
||||
* @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
|
||||
* @return true 成功 false失败
|
||||
*/
|
||||
public boolean hset(String key, String item, Object value, long time) {
|
||||
try {
|
||||
redisTemplate.opsForHash().put(key, item, value);
|
||||
if (time > 0) {
|
||||
expire(key, time);
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除hash表中的值
|
||||
* @param key 键 不能为null
|
||||
* @param item 项 可以使多个 不能为null
|
||||
*/
|
||||
public void hdel(String key, Object... item) {
|
||||
redisTemplate.opsForHash().delete(key, item);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断hash表中是否有该项的值
|
||||
* @param key 键 不能为null
|
||||
* @param item 项 不能为null
|
||||
* @return true 存在 false不存在
|
||||
*/
|
||||
public boolean hHasKey(String key, String item) {
|
||||
return redisTemplate.opsForHash().hasKey(key, item);
|
||||
}
|
||||
|
||||
/**
|
||||
* hash递增 如果不存在,就会创建一个 并把新增后的值返回
|
||||
* @param key 键
|
||||
* @param item 项
|
||||
* @param by 要增加几(大于0)
|
||||
*/
|
||||
public double hincr(String key, String item, double by) {
|
||||
return redisTemplate.opsForHash().increment(key, item, by);
|
||||
}
|
||||
|
||||
/**
|
||||
* hash递减
|
||||
* @param key 键
|
||||
* @param item 项
|
||||
* @param by 要减少记(小于0)
|
||||
*/
|
||||
public double hdecr(String key, String item, double by) {
|
||||
return redisTemplate.opsForHash().increment(key, item, -by);
|
||||
}
|
||||
|
||||
//============================set=============================
|
||||
|
||||
/**
|
||||
* 根据key获取Set中的所有值
|
||||
* @param key 键
|
||||
*/
|
||||
public Set<Object> sGet(String key) {
|
||||
try {
|
||||
return redisTemplate.opsForSet().members(key);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据value从一个set中查询,是否存在
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
* @return true 存在 false不存在
|
||||
*/
|
||||
public boolean sHasKey(String key, Object value) {
|
||||
try {
|
||||
return redisTemplate.opsForSet().isMember(key, value);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将数据放入set缓存
|
||||
* @param key 键
|
||||
* @param values 值 可以是多个
|
||||
* @return 成功个数
|
||||
*/
|
||||
public long sSet(String key, Object... values) {
|
||||
try {
|
||||
return redisTemplate.opsForSet().add(key, values);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将set数据放入缓存
|
||||
* @param key 键
|
||||
* @param time 时间(秒)
|
||||
* @param values 值 可以是多个
|
||||
* @return 成功个数
|
||||
*/
|
||||
public long sSetAndTime(String key, long time, Object... values) {
|
||||
try {
|
||||
Long count = redisTemplate.opsForSet().add(key, values);
|
||||
if (time > 0){
|
||||
expire(key, time);
|
||||
}
|
||||
return count;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取set缓存的长度
|
||||
* @param key 键
|
||||
*/
|
||||
public long sGetSetSize(String key) {
|
||||
try {
|
||||
return redisTemplate.opsForSet().size(key);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除值为value的
|
||||
* @param key 键
|
||||
* @param values 值 可以是多个
|
||||
* @return 移除的个数
|
||||
*/
|
||||
public long setRemove(String key, Object... values) {
|
||||
try {
|
||||
Long count = redisTemplate.opsForSet().remove(key, values);
|
||||
return count;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
//===============================list=================================
|
||||
|
||||
/**
|
||||
* 获取list缓存的内容
|
||||
* @param key 键
|
||||
* @param start 开始
|
||||
* @param end 结束 0 到 -1代表所有值
|
||||
*/
|
||||
public List<Object> lGet(String key, long start, long end) {
|
||||
try {
|
||||
return redisTemplate.opsForList().range(key, start, end);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取list缓存的长度
|
||||
* @param key 键
|
||||
*/
|
||||
public long lGetListSize(String key) {
|
||||
try {
|
||||
return redisTemplate.opsForList().size(key);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过索引 获取list中的值
|
||||
* @param key 键
|
||||
* @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
|
||||
*/
|
||||
public Object lGetIndex(String key, long index) {
|
||||
try {
|
||||
return redisTemplate.opsForList().index(key, index);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将list放入缓存
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
*/
|
||||
public boolean lSet(String key, Object value) {
|
||||
try {
|
||||
redisTemplate.opsForList().rightPush(key, value);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将list放入缓存
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
* @param time 时间(秒)
|
||||
*/
|
||||
public boolean lSet(String key, Object value, long time) {
|
||||
try {
|
||||
redisTemplate.opsForList().rightPush(key, value);
|
||||
if (time > 0) {
|
||||
expire(key, time);
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将list放入缓存
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
*/
|
||||
public boolean lSet(String key, List<Object> value) {
|
||||
try {
|
||||
redisTemplate.opsForList().rightPushAll(key, value);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将list放入缓存
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
* @param time 时间(秒)
|
||||
*/
|
||||
public boolean lSet(String key, List<Object> value, long time) {
|
||||
try {
|
||||
redisTemplate.opsForList().rightPushAll(key, value);
|
||||
if (time > 0) {
|
||||
expire(key, time);
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据索引修改list中的某条数据
|
||||
* @param key 键
|
||||
* @param index 索引
|
||||
* @param value 值
|
||||
*/
|
||||
public boolean lUpdateIndex(String key, long index, Object value) {
|
||||
try {
|
||||
redisTemplate.opsForList().set(key, index, value);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除N个值为value
|
||||
* @param key 键
|
||||
* @param count 移除多少个
|
||||
* @param value 值
|
||||
* @return 移除的个数
|
||||
*/
|
||||
public long lRemove(String key, long count, Object value) {
|
||||
try {
|
||||
Long remove = redisTemplate.opsForList().remove(key, count, value);
|
||||
return remove;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
|
||||
package util.time;
|
||||
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.*;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import static additive.ValidTool.assertIsTrue;
|
||||
|
||||
public class DateTimeUtil {
|
||||
|
||||
private static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd";
|
||||
private static final String DEFAULT_TIME_PATTERN = "HH:mm:ss";
|
||||
private static final String DEFAULT_PATTERN = "yyyy-MM-dd HH:mm:ss";
|
||||
private static final String DEFAULT_PATTERN_CLOSE = "yyyyMMddHHmmss";
|
||||
private static final String DATE_TIME_MINUTE_PATTERN = "yyyy-MM-dd HH:mm";
|
||||
private static final String ISO_8601_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSZZ";
|
||||
private static final String lO_G_PARAM_TIME_PATTERN = "yyyy-MM-dd-HHmm";
|
||||
|
||||
|
||||
/**
|
||||
* 获取当天日期,"yyyy-MM-dd"
|
||||
*/
|
||||
public static String getCurrentDate() {
|
||||
return LocalDate.now().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前时间,yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
public static String getCurrentDateTime() {
|
||||
return LocalDateTime.now().format(DateTimeFormatter.ofPattern(DEFAULT_PATTERN));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取与所给日期间隔要求天数的日期
|
||||
* @param localDate 参考日期, yyyy-MM-dd
|
||||
* @param dayOffset 间隔天数
|
||||
*/
|
||||
public static String plusDay(final String localDate, final int dayOffset) {
|
||||
assertIsTrue(dayOffset >= 0, "偏移量必须大于0");
|
||||
return LocalDate.parse(localDate).plusDays(dayOffset).format(DateTimeFormatter.ISO_LOCAL_DATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取与所给日期间隔要求天数的日期
|
||||
* @param localDate 参考日期, yyyy-MM-dd
|
||||
* @param dayOffset 间隔天数
|
||||
*/
|
||||
public static String minusDay(final String localDate, final int dayOffset) {
|
||||
assertIsTrue(dayOffset >= 0, "偏移量必须大于0");
|
||||
return LocalDate.parse(localDate).minusDays(dayOffset).format(DateTimeFormatter.ISO_LOCAL_DATE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将日期时间转换成指定格式的时间
|
||||
*/
|
||||
public static String dateToString(String pattern, LocalDateTime dateTime) {
|
||||
return DateTimeFormatter.ofPattern(pattern).format(dateTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间戳转换为指定格式字符串(秒)
|
||||
*/
|
||||
public static String dateToString(String pattern, long epochSecond, TimeZone timeZone) {
|
||||
return dateToString(pattern, LocalDateTime.ofInstant(Instant.ofEpochSecond(epochSecond), timeZone.toZoneId()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 时间戳转成指定格式字符串(毫秒)
|
||||
*/
|
||||
public static String timestampToString(String pattern, long timestamp, TimeZone timeZone) {
|
||||
return dateToString(pattern, LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), timeZone.toZoneId()));
|
||||
}
|
||||
|
||||
public static String dateToString(String pattern, ZonedDateTime dateTime) {
|
||||
return DateTimeFormatter.ofPattern(pattern)
|
||||
.format(dateTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将LocalDateTime转换成指定格式字符串
|
||||
*/
|
||||
public static String localTimeToString(LocalDateTime localDateTime, String pattern) {
|
||||
LocalTime localTime = localDateTime.toLocalTime();
|
||||
return DateTimeFormatter.ofPattern(pattern).format(localTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将时间格式换成"HH:mm:ss" 格式
|
||||
*/
|
||||
public static String formatDateToTime(LocalDateTime date) {
|
||||
return DateTimeUtil.dateToString(DEFAULT_TIME_PATTERN, date);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将时间格式换成"yyyy-MM-dd" 格式
|
||||
*/
|
||||
public static String formatDateToDay(LocalDateTime date) {
|
||||
return DateTimeUtil.dateToString(DEFAULT_DATE_PATTERN, date);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param timeString yyyy-MM-dd-HHmm
|
||||
* @return yyyy-MM-dd HH:mm 格式的时间字符串
|
||||
*/
|
||||
public static String paramTimeFormat(String timeString) throws ParseException {
|
||||
Date newDate = new SimpleDateFormat(lO_G_PARAM_TIME_PATTERN).parse(timeString);
|
||||
return new SimpleDateFormat(DATE_TIME_MINUTE_PATTERN).format(newDate);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取当前时间,yyyy-MM-dd HH:mm:ss
|
||||
* 注意:使用当前系统默认的时区
|
||||
*/
|
||||
public static LocalDateTime getNow() {
|
||||
return LocalDateTime.now();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将时间戳(单位:毫秒)转成 LocalDateTime
|
||||
*/
|
||||
public static LocalDateTime timeStampToLocalDateTime(long timeStamp) {
|
||||
return Instant.ofEpochMilli(timeStamp).atZone(ZoneId.systemDefault()).toLocalDateTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将时间戳(单位为:秒)转成 LocalDateTime
|
||||
*/
|
||||
public static LocalDateTime epochSecondToLocalDateTime(long epochSecond, TimeZone timeZone) {
|
||||
return epochSecondToLocalDateTime(epochSecond, timeZone.toZoneId());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将时间戳(单位为:秒)转成 LocalDateTime
|
||||
*/
|
||||
public static LocalDateTime epochSecondToLocalDateTime(long epochSecond, ZoneId zoneId) {
|
||||
return Instant.ofEpochSecond(epochSecond).atZone(zoneId).toLocalDateTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* LocalDateTime转成时间戳:毫秒
|
||||
*/
|
||||
public static long toEpochMilli(LocalDateTime localDateTime, TimeZone timeZone) {
|
||||
return Instant.from(localDateTime.atZone(timeZone.toZoneId())).toEpochMilli();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串转换为LocalDateTime
|
||||
*/
|
||||
public static LocalDateTime stringToLocalDateTime(String dateStr, String pattern) {
|
||||
DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern);
|
||||
return LocalDateTime.parse(dateStr, df);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 到天的字符串,转成LocalDateTime
|
||||
* @param dayStr 如"2017-11-16"
|
||||
* @return 返回0点0分0秒的时间 如 "2017-11-16 00:00:00"
|
||||
*/
|
||||
public static LocalDateTime dayStringToLocalDateTime(String dayStr) {
|
||||
return LocalDate.parse(dayStr, DateTimeFormatter.ofPattern(DEFAULT_DATE_PATTERN)).atTime(0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* LocalDateTime转成时间戳:秒
|
||||
*/
|
||||
public static long toEpochSecond(LocalDateTime localDateTime, TimeZone timeZone) {
|
||||
return Instant.from(localDateTime.atZone(timeZone.toZoneId())).getEpochSecond();
|
||||
}
|
||||
|
||||
|
||||
public static long toEpochSecond(LocalDateTime localDateTime, ZoneId zoneId) {
|
||||
return localDateTime.atZone(zoneId).toEpochSecond();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取当前时间的秒数
|
||||
*/
|
||||
public static long getNowSeconds(){
|
||||
return
|
||||
LocalDateTime.now().toEpochSecond(ZoneOffset.MAX);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否同一个时间点
|
||||
*/
|
||||
public static boolean isTheSameDay(LocalDateTime startDate, LocalDateTime endDate) {
|
||||
return startDate.toLocalDate()
|
||||
.isEqual(endDate.toLocalDate());
|
||||
}
|
||||
|
||||
/**
|
||||
* LocalDateTime 转成时间戳
|
||||
*/
|
||||
public static Instant toInstant(LocalDateTime endDate, TimeZone timeZone) {
|
||||
return endDate.atZone(timeZone.toZoneId()).toInstant();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
|
||||
|
||||
package util.time;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import entity.OriginTimeValue;
|
||||
import entity.TargetTimeValue;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 补时间点工具类
|
||||
* 之前在ws上班的时候,处理图标数据会遇到某些点没有数据的情况,就需要对这些时间点进行补点处理
|
||||
*
|
||||
* @author huangzj
|
||||
* @date 2018-11-23 22:43:36
|
||||
*/
|
||||
public enum FillFullTimeValueUtil {
|
||||
/**
|
||||
* 分钟粒度
|
||||
*/
|
||||
MINUTE {
|
||||
@Override
|
||||
public List<TargetTimeValue> fullFillTimeValue(LocalDateTime startDate, LocalDateTime endDate, int timeInterval,
|
||||
List<OriginTimeValue> originTimeValues, TimeZone timeZone) {
|
||||
//Myview 向前聚合,返回前XX秒为最开始计数时间
|
||||
Instant firstInstant = toInstant(startDate, timeZone);
|
||||
Instant finalInstant = toInstant(endDate, timeZone);
|
||||
//补时间点--规则一样,间隔转换成秒
|
||||
return fullFillRule(originTimeValues, firstInstant, finalInstant, timeInterval * 60);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 小时粒度
|
||||
*/
|
||||
HOUR {
|
||||
@Override
|
||||
public List<TargetTimeValue> fullFillTimeValue(LocalDateTime startDate, LocalDateTime endDate, int timeInterval,
|
||||
List<OriginTimeValue> originTimeValues, TimeZone timeZone) {
|
||||
Instant firstInstant = toInstant(startDate, timeZone);
|
||||
Instant finalInstant = toInstant(endDate, timeZone);
|
||||
//补时间点--规则一样
|
||||
return fullFillRule(originTimeValues, firstInstant, finalInstant, timeInterval * 60 * 60);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 天粒度
|
||||
*/
|
||||
DAY {
|
||||
@Override
|
||||
public List<TargetTimeValue> fullFillTimeValue(LocalDateTime startDate, LocalDateTime endDate, int timeInterval,
|
||||
List<OriginTimeValue> originTimeValues, TimeZone timeZone) {
|
||||
//区别,把时间转成天
|
||||
Instant firstInstant = toInstant(LocalDateTime.of(startDate.toLocalDate(), LocalTime.of(0, 0, 0)), timeZone);
|
||||
Instant finalInstant = toInstant(LocalDateTime.of(endDate.toLocalDate(), LocalTime.of(0, 0, 0)), timeZone);
|
||||
//补时间点--规则一样
|
||||
return fullFillRule(originTimeValues, firstInstant, finalInstant, timeInterval * 60 * 60 * 24);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 抽象方法,实现补充时间点
|
||||
* @param startDate 开始时间 格式如:yyyy-MM-dd 00:00:00
|
||||
* @param endDate 结束时间:格式如:yyyy-MM-dd 23:59:59
|
||||
* @param timeInterval 数据采集粒度,单位:分钟、小时、天
|
||||
* @param originTimeValues 缺少时间点对象(统一处理成long、long)
|
||||
* @param timeZone 时区
|
||||
* @return 补时间点后对象,没有补null
|
||||
*/
|
||||
public abstract List<TargetTimeValue> fullFillTimeValue(LocalDateTime startDate, LocalDateTime endDate,
|
||||
int timeInterval, List<OriginTimeValue> originTimeValues, TimeZone timeZone);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param dateTime 时间
|
||||
* @param timeZone 时区
|
||||
* @return Instant,和TimeStamp类似
|
||||
*/
|
||||
private static Instant toInstant(LocalDateTime dateTime, TimeZone timeZone) {
|
||||
return dateTime.atZone(timeZone.toZoneId())
|
||||
.toInstant();
|
||||
}
|
||||
|
||||
|
||||
private static List<TargetTimeValue> fullFillRule(List<OriginTimeValue> originTimeValues, Instant firstInstant, Instant finalInstant,
|
||||
int seconds) {
|
||||
//转换为Time-value形式的map
|
||||
if (CollectionUtils.isEmpty(originTimeValues)) {
|
||||
originTimeValues = Lists.newArrayList();
|
||||
}
|
||||
Map<Long, Long> timeValueMap = originTimeValues.stream().collect(Collectors.toMap(OriginTimeValue::getTime,
|
||||
OriginTimeValue::getValue));
|
||||
final List<TargetTimeValue> resultList = new ArrayList<>();
|
||||
|
||||
Instant cursorInstant = firstInstant;
|
||||
//循环按照时间粒度补充时间点。
|
||||
while (cursorInstant.isBefore(finalInstant) || cursorInstant.equals(finalInstant)) {
|
||||
long epochSecond = cursorInstant.getEpochSecond();
|
||||
TargetTimeValue timeValueInRule = new TargetTimeValue();
|
||||
timeValueInRule.setValue(timeValueMap.getOrDefault(epochSecond, null));
|
||||
timeValueInRule.setTime(epochSecond);
|
||||
resultList.add(timeValueInRule);
|
||||
|
||||
//移动到下一个数据点
|
||||
cursorInstant = cursorInstant.plusSeconds(seconds);
|
||||
}
|
||||
//按时间排序,最新的排在最后面
|
||||
return resultList.parallelStream()
|
||||
.sorted(Comparator.comparing(TargetTimeValue::getTime))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package util.transform;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParseException;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author: 志军
|
||||
* @description: json对象转java对象,java对象转json
|
||||
* @date: 2017/12/25 18:01
|
||||
*/
|
||||
public class JsonBinder {
|
||||
|
||||
|
||||
public static <T> T fromJson(String json, Class<T> type) {
|
||||
try {
|
||||
ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().build();
|
||||
return objectMapper.readValue(json, type);
|
||||
} catch (JsonParseException | JsonMappingException e) {
|
||||
throw new RuntimeException("JsonParseException | JsonMappingException 错误", e);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("IOException 错误", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String toJson(Object object) {
|
||||
try {
|
||||
ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().build();
|
||||
return objectMapper.writeValueAsString(object);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException("对象转换为json字符串失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package util.transform;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Marshaller;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* Xml的转换需要在对象的class上加上@XmlRootElement注释,在属性上加上@XmlElement注释
|
||||
* @author 志军
|
||||
* {@XmlRootElement(name = "xml")
|
||||
* @XmlAccessorType(XmlAccessType.FIELD)
|
||||
* static class JsonObject {
|
||||
* @XmlElement(name = "x1")
|
||||
* int x1;
|
||||
* @XmlElement(name = "x2")
|
||||
* String x2;
|
||||
* @XmlElement(name = "x3")
|
||||
* JsonObject x3;
|
||||
* get..set...
|
||||
* }
|
||||
*
|
||||
*/
|
||||
public class XmlBinder {
|
||||
|
||||
|
||||
/**
|
||||
* 将对象转化成xml字符串
|
||||
*/
|
||||
static String convertToXml(Object object) {
|
||||
//创建输出流
|
||||
StringWriter writer = new StringWriter();
|
||||
|
||||
try {
|
||||
Marshaller marshaller = getMarshaller(object);
|
||||
marshaller.marshal(object, writer);
|
||||
} catch (JAXBException e) {
|
||||
throw new RuntimeException("解析错误", e);
|
||||
}
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将对象转换为xml文件
|
||||
*/
|
||||
static void convertToXml(Object object, String path){
|
||||
FileWriter writer;
|
||||
try {
|
||||
Marshaller marshaller = getMarshaller(object);
|
||||
writer = new FileWriter(path);
|
||||
marshaller.marshal(object,writer);
|
||||
} catch (JAXBException | IOException e) {
|
||||
throw new RuntimeException("转换失败",e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串形式的xml转化成对象
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
static <T> T convertXmlStrToObject(String xml, Class<T> clazz){
|
||||
T xmlObject = null;
|
||||
try {
|
||||
Unmarshaller unmarshaller = getUnmarshaller(clazz);
|
||||
StringReader reader = new StringReader(xml);
|
||||
xmlObject = (T)unmarshaller.unmarshal(reader);
|
||||
} catch (JAXBException e) {
|
||||
throw new RuntimeException("解析错误", e);
|
||||
}
|
||||
return xmlObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从文件中转换出类
|
||||
*/
|
||||
public static Object convertXmlFileToObject(String path,Class clazz){
|
||||
try {
|
||||
Unmarshaller unmarshaller = getUnmarshaller(clazz);
|
||||
FileReader reader = new FileReader(path);
|
||||
return unmarshaller.unmarshal(reader);
|
||||
} catch (JAXBException | FileNotFoundException e) {
|
||||
throw new RuntimeException("解析错误", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 公共方法 --得到JAXB用于对象转化为xml
|
||||
*/
|
||||
private static Marshaller getMarshaller(Object object) throws JAXBException {
|
||||
//利用java的类生成实例
|
||||
JAXBContext jaxbContext = JAXBContext.newInstance(object.getClass());
|
||||
Marshaller marshaller = jaxbContext.createMarshaller();
|
||||
//格式化xml输出格式 --格式化
|
||||
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
|
||||
marshaller.setProperty(Marshaller.JAXB_ENCODING,"UTF-8");
|
||||
return marshaller;
|
||||
}
|
||||
|
||||
/**
|
||||
* 公共方法 --得到JAXB用于xml转化为对象
|
||||
*/
|
||||
private static Unmarshaller getUnmarshaller(Class clazz) throws JAXBException {
|
||||
JAXBContext context = JAXBContext.newInstance(clazz);
|
||||
return context.createUnmarshaller();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* @(#) TreeNode
|
||||
* 版权声明 网宿科技, 版权所有 违者必究
|
||||
*
|
||||
* <br> Copyright: Copyright (c) 2019
|
||||
* <br> Company:网宿科技
|
||||
* <br> @author Administrator
|
||||
* <br> @description 功能描述
|
||||
* <br> 2019-01-02 22:24:56
|
||||
*/
|
||||
|
||||
package util.tree;
|
||||
|
||||
/**
|
||||
* 树节点,主要是包含了path和parentCode的通用属性
|
||||
* @author 黄志军
|
||||
*/
|
||||
public class TreeNode {
|
||||
|
||||
/**
|
||||
* 当前节点的标识,code
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 父节点标识
|
||||
*/
|
||||
private String parentCode;
|
||||
|
||||
/**
|
||||
* 包含所有节点的code,包括自己
|
||||
* 比如说该节点为1,父节点为2,爷爷节点为3,网上根节点保存的是4.
|
||||
* path保存的就是4;3;2;1;
|
||||
*/
|
||||
private String path;
|
||||
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getParentCode() {
|
||||
return parentCode;
|
||||
}
|
||||
|
||||
public void setParentCode(String parentCode) {
|
||||
this.parentCode = parentCode;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package util.tree;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 这个对象主要用于处理从父推子的一条链路的处理
|
||||
* @author 黄志军
|
||||
*/
|
||||
public class TreeNode2 {
|
||||
|
||||
/**
|
||||
* 当前节点的标识,code
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 父节点标识
|
||||
*/
|
||||
private String parentCode;
|
||||
|
||||
/**
|
||||
* 子节点对象数组
|
||||
*/
|
||||
private List<TreeNode2> childNodeList;
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getParentCode() {
|
||||
return parentCode;
|
||||
}
|
||||
|
||||
public void setParentCode(String parentCode) {
|
||||
this.parentCode = parentCode;
|
||||
}
|
||||
|
||||
public List<TreeNode2> getChildNodeList() {
|
||||
return childNodeList;
|
||||
}
|
||||
|
||||
public void setChildNodeList(List<TreeNode2> childNodeList) {
|
||||
this.childNodeList = childNodeList;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* @(#) TreeUtils
|
||||
* 版权声明 网宿科技, 版权所有 违者必究
|
||||
*
|
||||
* <br> Copyright: Copyright (c) 2019
|
||||
* <br> Company:网宿科技
|
||||
* <br> @author Administrator
|
||||
* <br> @description 功能描述
|
||||
* <br> 2019-01-02 22:24:06
|
||||
*/
|
||||
|
||||
package util.tree;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 树数据的操作工具
|
||||
* 参考SI,兰姐,导入业务(参考ws的业务)
|
||||
* @author 黄志军
|
||||
*/
|
||||
class TreeUtils {
|
||||
|
||||
private static final String SEMICOLON = ";";
|
||||
|
||||
/**
|
||||
* 获取path的值(从根节点到当前节点的路径值),这边这个方法会对对应的code进行path的生成(前提是根节点的parentCode是空,或者用其他的标识也可以)
|
||||
*
|
||||
* @param treeNodeList 所有的树节点,因为这个主要是导入业务,所以数据包含文件和数据库中的
|
||||
* @param code 节点code
|
||||
* @return 从根节点到当前节点的路径值
|
||||
*/
|
||||
static String getCodePath(List<TreeNode> treeNodeList, String code) {
|
||||
//对所有的节点进行校验,校验规则是不能存在两个code一样的节点
|
||||
validTreeNodeList(treeNodeList);
|
||||
Map<String, TreeNode> treeNodeMap = Maps.newHashMap();
|
||||
//创建 code-节点的键值对关系
|
||||
treeNodeList.forEach(treeNode -> treeNodeMap.put(treeNode.getCode(), treeNode));
|
||||
//通过 递归函数 获取父节点以上的path关系
|
||||
StringBuffer pathStringBuffer = findParentCodes(treeNodeMap, code);
|
||||
//把父节点code和节点code拼接进去,如果这边本身就不存在这个code,就直接返回空,而不把这个code进行append
|
||||
if(treeNodeMap.get(code)!=null){
|
||||
pathStringBuffer.append(SEMICOLON).append(code).append(SEMICOLON);
|
||||
}
|
||||
return pathStringBuffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param treeNodeMap code-节点信息的map
|
||||
* @param code 节点信息(这个code是作为递归的起点)
|
||||
* @return 该节点父节点以上的path字符串
|
||||
*/
|
||||
private static StringBuffer findParentCodes(Map<String, TreeNode> treeNodeMap, String code) {
|
||||
StringBuffer result = new StringBuffer();
|
||||
TreeNode treeNode = treeNodeMap.get(code);
|
||||
//如果当前节点不为空。往下查找他的父节点
|
||||
if (treeNode != null) {
|
||||
TreeNode parentTreeNode = treeNodeMap.get(treeNode.getParentCode());
|
||||
//如果父节点不为空
|
||||
if (parentTreeNode != null) {
|
||||
//把父节点的code插入到最前面。
|
||||
result.insert(0, SEMICOLON + parentTreeNode.getCode());
|
||||
//通过递归,把父节点上面的节点找出来
|
||||
result.insert(0, findParentCodes(treeNodeMap, parentTreeNode.getCode()));
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
//直到当前节点为空,返回拼接的字符串
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static TreeNode2 getTreeWithChildNodeList(List<TreeNode2> treeNodeList ,String code){
|
||||
TreeNode2 destNode = validTreeNode2List(treeNodeList,code);
|
||||
if (destNode == null ){
|
||||
return null;
|
||||
}
|
||||
Map<String, List<TreeNode2>> treeNodeMap = Maps.newHashMap();
|
||||
//创建 父code-节点的键值对关系
|
||||
treeNodeList.forEach(treeNode -> {
|
||||
List<TreeNode2> list = treeNodeMap.get(treeNode.getParentCode());
|
||||
if (list == null ){
|
||||
list = Lists.newArrayList();
|
||||
}
|
||||
list.add(treeNode);
|
||||
treeNodeMap.put(treeNode.getParentCode(),list);
|
||||
});
|
||||
//通过 递归函数 获取父节点以上的path关系
|
||||
destNode.setChildNodeList(getChildNodeList(treeNodeMap,code));
|
||||
return destNode;
|
||||
}
|
||||
|
||||
private static List<TreeNode2> getChildNodeList( Map<String, List<TreeNode2>> treeNodeMap, String code) {
|
||||
List<TreeNode2> list = treeNodeMap.get(code);
|
||||
if( list == null || CollectionUtils.isEmpty(list)){
|
||||
return null;
|
||||
}
|
||||
for(TreeNode2 treeNode2:list){
|
||||
treeNode2.setChildNodeList(getChildNodeList(treeNodeMap,treeNode2.getCode()));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
private static void validTreeNodeList(List<TreeNode> treeNodeList){
|
||||
List<String> codeList = treeNodeList.stream().map(TreeNode::getCode).distinct().collect(Collectors.toList());
|
||||
if(codeList.size() != treeNodeList.size()){
|
||||
throw new RuntimeException("存在相同的code");
|
||||
}
|
||||
}
|
||||
|
||||
private static TreeNode2 validTreeNode2List(List<TreeNode2> treeNodeList,String code){
|
||||
List<String> codeList = treeNodeList.stream().map(TreeNode2::getCode).distinct().collect(Collectors.toList());
|
||||
if(codeList.size() != treeNodeList.size()){
|
||||
throw new RuntimeException("存在相同的code");
|
||||
}
|
||||
List<TreeNode2> list = treeNodeList.stream().filter(item->item.getCode().equals(code)).collect(Collectors.toList());
|
||||
return CollectionUtils.isEmpty(list) ?null:list.get(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package util.zip;
|
||||
|
||||
import org.springframework.util.StopWatch;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
class PrintTool {
|
||||
|
||||
static void calculateTimeAndLength(File[] files, StopWatch stopWatch, File resultFile){
|
||||
//计算一下文件的大小
|
||||
double length = 0.0000;
|
||||
|
||||
for (File file : files) {
|
||||
length = length + file.length();
|
||||
}
|
||||
|
||||
System.out.println(
|
||||
"文件大小:" + length / 1024.00 / 1024.00 + "M,转换时间:" + stopWatch.getTotalTimeMillis() / 1000.000 + " s," + "压缩后文件大小:" + resultFile
|
||||
.length() / 1024.00 / 1024.00 + " M");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
package util.zip;
|
||||
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
|
||||
import org.apache.commons.compress.utils.IOUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.StopWatch;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import static util.zip.PrintTool.calculateTimeAndLength;
|
||||
|
||||
/**
|
||||
* 总体思路
|
||||
* 1.将文件列表传入,通过tarArchiveOutputStream打包
|
||||
* 2.将tarArchiveOutputStream打包的文件,通过GZIPOutputStream进行压缩
|
||||
*
|
||||
* @author selfImpr
|
||||
* 参考地址:https://www.cnblogs.com/guochunyi/p/5311261.html
|
||||
*/
|
||||
public class TarArchiveGZIPOutputUtil {
|
||||
|
||||
/**
|
||||
* 设定读入缓冲区尺寸
|
||||
*/
|
||||
private static final byte[] BUF = new byte[1024];
|
||||
|
||||
private static final int BUF_SIZE = 1024;
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(TarArchiveGZIPOutputUtil.class);
|
||||
|
||||
private static final String GZ_SUFFIX = ".gz";
|
||||
|
||||
|
||||
/**
|
||||
* 根据传入的文件夹位置,打包对应的所有文件
|
||||
* @param dirPath 文件夹位置
|
||||
* @param zipFilePath 生成gz文件的位置
|
||||
* @return .tar.gz文件
|
||||
* @throws IOException io异常
|
||||
*/
|
||||
static File compress(String dirPath, String zipFilePath) throws IOException {
|
||||
StopWatch stopWatch = new StopWatch();
|
||||
stopWatch.start();
|
||||
|
||||
File dir = new File(dirPath);
|
||||
if (dir.exists() && dir.isDirectory()) {
|
||||
//遍历文件夹的所有文件
|
||||
File[] files = dir.listFiles();
|
||||
assert files != null;
|
||||
return compress(Arrays.asList(files), zipFilePath);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 压缩成gzip格式,最后的文件格式为 tar.gz
|
||||
*
|
||||
* @param files 文件
|
||||
* @param tarPath 存储位置
|
||||
* @throws IOException Io异常
|
||||
* @return tar.gz结尾的文件
|
||||
*/
|
||||
static File compress(List<File> files, String tarPath) throws IOException {
|
||||
StopWatch stopWatch = new StopWatch();
|
||||
stopWatch.start();
|
||||
//先进行打包
|
||||
packToTar(tarPath, files);
|
||||
//在进行压缩
|
||||
File file = compressToGz(tarPath);
|
||||
stopWatch.stop();
|
||||
|
||||
//输出文件大小和运行时间
|
||||
calculateTimeAndLength(files.toArray(new File[]{}),stopWatch,file);
|
||||
return file;
|
||||
}
|
||||
|
||||
/**
|
||||
* 只打包成tar文件,最后的格式为.tar
|
||||
*
|
||||
* @param files 文件
|
||||
* @param tarPath 存储位置
|
||||
* @throws IOException Io异常
|
||||
* @return tar结尾的文件
|
||||
*/
|
||||
static File compressToTar(List<File> files, String tarPath) throws IOException {
|
||||
StopWatch stopWatch = new StopWatch();
|
||||
stopWatch.start();
|
||||
//先进行打包
|
||||
File file = packToTar(tarPath, files);
|
||||
stopWatch.stop();
|
||||
//输出文件大小和运行时间
|
||||
calculateTimeAndLength(files.toArray(new File[]{}),stopWatch,file);
|
||||
return file;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据地址找到所有的文件进行打包
|
||||
* @param dirPath 文件夹位置
|
||||
* @param tarFilePath 生成tar文件位置
|
||||
* @return .tar文件
|
||||
* @throws IOException io异常
|
||||
*/
|
||||
static File compressToTar(String dirPath, String tarFilePath) throws IOException {
|
||||
StopWatch stopWatch = new StopWatch();
|
||||
stopWatch.start();
|
||||
|
||||
File dir = new File(dirPath);
|
||||
if (dir.exists() && dir.isDirectory()) {
|
||||
//遍历文件夹的所有文件
|
||||
File[] files = dir.listFiles();
|
||||
assert files != null;
|
||||
return compressToTar(Arrays.asList(files), tarFilePath);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 打包成tar格式
|
||||
*
|
||||
* @param tarPath 存储位置 这边传入的存储地址必须是.tar结尾的才会被转换成对应的格式,否则转换出来需要自己去重命名
|
||||
* @param files 文件
|
||||
* @throws IOException io异常
|
||||
* @return 返回打包对应的文件对象
|
||||
*/
|
||||
private static File packToTar(String tarPath, List<File> files) throws IOException {
|
||||
//建立压缩文件输出流
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(tarPath);
|
||||
TarArchiveOutputStream tarArchiveOutputStream = new TarArchiveOutputStream(fileOutputStream);
|
||||
FileInputStream fin = null;
|
||||
try {
|
||||
//建立tar压缩输出流
|
||||
for (File file : files) {
|
||||
//打开需压缩文件作为文件输入流
|
||||
fin = new FileInputStream(file);
|
||||
TarArchiveEntry tarEn = new TarArchiveEntry(file);
|
||||
//此处需重置名称,默认是带全路径的,否则打包后会带全路径
|
||||
tarEn.setName(file.getName());
|
||||
tarArchiveOutputStream.putArchiveEntry(tarEn);
|
||||
//IOUtils只是写入
|
||||
IOUtils.copy(fin, tarArchiveOutputStream);
|
||||
tarArchiveOutputStream.closeArchiveEntry();
|
||||
fin.close();
|
||||
}
|
||||
tarArchiveOutputStream.close();
|
||||
return new File(tarPath);
|
||||
} catch (IOException ex) {
|
||||
LOGGER.info("", ex);
|
||||
} finally {
|
||||
if (fin != null) {
|
||||
fin.close();
|
||||
}
|
||||
fileOutputStream.close();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 压缩成GZIP格式
|
||||
*
|
||||
* @param tarPath 压缩路径
|
||||
* @throws IOException 压缩失败,文件路径找不到
|
||||
*/
|
||||
private static File compressToGz(String tarPath) throws IOException {
|
||||
//建立压缩文件输出流
|
||||
String zipPath = tarPath + GZ_SUFFIX;
|
||||
FileOutputStream gzFileOutputStream = new FileOutputStream(zipPath);
|
||||
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(gzFileOutputStream);
|
||||
FileInputStream tarFileInputStream = new FileInputStream(tarPath);
|
||||
try {
|
||||
//建立gzip压缩输出流,这个不能使用IOUtils的copy,可以具体看一下方法
|
||||
int len;
|
||||
while ((len = tarFileInputStream.read(BUF, 0, BUF_SIZE)) != -1) {
|
||||
gzipOutputStream.write(BUF, 0, len);
|
||||
}
|
||||
gzipOutputStream.close();
|
||||
return new File(zipPath);
|
||||
} catch (IOException e) {
|
||||
LOGGER.info("e");
|
||||
} finally {
|
||||
gzFileOutputStream.close();
|
||||
tarFileInputStream.close();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
|
||||
|
||||
package util.zip;
|
||||
|
||||
import org.apache.commons.compress.utils.IOUtils;
|
||||
import org.springframework.util.StopWatch;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import static util.zip.PrintTool.calculateTimeAndLength;
|
||||
|
||||
/**
|
||||
* 压缩成ZIP文件,这边主要是通过 zipOutputStream 这个类进行对应的实现,所以其实也算是一个使用的实现例子
|
||||
* @author 黄志军
|
||||
*/
|
||||
class ZipOutputUtil {
|
||||
/**
|
||||
* @param originPath 此方法只压缩文件夹
|
||||
* @param zipFilePath 压缩文件的路径
|
||||
* @return 压缩之后的文件对象
|
||||
*/
|
||||
static File compress(String originPath, String zipFilePath) throws IOException {
|
||||
StopWatch stopWatch = new StopWatch();
|
||||
stopWatch.start();
|
||||
|
||||
File dir = new File(originPath);
|
||||
if (dir.exists() && dir.isDirectory()) {
|
||||
//遍历文件夹的所有文件
|
||||
File[] files = dir.listFiles();
|
||||
assert files != null;
|
||||
//进行ZipOutputStream的压缩操作
|
||||
File file = compress(files, zipFilePath);
|
||||
stopWatch.stop();
|
||||
//输出文件大小和运行时间
|
||||
calculateTimeAndLength(files,stopWatch,file);
|
||||
return file;
|
||||
}
|
||||
System.out.println("文件夹不存在或者非文件夹");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private static File compress(File[] files, String zipFilePath) throws IOException {
|
||||
File zipFile = new File(zipFilePath);
|
||||
// 文件输出流
|
||||
FileOutputStream outputStream = new FileOutputStream(zipFile);
|
||||
// 压缩流
|
||||
ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);
|
||||
for (File file : files) {
|
||||
FileInputStream inputStream = new FileInputStream(file);
|
||||
ZipEntry zipEntry = new ZipEntry(file.getName());
|
||||
zipOutputStream.putNextEntry(zipEntry);
|
||||
IOUtils.copy(inputStream, zipOutputStream);
|
||||
inputStream.close();
|
||||
zipOutputStream.closeEntry();
|
||||
}
|
||||
zipOutputStream.close();
|
||||
outputStream.close();
|
||||
return zipFile;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user