This commit is contained in:
Looly 2023-03-05 17:05:40 +08:00
parent ca59e1471d
commit 1eb629bc3b
4 changed files with 70 additions and 394 deletions

View File

@ -196,8 +196,8 @@ public class Ipv4UtilTest {
public void getMaskBitByIpRange() {
final String ip = "192.168.100.2";
for (int i = 1; i <= 32; i++) {
String beginIpStr = Ipv4Util.getBeginIpStr(ip, i);
String endIpStr = Ipv4Util.getEndIpStr(ip, i);
final String beginIpStr = Ipv4Util.getBeginIpStr(ip, i);
final String endIpStr = Ipv4Util.getEndIpStr(ip, i);
Assert.assertEquals(Ipv4Util.getMaskByMaskBit(i), Ipv4Util.getMaskByIpRange(beginIpStr, endIpStr));
}
}

View File

@ -1,321 +0,0 @@
package cn.hutool.http.client.engine.jdk;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.CaseInsensitiveMap;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.text.StrUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.http.meta.Header;
import cn.hutool.http.client.HeaderOperation;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
/**
* http基类提供请求和响应共用的属性和方法
*
* @param <T> 子类类型方便链式编程
* @author Looly
*/
@SuppressWarnings("unchecked")
public abstract class HttpBase<T extends HttpBase<T>> implements HeaderOperation<T> {
/**
* 默认的请求编码URL的encodedecode编码
*/
protected static final Charset DEFAULT_CHARSET = CharsetUtil.UTF_8;
/**
* HTTP/1.0
*/
public static final String HTTP_1_0 = "HTTP/1.0";
/**
* HTTP/1.1
*/
public static final String HTTP_1_1 = "HTTP/1.1";
/**
* 存储头信息
*/
protected Map<String, List<String>> headers = new HashMap<>();
/**
* 编码
*/
protected Charset charset = DEFAULT_CHARSET;
/**
* http版本
*/
protected String httpVersion = HTTP_1_1;
/**
* 存储主体
*/
protected byte[] bodyBytes;
// ---------------------------------------------------------------- Headers start
/**
* 根据name获取头信息列表
*
* @param name Header名
* @return Header值
* @since 3.1.1
*/
public List<String> headerList(final String name) {
if (StrUtil.isBlank(name)) {
return null;
}
final CaseInsensitiveMap<String, List<String>> headersIgnoreCase = new CaseInsensitiveMap<>(this.headers);
return headersIgnoreCase.get(name.trim());
}
/**
* 根据name获取头信息
*
* @param header Header名
* @return Header值
*/
public String header(final Header header) {
if (null == header) {
return null;
}
return header(header.toString());
}
/**
* 设置一个header<br>
* 如果覆盖模式则替换之前的值否则加入到值列表中
*
* @param name Header名
* @param value Header值
* @param isOverride 是否覆盖已有值
* @return T 本身
*/
@Override
public T header(final String name, final String value, final boolean isOverride) {
if (null != name && null != value) {
final List<String> values = headers.get(name.trim());
if (isOverride || CollUtil.isEmpty(values)) {
final ArrayList<String> valueList = new ArrayList<>();
valueList.add(value);
headers.put(name.trim(), valueList);
} else {
values.add(value.trim());
}
}
return (T) this;
}
/**
* 设置请求头
*
* @param headers 请求头
* @param isOverride 是否覆盖已有头信息
* @return this
* @since 4.6.3
*/
public T headerMap(final Map<String, String> headers, final boolean isOverride) {
if (MapUtil.isEmpty(headers)) {
return (T) this;
}
for (final Entry<String, String> entry : headers.entrySet()) {
this.header(entry.getKey(), StrUtil.emptyIfNull(entry.getValue()), isOverride);
}
return (T) this;
}
/**
* 设置请求头<br>
* 不覆盖原有请求头
*
* @param headers 请求头
* @return this
*/
public T header(final Map<String, List<String>> headers) {
return header(headers, false);
}
/**
* 设置请求头
*
* @param headers 请求头
* @param isOverride 是否覆盖已有头信息
* @return this
* @since 4.0.8
*/
public T header(final Map<String, List<String>> headers, final boolean isOverride) {
if (MapUtil.isEmpty(headers)) {
return (T) this;
}
String name;
for (final Entry<String, List<String>> entry : headers.entrySet()) {
name = entry.getKey();
for (final String value : entry.getValue()) {
this.header(name, StrUtil.emptyIfNull(value), isOverride);
}
}
return (T) this;
}
/**
* 新增请求头<br>
* 不覆盖原有请求头
*
* @param headers 请求头
* @return this
* @since 4.0.3
*/
public T addHeaders(final Map<String, String> headers) {
if (MapUtil.isEmpty(headers)) {
return (T) this;
}
for (final Entry<String, String> entry : headers.entrySet()) {
this.header(entry.getKey(), StrUtil.emptyIfNull(entry.getValue()), false);
}
return (T) this;
}
/**
* 移除一个头信息
*
* @param name Header名
* @return this
*/
public T removeHeader(final String name) {
if (name != null) {
headers.remove(name.trim());
}
return (T) this;
}
/**
* 移除一个头信息
*
* @param name Header名
* @return this
*/
public T removeHeader(final Header name) {
return removeHeader(name.toString());
}
/**
* 获取headers
*
* @return Headers Map
*/
@Override
public Map<String, List<String>> headers() {
return Collections.unmodifiableMap(headers);
}
/**
* 清除所有头信息包括全局头信息
*
* @return this
* @since 5.7.13
*/
public T clearHeaders() {
this.headers.clear();
return (T) this;
}
// ---------------------------------------------------------------- Headers end
/**
* 返回http版本
*
* @return String
*/
public String httpVersion() {
return httpVersion;
}
/**
* 设置http版本此方法不会影响到实际请求的HTTP版本只用于帮助判断是否connect:Keep-Alive
*
* @param httpVersion Http版本{@link HttpBase#HTTP_1_0}{@link HttpBase#HTTP_1_1}
* @return this
*/
public T httpVersion(final String httpVersion) {
this.httpVersion = httpVersion;
return (T) this;
}
/**
* 返回字符集
*
* @return 字符集
*/
public String charsetName() {
return charset.name();
}
/**
* 返回字符集
*
* @return 字符集
*/
public Charset charset() {
return this.charset;
}
/**
* 设置字符集
*
* @param charset 字符集
* @return T 自己
* @see CharsetUtil
*/
public T charset(final String charset) {
if (StrUtil.isNotBlank(charset)) {
charset(Charset.forName(charset));
}
return (T) this;
}
/**
* 设置字符集
*
* @param charset 字符集
* @return T 自己
* @see CharsetUtil
*/
public T charset(final Charset charset) {
if (null != charset) {
this.charset = charset;
}
return (T) this;
}
/**
* 获取bodyBytes存储字节码
*
* @return byte[]
*/
public byte[] bodyBytes() {
return this.bodyBytes;
}
@Override
public String toString() {
final StringBuilder sb = StrUtil.builder();
sb.append("Request Headers: ").append(StrUtil.CRLF);
for (final Entry<String, List<String>> entry : this.headers.entrySet()) {
sb.append(" ")
.append(entry.getKey()).append(":").append(CollUtil.join(entry.getValue(), ","))
.append(StrUtil.CRLF);
}
sb.append("Request Body: ").append(StrUtil.CRLF);
sb.append(" ").append(StrUtil.str(this.bodyBytes, this.charset)).append(StrUtil.CRLF);
return sb.toString();
}
}

View File

@ -4,13 +4,17 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.text.StrUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.XmlUtil;
import cn.hutool.http.HttpGlobalConfig;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.client.HeaderOperation;
import cn.hutool.http.client.Request;
import cn.hutool.http.client.Response;
import cn.hutool.http.client.engine.ClientEngineFactory;
import cn.hutool.http.client.engine.jdk.HttpBase;
import cn.hutool.http.meta.Header;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
@ -25,8 +29,7 @@ import javax.xml.soap.SOAPMessage;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
/**
@ -51,7 +54,7 @@ import java.util.Map.Entry;
* @author looly
* @since 4.5.4
*/
public class SoapClient extends HttpBase<SoapClient> {
public class SoapClient implements HeaderOperation<SoapClient> {
/**
* XML消息体的Content-Type
@ -66,15 +69,7 @@ public class SoapClient extends HttpBase<SoapClient> {
* 请求的URL地址
*/
private String url;
/**
* 默认连接超时
*/
private int connectionTimeout = HttpGlobalConfig.getTimeout();
/**
* 默认读取超时
*/
private int readTimeout = HttpGlobalConfig.getTimeout();
private Charset charset = CharsetUtil.UTF_8;
/**
* 消息工厂用于创建消息
@ -98,6 +93,10 @@ public class SoapClient extends HttpBase<SoapClient> {
* soap1.2 : application/soap+xml
*/
private final SoapProtocol protocol;
/**
* 存储头信息
*/
private final Map<String, List<String>> headers = new HashMap<>();
/**
* 创建SOAP客户端默认使用soap1.1版本协议
@ -211,20 +210,16 @@ public class SoapClient extends HttpBase<SoapClient> {
*
* @param charset 编码
* @return this
* @see #charset(Charset)
*/
public SoapClient setCharset(final Charset charset) {
return this.charset(charset);
}
@Override
public SoapClient charset(final Charset charset) {
super.charset(charset);
try {
this.message.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, this.charset());
this.message.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "true");
} catch (final SOAPException e) {
// ignore
if (null != charset) {
this.charset = charset;
try {
this.message.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, charset.name());
this.message.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "true");
} catch (final SOAPException e) {
// ignore
}
}
return this;
@ -241,6 +236,51 @@ public class SoapClient extends HttpBase<SoapClient> {
return this;
}
/**
* 设置一个header<br>
* 如果覆盖模式则替换之前的值否则加入到值列表中
*
* @param name Header名
* @param value Header值
* @param isOverride 是否覆盖已有值
* @return T 本身
*/
@Override
public SoapClient header(final String name, final String value, final boolean isOverride) {
if (null != name && null != value) {
final List<String> values = headers.get(name.trim());
if (isOverride || CollUtil.isEmpty(values)) {
final ArrayList<String> valueList = new ArrayList<>();
valueList.add(value);
headers.put(name.trim(), valueList);
} else {
values.add(value.trim());
}
}
return this;
}
/**
* 获取headers
*
* @return Headers Map
*/
@Override
public Map<String, List<String>> headers() {
return Collections.unmodifiableMap(headers);
}
/**
* 清除所有头信息包括全局头信息
*
* @return this
* @since 5.7.13
*/
public SoapClient clearHeaders() {
this.headers.clear();
return this;
}
/**
* 增加SOAP头信息方法返回{@link SOAPHeaderElement}可以设置具体属性和子节点
*
@ -493,50 +533,6 @@ public class SoapClient extends HttpBase<SoapClient> {
return this;
}
/**
* 设置超时单位毫秒<br>
* 超时包括
*
* <pre>
* 1. 连接超时
* 2. 读取响应超时
* </pre>
*
* @param milliseconds 超时毫秒数
* @return this
* @see #setConnectionTimeout(int)
* @see #setReadTimeout(int)
*/
public SoapClient timeout(final int milliseconds) {
setConnectionTimeout(milliseconds);
setReadTimeout(milliseconds);
return this;
}
/**
* 设置连接超时单位毫秒
*
* @param milliseconds 超时毫秒数
* @return this
* @since 4.5.6
*/
public SoapClient setConnectionTimeout(final int milliseconds) {
this.connectionTimeout = milliseconds;
return this;
}
/**
* 设置连接超时单位毫秒
*
* @param milliseconds 超时毫秒数
* @return this
* @since 4.5.6
*/
public SoapClient setReadTimeout(final int milliseconds) {
this.readTimeout = milliseconds;
return this;
}
/**
* 执行Webservice请求即发送SOAP内容
*
@ -574,6 +570,7 @@ public class SoapClient extends HttpBase<SoapClient> {
* @param pretty 是否格式化
* @return 返回结果
*/
@SuppressWarnings("resource")
public String send(final boolean pretty) {
final String body = sendForResponse().bodyStr();
return pretty ? XmlUtil.format(body) : body;
@ -592,7 +589,7 @@ public class SoapClient extends HttpBase<SoapClient> {
.contentType(getXmlContentType())
.header(this.headers, false)
.body(getMsgStr(false));
return ClientEngineFactory.get().send(request);
return request.send();
}
/**
@ -601,7 +598,7 @@ public class SoapClient extends HttpBase<SoapClient> {
* @return 请求的Content-Type
*/
private String getXmlContentType() {
switch (this.protocol){
switch (this.protocol) {
case SOAP_1_1:
return CONTENT_TYPE_SOAP11_TEXT_XML.concat(this.charset.toString());
case SOAP_1_2:

View File

@ -21,7 +21,7 @@ public class SoapClientTest {
public void requestTest() {
final SoapClient client = SoapClient.of("http://www.webxml.com.cn/WebServices/IpAddressSearchWebService.asmx")
.setMethod("web:getCountryCityByIp", "http://WebXml.com.cn/")
.setCharset(CharsetUtil.GBK)
.charset(CharsetUtil.GBK)
.setParam("theIpAddress", "218.21.240.106");
Console.log(client.getMsgStr(true));