add patch support

This commit is contained in:
Looly 2020-02-29 22:25:22 +08:00
parent 1ed2ec9dc4
commit 405a92cfe4
9 changed files with 124 additions and 77 deletions

View File

@ -10,6 +10,7 @@
* 【core 】 增加ReflectUtil.getFieldValue支持Alias注解
* 【core 】 Bean字段支持Alias注解包括转map,转bean等
* 【core 】 增加ValueListHandler优化结果集获取方式
* 【http 】 支持patch方法issue#666@Github
### Bug修复

View File

@ -1849,7 +1849,9 @@ public class DateUtil {
* @param checkDate 检查时间可以是当前时间
* @return 是否过期
* @since 5.1.1
* @deprecated 使用isIn方法
*/
@Deprecated
public static boolean isExpired(Date startDate, Date endDate, Date checkDate) {
return betweenMs(startDate, checkDate) > betweenMs(startDate, endDate);
}

View File

@ -294,7 +294,7 @@ public class ReflectUtil {
/**
* 设置字段值
*
* @param obj 对象
* @param obj 对象,static字段则此处传Class
* @param fieldName 字段名
* @param value 值类型必须与字段类型匹配不会自动转换对象类型
* @throws UtilException 包装IllegalAccessException异常
@ -303,7 +303,7 @@ public class ReflectUtil {
Assert.notNull(obj);
Assert.notBlank(fieldName);
final Field field = getField(obj.getClass(), fieldName);
final Field field = getField((obj instanceof Class) ? (Class<?>)obj : obj.getClass(), fieldName);
Assert.notNull(field, "Field [{}] is not exist in [{}]", fieldName, obj.getClass().getName());
setFieldValue(obj, field, value);
}
@ -317,9 +317,7 @@ public class ReflectUtil {
* @throws UtilException UtilException 包装IllegalAccessException异常
*/
public static void setFieldValue(Object obj, Field field, Object value) throws UtilException {
Assert.notNull(field, "Field in [{}] not exist !", obj.getClass().getName());
setAccessible(field);
Assert.notNull(field, "Field in [{}] not exist !", obj);
if (null != value) {
Class<?> fieldType = field.getType();
@ -332,10 +330,11 @@ public class ReflectUtil {
}
}
setAccessible(field);
try {
field.set(obj, value);
field.set(obj instanceof Class ? null : obj, value);
} catch (IllegalAccessException e) {
throw new UtilException(e, "IllegalAccess for {}.{}", obj.getClass(), field.getName());
throw new UtilException(e, "IllegalAccess for {}.{}", obj, field.getName());
}
}

View File

@ -82,6 +82,14 @@ public class DateUtilTest {
Assert.assertEquals("2017-03-01 23:59:59", endOfDay.toString());
}
@Test
public void truncateTest(){
String dateStr2 = "2020-02-29 12:59:34";
Date date2 = DateUtil.parse(dateStr2);
final DateTime dateTime = DateUtil.truncate(date2, DateField.MINUTE);
Assert.assertEquals("2020-02-29 12:59:00", dateTime.toString());
}
@Test
public void beginAndWeedTest() {
String dateStr = "2017-03-01 22:33:23";

View File

@ -2,11 +2,10 @@ package cn.hutool.http;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.ssl.AndroidSupportSSLFactory;
import cn.hutool.http.ssl.DefaultSSLInfo;
import cn.hutool.http.ssl.SSLSocketFactoryBuilder;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
@ -14,6 +13,8 @@ import javax.net.ssl.SSLSocketFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.Proxy;
@ -21,17 +22,14 @@ import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
/**
* http连接对象对HttpURLConnection的包装
*
* @author Looly
*
* @author Looly
*/
public class HttpConnection {
@ -41,9 +39,9 @@ public class HttpConnection {
/**
* 创建HttpConnection
*
*
* @param urlStr URL
* @param proxy 代理无代理传{@code null}
* @param proxy 代理无代理传{@code null}
* @return HttpConnection
*/
public static HttpConnection create(String urlStr, Proxy proxy) {
@ -52,8 +50,8 @@ public class HttpConnection {
/**
* 创建HttpConnection
*
* @param url URL
*
* @param url URL
* @param proxy 代理无代理传{@code null}
* @return HttpConnection
*/
@ -62,10 +60,11 @@ public class HttpConnection {
}
// --------------------------------------------------------------- Constructor start
/**
* 构造HttpConnection
*
* @param url URL
*
* @param url URL
* @param proxy 代理
*/
public HttpConnection(URL url, Proxy proxy) {
@ -80,7 +79,7 @@ public class HttpConnection {
/**
* 初始化连接相关信息
*
*
* @return HttpConnection
* @since 4.4.1
*/
@ -98,10 +97,11 @@ public class HttpConnection {
}
// --------------------------------------------------------------- Getters And Setters start
/**
* 获取请求方法,GET/POST
*
* @return 请求方法,GET/POST
*
* @return 请求方法, GET/POST
*/
public Method getMethod() {
return Method.valueOf(this.conn.getRequestMethod());
@ -109,11 +109,23 @@ public class HttpConnection {
/**
* 设置请求方法
*
*
* @param method 请求方法
* @return 自己
*/
public HttpConnection setMethod(Method method) {
if (Method.POST.equals(method) //
|| Method.PUT.equals(method)//
|| Method.PATCH.equals(method)//
|| Method.DELETE.equals(method)) {
this.conn.setUseCaches(false);
// 增加PATCH方法支持
if (Method.PATCH.equals(method)) {
allowPatch();
}
}
// method
try {
this.conn.setRequestMethod(method.toString());
@ -121,18 +133,12 @@ public class HttpConnection {
throw new HttpException(e);
}
if (Method.POST.equals(method) //
|| Method.PUT.equals(method)//
|| Method.PATCH.equals(method)//
|| Method.DELETE.equals(method)) {
this.conn.setUseCaches(false);
}
return this;
}
/**
* 获取请求URL
*
*
* @return 请求URL
*/
public URL getUrl() {
@ -141,7 +147,7 @@ public class HttpConnection {
/**
* 获得代理
*
*
* @return {@link Proxy}
*/
public Proxy getProxy() {
@ -150,7 +156,7 @@ public class HttpConnection {
/**
* 获取HttpURLConnection对象
*
*
* @return HttpURLConnection
*/
public HttpURLConnection getHttpURLConnection() {
@ -160,12 +166,13 @@ public class HttpConnection {
// --------------------------------------------------------------- Getters And Setters end
// ---------------------------------------------------------------- Headers start
/**
* 设置请求头<br>
* 当请求头存在时覆盖之
*
* @param header 头名
* @param value 头值
*
* @param header 头名
* @param value 头值
* @param isOverride 是否覆盖旧值
* @return HttpConnection
*/
@ -184,9 +191,9 @@ public class HttpConnection {
/**
* 设置请求头<br>
* 当请求头存在时覆盖之
*
* @param header 头名
* @param value 头值
*
* @param header 头名
* @param value 头值
* @param isOverride 是否覆盖旧值
* @return HttpConnection
*/
@ -197,8 +204,8 @@ public class HttpConnection {
/**
* 设置请求头<br>
* 不覆盖原有请求头
*
* @param headerMap 请求头
*
* @param headerMap 请求头
* @param isOverride 是否覆盖
* @return this
*/
@ -217,7 +224,7 @@ public class HttpConnection {
/**
* 获取Http请求头
*
*
* @param name Header名
* @return Http请求头值
*/
@ -227,7 +234,7 @@ public class HttpConnection {
/**
* 获取Http请求头
*
*
* @param name Header名
* @return Http请求头值
*/
@ -237,7 +244,7 @@ public class HttpConnection {
/**
* 获取所有Http请求头
*
*
* @return Http请求头Map
*/
public Map<String, List<String>> headers() {
@ -249,9 +256,9 @@ public class HttpConnection {
/**
* 设置https请求参数<br>
* 有些时候htts请求会出现com.sun.net.ssl.internal.www.protocol.https.HttpsURLConnectionOldImpl的实现此为sun内部api按照普通http请求处理
*
*
* @param hostnameVerifier 域名验证器非https传入null
* @param ssf SSLSocketFactory非https传入null
* @param ssf SSLSocketFactory非https传入null
* @return this
* @throws HttpException KeyManagementException和NoSuchAlgorithmException异常包装
*/
@ -271,9 +278,9 @@ public class HttpConnection {
/**
* 关闭缓存
*
*
* @return this
* @see HttpURLConnection#setUseCaches(boolean)
* @see HttpURLConnection#setUseCaches(boolean)
*/
public HttpConnection disableCache() {
this.conn.setUseCaches(false);
@ -282,7 +289,7 @@ public class HttpConnection {
/**
* 设置连接超时
*
*
* @param timeout 超时
* @return this
*/
@ -296,7 +303,7 @@ public class HttpConnection {
/**
* 设置读取超时
*
*
* @param timeout 超时
* @return this
*/
@ -310,7 +317,7 @@ public class HttpConnection {
/**
* 设置连接和读取的超时时间
*
*
* @param timeout 超时时间
* @return this
*/
@ -323,7 +330,7 @@ public class HttpConnection {
/**
* 设置Cookie
*
*
* @param cookie Cookie
* @return this
*/
@ -337,12 +344,12 @@ public class HttpConnection {
/**
* 采用流方式上传数据无需本地缓存数据<br>
* HttpUrlConnection默认是将所有数据读到本地缓存然后再发送给服务器这样上传大文件时就会导致内存溢出
*
*
* @param blockSize 块大小bytes数0或小于0表示不设置Chuncked模式
* @return this
*/
public HttpConnection setChunkedStreamingMode(int blockSize) {
if(blockSize > 0) {
if (blockSize > 0) {
conn.setChunkedStreamingMode(blockSize);
}
return this;
@ -350,7 +357,7 @@ public class HttpConnection {
/**
* 设置自动HTTP 30X跳转
*
*
* @param isInstanceFollowRedirects 是否自定跳转
* @return this
*/
@ -361,7 +368,7 @@ public class HttpConnection {
/**
* 连接
*
*
* @return this
* @throws IOException IO异常
*/
@ -371,10 +378,10 @@ public class HttpConnection {
}
return this;
}
/**
* 静默断开连接不抛出异常
*
*
* @return this
* @since 4.6.0
*/
@ -384,13 +391,13 @@ public class HttpConnection {
} catch (Throwable e) {
// ignore
}
return this;
}
/**
* 断开连接
*
*
* @return this
*/
public HttpConnection disconnect() {
@ -403,7 +410,7 @@ public class HttpConnection {
/**
* 获得输入流对象<br>
* 输入流对象用于读取数据
*
*
* @return 输入流对象
* @throws IOException IO异常
*/
@ -416,7 +423,7 @@ public class HttpConnection {
/**
* 当返回错误代码时获得错误内容流
*
*
* @return 错误内容
*/
public InputStream getErrorStream() {
@ -428,7 +435,7 @@ public class HttpConnection {
/**
* 获取输出流对象 输出流对象用于发送数据
*
*
* @return OutputStream
* @throws IOException IO异常
*/
@ -444,7 +451,7 @@ public class HttpConnection {
/**
* 获取响应码
*
*
* @return 响应码
* @throws IOException IO异常
*/
@ -459,7 +466,7 @@ public class HttpConnection {
* 获得字符集编码<br>
* 从Http连接的头信息中获得字符集<br>
* 从ContentType中获取
*
*
* @return 字符集编码
*/
public String getCharsetName() {
@ -470,7 +477,7 @@ public class HttpConnection {
* 获取字符集编码<br>
* 从Http连接的头信息中获得字符集<br>
* 从ContentType中获取
*
*
* @return {@link Charset}编码
* @since 3.0.9
*/
@ -501,10 +508,11 @@ public class HttpConnection {
}
// --------------------------------------------------------------- Private Method start
/**
* 初始化http或https请求参数<br>
* 有些时候https请求会出现com.sun.net.ssl.internal.www.protocol.https.HttpsURLConnectionOldImpl的实现此为sun内部api按照普通http请求处理
*
*
* @return {@link HttpURLConnection}https返回{@link HttpsURLConnection}
*/
private HttpURLConnection openHttp() throws IOException {
@ -519,12 +527,30 @@ public class HttpConnection {
/**
* 建立连接
*
*
* @return {@link URLConnection}
* @throws IOException IO异常
*/
private URLConnection openConnection() throws IOException {
return (null == this.proxy) ? url.openConnection() : url.openConnection(this.proxy);
}
/**
* 增加支持的METHOD方法
* see: https://stackoverflow.com/questions/25163131/httpurlconnection-invalid-http-method-patch
*
* @since 5.1.6
*/
private static void allowPatch() {
final Field methodsField = ReflectUtil.getField(HttpURLConnection.class, "methods");
if (null != methodsField) {
// 去除final修饰
ReflectUtil.setFieldValue(methodsField, "modifiers", methodsField.getModifiers() & ~Modifier.FINAL);
final String[] methods = {
"GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE", "PATCH"
};
ReflectUtil.setFieldValue(null, methodsField, methods);
}
}
// --------------------------------------------------------------- Private Method end
}

View File

@ -338,13 +338,14 @@ public class HttpRequest extends HttpBase<HttpRequest> {
* @return HttpRequest
*/
public HttpRequest method(Method method) {
if (Method.PATCH == method) {
this.method = Method.POST;
this.header("X-HTTP-Method-Override", "PATCH");
} else {
this.method = method;
}
// if (Method.PATCH == method) {
// this.method = Method.POST;
// this.header("X-HTTP-Method-Override", "PATCH");
// } else {
// this.method = method;
// }
this.method = method;
return this;
}

View File

@ -9,14 +9,24 @@ import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.StreamProgress;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.*;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.nio.charset.Charset;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;

View File

@ -2,8 +2,8 @@ package cn.hutool.http;
/**
* Http方法枚举
* @author Looly
*
* @author Looly
*/
public enum Method {
GET, POST, HEAD, OPTIONS, PUT, DELETE, TRACE, CONNECT, PATCH

View File

@ -220,7 +220,7 @@ public class HttpUtilTest {
@Test
@Ignore
public void patchTest() {
String body = HttpRequest.post("https://www.baidu.com").execute().body();
String body = HttpRequest.patch("https://www.baidu.com").execute().body();
Console.log(body);
}