This commit is contained in:
赵东海 2020-10-23 17:09:46 +08:00
parent 3460a0f5df
commit e6904a058a
19 changed files with 2767 additions and 0 deletions

48
pom.xml Normal file
View File

@ -0,0 +1,48 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.sinosoft</groupId>
<artifactId>cloud-plus</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>cloud-plus-common</artifactId>
<packaging>jar</packaging>
<name>cloud-plus-common</name>
<description>cloud-plus-公共组件</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-bean-validators</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutz</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,168 @@
package com.sinosoft.cloud.plus.dto;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.nutz.json.Json;
import org.nutz.json.JsonFormat;
import org.nutz.lang.util.NutMap;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Builder.Default;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author zhaodonghai@sinosoft.com.cn
* @since 2020-10-23
* @param <T>
* 数据泛型
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> {
/**
* @author zhaodonghai@sinosoft.com.cn
* @since 2020-10-23
*/
public enum OperationState {
/**
* 成功
*/
SUCCESS,
/**
* 失败
*/
FAIL,
/**
* 异常
*/
EXCEPTION;
}
@Default
@ApiModelProperty(value = "响应扩展数据", required = false)
private NutMap ext = new NutMap();
@Default
@ApiModelProperty(value = "响应状态", required = true)
private OperationState state = OperationState.SUCCESS;
@ApiModelProperty(value = "错误信息列表")
private String[] errors;
@ApiModelProperty(value = "响应数据", required = true)
private T data;
/**
* 返回成功
*
* @return 成功的结果
*/
@SuppressWarnings("rawtypes")
public static Result success() {
return Result.builder().build();
}
/**
* 携带数据返回成功
*
* @param <T>
* 数据泛型
* @param t
* 数据
* @return 成功的结果
*/
public static <T> Result<T> success(T t) {
return Result.<T> builder().data(t).build();
}
/**
* 返回失败及原因
*
* @param errors
* 失败原因
* @return 失败的结果
*/
@SuppressWarnings("rawtypes")
public static Result fail(String... errors) {
return Result.builder().state(OperationState.FAIL).errors(errors).build();
}
/**
* 返回异常及原因
*
* @param errors
* 异常原因
* @return 异常的结果
*/
@SuppressWarnings("rawtypes")
public static Result exception(String... errors) {
return Result.builder().state(OperationState.EXCEPTION).errors(errors).build();
}
/**
* 返回异常及原因
*
* @param errors
* 异常原因
* @return 异常的结果
*/
@SuppressWarnings("rawtypes")
public static Result exception(List<String> errors) {
return Result.builder().state(OperationState.EXCEPTION).errors(errors.toArray(new String[errors.size()])).build();
}
/**
* 返回异常及原因
*
* @param exceptions
* 异常
* @return 异常的结果
*/
@SuppressWarnings("rawtypes")
public static Result exception(Throwable... exceptions) {
return exception(Arrays.stream(exceptions).map(Throwable::getMessage).collect(Collectors.toList()));
}
/**
* 添加扩展数据
*
* @param key
* 数据key
* @param value
* 数据
* @return 返回结果对象
*/
@SuppressWarnings("rawtypes")
public Result addExtData(String key, Object value) {
getExt().setv(key, value);
return this;
}
/**
* 是否成功
*
* @return 是否成功标识
*/
public boolean isSuccess() {
return getState() == OperationState.SUCCESS;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return Json.toJson(this, JsonFormat.forLook());
}
}

View File

