This commit is contained in:
Looly 2019-09-18 17:29:29 +08:00
parent 8b94fa0c5d
commit 8e70a2aca7
6 changed files with 346 additions and 279 deletions

View File

@ -7,7 +7,10 @@
### 新特性 ### 新特性
* 【core】 ImgUtil.rotate支持负数issue#543@Github * 【core】 ImgUtil.rotate支持负数issue#543@Github
* 【http】 body方法传null跳过而非报错issue#I12AP2@Github
* 【core】 TimeInterval增加intervalPretty方法issue#I12A6T@Github
### Bug修复 ### Bug修复
* 【core】 修复DateUtil.offset导致的时区错误问题issue#I1294O@Github
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------

View File

@ -17,23 +17,28 @@ import cn.hutool.core.util.StrUtil;
/** /**
* 包装java.util.Date * 包装java.util.Date
*
* @author xiaoleilu
* *
* @author xiaoleilu
*/ */
public class DateTime extends Date { public class DateTime extends Date {
private static final long serialVersionUID = -5395712593979185936L; private static final long serialVersionUID = -5395712593979185936L;
/** 是否可变对象 */ /**
* 是否可变对象
*/
private boolean mutable = true; private boolean mutable = true;
/** 一周的第一天,默认是周一, 在设置或获得 WEEK_OF_MONTH 或 WEEK_OF_YEAR 字段时Calendar 必须确定一个月或一年的第一个星期,以此作为参考点。 */ /**
* 一周的第一天默认是周一 在设置或获得 WEEK_OF_MONTH WEEK_OF_YEAR 字段时Calendar 必须确定一个月或一年的第一个星期以此作为参考点
*/
private Week firstDayOfWeek = Week.MONDAY; private Week firstDayOfWeek = Week.MONDAY;
/** 时区 */ /**
* 时区
*/
private TimeZone timeZone; private TimeZone timeZone;
/** /**
* 转换时间戳为 DateTime * 转换时间戳为 DateTime
* *
* @param timeMillis 时间戳毫秒数 * @param timeMillis 时间戳毫秒数
* @return DateTime * @return DateTime
* @since 4.6.3 * @since 4.6.3
@ -44,7 +49,7 @@ public class DateTime extends Date {
/** /**
* 转换JDK date为 DateTime * 转换JDK date为 DateTime
* *
* @param date JDK Date * @param date JDK Date
* @return DateTime * @return DateTime
*/ */
@ -57,7 +62,7 @@ public class DateTime extends Date {
/** /**
* 转换 {@link Calendar} DateTime * 转换 {@link Calendar} DateTime
* *
* @param calendar {@link Calendar} * @param calendar {@link Calendar}
* @return DateTime * @return DateTime
*/ */
@ -67,11 +72,11 @@ public class DateTime extends Date {
/** /**
* 构造 * 构造
* *
* @see DatePattern
* @param dateStr Date字符串 * @param dateStr Date字符串
* @param format 格式 * @param format 格式
* @return {@link DateTime} * @return {@link DateTime}
* @see DatePattern
*/ */
public static DateTime of(String dateStr, String format) { public static DateTime of(String dateStr, String format) {
return new DateTime(dateStr, format); return new DateTime(dateStr, format);
@ -79,7 +84,7 @@ public class DateTime extends Date {
/** /**
* 现在的时间 * 现在的时间
* *
* @return 现在的时间 * @return 现在的时间
*/ */
public static DateTime now() { public static DateTime now() {
@ -87,9 +92,9 @@ public class DateTime extends Date {
} }
// -------------------------------------------------------------------- Constructor start // -------------------------------------------------------------------- Constructor start
/** /**
* 当前时间 * 当前时间
*
*/ */
public DateTime() { public DateTime() {
this(TimeZone.getDefault()); this(TimeZone.getDefault());
@ -97,7 +102,7 @@ public class DateTime extends Date {
/** /**
* 当前时间 * 当前时间
* *
* @param timeZone 时区 * @param timeZone 时区
* @since 4.1.2 * @since 4.1.2
*/ */
@ -107,17 +112,20 @@ public class DateTime extends Date {
/** /**
* 给定日期的构造 * 给定日期的构造
* *
* @param date 日期 * @param date 日期
*/ */
public DateTime(Date date) { public DateTime(Date date) {
this(date.getTime(), TimeZone.getDefault()); this(
date.getTime(),//
(date instanceof DateTime) ? ((DateTime) date).timeZone : TimeZone.getDefault()
);
} }
/** /**
* 给定日期的构造 * 给定日期的构造
* *
* @param date 日期 * @param date 日期
* @param timeZone 时区 * @param timeZone 时区
* @since 4.1.2 * @since 4.1.2
*/ */
@ -127,28 +135,28 @@ public class DateTime extends Date {
/** /**
* 给定日期的构造 * 给定日期的构造
* *
* @param calendar {@link Calendar} * @param calendar {@link Calendar}
*/ */
public DateTime(Calendar calendar) { public DateTime(Calendar calendar) {
this(calendar.getTime(), (TimeZone) null); this(calendar.getTime(), calendar.getTimeZone());
} }
/** /**
* 给定日期毫秒数的构造 * 给定日期毫秒数的构造
* *
* @param timeMillis 日期毫秒数 * @param timeMillis 日期毫秒数
* @since 4.1.2 * @since 4.1.2
*/ */
public DateTime(long timeMillis) { public DateTime(long timeMillis) {
this(timeMillis, (TimeZone) null); this(timeMillis, TimeZone.getDefault());
} }
/** /**
* 给定日期毫秒数的构造 * 给定日期毫秒数的构造
* *
* @param timeMillis 日期毫秒数 * @param timeMillis 日期毫秒数
* @param timeZone 时区 * @param timeZone 时区
* @since 4.1.2 * @since 4.1.2
*/ */
public DateTime(long timeMillis, TimeZone timeZone) { public DateTime(long timeMillis, TimeZone timeZone) {
@ -160,10 +168,10 @@ public class DateTime extends Date {
/** /**
* 构造 * 构造
* *
* @see DatePattern
* @param dateStr Date字符串 * @param dateStr Date字符串
* @param format 格式 * @param format 格式
* @see DatePattern
*/ */
public DateTime(String dateStr, String format) { public DateTime(String dateStr, String format) {
this(dateStr, new SimpleDateFormat(format)); this(dateStr, new SimpleDateFormat(format));
@ -171,10 +179,10 @@ public class DateTime extends Date {
/** /**
* 构造 * 构造
* *
* @see DatePattern * @param dateStr Date字符串
* @param dateStr Date字符串
* @param dateFormat 格式化器 {@link SimpleDateFormat} * @param dateFormat 格式化器 {@link SimpleDateFormat}
* @see DatePattern
*/ */
public DateTime(String dateStr, DateFormat dateFormat) { public DateTime(String dateStr, DateFormat dateFormat) {
this(parse(dateStr, dateFormat), dateFormat.getTimeZone()); this(parse(dateStr, dateFormat), dateFormat.getTimeZone());
@ -182,24 +190,25 @@ public class DateTime extends Date {
/** /**
* 构造 * 构造
* *
* @see DatePattern * @param dateStr Date字符串
* @param dateStr Date字符串
* @param dateParser 格式化器 {@link DateParser}可以使用 {@link FastDateFormat} * @param dateParser 格式化器 {@link DateParser}可以使用 {@link FastDateFormat}
* @see DatePattern
*/ */
public DateTime(String dateStr, DateParser dateParser) { public DateTime(String dateStr, DateParser dateParser) {
this(parse(dateStr, dateParser), dateParser.getTimeZone()); this(parse(dateStr, dateParser), dateParser.getTimeZone());
} }
// -------------------------------------------------------------------- Constructor end // -------------------------------------------------------------------- Constructor end
// -------------------------------------------------------------------- offset start // -------------------------------------------------------------------- offset start
/** /**
* 调整日期和时间<br> * 调整日期和时间<br>
* 如果此对象为可变对象返回自身否则返回新对象设置是否可变对象见{@link #setMutable(boolean)} * 如果此对象为可变对象返回自身否则返回新对象设置是否可变对象见{@link #setMutable(boolean)}
* *
* @param datePart 调整的部分 {@link DateField} * @param datePart 调整的部分 {@link DateField}
* @param offset 偏移量正数为向后偏移负数为向前偏移 * @param offset 偏移量正数为向后偏移负数为向前偏移
* @return 如果此对象为可变对象返回自身否则返回新对象 * @return 如果此对象为可变对象返回自身否则返回新对象
*/ */
public DateTime offset(DateField datePart, int offset) { public DateTime offset(DateField datePart, int offset) {
@ -213,9 +222,9 @@ public class DateTime extends Date {
/** /**
* 调整日期和时间<br> * 调整日期和时间<br>
* 返回调整后的新{@link DateTime}不影响原对象 * 返回调整后的新{@link DateTime}不影响原对象
* *
* @param datePart 调整的部分 {@link DateField} * @param datePart 调整的部分 {@link DateField}
* @param offset 偏移量正数为向后偏移负数为向前偏移 * @param offset 偏移量正数为向后偏移负数为向前偏移
* @return 如果此对象为可变对象返回自身否则返回新对象 * @return 如果此对象为可变对象返回自身否则返回新对象
* @since 3.0.9 * @since 3.0.9
*/ */
@ -229,10 +238,11 @@ public class DateTime extends Date {
// -------------------------------------------------------------------- offset end // -------------------------------------------------------------------- offset end
// -------------------------------------------------------------------- Part of Date start // -------------------------------------------------------------------- Part of Date start
/** /**
* 获得日期的某个部分<br> * 获得日期的某个部分<br>
* 例如获得年的部分则使用 getField(DatePart.YEAR) * 例如获得年的部分则使用 getField(DatePart.YEAR)
* *
* @param field 表示日期的哪个部分的枚举 {@link DateField} * @param field 表示日期的哪个部分的枚举 {@link DateField}
* @return 某个部分的值 * @return 某个部分的值
*/ */
@ -243,7 +253,7 @@ public class DateTime extends Date {
/** /**
* 获得日期的某个部分<br> * 获得日期的某个部分<br>
* 例如获得年的部分则使用 getField(Calendar.YEAR) * 例如获得年的部分则使用 getField(Calendar.YEAR)
* *
* @param field 表示日期的哪个部分的int值 {@link Calendar} * @param field 表示日期的哪个部分的int值 {@link Calendar}
* @return 某个部分的值 * @return 某个部分的值
*/ */
@ -254,7 +264,7 @@ public class DateTime extends Date {
/** /**
* 设置日期的某个部分<br> * 设置日期的某个部分<br>
* 如果此对象为可变对象返回自身否则返回新对象设置是否可变对象见{@link #setMutable(boolean)} * 如果此对象为可变对象返回自身否则返回新对象设置是否可变对象见{@link #setMutable(boolean)}
* *
* @param field 表示日期的哪个部分的枚举 {@link DateField} * @param field 表示日期的哪个部分的枚举 {@link DateField}
* @param value * @param value
* @return {@link DateTime} * @return {@link DateTime}
@ -266,7 +276,7 @@ public class DateTime extends Date {
/** /**
* 设置日期的某个部分<br> * 设置日期的某个部分<br>
* 如果此对象为可变对象返回自身否则返回新对象设置是否可变对象见{@link #setMutable(boolean)} * 如果此对象为可变对象返回自身否则返回新对象设置是否可变对象见{@link #setMutable(boolean)}
* *
* @param field 表示日期的哪个部分的int值 {@link Calendar} * @param field 表示日期的哪个部分的int值 {@link Calendar}
* @param value * @param value
* @return {@link DateTime} * @return {@link DateTime}
@ -293,7 +303,7 @@ public class DateTime extends Date {
/** /**
* 获得年的部分 * 获得年的部分
* *
* @return 年的部分 * @return 年的部分
*/ */
public int year() { public int year() {
@ -306,7 +316,7 @@ public class DateTime extends Date {
* 2第二季度<br> * 2第二季度<br>
* 3第三季度<br> * 3第三季度<br>
* 4第四季度<br> * 4第四季度<br>
* *
* @return 第几个季度 * @return 第几个季度
* @deprecated 请使用{@link Quarter}代替 * @deprecated 请使用{@link Quarter}代替
*/ */
@ -317,7 +327,7 @@ public class DateTime extends Date {
/** /**
* 获得当前日期所属季度<br> * 获得当前日期所属季度<br>
* *
* @return 第几个季度 {@link Season} * @return 第几个季度 {@link Season}
* @deprecated 请使用{@link #quarterEnum}代替 * @deprecated 请使用{@link #quarterEnum}代替
*/ */
@ -328,7 +338,7 @@ public class DateTime extends Date {
/** /**
* 获得当前日期所属季度从1开始计数<br> * 获得当前日期所属季度从1开始计数<br>
* *
* @return 第几个季度 {@link Quarter} * @return 第几个季度 {@link Quarter}
*/ */
public int quarter() { public int quarter() {
@ -337,7 +347,7 @@ public class DateTime extends Date {
/** /**
* 获得当前日期所属季度<br> * 获得当前日期所属季度<br>
* *
* @return 第几个季度 {@link Quarter} * @return 第几个季度 {@link Quarter}
*/ */
public Quarter quarterEnum() { public Quarter quarterEnum() {
@ -346,7 +356,7 @@ public class DateTime extends Date {
/** /**
* 获得月份从0开始计数 * 获得月份从0开始计数
* *
* @return 月份 * @return 月份
*/ */
public int month() { public int month() {
@ -356,7 +366,7 @@ public class DateTime extends Date {
/** /**
* 获得月份从1开始计数<br> * 获得月份从1开始计数<br>
* 由于{@link Calendar} 中的月份按照0开始计数导致某些需求容易误解因此如果想用1表示一月2表示二月则调用此方法 * 由于{@link Calendar} 中的月份按照0开始计数导致某些需求容易误解因此如果想用1表示一月2表示二月则调用此方法
* *
* @return 月份 * @return 月份
*/ */
public int monthStartFromOne() { public int monthStartFromOne() {
@ -365,7 +375,7 @@ public class DateTime extends Date {
/** /**
* 获得月份 * 获得月份
* *
* @return {@link Month} * @return {@link Month}
*/ */
public Month monthEnum() { public Month monthEnum() {
@ -378,7 +388,7 @@ public class DateTime extends Date {
* 2016年1月3日为周日如果一周的第一天为周日那这天是第二周返回2<br> * 2016年1月3日为周日如果一周的第一天为周日那这天是第二周返回2<br>
* 如果一周的第一天为周一那这天是第一周返回1<br> * 如果一周的第一天为周一那这天是第一周返回1<br>
* 跨年的那个星期得到的结果总是1 * 跨年的那个星期得到的结果总是1
* *
* @return * @return
* @see #setFirstDayOfWeek(Week) * @see #setFirstDayOfWeek(Week)
*/ */
@ -391,7 +401,7 @@ public class DateTime extends Date {
* 此方法返回值与一周的第一天有关比如<br> * 此方法返回值与一周的第一天有关比如<br>
* 2016年1月3日为周日如果一周的第一天为周日那这天是第二周返回2<br> * 2016年1月3日为周日如果一周的第一天为周日那这天是第二周返回2<br>
* 如果一周的第一天为周一那这天是第一周返回1 * 如果一周的第一天为周一那这天是第一周返回1
* *
* @return * @return
* @see #setFirstDayOfWeek(Week) * @see #setFirstDayOfWeek(Week)
*/ */
@ -401,7 +411,7 @@ public class DateTime extends Date {
/** /**
* 获得指定日期是这个日期所在月份的第几天<br> * 获得指定日期是这个日期所在月份的第几天<br>
* *
* @return * @return
*/ */
public int dayOfMonth() { public int dayOfMonth() {
@ -410,7 +420,7 @@ public class DateTime extends Date {
/** /**
* 获得指定日期是星期几1表示周日2表示周一 * 获得指定日期是星期几1表示周日2表示周一
* *
* @return 星期几 * @return 星期几
*/ */
public int dayOfWeek() { public int dayOfWeek() {
@ -419,7 +429,7 @@ public class DateTime extends Date {
/** /**
* 获得天所在的周是这个月的第几周 * 获得天所在的周是这个月的第几周
* *
* @return * @return
*/ */
public int dayOfWeekInMonth() { public int dayOfWeekInMonth() {
@ -428,7 +438,7 @@ public class DateTime extends Date {
/** /**
* 获得指定日期是星期几 * 获得指定日期是星期几
* *
* @return {@link Week} * @return {@link Week}
*/ */
public Week dayOfWeekEnum() { public Week dayOfWeekEnum() {
@ -437,7 +447,7 @@ public class DateTime extends Date {
/** /**
* 获得指定日期的小时数部分<br> * 获得指定日期的小时数部分<br>
* *
* @param is24HourClock 是否24小时制 * @param is24HourClock 是否24小时制
* @return 小时数 * @return 小时数
*/ */
@ -448,7 +458,7 @@ public class DateTime extends Date {
/** /**
* 获得指定日期的分钟数部分<br> * 获得指定日期的分钟数部分<br>
* 例如10:04:15.250 = 4 * 例如10:04:15.250 = 4
* *
* @return 分钟数 * @return 分钟数
*/ */
public int minute() { public int minute() {
@ -457,7 +467,7 @@ public class DateTime extends Date {
/** /**
* 获得指定日期的秒数部分<br> * 获得指定日期的秒数部分<br>
* *
* @return 秒数 * @return 秒数
*/ */
public int second() { public int second() {
@ -466,7 +476,7 @@ public class DateTime extends Date {
/** /**
* 获得指定日期的毫秒数部分<br> * 获得指定日期的毫秒数部分<br>
* *
* @return 毫秒数 * @return 毫秒数
*/ */
public int millsecond() { public int millsecond() {
@ -475,7 +485,7 @@ public class DateTime extends Date {
/** /**
* 是否为上午 * 是否为上午
* *
* @return 是否为上午 * @return 是否为上午
*/ */
public boolean isAM() { public boolean isAM() {
@ -484,7 +494,7 @@ public class DateTime extends Date {
/** /**
* 是否为下午 * 是否为下午
* *
* @return 是否为下午 * @return 是否为下午
*/ */
public boolean isPM() { public boolean isPM() {
@ -493,7 +503,7 @@ public class DateTime extends Date {
/** /**
* 是否为周末周末指周六或者周日 * 是否为周末周末指周六或者周日
* *
* @return 是否为周末周末指周六或者周日 * @return 是否为周末周末指周六或者周日
* @since 4.1.14 * @since 4.1.14
*/ */
@ -505,9 +515,9 @@ public class DateTime extends Date {
/** /**
* 是否闰年 * 是否闰年
* *
* @see DateUtil#isLeapYear(int)
* @return 是否闰年 * @return 是否闰年
* @see DateUtil#isLeapYear(int)
*/ */
public boolean isLeapYear() { public boolean isLeapYear() {
return DateUtil.isLeapYear(year()); return DateUtil.isLeapYear(year());
@ -515,7 +525,7 @@ public class DateTime extends Date {
/** /**
* 转换为Calendar, 默认 {@link Locale} * 转换为Calendar, 默认 {@link Locale}
* *
* @return {@link Calendar} * @return {@link Calendar}
*/ */
public Calendar toCalendar() { public Calendar toCalendar() {
@ -524,7 +534,7 @@ public class DateTime extends Date {
/** /**
* 转换为Calendar * 转换为Calendar
* *
* @param locale 地域 {@link Locale} * @param locale 地域 {@link Locale}
* @return {@link Calendar} * @return {@link Calendar}
*/ */
@ -534,7 +544,7 @@ public class DateTime extends Date {
/** /**
* 转换为Calendar * 转换为Calendar
* *
* @param zone 时区 {@link TimeZone} * @param zone 时区 {@link TimeZone}
* @return {@link Calendar} * @return {@link Calendar}
*/ */
@ -544,8 +554,8 @@ public class DateTime extends Date {
/** /**
* 转换为Calendar * 转换为Calendar
* *
* @param zone 时区 {@link TimeZone} * @param zone 时区 {@link TimeZone}
* @param locale 地域 {@link Locale} * @param locale 地域 {@link Locale}
* @return {@link Calendar} * @return {@link Calendar}
*/ */
@ -562,7 +572,7 @@ public class DateTime extends Date {
/** /**
* 转换为 {@link Date}<br> * 转换为 {@link Date}<br>
* 考虑到很多框架例如Hibernate的兼容性提供此方法返回JDK原生的Date对象 * 考虑到很多框架例如Hibernate的兼容性提供此方法返回JDK原生的Date对象
* *
* @return {@link Date} * @return {@link Date}
* @since 3.2.2 * @since 3.2.2
*/ */
@ -572,7 +582,7 @@ public class DateTime extends Date {
/** /**
* 转为{@link Timestamp} * 转为{@link Timestamp}
* *
* @return {@link Timestamp} * @return {@link Timestamp}
*/ */
public Timestamp toTimestamp() { public Timestamp toTimestamp() {
@ -581,7 +591,7 @@ public class DateTime extends Date {
/** /**
* 转为 {@link java.sql.Date} * 转为 {@link java.sql.Date}
* *
* @return {@link java.sql.Date} * @return {@link java.sql.Date}
*/ */
public java.sql.Date toSqlDate() { public java.sql.Date toSqlDate() {
@ -590,7 +600,7 @@ public class DateTime extends Date {
/** /**
* 计算相差时长 * 计算相差时长
* *
* @param date 对比的日期 * @param date 对比的日期
* @return {@link DateBetween} * @return {@link DateBetween}
*/ */
@ -600,7 +610,7 @@ public class DateTime extends Date {
/** /**
* 计算相差时长 * 计算相差时长
* *
* @param date 对比的日期 * @param date 对比的日期
* @param unit 单位 {@link DateUnit} * @param unit 单位 {@link DateUnit}
* @return 相差时长 * @return 相差时长
@ -611,9 +621,9 @@ public class DateTime extends Date {
/** /**
* 计算相差时长 * 计算相差时长
* *
* @param date 对比的日期 * @param date 对比的日期
* @param unit 单位 {@link DateUnit} * @param unit 单位 {@link DateUnit}
* @param formatLevel 格式化级别 * @param formatLevel 格式化级别
* @return 相差时长 * @return 相差时长
*/ */
@ -624,9 +634,9 @@ public class DateTime extends Date {
/** /**
* 当前日期是否在日期指定范围内<br> * 当前日期是否在日期指定范围内<br>
* 起始日期和结束日期可以互换 * 起始日期和结束日期可以互换
* *
* @param beginDate 起始日期 * @param beginDate 起始日期
* @param endDate 结束日期 * @param endDate 结束日期
* @return 是否在范围内 * @return 是否在范围内
* @since 3.0.8 * @since 3.0.8
*/ */
@ -640,7 +650,7 @@ public class DateTime extends Date {
/** /**
* 是否在给定日期之前 * 是否在给定日期之前
* *
* @param date 日期 * @param date 日期
* @return 是否在给定日期之前 * @return 是否在给定日期之前
* @since 4.1.3 * @since 4.1.3
@ -654,7 +664,7 @@ public class DateTime extends Date {
/** /**
* 是否在给定日期之前或与给定日期相等 * 是否在给定日期之前或与给定日期相等
* *
* @param date 日期 * @param date 日期
* @return 是否在给定日期之前或与给定日期相等 * @return 是否在给定日期之前或与给定日期相等
* @since 3.0.9 * @since 3.0.9
@ -668,7 +678,7 @@ public class DateTime extends Date {
/** /**
* 是否在给定日期之后 * 是否在给定日期之后
* *
* @param date 日期 * @param date 日期
* @return 是否在给定日期之后 * @return 是否在给定日期之后
* @since 4.1.3 * @since 4.1.3
@ -682,7 +692,7 @@ public class DateTime extends Date {
/** /**
* 是否在给定日期之后或与给定日期相等 * 是否在给定日期之后或与给定日期相等
* *
* @param date 日期 * @param date 日期
* @return 是否在给定日期之后或与给定日期相等 * @return 是否在给定日期之后或与给定日期相等
* @since 3.0.9 * @since 3.0.9
@ -703,7 +713,7 @@ public class DateTime extends Date {
* <li>{@link DateTime#setField(int, int)}</li> * <li>{@link DateTime#setField(int, int)}</li>
* </ul> * </ul>
* 如果为不可变对象{@link DateTime#setTime(long)}将抛出异常 * 如果为不可变对象{@link DateTime#setTime(long)}将抛出异常
* *
* @return 对象是否可变 * @return 对象是否可变
*/ */
public boolean isMutable() { public boolean isMutable() {
@ -718,7 +728,7 @@ public class DateTime extends Date {
* <li>{@link DateTime#setField(int, int)}</li> * <li>{@link DateTime#setField(int, int)}</li>
* </ul> * </ul>
* 如果为不可变对象{@link DateTime#setTime(long)}将抛出异常 * 如果为不可变对象{@link DateTime#setTime(long)}将抛出异常
* *
* @param mutable 是否可变 * @param mutable 是否可变
* @return this * @return this
*/ */
@ -729,7 +739,7 @@ public class DateTime extends Date {
/** /**
* 获得一周的第一天默认为周一 * 获得一周的第一天默认为周一
* *
* @return 一周的第一天 * @return 一周的第一天
*/ */
public Week getFirstDayOfWeek() { public Week getFirstDayOfWeek() {
@ -740,7 +750,7 @@ public class DateTime extends Date {
* 设置一周的第一天<br> * 设置一周的第一天<br>
* JDK的Calendar中默认一周的第一天是周日Hutool中将此默认值设置为周一<br> * JDK的Calendar中默认一周的第一天是周日Hutool中将此默认值设置为周一<br>
* 设置一周的第一天主要影响{@link #weekOfMonth()}{@link #weekOfYear()} 两个方法 * 设置一周的第一天主要影响{@link #weekOfMonth()}{@link #weekOfYear()} 两个方法
* *
* @param firstDayOfWeek 一周的第一天 * @param firstDayOfWeek 一周的第一天
* @return this * @return this
* @see #weekOfMonth() * @see #weekOfMonth()
@ -753,7 +763,7 @@ public class DateTime extends Date {
/** /**
* 设置时区 * 设置时区
* *
* @param timeZone 时区 * @param timeZone 时区
* @return this * @return this
* @since 4.1.2 * @since 4.1.2
@ -764,10 +774,11 @@ public class DateTime extends Date {
} }
// -------------------------------------------------------------------- toString start // -------------------------------------------------------------------- toString start
/** /**
* 转为"yyyy-MM-dd yyyy-MM-dd HH:mm:ss " 格式字符串<br> * 转为"yyyy-MM-dd yyyy-MM-dd HH:mm:ss " 格式字符串<br>
* 如果时区被设置会转换为其时区对应的时间否则转换为当前地点对应的时区 * 如果时区被设置会转换为其时区对应的时间否则转换为当前地点对应的时区
* *
* @return "yyyy-MM-dd yyyy-MM-dd HH:mm:ss " 格式字符串 * @return "yyyy-MM-dd yyyy-MM-dd HH:mm:ss " 格式字符串
*/ */
@Override @Override
@ -778,7 +789,7 @@ public class DateTime extends Date {
/** /**
* 转为"yyyy-MM-dd yyyy-MM-dd HH:mm:ss " 格式字符串<br> * 转为"yyyy-MM-dd yyyy-MM-dd HH:mm:ss " 格式字符串<br>
* 时区使用当前地区的默认时区 * 时区使用当前地区的默认时区
* *
* @return "yyyy-MM-dd yyyy-MM-dd HH:mm:ss " 格式字符串 * @return "yyyy-MM-dd yyyy-MM-dd HH:mm:ss " 格式字符串
* @since 4.1.14 * @since 4.1.14
*/ */
@ -789,7 +800,7 @@ public class DateTime extends Date {
/** /**
* 转为"yyyy-MM-dd yyyy-MM-dd HH:mm:ss " 格式字符串<br> * 转为"yyyy-MM-dd yyyy-MM-dd HH:mm:ss " 格式字符串<br>
* 如果时区不为{@code null}会转换为其时区对应的时间否则转换为当前时间对应的时区 * 如果时区不为{@code null}会转换为其时区对应的时间否则转换为当前时间对应的时区
* *
* @param timeZone 时区 * @param timeZone 时区
* @return "yyyy-MM-dd yyyy-MM-dd HH:mm:ss " 格式字符串 * @return "yyyy-MM-dd yyyy-MM-dd HH:mm:ss " 格式字符串
* @since 4.1.14 * @since 4.1.14
@ -805,7 +816,7 @@ public class DateTime extends Date {
/** /**
* 转为"yyyy-MM-dd " 格式字符串 * 转为"yyyy-MM-dd " 格式字符串
* *
* @return "yyyy-MM-dd " 格式字符串 * @return "yyyy-MM-dd " 格式字符串
* @since 4.0.0 * @since 4.0.0
*/ */
@ -820,7 +831,7 @@ public class DateTime extends Date {
/** /**
* 转为"HH:mm:ss" 格式字符串 * 转为"HH:mm:ss" 格式字符串
* *
* @return "HH:mm:ss" 格式字符串 * @return "HH:mm:ss" 格式字符串
* @since 4.1.4 * @since 4.1.4
*/ */
@ -835,7 +846,7 @@ public class DateTime extends Date {
/** /**
* 转为字符串 * 转为字符串
* *
* @param format 日期格式常用格式见 {@link DatePattern} * @param format 日期格式常用格式见 {@link DatePattern}
* @return String * @return String
*/ */
@ -850,7 +861,7 @@ public class DateTime extends Date {
/** /**
* 转为字符串 * 转为字符串
* *
* @param format {@link DatePrinter} {@link FastDateFormat} * @param format {@link DatePrinter} {@link FastDateFormat}
* @return String * @return String
*/ */
@ -860,7 +871,7 @@ public class DateTime extends Date {
/** /**
* 转为字符串 * 转为字符串
* *
* @param format {@link SimpleDateFormat} * @param format {@link SimpleDateFormat}
* @return String * @return String
*/ */
@ -878,8 +889,8 @@ public class DateTime extends Date {
/** /**
* 转换字符串为Date * 转换字符串为Date
* *
* @param dateStr 日期字符串 * @param dateStr 日期字符串
* @param dateFormat {@link SimpleDateFormat} * @param dateFormat {@link SimpleDateFormat}
* @return {@link Date} * @return {@link Date}
*/ */
@ -899,9 +910,9 @@ public class DateTime extends Date {
/** /**
* 转换字符串为Date * 转换字符串为Date
* *
* @param dateStr 日期字符串 * @param dateStr 日期字符串
* @param parser {@link FastDateFormat} * @param parser {@link FastDateFormat}
* @return {@link Date} * @return {@link Date}
*/ */
private static Date parse(String dateStr, DateParser parser) { private static Date parse(String dateStr, DateParser parser) {
@ -916,7 +927,7 @@ public class DateTime extends Date {
/** /**
* 设置日期时间 * 设置日期时间
* *
* @param time 日期时间毫秒 * @param time 日期时间毫秒
* @return this * @return this
*/ */

View File

@ -1325,7 +1325,7 @@ public class DateUtil {
} }
/** /**
* 获取指定日期偏移指定时间后的时间 * 获取指定日期偏移指定时间后的时间生成的偏移日期不影响原日期
* *
* @param date 基准日期 * @param date 基准日期
* @param dateField 偏移的粒度大小小时月等{@link DateField} * @param dateField 偏移的粒度大小小时月等{@link DateField}
@ -1333,10 +1333,7 @@ public class DateUtil {
* @return 偏移后的日期 * @return 偏移后的日期
*/ */
public static DateTime offset(Date date, DateField dateField, int offset) { public static DateTime offset(Date date, DateField dateField, int offset) {
Calendar cal = Calendar.getInstance(); return dateNew(date).offset(dateField, offset);
cal.setTime(date);
cal.add(dateField.getValue(), offset);
return new DateTime(cal.getTime());
} }
/** /**

View File

@ -5,13 +5,12 @@ import java.io.Serializable;
/** /**
* 计时器<br> * 计时器<br>
* 计算某个过程花费的时间精确到毫秒 * 计算某个过程花费的时间精确到毫秒
*
* @author Looly
* *
* @author Looly
*/ */
public class TimeInterval implements Serializable{ public class TimeInterval implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private long time; private long time;
private boolean isNano; private boolean isNano;
@ -41,73 +40,92 @@ public class TimeInterval implements Serializable{
time = now; time = now;
return d; return d;
} }
/** /**
* 重新开始计算时间重置开始时间 * 重新开始计算时间重置开始时间
*
* @return this * @return this
* @since 3.0.1 * @since 3.0.1
*/ */
public TimeInterval restart(){ public TimeInterval restart() {
time = DateUtil.current(isNano); time = DateUtil.current(isNano);
return this; return this;
} }
//----------------------------------------------------------- Interval //----------------------------------------------------------- Interval
/** /**
* 从开始到当前的间隔时间毫秒数<br> * 从开始到当前的间隔时间毫秒数<br>
* 如果使用纳秒计时返回纳秒差否则返回毫秒差 * 如果使用纳秒计时返回纳秒差否则返回毫秒差
*
* @return 从开始到当前的间隔时间毫秒数 * @return 从开始到当前的间隔时间毫秒数
*/ */
public long interval() { public long interval() {
return DateUtil.current(isNano) - time; return DateUtil.current(isNano) - time;
} }
/**
* 从开始到当前的间隔时间毫秒数返回XX天XX小时XX分XX秒XX毫秒
*
* @return 从开始到当前的间隔时间毫秒数
* @since 4.6.7
*/
public String intervalPretty() {
return DateUtil.formatBetween(intervalMs());
}
/** /**
* 从开始到当前的间隔时间毫秒数 * 从开始到当前的间隔时间毫秒数
*
* @return 从开始到当前的间隔时间毫秒数 * @return 从开始到当前的间隔时间毫秒数
*/ */
public long intervalMs() { public long intervalMs() {
return isNano ? interval() / 1000000L : interval(); return isNano ? interval() / 1000000L : interval();
} }
/** /**
* 从开始到当前的间隔秒数取绝对值 * 从开始到当前的间隔秒数取绝对值
*
* @return 从开始到当前的间隔秒数取绝对值 * @return 从开始到当前的间隔秒数取绝对值
*/ */
public long intervalSecond(){ public long intervalSecond() {
return intervalMs() / DateUnit.SECOND.getMillis(); return intervalMs() / DateUnit.SECOND.getMillis();
} }
/** /**
* 从开始到当前的间隔分钟数取绝对值 * 从开始到当前的间隔分钟数取绝对值
*
* @return 从开始到当前的间隔分钟数取绝对值 * @return 从开始到当前的间隔分钟数取绝对值
*/ */
public long intervalMinute(){ public long intervalMinute() {
return intervalMs() / DateUnit.MINUTE.getMillis(); return intervalMs() / DateUnit.MINUTE.getMillis();
} }
/** /**
* 从开始到当前的间隔小时数取绝对值 * 从开始到当前的间隔小时数取绝对值
*
* @return 从开始到当前的间隔小时数取绝对值 * @return 从开始到当前的间隔小时数取绝对值
*/ */
public long intervalHour(){ public long intervalHour() {
return intervalMs() / DateUnit.HOUR.getMillis(); return intervalMs() / DateUnit.HOUR.getMillis();
} }
/** /**
* 从开始到当前的间隔天数取绝对值 * 从开始到当前的间隔天数取绝对值
*
* @return 从开始到当前的间隔天数取绝对值 * @return 从开始到当前的间隔天数取绝对值
*/ */
public long intervalDay(){ public long intervalDay() {
return intervalMs() / DateUnit.DAY.getMillis(); return intervalMs() / DateUnit.DAY.getMillis();
} }
/** /**
* 从开始到当前的间隔周数取绝对值 * 从开始到当前的间隔周数取绝对值
*
* @return 从开始到当前的间隔周数取绝对值 * @return 从开始到当前的间隔周数取绝对值
*/ */
public long intervalWeek(){ public long intervalWeek() {
return intervalMs() / DateUnit.WEEK.getMillis(); return intervalMs() / DateUnit.WEEK.getMillis();
} }
} }

View File

@ -1,31 +1,23 @@
package cn.hutool.core.date; package cn.hutool.core.date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.TimeZone;
import org.junit.Assert;
import org.junit.Test;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.BetweenFormater.Level; import cn.hutool.core.date.BetweenFormater.Level;
import org.junit.Assert;
import org.junit.Test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
/** /**
* 时间工具单元测试<br> * 时间工具单元测试<br>
* 此单元测试依赖时区为中国+08:00 * 此单元测试依赖时区为中国+08:00
* *
* <pre> * <pre>
* export TZ=Asia/Shanghai * export TZ=Asia/Shanghai
* </pre> * </pre>
*
* @author Looly
* *
* @author Looly
*/ */
public class DateUtilTest { public class DateUtilTest {
@ -289,13 +281,13 @@ public class DateUtilTest {
} }
@Test @Test
public void parseTest4() throws ParseException { public void parseTest4() {
String ymd = DateUtil.parse("2019-3-21 12:20:15", "yyyy-MM-dd").toString(DatePattern.PURE_DATE_PATTERN); String ymd = DateUtil.parse("2019-3-21 12:20:15", "yyyy-MM-dd").toString(DatePattern.PURE_DATE_PATTERN);
Assert.assertEquals("20190321", ymd); Assert.assertEquals("20190321", ymd);
} }
@Test @Test
public void parseTest5() throws ParseException { public void parseTest5() {
// 测试时间解析 // 测试时间解析
String time = DateUtil.parse("22:12:12").toString(DatePattern.NORM_TIME_FORMAT); String time = DateUtil.parse("22:12:12").toString(DatePattern.NORM_TIME_FORMAT);
Assert.assertEquals("22:12:12", time); Assert.assertEquals("22:12:12", time);
@ -321,21 +313,32 @@ public class DateUtilTest {
} }
@Test @Test
public void parseTest6() throws ParseException { public void parseTest6() {
String str = "Tue Jun 4 16:25:15 +0800 2019"; String str = "Tue Jun 4 16:25:15 +0800 2019";
DateTime dateTime = DateUtil.parse(str); DateTime dateTime = DateUtil.parse(str);
Assert.assertEquals("2019-06-04 16:25:15", dateTime.toString()); Assert.assertEquals("2019-06-04 16:25:15", dateTime.toString());
} }
@Test @Test
public void parseTest7() throws ParseException { public void parseTest7() {
String str = "2019-06-01T19:45:43.000 +0800"; String str = "2019-06-01T19:45:43.000 +0800";
DateTime dateTime = DateUtil.parse(str, "yyyy-MM-dd'T'HH:mm:ss.SSS Z"); DateTime dateTime = DateUtil.parse(str, "yyyy-MM-dd'T'HH:mm:ss.SSS Z");
Assert.assertEquals("2019-06-01 19:45:43", dateTime.toString()); Assert.assertEquals("2019-06-01 19:45:43", dateTime.toString());
} }
@Test @Test
public void parseDateTest() throws ParseException { public void parseAndOffsetTest() {
// 检查UTC时间偏移是否准确
String str = "2019-09-17T13:26:17.948Z";
DateTime dateTime = DateUtil.parse(str);
Assert.assertEquals("2019-09-17 13:26:17", dateTime.toString());
DateTime offset = DateUtil.offsetHour(dateTime, 8);
Assert.assertEquals("2019-09-17 21:26:17", offset.toString());
}
@Test
public void parseDateTest() {
String dateStr = "2018-4-10"; String dateStr = "2018-4-10";
Date date = DateUtil.parseDate(dateStr); Date date = DateUtil.parseDate(dateStr);
String format = DateUtil.format(date, DatePattern.NORM_DATE_PATTERN); String format = DateUtil.format(date, DatePattern.NORM_DATE_PATTERN);
@ -411,7 +414,7 @@ public class DateUtilTest {
} }
@Test @Test
public void parseUTCTest() throws ParseException { public void parseUTCTest() {
String dateStr1 = "2018-09-13T05:34:31Z"; String dateStr1 = "2018-09-13T05:34:31Z";
DateTime dt = DateUtil.parseUTC(dateStr1); DateTime dt = DateUtil.parseUTC(dateStr1);
@ -426,44 +429,44 @@ public class DateUtilTest {
// 使用当前上海时区 // 使用当前上海时区
dateStr = dt.toString(TimeZone.getTimeZone("GMT+8:00")); dateStr = dt.toString(TimeZone.getTimeZone("GMT+8:00"));
Assert.assertEquals("2018-09-13 13:34:31", dateStr); Assert.assertEquals("2018-09-13 13:34:31", dateStr);
dateStr1 = "2018-09-13T13:34:32+0800"; dateStr1 = "2018-09-13T13:34:32+0800";
dt = DateUtil.parseUTC(dateStr1); dt = DateUtil.parseUTC(dateStr1);
dateStr = dt.toString(TimeZone.getTimeZone("GMT+8:00")); dateStr = dt.toString(TimeZone.getTimeZone("GMT+8:00"));
Assert.assertEquals("2018-09-13 13:34:32", dateStr); Assert.assertEquals("2018-09-13 13:34:32", dateStr);
dateStr1 = "2018-09-13T13:34:33+08:00"; dateStr1 = "2018-09-13T13:34:33+08:00";
dt = DateUtil.parseUTC(dateStr1); dt = DateUtil.parseUTC(dateStr1);
dateStr = dt.toString(TimeZone.getTimeZone("GMT+8:00")); dateStr = dt.toString(TimeZone.getTimeZone("GMT+8:00"));
Assert.assertEquals("2018-09-13 13:34:33", dateStr); Assert.assertEquals("2018-09-13 13:34:33", dateStr);
dateStr1 = "2018-09-13T13:34:34+0800"; dateStr1 = "2018-09-13T13:34:34+0800";
dt = DateUtil.parse(dateStr1); dt = DateUtil.parse(dateStr1);
dateStr = dt.toString(TimeZone.getTimeZone("GMT+8:00")); dateStr = dt.toString(TimeZone.getTimeZone("GMT+8:00"));
Assert.assertEquals("2018-09-13 13:34:34", dateStr); Assert.assertEquals("2018-09-13 13:34:34", dateStr);
dateStr1 = "2018-09-13T13:34:35+08:00"; dateStr1 = "2018-09-13T13:34:35+08:00";
dt = DateUtil.parse(dateStr1); dt = DateUtil.parse(dateStr1);
dateStr = dt.toString(TimeZone.getTimeZone("GMT+8:00")); dateStr = dt.toString(TimeZone.getTimeZone("GMT+8:00"));
Assert.assertEquals("2018-09-13 13:34:35", dateStr); Assert.assertEquals("2018-09-13 13:34:35", dateStr);
dateStr1 = "2018-09-13T13:34:36.999+0800"; dateStr1 = "2018-09-13T13:34:36.999+0800";
dt = DateUtil.parseUTC(dateStr1); dt = DateUtil.parseUTC(dateStr1);
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DatePattern.NORM_DATETIME_MS_PATTERN); final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DatePattern.NORM_DATETIME_MS_PATTERN);
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT+8:00")); simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
dateStr = dt.toString(simpleDateFormat); dateStr = dt.toString(simpleDateFormat);
Assert.assertEquals("2018-09-13 13:34:36.999", dateStr); Assert.assertEquals("2018-09-13 13:34:36.999", dateStr);
dateStr1 = "2018-09-13T13:34:37.999+08:00"; dateStr1 = "2018-09-13T13:34:37.999+08:00";
dt = DateUtil.parseUTC(dateStr1); dt = DateUtil.parseUTC(dateStr1);
dateStr = dt.toString(simpleDateFormat); dateStr = dt.toString(simpleDateFormat);
Assert.assertEquals("2018-09-13 13:34:37.999", dateStr); Assert.assertEquals("2018-09-13 13:34:37.999", dateStr);
dateStr1 = "2018-09-13T13:34:38.999+0800"; dateStr1 = "2018-09-13T13:34:38.999+0800";
dt = DateUtil.parse(dateStr1); dt = DateUtil.parse(dateStr1);
dateStr = dt.toString(simpleDateFormat); dateStr = dt.toString(simpleDateFormat);
Assert.assertEquals("2018-09-13 13:34:38.999", dateStr); Assert.assertEquals("2018-09-13 13:34:38.999", dateStr);
dateStr1 = "2018-09-13T13:34:39.999+08:00"; dateStr1 = "2018-09-13T13:34:39.999+08:00";
dt = DateUtil.parse(dateStr1); dt = DateUtil.parse(dateStr1);
dateStr = dt.toString(simpleDateFormat); dateStr = dt.toString(simpleDateFormat);
@ -471,7 +474,7 @@ public class DateUtilTest {
} }
@Test @Test
public void parseJDkTest() throws ParseException { public void parseJDkTest() {
String dateStr = "Thu May 16 17:57:18 GMT+08:00 2019"; String dateStr = "Thu May 16 17:57:18 GMT+08:00 2019";
DateTime time = DateUtil.parse(dateStr); DateTime time = DateUtil.parse(dateStr);
Assert.assertEquals("2019-05-16 17:57:18", time.toString()); Assert.assertEquals("2019-05-16 17:57:18", time.toString());
@ -484,7 +487,7 @@ public class DateUtilTest {
DateTime endOfYear = DateUtil.endOfYear(date); DateTime endOfYear = DateUtil.endOfYear(date);
Assert.assertEquals("2019-12-31 23:59:59", endOfYear.toString()); Assert.assertEquals("2019-12-31 23:59:59", endOfYear.toString());
} }
@Test @Test
public void endOfWeekTest() { public void endOfWeekTest() {
// 周日 // 周日
@ -521,7 +524,7 @@ public class DateUtilTest {
try { try {
range.next(); range.next();
Assert.fail("已超过边界,下一个元素不应该存在!"); Assert.fail("已超过边界,下一个元素不应该存在!");
} catch (NoSuchElementException e) { } catch (NoSuchElementException ignored) {
} }
// 测试多步进的情况 // 测试多步进的情况
@ -535,7 +538,7 @@ public class DateUtilTest {
try { try {
range.next(); range.next();
Assert.fail("不包含结束时间情况下,下一个元素不应该存在!"); Assert.fail("不包含结束时间情况下,下一个元素不应该存在!");
} catch (NoSuchElementException e) { } catch (NoSuchElementException ignored) {
} }
} }

View File

@ -41,7 +41,7 @@ import cn.hutool.json.JSON;
/** /**
* http请求类<br> * http请求类<br>
* Http请求类用于构建Http请求并同步获取结果此类通过CookieManager持有域名对应的Cookie值再次请求时会自动附带Cookie信息 * Http请求类用于构建Http请求并同步获取结果此类通过CookieManager持有域名对应的Cookie值再次请求时会自动附带Cookie信息
* *
* @author Looly * @author Looly
*/ */
public class HttpRequest extends HttpBase<HttpRequest> { public class HttpRequest extends HttpBase<HttpRequest> {
@ -53,10 +53,10 @@ public class HttpRequest extends HttpBase<HttpRequest> {
private static final String CONTENT_TYPE_MULTIPART_PREFIX = "multipart/form-data; boundary="; private static final String CONTENT_TYPE_MULTIPART_PREFIX = "multipart/form-data; boundary=";
private static final String CONTENT_TYPE_FILE_TEMPLATE = "Content-Type: {}\r\n\r\n"; private static final String CONTENT_TYPE_FILE_TEMPLATE = "Content-Type: {}\r\n\r\n";
/** /**
* 设置全局默认的连接和读取超时时长 * 设置全局默认的连接和读取超时时长
* *
* @param customTimeout 超时时长 * @param customTimeout 超时时长
* @see HttpGlobalConfig#setTimeout(int) * @see HttpGlobalConfig#setTimeout(int)
* @since 4.6.2 * @since 4.6.2
@ -67,10 +67,10 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 获取Cookie管理器用于自定义Cookie管理 * 获取Cookie管理器用于自定义Cookie管理
* *
* @return {@link CookieManager} * @return {@link CookieManager}
* @since 4.1.0
* @see GlobalCookieManager#getCookieManager() * @see GlobalCookieManager#getCookieManager()
* @since 4.1.0
*/ */
public static CookieManager getCookieManager() { public static CookieManager getCookieManager() {
return GlobalCookieManager.getCookieManager(); return GlobalCookieManager.getCookieManager();
@ -78,10 +78,10 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 自定义{@link CookieManager} * 自定义{@link CookieManager}
* *
* @param customCookieManager 自定义的{@link CookieManager} * @param customCookieManager 自定义的{@link CookieManager}
* @since 4.5.14
* @see GlobalCookieManager#setCookieManager(CookieManager) * @see GlobalCookieManager#setCookieManager(CookieManager)
* @since 4.5.14
*/ */
public static void setCookieManager(CookieManager customCookieManager) { public static void setCookieManager(CookieManager customCookieManager) {
GlobalCookieManager.setCookieManager(customCookieManager); GlobalCookieManager.setCookieManager(customCookieManager);
@ -89,9 +89,9 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 关闭Cookie * 关闭Cookie
* *
* @since 4.1.9
* @see GlobalCookieManager#setCookieManager(CookieManager) * @see GlobalCookieManager#setCookieManager(CookieManager)
* @since 4.1.9
*/ */
public static void closeCookie() { public static void closeCookie() {
GlobalCookieManager.setCookieManager(null); GlobalCookieManager.setCookieManager(null);
@ -100,42 +100,72 @@ public class HttpRequest extends HttpBase<HttpRequest> {
private String url; private String url;
private URLStreamHandler urlHandler; private URLStreamHandler urlHandler;
private Method method = Method.GET; private Method method = Method.GET;
/** 默认连接超时 */ /**
* 默认连接超时
*/
private int connectionTimeout = HttpGlobalConfig.timeout; private int connectionTimeout = HttpGlobalConfig.timeout;
/** 默认读取超时 */ /**
* 默认读取超时
*/
private int readTimeout = HttpGlobalConfig.timeout; private int readTimeout = HttpGlobalConfig.timeout;
/** 存储表单数据 */ /**
* 存储表单数据
*/
private Map<String, Object> form; private Map<String, Object> form;
/** 文件表单对象,用于文件上传 */ /**
* 文件表单对象用于文件上传
*/
private Map<String, Resource> fileForm; private Map<String, Resource> fileForm;
/** Cookie */ /**
* Cookie
*/
private String cookie; private String cookie;
/** 连接对象 */ /**
* 连接对象
*/
private HttpConnection httpConnection; private HttpConnection httpConnection;
/** 是否禁用缓存 */ /**
* 是否禁用缓存
*/
private boolean isDisableCache; private boolean isDisableCache;
/** 是否对url中的参数进行编码 */ /**
* 是否对url中的参数进行编码
*/
private boolean encodeUrlParams; private boolean encodeUrlParams;
/** 是否是REST请求模式 */ /**
* 是否是REST请求模式
*/
private boolean isRest; private boolean isRest;
/** 重定向次数计数器,内部使用 */ /**
* 重定向次数计数器内部使用
*/
private int redirectCount; private int redirectCount;
/** 最大重定向次数 */ /**
* 最大重定向次数
*/
private int maxRedirectCount; private int maxRedirectCount;
/** Chuncked块大小0或小于0表示不设置Chuncked模式 */ /**
* Chuncked块大小0或小于0表示不设置Chuncked模式
*/
private int blockSize; private int blockSize;
/** 代理 */ /**
* 代理
*/
private Proxy proxy; private Proxy proxy;
/** HostnameVerifier用于HTTPS安全连接 */ /**
* HostnameVerifier用于HTTPS安全连接
*/
private HostnameVerifier hostnameVerifier; private HostnameVerifier hostnameVerifier;
/** SSLSocketFactory用于HTTPS安全连接 */ /**
* SSLSocketFactory用于HTTPS安全连接
*/
private SSLSocketFactory ssf; private SSLSocketFactory ssf;
/** /**
* 构造 * 构造
* *
* @param url URL * @param url URL
*/ */
public HttpRequest(String url) { public HttpRequest(String url) {
@ -146,9 +176,10 @@ public class HttpRequest extends HttpBase<HttpRequest> {
} }
// ---------------------------------------------------------------- static Http Method start // ---------------------------------------------------------------- static Http Method start
/** /**
* POST请求 * POST请求
* *
* @param url URL * @param url URL
* @return HttpRequest * @return HttpRequest
*/ */
@ -158,7 +189,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* GET请求 * GET请求
* *
* @param url URL * @param url URL
* @return HttpRequest * @return HttpRequest
*/ */
@ -168,7 +199,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* HEAD请求 * HEAD请求
* *
* @param url URL * @param url URL
* @return HttpRequest * @return HttpRequest
*/ */
@ -178,7 +209,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* OPTIONS请求 * OPTIONS请求
* *
* @param url URL * @param url URL
* @return HttpRequest * @return HttpRequest
*/ */
@ -188,7 +219,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* PUT请求 * PUT请求
* *
* @param url URL * @param url URL
* @return HttpRequest * @return HttpRequest
*/ */
@ -198,7 +229,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* PATCH请求 * PATCH请求
* *
* @param url URL * @param url URL
* @return HttpRequest * @return HttpRequest
* @since 3.0.9 * @since 3.0.9
@ -209,7 +240,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* DELETE请求 * DELETE请求
* *
* @param url URL * @param url URL
* @return HttpRequest * @return HttpRequest
*/ */
@ -219,7 +250,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* TRACE请求 * TRACE请求
* *
* @param url URL * @param url URL
* @return HttpRequest * @return HttpRequest
*/ */
@ -230,7 +261,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 获取请求URL * 获取请求URL
* *
* @return URL字符串 * @return URL字符串
* @since 4.1.8 * @since 4.1.8
*/ */
@ -240,7 +271,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 设置URL * 设置URL
* *
* @param url url字符串 * @param url url字符串
* @since 4.1.8 * @since 4.1.8
*/ */
@ -257,7 +288,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
* 因此weblogic不支持https的sni协议的主机名验证此时需要将此值设置为sun.net.www.protocol.https.Handler对象 * 因此weblogic不支持https的sni协议的主机名验证此时需要将此值设置为sun.net.www.protocol.https.Handler对象
* <p> * <p>
* 相关issue见https://gitee.com/loolly/hutool/issues/IMD1X * 相关issue见https://gitee.com/loolly/hutool/issues/IMD1X
* *
* @param urlHandler {@link URLStreamHandler} * @param urlHandler {@link URLStreamHandler}
* @since 4.1.9 * @since 4.1.9
*/ */
@ -268,7 +299,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 获取Http请求方法 * 获取Http请求方法
* *
* @return {@link Method} * @return {@link Method}
* @since 4.1.8 * @since 4.1.8
*/ */
@ -278,7 +309,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 设置请求方法 * 设置请求方法
* *
* @param method HTTP方法 * @param method HTTP方法
* @return HttpRequest * @return HttpRequest
* @see #method(Method) * @see #method(Method)
@ -291,7 +322,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 获取{@link HttpConnection}<br> * 获取{@link HttpConnection}<br>
* {@link #execute()} 执行前此对象为null * {@link #execute()} 执行前此对象为null
* *
* @return {@link HttpConnection} * @return {@link HttpConnection}
* @since 4.2.2 * @since 4.2.2
*/ */
@ -301,7 +332,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 设置请求方法 * 设置请求方法
* *
* @param method HTTP方法 * @param method HTTP方法
* @return HttpRequest * @return HttpRequest
*/ */
@ -312,14 +343,15 @@ public class HttpRequest extends HttpBase<HttpRequest> {
} else { } else {
this.method = method; this.method = method;
} }
return this; return this;
} }
// ---------------------------------------------------------------- Http Request Header start // ---------------------------------------------------------------- Http Request Header start
/** /**
* 设置contentType * 设置contentType
* *
* @param contentType contentType * @param contentType contentType
* @return HttpRequest * @return HttpRequest
*/ */
@ -330,7 +362,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 设置是否为长连接 * 设置是否为长连接
* *
* @param isKeepAlive 是否长连接 * @param isKeepAlive 是否长连接
* @return HttpRequest * @return HttpRequest
*/ */
@ -353,7 +385,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 获取内容长度 * 获取内容长度
* *
* @return String * @return String
*/ */
public String contentLength() { public String contentLength() {
@ -362,7 +394,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 设置内容长度 * 设置内容长度
* *
* @param value 长度 * @param value 长度
* @return HttpRequest * @return HttpRequest
*/ */
@ -374,7 +406,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 设置Cookie<br> * 设置Cookie<br>
* 自定义Cookie后会覆盖Hutool的默认Cookie行为 * 自定义Cookie后会覆盖Hutool的默认Cookie行为
* *
* @param cookies Cookie值数组如果为{@code null}则设置无效使用默认Cookie行为 * @param cookies Cookie值数组如果为{@code null}则设置无效使用默认Cookie行为
* @return this * @return this
* @since 3.1.1 * @since 3.1.1
@ -389,7 +421,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 设置Cookie<br> * 设置Cookie<br>
* 自定义Cookie后会覆盖Hutool的默认Cookie行为 * 自定义Cookie后会覆盖Hutool的默认Cookie行为
* *
* @param cookie Cookie值如果为{@code null}则设置无效使用默认Cookie行为 * @param cookie Cookie值如果为{@code null}则设置无效使用默认Cookie行为
* @return this * @return this
* @since 3.0.7 * @since 3.0.7
@ -403,7 +435,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
* 禁用默认Cookie行为此方法调用后会将Cookie置为空<br> * 禁用默认Cookie行为此方法调用后会将Cookie置为空<br>
* 如果想重新启用Cookie请调用{@link #cookie(String)}方法自定义Cookie<br> * 如果想重新启用Cookie请调用{@link #cookie(String)}方法自定义Cookie<br>
* 如果想启动默认的Cookie行为自动回填服务器传回的Cookie则调用{@link #enableDefaultCookie()} * 如果想启动默认的Cookie行为自动回填服务器传回的Cookie则调用{@link #enableDefaultCookie()}
* *
* @return this * @return this
* @since 3.0.7 * @since 3.0.7
*/ */
@ -413,7 +445,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 打开默认的Cookie行为自动回填服务器传回的Cookie * 打开默认的Cookie行为自动回填服务器传回的Cookie
* *
* @return this * @return this
*/ */
public HttpRequest enableDefaultCookie() { public HttpRequest enableDefaultCookie() {
@ -422,10 +454,11 @@ public class HttpRequest extends HttpBase<HttpRequest> {
// ---------------------------------------------------------------- Http Request Header end // ---------------------------------------------------------------- Http Request Header end
// ---------------------------------------------------------------- Form start // ---------------------------------------------------------------- Form start
/** /**
* 设置表单数据<br> * 设置表单数据<br>
* *
* @param name * @param name
* @param value * @param value
* @return this * @return this
*/ */
@ -469,12 +502,11 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 设置表单数据 * 设置表单数据
* *
* @param name * @param name
* @param value * @param value
* @param parameters 参数对奇数为名偶数为值 * @param parameters 参数对奇数为名偶数为值
* @return this * @return this
*
*/ */
public HttpRequest form(String name, Object value, Object... parameters) { public HttpRequest form(String name, Object value, Object... parameters) {
form(name, value); form(name, value);
@ -488,10 +520,9 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 设置map类型表单数据 * 设置map类型表单数据
* *
* @param formMap 表单内容 * @param formMap 表单内容
* @return this * @return this
*
*/ */
public HttpRequest form(Map<String, Object> formMap) { public HttpRequest form(Map<String, Object> formMap) {
if (MapUtil.isNotEmpty(formMap)) { if (MapUtil.isNotEmpty(formMap)) {
@ -505,8 +536,8 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 文件表单项<br> * 文件表单项<br>
* 一旦有文件加入表单变为multipart/form-data * 一旦有文件加入表单变为multipart/form-data
* *
* @param name * @param name
* @param files 需要上传的文件 * @param files 需要上传的文件
* @return this * @return this
*/ */
@ -521,7 +552,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 文件表单项<br> * 文件表单项<br>
* 一旦有文件加入表单变为multipart/form-data * 一旦有文件加入表单变为multipart/form-data
* *
* @param name * @param name
* @param file 需要上传的文件 * @param file 需要上传的文件
* @return this * @return this
@ -533,9 +564,9 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 文件表单项<br> * 文件表单项<br>
* 一旦有文件加入表单变为multipart/form-data * 一旦有文件加入表单变为multipart/form-data
* *
* @param name * @param name
* @param file 需要上传的文件 * @param file 需要上传的文件
* @param fileName 文件名为空使用文件默认的文件名 * @param fileName 文件名为空使用文件默认的文件名
* @return this * @return this
*/ */
@ -549,10 +580,10 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 文件byte[]表单项<br> * 文件byte[]表单项<br>
* 一旦有文件加入表单变为multipart/form-data * 一旦有文件加入表单变为multipart/form-data
* *
* @param name * @param name
* @param fileBytes 需要上传的文件 * @param fileBytes 需要上传的文件
* @param fileName 文件名 * @param fileName 文件名
* @return this * @return this
* @since 4.1.0 * @since 4.1.0
*/ */
@ -566,8 +597,8 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 文件表单项<br> * 文件表单项<br>
* 一旦有文件加入表单变为multipart/form-data * 一旦有文件加入表单变为multipart/form-data
* *
* @param name * @param name
* @param resource 数据源文件可以使用{@link FileResource}包装使用 * @param resource 数据源文件可以使用{@link FileResource}包装使用
* @return this * @return this
* @since 4.0.9 * @since 4.0.9
@ -589,7 +620,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 获取表单数据 * 获取表单数据
* *
* @return 表单Map * @return 表单Map
*/ */
public Map<String, Object> form() { public Map<String, Object> form() {
@ -598,7 +629,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 获取文件表单数据 * 获取文件表单数据
* *
* @return 文件表单Map * @return 文件表单Map
* @since 3.3.0 * @since 3.3.0
*/ */
@ -608,15 +639,16 @@ public class HttpRequest extends HttpBase<HttpRequest> {
// ---------------------------------------------------------------- Form end // ---------------------------------------------------------------- Form end
// ---------------------------------------------------------------- Body start // ---------------------------------------------------------------- Body start
/** /**
* 设置内容主体<br> * 设置内容主体<br>
* 请求体body参数支持两种类型 * 请求体body参数支持两种类型
* *
* <pre> * <pre>
* 1. 标准参数例如 a=1&amp;b=2 这种格式 * 1. 标准参数例如 a=1&amp;b=2 这种格式
* 2. Rest模式此时body需要传入一个JSON或者XML字符串Hutool会自动绑定其对应的Content-Type * 2. Rest模式此时body需要传入一个JSON或者XML字符串Hutool会自动绑定其对应的Content-Type
* </pre> * </pre>
* *
* @param body 请求体 * @param body 请求体
* @return this * @return this
*/ */
@ -627,13 +659,13 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 设置内容主体<br> * 设置内容主体<br>
* 请求体body参数支持两种类型 * 请求体body参数支持两种类型
* *
* <pre> * <pre>
* 1. 标准参数例如 a=1&amp;b=2 这种格式 * 1. 标准参数例如 a=1&amp;b=2 这种格式
* 2. Rest模式此时body需要传入一个JSON或者XML字符串Hutool会自动绑定其对应的Content-Type * 2. Rest模式此时body需要传入一个JSON或者XML字符串Hutool会自动绑定其对应的Content-Type
* </pre> * </pre>
* *
* @param body 请求体 * @param body 请求体
* @param contentType 请求体类型{@code null}表示自动判断类型 * @param contentType 请求体类型{@code null}表示自动判断类型
* @return this * @return this
*/ */
@ -668,7 +700,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 设置JSON内容主体<br> * 设置JSON内容主体<br>
* 设置默认的Content-Type为 application/json 需在此方法调用前使用charset方法设置编码否则使用默认编码UTF-8 * 设置默认的Content-Type为 application/json 需在此方法调用前使用charset方法设置编码否则使用默认编码UTF-8
* *
* @param json JSON请求体 * @param json JSON请求体
* @return this * @return this
* @deprecated 未来可能去除此方法使用{@link #body(String)} 传入JSON字符串即可 * @deprecated 未来可能去除此方法使用{@link #body(String)} 传入JSON字符串即可
@ -681,13 +713,14 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 设置主体字节码<br> * 设置主体字节码<br>
* 需在此方法调用前使用charset方法设置编码否则使用默认编码UTF-8 * 需在此方法调用前使用charset方法设置编码否则使用默认编码UTF-8
* *
* @param bodyBytes 主体 * @param bodyBytes 主体
* @return this * @return this
*/ */
public HttpRequest body(byte[] bodyBytes) { public HttpRequest body(byte[] bodyBytes) {
Assert.notNull(bodyBytes, "Body must be not null !"); if (null != bodyBytes) {
this.bodyBytes = bodyBytes; this.bodyBytes = bodyBytes;
}
return this; return this;
} }
// ---------------------------------------------------------------- Body end // ---------------------------------------------------------------- Body end
@ -695,12 +728,12 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 设置超时单位毫秒<br> * 设置超时单位毫秒<br>
* 超时包括 * 超时包括
* *
* <pre> * <pre>
* 1. 连接超时 * 1. 连接超时
* 2. 读取响应超时 * 2. 读取响应超时
* </pre> * </pre>
* *
* @param milliseconds 超时毫秒数 * @param milliseconds 超时毫秒数
* @return this * @return this
* @see #setConnectionTimeout(int) * @see #setConnectionTimeout(int)
@ -714,7 +747,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 设置连接超时单位毫秒 * 设置连接超时单位毫秒
* *
* @param milliseconds 超时毫秒数 * @param milliseconds 超时毫秒数
* @return this * @return this
* @since 4.5.6 * @since 4.5.6
@ -726,7 +759,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 设置连接超时单位毫秒 * 设置连接超时单位毫秒
* *
* @param milliseconds 超时毫秒数 * @param milliseconds 超时毫秒数
* @return this * @return this
* @since 4.5.6 * @since 4.5.6
@ -738,7 +771,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 禁用缓存 * 禁用缓存
* *
* @return this * @return this
*/ */
public HttpRequest disableCache() { public HttpRequest disableCache() {
@ -748,7 +781,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 是否对URL中的参数进行编码 * 是否对URL中的参数进行编码
* *
* @param isEncodeUrlParams 是否对URL中的参数进行编码 * @param isEncodeUrlParams 是否对URL中的参数进行编码
* @return this * @return this
* @since 4.4.1 * @since 4.4.1
@ -761,7 +794,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 设置是否打开重定向如果打开默认重定向次数为2<br> * 设置是否打开重定向如果打开默认重定向次数为2<br>
* 此方法效果与{@link #setMaxRedirectCount(int)} 一致 * 此方法效果与{@link #setMaxRedirectCount(int)} 一致
* *
* @param isFollowRedirects 是否打开重定向 * @param isFollowRedirects 是否打开重定向
* @return this * @return this
*/ */
@ -772,7 +805,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 设置最大重定向次数<br> * 设置最大重定向次数<br>
* 如果次数小于1则表示不重定向大于等于1表示打开重定向 * 如果次数小于1则表示不重定向大于等于1表示打开重定向
* *
* @param maxRedirectCount 最大重定向次数 * @param maxRedirectCount 最大重定向次数
* @return this * @return this
* @since 3.3.0 * @since 3.3.0
@ -789,7 +822,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 设置域名验证器<br> * 设置域名验证器<br>
* 只针对HTTPS请求如果不设置不做验证所有域名被信任 * 只针对HTTPS请求如果不设置不做验证所有域名被信任
* *
* @param hostnameVerifier HostnameVerifier * @param hostnameVerifier HostnameVerifier
* @return this * @return this
*/ */
@ -801,7 +834,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 设置代理 * 设置代理
* *
* @param proxy 代理 {@link Proxy} * @param proxy 代理 {@link Proxy}
* @return this * @return this
*/ */
@ -814,7 +847,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
* 设置SSLSocketFactory<br> * 设置SSLSocketFactory<br>
* 只针对HTTPS请求如果不设置使用默认的SSLSocketFactory<br> * 只针对HTTPS请求如果不设置使用默认的SSLSocketFactory<br>
* 默认SSLSocketFactory为SSLSocketFactoryBuilder.create().build(); * 默认SSLSocketFactory为SSLSocketFactoryBuilder.create().build();
* *
* @param ssf SSLScketFactory * @param ssf SSLScketFactory
* @return this * @return this
*/ */
@ -825,17 +858,17 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 设置HTTPS安全连接协议只针对HTTPS请求可以使用的协议包括<br> * 设置HTTPS安全连接协议只针对HTTPS请求可以使用的协议包括<br>
* *
* <pre> * <pre>
* 1. TLSv1.2 * 1. TLSv1.2
* 2. TLSv1.1 * 2. TLSv1.1
* 3. SSLv3 * 3. SSLv3
* ... * ...
* </pre> * </pre>
* *
* @see SSLSocketFactoryBuilder
* @param protocol 协议 * @param protocol 协议
* @return this * @return this
* @see SSLSocketFactoryBuilder
*/ */
public HttpRequest setSSLProtocol(String protocol) { public HttpRequest setSSLProtocol(String protocol) {
if (null == this.ssf) { if (null == this.ssf) {
@ -850,7 +883,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 设置是否rest模式 * 设置是否rest模式
* *
* @param isRest 是否rest模式 * @param isRest 是否rest模式
* @return this * @return this
* @since 4.5.0 * @since 4.5.0
@ -859,11 +892,11 @@ public class HttpRequest extends HttpBase<HttpRequest> {
this.isRest = isRest; this.isRest = isRest;
return this; return this;
} }
/** /**
* 采用流方式上传数据无需本地缓存数据<br> * 采用流方式上传数据无需本地缓存数据<br>
* HttpUrlConnection默认是将所有数据读到本地缓存然后再发送给服务器这样上传大文件时就会导致内存溢出 * HttpUrlConnection默认是将所有数据读到本地缓存然后再发送给服务器这样上传大文件时就会导致内存溢出
* *
* @param blockSize 块大小bytes数0或小于0表示不设置Chuncked模式 * @param blockSize 块大小bytes数0或小于0表示不设置Chuncked模式
* @return this * @return this
* @since 4.6.5 * @since 4.6.5
@ -875,7 +908,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 执行Reuqest请求 * 执行Reuqest请求
* *
* @return this * @return this
*/ */
public HttpResponse execute() { public HttpResponse execute() {
@ -886,11 +919,10 @@ public class HttpRequest extends HttpBase<HttpRequest> {
* 异步请求<br> * 异步请求<br>
* 异步请求后获取的{@link HttpResponse} 为异步模式执行完此方法后发送请求到服务器但是并不立即读取响应内容<br> * 异步请求后获取的{@link HttpResponse} 为异步模式执行完此方法后发送请求到服务器但是并不立即读取响应内容<br>
* 此时保持Http连接不关闭直调用获取内容方法为止 * 此时保持Http连接不关闭直调用获取内容方法为止
* *
* <p> * <p>
* 一般执行完execute之后会把响应内容全部读出来放在一个 byte数组里如果你响应的内容太多内存就爆了此法是发送完请求不直接读响应内容等有需要的时候读 * 一般执行完execute之后会把响应内容全部读出来放在一个 byte数组里如果你响应的内容太多内存就爆了此法是发送完请求不直接读响应内容等有需要的时候读
*
*
* @return 异步对象使用get方法获取HttpResponse对象 * @return 异步对象使用get方法获取HttpResponse对象
*/ */
public HttpResponse executeAsync() { public HttpResponse executeAsync() {
@ -899,7 +931,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 执行Reuqest请求 * 执行Reuqest请求
* *
* @param isAsync 是否异步 * @param isAsync 是否异步
* @return this * @return this
*/ */
@ -928,7 +960,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 简单验证 * 简单验证
* *
* @param username 用户名 * @param username 用户名
* @param password 密码 * @param password 密码
* @return HttpRequest * @return HttpRequest
@ -943,15 +975,16 @@ public class HttpRequest extends HttpBase<HttpRequest> {
} }
// ---------------------------------------------------------------- Private method start // ---------------------------------------------------------------- Private method start
/** /**
* 初始化网络连接 * 初始化网络连接
*/ */
private void initConnecton() { private void initConnecton() {
if(null != this.httpConnection) { if (null != this.httpConnection) {
// 执行下次请求时自动关闭上次请求常用于转发 // 执行下次请求时自动关闭上次请求常用于转发
this.httpConnection.disconnectQuietly(); this.httpConnection.disconnectQuietly();
} }
this.httpConnection = HttpConnection.create(URLUtil.toUrlForHttp(this.url, this.urlHandler), this.proxy)// this.httpConnection = HttpConnection.create(URLUtil.toUrlForHttp(this.url, this.urlHandler), this.proxy)//
.setMethod(this.method)// .setMethod(this.method)//
.setHttpsInfo(this.hostnameVerifier, this.ssf)// .setHttpsInfo(this.hostnameVerifier, this.ssf)//
@ -965,7 +998,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
.setChunkedStreamingMode(this.blockSize) .setChunkedStreamingMode(this.blockSize)
// 覆盖默认Header // 覆盖默认Header
.header(this.headers, true); .header(this.headers, true);
// 读取全局Cookie信息并附带到请求中 // 读取全局Cookie信息并附带到请求中
GlobalCookieManager.add(this.httpConnection); GlobalCookieManager.add(this.httpConnection);
@ -992,7 +1025,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 调用转发如果需要转发返回转发结果否则返回<code>null</code> * 调用转发如果需要转发返回转发结果否则返回<code>null</code>
* *
* @return {@link HttpResponse}无转发返回 <code>null</code> * @return {@link HttpResponse}无转发返回 <code>null</code>
*/ */
private HttpResponse sendRedirectIfPosible() { private HttpResponse sendRedirectIfPosible() {
@ -1026,7 +1059,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 发送数据流 * 发送数据流
* *
* @throws IOException * @throws IOException
*/ */
private void send() throws HttpException { private void send() throws HttpException {
@ -1050,7 +1083,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 发送普通表单<br> * 发送普通表单<br>
* 发送数据后自动关闭输出流 * 发送数据后自动关闭输出流
* *
* @throws IOException * @throws IOException
*/ */
private void sendFormUrlEncoded() throws IOException { private void sendFormUrlEncoded() throws IOException {
@ -1071,13 +1104,13 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 发送多组件请求例如包含文件的表单<br> * 发送多组件请求例如包含文件的表单<br>
* 发送数据后自动关闭输出流 * 发送数据后自动关闭输出流
* *
* @throws IOException * @throws IOException
*/ */
private void sendMultipart() throws IOException { private void sendMultipart() throws IOException {
setMultipart();// 设置表单类型为Multipart setMultipart();// 设置表单类型为Multipart
try(OutputStream out = this.httpConnection.getOutputStream()) { try (OutputStream out = this.httpConnection.getOutputStream()) {
writeFileForm(out); writeFileForm(out);
writeForm(out); writeForm(out);
formEnd(out); formEnd(out);
@ -1087,9 +1120,10 @@ public class HttpRequest extends HttpBase<HttpRequest> {
} }
// 普通字符串数据 // 普通字符串数据
/** /**
* 发送普通表单内容 * 发送普通表单内容
* *
* @param out 输出流 * @param out 输出流
* @throws IOException * @throws IOException
*/ */
@ -1107,7 +1141,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 发送文件对象表单 * 发送文件对象表单
* *
* @param out 输出流 * @param out 输出流
* @throws IOException * @throws IOException
*/ */
@ -1119,10 +1153,10 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 添加Multipart表单的数据项 * 添加Multipart表单的数据项
* *
* @param formFieldName 表单名 * @param formFieldName 表单名
* @param resource 资源可以是文件等 * @param resource 资源可以是文件等
* @param out Http流 * @param out Http流
* @since 4.1.0 * @since 4.1.0
*/ */
private void appendPart(String formFieldName, Resource resource, OutputStream out) { private void appendPart(String formFieldName, Resource resource, OutputStream out) {
@ -1152,9 +1186,10 @@ public class HttpRequest extends HttpBase<HttpRequest> {
} }
// 添加结尾数据 // 添加结尾数据
/** /**
* 上传表单结束 * 上传表单结束
* *
* @param out 输出流 * @param out 输出流
* @throws IOException * @throws IOException
*/ */
@ -1165,7 +1200,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 设置表单类型为Multipart文件上传 * 设置表单类型为Multipart文件上传
* *
* @return HttpConnection * @return HttpConnection
*/ */
private void setMultipart() { private void setMultipart() {
@ -1175,7 +1210,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
/** /**
* 是否忽略读取响应body部分<br> * 是否忽略读取响应body部分<br>
* HEADCONNECTOPTIONSTRACE方法将不读取响应体 * HEADCONNECTOPTIONSTRACE方法将不读取响应体
* *
* @return 是否需要忽略响应body部分 * @return 是否需要忽略响应body部分
* @since 3.1.2 * @since 3.1.2
*/ */