#2 加强Utils Modules模块 Random,Hash的性能优化等

This commit is contained in:
calvin1978
2017-01-14 11:25:33 +08:00
parent 2d844ec549
commit 229baa6ca8
24 changed files with 341 additions and 155 deletions
@@ -13,7 +13,7 @@ import org.springframework.web.bind.annotation.RestController;
import org.springside.examples.bootapi.service.AccountService;
import org.springside.examples.bootapi.service.exception.ErrorCode;
import org.springside.examples.bootapi.service.exception.ServiceException;
import org.springside.modules.utils.net.MediaTypes;
import org.springside.modules.web.MediaTypes;
// Spring Restful MVC Controller的标识, 直接输出内容,不调用template引擎.
@RestController
@@ -20,8 +20,8 @@ import org.springside.examples.bootapi.service.BookAdminService;
import org.springside.examples.bootapi.service.BookBorrowService;
import org.springside.examples.bootapi.service.exception.ErrorCode;
import org.springside.examples.bootapi.service.exception.ServiceException;
import org.springside.modules.utils.net.MediaTypes;
import org.springside.modules.utils.reflect.BeanMapper;
import org.springside.modules.web.MediaTypes;
// Spring Restful MVC Controller的标识, 直接输出内容,不调用template引擎.
@RestController
@@ -16,8 +16,8 @@ import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import org.springside.examples.bootapi.service.exception.ServiceException;
import org.springside.modules.utils.net.MediaTypes;
import org.springside.modules.utils.text.JsonMapper;
import org.springside.modules.web.MediaTypes;
import com.google.common.collect.Maps;
@@ -15,8 +15,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springside.modules.utils.net.MediaTypes;
import org.springside.modules.utils.text.JsonMapper;
import org.springside.modules.web.MediaTypes;
/**
* 重载替换Spring Boot默认的BasicErrorController, 增加日志并让错误返回方式统一.
@@ -4,7 +4,7 @@ import org.javasimon.aop.Monitored;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springside.modules.utils.net.MediaTypes;
import org.springside.modules.web.MediaTypes;
@RestController
public class HelloController {
@@ -1,4 +1,4 @@
package org.springside.modules.utils.collection;
package org.springside.modules.web;
import java.util.ArrayList;
import java.util.Collection;
@@ -3,7 +3,7 @@
*
* Licensed under the Apache License, Version 2.0 (the "License");
*******************************************************************************/
package org.springside.modules.mapper;
package org.springside.modules.web;
import java.io.StringReader;
import java.io.StringWriter;
@@ -3,7 +3,7 @@
*
* Licensed under the Apache License, Version 2.0 (the "License");
*******************************************************************************/
package org.springside.modules.utils.net;
package org.springside.modules.web;
/**
* 带UTF-8 charset 定义的MediaType.
@@ -3,13 +3,14 @@
*
* Licensed under the Apache License, Version 2.0 (the "License");
*******************************************************************************/
package org.springside.modules.utils.collection;
package org.springside.modules.mapper;
import static org.assertj.core.api.Assertions.*;
import java.util.List;
import org.junit.Test;
import org.springside.modules.web.CollectionExtractor;
import com.google.common.collect.Lists;
@@ -22,6 +22,7 @@ import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.junit.Test;
import org.springside.modules.web.JaxbMapper;
import com.google.common.collect.Lists;
@@ -17,7 +17,7 @@ import org.springside.modules.utils.number.NumberUtil;
/**
* 关于Properties的工具类
*
* 1. Boolean.readBoolean(name) 与其他类型如Integer.readInteger()等的行为不一致,进行扩展.
* 1. 统一的读取系统变量,其中Boolean.readBoolean的风格不统一,Double则不支持,都进行了扩展.
*
* 2. 简单的合并系统变量(-D),环境变量 和默认值,以系统变量优先,在未引入Commons Config时使用.
*
@@ -34,50 +34,84 @@ public abstract class PropertiesUtil {
/////////// Boolean.readBoolean()扩展 ///////////////
/**
* 读取Boolean类型的系统变量,为空时返回False,与Boolean.getBoolean()一致.
*/
public static boolean getBooleanDefaultFalse(String name) {
return Boolean.getBoolean(name);
}
/**
* 读取Boolean类型的系统变量,为空时返回null,代表未设置,而不是Boolean.getBoolean()的false.
*/
public static Boolean getBooleanDefaultNull(String name) {
public static Boolean booleanSystemProperty(String name) {
String stringResult = System.getProperty(name);
if (stringResult != null) {
return Boolean.valueOf(stringResult);
}
return null; // NOSONAR
return null;
}
/**
* 读取Boolean类型的系统变量,为空时返回默认值, 而不是Boolean.getBoolean()的false.
*
* 因为默认值为Boolean,返回值也是Boolean
*/
public static Boolean getBoolean(String name, Boolean defaultVal) {
public static Boolean booleanSystemProperty(String name, Boolean defaultValue) {
String stringResult = System.getProperty(name);
if (stringResult != null) {
return Boolean.valueOf(stringResult);
} else {
return defaultVal;
return defaultValue;
}
}
/**
* 读取Boolean类型的系统变量,为空时返回默认值, 而不是Boolean.getBoolean()的false.
*
* 因为默认值为boolean,返回值也是boolean
* 读取String类型的系统变量,为空时返回null.
*/
public static boolean getBoolean(String name, boolean defaultVal) {
String stringResult = System.getProperty(name);
if (stringResult != null) {
return Boolean.parseBoolean(stringResult);
} else {
return defaultVal;
}
public static String stringSystemProperty(String name) {
return System.getProperty(name);
}
/**
* 读取String类型的系统变量,为空时返回默认值
*/
public static String stringSystemProperty(String name, String defaultValue) {
return System.getProperty(name, defaultValue);
}
/**
* 读取Integer类型的系统变量,为空时返回null.
*/
public static Integer intSystemProperty(String name) {
return Integer.getInteger(name);
}
/**
* 读取Integer类型的系统变量,为空时返回默认值
*/
public static Integer intSystemProperty(String name, Integer defaultValue) {
return Integer.getInteger(name, defaultValue);
}
/**
* 读取Long类型的系统变量,为空时返回null.
*/
public static Long longSystemProperty(String name) {
return Long.getLong(name);
}
/**
* 读取Integer类型的系统变量,为空时返回默认值
*/
public static Long longSystemProperty(String name, Long defaultValue) {
return Long.getLong(name, defaultValue);
}
/**
* 读取Double类型的系统变量,为空时返回null.
*/
public static Double doubleSystemProperty(String propertyName) {
return NumberUtil.toDoubleObject(System.getProperty(propertyName));
}
/**
* 读取Double类型的系统变量,为空时返回默认值.
*/
public static Double doubleSystemProperty(String propertyName, Double defaultValue) {
Double propertyValue = NumberUtil.toDoubleObject(System.getProperty(propertyName));
return propertyValue != null ? propertyValue : defaultValue;
}
/////////// 简单的合并系统变量(-D),环境变量 和默认值,以系统变量优先.///////////////
@@ -85,7 +119,7 @@ public abstract class PropertiesUtil {
/**
* 合并系统变量(-D),环境变量 和默认值,以系统变量优先
*/
public static String readString(String propertyName, String envName, String defaultValue) {
public static String stringSystemProperty(String propertyName, String envName, String defaultValue) {
checkEnvName(envName);
String propertyValue = System.getProperty(propertyName);
if (propertyValue != null) {
@@ -99,7 +133,7 @@ public abstract class PropertiesUtil {
/**
* 合并系统变量(-D),环境变量 和默认值,以系统变量优先
*/
public static Integer readInt(String propertyName, String envName, Integer defaultValue) {
public static Integer intSystemProperty(String propertyName, String envName, Integer defaultValue) {
checkEnvName(envName);
Integer propertyValue = NumberUtil.toIntObject(System.getProperty(propertyName));
if (propertyValue != null) {
@@ -113,7 +147,7 @@ public abstract class PropertiesUtil {
/**
* 合并系统变量(-D),环境变量 和默认值,以系统变量优先
*/
public static Long readLong(String propertyName, String envName, Long defaultValue) {
public static Long longSystemProperty(String propertyName, String envName, Long defaultValue) {
checkEnvName(envName);
Long propertyValue = NumberUtil.toLongObject(System.getProperty(propertyName));
if (propertyValue != null) {
@@ -127,7 +161,7 @@ public abstract class PropertiesUtil {
/**
* 合并系统变量(-D),环境变量 和默认值,以系统变量优先
*/
public static Double readDouble(String propertyName, String envName, Double defaultValue) {
public static Double doubleSystemProperty(String propertyName, String envName, Double defaultValue) {
checkEnvName(envName);
Double propertyValue = NumberUtil.toDoubleObject(System.getProperty(propertyName));
if (propertyValue != null) {
@@ -141,7 +175,7 @@ public abstract class PropertiesUtil {
/**
* 合并系统变量(-D),环境变量 和默认值,以系统变量优先
*/
public static Boolean readBoolean(String propertyName, String envName, Boolean defaultValue) {
public static Boolean booleanSystemProperty(String propertyName, String envName, Boolean defaultValue) {
checkEnvName(envName);
Boolean propertyValue = toBooleanObject(System.getProperty(propertyName));
if (propertyValue != null) {
@@ -99,25 +99,57 @@ public abstract class FileUtil {
return Files.newWriter(getFileByPath(fileName), Charsets.UTF_8);
}
///// 文件操作/////
///// 文件操作 /////
/**
* 复制文件或目录
*/
public static void copy(File from, File to) throws IOException {
if (from.isDirectory())
copyDir(from, to);
else
copyFile(from, to);
}
/**
* 文件复制.
*
* 如果文件不存在或者是目录,不做修改
*/
public static void copy(@Nullable File from, File to) throws IOException {
public static void copyFile(@Nullable File from, File to) throws IOException {
if (isFileExists(from)) {
Files.copy(from, to);
}
}
/**
* 复制目录
*/
public static void copyDir(File from, File to) throws IOException {
if (to.exists()) {
if (!to.isDirectory())
throw new IllegalArgumentException(to.toString());
} else {
to.mkdirs();
}
File[] files = from.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
String name = files[i].getName();
if (".".equals(name) || "..".equals(name))
continue;
copy(files[i], new File(to, name));
}
}
}
/**
* 文件移动/重命名.
*
* 如果文件不存在或者是目录,不做修改.
*/
public static void move(@Nullable File from, File to) throws IOException {
public static void moveFile(@Nullable File from, File to) throws IOException {
if (isFileExists(from)) {
Files.move(from, to);
}
@@ -155,7 +187,7 @@ public abstract class FileUtil {
if (!isDirExists(dir)) {
return;
}
//后序遍历,先删掉子目录中的文件/目录
// 后序遍历,先删掉子目录中的文件/目录
Iterator<File> iterator = Files.fileTreeTraverser().postOrderTraversal(dir).iterator();
while (iterator.hasNext()) {
iterator.next().delete();
@@ -182,13 +214,7 @@ public abstract class FileUtil {
* 前序递归列出所有文件, 只包含后缀名匹配的文件. (后缀名不包含.)
*/
public static List<File> listFileWithExtension(final File rootDir, final String extension) {
return Files.fileTreeTraverser().preOrderTraversal(rootDir).filter(new Predicate<File>() {
@Override
public boolean apply(File input) {
return input.isFile() && extension.equals(FilePathUtil.getFileExtension(input));
}
}).toList();
return Files.fileTreeTraverser().preOrderTraversal(rootDir).filter(new FileExtensionFilter(extension)).toList();
}
/**
@@ -219,6 +245,9 @@ public abstract class FileUtil {
return dir.exists() && dir.isDirectory();
}
/**
* 确保目录存在, 如不存在则创建
*/
public static void makeSureDirExists(String dirPath) throws IOException {
makeSureDirExists(getFileByPath(dirPath));
}
@@ -289,4 +318,20 @@ public abstract class FileUtil {
private static File getFileByPath(String filePath) {
return StringUtils.isBlank(filePath) ? null : new File(filePath);
}
/**
* 以文件名后缀做filter,配合fileTreeTraverser使用
*/
public static final class FileExtensionFilter implements Predicate<File> {
private final String extension;
private FileExtensionFilter(String extension) {
this.extension = extension;
}
@Override
public boolean apply(File input) {
return input.isFile() && extension.equals(FilePathUtil.getFileExtension(input));
}
}
}
@@ -15,6 +15,7 @@ import java.util.zip.ZipFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springside.modules.utils.io.type.StringBuilderWriter;
import org.springside.modules.utils.text.Charsets;
import com.google.common.annotations.Beta;
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springside.modules.utils.io;
package org.springside.modules.utils.io.type;
import java.io.Serializable;
import java.io.Writer;
@@ -149,10 +149,10 @@ public abstract class NetUtil {
*/
private static InetAddress findLocalAddressViaNetworkInterface() {
// 如果hostname +/etc/hosts 得到的是127.0.0.1, 则首选这块网卡
String preferNamePrefix = PropertiesUtil.readString("localhost.prefer.nic.prefix",
String preferNamePrefix = PropertiesUtil.stringSystemProperty("localhost.prefer.nic.prefix",
"LOCALHOST_PREFER_NIC_PREFIX", "bond0.");
// 如果hostname +/etc/hosts 得到的是127.0.0.1, 和首选网卡都不符合要求,则按顺序遍历下面的网卡
String defaultNicList = PropertiesUtil.readString("localhost.default.nic.list", "LOCALHOST_DEFAULT_NIC_LIST",
String defaultNicList = PropertiesUtil.stringSystemProperty("localhost.default.nic.list", "LOCALHOST_DEFAULT_NIC_LIST",
"bond0,eth0,em0,br0");
InetAddress resultAddress = null;
@@ -83,4 +83,16 @@ public abstract class MathUtil {
public static long gcd(long a, long b) {
return LongMath.gcd(a, b);
}
/**
* 保证结果为正数的取模,from ElasticSearch
*/
public static int mod(int v, int m) {
int r = v % m;
if (r < 0) {
r += m;
}
return r;
}
}
@@ -27,6 +27,13 @@ public abstract class NumberUtil {
return Longs.toByteArray(value);
}
/**
* from ElasticSearch Numbers
*/
public static byte[] toBytes(double val) {
return toBytes(Double.doubleToRawLongBits(val));
}
public static int toInt(byte[] bytes) {
return Ints.fromByteArray(bytes);
}
@@ -35,6 +42,13 @@ public abstract class NumberUtil {
return Longs.fromByteArray(bytes);
}
/**
* from ElasticSearch Numbers
*/
public static double toDouble(byte[] bytes) {
return Double.longBitsToDouble(toLong(bytes));
}
/////// 判断字符串类型//////////
/**
* 判断字符串是否合法数字
@@ -11,23 +11,25 @@ import org.springside.modules.utils.base.Platforms;
/**
* 随机数工具集.
*
* 1. 获取无锁的ThreadLocalRandom
* 1. 获取无锁的兼容JDK6的ThreadLocalRandom
*
* 2. 获取性能较佳的SecureRandom
*
* 3. 保证没有负数陷阱,也能更精确she定范围的nextInt 与 nextLong(copy from Common Lang RandomUtils)
* 3. 保证没有负数陷阱,也能更精确设定范围的nextInt/nextLong/nextDouble
* (copy from Common Lang RandomUtils,但默认使用性能较优的ThreadLocalRandom,并可配置其他的Random)
*
* 4. 随机字符串
*
* @author calvin
*/
public abstract class RandomUtil {
private static final Random RANDOM = new Random();
/////////////////// 获取Random实例//////////////
/**
* 返回无锁的ThreadLocalRandom
*
* 如果JDK6,使用移植于JDK7的版本,否则使用JDK自带
* 如果JDK6,使用移植于jsr166e的版本(相当于JDK7的实现)
*/
public static Random threadLocalRandom() {
if (Platforms.IS_ATLEASET_JAVA7) {
@@ -57,7 +59,7 @@ public abstract class RandomUtil {
* 返回0到Intger.MAX_VALUE的随机Int, 使用内置全局普通Random.
*/
public static int nextInt() {
return nextInt(RANDOM);
return nextInt(threadLocalRandom());
}
/**
@@ -78,7 +80,7 @@ public abstract class RandomUtil {
* 返回0到max的随机Int, 使用内置全局普通Random.
*/
public static int nextInt(int max) {
return nextInt(RANDOM, max);
return nextInt(threadLocalRandom(), max);
}
/**
@@ -94,7 +96,7 @@ public abstract class RandomUtil {
* min必须大于0.
*/
public static int nextInt(int min, int max) {
return nextInt(RANDOM, min, max);
return nextInt(threadLocalRandom(), min, max);
}
/**
@@ -122,7 +124,7 @@ public abstract class RandomUtil {
* 返回0-Long.MAX_VALUE间的随机Long, 使用内置全局普通Random.
*/
public static long nextLong() {
return nextLong(RANDOM);
return nextLong(threadLocalRandom());
}
/**
@@ -142,7 +144,7 @@ public abstract class RandomUtil {
* 返回0-max间的随机Long, 使用内置全局普通Random.
*/
public static long nextLong(long max) {
return nextLong(RANDOM, 0, max);
return nextLong(threadLocalRandom(), 0, max);
}
/**
@@ -158,7 +160,7 @@ public abstract class RandomUtil {
* min必须大于0.
*/
public static long nextLong(long min, long max) {
return nextLong(RANDOM, min, max);
return nextLong(threadLocalRandom(), min, max);
}
/**
@@ -186,7 +188,7 @@ public abstract class RandomUtil {
* 返回0-之间的double
*/
public static double nextDouble() {
return nextDouble(RANDOM, 0, Double.MAX_VALUE);
return nextDouble(threadLocalRandom(), 0, Double.MAX_VALUE);
}
/**
@@ -200,7 +202,7 @@ public abstract class RandomUtil {
* 返回0-max之间的double
*/
public static double nextDouble(double max) {
return nextDouble(RANDOM, 0, max);
return nextDouble(threadLocalRandom(), 0, max);
}
/**
@@ -214,7 +216,7 @@ public abstract class RandomUtil {
* 返回min-max之间的double
*/
public static double nextDouble(final double min, final double max) {
return nextDouble(RANDOM, min, max);
return nextDouble(threadLocalRandom(), min, max);
}
/**
@@ -236,7 +238,7 @@ public abstract class RandomUtil {
* 随机字母或数字,固定长度
*/
public static String randomStringFixLength(int length) {
return RandomStringUtils.random(length, 0, 0, true, true, null, RANDOM);
return RandomStringUtils.random(length, 0, 0, true, true, null, threadLocalRandom());
}
/**
@@ -250,7 +252,7 @@ public abstract class RandomUtil {
* 随机字母或数字,随机长度
*/
public static String randomStringRandomLength(int minLength, int maxLength) {
return RandomStringUtils.random(nextInt(minLength, maxLength), 0, 0, true, true, null, RANDOM);
return RandomStringUtils.random(nextInt(minLength, maxLength), 0, 0, true, true, null, threadLocalRandom());
}
/**
@@ -264,7 +266,7 @@ public abstract class RandomUtil {
* 随机字母,固定长度
*/
public static String randomLetterFixLength(int length) {
return RandomStringUtils.random(length, 0, 0, true, false, null, RANDOM);
return RandomStringUtils.random(length, 0, 0, true, false, null, threadLocalRandom());
}
/**
@@ -278,7 +280,7 @@ public abstract class RandomUtil {
* 随机字母,随机长度
*/
public static String randomLetterRandomLength(int minLength, int maxLength) {
return RandomStringUtils.random(nextInt(minLength, maxLength), 0, 0, true, false, null, RANDOM);
return RandomStringUtils.random(nextInt(minLength, maxLength), 0, 0, true, false, null, threadLocalRandom());
}
/**
@@ -292,7 +294,7 @@ public abstract class RandomUtil {
* 随机ASCII字符(含字母,数字及其他符号),固定长度
*/
public static String randomAsciiFixLength(int length) {
return RandomStringUtils.random(length, 32, 127, false, false, null, RANDOM);
return RandomStringUtils.random(length, 32, 127, false, false, null, threadLocalRandom());
}
/**
@@ -306,7 +308,8 @@ public abstract class RandomUtil {
* 随机ASCII字符(含字母,数字及其他符号),随机长度
*/
public static String randomAsciiRandomLength(int minLength, int maxLength) {
return RandomStringUtils.random(nextInt(minLength, maxLength), 32, 127, false, false, null, RANDOM);
return RandomStringUtils.random(nextInt(minLength, maxLength), 32, 127, false, false, null,
threadLocalRandom());
}
/**
@@ -7,8 +7,8 @@ package org.springside.modules.utils.text;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Collection;
@@ -16,7 +16,6 @@ import java.util.Iterator;
import java.util.zip.CRC32;
import org.apache.commons.lang3.Validate;
import org.springside.modules.utils.base.ExceptionUtil;
import com.google.common.hash.Hashing;
@@ -25,11 +24,13 @@ import com.google.common.hash.Hashing;
*
* 1.集合类的HashCode, 返回int
*
* 2.SHA-1, 安全性较高, 返回byte[](可用Encodes进一步被编码为Hex, Base64),
* 2.SHA-1, 安全性较高, 返回byte[](可用Encodes进一步被编码为Hex, Base64)
*
* 性能优化,使用ThreadLocal的MessageDigest(from ElasticSearch)
*
* 支持带salt并且进行迭代达到更高的安全性.
*
* MD5的安全性较低, 默认已不支持.
* MD5的安全性较低, 只在文件Checksum时支持.
*
* 3.crc32, murmur32这些不追求安全性, 性能较高, 返回int.
*
@@ -39,8 +40,22 @@ import com.google.common.hash.Hashing;
*/
public abstract class HashUtil {
private static final String SHA1_ALG = "SHA-1";
private static final String MD5_ALG = "MD5";
private static ThreadLocal<MessageDigest> createThreadLocalMessageDigest(final String digest) {
return new ThreadLocal<MessageDigest>() {
@Override
protected MessageDigest initialValue() {
try {
return MessageDigest.getInstance(digest);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(
"unexpected exception creating MessageDigest instance for [" + digest + "]", e);
}
}
};
}
private static final ThreadLocal<MessageDigest> MD5_DIGEST = createThreadLocalMessageDigest("MD5");
private static final ThreadLocal<MessageDigest> SHA_1_DIGEST = createThreadLocalMessageDigest("SHA-1");
private static SecureRandom random = new SecureRandom();
@@ -74,28 +89,28 @@ public abstract class HashUtil {
* 对输入字符串进行sha1散列.
*/
public static byte[] sha1(byte[] input) {
return digest(input, SHA1_ALG, null, 1);
return digest(input, get(SHA_1_DIGEST), null, 1);
}
/**
* 对输入字符串进行sha1散列, 编码默认为UTF8.
*/
public static byte[] sha1(String input) {
return digest(input.getBytes(Charsets.UTF_8), SHA1_ALG, null, 1);
return digest(input.getBytes(Charsets.UTF_8), get(SHA_1_DIGEST), null, 1);
}
/**
* 对输入字符串进行sha1散列,带salt达到更高的安全性.
*/
public static byte[] sha1(byte[] input, byte[] salt) {
return digest(input, SHA1_ALG, salt, 1);
return digest(input, get(SHA_1_DIGEST), salt, 1);
}
/**
* 对输入字符串进行sha1散列,带salt达到更高的安全性.
*/
public static byte[] sha1(String input, byte[] salt) {
return digest(input.getBytes(Charsets.UTF_8), SHA1_ALG, salt, 1);
return digest(input.getBytes(Charsets.UTF_8), get(SHA_1_DIGEST), salt, 1);
}
/**
@@ -104,7 +119,7 @@ public abstract class HashUtil {
* @see #generateSalt(int)
*/
public static byte[] sha1(byte[] input, byte[] salt, int iterations) {
return digest(input, SHA1_ALG, salt, iterations);
return digest(input, get(SHA_1_DIGEST), salt, iterations);
}
/**
@@ -113,34 +128,34 @@ public abstract class HashUtil {
* @see #generateSalt(int)
*/
public static byte[] sha1(String input, byte[] salt, int iterations) {
return digest(input.getBytes(Charsets.UTF_8), SHA1_ALG, salt, iterations);
return digest(input.getBytes(Charsets.UTF_8), get(SHA_1_DIGEST), salt, iterations);
}
private static MessageDigest get(ThreadLocal<MessageDigest> messageDigest) {
MessageDigest instance = messageDigest.get();
instance.reset();
return instance;
}
/**
* 对字符串进行散列, 支持md5与sha1算法.
*/
private static byte[] digest(byte[] input, String algorithm, byte[] salt, int iterations) {
try {
MessageDigest digest = MessageDigest.getInstance(algorithm);
// 带盐
if (salt != null) {
digest.update(salt);
}
// 第一次散列
byte[] result = digest.digest(input);
// 如果迭代次数>1,进一步迭代散列
for (int i = 1; i < iterations; i++) {
digest.reset();
result = digest.digest(result);
}
return result;
} catch (GeneralSecurityException e) {
throw ExceptionUtil.unchecked(e);
private static byte[] digest(byte[] input, MessageDigest digest, byte[] salt, int iterations) {
// 带盐
if (salt != null) {
digest.update(salt);
}
// 第一次散列
byte[] result = digest.digest(input);
// 如果迭代次数>1,进一步迭代散列
for (int i = 1; i < iterations; i++) {
digest.reset();
result = digest.digest(result);
}
return result;
}
/**
@@ -160,32 +175,27 @@ public abstract class HashUtil {
* 对文件进行sha1散列.
*/
public static byte[] sha1File(InputStream input) throws IOException {
return digestFile(input, SHA1_ALG);
return digestFile(input, get(SHA_1_DIGEST));
}
/**
* 对文件进行md5散列,被破解后MD5已较少人用.
*/
public static byte[] md5File(InputStream input) throws IOException {
return digestFile(input, MD5_ALG);
return digestFile(input, get(MD5_DIGEST));
}
private static byte[] digestFile(InputStream input, String algorithm) throws IOException {
try {
MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
int bufferLength = 8 * 1024;
byte[] buffer = new byte[bufferLength];
int read = input.read(buffer, 0, bufferLength);
private static byte[] digestFile(InputStream input, MessageDigest messageDigest) throws IOException {
int bufferLength = 8 * 1024;
byte[] buffer = new byte[bufferLength];
int read = input.read(buffer, 0, bufferLength);
while (read > -1) {
messageDigest.update(buffer, 0, read);
read = input.read(buffer, 0, bufferLength);
}
return messageDigest.digest();
} catch (GeneralSecurityException e) {
throw ExceptionUtil.unchecked(e);
while (read > -1) {
messageDigest.update(buffer, 0, read);
read = input.read(buffer, 0, bufferLength);
}
return messageDigest.digest();
}
////////////////// 基于JDK的CRC32 ///////////////////
@@ -26,6 +26,7 @@ public abstract class DateUtil {
private static final int[] MONTH_LENGTH = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
//////// 日期比较 ///////////
/**
* 是否同一天.
*
@@ -39,9 +40,23 @@ public abstract class DateUtil {
* 是否同一时刻.
*/
public static boolean isSameTime(@NotNull final Date date1, @NotNull final Date date2) {
return date1.getTime() == date2.getTime();
// date.getMillisOf() 比date.getTime()快
return date1.compareTo(date2) == 0;
}
/**
* 判断日期是否在范围内,包含相等的日期
*/
public static boolean isBetween(@NotNull final Date date, @NotNull final Date start, @NotNull final Date end) {
if (date == null || start == null || end == null || start.after(end)) {
throw new IllegalArgumentException("some date parameters is null or dateBein after dateEnd");
}
return !date.before(start) && !date.after(end);
}
/////////// 日期设置处理 /////////
/**
* 日期往下取整.
*
@@ -12,53 +12,100 @@ import org.springside.modules.utils.number.RandomUtil;
public class PropertiesUtilTest {
@Test
public void getBoolean() {
public void systemProperty() {
String name = "ss.test" + RandomUtil.nextInt();
boolean result = PropertiesUtil.getBooleanDefaultFalse(name);
assertThat(result).isFalse();
Boolean result0 = PropertiesUtil.getBooleanDefaultNull(name);
Boolean result0 = PropertiesUtil.booleanSystemProperty(name);
assertThat(result0).isNull();
Boolean result1 = PropertiesUtil.getBoolean(name, null);
Boolean result1 = PropertiesUtil.booleanSystemProperty(name, null);
assertThat(result1).isNull();
boolean result2 = PropertiesUtil.getBoolean(name, false);
assertThat(result2).isFalse();
Boolean result3 = PropertiesUtil.getBoolean(name, Boolean.TRUE);
Boolean result3 = PropertiesUtil.booleanSystemProperty(name, Boolean.TRUE);
assertThat(result3).isTrue();
System.setProperty(name, "true");
Boolean result4 = PropertiesUtil.getBoolean(name, false);
assertThat(result4).isTrue();
Boolean result5 = PropertiesUtil.getBoolean(name, Boolean.FALSE);
Boolean result5 = PropertiesUtil.booleanSystemProperty(name, Boolean.FALSE);
assertThat(result5).isTrue();
System.clearProperty(name);
/// int
Integer result6 = PropertiesUtil.intSystemProperty(name);
assertThat(result6).isNull();
result6 = PropertiesUtil.intSystemProperty(name, 1);
assertThat(result6).isEqualTo(1);
System.setProperty(name, "2");
result6 = PropertiesUtil.intSystemProperty(name, 1);
assertThat(result6).isEqualTo(2);
System.clearProperty(name);
///// long
Long result7 = PropertiesUtil.longSystemProperty(name);
assertThat(result7).isNull();
result7 = PropertiesUtil.longSystemProperty(name, 1L);
assertThat(result7).isEqualTo(1L);
System.setProperty(name, "2");
result7 = PropertiesUtil.longSystemProperty(name, 1L);
assertThat(result7).isEqualTo(2L);
System.clearProperty(name);
///// doulbe
Double result8 = PropertiesUtil.doubleSystemProperty(name);
assertThat(result8).isNull();
result8 = PropertiesUtil.doubleSystemProperty(name, 1.1);
assertThat(result8).isEqualTo(1.1);
System.setProperty(name, "2.1");
result8 = PropertiesUtil.doubleSystemProperty(name, 1.1);
assertThat(result8).isEqualTo(2.1);
System.clearProperty(name);
///// String
String result9 = PropertiesUtil.stringSystemProperty(name);
assertThat(result9).isNull();
result9 = PropertiesUtil.stringSystemProperty(name, "1.1");
assertThat(result9).isEqualTo("1.1");
System.setProperty(name, "2.1");
result9 = PropertiesUtil.stringSystemProperty(name, "1.1");
assertThat(result9).isEqualTo("2.1");
System.clearProperty(name);
}
@Test
public void readString() {
public void stringSystemProperty() {
String name = "ss.test" + RandomUtil.nextInt();
String envName = "ss_test" + RandomUtil.nextInt();
// default 值
String result = PropertiesUtil.readString(name, envName, "123");
String result = PropertiesUtil.stringSystemProperty(name, envName, "123");
assertThat(result).isEqualTo("123");
// env值
String result2 = PropertiesUtil.readString(name, "HOME", "123");
String result2 = PropertiesUtil.stringSystemProperty(name, "HOME", "123");
assertThat(result2).isNotEqualTo("123");
// system properties值
System.setProperty(name, "456");
String result3 = PropertiesUtil.readString(name, envName, "123");
String result3 = PropertiesUtil.stringSystemProperty(name, envName, "123");
assertThat(result3).isEqualTo("456");
try {
// 非法字符
String result4 = PropertiesUtil.readString(name, name, "123");
String result4 = PropertiesUtil.stringSystemProperty(name, name, "123");
Assert.fail("should fail before");
} catch (Exception e) {
assertThat(e).isInstanceOf(IllegalArgumentException.class);
@@ -68,81 +115,81 @@ public class PropertiesUtilTest {
}
@Test
public void readInt() {
public void intSystemProperty() {
String name = "ss.test" + RandomUtil.nextInt();
String envName = "ss_test" + RandomUtil.nextInt();
// default 值
int result = PropertiesUtil.readInt(name, envName, 123);
int result = PropertiesUtil.intSystemProperty(name, envName, 123);
assertThat(result).isEqualTo(123);
// env值没有数字类型的,忽略
// system properties值
System.setProperty(name, "456");
int result3 = PropertiesUtil.readInt(name, envName, 123);
int result3 = PropertiesUtil.intSystemProperty(name, envName, 123);
assertThat(result3).isEqualTo(456);
System.clearProperty(name);
}
@Test
public void readLong() {
public void longSystemProperty() {
String name = "ss.test" + RandomUtil.nextInt();
String envName = "ss_test" + RandomUtil.nextInt();
// default 值
long result = PropertiesUtil.readLong(name, envName, 123L);
long result = PropertiesUtil.longSystemProperty(name, envName, 123L);
assertThat(result).isEqualTo(123L);
// env值没有数字类型的,忽略
// system properties值
System.setProperty(name, "456");
long result3 = PropertiesUtil.readLong(name, envName, 123L);
long result3 = PropertiesUtil.longSystemProperty(name, envName, 123L);
assertThat(result3).isEqualTo(456L);
System.clearProperty(name);
}
@Test
public void readDouble() {
public void doubleSystemProperty() {
String name = "ss.test" + RandomUtil.nextInt();
String envName = "ss_test" + RandomUtil.nextInt();
// default 值
double result = PropertiesUtil.readDouble(name, envName, 123d);
double result = PropertiesUtil.doubleSystemProperty(name, envName, 123d);
assertThat(result).isEqualTo(123d);
// env值没有数字类型的,忽略
// system properties值
System.setProperty(name, "456");
double result3 = PropertiesUtil.readDouble(name, envName, 123d);
double result3 = PropertiesUtil.doubleSystemProperty(name, envName, 123d);
assertThat(result3).isEqualTo(456d);
System.clearProperty(name);
}
@Test
public void readBoolean() {
public void booleanSystemProperty() {
String name = "ss.test" + RandomUtil.nextInt();
String envName = "ss_test" + RandomUtil.nextInt();
// default 值
boolean result = PropertiesUtil.readBoolean(name, envName, true);
boolean result = PropertiesUtil.booleanSystemProperty(name, envName, true);
assertThat(result).isTrue();
// env值没有boolean类型的,忽略
// system properties值
System.setProperty(name, "true");
boolean result3 = PropertiesUtil.readBoolean(name, envName, false);
boolean result3 = PropertiesUtil.booleanSystemProperty(name, envName, false);
assertThat(result3).isTrue();
System.clearProperty(name);
}
@Test
public void loadProperties() {
Properties p1 = PropertiesUtil.loadFromFile("classpath://application.properties");
@@ -26,6 +26,8 @@ public class ThreadLocalContextTest {
ThreadLocalContext.put("myname", Thread.currentThread().getName());
ThreadUtil.sleep(RandomUtil.nextLong(100, 300));
System.out.println(ThreadLocalContext.get("myname"));
ThreadLocalContext.reset();
System.out.println("shoud null for " +Thread.currentThread().getName() + ":"+ThreadLocalContext.get("myname"));
countdown.countDown();
}
};
@@ -43,7 +43,7 @@ public class FileUtilTest {
FileUtil.write(content, file);
File newFile = new File(FilePathUtil.contact(Platforms.TMP_DIR, "testFile" + RandomUtil.nextInt()));
FileUtil.copy(file, newFile);
FileUtil.copyFile(file, newFile);
assertThat(FileUtil.isFileExists(newFile)).isTrue();
String result = FileUtil.toString(newFile);
@@ -7,6 +7,7 @@ import java.io.Closeable;
import java.io.IOException;
import org.junit.Test;
import org.springside.modules.utils.io.type.StringBuilderWriter;
import org.springside.modules.utils.text.Charsets;
public class IOUtilTest {