@ -0,0 +1,113 @@
package com.sinosoft.cloud.plus.utils;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.repo.Base64;
/**
* @author zhaodonghai@sinosoft.com.cn
* @since 2020-10-23
*/
public class AES {
private AES() {}
public static final String AES_NAME = "AES";
public static final String CHER_SET = "UTF-8";
public static final String DEFAULT_KEY = "EBD0B5D2-F4E7-453A-9E16-01AE8F6E2977";
private static Log log = Logs.get();
/**
* 使用默认密钥加密
*
* @param sSrc
* 明文
* @return 密文
*/
public static String encrypt(String sSrc) {
return encrypt(sSrc, DEFAULT_KEY);
}
/**
* 加密
*
* @param sSrc
* 明文
* @param sKey
* 密钥
* @return 密文
*/
public static String encrypt(String sSrc, String sKey) {
try {
if (sKey == null) {
log.error("key 不能为空!");
return null;
}
// 判断Key是否为16位
if (sKey.length() != 16) {
log.error("key 长度不是16位");
return null;
}
byte[] raw = sKey.getBytes(CHER_SET);
SecretKeySpec skeySpec = new SecretKeySpec(raw, AES_NAME);
Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5Padding");// "算法/模式/补码方式"
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(sSrc.getBytes(CHER_SET));
return Base64.encodeToString(encrypted, false);
}
catch (Exception e) {
log.error(e);
return null;
}
}
/**
* 解密(使用默认密钥)
*
* @param sSrc
* 密文
* @return 明文
*/
public static String decrypt(String sSrc) {
return decrypt(sSrc, DEFAULT_KEY);
}
/**
* 解密
*
* @param sSrc
* 密文
* @param sKey
* 密钥
* @return 明文
*/
public static String decrypt(String sSrc, String sKey) {
try {
if (sKey == null) {
log.error("key 不能为空!");
return null;
}
if (sKey.length() != 16) {
log.error("key 长度不是16位");
return null;
}
byte[] raw = sKey.getBytes(CHER_SET);
SecretKeySpec skeySpec = new SecretKeySpec(raw, AES_NAME);
Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] encrypted1 = Base64.decode(sSrc);// 先用base64解密
byte[] original = cipher.doFinal(encrypted1);
return new String(original, CHER_SET);
}
catch (Exception e) {
log.error(e);
return null;
}
}
}

View File

