ソースを参照

add parseCST and fix cookie bug

Looly 6 年 前
コミット
a4515e218b

+ 5 - 1
CHANGELOG.md

@@ -8,10 +8,14 @@
 ### 新特性
 * 【all】        修复注释中的错别字(issue#I12XE6@Gitee)
 * 【core】       CsvWriter支持其它类型的参数(issue#I12XE3@Gitee)
-* 【core】       ClassScaner支持自定义ClassLoader
+* 【core】       ClassScanner支持自定义ClassLoader
+* 【core】       修改错别字(pr#568@Github)
+* 【core】       增加DateUtil.parseCST方法(issue#570@Github)
 
 ### Bug修复
 * 【all】        修复阶乘计算错误bug(issue#I12XE4@Gitee)
+* 【http】       修复disableCookie无效问题(issue#572@Github)
+* 【http】       修复HttpResponse.getCookies导致的问题(issue#572@Github)
 
 -------------------------------------------------------------------------------------------------------------
 

+ 1 - 0
hutool-core/src/main/java/cn/hutool/core/date/DateTime.java

@@ -140,6 +140,7 @@ public class DateTime extends Date {
 	 */
 	public DateTime(Calendar calendar) {
 		this(calendar.getTime(), calendar.getTimeZone());
+		this.setFirstDayOfWeek(Week.of(calendar.getFirstDayOfWeek()));
 	}
 
 	/**

+ 23 - 2
hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java

@@ -758,6 +758,24 @@ public class DateUtil {
 	}
 
 	/**
+	 * 解析CST时间,格式:<br>
+	 * <ol>
+	 * <li>EEE MMM dd HH:mm:ss z yyyy(例如:Wed Aug 01 00:00:00 CST 2012)</li>
+	 * </ol>
+	 *
+	 * @param cstString UTC时间
+	 * @return 日期对象
+	 * @since 4.6.9
+	 */
+	public static DateTime parseCST(String cstString) {
+		if (cstString == null) {
+			return null;
+		}
+
+		return parse(cstString, DatePattern.JDK_DATETIME_FORMAT);
+	}
+
+	/**
 	 * 将日期字符串转换为{@link DateTime}对象,格式:<br>
 	 * <ol>
 	 * <li>yyyy-MM-dd HH:mm:ss</li>
@@ -808,8 +826,11 @@ public class DateUtil {
 			// HH:mm:ss 或者 HH:mm 时间格式匹配单独解析
 			return parseTimeToday(dateStr);
 		} else if (StrUtil.containsAnyIgnoreCase(dateStr, wtb)) {
-			// JDK的Date对象toString默认格式,类似于:Tue Jun 4 16:25:15 +0800 2019 或 Thu May 16 17:57:18 GMT+08:00 2019
-			return parse(dateStr, DatePattern.JDK_DATETIME_FORMAT);
+			// JDK的Date对象toString默认格式,类似于:
+			// Tue Jun 4 16:25:15 +0800 2019
+			// Thu May 16 17:57:18 GMT+08:00 2019
+			// Wed Aug 01 00:00:00 CST 2012
+			return parseCST(dateStr);
 		} else if (StrUtil.contains(dateStr, 'T')) {
 			// UTC时间
 			return parseUTC(dateStr);

+ 7 - 7
hutool-core/src/main/java/cn/hutool/core/lang/ClassScaner.java

@@ -23,9 +23,9 @@ import java.util.jar.JarFile;
  * 类扫描器
  *
  * @author looly
- * @since 4.1.5
+ * @since 4.6.9
  */
-public class ClassScaner implements Serializable {
+public class ClassScanner implements Serializable {
 	private static final long serialVersionUID = 1L;
 
 	/**
@@ -124,13 +124,13 @@ public class ClassScaner implements Serializable {
 	 * @return 类集合
 	 */
 	public static Set<Class<?>> scanPackage(String packageName, Filter<Class<?>> classFilter) {
-		return new ClassScaner(packageName, classFilter).scan();
+		return new ClassScanner(packageName, classFilter).scan();
 	}
 
 	/**
 	 * 构造,默认UTF-8编码
 	 */
-	public ClassScaner() {
+	public ClassScanner() {
 		this(null);
 	}
 
@@ -139,7 +139,7 @@ public class ClassScaner implements Serializable {
 	 *
 	 * @param packageName 包名,所有包传入""或者null
 	 */
-	public ClassScaner(String packageName) {
+	public ClassScanner(String packageName) {
 		this(packageName, null);
 	}
 
@@ -149,7 +149,7 @@ public class ClassScaner implements Serializable {
 	 * @param packageName 包名,所有包传入""或者null
 	 * @param classFilter 过滤器,无需传入null
 	 */
-	public ClassScaner(String packageName, Filter<Class<?>> classFilter) {
+	public ClassScanner(String packageName, Filter<Class<?>> classFilter) {
 		this(packageName, classFilter, CharsetUtil.CHARSET_UTF_8);
 	}
 
@@ -160,7 +160,7 @@ public class ClassScaner implements Serializable {
 	 * @param classFilter 过滤器,无需传入null
 	 * @param charset     编码
 	 */
-	public ClassScaner(String packageName, Filter<Class<?>> classFilter, Charset charset) {
+	public ClassScanner(String packageName, Filter<Class<?>> classFilter, Charset charset) {
 		packageName = StrUtil.nullToEmpty(packageName);
 		this.packageName = packageName;
 		this.packageNameWithDot = StrUtil.addSuffixIfNot(packageName, StrUtil.DOT);

+ 12 - 12
hutool-core/src/main/java/cn/hutool/core/thread/NamedThreadFactory.java

@@ -26,7 +26,7 @@ public class NamedThreadFactory implements ThreadFactory {
 	/** 线程组 */
 	private final AtomicInteger threadNumber = new AtomicInteger(1);
 	/** 是否守护线程 */
-	private final boolean isDeamon;
+	private final boolean isDaemon;
 	/** 无法捕获的异常统一处理 */
 	private final UncaughtExceptionHandler handler;
 
@@ -34,10 +34,10 @@ public class NamedThreadFactory implements ThreadFactory {
 	 * 构造
 	 * 
 	 * @param prefix 线程名前缀
-	 * @param isDeamon 是否守护线程
+	 * @param isDaemon 是否守护线程
 	 */
-	public NamedThreadFactory(String prefix, boolean isDeamon) {
-		this(prefix, null, isDeamon);
+	public NamedThreadFactory(String prefix, boolean isDaemon) {
+		this(prefix, null, isDaemon);
 	}
 	
 	/**
@@ -45,10 +45,10 @@ public class NamedThreadFactory implements ThreadFactory {
 	 * 
 	 * @param prefix 线程名前缀
 	 * @param threadGroup 线程组,可以为null
-	 * @param isDeamon 是否守护线程
+	 * @param isDaemon 是否守护线程
 	 */
-	public NamedThreadFactory(String prefix, ThreadGroup threadGroup, boolean isDeamon) {
-		this(prefix, threadGroup, isDeamon, null);
+	public NamedThreadFactory(String prefix, ThreadGroup threadGroup, boolean isDaemon) {
+		this(prefix, threadGroup, isDaemon, null);
 	}
 
 	/**
@@ -56,16 +56,16 @@ public class NamedThreadFactory implements ThreadFactory {
 	 * 
 	 * @param prefix 线程名前缀
 	 * @param threadGroup 线程组,可以为null
-	 * @param isDeamon 是否守护线程
+	 * @param isDaemon 是否守护线程
 	 * @param handler 未捕获异常处理
 	 */
-	public NamedThreadFactory(String prefix, ThreadGroup threadGroup, boolean isDeamon, UncaughtExceptionHandler handler) {
+	public NamedThreadFactory(String prefix, ThreadGroup threadGroup, boolean isDaemon, UncaughtExceptionHandler handler) {
 		this.prefix = StrUtil.isBlank(prefix) ? "Hutool" : prefix;
 		if (null == threadGroup) {
 			threadGroup = ThreadUtil.currentThreadGroup();
 		}
 		this.group = threadGroup;
-		this.isDeamon = isDeamon;
+		this.isDaemon = isDaemon;
 		this.handler = handler;
 	}
 
@@ -75,11 +75,11 @@ public class NamedThreadFactory implements ThreadFactory {
 		
 		//守护线程
 		if (false == t.isDaemon()) {
-			if (isDeamon) {
+			if (isDaemon) {
 				// 原线程为非守护则设置为守护
 				t.setDaemon(true);
 			}
-		} else if (false == isDeamon) {
+		} else if (false == isDaemon) {
 			// 原线程为守护则还原为非守护
 			t.setDaemon(false);
 		}

+ 15 - 15
hutool-core/src/main/java/cn/hutool/core/thread/ThreadUtil.java

@@ -98,17 +98,17 @@ public class ThreadUtil {
 	 * 执行异步方法
 	 * 
 	 * @param runnable 需要执行的方法体
-	 * @param isDeamon 是否守护线程。守护线程会在主线程结束后自动结束
+	 * @param isDaemon 是否守护线程。守护线程会在主线程结束后自动结束
 	 * @return 执行的方法体
 	 */
-	public static Runnable excAsync(final Runnable runnable, boolean isDeamon) {
+	public static Runnable excAsync(final Runnable runnable, boolean isDaemon) {
 		Thread thread = new Thread() {
 			@Override
 			public void run() {
 				runnable.run();
 			}
 		};
-		thread.setDaemon(isDeamon);
+		thread.setDaemon(isDaemon);
 		thread.start();
 
 		return runnable;
@@ -192,13 +192,13 @@ public class ThreadUtil {
 	 * 
 	 * @param runnable {@link Runnable}
 	 * @param name 线程名
-	 * @param isDeamon 是否守护线程
+	 * @param isDaemon 是否守护线程
 	 * @return {@link Thread}
 	 * @since 4.1.2
 	 */
-	public static Thread newThread(Runnable runnable, String name, boolean isDeamon) {
+	public static Thread newThread(Runnable runnable, String name, boolean isDaemon) {
 		final Thread t = new Thread(null, runnable, name);
-		t.setDaemon(isDeamon);
+		t.setDaemon(isDaemon);
 		return t;
 	}
 
@@ -396,11 +396,11 @@ public class ThreadUtil {
 	 * 创建线程工厂
 	 * 
 	 * @param prefix 线程名前缀
-	 * @param isDeamon 是否守护线程
+	 * @param isDaemon 是否守护线程
 	 * @since 4.0.0
 	 */
-	public static ThreadFactory newNamedThreadFactory(String prefix, boolean isDeamon) {
-		return new NamedThreadFactory(prefix, isDeamon);
+	public static ThreadFactory newNamedThreadFactory(String prefix, boolean isDaemon) {
+		return new NamedThreadFactory(prefix, isDaemon);
 	}
 
 	/**
@@ -408,11 +408,11 @@ public class ThreadUtil {
 	 * 
 	 * @param prefix 线程名前缀
 	 * @param threadGroup 线程组,可以为null
-	 * @param isDeamon 是否守护线程
+	 * @param isDaemon 是否守护线程
 	 * @since 4.0.0
 	 */
-	public static ThreadFactory newNamedThreadFactory(String prefix, ThreadGroup threadGroup, boolean isDeamon) {
-		return new NamedThreadFactory(prefix, threadGroup, isDeamon);
+	public static ThreadFactory newNamedThreadFactory(String prefix, ThreadGroup threadGroup, boolean isDaemon) {
+		return new NamedThreadFactory(prefix, threadGroup, isDaemon);
 	}
 
 	/**
@@ -420,12 +420,12 @@ public class ThreadUtil {
 	 * 
 	 * @param prefix 线程名前缀
 	 * @param threadGroup 线程组,可以为null
-	 * @param isDeamon 是否守护线程
+	 * @param isDaemon 是否守护线程
 	 * @param handler 未捕获异常处理
 	 * @since 4.0.0
 	 */
-	public static ThreadFactory newNamedThreadFactory(String prefix, ThreadGroup threadGroup, boolean isDeamon, UncaughtExceptionHandler handler) {
-		return new NamedThreadFactory(prefix, threadGroup, isDeamon, handler);
+	public static ThreadFactory newNamedThreadFactory(String prefix, ThreadGroup threadGroup, boolean isDaemon, UncaughtExceptionHandler handler) {
+		return new NamedThreadFactory(prefix, threadGroup, isDaemon, handler);
 	}
 
 	/**

+ 10 - 10
hutool-core/src/main/java/cn/hutool/core/util/ClassUtil.java

@@ -21,7 +21,7 @@ import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.io.IORuntimeException;
 import cn.hutool.core.io.resource.ResourceUtil;
 import cn.hutool.core.lang.Assert;
-import cn.hutool.core.lang.ClassScaner;
+import cn.hutool.core.lang.ClassScanner;
 import cn.hutool.core.lang.Filter;
 import cn.hutool.core.lang.Singleton;
 
@@ -176,10 +176,10 @@ public class ClassUtil {
 	 * @param packageName     包路径
 	 * @param annotationClass 注解类
 	 * @return 类集合
-	 * @see ClassScaner#scanPackageByAnnotation(String, Class)
+	 * @see ClassScanner#scanPackageByAnnotation(String, Class)
 	 */
 	public static Set<Class<?>> scanPackageByAnnotation(String packageName, final Class<? extends Annotation> annotationClass) {
-		return ClassScaner.scanPackageByAnnotation(packageName, annotationClass);
+		return ClassScanner.scanPackageByAnnotation(packageName, annotationClass);
 	}
 
 	/**
@@ -188,20 +188,20 @@ public class ClassUtil {
 	 * @param packageName 包路径
 	 * @param superClass  父类或接口
 	 * @return 类集合
-	 * @see ClassScaner#scanPackageBySuper(String, Class)
+	 * @see ClassScanner#scanPackageBySuper(String, Class)
 	 */
 	public static Set<Class<?>> scanPackageBySuper(String packageName, final Class<?> superClass) {
-		return ClassScaner.scanPackageBySuper(packageName, superClass);
+		return ClassScanner.scanPackageBySuper(packageName, superClass);
 	}
 
 	/**
 	 * 扫面该包路径下所有class文件
 	 *
 	 * @return 类集合
-	 * @see ClassScaner#scanPackage()
+	 * @see ClassScanner#scanPackage()
 	 */
 	public static Set<Class<?>> scanPackage() {
-		return ClassScaner.scanPackage();
+		return ClassScanner.scanPackage();
 	}
 
 	/**
@@ -209,10 +209,10 @@ public class ClassUtil {
 	 *
 	 * @param packageName 包路径 com | com. | com.abs | com.abs.
 	 * @return 类集合
-	 * @see ClassScaner#scanPackage(String)
+	 * @see ClassScanner#scanPackage(String)
 	 */
 	public static Set<Class<?>> scanPackage(String packageName) {
-		return ClassScaner.scanPackage(packageName);
+		return ClassScanner.scanPackage(packageName);
 	}
 
 	/**
@@ -225,7 +225,7 @@ public class ClassUtil {
 	 * @return 类集合
 	 */
 	public static Set<Class<?>> scanPackage(String packageName, Filter<Class<?>> classFilter) {
-		return ClassScaner.scanPackage(packageName, classFilter);
+		return ClassScanner.scanPackage(packageName, classFilter);
 	}
 
 	// ----------------------------------------------------------------------------------------- Method

+ 4 - 10
hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java

@@ -585,10 +585,7 @@ public class StrUtil {
 	 */
 	public static boolean startWith(CharSequence str, CharSequence prefix, boolean isIgnoreCase) {
 		if (null == str || null == prefix) {
-			if (null == str && null == prefix) {
-				return true;
-			}
-			return false;
+			return null == str && null == prefix;
 		}
 
 		if (isIgnoreCase) {
@@ -664,10 +661,7 @@ public class StrUtil {
 	 */
 	public static boolean endWith(CharSequence str, CharSequence suffix, boolean isIgnoreCase) {
 		if (null == str || null == suffix) {
-			if (null == str && null == suffix) {
-				return true;
-			}
-			return false;
+			return null == str && null == suffix;
 		}
 
 		if (isIgnoreCase) {
@@ -3831,7 +3825,7 @@ public class StrUtil {
 		}
 
 		int preIndex = fromIndex;
-		int index = fromIndex;
+		int index;
 		while ((index = indexOf(str, searchStr, preIndex, ignoreCase)) > -1) {
 			result.append(str.subSequence(preIndex, index));
 			result.append(replacement);
@@ -3985,7 +3979,7 @@ public class StrUtil {
 	 * 
 	 * @param str1 字符串1
 	 * @param str2 字符串2
-	 * @param scale
+	 * @param scale 相似度
 	 * @return 相似度百分比
 	 * @since 3.2.3
 	 */

+ 14 - 0
hutool-core/src/main/java/cn/hutool/core/util/URLUtil.java

@@ -214,6 +214,20 @@ public class URLUtil {
 	}
 
 	/**
+	 * 获取URL中域名部分
+	 *
+	 * @param url URL
+	 * @return 域名的URI
+	 * @since 4.6.9
+	 */
+	public static URI getHost(URL url){
+		if(null == url){
+			return null;
+		}
+		return toURI(url.getHost());
+	}
+
+	/**
 	 * 补全相对路径
 	 * 
 	 * @param baseUrl 基准URL

+ 11 - 0
hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java

@@ -2,6 +2,7 @@ package cn.hutool.core.date;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.date.BetweenFormater.Level;
+import cn.hutool.core.lang.Console;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -473,6 +474,16 @@ public class DateUtilTest {
 	}
 
 	@Test
+	public void parseCSTTest(){
+		String dateStr = "Wed Sep 16 11:26:23 CST 2009";
+		DateTime dateTime = DateUtil.parseCST(dateStr);
+		Assert.assertEquals("2009-09-17 01:26:23", dateTime.toString());
+
+		dateTime = DateUtil.parse(dateStr);
+		Assert.assertEquals("2009-09-17 01:26:23", dateTime.toString());
+	}
+
+	@Test
 	public void parseJDkTest() {
 		String dateStr = "Thu May 16 17:57:18 GMT+08:00 2019";
 		DateTime time = DateUtil.parse(dateStr);

+ 1 - 1
hutool-core/src/test/java/cn/hutool/core/lang/ClassScanerTest.java

@@ -10,7 +10,7 @@ public class ClassScanerTest {
 	@Test
 	@Ignore
 	public void scanTest() {
-		ClassScaner scaner = new ClassScaner("cn.hutool.core.util", null);
+		ClassScanner scaner = new ClassScanner("cn.hutool.core.util", null);
 		Set<Class<?>> set = scaner.scan();
 		for (Class<?> clazz : set) {
 			Console.log(clazz.getName());

+ 14 - 1
hutool-core/src/test/java/cn/hutool/core/util/URLUtilTest.java

@@ -1,8 +1,13 @@
 package cn.hutool.core.util;
 
+import cn.hutool.core.lang.Console;
 import org.junit.Assert;
 import org.junit.Test;
 
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+
 /**
  * URLUtil单元测试
  * 
@@ -54,7 +59,15 @@ public class URLUtilTest {
 		String normalize = URLUtil.normalize(url);
 		Assert.assertEquals("http://www.hutool.cn/aaa/bbb?a=1&b=2", normalize);
 	}
-	
+
+	@Test
+	public void getHostTest() throws MalformedURLException {
+		String url = "//www.hutool.cn//aaa/\\bbb?a=1&b=2";
+		String normalize = URLUtil.normalize(url);
+		URI host = URLUtil.getHost(new URL(normalize));
+		Assert.assertEquals("www.hutool.cn", host.toString());
+	}
+
 	@Test
 	public void encodeTest() {
 		String body = "366466 - 副本.jpg";

+ 3 - 3
hutool-cron/src/main/java/cn/hutool/cron/CronUtil.java

@@ -145,9 +145,9 @@ public class CronUtil {
 	/**
 	 * 开始
 	 * 
-	 * @param isDeamon 是否以守护线程方式启动,如果为true,则在调用{@link #stop()}方法后执行的定时任务立即结束,否则等待执行完毕才结束。
+	 * @param isDaemon 是否以守护线程方式启动,如果为true,则在调用{@link #stop()}方法后执行的定时任务立即结束,否则等待执行完毕才结束。
 	 */
-	synchronized public static void start(boolean isDeamon) {
+	synchronized public static void start(boolean isDaemon) {
 		if (scheduler.isStarted()) {
 			throw new UtilException("Scheduler has been started, please stop it first!");
 		}
@@ -167,7 +167,7 @@ public class CronUtil {
 		}
 
 		schedule(crontabSetting);
-		scheduler.start(isDeamon);
+		scheduler.start(isDaemon);
 	}
 
 	/**

+ 4 - 4
hutool-cron/src/main/java/cn/hutool/cron/Scheduler.java

@@ -126,7 +126,7 @@ public class Scheduler implements Serializable {
 	 * 
 	 * @return 是否为守护线程
 	 */
-	public boolean isDeamon() {
+	public boolean isDaemon() {
 		return this.daemon;
 	}
 
@@ -362,11 +362,11 @@ public class Scheduler implements Serializable {
 	/**
 	 * 启动
 	 * 
-	 * @param isDeamon 是否以守护线程方式启动,如果为true,则在调用{@link #stop()}方法后执行的定时任务立即结束,否则等待执行完毕才结束。
+	 * @param isDaemon 是否以守护线程方式启动,如果为true,则在调用{@link #stop()}方法后执行的定时任务立即结束,否则等待执行完毕才结束。
 	 * @return this
 	 */
-	public Scheduler start(boolean isDeamon) {
-		this.daemon = isDeamon;
+	public Scheduler start(boolean isDaemon) {
+		this.daemon = isDaemon;
 		return start();
 	}
 

+ 13 - 9
hutool-crypto/src/main/java/cn/hutool/crypto/KeyUtil.java

@@ -50,8 +50,12 @@ import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
 public class KeyUtil {
 
 	/** Java密钥库(Java Key Store,JKS)KEY_STORE */
-	public static final String KEY_STORE = "JKS";
-	public static final String X509 = "X.509";
+	public static final String KEY_TYPE_JKS = "JKS";
+	/** jceks */
+	public static final String KEY_TYPE_JCEKS = "jceks";
+	/** PKCS12是公钥加密标准,它规定了可包含所有私钥、公钥和证书。其以二进制格式存储,也称为 PFX 文件 */
+	public static final String KEY_TYPE_PKCS12 = "pkcs12";
+	public static final String KEY_TYPE_X509 = "X.509";
 
 	/**
 	 * 默认密钥字节数
@@ -113,7 +117,7 @@ public class KeyUtil {
 	 */
 	public static SecretKey generateKey(String algorithm, byte[] key) {
 		Assert.notBlank(algorithm, "Algorithm is blank!");
-		SecretKey secretKey = null;
+		SecretKey secretKey;
 		if (algorithm.startsWith("PBE")) {
 			// PBE密钥
 			secretKey = generatePBEKey(algorithm, (null == key) ? null : StrUtil.str(key, CharsetUtil.CHARSET_UTF_8).toCharArray());
@@ -139,7 +143,7 @@ public class KeyUtil {
 			throw new CryptoException("Algorithm [{}] is not a DES algorithm!");
 		}
 
-		SecretKey secretKey = null;
+		SecretKey secretKey;
 		if (null == key) {
 			secretKey = generateKey(algorithm);
 		} else {
@@ -608,7 +612,7 @@ public class KeyUtil {
 	 * @return {@link KeyStore}
 	 */
 	public static KeyStore readJKSKeyStore(InputStream in, char[] password) {
-		return readKeyStore(KEY_STORE, in, password);
+		return readKeyStore(KEY_TYPE_JKS, in, password);
 	}
 
 	/**
@@ -618,11 +622,11 @@ public class KeyUtil {
 	 * 
 	 * @param type 类型
 	 * @param in {@link InputStream} 如果想从文件读取.keystore文件,使用 {@link FileUtil#getInputStream(java.io.File)} 读取
-	 * @param password 密码
+	 * @param password 密码,null表示无密码
 	 * @return {@link KeyStore}
 	 */
 	public static KeyStore readKeyStore(String type, InputStream in, char[] password) {
-		KeyStore keyStore = null;
+		KeyStore keyStore;
 		try {
 			keyStore = KeyStore.getInstance(type);
 			keyStore.load(in, password);
@@ -680,7 +684,7 @@ public class KeyUtil {
 	 * @since 4.4.1
 	 */
 	public static Certificate readX509Certificate(InputStream in, char[] password, String alias) {
-		return readCertificate(X509, in, password, alias);
+		return readCertificate(KEY_TYPE_X509, in, password, alias);
 	}
 
 	/**
@@ -710,7 +714,7 @@ public class KeyUtil {
 	 * @since 4.4.1
 	 */
 	public static Certificate readX509Certificate(InputStream in) {
-		return readCertificate(X509, in);
+		return readCertificate(KEY_TYPE_X509, in);
 	}
 
 	/**

+ 2 - 2
hutool-http/src/main/java/cn/hutool/http/HttpBase.java

@@ -27,7 +27,7 @@ public abstract class HttpBase<T> {
 	public static final String HTTP_1_1 = "HTTP/1.1";
 	
 	/**存储头信息*/
-	protected Map<String, List<String>> headers = new HashMap<String, List<String>>();
+	protected Map<String, List<String>> headers = new HashMap<>();
 	/**编码*/
 	protected Charset charset = CharsetUtil.CHARSET_UTF_8;
 	/**http版本*/
@@ -90,7 +90,7 @@ public abstract class HttpBase<T> {
 		if(null != name && null != value){
 			final List<String> values = headers.get(name.trim());
 			if(isOverride || CollectionUtil.isEmpty(values)) {
-				final ArrayList<String> valueList = new ArrayList<String>();
+				final ArrayList<String> valueList = new ArrayList<>();
 				valueList.add(value);
 				headers.put(name.trim(), valueList);
 			}else {

+ 22 - 34
hutool-http/src/main/java/cn/hutool/http/HttpRequest.java

@@ -1,44 +1,31 @@
 package cn.hutool.http;
 
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.CookieManager;
-import java.net.HttpCookie;
-import java.net.HttpURLConnection;
-import java.net.Proxy;
-import java.net.URLStreamHandler;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.SSLSocketFactory;
-
 import cn.hutool.core.codec.Base64;
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.convert.Convert;
 import cn.hutool.core.io.IORuntimeException;
 import cn.hutool.core.io.IoUtil;
-import cn.hutool.core.io.resource.BytesResource;
-import cn.hutool.core.io.resource.FileResource;
-import cn.hutool.core.io.resource.MultiFileResource;
-import cn.hutool.core.io.resource.MultiResource;
-import cn.hutool.core.io.resource.Resource;
+import cn.hutool.core.io.resource.*;
 import cn.hutool.core.lang.Assert;
 import cn.hutool.core.map.MapUtil;
-import cn.hutool.core.util.ArrayUtil;
-import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.core.util.RandomUtil;
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.core.util.URLUtil;
+import cn.hutool.core.util.*;
 import cn.hutool.http.cookie.GlobalCookieManager;
 import cn.hutool.http.ssl.SSLSocketFactoryBuilder;
 import cn.hutool.json.JSON;
 
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLSocketFactory;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.*;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
 /**
  * http请求类<br>
  * Http请求类用于构建Http请求并同步获取结果,此类通过CookieManager持有域名对应的Cookie值,再次请求时会自动附带Cookie信息
@@ -987,8 +974,6 @@ public class HttpRequest extends HttpBase<HttpRequest> {
 				.setHttpsInfo(this.hostnameVerifier, this.ssf)//
 				.setConnectTimeout(this.connectionTimeout)//
 				.setReadTimeout(this.readTimeout)//
-				// 自定义Cookie
-				.setCookie(this.cookie)
 				// 定义转发
 				.setInstanceFollowRedirects(this.maxRedirectCount > 0)
 				// 流方式上传数据
@@ -996,8 +981,13 @@ public class HttpRequest extends HttpBase<HttpRequest> {
 				// 覆盖默认Header
 				.header(this.headers, true);
 
-		// 读取全局Cookie信息并附带到请求中
-		GlobalCookieManager.add(this.httpConnection);
+		if (null != this.cookie) {
+			// 当用户自定义Cookie时,全局Cookie自动失效
+			this.httpConnection.setCookie(this.cookie);
+		} else {
+			// 读取全局Cookie信息并附带到请求中
+			GlobalCookieManager.add(this.httpConnection);
+		}
 
 		// 是否禁用缓存
 		if (this.isDisableCache) {
@@ -1193,8 +1183,6 @@ public class HttpRequest extends HttpBase<HttpRequest> {
 
 	/**
 	 * 设置表单类型为Multipart(文件上传)
-	 *
-	 * @return HttpConnection HTTP连接对象
 	 */
 	private void setMultipart() {
 		this.httpConnection.header(Header.CONTENT_TYPE, CONTENT_TYPE_MULTIPART_PREFIX + BOUNDARY, true);

+ 3 - 6
hutool-http/src/main/java/cn/hutool/http/HttpResponse.java

@@ -151,10 +151,9 @@ public class HttpResponse extends HttpBase<HttpResponse> implements Closeable {
 	 * 
 	 * @return Cookie列表
 	 * @since 3.1.1
-	 * @see GlobalCookieManager#getCookieManager()
 	 */
 	public List<HttpCookie> getCookies() {
-		return GlobalCookieManager.getCookieManager().getCookieStore().getCookies();
+		return GlobalCookieManager.getCookies(this.httpConnection);
 	}
 
 	/**
@@ -374,11 +373,10 @@ public class HttpResponse extends HttpBase<HttpResponse> implements Closeable {
 		try {
 			this.status = httpConnection.responseCode();
 		} catch (IOException e) {
-			if (e instanceof FileNotFoundException) {
-				// 服务器无返回内容,忽略之
-			} else {
+			if (false == (e instanceof FileNotFoundException)) {
 				throw new HttpException(e);
 			}
+			// 服务器无返回内容,忽略之
 		}
 
 		// 读取响应头信息
@@ -410,7 +408,6 @@ public class HttpResponse extends HttpBase<HttpResponse> implements Closeable {
 	 * 读取主体,忽略EOFException异常
 	 * 
 	 * @param in 输入流
-	 * @return 自身
 	 * @throws IORuntimeException IO异常
 	 */
 	private void readBody(InputStream in) throws IORuntimeException {

+ 25 - 3
hutool-http/src/main/java/cn/hutool/http/cookie/GlobalCookieManager.java

@@ -7,6 +7,8 @@ import cn.hutool.http.HttpConnection;
 import java.io.IOException;
 import java.net.CookieManager;
 import java.net.CookiePolicy;
+import java.net.HttpCookie;
+import java.net.URI;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -44,6 +46,17 @@ public class GlobalCookieManager {
 	}
 
 	/**
+	 * 获取指定域名下所有Cookie信息
+	 *
+	 * @param conn HTTP连接
+	 * @return Cookie信息列表
+	 * @since 4.6.9
+	 */
+	public static List<HttpCookie> getCookies(HttpConnection conn){
+		return cookieManager.getCookieStore().get(getDomain(conn));
+	}
+
+	/**
 	 * 将本地存储的Cookie信息附带到Http请求中,不覆盖用户定义好的Cookie
 	 * 
 	 * @param conn {@link HttpConnection}
@@ -53,10 +66,10 @@ public class GlobalCookieManager {
 			// 全局Cookie管理器关闭
 			return;
 		}
-		
+
 		Map<String, List<String>> cookieHeader;
 		try {
-			cookieHeader = cookieManager.get(URLUtil.toURI(conn.getUrl()), new HashMap<String, List<String>>(0));
+			cookieHeader = cookieManager.get(getDomain(conn), new HashMap<String, List<String>>(0));
 		} catch (IOException e) {
 			throw new IORuntimeException(e);
 		}
@@ -77,9 +90,18 @@ public class GlobalCookieManager {
 		}
 		
 		try {
-			cookieManager.put(URLUtil.toURI(conn.getUrl()), conn.headers());
+			cookieManager.put(getDomain(conn), conn.headers());
 		} catch (IOException e) {
 			throw new IORuntimeException(e);
 		}
 	}
+
+	/**
+	 * 获取连接的URL中域名信息,例如http://www.hutool.cn/aaa/bb.html,得到www.hutool.cn
+	 * @param conn HttpConnection
+	 * @return URI
+	 */
+	private static URI getDomain(HttpConnection conn){
+		return URLUtil.getHost(conn.getUrl());
+	}
 }

+ 9 - 0
hutool-http/src/test/java/cn/hutool/http/test/HttpRequestTest.java

@@ -29,6 +29,15 @@ public class HttpRequestTest {
 		String body = HttpRequest.get("https://www.gjifa.com/pc/").execute().body();
 		Console.log(body);
 	}
+
+	@Test
+	@Ignore
+	public void getCookiesTest() {
+		// 检查在Connection关闭情况下Cookie是否可以正常获取
+		HttpResponse res = HttpRequest.get("https://www.oschina.net/").execute();
+		String body = res.body();
+		Console.log(res.getCookies());
+	}
 	
 	@Test
 	@Ignore