@ -0,0 +1,164 @@
package com.sinosoft.cloud.plus.utils;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* @author zhaodonghai@sinosoft.com.cn
* @since 2020-10-23
*/
public class Ariths {
private static final int DEF_DIV_SCALE = 10;
/**
* 提供精确的加法运算
*
* @param v1
* 被加数
* @param v2
* 加数
* @return 两个参数的和
*/
public static double add(double v1, double v2) {
BigDecimal b1 = BigDecimal.valueOf(v1);
BigDecimal b2 = BigDecimal.valueOf(v2);
return b1.add(b2).doubleValue();
}
/**
* 提供相对精确的除法运算当发生除不尽的情况时精确到 小数点以后10位以后的数字四舍五入
*
* @param v1
* 被除数
* @param v2
* 除数
* @return 两个参数的商
*/
public static double div(double v1, double v2) {
return div(v1, v2, DEF_DIV_SCALE);
}
/**
* 提供相对精确的除法运算当发生除不尽的情况时由scale参数指 定精度以后的数字四舍五入
*
* @param v1
* 被除数
* @param v2
* 除数
* @param scale
* 表示表示需要精确到小数点以后几位
* @return 两个参数的商
*/
public static double div(double v1, double v2, int scale) {
if (scale < 0) {
throw new ScaleMustBePositiveIntegerOrZeroException();
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue();
}
public static class ScaleMustBePositiveIntegerOrZeroException extends IllegalArgumentException {
private static final long serialVersionUID = 1L;
/**
*
*/
public ScaleMustBePositiveIntegerOrZeroException() {
super("The scale must be a positive integer or zero");
}
}
/**
* 提供精确的乘法运算
*
* @param v1
* 被乘数
* @param v2
* 乘数
* @return 两个参数的积
*/
public static double mul(double v1, double v2) {
BigDecimal b1 = BigDecimal.valueOf(v1);
BigDecimal b2 = BigDecimal.valueOf(v2);
return b1.multiply(b2).doubleValue();
}
/**
* 提供精确的乘法运算
*
* @param v1
* 被乘数
* @param v2
* 乘数
* @return 两个参数的积的int表示
*/
public static int mulToInt(double v1, double v2) {
BigDecimal b1 = BigDecimal.valueOf(v1);
BigDecimal b2 = BigDecimal.valueOf(v2);
return b1.multiply(b2).intValue();
}
/**
* 提供精确的小数位四舍五入处理
*
* @param v
* 需要四舍五入的数字
* @param scale
* 小数点后保留几位
* @return 四舍五入后的结果
*/
public static double round(double v, int scale) {
if (scale < 0) {
throw new ScaleMustBePositiveIntegerOrZeroException();
}
BigDecimal b = new BigDecimal(Double.toString(v));
BigDecimal one = new BigDecimal("1");
return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue();
}
/**
* 提供精确的小数位四舍五入处理
*
* @param v
* 需要四舍五入的数字
* @param scale
* 小数点后保留几位
* @param mode
* 进位模式
* @return 结果
*/
public static double round(double v, int scale, RoundingMode mode) {
if (scale < 0) {
throw new ScaleMustBePositiveIntegerOrZeroException();
}
BigDecimal b = BigDecimal.valueOf(v);
BigDecimal one = BigDecimal.valueOf(1);
return b.divide(one, scale, mode).doubleValue();
}
/**
* 提供精确的减法运算
*
* @param v1
* 被减数
* @param v2
* 减数
* @return 两个参数的差
*/
public static double sub(double v1, double v2) {
BigDecimal b1 = BigDecimal.valueOf(v1);
BigDecimal b2 = BigDecimal.valueOf(v2);
return b1.subtract(b2).doubleValue();
}
private Ariths() {}
}

View File

@ -0,0 +1,72 @@
package com.sinosoft.cloud.plus.utils;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Supplier;
/**
* @author zhaodonghai@sinosoft.com.cn
* @since 2020-10-23
*/
public class Builder<T> {
private final Supplier<T> instantiator;
private List<Consumer<T>> modifiers = new ArrayList<>();
public Builder(Supplier<T> instantiator) {
this.instantiator = instantiator;
}
public static <T> Builder<T> of(Supplier<T> instantiator) {
return new Builder<>(instantiator);
}
public <P1> Builder<T> with(Consumer1<T, P1> consumer, P1 p1) {
Consumer<T> c = instance -> consumer.accept(instance, p1);
modifiers.add(c);
return this;
}
public <P1, P2> Builder<T> with(Consumer2<T, P1, P2> consumer, P1 p1, P2 p2) {
Consumer<T> c = instance -> consumer.accept(instance, p1, p2);
modifiers.add(c);
return this;
}
public <P1, P2, P3> Builder<T> with(Consumer3<T, P1, P2, P3> consumer, P1 p1, P2 p2, P3 p3) {
Consumer<T> c = instance -> consumer.accept(instance, p1, p2, p3);
modifiers.add(c);
return this;
}
public T build() {
T value = instantiator.get();
modifiers.forEach(modifier -> modifier.accept(value));
modifiers.clear();
return value;
}
/**
* 1 参数 Consumer
*/
@FunctionalInterface
public interface Consumer1<T, P1> {
void accept(T t, P1 p1);
}
/**
* 2 参数 Consumer
*/
@FunctionalInterface
public interface Consumer2<T, P1, P2> {
void accept(T t, P1 p1, P2 p2);
}
/**
* 3 参数 Consumer
*/
@FunctionalInterface
public interface Consumer3<T, P1, P2, P3> {
void accept(T t, P1 p1, P2 p2, P3 p3);
}
}

View File

@ -0,0 +1,149 @@
package com.sinosoft.cloud.plus.utils;
import java.util.ArrayList;
import java.util.List;
import org.nutz.lang.Lang;
/**
* @author zhaodonghai@sinosoft.com.cn
* @since 2020-10-23
*/
public class CharSequence {
/**
* 解码
*
* @param data
* 数据数组
* @return 原数据
*/
public static String decode(Integer[] data) {
return decode(Lang.array2list(data));
}
/**
* 解码
*
* @param data
* 数据list
* @return 原数据
*/
public static String decode(List<Integer> data) {
return new CharSequence(data).toString();
}
/**
* 解码
*
* @param data
* 数据串 ',' 分隔
* @return 原数据
*/
public static String decode(String data) {
List<Integer> value = parse(data);
return decode(value);
}
/**
* NB解码
*
* @param data
* 数据
* @param times
* 次数
* @return 解码结果
*/
public static String decode(String data, int times) {
String target = data;
String cache = null;
for (int i = 0; i < times; i++) {
try {
target = decode(target);
}
catch (Exception e) {
return cache;
}
cache = target;
}
return target;
}
/**
* 编码
*
* @param info
* 带编码字符串
* @return 编码结果串
*/
public static List<Integer> encode(String info) {
return new CharSequence(info).getValue();
}
/**
* 编码成串
*
* @param info
* 数据
* @return 返回串
*/
public static String encodeToString(String info) {
StringBuilder builder = new StringBuilder();
for (Integer i : encode(info)) {
builder.append(i + ",");
}
if (builder.length() == 0) {
return "";
}
return builder.substring(0, builder.length() - 1);
}
/**
* 编码成串
*
* @param info
* 数据
* @param times
* 次数
* @return 返回串
*/
public static String encodeToString(String info, int times) {
String target = info;
for (int i = 0; i < times; i++) {
target = encodeToString(target);
}
return target;
}
private static List<Integer> parse(String data) {
List<Integer> target = new ArrayList<>();
String[] infos = data.split(",");
for (String info : infos) {
target.add(Integer.parseInt(info.trim()));
}
return target;
}
private List<Integer> value = new ArrayList<>();
private String stringValue;
public CharSequence(List<Integer> value) {
this.value = value;
this.stringValue = toString();
}
private CharSequence(String in) {
for (char c : in.toCharArray()) {
value.add((int) c);
}
this.stringValue = in;
}
public String getStringValue() {
return stringValue;
}
public List<Integer> getValue() {
return value;
}
}

View File

@ -0,0 +1,137 @@
package com.sinosoft.cloud.plus.utils;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.repo.Base64;
/**
* @author zhaodonghai@sinosoft.com.cn
* @since 2020-10-23
*/
public class DES {
private DES() {
}
private static final String DES_NAME = "DES";
public static final String DEFAULT_KEY = "abcdefgh";
private static Log log = Logs.get();
public static String encrypt(String data) {
return encrypt(data, DEFAULT_KEY);
}
public static String decrypt(String data) {
return decrypt(data, DEFAULT_KEY);
}
/**
* Description 根据键值进行加密
*
* @param data 数据
* @param key 加密键byte数组
* @return 密文
*/
public static String encrypt(String data, String key) {
byte[] bt = null;
try {
bt = encrypt(data.getBytes(), key.getBytes());
} catch (Exception e) {
log.error(e);
}
return Base64.encodeToString(bt, false);
}
/**
* Description 根据键值进行解密
*
* @param data 数据
* @param key 加密键byte数组
* @return 明文
*/
public static String decrypt(String data, String key) {
if (data == null)
{return null;}
byte[] buf = Base64.decode(data);
byte[] bt = null;
try {
bt = decrypt(buf, key.getBytes());
} catch (Exception e) {
log.error(e);
}
return new String(bt);
}
/**
* Description 根据键值进行加密
*
* @param data 数据
* @param key 加密键byte数组
* @return 密文
* @throws InvalidKeyException
* @throws NoSuchAlgorithmException
* @throws NoSuchPaddingException
* @throws InvalidKeySpecException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
*/
private static byte[] encrypt(byte[] data, byte[] key) throws InvalidKeyException, NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException {
SecureRandom sr = new SecureRandom();
DESKeySpec dks = new DESKeySpec(key);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES_NAME);
SecretKey securekey = keyFactory.generateSecret(dks);
Cipher cipher = Cipher.getInstance(DES_NAME);
cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);
return cipher.doFinal(data);
}
/**
* Description 根据键值进行解密
*
* @param data 数据
* @param key 加密键byte数组
* @return 明文
* @throws InvalidKeyException
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
* @throws NoSuchPaddingException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
*/
private static byte[] decrypt(byte[] data, byte[] key) throws InvalidKeyException, NoSuchAlgorithmException,
InvalidKeySpecException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
SecureRandom sr = new SecureRandom();
DESKeySpec dks = new DESKeySpec(key);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES_NAME);
SecretKey securekey = keyFactory.generateSecret(dks);
Cipher cipher = Cipher.getInstance(DES_NAME);
cipher.init(Cipher.DECRYPT_MODE, securekey, sr);
return cipher.doFinal(data);
}
}

View File

@ -0,0 +1,281 @@
package com.sinosoft.cloud.plus.utils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import org.nutz.lang.Times;
/**
* @author zhaodonghai@sinosoft.com.cn
* @since 2020-10-23
*/
public class DateUtils extends Times {
public static final String DATE_FORMAT_MONTH = "yyyy-MM";
public static final String DATE_FORMAT_DAY = "yyyy-MM-dd";
/**
* 日期加减
*
* @param base
* 开始日期
* @param days
* 增加天数 正数为之后日期负数为之前日期
* @return 目标日期
*/
public static Date addDays(Date base, int days) {
return D(base.getTime() + days * 24 * 60 * 60 * 1000L);
}
/**
* 从今日开始的日期加减
*
* @param days
* 增加天数 正数为之后日期负数为之前日期
* @return 目标日期
*/
public static Date addDays(int days) {
return addDays(now(), days);
}
/**
* 两个日期之间的天数差
*
* @param start
* 开始日期
* @param end
* 结束日期
* @return 天数
*/
public static double daysBetween(Date start, Date end) {
return BigDecimal.valueOf((end.getTime() - start.getTime()) / 1000.0d / 24.0d / 60.0d / 60.0d)
.setScale(0, RoundingMode.HALF_UP)
.doubleValue();
}
/**
* 获取当日凌晨
*
* @param d
* 日期
* @return 当日凌晨 date 对象
*/
public static Date getDayStart(Date d) {
return D(format("yyyy-MM-dd 00:00:00", d));
}
public static Date getDayEnd(Date d) {
return D(format("yyyy-MM-dd 23:59:59", d));
}
/**
* 获取今日凌晨
*
* @return 今日凌晨0:0:0的时间实例
*/
public static Date getDayStart() {
return D(format("yyyy-MM-dd 00:00:00", now()));
}
public static Date getDayEnd() {
return D(format("yyyy-MM-dd 23:59:59", now()));
}
/**
* 获取当前日期的周结束(周日或者周六)
*
* @param startFromSunday
* 从周日开始计算周 标识
* @return startFromSunday 为true 则返回下一个周六 为false则返回下一个周日
*/
public static Date getWeekEnd(boolean startFromSunday) {
Date date = addDays(getWeekStart(startFromSunday), 6);
return getDayEnd(date);
}
public static Date getWeekEnd(boolean startFromSunday, Date date) {
Date newDate = addDays(getWeekStart(startFromSunday, date), 6);
return getDayEnd(newDate);
}
/**
* 获取当前日期的周开始(周一或者周日)
*
* @param startFromSunday
* 从周日开始计算周 标识
* @return startFromSunday 为true 则返回上一个周日 为false则返回上一个周一
*/
public static Date getWeekStart(boolean startFromSunday) {
return addDays(getDayStart(),
-1
* (Times.C(now()).get(Calendar.DAY_OF_WEEK)
- 1
- (startFromSunday ? 0 : 1)));
}
public static Date getWeekStart(boolean startFromSunday, Date date) {
return addDays(getDayStart(date),
-1
* (Times.C(now()).get(Calendar.DAY_OF_WEEK)
- 1
- (startFromSunday ? 0 : 1)));
}
/**
* 增加秒
*
* @param base
* 基础时间
* @param seconds
* 秒数
* @return 日期对象
*/
public static Date addSeconds(Date base, long seconds) {
return D(base.getTime() + seconds * 1000);
}
/**
* 增加秒
*
* @param seconds
* 秒数
* @return 日期对象
*/
public static Date addSeconds(long seconds) {
return addSeconds(now(), seconds);
}
/**
* 获取元旦日期
*
* @param d
* 日期
* @return 元旦日期
*/
public static Date getYearStart(Date d) {
String year = format("yyyy", d);
year += "-01-01";
return D(year);
}
/**
* 获取元旦日期
*
* @return 元旦日期
*/
public static Date getYearStart() {
return getYearStart(now());
}
/**
* 获取年末日期
*
* @param d
* 日期
* @return 年末日期
*/
public static Date getYearEnd(Date d) {
String year = format("yyyy", d);
year += "-12-31";
return getDayEnd(D(year));
}
/**
* 获取年末日期
*
* @return 年末日期
*/
public static Date getYearEnd() {
return getYearEnd(now());
}
/**
* 获取月初日期
*
* @param d
* 日期
* @return 月初日期
*/
public static Date getMonthStart(Date d) {
String month = format(DATE_FORMAT_MONTH, d) + "-01";
return D(month);
}
/**
* 获取月初日期
*
* @return 月初日期
*/
public static Date getMonthStart() {
return getMonthStart(now());
}
/**
* 获取月末日期
*
* @param d
* 日期
* @return 月末日期
*/
public static Date getMonthEnd(Date d) {
Calendar ca = Calendar.getInstance();
ca.setTime(d);
ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
return getDayEnd(ca.getTime());
}
/**
* 获取月末日期
*
* @return 月末日期
*/
public static Date getMonthEnd() {
return getMonthEnd(now());
}
// 获取时间相关序列
public static String getSequence() {
String sequence = format("yyyyMMDD", now());
sequence += ms() % 10000;
return sequence;
}
public static String getYearStartMonth() {
return format(DATE_FORMAT_MONTH, getYearStart());
}
public static String getYearStartMonth(Date date) {
return format(DATE_FORMAT_MONTH, getYearStart(date));
}
public static String getYearEndMonth() {
return format(DATE_FORMAT_MONTH, getYearEnd());
}
public static String getYearEndMonth(Date date) {
return format(DATE_FORMAT_MONTH, getYearEnd(date));
}
public static String getMonthStartDate() {
return format(DATE_FORMAT_DAY, getMonthStart());
}
public static String getMonthStartDate(Date date) {
return format(DATE_FORMAT_DAY, getMonthStart(date));
}
public static String getMonthEndDate() {
return format(DATE_FORMAT_DAY, getMonthEnd());
}
public static String getMonthEndDate(Date date) {
return format(DATE_FORMAT_DAY, getMonthEnd(date));
}
public static int getDayOfMonth() {
return Calendar.getInstance(Locale.CHINA).getActualMaximum(Calendar.DATE);
}
}

View File

@ -0,0 +1,309 @@
package com.sinosoft.cloud.plus.utils;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.DecimalFormat;
import org.nutz.lang.Files;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.log.Log;
import org.nutz.log.Logs;
/**
* @author zhaodonghai@sinosoft.com.cn
* @since 2020-10-23
*/
public class FileUtils {
private FileUtils() {}
/**
* 清除SVN
*
* @param dir
* 待清除的目录
* @return 清除成功状态标识
*/
public static boolean cleanSvn(File dir) {
try {
Files.cleanAllFolderInSubFolderes(dir, ".svn");
}
catch (IOException e) {
log.error(e.getMessage());
return false;
}
return true;
}
/**
* 清除项目下的文件
*
* @param dir
* 根目录
* @param name
* 文件名
* @throws IOException
* 删除失败时
*/
public static void cleanAllFileInSubFolderes(File dir, String name) throws IOException {
File[] files = dir.listFiles();
if (files == null)
{
return;
}
for (File d : files) {
if (!d.isDirectory() && d.getName().equalsIgnoreCase(name))
{
Files.deleteFile(d);
}
else if (d.isDirectory())
{ cleanAllFileInSubFolderes(d, name);}
}
}
/**
* 清理项目
*
* @param dir
* 项目根目录
*/
public static void cleanProject(String dir) {
cleanProject(Files.checkFile(dir), ".project", ".settings", ".idea", ".vscode", ".classpath", ".factorypath", "target");
}
/**
* 清理项目
*
* @param dir
* 项目根目录
*/
public static void cleanProject(File dir) {
cleanProject(dir, ".project", ".settings", ".idea", ".vscode", ".classpath", ".factorypath", "target");
}
/**
* 清理项目
*
* @param dir
* 项目根目录
* @param files
* 待清除文件
*/
public static void cleanProject(File dir, String... files) {
Lang.list(files).stream().forEach(item -> {
try {
Files.cleanAllFolderInSubFolderes(dir, item);
cleanAllFileInSubFolderes(dir, item);
}
catch (IOException e) {
log.error(e.getMessage());
}
});
}
/**
* 统计文件或者目录下的java代码的行数
*
* @param file
* 文件或者目录
* @return java代码行数
*/
public static long countJavaCodeLines(File file) {
return countLines(file, ".java");
}
public static double getDirSize(File file) {
if (file.exists()) {
if (file.isDirectory()) {
File[] children = file.listFiles();
double size = 0;
for (File f : children) {
size += getDirSize(f);
}
return size;
} else {
return file.length();
}
} else {
return 0.0;
}
}
/**
* 转换文件大小
*
* @param length
* 文件长度
* @return 文件大小字串描述
*/
public static String formetFileSize(double length) {
DecimalFormat df = new DecimalFormat("#.00");
String fileSizeString = "";
if (length < 1024) {
fileSizeString = df.format(length) + "B";
} else if (length < 1048576) {
fileSizeString = df.format(length / 1024) + "K";
} else if (length < 1073741824) {
fileSizeString = df.format(length / 1048576) + "M";
} else {
fileSizeString = df.format(length / 1073741824) + "G";
}
return fileSizeString;
}
/**
* 计算文件行数
*
* @param file
* 文件(非目录类型)
* @return 行数
*/
public static long countLine(File file) {
long target = 0;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)))) {
String line = null;
while ((line = reader.readLine()) != null) {
log.debug(line);
target++;
}
}
catch (IOException e) {
log.error(e.getMessage());
}
return target;
}
/**
* 统计文件或者目录下的指定类型文件的行数
*
* @param file
* 文件或者目录
* @param suf
* 扩展名
* @return 行数
*/
public static long countLines(File file, String suf) {
long target = 0;
if (file.isFile() && file.getName().endsWith(suf)) {
return countLine(file);
} else if (file.isFile()) {
return 0;
} else if (file.isDirectory()) {
File[] files = file.listFiles();
for (File f : files) {
target += countLines(f, suf);
}
}
return target;
}
/**
* 快速查找
*
* @param dir
* 基目录
* @param name
* 待查找文件名
* @return 文件
*/
public static File fastFindFile(File dir, String name) {
return fastFindFile(dir, name, 1);
}
/**
* 快速查找文件
*
* @param dir
* 基目录
* @param name
* 文件名
* @param method
* 查找方法 1 全等查询 2 模糊查找 3 忽略大小写全等 4忽略大小写模糊
* @return 文件
*/
public static File fastFindFile(File dir, String name, int method) {
File target = null;
File[] dirs = Files.dirs(dir);// 获取目录
File[] files = Files.files(dir, name);// 获取文件
// 优先扫描文件
if (files != null) {
for (File file : files) {
if (matchs(file.getName(), name, method)) {
return file;
}
}
}
// 然后扫目录
if (dirs != null) {
for (File file : dirs) {
target = fastFindFile(file, name, method);
if (target != null) {
return target;
}
}
}
return target;
}
private static boolean matchs(String fileName, String name, int method) {
switch (method) {
case 1:
return Strings.equals(fileName, name);
case 2:
return fileName.endsWith(name);
case 3:
return Strings.equals(fileName.toUpperCase(), name.toUpperCase());
default:
return fileName.toUpperCase().endsWith(name.toUpperCase());
}
}
public static File fastFindFile(String dir, String name) {
return fastFindFile(new File(dir), name, 1);
}
/**
* 快速查找
*
* @param dir
* 基目录
* @param name
* 待查找文件名
* @return 文件
*/
public static File fastFindFileLikeName(File dir, String name) {
return fastFindFile(dir, name, 2);
}
/**
* 基本实现 文件查找
*
* @param dir
* 查找的开始位置
* @param name
* 查找的文件的名字
* @return 文件
*/
public static File findFile(File dir, String name) {
File target = null;
File[] files = dir.listFiles();
if (files != null) {
for (File file : files) {
if (file.isFile() && Strings.equals(file.getName(), name)) {
return file;
} else if (file.isDirectory()) {
target = findFile(file, name);
if (target != null) {
return target;
}
}
}
}
return target;