Compare commits

..

2 Commits

115 changed files with 15431 additions and 811 deletions

View File

@ -1,9 +1,9 @@
window.Utils = {
class CusUtils {
/**
* @author youhong.ai
* @desc 发起请求
*/
request: function (url, type = "GET", data, isAsync = true, success = () => {
request(url, type = "GET", data, isAsync = true, success = () => {
}, error = () => {
}, complete = () => {
}, contentType = 'application/json', beforeSend = () => {
@ -24,13 +24,13 @@ window.Utils = {
options.data = JSON.stringify(data)
}
return $.ajax(options)
},
}
/**
* @author youhong.ai
* @desc 发起请求
*/
api: function (requestOptions = {
api(requestOptions = {
url: "",
type: "GET",
data: "",
@ -61,13 +61,13 @@ window.Utils = {
}
}, requestOptions)
return $.ajax(options)
},
}
/**
* @author youhong.ai
* @desc 获取react组件实例
*/
findReact: function (dom, traverseUp = 0) {
findReact(dom, traverseUp = 0) {
const key = Object.keys(dom).find(key => {
return key.startsWith("__reactFiber$") // react 17+
|| key.startsWith("__reactInternalInstance$")
@ -96,7 +96,7 @@ window.Utils = {
compFiber = GetCompFiber(compFiber);
}
return compFiber.stateNode;
},
}
/**
@ -104,7 +104,7 @@ window.Utils = {
* @param fieldName 字段名称
* @returns {*|string}
*/
convertNameToIdUtil: function (fieldName) {
convertNameToIdUtil(fieldName) {
let fieldIds = [];
if (fieldName instanceof Array) {
fieldName.forEach(item => {
@ -113,19 +113,19 @@ window.Utils = {
return fieldIds.join(',')
}
return Utils.convertNameObjToId(fieldName)
},
}
/**
* 将字段名称转为字段id
* @param fieldObj 字段名称对象 {string|object}
* @returns {*}
*/
convertNameObjToId: function (fieldObj = {fieldName: '', table: 'main'}) {
convertNameObjToId(fieldObj = {fieldName: '', table: 'main'}) {
if (typeof fieldObj === 'object') {
return WfForm.convertFieldNameToId(fieldObj.fieldName, fieldObj.table)
}
return WfForm.convertFieldNameToId(fieldObj)
},
}
/**
* 根据字段名称查询字段值
@ -133,17 +133,18 @@ window.Utils = {
* @param rowIndex 明细行下表明细获取才传递
* @returns {*} 字段值
*/
getFiledValueByName: function (fieldName, rowIndex) {
getFiledValueByName(fieldName, rowIndex) {
return WfForm.getFieldValue(Utils.convertNameObjToId(fieldName) + (rowIndex ? '_' + rowIndex : ''))
},
}
/**
* 通过字段名称修改字段值
* @param fieldName 字段名称
* @param value
*/
changeFieldValueByName: function (fieldName, value) {
changeFieldValueByName(fieldName, value) {
WfForm.changeFieldValue(Utils.convertNameObjToId(fieldName), {value})
}
}
window.Utils = new CusUtils()

View File

@ -1,3 +1,10 @@
const ecodeSDK = {}
ecodeSDK.setCom = (id, name, Com) => {
}
ecodeSDK.imp = (obj) => {
}
ecodeSDK.exp = (obj) => {
}
const WfForm = {
isMobile: () => {
// true表示是eMobile、微信、钉钉等移动终端false代表PC端

View File

@ -680,4 +680,62 @@ $(() => {
})
/* ******************* 明细数据数量统计添加 end ******************* */
/* ******************* 明细数据数量统计添加 end ******************* */
/* ******************* 计算年月日 start ******************* */
$(() => {
const config = [{
// 源字段
sourceField: '',
// 目标字段
targetField: '',
// 日期加月份字段
numberField: ''
}, {
sourceField: '',
targetField: '',
numberField: ''
}]
runJs();
function runJs() {
config.forEach(item => {
bindAction(item)
})
}
function bindAction(configItem) {
let fieldId = WfForm.convertFieldNameToId(configItem.numberField)
WfForm.bindFieldChangeEvent(fieldId, (obj, id, value) => {
if ("" == value) {
WfForm.changeFieldValue(WfForm.convertFieldNameToId(configItem.targetField, {value: ""}))
return
}
let sourceValue = WfForm.getFieldValue(WfForm.convertFieldNameToId(configItem.sourceField));
let date = new Date(sourceValue)
date.setMonth(date.getMonth() + +value)
let objectDate = new Date();
let day = objectDate.getDate();
let month = objectDate.getMonth() + 1;
let year = objectDate.getFullYear();
WfForm.changeFieldValue(WfForm.convertFieldNameToId(configItem.targetField, {
value: `${year}-${fullNum(month)}-${fullNum(day)}`
}))
})
}
function fullNum(i) {
if (i <= 9) {
return '0' + i
} else {
return i
}
}
})
/* ******************* 计算年月日 end ******************* */

View File

@ -0,0 +1,25 @@
package aiyh.utils;
import aiyh.utils.tool.org.apache.commons.jexl3.*;
import java.util.Map;
/**
* <h1></h1>
*
* <p>create: 2023/3/3 23:03</p>
*
* @author youHong.ai
*/
public class ScriptUtil {
private static final JexlEngine jexl = new JexlBuilder().create();
public static Object invokeScript(String script, Map<String, Object> params) {
JexlContext jc = new MapContext();
for (Map.Entry<String, Object> entry : params.entrySet()) {
jc.set(entry.getKey(), entry.getValue());
}
JexlExpression expression = jexl.createExpression(script);
return expression.evaluate(jc);
}
}

View File

@ -3751,6 +3751,32 @@ public class Util extends weaver.general.Util {
return pathParamMap;
}
public static <T> T getClassInstance(String classPath, Class<T> t) {
Class<?> aClass;
try {
aClass = Class.forName(classPath);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("未能找到自定义接口:" + classPath);
}
if (!t.isAssignableFrom(aClass)) {
throw new IllegalArgumentException("自定义接口:" + classPath + " 不是"
+ t.getName() + "的子类或实现类!");
}
Constructor<?> constructor;
try {
constructor = aClass.getConstructor();
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException(classPath + "没有空参构造方法,无法获取构造方法对象!");
}
T o;
try {
o = (T) constructor.newInstance();
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new IllegalArgumentException("无法构造" + classPath + "对象!");
}
return o;
}
public static Object executeActionProcess(String process, RequestInfo requestInfo) {
if (StringUtils.isNullOrEmpty(process)) {
return null;

View File

@ -569,7 +569,9 @@ public class ResultMapper {
cassociationValue = paramType.get(declaredField.getType()).apply(String.valueOf(cassociationValue));
}
try {
propertyDescriptor.getWriteMethod().invoke(o, cassociationValue);
if (Objects.nonNull(value)) {
propertyDescriptor.getWriteMethod().invoke(o, cassociationValue);
}
} catch (Exception e) {
Util.getLogger().error("实体数据写入报错:" + fieldName + " => " + value);
if (value != null) {
@ -584,7 +586,9 @@ public class ResultMapper {
if (collectionMapping != null) {
Object collection = collection(rs, collectionMapping, method);
try {
propertyDescriptor.getWriteMethod().invoke(o, collection);
if (Objects.nonNull(value)) {
propertyDescriptor.getWriteMethod().invoke(o, collection);
}
} catch (Exception e) {
Util.getLogger().error("实体数据写入报错:" + fieldName + " => " + value);
if (value != null) {

View File

@ -0,0 +1,161 @@
package aiyh.utils.tool.cn.hutool.http;
import aiyh.utils.tool.cn.hutool.core.util.StrUtil;
import java.nio.charset.Charset;
/**
* Content-Type
*
* @author looly
* @since 4.0.11
*/
public enum ContentType {
/**
* actiongetx-www-form-urlencodedformname1=value1&amp;name2=value2
*/
FORM_URLENCODED("application/x-www-form-urlencoded"),
/**
* Content-Disposition(boundary)
*/
MULTIPART("multipart/form-data"),
/**
* RestJSON
*/
JSON("application/json"),
/**
* RestXML
*/
XML("application/xml"),
/**
* text/plain
*/
TEXT_PLAIN("text/plain"),
/**
* Resttext/xml
*/
TEXT_XML("text/xml"),
/**
* text/html
*/
TEXT_HTML("text/html"),
/**
* application/octet-stream
*/
OCTET_STREAM("application/octet-stream");
private final String value;
/**
*
*
* @param value ContentType
*/
ContentType(String value) {
this.value = value;
}
/**
* value
*
* @return value
* @since 5.2.6
*/
public String getValue() {
return value;
}
@Override
public String toString() {
return getValue();
}
/**
* Content-Type
*
* @param charset
* @return Content-Type
*/
public String toString(Charset charset) {
return build(this.value, charset);
}
/**
* Content-Type{@code null}application/x-www-form-urlencoded
*
* @param contentType
* @return Content-Type
* @since 4.1.5
*/
public static boolean isDefault(String contentType) {
return null == contentType || isFormUrlEncode(contentType);
}
/**
* application/x-www-form-urlencoded
*
* @param contentType
* @return application/x-www-form-urlencoded
*/
public static boolean isFormUrlEncode(String contentType) {
return StrUtil.startWithIgnoreCase(contentType, FORM_URLENCODED.toString());
}
/**
* bodyContent-Type
*
* <pre>
* 1. application/json
* 1. application/xml
* </pre>
*
* @param body
* @return Content-Typenull
*/
public static ContentType get(String body) {
ContentType contentType = null;
if (StrUtil.isNotBlank(body)) {
char firstChar = body.charAt(0);
switch (firstChar) {
case '{':
case '[':
// JSON请求体
contentType = JSON;
break;
case '<':
// XML请求体
contentType = XML;
break;
default:
break;
}
}
return contentType;
}
/**
* Content-Type
*
* @param contentType Content-Type
* @param charset
* @return Content-Type
* @since 4.5.4
*/
public static String build(String contentType, Charset charset) {
return StrUtil.format("{};charset={}", contentType, charset.name());
}
/**
* Content-Type
*
* @param contentType Content-Type
* @param charset
* @return Content-Type
* @since 5.7.15
*/
public static String build(ContentType contentType, Charset charset) {
return build(contentType.getValue(), charset);
}
}

View File

@ -0,0 +1,229 @@
package aiyh.utils.tool.cn.hutool.http;
import aiyh.utils.tool.cn.hutool.core.collection.CollectionUtil;
import aiyh.utils.tool.cn.hutool.core.map.MapUtil;
import aiyh.utils.tool.cn.hutool.core.util.StrUtil;
import java.util.*;
import java.util.Map.Entry;
/**
* <br>
* Http{@link HttpRequest}
*
* @author looly
*/
public enum GlobalHeaders {
INSTANCE;
/**
*
*/
final Map<String, List<String>> headers = new HashMap<>();
/**
*
*/
GlobalHeaders() {
putDefault(false);
}
/**
*
*
* @param isReset
* @return this
*/
public GlobalHeaders putDefault(boolean isReset) {
// 解决HttpURLConnection中无法自定义Host等头信息的问题
// https://stackoverflow.com/questions/9096987/how-to-overwrite-http-header-host-in-a-httpurlconnection/9098440
System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
// 解决server certificate change is restricted during renegotiation问题
System.setProperty("jdk.tls.allowUnsafeServerCertChange", "true");
System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", "true");
if (isReset) {
this.headers.clear();
}
header(aiyh.utils.tool.cn.hutool.http.Header.ACCEPT, "text/html,application/json,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", true);
header(aiyh.utils.tool.cn.hutool.http.Header.ACCEPT_ENCODING, "gzip, deflate", true);
header(aiyh.utils.tool.cn.hutool.http.Header.ACCEPT_LANGUAGE, "zh-CN,zh;q=0.8", true);
// 此Header只有在post请求中有用因此在HttpRequest的method方法中设置此头信息此处去掉
// header(Header.CONTENT_TYPE, ContentType.FORM_URLENCODED.toString(CharsetUtil.CHARSET_UTF_8), true);
header(aiyh.utils.tool.cn.hutool.http.Header.USER_AGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36 Hutool", true);
return this;
}
// ---------------------------------------------------------------- Headers start
/**
* name
*
* @param name Header
* @return Header
*/
public String header(String name) {
final List<String> values = headerList(name);
if (CollectionUtil.isEmpty(values)) {
return null;
}
return values.get(0);
}
/**
* name
*
* @param name Header
* @return Header
* @since 3.1.1
*/
public List<String> headerList(String name) {
if (StrUtil.isBlank(name)) {
return null;
}
return headers.get(name.trim());
}
/**
* name
*
* @param name Header
* @return Header
*/
public String header(aiyh.utils.tool.cn.hutool.http.Header name) {
if (null == name) {
return null;
}
return header(name.toString());
}
/**
* header<br>
*
*
* @param name Header
* @param value Header
* @param isOverride
* @return this
*/
synchronized public GlobalHeaders header(String name, String value, boolean isOverride) {
if (null != name && null != value) {
final List<String> values = headers.get(name.trim());
if (isOverride || CollectionUtil.isEmpty(values)) {
final ArrayList<String> valueList = new ArrayList<>();
valueList.add(value);
headers.put(name.trim(), valueList);
} else {
values.add(value.trim());
}
}
return this;
}
/**
* header<br>
*
*
* @param name Header
* @param value Header
* @param isOverride
* @return this
*/
public GlobalHeaders header(aiyh.utils.tool.cn.hutool.http.Header name, String value, boolean isOverride) {
return header(name.toString(), value, isOverride);
}
/**
* header<br>
*
*
* @param name Header
* @param value Header
* @return this
*/
public GlobalHeaders header(aiyh.utils.tool.cn.hutool.http.Header name, String value) {
return header(name.toString(), value, true);
}
/**
* header<br>
*
*
* @param name Header
* @param value Header
* @return this
*/
public GlobalHeaders header(String name, String value) {
return header(name, value, true);
}
/**
* <br>
*
*
* @param headers
* @return this
*/
public GlobalHeaders header(Map<String, List<String>> headers) {
if (MapUtil.isEmpty(headers)) {
return this;
}
String name;
for (Entry<String, List<String>> entry : headers.entrySet()) {
name = entry.getKey();
for (String value : entry.getValue()) {
this.header(name, StrUtil.nullToEmpty(value), false);
}
}
return this;
}
/**
*
*
* @param name Header
* @return this
*/
synchronized public GlobalHeaders removeHeader(String name) {
if (name != null) {
headers.remove(name.trim());
}
return this;
}
/**
*
*
* @param name Header
* @return this
*/
public GlobalHeaders removeHeader(Header name) {
return removeHeader(name.toString());
}
/**
* headers
*
* @return Headers Map
*/
public Map<String, List<String>> headers() {
return Collections.unmodifiableMap(headers);
}
/**
*
*
* @return this
* @since 5.7.13
*/
synchronized public GlobalHeaders clearHeaders() {
this.headers.clear();
return this;
}
// ---------------------------------------------------------------- Headers end
}

View File

@ -0,0 +1,94 @@
package aiyh.utils.tool.cn.hutool.http;
/**
* <br>
*
*
* @author looly
* @since 5.8.0
*/
public enum GlobalInterceptor {
INSTANCE;
private final HttpInterceptor.Chain<aiyh.utils.tool.cn.hutool.http.HttpRequest> requestInterceptors = new HttpInterceptor.Chain<>();
private final HttpInterceptor.Chain<aiyh.utils.tool.cn.hutool.http.HttpResponse> responseInterceptors = new HttpInterceptor.Chain<>();
/**
*
*
* @param interceptor
* @return this
*/
synchronized public GlobalInterceptor addRequestInterceptor(HttpInterceptor<aiyh.utils.tool.cn.hutool.http.HttpRequest> interceptor) {
this.requestInterceptors.addChain(interceptor);
return this;
}
/**
*
*
* @param interceptor
* @return this
*/
synchronized public GlobalInterceptor addResponseInterceptor(HttpInterceptor<aiyh.utils.tool.cn.hutool.http.HttpResponse> interceptor) {
this.responseInterceptors.addChain(interceptor);
return this;
}
/**
*
*
* @return this
*/
public GlobalInterceptor clear() {
clearRequest();
clearResponse();
return this;
}
/**
*
*
* @return this
*/
synchronized public GlobalInterceptor clearRequest() {
requestInterceptors.clear();
return this;
}
/**
*
*
* @return this
*/
synchronized public GlobalInterceptor clearResponse() {
responseInterceptors.clear();
return this;
}
/**
*
*
* @return {@link HttpInterceptor.Chain}
*/
HttpInterceptor.Chain<aiyh.utils.tool.cn.hutool.http.HttpRequest> getCopiedRequestInterceptor() {
final HttpInterceptor.Chain<aiyh.utils.tool.cn.hutool.http.HttpRequest> copied = new HttpInterceptor.Chain<>();
for (HttpInterceptor<HttpRequest> interceptor : this.requestInterceptors) {
copied.addChain(interceptor);
}
return copied;
}
/**
*
*
* @return {@link HttpInterceptor.Chain}
*/
HttpInterceptor.Chain<aiyh.utils.tool.cn.hutool.http.HttpResponse> getCopiedResponseInterceptor() {
final HttpInterceptor.Chain<aiyh.utils.tool.cn.hutool.http.HttpResponse> copied = new HttpInterceptor.Chain<>();
for (HttpInterceptor<HttpResponse> interceptor : this.responseInterceptors) {
copied.addChain(interceptor);
}
return copied;
}
}

View File

@ -0,0 +1,539 @@
package aiyh.utils.tool.cn.hutool.http;
import aiyh.utils.tool.cn.hutool.core.lang.Console;
import aiyh.utils.tool.cn.hutool.core.map.SafeConcurrentHashMap;
import aiyh.utils.tool.cn.hutool.core.util.CharUtil;
import java.util.*;
import java.util.concurrent.ConcurrentMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* HTMLXSS(Cross Site Scripting)
*
* <p>
* 线
* </p>
*
* <pre>
* String clean = new HTMLFilter().filter(input);
* </pre>
* <p>
* http://xss-html-filter.sf.net
*
* @author Joseph O'Connell
* @author Cal Hendersen
* @author Michael Semb Wever
*/
public final class HTMLFilter {
/**
* regex flag union representing /si modifiers in php
**/
private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL;
private static final Pattern P_COMMENTS = Pattern.compile("<!--(.*?)-->", Pattern.DOTALL);
private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI);
private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL);
private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI);
private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI);
private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI);
private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI);
private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI);
private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?");
private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?");
private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?");
private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))");
private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL);
private static final Pattern P_END_ARROW = Pattern.compile("^>");
private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)");
private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)");
private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)");
private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)");
private static final Pattern P_AMP = Pattern.compile("&");
private static final Pattern P_QUOTE = Pattern.compile("\"");
private static final Pattern P_LEFT_ARROW = Pattern.compile("<");
private static final Pattern P_RIGHT_ARROW = Pattern.compile(">");
private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>");
// @xxx could grow large... maybe use sesat's ReferenceMap
private static final ConcurrentMap<String, Pattern> P_REMOVE_PAIR_BLANKS = new SafeConcurrentHashMap<>();
private static final ConcurrentMap<String, Pattern> P_REMOVE_SELF_BLANKS = new SafeConcurrentHashMap<>();
/**
* set of allowed html elements, along with allowed attributes for each element
**/
private final Map<String, List<String>> vAllowed;
/**
* counts of open tags for each (allowable) html element
**/
private final Map<String, Integer> vTagCounts = new HashMap<>();
/**
* html elements which must always be self-closing (e.g. "&lt;img /&gt;")
**/
private final String[] vSelfClosingTags;
/**
* html elements which must always have separate opening and closing tags (e.g. "&lt;b&gt;&lt;/b&gt;")
**/
private final String[] vNeedClosingTags;
/**
* set of disallowed html elements
**/
private final String[] vDisallowed;
/**
* attributes which should be checked for valid protocols
**/
private final String[] vProtocolAtts;
/**
* allowed protocols
**/
private final String[] vAllowedProtocols;
/**
* tags which should be removed if they contain no content (e.g. "&lt;b&gt;&lt;/b&gt;" or "&lt;b /&gt;")
**/
private final String[] vRemoveBlanks;
/**
* entities allowed within html markup
**/
private final String[] vAllowedEntities;
/**
* flag determining whether comments are allowed in input String.
*/
private final boolean stripComment;
private final boolean encodeQuotes;
private boolean vDebug = false;
/**
* flag determining whether to try to make tags when presented with "unbalanced" angle brackets (e.g. "&lt;b text &lt;/b&gt;" becomes "&lt;b&gt; text &lt;/g&gt;").
* If set to false, unbalanced angle brackets will be
* html escaped.
*/
private final boolean alwaysMakeTags;
/**
* Default constructor.
*/
public HTMLFilter() {
vAllowed = new HashMap<>();
final ArrayList<String> a_atts = new ArrayList<>();
a_atts.add("href");
a_atts.add("target");
vAllowed.put("a", a_atts);
final ArrayList<String> img_atts = new ArrayList<>();
img_atts.add("src");
img_atts.add("width");
img_atts.add("height");
img_atts.add("alt");
vAllowed.put("img", img_atts);
final ArrayList<String> no_atts = new ArrayList<>();
vAllowed.put("b", no_atts);
vAllowed.put("strong", no_atts);
vAllowed.put("i", no_atts);
vAllowed.put("em", no_atts);
vSelfClosingTags = new String[]{"img"};
vNeedClosingTags = new String[]{"a", "b", "strong", "i", "em"};
vDisallowed = new String[]{};
vAllowedProtocols = new String[]{"http", "mailto", "https"}; // no ftp.
vProtocolAtts = new String[]{"src", "href"};
vRemoveBlanks = new String[]{"a", "b", "strong", "i", "em"};
vAllowedEntities = new String[]{"amp", "gt", "lt", "quot"};
stripComment = true;
encodeQuotes = true;
alwaysMakeTags = true;
}
/**
* Set debug flag to true. Otherwise use default settings. See the default constructor.
*
* @param debug turn debug on with a true argument
*/
public HTMLFilter(final boolean debug) {
this();
vDebug = debug;
}
/**
* Map-parameter configurable constructor.
*
* @param conf map containing configuration. keys match field names.
*/
@SuppressWarnings("unchecked")
public HTMLFilter(final Map<String, Object> conf) {
assert conf.containsKey("vAllowed") : "configuration requires vAllowed";
assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags";
assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags";
assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed";
assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols";
assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts";
assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks";
assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities";
vAllowed = Collections.unmodifiableMap((HashMap<String, List<String>>) conf.get("vAllowed"));
vSelfClosingTags = (String[]) conf.get("vSelfClosingTags");
vNeedClosingTags = (String[]) conf.get("vNeedClosingTags");
vDisallowed = (String[]) conf.get("vDisallowed");
vAllowedProtocols = (String[]) conf.get("vAllowedProtocols");
vProtocolAtts = (String[]) conf.get("vProtocolAtts");
vRemoveBlanks = (String[]) conf.get("vRemoveBlanks");
vAllowedEntities = (String[]) conf.get("vAllowedEntities");
stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true;
encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true;
alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true;
}
private void reset() {
vTagCounts.clear();
}
private void debug(final String msg) {
if (vDebug) {
Console.log(msg);
}
}
// ---------------------------------------------------------------
// my versions of some PHP library functions
public static String chr(final int decimal) {
return String.valueOf((char) decimal);
}
public static String htmlSpecialChars(final String s) {
String result = s;
result = regexReplace(P_AMP, "&amp;", result);
result = regexReplace(P_QUOTE, "&quot;", result);
result = regexReplace(P_LEFT_ARROW, "&lt;", result);
result = regexReplace(P_RIGHT_ARROW, "&gt;", result);
return result;
}
// ---------------------------------------------------------------
/**
* given a user submitted input String, filter out any invalid or restricted html.
*
* @param input text (i.e. submitted by a user) than may contain html
* @return "clean" version of input, with only valid, whitelisted html elements allowed
*/
public String filter(final String input) {
reset();
String s = input;
debug("************************************************");
debug(" INPUT: " + input);
s = escapeComments(s);
debug(" escapeComments: " + s);
s = balanceHTML(s);
debug(" balanceHTML: " + s);
s = checkTags(s);
debug(" checkTags: " + s);
s = processRemoveBlanks(s);
debug("processRemoveBlanks: " + s);
s = validateEntities(s);
debug(" validateEntites: " + s);
debug("************************************************\n\n");
return s;
}
public boolean isAlwaysMakeTags() {
return alwaysMakeTags;
}
public boolean isStripComments() {
return stripComment;
}
private String escapeComments(final String s) {
final Matcher m = P_COMMENTS.matcher(s);
final StringBuffer buf = new StringBuffer();
if (m.find()) {
final String match = m.group(1); // (.*?)
m.appendReplacement(buf, Matcher.quoteReplacement("<!--" + htmlSpecialChars(match) + "-->"));
}
m.appendTail(buf);
return buf.toString();
}
private String balanceHTML(String s) {
if (alwaysMakeTags) {
//
// try and form html
//
s = regexReplace(P_END_ARROW, "", s);
s = regexReplace(P_BODY_TO_END, "<$1>", s);
s = regexReplace(P_XML_CONTENT, "$1<$2", s);
} else {
//
// escape stray brackets
//
s = regexReplace(P_STRAY_LEFT_ARROW, "&lt;$1", s);
s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2&gt;<", s);
//
// the last regexp causes '<>' entities to appear
// (we need to do a lookahead assertion so that the last bracket can
// be used in the next pass of the regexp)
//
s = regexReplace(P_BOTH_ARROWS, "", s);
}
return s;
}
private String checkTags(String s) {
Matcher m = P_TAGS.matcher(s);
final StringBuffer buf = new StringBuffer();
while (m.find()) {
String replaceStr = m.group(1);
replaceStr = processTag(replaceStr);
m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr));
}
m.appendTail(buf);
// these get tallied in processTag
// (remember to reset before subsequent calls to filter method)
final StringBuilder sBuilder = new StringBuilder(buf.toString());
for (String key : vTagCounts.keySet()) {
for (int ii = 0; ii < vTagCounts.get(key); ii++) {
sBuilder.append("</").append(key).append(">");
}
}
s = sBuilder.toString();
return s;
}
private String processRemoveBlanks(final String s) {
String result = s;
for (String tag : vRemoveBlanks) {
if (!P_REMOVE_PAIR_BLANKS.containsKey(tag)) {
P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?></" + tag + ">"));
}
result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result);
if (!P_REMOVE_SELF_BLANKS.containsKey(tag)) {
P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>"));
}
result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result);
}
return result;
}
private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) {
Matcher m = regex_pattern.matcher(s);
return m.replaceAll(replacement);
}
private String processTag(final String s) {
// ending tags
Matcher m = P_END_TAG.matcher(s);
if (m.find()) {
final String name = m.group(1).toLowerCase();
if (allowed(name)) {
if (!inArray(name, vSelfClosingTags)) {
if (vTagCounts.containsKey(name)) {
vTagCounts.put(name, vTagCounts.get(name) - 1);
return "</" + name + ">";
}
}
}
}
// starting tags
m = P_START_TAG.matcher(s);
if (m.find()) {
final String name = m.group(1).toLowerCase();
final String body = m.group(2);
String ending = m.group(3);
// debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" );
if (allowed(name)) {
final StringBuilder params = new StringBuilder();
final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body);
final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body);
final List<String> paramNames = new ArrayList<>();
final List<String> paramValues = new ArrayList<>();
while (m2.find()) {
paramNames.add(m2.group(1)); // ([a-z0-9]+)
paramValues.add(m2.group(3)); // (.*?)
}
while (m3.find()) {
paramNames.add(m3.group(1)); // ([a-z0-9]+)
paramValues.add(m3.group(3)); // ([^\"\\s']+)
}
String paramName, paramValue;
for (int ii = 0; ii < paramNames.size(); ii++) {
paramName = paramNames.get(ii).toLowerCase();
paramValue = paramValues.get(ii);
// debug( "paramName='" + paramName + "'" );
// debug( "paramValue='" + paramValue + "'" );
// debug( "allowed? " + vAllowed.get( name ).contains( paramName ) );
if (allowedAttribute(name, paramName)) {
if (inArray(paramName, vProtocolAtts)) {
paramValue = processParamProtocol(paramValue);
}
params.append(CharUtil.SPACE).append(paramName).append("=\"").append(paramValue).append("\"");
}
}
if (inArray(name, vSelfClosingTags)) {
ending = " /";
}
if (inArray(name, vNeedClosingTags)) {
ending = "";
}
if (ending == null || ending.length() < 1) {
if (vTagCounts.containsKey(name)) {
vTagCounts.put(name, vTagCounts.get(name) + 1);
} else {
vTagCounts.put(name, 1);
}
} else {
ending = " /";
}
return "<" + name + params + ending + ">";
} else {
return "";
}
}
// comments
m = P_COMMENT.matcher(s);
if (!stripComment && m.find()) {
return "<" + m.group() + ">";
}
return "";
}
private String processParamProtocol(String s) {
s = decodeEntities(s);
final Matcher m = P_PROTOCOL.matcher(s);
if (m.find()) {
final String protocol = m.group(1);
if (!inArray(protocol, vAllowedProtocols)) {
// bad protocol, turn into local anchor link instead
s = "#" + s.substring(protocol.length() + 1);
if (s.startsWith("#//")) {
s = "#" + s.substring(3);
}
}
}
return s;
}
private String decodeEntities(String s) {
StringBuffer buf = new StringBuffer();
Matcher m = P_ENTITY.matcher(s);
while (m.find()) {
final String match = m.group(1);
final int decimal = Integer.decode(match);
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
}
m.appendTail(buf);
s = buf.toString();
buf = new StringBuffer();
m = P_ENTITY_UNICODE.matcher(s);
while (m.find()) {
final String match = m.group(1);
final int decimal = Integer.parseInt(match, 16);
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
}
m.appendTail(buf);
s = buf.toString();
buf = new StringBuffer();
m = P_ENCODE.matcher(s);
while (m.find()) {
final String match = m.group(1);
final int decimal = Integer.parseInt(match, 16);
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
}
m.appendTail(buf);
s = buf.toString();
s = validateEntities(s);
return s;
}
private String validateEntities(final String s) {
StringBuffer buf = new StringBuffer();
// validate entities throughout the string
Matcher m = P_VALID_ENTITIES.matcher(s);
while (m.find()) {
final String one = m.group(1); // ([^&;]*)
final String two = m.group(2); // (?=(;|&|$))
m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two)));
}
m.appendTail(buf);
return encodeQuotes(buf.toString());
}
private String encodeQuotes(final String s) {
if (encodeQuotes) {
StringBuffer buf = new StringBuffer();
Matcher m = P_VALID_QUOTES.matcher(s);
while (m.find()) {
final String one = m.group(1); // (>|^)
final String two = m.group(2); // ([^<]+?)
final String three = m.group(3); // (<|$)
m.appendReplacement(buf, Matcher.quoteReplacement(one + regexReplace(P_QUOTE, "&quot;", two) + three));
}
m.appendTail(buf);
return buf.toString();
} else {
return s;
}
}
private String checkEntity(final String preamble, final String term) {
return ";".equals(term) && isValidEntity(preamble) ? '&' + preamble : "&amp;" + preamble;
}
private boolean isValidEntity(final String entity) {
return inArray(entity, vAllowedEntities);
}
private static boolean inArray(final String s, final String[] array) {
for (String item : array) {
if (item != null && item.equals(s)) {
return true;
}
}
return false;
}
private boolean allowed(final String name) {
return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed);
}
private boolean allowedAttribute(final String name, final String paramName) {
return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName));
}
}

View File

@ -0,0 +1,153 @@
package aiyh.utils.tool.cn.hutool.http;
/**
* Http
*
* @author Looly
*/
public enum Header {
//------------------------------------------------------------- 通用头域
/**
*
* <pre>
* Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
* </pre>
*/
AUTHORIZATION("Authorization"),
/**
*
* <pre>
* Proxy-Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
* </pre>
*/
PROXY_AUTHORIZATION("Proxy-Authorization"),
/**
* ,
*/
DATE("Date"),
/**
* /
*/
CONNECTION("Connection"),
/**
* 使MIME
*/
MIME_VERSION("MIME-Version"),
/**
* (chunked transfer encoding) ,(trailer)
*/
TRAILER("Trailer"),
/**
* ,
*/
TRANSFER_ENCODING("Transfer-Encoding"),
/**
* "升级"使
*/
UPGRADE("Upgrade"),
/**
*
*/
VIA("Via"),
/**
*
*/
CACHE_CONTROL("Cache-Control"),
/**
* Pragma:no-cacheHTTP/1.1Cache- Control:no-cache
*/
PRAGMA("Pragma"),
/**
* MIME
*/
CONTENT_TYPE("Content-Type"),
//------------------------------------------------------------- 请求头域
/**
* InteneturlHTTP/1.1400
*/
HOST("Host"),
/**
* uri退cache uriuriRefereruri
*/
REFERER("Referer"),
/**
*
*/
ORIGIN("Origin"),
/**
* HTTPwebHTTP
*/
USER_AGENT("User-Agent"),
/**
*
*/
ACCEPT("Accept"),
/**
* HTTP
*/
ACCEPT_LANGUAGE("Accept-Language"),
/**
* web
*/
ACCEPT_ENCODING("Accept-Encoding"),
/**
*
*/
ACCEPT_CHARSET("Accept-Charset"),
/**
* HTTPcookieweb
*/
COOKIE("Cookie"),
/**
*
*/
CONTENT_LENGTH("Content-Length"),
//------------------------------------------------------------- 响应头域
/**
* WWW
*/
WWW_AUTHENTICATE("WWW-Authenticate"),
/**
* Cookie
*/
SET_COOKIE("Set-Cookie"),
/**
* Content-Encoding
*/
CONTENT_ENCODING("Content-Encoding"),
/**
* Content-Disposition
*/
CONTENT_DISPOSITION("Content-Disposition"),
/**
* ETag
*/
ETAG("ETag"),
/**
* URL
*/
LOCATION("Location");
private final String value;
Header(String value) {
this.value = value;
}
/**
*
*
* @return
*/
public String getValue() {
return this.value;
}
@Override
public String toString() {
return getValue();
}
}

View File

@ -0,0 +1,212 @@
package aiyh.utils.tool.cn.hutool.http;
import aiyh.utils.tool.cn.hutool.core.util.EscapeUtil;
import aiyh.utils.tool.cn.hutool.core.util.ReUtil;
import aiyh.utils.tool.cn.hutool.core.util.StrUtil;
/**
* HTML
*
* <p>
* 使HTMLHTML<br>
* 广JS使
*
* @author xiaoleilu
*/
public class HtmlUtil {
public static final String NBSP = StrUtil.HTML_NBSP;
public static final String AMP = StrUtil.HTML_AMP;
public static final String QUOTE = StrUtil.HTML_QUOTE;
public static final String APOS = StrUtil.HTML_APOS;
public static final String LT = StrUtil.HTML_LT;
public static final String GT = StrUtil.HTML_GT;
public static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)";
public static final String RE_SCRIPT = "<[\\s]*?script[^>]*?>.*?<[\\s]*?\\/[\\s]*?script[\\s]*?>";
private static final char[][] TEXT = new char[256][];
static {
// ascii码值最大的是【0x7f=127】扩展ascii码值最大的是【0xFF=255】因为ASCII码使用指定的7位或8位二进制数组合来表示128或256种可能的字符标准ASCII码也叫基础ASCII码。
for (int i = 0; i < 256; i++) {
TEXT[i] = new char[]{(char) i};
}
// special HTML characters
TEXT['\''] = "&#039;".toCharArray(); // 单引号 ('&apos;' doesn't work - it is not by the w3 specs)
TEXT['"'] = QUOTE.toCharArray(); // 双引号
TEXT['&'] = AMP.toCharArray(); // &符
TEXT['<'] = LT.toCharArray(); // 小于号
TEXT['>'] = GT.toCharArray(); // 大于号
TEXT[' '] = NBSP.toCharArray(); // 不断开空格non-breaking space缩写nbsp。ASCII值是32是用键盘输入的空格ASCII值是160不间断空格即 &nbsp所产生的空格作用是在页面换行时不被打断
}
/**
* HTML
* <ul>
* <li>' &amp;#039; (&amp;apos; doesn't work in HTML4)</li>
* <li>" &amp;quot;</li>
* <li>&amp; &amp;amp;</li>
* <li>&lt; &amp;lt;</li>
* <li>&gt; &amp;gt;</li>
* </ul>
*
* @param text
* @return
*/
public static String escape(String text) {
return encode(text);
}
/**
* HTML
*
* @param htmlStr HTML
* @return
*/
public static String unescape(String htmlStr) {
if (StrUtil.isBlank(htmlStr)) {
return htmlStr;
}
return EscapeUtil.unescapeHtml4(htmlStr);
}
// ---------------------------------------------------------------- encode text
/**
* HTML
*
* @param content
* @return
*/
public static String cleanHtmlTag(String content) {
return content.replaceAll(RE_HTML_MARK, "");
}
/**
* HTML<br>
*
*
* @param content
* @param tagNames
* @return
*/
public static String removeHtmlTag(String content, String... tagNames) {
return removeHtmlTag(content, true, tagNames);
}
/**
* HTML<br>
*
*
* @param content
* @param tagNames
* @return
*/
public static String unwrapHtmlTag(String content, String... tagNames) {
return removeHtmlTag(content, false, tagNames);
}
/**
* HTML<br>
*
*
* @param content
* @param withTagContent
* @param tagNames
* @return
*/
public static String removeHtmlTag(String content, boolean withTagContent, String... tagNames) {
String regex;
for (String tagName : tagNames) {
if (StrUtil.isBlank(tagName)) {
continue;
}
tagName = tagName.trim();
// (?i)表示其后面的表达式忽略大小写
if (withTagContent) {
// 标签及其包含内容
regex = StrUtil.format("(?i)<{}(\\s+[^>]*?)?/?>(.*?</{}>)?", tagName, tagName);
} else {
// 标签不包含内容
regex = StrUtil.format("(?i)<{}(\\s+[^>]*?)?/?>|</?{}>", tagName, tagName);
}
content = ReUtil.delAll(regex, content); // 非自闭标签小写
}
return content;
}
/**
* HTML
*
* @param content
* @param attrs
* @return
*/
public static String removeHtmlAttr(String content, String... attrs) {
String regex;
for (String attr : attrs) {
// (?i) 表示忽略大小写
// \s* 属性名前后的空白符去除
// [^>]+? 属性值,至少有一个非>的字符,>表示标签结束
// \s+(?=>) 表示属性值后跟空格加>,即末尾的属性,此时去掉空格
// (?=\s|>) 表示属性值后跟空格(属性后还有别的属性)或者跟>(最后一个属性)
regex = StrUtil.format("(?i)(\\s*{}\\s*=[^>]+?\\s+(?=>))|(\\s*{}\\s*=[^>]+?(?=\\s|>))", attr, attr);
content = content.replaceAll(regex, StrUtil.EMPTY);
}
return content;
}
/**
*
*
* @param content
* @param tagNames
* @return
*/
public static String removeAllHtmlAttr(String content, String... tagNames) {
String regex;
for (String tagName : tagNames) {
regex = StrUtil.format("(?i)<{}[^>]*?>", tagName);
content = content.replaceAll(regex, StrUtil.format("<{}>", tagName));
}
return content;
}
/**
* Encoder
*
* @param text
* @return
*/
private static String encode(String text) {
int len;
if ((text == null) || ((len = text.length()) == 0)) {
return StrUtil.EMPTY;
}
StringBuilder buffer = new StringBuilder(len + (len >> 2));
char c;
for (int i = 0; i < len; i++) {
c = text.charAt(i);
if (c < 256) {
buffer.append(TEXT[c]);
} else {
buffer.append(c);
}
}
return buffer.toString();
}
/**
* HTMLXSS
*
* @param htmlContent HTML
* @return
*/
public static String filter(String htmlContent) {
return new HTMLFilter().filter(htmlContent);
}
}

View File

@ -0,0 +1,357 @@
package aiyh.utils.tool.cn.hutool.http;
import aiyh.utils.tool.cn.hutool.core.collection.CollUtil;
import aiyh.utils.tool.cn.hutool.core.collection.CollectionUtil;
import aiyh.utils.tool.cn.hutool.core.map.CaseInsensitiveMap;
import aiyh.utils.tool.cn.hutool.core.map.MapUtil;
import aiyh.utils.tool.cn.hutool.core.util.CharsetUtil;
import aiyh.utils.tool.cn.hutool.core.util.StrUtil;
import java.nio.charset.Charset;
import java.util.*;
import java.util.Map.Entry;
/**
* http
*
* @param <T> 便
* @author Looly
*/
@SuppressWarnings("unchecked")
public abstract class HttpBase<T> {
/**
* URLencodedecode
*/
protected static final Charset DEFAULT_CHARSET = CharsetUtil.CHARSET_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<br>
* RFC2616headername
*
* @param name Header
* @return Header
*/
public String header(String name) {
final List<String> values = headerList(name);
if (CollectionUtil.isEmpty(values)) {
return null;
}
return values.get(0);
}
/**
* name
*
* @param name Header
* @return Header
* @since 3.1.1
*/
public List<String> headerList(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 name Header
* @return Header
*/
public String header(Header name) {
if (null == name) {
return null;
}
return header(name.toString());
}
/**
* header<br>
*
*
* @param name Header
* @param value Header
* @param isOverride
* @return T
*/
public T header(String name, String value, boolean isOverride) {
if (null != name && null != value) {
final List<String> values = headers.get(name.trim());
if (isOverride || CollectionUtil.isEmpty(values)) {
final ArrayList<String> valueList = new ArrayList<>();
valueList.add(value);
headers.put(name.trim(), valueList);
} else {
values.add(value.trim());
}
}
return (T) this;
}
/**
* header<br>
*
*
* @param name Header
* @param value Header
* @param isOverride
* @return T
*/
public T header(Header name, String value, boolean isOverride) {
return header(name.toString(), value, isOverride);
}
/**
* header<br>
*
*
* @param name Header
* @param value Header
* @return T
*/
public T header(Header name, String value) {
return header(name.toString(), value, true);
}
/**
* header<br>
*
*
* @param name Header
* @param value Header
* @return T
*/
public T header(String name, String value) {
return header(name, value, true);
}
/**
*
*
* @param headers
* @param isOverride
* @return this
* @since 4.6.3
*/
public T headerMap(Map<String, String> headers, boolean isOverride) {
if (MapUtil.isEmpty(headers)) {
return (T) this;
}
for (Entry<String, String> entry : headers.entrySet()) {
this.header(entry.getKey(), StrUtil.nullToEmpty(entry.getValue()), isOverride);
}
return (T) this;
}
/**
* <br>
*
*
* @param headers
* @return this
*/
public T header(Map<String, List<String>> headers) {
return header(headers, false);
}
/**
*
*
* @param headers
* @param isOverride
* @return this
* @since 4.0.8
*/
public T header(Map<String, List<String>> headers, boolean isOverride) {
if (MapUtil.isEmpty(headers)) {
return (T) this;
}
String name;
for (Entry<String, List<String>> entry : headers.entrySet()) {
name = entry.getKey();
for (String value : entry.getValue()) {
this.header(name, StrUtil.nullToEmpty(value), isOverride);
}
}
return (T) this;
}
/**
* <br>
*
*
* @param headers
* @return this
* @since 4.0.3
*/
public T addHeaders(Map<String, String> headers) {
if (MapUtil.isEmpty(headers)) {
return (T) this;
}
for (Entry<String, String> entry : headers.entrySet()) {
this.header(entry.getKey(), StrUtil.nullToEmpty(entry.getValue()), false);
}
return (T) this;
}
/**
*
*
* @param name Header
* @return this
*/
public T removeHeader(String name) {
if (name != null) {
headers.remove(name.trim());
}
return (T) this;
}
/**
*
*
* @param name Header
* @return this
*/
public T removeHeader(Header name) {
return removeHeader(name.toString());
}
/**
* headers
*
* @return Headers Map
*/
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;
}
/**
* httpHTTPconnect:Keep-Alive
*
* @param httpVersion Http{@link HttpBase#HTTP_1_0}{@link HttpBase#HTTP_1_1}
* @return this
*/
public T httpVersion(String httpVersion) {
this.httpVersion = httpVersion;
return (T) this;
}
/**
* bodyBytes
*
* @return byte[]
*/
public byte[] bodyBytes() {
return this.bodyBytes;
}
/**
*
*
* @return
*/
public String charset() {
return charset.name();
}
/**
*
*
* @param charset
* @return T
* @see CharsetUtil
*/
public T charset(String charset) {
if (StrUtil.isNotBlank(charset)) {
charset(Charset.forName(charset));
}
return (T) this;
}
/**
*
*
* @param charset
* @return T
* @see CharsetUtil
*/
public T charset(Charset charset) {
if (null != charset) {
this.charset = charset;
}
return (T) this;
}
@Override
public String toString() {
StringBuilder sb = StrUtil.builder();
sb.append("Request Headers: ").append(StrUtil.CRLF);
for (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

@ -0,0 +1,300 @@
package aiyh.utils.tool.cn.hutool.http;
import aiyh.utils.tool.cn.hutool.core.lang.Assert;
import aiyh.utils.tool.cn.hutool.core.net.SSLUtil;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSocketFactory;
import java.net.InetSocketAddress;
import java.net.Proxy;
/**
* Http
*
* @author looly
* @since 5.8.0
*/
public class HttpConfig {
/**
* Http
*
* @return HttpConfig
*/
public static HttpConfig create() {
return new HttpConfig();
}
/**
*
*/
int connectionTimeout = HttpGlobalConfig.getTimeout();
/**
*
*/
int readTimeout = HttpGlobalConfig.getTimeout();
/**
*
*/
boolean isDisableCache;
/**
*
*/
int maxRedirectCount = HttpGlobalConfig.getMaxRedirectCount();
/**
*
*/
Proxy proxy;
/**
* HostnameVerifierHTTPS
*/
HostnameVerifier hostnameVerifier;
/**
* SSLSocketFactoryHTTPS
*/
SSLSocketFactory ssf;
/**
* Chuncked00Chuncked
*/
int blockSize;
/**
* EOF<br>
* HttpTransfer-Encoding: ChunkedLength0chunk<br>
* EOF
*/
boolean ignoreEOFError = HttpGlobalConfig.isIgnoreEOFError();
/**
* URLURLPathParam<br>
* HttpURL{@code true}<br>
* RFC3986{@code false}
*/
boolean decodeUrl = HttpGlobalConfig.isDecodeUrl();
/**
*
*/
final HttpInterceptor.Chain<aiyh.utils.tool.cn.hutool.http.HttpRequest> requestInterceptors = GlobalInterceptor.INSTANCE.getCopiedRequestInterceptor();
/**
*
*/
final HttpInterceptor.Chain<aiyh.utils.tool.cn.hutool.http.HttpResponse> responseInterceptors = GlobalInterceptor.INSTANCE.getCopiedResponseInterceptor();
/**
* 使
*/
boolean interceptorOnRedirect;
/**
* <br>
*
*
* <pre>
* 1.
* 2.
* </pre>
*
* @param milliseconds
* @return this
* @see #setConnectionTimeout(int)
* @see #setReadTimeout(int)
*/
public HttpConfig timeout(int milliseconds) {
setConnectionTimeout(milliseconds);
setReadTimeout(milliseconds);
return this;
}
/**
*
*
* @param milliseconds
* @return this
*/
public HttpConfig setConnectionTimeout(int milliseconds) {
this.connectionTimeout = milliseconds;
return this;
}
/**
*
*
* @param milliseconds
* @return this
*/
public HttpConfig setReadTimeout(int milliseconds) {
this.readTimeout = milliseconds;
return this;
}
/**
*
*
* @return this
*/
public HttpConfig disableCache() {
this.isDisableCache = true;
return this;
}
/**
* <br>
* 11
*
* @param maxRedirectCount
* @return this
*/
public HttpConfig setMaxRedirectCount(int maxRedirectCount) {
this.maxRedirectCount = Math.max(maxRedirectCount, 0);
return this;
}
/**
* <br>
* HTTPS
*
* @param hostnameVerifier HostnameVerifier
* @return this
*/
public HttpConfig setHostnameVerifier(HostnameVerifier hostnameVerifier) {
// 验证域
this.hostnameVerifier = hostnameVerifier;
return this;
}
/**
* Http
*
* @param host
* @param port
* @return this
*/
public HttpConfig setHttpProxy(String host, int port) {
final Proxy proxy = new Proxy(Proxy.Type.HTTP,
new InetSocketAddress(host, port));
return setProxy(proxy);
}
/**
*
*
* @param proxy {@link Proxy}
* @return this
*/
public HttpConfig setProxy(Proxy proxy) {
this.proxy = proxy;
return this;
}
/**
* SSLSocketFactory<br>
* HTTPS使SSLSocketFactory<br>
* SSLSocketFactorySSLSocketFactoryBuilder.create().build();
*
* @param ssf SSLScketFactory
* @return this
*/
public HttpConfig setSSLSocketFactory(SSLSocketFactory ssf) {
this.ssf = ssf;
return this;
}
/**
* HTTPSHTTPS使<br>
* {@link #setSSLSocketFactory(SSLSocketFactory)}
*
* <pre>
* 1. TLSv1.2
* 2. TLSv1.1
* 3. SSLv3
* ...
* </pre>
*
* @param protocol
* @return this
* @see SSLUtil#createSSLContext(String)
* @see #setSSLSocketFactory(SSLSocketFactory)
*/
public HttpConfig setSSLProtocol(String protocol) {
Assert.notBlank(protocol, "protocol must be not blank!");
setSSLSocketFactory(SSLUtil.createSSLContext(protocol).getSocketFactory());
return this;
}
/**
* <br>
* HttpUrlConnection
*
* @param blockSize bytes00Chuncked
* @return this
*/
public HttpConfig setBlockSize(int blockSize) {
this.blockSize = blockSize;
return this;
}
/**
* EOF<br>
* HttpTransfer-Encoding: ChunkedLength0chunk<br>
* EOF
*
* @param ignoreEOFError EOF
* @return this
* @since 5.7.20
*/
public HttpConfig setIgnoreEOFError(boolean ignoreEOFError) {
this.ignoreEOFError = ignoreEOFError;
return this;
}
/**
* URLURLPathParam<br>
* HttpURL{@code true}<br>
* RFC3986{@code false}
*
* @param decodeUrl URL
* @return this
*/
public HttpConfig setDecodeUrl(boolean decodeUrl) {
this.decodeUrl = decodeUrl;
return this;
}
/**
*
*
* @param interceptor
* @return this
*/
public HttpConfig addRequestInterceptor(HttpInterceptor<HttpRequest> interceptor) {
this.requestInterceptors.addChain(interceptor);
return this;
}
/**
*
*
* @param interceptor
* @return this
*/
public HttpConfig addResponseInterceptor(HttpInterceptor<HttpResponse> interceptor) {
this.responseInterceptors.addChain(interceptor);
return this;
}
/**
* 使
*
* @param interceptorOnRedirect 使
* @return this
*/
public HttpConfig setInterceptorOnRedirect(boolean interceptorOnRedirect) {
this.interceptorOnRedirect = interceptorOnRedirect;
return this;
}
}

View File

@ -0,0 +1,568 @@
package aiyh.utils.tool.cn.hutool.http;
import aiyh.utils.tool.cn.hutool.core.map.MapUtil;
import aiyh.utils.tool.cn.hutool.core.util.ObjectUtil;
import aiyh.utils.tool.cn.hutool.core.util.ReflectUtil;
import aiyh.utils.tool.cn.hutool.core.util.StrUtil;
import aiyh.utils.tool.cn.hutool.core.util.URLUtil;
import aiyh.utils.tool.cn.hutool.http.ssl.DefaultSSLInfo;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocketFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.*;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
/**
* httpHttpURLConnection
*
* @author Looly
*/
public class HttpConnection {
private final URL url;
private final Proxy proxy;
private HttpURLConnection conn;
/**
* HttpConnection
*
* @param urlStr URL
* @param proxy {@code null}
* @return HttpConnection
*/
public static HttpConnection create(String urlStr, Proxy proxy) {
return create(URLUtil.toUrlForHttp(urlStr), proxy);
}
/**
* HttpConnection
*
* @param url URL
* @param proxy {@code null}
* @return HttpConnection
*/
public static HttpConnection create(URL url, Proxy proxy) {
return new HttpConnection(url, proxy);
}
// --------------------------------------------------------------- Constructor start
/**
* HttpConnection
*
* @param url URL
* @param proxy
*/
public HttpConnection(URL url, Proxy proxy) {
this.url = url;
this.proxy = proxy;
// 初始化Http连接
initConn();
}
// --------------------------------------------------------------- Constructor end
/**
*
*
* @return HttpConnection
* @since 4.4.1
*/
public HttpConnection initConn() {
try {
this.conn = openHttp();
} catch (IOException e) {
throw new HttpException(e);
}
// 默认读取响应内容
this.conn.setDoInput(true);
return this;
}
// --------------------------------------------------------------- Getters And Setters start
/**
* ,GET/POST
*
* @return , GET/POST
*/
public aiyh.utils.tool.cn.hutool.http.Method getMethod() {
return aiyh.utils.tool.cn.hutool.http.Method.valueOf(this.conn.getRequestMethod());
}
/**
*
*
* @param method
* @return
*/
public HttpConnection setMethod(aiyh.utils.tool.cn.hutool.http.Method method) {
if (aiyh.utils.tool.cn.hutool.http.Method.POST.equals(method) //
|| aiyh.utils.tool.cn.hutool.http.Method.PUT.equals(method)//
|| aiyh.utils.tool.cn.hutool.http.Method.PATCH.equals(method)//
|| aiyh.utils.tool.cn.hutool.http.Method.DELETE.equals(method)) {
this.conn.setUseCaches(false);
// 增加PATCH方法支持
if (aiyh.utils.tool.cn.hutool.http.Method.PATCH.equals(method)) {
try {
HttpGlobalConfig.allowPatch();
} catch (Exception ignore) {
// ignore
// https://github.com/dromara/hutool/issues/2832
}
}
}
// method
try {
this.conn.setRequestMethod(method.toString());
} catch (ProtocolException e) {
if (aiyh.utils.tool.cn.hutool.http.Method.PATCH.equals(method)) {
// 如果全局设置失效,此处针对单独链接重新设置
reflectSetMethod(method);
} else {
throw new HttpException(e);
}
}
return this;
}
/**
* URL
*
* @return URL
*/
public URL getUrl() {
return url;
}
/**
*
*
* @return {@link Proxy}
*/
public Proxy getProxy() {
return proxy;
}
/**
* HttpURLConnection
*
* @return HttpURLConnection
*/
public HttpURLConnection getHttpURLConnection() {
return conn;
}
// --------------------------------------------------------------- Getters And Setters end
// ---------------------------------------------------------------- Headers start
/**
* <br>
*
*
* @param header
* @param value
* @param isOverride
* @return HttpConnection
*/
public HttpConnection header(String header, String value, boolean isOverride) {
if (null != this.conn) {
if (isOverride) {
this.conn.setRequestProperty(header, value);
} else {
this.conn.addRequestProperty(header, value);
}
}
return this;
}
/**
* <br>
*
*
* @param header
* @param value
* @param isOverride
* @return HttpConnection
*/
public HttpConnection header(aiyh.utils.tool.cn.hutool.http.Header header, String value, boolean isOverride) {
return header(header.toString(), value, isOverride);
}
/**
* <br>
*
*
* @param headerMap
* @param isOverride
* @return this
*/
public HttpConnection header(Map<String, List<String>> headerMap, boolean isOverride) {
if (MapUtil.isNotEmpty(headerMap)) {
String name;
for (Entry<String, List<String>> entry : headerMap.entrySet()) {
name = entry.getKey();
for (String value : entry.getValue()) {
this.header(name, StrUtil.nullToEmpty(value), isOverride);
}
}
}
return this;
}
/**
* Http
*
* @param name Header
* @return Http
*/
public String header(String name) {
return this.conn.getHeaderField(name);
}
/**
* Http
*
* @param name Header
* @return Http
*/
public String header(aiyh.utils.tool.cn.hutool.http.Header name) {
return header(name.toString());
}
/**
* Http
*
* @return HttpMap
*/
public Map<String, List<String>> headers() {
return this.conn.getHeaderFields();
}
// ---------------------------------------------------------------- Headers end
/**
* https<br>
* httscom.sun.net.ssl.internal.www.protocol.https.HttpsURLConnectionOldImplsunapihttp
*
* @param hostnameVerifier httpsnull
* @param ssf SSLSocketFactoryhttpsnull
* @return this
* @throws HttpException KeyManagementExceptionNoSuchAlgorithmException
*/
public HttpConnection setHttpsInfo(HostnameVerifier hostnameVerifier, SSLSocketFactory ssf) throws HttpException {
final HttpURLConnection conn = this.conn;
if (conn instanceof HttpsURLConnection) {
// Https请求
final HttpsURLConnection httpsConn = (HttpsURLConnection) conn;
// 验证域
httpsConn.setHostnameVerifier(ObjectUtil.defaultIfNull(hostnameVerifier, DefaultSSLInfo.TRUST_ANY_HOSTNAME_VERIFIER));
httpsConn.setSSLSocketFactory(ObjectUtil.defaultIfNull(ssf, DefaultSSLInfo.DEFAULT_SSF));
}
return this;
}
/**
*
*
* @return this
* @see HttpURLConnection#setUseCaches(boolean)
*/
public HttpConnection disableCache() {
this.conn.setUseCaches(false);
return this;
}
/**
*
*
* @param timeout
* @return this
*/
public HttpConnection setConnectTimeout(int timeout) {
if (timeout > 0 && null != this.conn) {
this.conn.setConnectTimeout(timeout);
}
return this;
}
/**
*
*
* @param timeout
* @return this
*/
public HttpConnection setReadTimeout(int timeout) {
if (timeout > 0 && null != this.conn) {
this.conn.setReadTimeout(timeout);
}
return this;
}
/**
*
*
* @param timeout
* @return this
*/
public HttpConnection setConnectionAndReadTimeout(int timeout) {
setConnectTimeout(timeout);
setReadTimeout(timeout);
return this;
}
/**
* Cookie
*
* @param cookie Cookie
* @return this
*/
public HttpConnection setCookie(String cookie) {
if (cookie != null) {
header(Header.COOKIE, cookie, true);
}
return this;
}
/**
* <br>
* HttpUrlConnection
*
* @param blockSize bytes00Chuncked
* @return this
*/
public HttpConnection setChunkedStreamingMode(int blockSize) {
if (blockSize > 0) {
conn.setChunkedStreamingMode(blockSize);
}
return this;
}
/**
* HTTP 30X
*
* @param isInstanceFollowRedirects
* @return this
*/
public HttpConnection setInstanceFollowRedirects(boolean isInstanceFollowRedirects) {
conn.setInstanceFollowRedirects(isInstanceFollowRedirects);
return this;
}
/**
*
*
* @return this
* @throws IOException IO
*/
public HttpConnection connect() throws IOException {
if (null != this.conn) {
this.conn.connect();
}
return this;
}
/**
*
*
* @return this
* @since 4.6.0
*/
public HttpConnection disconnectQuietly() {
try {
disconnect();
} catch (Throwable e) {
// ignore
}
return this;
}
/**
*
*
* @return this
*/
public HttpConnection disconnect() {
if (null != this.conn) {
this.conn.disconnect();
}
return this;
}
/**
* <br>
*
*
* @return
* @throws IOException IO
*/
public InputStream getInputStream() throws IOException {
if (null != this.conn) {
return this.conn.getInputStream();
}
return null;
}
/**
*
*
* @return
*/
public InputStream getErrorStream() {
if (null != this.conn) {
return this.conn.getErrorStream();
}
return null;
}
/**
*
*
* @return OutputStream
* @throws IOException IO
*/
public OutputStream getOutputStream() throws IOException {
if (null == this.conn) {
throw new IOException("HttpURLConnection has not been initialized.");
}
final aiyh.utils.tool.cn.hutool.http.Method method = getMethod();
// 当有写出需求时,自动打开之
this.conn.setDoOutput(true);
final OutputStream out = this.conn.getOutputStream();
// 解决在Rest请求中GET请求附带body导致GET请求被强制转换为POST
// 在sun.net.www.protocol.http.HttpURLConnection.getOutputStream0方法中会把GET方法
// 修改为POST而且无法调用setRequestMethod方法修改因此此处使用反射强制修改字段属性值
// https://stackoverflow.com/questions/978061/http-get-with-request-body/983458
if (method == aiyh.utils.tool.cn.hutool.http.Method.GET && method != getMethod()) {
reflectSetMethod(method);
}
return out;
}
/**
*
*
* @return
* @throws IOException IO
*/
public int responseCode() throws IOException {
if (null != this.conn) {
return this.conn.getResponseCode();
}
return 0;
}
/**
* <br>
* Http<br>
* ContentType
*
* @return
*/
public String getCharsetName() {
return HttpUtil.getCharset(conn);
}
/**
* <br>
* Http<br>
* ContentType
*
* @return {@link Charset}
* @since 3.0.9
*/
public Charset getCharset() {
Charset charset = null;
final String charsetName = getCharsetName();
if (StrUtil.isNotBlank(charsetName)) {
try {
charset = Charset.forName(charsetName);
} catch (UnsupportedCharsetException e) {
// ignore
}
}
return charset;
}
@Override
public String toString() {
StringBuilder sb = StrUtil.builder();
sb.append("Request URL: ").append(this.url).append(StrUtil.CRLF);
sb.append("Request Method: ").append(this.getMethod()).append(StrUtil.CRLF);
// sb.append("Request Headers: ").append(StrUtil.CRLF);
// for (Entry<String, List<String>> entry : this.conn.getHeaderFields().entrySet()) {
// sb.append(" ").append(entry).append(StrUtil.CRLF);
// }
return sb.toString();
}
// --------------------------------------------------------------- Private Method start
/**
* httphttps<br>
* httpscom.sun.net.ssl.internal.www.protocol.https.HttpsURLConnectionOldImplsunapihttp
*
* @return {@link HttpURLConnection}https{@link HttpsURLConnection}
*/
private HttpURLConnection openHttp() throws IOException {
final URLConnection conn = openConnection();
if (!(conn instanceof HttpURLConnection)) {
// 防止其它协议造成的转换异常
throw new HttpException("'{}' of URL [{}] is not a http connection, make sure URL is format for http.", conn.getClass().getName(), this.url);
}
return (HttpURLConnection) conn;
}
/**
*
*
* @return {@link URLConnection}
* @throws IOException IO
*/
private URLConnection openConnection() throws IOException {
return (null == this.proxy) ? url.openConnection() : url.openConnection(this.proxy);
}
/**
* HttpURLConnection
*
* @param method
*/
private void reflectSetMethod(Method method) {
ReflectUtil.setFieldValue(this.conn, "method", method.name());
// HttpsURLConnectionImpl实现中使用了代理类需要修改被代理类的method方法
final Object delegate = ReflectUtil.getFieldValue(this.conn, "delegate");
if (null != delegate) {
ReflectUtil.setFieldValue(delegate, "method", method.name());
}
}
// --------------------------------------------------------------- Private Method end
}

View File

@ -0,0 +1,122 @@
package aiyh.utils.tool.cn.hutool.http;
import aiyh.utils.tool.cn.hutool.core.io.FastByteArrayOutputStream;
import aiyh.utils.tool.cn.hutool.core.io.StreamProgress;
import aiyh.utils.tool.cn.hutool.core.lang.Assert;
import java.io.File;
import java.io.OutputStream;
import java.nio.charset.Charset;
/**
* 使{@code GET}30x
*
* @author looly
* @since 5.6.4
*/
public class HttpDownloader {
/**
*
*
* @param url url
* @param customCharset 使{@code CharsetUtil#charset}
* @param streamPress {@link StreamProgress}
* @return
*/
public static String downloadString(String url, Charset customCharset, StreamProgress streamPress) {
final FastByteArrayOutputStream out = new FastByteArrayOutputStream();
download(url, out, true, streamPress);
return null == customCharset ? out.toString() : out.toString(customCharset);
}
/**
* 30x
*
* @param url url
* @return
*/
public static byte[] downloadBytes(String url) {
return requestDownload(url, -1).bodyBytes();
}
/**
*
*
* @param url url
* @param targetFileOrDir URL使URL
* @param timeout -1
* @param streamProgress
* @return
*/
public static long downloadFile(String url, File targetFileOrDir, int timeout, StreamProgress streamProgress) {
return requestDownload(url, timeout).writeBody(targetFileOrDir, streamProgress);
}
/**
* -<br>
* https://gitee.com/dromara/hutool/pulls/407<br>
*
*
* @param url url
* @param targetFileOrDir URL使URL
* @param tempFileSuffix ".temp"
* @param timeout -1
* @param streamProgress
* @return
* @since 5.7.12
*/
public long downloadFile(String url, File targetFileOrDir, String tempFileSuffix, int timeout, StreamProgress streamProgress) {
return requestDownload(url, timeout).writeBody(targetFileOrDir, tempFileSuffix, streamProgress);
}
/**
*
*
* @param url url
* @param targetFileOrDir URL使URL
* @param timeout -1
* @param streamProgress
* @return
*/
public static File downloadForFile(String url, File targetFileOrDir, int timeout, StreamProgress streamProgress) {
return requestDownload(url, timeout).writeBodyForFile(targetFileOrDir, streamProgress);
}
/**
*
*
* @param url url
* @param out {@link OutputStream}
* @param isCloseOut
* @param streamProgress
* @return
*/
public static long download(String url, OutputStream out, boolean isCloseOut, StreamProgress streamProgress) {
Assert.notNull(out, "[out] is null !");
return requestDownload(url, -1).writeBody(out, isCloseOut, streamProgress);
}
/**
*
*
* @param url
* @param timeout
* @return HttpResponse
* @since 5.4.1
*/
private static aiyh.utils.tool.cn.hutool.http.HttpResponse requestDownload(String url, int timeout) {
Assert.notBlank(url, "[url] is blank !");
final HttpResponse response = HttpUtil.createGet(url, true)
.timeout(timeout)
.executeAsync();
if (response.isOk()) {
return response;
}
throw new HttpException("Server response error with status code: [{}]", response.getStatus());
}
}

View File

@ -0,0 +1,36 @@
package aiyh.utils.tool.cn.hutool.http;
import aiyh.utils.tool.cn.hutool.core.util.StrUtil;
/**
* HTTP
*
* @author xiaoleilu
*/
public class HttpException extends RuntimeException {
private static final long serialVersionUID = 8247610319171014183L;
public HttpException(Throwable e) {
super(e.getMessage(), e);
}
public HttpException(String message) {
super(message);
}
public HttpException(String messageTemplate, Object... params) {
super(StrUtil.format(messageTemplate, params));
}
public HttpException(String message, Throwable throwable) {
super(message, throwable);
}
public HttpException(String message, Throwable throwable, boolean enableSuppression, boolean writableStackTrace) {
super(message, throwable, enableSuppression, writableStackTrace);
}
public HttpException(Throwable throwable, String messageTemplate, Object... params) {
super(StrUtil.format(messageTemplate, params), throwable);
}
}

View File

@ -0,0 +1,214 @@
package aiyh.utils.tool.cn.hutool.http;
import aiyh.utils.tool.cn.hutool.core.util.ArrayUtil;
import aiyh.utils.tool.cn.hutool.core.util.RandomUtil;
import aiyh.utils.tool.cn.hutool.core.util.ReflectUtil;
import aiyh.utils.tool.cn.hutool.http.cookie.GlobalCookieManager;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.net.CookieManager;
import java.net.HttpURLConnection;
/**
* HTTP
*
* @author Looly
* @since 4.6.2
*/
public class HttpGlobalConfig implements Serializable {
private static final long serialVersionUID = 1L;
/**
* -1:
* timeout = 3s(3000 ms), 6s
* timeout of zero is interpreted as an infinite timeout. 0
* .
* {@link HttpURLConnection#setReadTimeout(int)} :
* {@link HttpURLConnection#setConnectTimeout(int)} :
*/
private static int timeout = -1;
private static boolean isAllowPatch = false;
private static String boundary = "--------------------Hutool_" + RandomUtil.randomString(16);
private static int maxRedirectCount = 0;
private static boolean ignoreEOFError = true;
private static boolean decodeUrl = false;
/**
*
*
* @return
*/
public static int getTimeout() {
return timeout;
}
/**
* <br>
* -1: <br>
* timeout = 3s(3000 ms), 6s<br>
* timeout of zero is interpreted as an infinite timeout. 0<br>
* .<br>
* {@link HttpURLConnection#setReadTimeout(int)} : <br>
* {@link HttpURLConnection#setConnectTimeout(int)} :
*
* @param customTimeout
*/
synchronized public static void setTimeout(int customTimeout) {
timeout = customTimeout;
}
/**
* Multipart
*
* @return Multipart
* @since 5.7.17
*/
public static String getBoundary() {
return boundary;
}
/**
* Multipart
*
* @param customBoundary Multipart
* @since 5.7.17
*/
synchronized public static void setBoundary(String customBoundary) {
boundary = customBoundary;
}
/**
* 0<br>
* 1
*
* @return
* @since 5.7.19
*/
public static int getMaxRedirectCount() {
return maxRedirectCount;
}
/**
* 0<br>
* 1
*
* @param customMaxRedirectCount
* @since 5.7.19
*/
synchronized public static void setMaxRedirectCount(int customMaxRedirectCount) {
maxRedirectCount = customMaxRedirectCount;
}
/**
* EOF<br>
* HttpTransfer-Encoding: ChunkedLength0chunk<br>
* EOF
*
* @return EOF
* @since 5.7.20
*/
public static boolean isIgnoreEOFError() {
return ignoreEOFError;
}
/**
* EOF<br>
* HttpTransfer-Encoding: ChunkedLength0chunk<br>
* EOF
*
* @param customIgnoreEOFError EOF
* @since 5.7.20
*/
synchronized public static void setIgnoreEOFError(boolean customIgnoreEOFError) {
ignoreEOFError = customIgnoreEOFError;
}
/**
* URLURLPathParam<br>
* HttpURL{@code true}<br>
* RFC3986{@code false}
*
* @return URL
* @since 5.7.22
*/
public static boolean isDecodeUrl() {
return decodeUrl;
}
/**
* URLURLPathParam<br>
* HttpURL{@code true}<br>
* RFC3986{@code false}
*
* @param customDecodeUrl URL
* @since 5.7.22
*/
synchronized public static void setDecodeUrl(boolean customDecodeUrl) {
decodeUrl = customDecodeUrl;
}
/**
* CookieCookie
*
* @return {@link CookieManager}
* @see GlobalCookieManager#getCookieManager()
* @since 4.1.0
*/
public static CookieManager getCookieManager() {
return GlobalCookieManager.getCookieManager();
}
/**
* {@link CookieManager}
*
* @param customCookieManager {@link CookieManager}
* @see GlobalCookieManager#setCookieManager(CookieManager)
* @since 4.5.14
*/
synchronized public static void setCookieManager(CookieManager customCookieManager) {
GlobalCookieManager.setCookieManager(customCookieManager);
}
/**
* Cookie
*
* @see GlobalCookieManager#setCookieManager(CookieManager)
* @since 4.1.9
*/
synchronized public static void closeCookie() {
GlobalCookieManager.setCookieManager(null);
}
/**
* METHOD<br>
* {@link HttpURLConnection}methodsPATCH<br>
* see: <a href="https://stackoverflow.com/questions/25163131/httpurlconnection-invalid-http-method-patch">https://stackoverflow.com/questions/25163131/httpurlconnection-invalid-http-method-patch</a>
*
* @since 5.7.4
*/
synchronized public static void allowPatch() {
if (isAllowPatch) {
return;
}
final Field methodsField = ReflectUtil.getField(HttpURLConnection.class, "methods");
if (null == methodsField) {
throw new HttpException("None static field [methods] with Java version: [{}]", System.getProperty("java.version"));
}
// 去除final修饰
ReflectUtil.removeFinalModify(methodsField);
final String[] methods = {
"GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE", "PATCH"
};
ReflectUtil.setFieldValue(null, methodsField, methods);
// 检查注入是否成功
final Object staticFieldValue = ReflectUtil.getStaticFieldValue(methodsField);
if (!ArrayUtil.equals(methods, staticFieldValue)) {
throw new HttpException("Inject value to field [methods] failed!");
}
isAllowPatch = true;
}
}

View File

@ -0,0 +1,108 @@
package aiyh.utils.tool.cn.hutool.http;
import aiyh.utils.tool.cn.hutool.core.util.StrUtil;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
/**
* HTTPHttp
*
* @author Looly
*
*/
public class HttpInputStream extends InputStream {
/** 原始流 */
private InputStream in;
/**
*
*
* @param response
*/
public HttpInputStream(aiyh.utils.tool.cn.hutool.http.HttpResponse response) {
init(response);
}
@Override
public int read() throws IOException {
return this.in.read();
}
@SuppressWarnings("NullableProblems")
@Override
public int read(byte[] b, int off, int len) throws IOException {
return this.in.read(b, off, len);
}
@Override
public long skip(long n) throws IOException {
return this.in.skip(n);
}
@Override
public int available() throws IOException {
return this.in.available();
}
@Override
public void close() throws IOException {
this.in.close();
}
@Override
public synchronized void mark(int readlimit) {
this.in.mark(readlimit);
}
@Override
public synchronized void reset() throws IOException {
this.in.reset();
}
@Override
public boolean markSupported() {
return this.in.markSupported();
}
/**
*
*
* @param response
*/
private void init(HttpResponse response) {
try {
this.in = (response.status < HttpStatus.HTTP_BAD_REQUEST) ? response.httpConnection.getInputStream() : response.httpConnection.getErrorStream();
} catch (IOException e) {
if (false == (e instanceof FileNotFoundException)) {
throw new HttpException(e);
}
// 服务器无返回内容,忽略之
}
// 在一些情况下返回的流为null此时提供状态码说明
if (null == this.in) {
this.in = new ByteArrayInputStream(StrUtil.format("Error request, response status: {}", response.status).getBytes());
return;
}
if (response.isGzip() && false == (response.in instanceof GZIPInputStream)) {
// Accept-Encoding: gzip
try {
this.in = new GZIPInputStream(this.in);
} catch (IOException e) {
// 在类似于Head等方法中无body返回此时GZIPInputStream构造会出现错误在此忽略此错误读取普通数据
// ignore
}
} else if (response.isDeflate() && false == (this.in instanceof InflaterInputStream)) {
// Accept-Encoding: defalte
this.in = new InflaterInputStream(this.in, new Inflater(true));
}
}
}

View File

@ -0,0 +1,56 @@
package aiyh.utils.tool.cn.hutool.http;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
/**
* Http
*
* @param <T> HttpRequestHttpResponse
* @author looly
* @since 5.7.16
*/
@FunctionalInterface
public interface HttpInterceptor<T extends aiyh.utils.tool.cn.hutool.http.HttpBase<T>> {
/**
*
*
* @param httpObj
*/
void process(T httpObj);
/**
*
*
* @param <T> HttpRequestHttpResponse
* @author looly
* @since 5.7.16
*/
class Chain<T extends HttpBase<T>> implements aiyh.utils.tool.cn.hutool.core.lang.Chain<HttpInterceptor<T>, Chain<T>> {
private final List<HttpInterceptor<T>> interceptors = new LinkedList<>();
@Override
public Chain<T> addChain(HttpInterceptor<T> element) {
interceptors.add(element);
return this;
}
@Override
public Iterator<HttpInterceptor<T>> iterator() {
return interceptors.iterator();
}
/**
*
*
* @return this
* @since 5.8.0
*/
public Chain<T> clear() {
interceptors.clear();
return this;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,56 @@
package aiyh.utils.tool.cn.hutool.http;
import aiyh.utils.tool.cn.hutool.core.io.resource.Resource;
import aiyh.utils.tool.cn.hutool.core.lang.Assert;
import java.io.InputStream;
import java.io.Serializable;
import java.net.URL;
/**
* HTTPContent-Type
*
* @author looly
* @since 5.7.17
*/
public class HttpResource implements Resource, Serializable {
private static final long serialVersionUID = 1L;
private final Resource resource;
private final String contentType;
/**
*
*
* @param resource
* @param contentType Content-Type{@code null}
*/
public HttpResource(Resource resource, String contentType) {
this.resource = Assert.notNull(resource, "Resource must be not null !");
this.contentType = contentType;
}
@Override
public String getName() {
return resource.getName();
}
@Override
public URL getUrl() {
return resource.getUrl();
}
@Override
public InputStream getStream() {
return resource.getStream();
}
/**
* Content-Type
*
* @return Content-Type
*/
public String getContentType() {
return this.contentType;
}
}

View File

@ -0,0 +1,644 @@
package aiyh.utils.tool.cn.hutool.http;
import aiyh.utils.tool.cn.hutool.core.convert.Convert;
import aiyh.utils.tool.cn.hutool.core.io.FastByteArrayOutputStream;
import aiyh.utils.tool.cn.hutool.core.io.FileUtil;
import aiyh.utils.tool.cn.hutool.core.io.IORuntimeException;
import aiyh.utils.tool.cn.hutool.core.io.IoUtil;
import aiyh.utils.tool.cn.hutool.core.io.StreamProgress;
import aiyh.utils.tool.cn.hutool.core.lang.Assert;
import aiyh.utils.tool.cn.hutool.core.util.ObjUtil;
import aiyh.utils.tool.cn.hutool.core.util.ReUtil;
import aiyh.utils.tool.cn.hutool.core.util.StrUtil;
import aiyh.utils.tool.cn.hutool.core.util.URLUtil;
import aiyh.utils.tool.cn.hutool.http.cookie.GlobalCookieManager;
import java.io.ByteArrayInputStream;
import java.io.Closeable;
import java.io.EOFException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpCookie;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map.Entry;
/**
* Http<br>
* 线
*
* @author Looly
*/
public class HttpResponse extends HttpBase<HttpResponse> implements Closeable {
/**
* Http
*/
protected HttpConfig config;
/**
*
*/
protected HttpConnection httpConnection;
/**
* Http
*/
protected InputStream in;
/**
* body
*/
private volatile boolean isAsync;
/**
*
*/
protected int status;
/**
* Http
*/
private final boolean ignoreBody;
/**
*
*/
private Charset charsetFromResponse;
/**
*
*
* @param httpConnection {@link HttpConnection}
* @param config Http
* @param charset
* @param isAsync
* @param isIgnoreBody
* @since 3.1.2
*/
protected HttpResponse(HttpConnection httpConnection, HttpConfig config, Charset charset, boolean isAsync, boolean isIgnoreBody) {
this.httpConnection = httpConnection;
this.config = config;
this.charset = charset;
this.isAsync = isAsync;
this.ignoreBody = isIgnoreBody;
initWithDisconnect();
}
/**
*
*
* @return
*/
public int getStatus() {
return this.status;
}
/**
* 200~299
*
* @return
* @since 4.1.9
*/
public boolean isOk() {
return this.status >= 200 && this.status < 300;
}
/**
* <br>
* Http{@link InputStream}<br>
* Httpbody
*
* @return this
*/
public HttpResponse sync() {
return this.isAsync ? forceSync() : this;
}
// ---------------------------------------------------------------- Http Response Header start
/**
*
*
* @return String
*/
public String contentEncoding() {
return header(aiyh.utils.tool.cn.hutool.http.Header.CONTENT_ENCODING);
}
/**
*
* <ul>
* <li>Transfer-Encoding: Chunked</li>
* <li>Content-Encoding: XXX</li>
* </ul>
* https://blog.csdn.net/jiang7701037/article/details/86304302
*
* @return -1
* @since 5.7.9
*/
public long contentLength() {
long contentLength = Convert.toLong(header(aiyh.utils.tool.cn.hutool.http.Header.CONTENT_LENGTH), -1L);
if (contentLength > 0 && (isChunked() || StrUtil.isNotBlank(contentEncoding()))) {
//按照HTTP协议规范在 Transfer-Encoding和Content-Encoding设置后 Content-Length 无效。
contentLength = -1;
}
return contentLength;
}
/**
* gzip
*
* @return gzip
*/
public boolean isGzip() {
final String contentEncoding = contentEncoding();
return "gzip".equalsIgnoreCase(contentEncoding);
}
/**
* zlib(Deflate)
*
* @return zlib(Deflate)
* @since 4.5.7
*/
public boolean isDeflate() {
final String contentEncoding = contentEncoding();
return "deflate".equalsIgnoreCase(contentEncoding);
}
/**
* Transfer-Encoding:Chunked
*
* @return Transfer-Encoding:Chunked
* @since 4.6.2
*/
public boolean isChunked() {
final String transferEncoding = header(aiyh.utils.tool.cn.hutool.http.Header.TRANSFER_ENCODING);
return "Chunked".equalsIgnoreCase(transferEncoding);
}
/**
* Cookie
*
* @return Cookie
* @since 3.1.1
*/
public String getCookieStr() {
return header(aiyh.utils.tool.cn.hutool.http.Header.SET_COOKIE);
}
/**
* Cookie
*
* @return Cookie
* @since 3.1.1
*/
public List<HttpCookie> getCookies() {
return GlobalCookieManager.getCookies(this.httpConnection);
}
/**
* Cookie
*
* @param name Cookie
* @return {@link HttpCookie}
* @since 4.1.4
*/
public HttpCookie getCookie(String name) {
List<HttpCookie> cookie = getCookies();
if (null != cookie) {
for (HttpCookie httpCookie : cookie) {
if (httpCookie.getName().equals(name)) {
return httpCookie;
}
}
}
return null;
}
/**
* Cookie
*
* @param name Cookie
* @return Cookie
* @since 4.1.4
*/
public String getCookieValue(String name) {
HttpCookie cookie = getCookie(name);
return (null == cookie) ? null : cookie.getValue();
}
// ---------------------------------------------------------------- Http Response Header end
// ---------------------------------------------------------------- Body start
/**
* <br>
* Http<br>
* {@link #sync()}<br>
*
*
* @return
*/
public InputStream bodyStream() {
if (isAsync) {
return this.in;
}
return new ByteArrayInputStream(this.bodyBytes);
}
/**
* <br>
*
*
* @return byte[]
*/
@Override
public byte[] bodyBytes() {
sync();
return this.bodyBytes;
}
/**
* <br>
* 使charset使UTF-8
*
* @param bodyBytes
* @return this
*/
public HttpResponse body(byte[] bodyBytes) {
sync();
if (null != bodyBytes) {
this.bodyBytes = bodyBytes;
}
return this;
}
/**
*
*
* @return String
* @throws HttpException IO
*/
public String body() throws HttpException {
return HttpUtil.getString(bodyBytes(), this.charset, null == this.charsetFromResponse);
}
/**
* {@link OutputStream}<br>
* Http<br>
* Http
*
* @param out
* @param isCloseOut
* @param streamProgress
* @return bytes
* @since 3.3.2
*/
public long writeBody(OutputStream out, boolean isCloseOut, StreamProgress streamProgress) {
Assert.notNull(out, "[out] must be not null!");
final long contentLength = contentLength();
try {
return copyBody(bodyStream(), out, contentLength, streamProgress, this.config.ignoreEOFError);
} finally {
IoUtil.close(this);
if (isCloseOut) {
IoUtil.close(out);
}
}
}
/**
* <br>
* Http<br>
* Http
*
* @param targetFileOrDir
* @param streamProgress
* @return bytes
* @since 3.3.2
*/
public long writeBody(File targetFileOrDir, StreamProgress streamProgress) {
Assert.notNull(targetFileOrDir, "[targetFileOrDir] must be not null!");
final File outFile = completeFileNameFromHeader(targetFileOrDir);
return writeBody(FileUtil.getOutputStream(outFile), true, streamProgress);
}
/**
* -<br>
* Http<br>
* Http<br>
* https://gitee.com/dromara/hutool/pulls/407<br>
*
*
* @param targetFileOrDir
* @param tempFileSuffix ".temp"
* @param streamProgress
* @return bytes
* @since 5.7.12
*/
public long writeBody(File targetFileOrDir, String tempFileSuffix, StreamProgress streamProgress) {
Assert.notNull(targetFileOrDir, "[targetFileOrDir] must be not null!");
File outFile = completeFileNameFromHeader(targetFileOrDir);
if (StrUtil.isBlank(tempFileSuffix)) {
tempFileSuffix = ".temp";
} else {
tempFileSuffix = StrUtil.addPrefixIfNot(tempFileSuffix, StrUtil.DOT);
}
// 目标文件真实名称
final String fileName = outFile.getName();
// 临时文件名称
final String tempFileName = fileName + tempFileSuffix;
// 临时文件
outFile = new File(outFile.getParentFile(), tempFileName);
long length;
try {
length = writeBody(outFile, streamProgress);
// 重命名下载好的临时文件
FileUtil.rename(outFile, fileName, true);
} catch (Throwable e) {
// 异常则删除临时文件
FileUtil.del(outFile);
throw new HttpException(e);
}
return length;
}
/**
* <br>
* Http<br>
* Http
*
* @param targetFileOrDir
* @param streamProgress
* @return
* @since 5.6.4
*/
public File writeBodyForFile(File targetFileOrDir, StreamProgress streamProgress) {
Assert.notNull(targetFileOrDir, "[targetFileOrDir] must be not null!");
final File outFile = completeFileNameFromHeader(targetFileOrDir);
writeBody(FileUtil.getOutputStream(outFile), true, streamProgress);
return outFile;
}
/**
* <br>
* Http<br>
* Http
*
* @param targetFileOrDir
* @return bytes
* @since 3.3.2
*/
public long writeBody(File targetFileOrDir) {
return writeBody(targetFileOrDir, null);
}
/**
* <br>
* Http<br>
* Http
*
* @param targetFileOrDir
* @return bytes
* @since 3.3.2
*/
public long writeBody(String targetFileOrDir) {
return writeBody(FileUtil.file(targetFileOrDir));
}
// ---------------------------------------------------------------- Body end
@Override
public void close() {
IoUtil.close(this.in);
this.in = null;
// 关闭连接
this.httpConnection.disconnectQuietly();
}
@Override
public String toString() {
StringBuilder sb = StrUtil.builder();
sb.append("Response Headers: ").append(StrUtil.CRLF);
for (Entry<String, List<String>> entry : this.headers.entrySet()) {
sb.append(" ").append(entry).append(StrUtil.CRLF);
}
sb.append("Response Body: ").append(StrUtil.CRLF);
sb.append(" ").append(this.body()).append(StrUtil.CRLF);
return sb.toString();
}
/**
*
*
* @param targetFileOrDir
* @return File
* @since 5.4.1
*/
public File completeFileNameFromHeader(File targetFileOrDir) {
if (false == targetFileOrDir.isDirectory()) {
// 非目录直接返回
return targetFileOrDir;
}
// 从头信息中获取文件名
String fileName = getFileNameFromDisposition(null);
if (StrUtil.isBlank(fileName)) {
final String path = httpConnection.getUrl().getPath();
// 从路径中获取文件名
fileName = StrUtil.subSuf(path, path.lastIndexOf('/') + 1);
if (StrUtil.isBlank(fileName)) {
// 编码后的路径做为文件名
fileName = URLUtil.encodeQuery(path, charset);
} else {
// issue#I4K0FS@Gitee
fileName = URLUtil.decode(fileName, charset);
}
}
return FileUtil.file(targetFileOrDir, fileName);
}
/**
* Content-Disposition
* @param paramName
*
* @return empty
*/
public String getFileNameFromDisposition(String paramName) {
paramName = ObjUtil.defaultIfNull(paramName, "filename");
String fileName = null;
final String disposition = header(Header.CONTENT_DISPOSITION);
if (StrUtil.isNotBlank(disposition)) {
fileName = ReUtil.get(paramName+"=\"(.*?)\"", disposition, 1);
if (StrUtil.isBlank(fileName)) {
fileName = StrUtil.subAfter(disposition, paramName + "=", true);
}
}
return fileName;
}
// ---------------------------------------------------------------- Private method start
/**
* Http<br>
*
*
* <pre>
* 1Http
* 2
* 3Http
* </pre>
*
* @return this
* @throws HttpException IO
*/
private HttpResponse initWithDisconnect() throws HttpException {
try {
init();
} catch (HttpException e) {
this.httpConnection.disconnectQuietly();
throw e;
}
return this;
}
/**
* Http<br>
*
*
* <pre>
* 1Http
* 2
* 3Http
* </pre>
*
* @return this
* @throws HttpException IO
*/
private HttpResponse init() throws HttpException {
// 获取响应状态码
try {
this.status = httpConnection.responseCode();
} catch (IOException e) {
if (false == (e instanceof FileNotFoundException)) {
throw new HttpException(e);
}
// 服务器无返回内容,忽略之
}
// 读取响应头信息
try {
this.headers = httpConnection.headers();
} catch (IllegalArgumentException e) {
// ignore
// StaticLog.warn(e, e.getMessage());
}
// 存储服务端设置的Cookie信息
GlobalCookieManager.store(httpConnection);
// 获取响应编码
final Charset charset = httpConnection.getCharset();
this.charsetFromResponse = charset;
if (null != charset) {
this.charset = charset;
}
// 获取响应内容流
this.in = new HttpInputStream(this);
// 同步情况下强制同步
return this.isAsync ? this : forceSync();
}
/**
* <br>
*
*
* <pre>
* 1body
* 2false
* 3Http
* 4
* </pre>
*
* @return this
*/
private HttpResponse forceSync() {
// 非同步状态转为同步状态
try {
this.readBody(this.in);
} catch (IORuntimeException e) {
//noinspection StatementWithEmptyBody
if (e.getCause() instanceof FileNotFoundException) {
// 服务器无返回内容,忽略之
} else {
throw new HttpException(e);
}
} finally {
if (this.isAsync) {
this.isAsync = false;
}
this.close();
}
return this;
}
/**
* EOFException
*
* @param in
* @throws IORuntimeException IO
*/
private void readBody(InputStream in) throws IORuntimeException {
if (ignoreBody) {
return;
}
final long contentLength = contentLength();
final FastByteArrayOutputStream out = new FastByteArrayOutputStream((int) contentLength);
copyBody(in, out, contentLength, null, this.config.ignoreEOFError);
this.bodyBytes = out.toByteArray();
}
/**
* {@link OutputStream}<br>
* Http<br>
* Http
*
* @param in
* @param out
* @param contentLength -1
* @param streamProgress
* @param isIgnoreEOFError EOF
* @return
*/
private static long copyBody(InputStream in, OutputStream out, long contentLength, StreamProgress streamProgress, boolean isIgnoreEOFError) {
if (null == out) {
throw new NullPointerException("[out] is null!");
}
long copyLength = -1;
try {
copyLength = IoUtil.copy(in, out, IoUtil.DEFAULT_BUFFER_SIZE, contentLength, streamProgress);
} catch (IORuntimeException e) {
//noinspection StatementWithEmptyBody
if (isIgnoreEOFError
&& (e.getCause() instanceof EOFException || StrUtil.containsIgnoreCase(e.getMessage(), "Premature EOF"))) {
// 忽略读取HTTP流中的EOF错误
} else {
throw e;
}
}
return copyLength;
}
// ---------------------------------------------------------------- Private method end
}

View File

@ -0,0 +1,222 @@
package aiyh.utils.tool.cn.hutool.http;
/**
* HTTP
*
* @author Looly
* @see java.net.HttpURLConnection
*
*/
public class HttpStatus {
/* 2XX: generally "OK" */
/**
* HTTP Status-Code 200: OK.
*/
public static final int HTTP_OK = 200;
/**
* HTTP Status-Code 201: Created.
*/
public static final int HTTP_CREATED = 201;
/**
* HTTP Status-Code 202: Accepted.
*/
public static final int HTTP_ACCEPTED = 202;
/**
* HTTP Status-Code 203: Non-Authoritative Information.
*/
public static final int HTTP_NOT_AUTHORITATIVE = 203;
/**
* HTTP Status-Code 204: No Content.
*/
public static final int HTTP_NO_CONTENT = 204;
/**
* HTTP Status-Code 205: Reset Content.
*/
public static final int HTTP_RESET = 205;
/**
* HTTP Status-Code 206: Partial Content.
*/
public static final int HTTP_PARTIAL = 206;
/* 3XX: relocation/redirect */
/**
* HTTP Status-Code 300: Multiple Choices.
*/
public static final int HTTP_MULT_CHOICE = 300;
/**
* HTTP Status-Code 301: Moved Permanently.
*/
public static final int HTTP_MOVED_PERM = 301;
/**
* HTTP Status-Code 302: Temporary Redirect.
*/
public static final int HTTP_MOVED_TEMP = 302;
/**
* HTTP Status-Code 303: See Other.
*/
public static final int HTTP_SEE_OTHER = 303;
/**
* HTTP Status-Code 304: Not Modified.
*/
public static final int HTTP_NOT_MODIFIED = 304;
/**
* HTTP Status-Code 305: Use Proxy.
*/
public static final int HTTP_USE_PROXY = 305;
/**
* HTTP 1.1 Status-Code 307: Temporary Redirect.<br>
* RFC-7231
*/
public static final int HTTP_TEMP_REDIRECT = 307;
/**
* HTTP 1.1 Status-Code 308: Permanent Redirect <br>
* RFC-7231
*/
public static final int HTTP_PERMANENT_REDIRECT = 308;
/* 4XX: client error */
/**
* HTTP Status-Code 400: Bad Request.
*/
public static final int HTTP_BAD_REQUEST = 400;
/**
* HTTP Status-Code 401: Unauthorized.
*/
public static final int HTTP_UNAUTHORIZED = 401;
/**
* HTTP Status-Code 402: Payment Required.
*/
public static final int HTTP_PAYMENT_REQUIRED = 402;
/**
* HTTP Status-Code 403: Forbidden.
*/
public static final int HTTP_FORBIDDEN = 403;
/**
* HTTP Status-Code 404: Not Found.
*/
public static final int HTTP_NOT_FOUND = 404;
/**
* HTTP Status-Code 405: Method Not Allowed.
*/
public static final int HTTP_BAD_METHOD = 405;
/**
* HTTP Status-Code 406: Not Acceptable.
*/
public static final int HTTP_NOT_ACCEPTABLE = 406;
/**
* HTTP Status-Code 407: Proxy Authentication Required.
*/
public static final int HTTP_PROXY_AUTH = 407;
/**
* HTTP Status-Code 408: Request Time-Out.
*/
public static final int HTTP_CLIENT_TIMEOUT = 408;
/**
* HTTP Status-Code 409: Conflict.
*/
public static final int HTTP_CONFLICT = 409;
/**
* HTTP Status-Code 410: Gone.
*/
public static final int HTTP_GONE = 410;
/**
* HTTP Status-Code 411: Length Required.
*/
public static final int HTTP_LENGTH_REQUIRED = 411;
/**
* HTTP Status-Code 412: Precondition Failed.
*/
public static final int HTTP_PRECON_FAILED = 412;
/**
* HTTP Status-Code 413: Request Entity Too Large.
*/
public static final int HTTP_ENTITY_TOO_LARGE = 413;
/**
* HTTP Status-Code 414: Request-URI Too Large.
*/
public static final int HTTP_REQ_TOO_LONG = 414;
/**
* HTTP Status-Code 415: Unsupported Media Type.
*/
public static final int HTTP_UNSUPPORTED_TYPE = 415;
/* 5XX: server error */
/**
* HTTP Status-Code 500: Internal Server Error.
*/
public static final int HTTP_INTERNAL_ERROR = 500;
/**
* HTTP Status-Code 501: Not Implemented.
*/
public static final int HTTP_NOT_IMPLEMENTED = 501;
/**
* HTTP Status-Code 502: Bad Gateway.
*/
public static final int HTTP_BAD_GATEWAY = 502;
/**
* HTTP Status-Code 503: Service Unavailable.
*/
public static final int HTTP_UNAVAILABLE = 503;
/**
* HTTP Status-Code 504: Gateway Timeout.
*/
public static final int HTTP_GATEWAY_TIMEOUT = 504;
/**
* HTTP Status-Code 505: HTTP Version Not Supported.
*/
public static final int HTTP_VERSION = 505;
/**
*
* @param responseCode
* @return
* @since 5.6.3
*/
public static boolean isRedirected(int responseCode){
return responseCode == HTTP_MOVED_PERM
|| responseCode == HTTP_MOVED_TEMP
|| responseCode == HTTP_SEE_OTHER
// issue#1504@Github307和308是RFC 7538中http 1.1定义的规范
|| responseCode == HTTP_TEMP_REDIRECT
|| responseCode == HTTP_PERMANENT_REDIRECT;
}
}

View File

@ -0,0 +1,893 @@
package aiyh.utils.tool.cn.hutool.http;
import aiyh.utils.tool.cn.hutool.core.codec.Base64;
import aiyh.utils.tool.cn.hutool.core.convert.Convert;
import aiyh.utils.tool.cn.hutool.core.io.FileUtil;
import aiyh.utils.tool.cn.hutool.core.io.IoUtil;
import aiyh.utils.tool.cn.hutool.core.io.StreamProgress;
import aiyh.utils.tool.cn.hutool.core.map.MapUtil;
import aiyh.utils.tool.cn.hutool.core.net.RFC3986;
import aiyh.utils.tool.cn.hutool.core.net.url.UrlQuery;
import aiyh.utils.tool.cn.hutool.core.text.StrBuilder;
import aiyh.utils.tool.cn.hutool.core.util.CharsetUtil;
import aiyh.utils.tool.cn.hutool.core.util.ObjectUtil;
import aiyh.utils.tool.cn.hutool.core.util.ReUtil;
import aiyh.utils.tool.cn.hutool.core.util.StrUtil;
import aiyh.utils.tool.cn.hutool.core.util.URLUtil;
import aiyh.utils.tool.cn.hutool.http.cookie.GlobalCookieManager;
import aiyh.utils.tool.cn.hutool.http.server.SimpleServer;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.CookieManager;
import java.net.HttpURLConnection;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
/**
* Http
*
* @author xiaoleilu
*/
public class HttpUtil {
/**
* Content-Type
*/
public static final Pattern CHARSET_PATTERN = Pattern.compile("charset\\s*=\\s*([a-z0-9-]*)", Pattern.CASE_INSENSITIVE);
/**
* meta
*/
public static final Pattern META_CHARSET_PATTERN = Pattern.compile("<meta[^>]*?charset\\s*=\\s*['\"]?([a-z0-9-]*)", Pattern.CASE_INSENSITIVE);
/**
* https
*
* @param url URL
* @return https
*/
public static boolean isHttps(String url) {
return StrUtil.startWithIgnoreCase(url, "https:");
}
/**
* http
*
* @param url URL
* @return http
* @since 5.3.8
*/
public static boolean isHttp(String url) {
return StrUtil.startWithIgnoreCase(url, "http:");
}
/**
* Http
*
* @param method {@link aiyh.utils.tool.cn.hutool.http.Method}
* @param url URL使HTTPHTTPS
* @return {@link aiyh.utils.tool.cn.hutool.http.HttpRequest}
* @since 3.0.9
*/
public static aiyh.utils.tool.cn.hutool.http.HttpRequest createRequest(Method method, String url) {
return aiyh.utils.tool.cn.hutool.http.HttpRequest.of(url).method(method);
}
/**
* Http GET
*
* @param url URL使HTTPHTTPS
* @return {@link aiyh.utils.tool.cn.hutool.http.HttpRequest}
* @since 3.2.0
*/
public static aiyh.utils.tool.cn.hutool.http.HttpRequest createGet(String url) {
return createGet(url, false);
}
/**
* Http GET
*
* @param url URL使HTTPHTTPS
* @param isFollowRedirects
* @return {@link aiyh.utils.tool.cn.hutool.http.HttpRequest}
* @since 5.6.4
*/
public static aiyh.utils.tool.cn.hutool.http.HttpRequest createGet(String url, boolean isFollowRedirects) {
return aiyh.utils.tool.cn.hutool.http.HttpRequest.get(url).setFollowRedirects(isFollowRedirects);
}
/**
* Http POST
*
* @param url URL使HTTPHTTPS
* @return {@link aiyh.utils.tool.cn.hutool.http.HttpRequest}
* @since 3.2.0
*/
public static aiyh.utils.tool.cn.hutool.http.HttpRequest createPost(String url) {
return aiyh.utils.tool.cn.hutool.http.HttpRequest.post(url);
}
/**
* get
*
* @param urlString
* @param customCharset 使
* @return "" null
*/
public static String get(String urlString, Charset customCharset) {
return aiyh.utils.tool.cn.hutool.http.HttpRequest.get(urlString).charset(customCharset).execute().body();
}
/**
* get
*
* @param urlString
* @return "" null
*/
public static String get(String urlString) {
return get(urlString, HttpGlobalConfig.getTimeout());
}
/**
* get
*
* @param urlString
* @param timeout -1
* @return "" null
* @since 3.2.0
*/
public static String get(String urlString, int timeout) {
return aiyh.utils.tool.cn.hutool.http.HttpRequest.get(urlString).timeout(timeout).execute().body();
}
/**
* get
*
* @param urlString
* @param paramMap post
* @return
*/
public static String get(String urlString, Map<String, Object> paramMap) {
return aiyh.utils.tool.cn.hutool.http.HttpRequest.get(urlString).form(paramMap).execute().body();
}
/**
* get
*
* @param urlString
* @param paramMap post
* @param timeout -1
* @return
* @since 3.3.0
*/
public static String get(String urlString, Map<String, Object> paramMap, int timeout) {
return aiyh.utils.tool.cn.hutool.http.HttpRequest.get(urlString).form(paramMap).timeout(timeout).execute().body();
}
/**
* post
*
* @param urlString
* @param paramMap post
* @return
*/
public static String post(String urlString, Map<String, Object> paramMap) {
return post(urlString, paramMap, HttpGlobalConfig.getTimeout());
}
/**
* post
*
* @param urlString
* @param paramMap post
* @param timeout -1
* @return
* @since 3.2.0
*/
public static String post(String urlString, Map<String, Object> paramMap, int timeout) {
return aiyh.utils.tool.cn.hutool.http.HttpRequest.post(urlString).form(paramMap).timeout(timeout).execute().body();
}
/**
* post<br>
* body
*
* <pre>
* 1. a=1&amp;b=2
* 2. RestbodyJSONXMLHutoolContent-Type
* </pre>
*
* @param urlString
* @param body post
* @return
*/
public static String post(String urlString, String body) {
return post(urlString, body, HttpGlobalConfig.getTimeout());
}
/**
* post<br>
* body
*
* <pre>
* 1. a=1&amp;b=2
* 2. RestbodyJSONXMLHutoolContent-Type
* </pre>
*
* @param urlString
* @param body post
* @param timeout -1
* @return
* @since 3.2.0
*/
public static String post(String urlString, String body, int timeout) {
return HttpRequest.post(urlString).timeout(timeout).body(body).execute().body();
}
// ---------------------------------------------------------------------------------------- download
/**
*
*
* @param url url
* @param customCharsetName
* @return
*/
public static String downloadString(String url, String customCharsetName) {
return downloadString(url, CharsetUtil.charset(customCharsetName), null);
}
/**
*
*
* @param url url
* @param customCharset 使{@link CharsetUtil#charset}
* @return
*/
public static String downloadString(String url, Charset customCharset) {
return downloadString(url, customCharset, null);
}
/**
*
*
* @param url url
* @param customCharset 使{@link CharsetUtil#charset}
* @param streamPress {@link StreamProgress}
* @return
*/
public static String downloadString(String url, Charset customCharset, StreamProgress streamPress) {
return HttpDownloader.downloadString(url, customCharset, streamPress);
}
/**
*
*
* @param url url
* @param dest URL使URL
* @return
*/
public static long downloadFile(String url, String dest) {
return downloadFile(url, FileUtil.file(dest));
}
/**
*
*
* @param url url
* @param destFile URL使URL
* @return
*/
public static long downloadFile(String url, File destFile) {
return downloadFile(url, destFile, null);
}
/**
*
*
* @param url url
* @param destFile URL使URL
* @param timeout -1
* @return
* @since 4.0.4
*/
public static long downloadFile(String url, File destFile, int timeout) {
return downloadFile(url, destFile, timeout, null);
}
/**
*
*
* @param url url
* @param destFile URL使URL
* @param streamProgress
* @return
*/
public static long downloadFile(String url, File destFile, StreamProgress streamProgress) {
return downloadFile(url, destFile, -1, streamProgress);
}
/**
*
*
* @param url url
* @param destFile URL使URL
* @param timeout -1
* @param streamProgress
* @return
* @since 4.0.4
*/
public static long downloadFile(String url, File destFile, int timeout, StreamProgress streamProgress) {
return HttpDownloader.downloadFile(url, destFile, timeout, streamProgress);
}
/**
*
*
* @param url url
* @param dest URL使URL
* @return
* @since 5.4.1
*/
public static File downloadFileFromUrl(String url, String dest) {
return downloadFileFromUrl(url, FileUtil.file(dest));
}
/**
*
*
* @param url url
* @param destFile URL使URL
* @return
* @since 5.4.1
*/
public static File downloadFileFromUrl(String url, File destFile) {
return downloadFileFromUrl(url, destFile, null);
}
/**
*
*
* @param url url
* @param destFile URL使URL
* @param timeout -1
* @return
* @since 5.4.1
*/
public static File downloadFileFromUrl(String url, File destFile, int timeout) {
return downloadFileFromUrl(url, destFile, timeout, null);
}
/**
*
*
* @param url url
* @param destFile URL使URL
* @param streamProgress
* @return
* @since 5.4.1
*/
public static File downloadFileFromUrl(String url, File destFile, StreamProgress streamProgress) {
return downloadFileFromUrl(url, destFile, -1, streamProgress);
}
/**
*
*
* @param url url
* @param destFile URL使URL
* @param timeout -1
* @param streamProgress
* @return
* @since 5.4.1
*/
public static File downloadFileFromUrl(String url, File destFile, int timeout, StreamProgress streamProgress) {
return HttpDownloader.downloadForFile(url, destFile, timeout, streamProgress);
}
/**
*
*
* @param url url
* @param out {@link OutputStream}
* @param isCloseOut
* @return
*/
public static long download(String url, OutputStream out, boolean isCloseOut) {
return download(url, out, isCloseOut, null);
}
/**
*
*
* @param url url
* @param out {@link OutputStream}
* @param isCloseOut
* @param streamProgress
* @return
*/
public static long download(String url, OutputStream out, boolean isCloseOut, StreamProgress streamProgress) {
return HttpDownloader.download(url, out, isCloseOut, streamProgress);
}
/**
* 30x
*
* @param url url
* @return
* @since 5.3.6
*/
public static byte[] downloadBytes(String url) {
return HttpDownloader.downloadBytes(url);
}
/**
* MapFormUrlurl
*
* @param paramMap
* @return url
*/
public static String toParams(Map<String, ?> paramMap) {
return toParams(paramMap, CharsetUtil.CHARSET_UTF_8);
}
/**
* MapFormUrl<br>
*
*
* @param paramMap
* @param charsetName
* @return url
* @deprecated 使 {@link #toParams(Map, Charset)}
*/
@Deprecated
public static String toParams(Map<String, Object> paramMap, String charsetName) {
return toParams(paramMap, CharsetUtil.charset(charsetName));
}
/**
* MapFormUrl<br>
* paramMapkeynull""valuenull""<br>
* url<br>
* URLQueryPOST
*
* <pre>
* key1=v1&amp;key2=&amp;key3=v3
* </pre>
*
* @param paramMap
* @param charset {@code null} encode
* @return url
* @see #toParams(Map, Charset, boolean)
*/
public static String toParams(Map<String, ?> paramMap, Charset charset) {
return toParams(paramMap, charset, false);
}
/**
* MapFormUrl<br>
* paramMapkeynull""valuenull""<br>
* url
*
* <pre>
* key1=v1&amp;key2=&amp;key3=v3
* </pre>
*
* @param paramMap
* @param charset nullencode
* @param isFormUrlEncoded x-www-form-urlencoded'+'
* @return url
* @since 5.7.16
*/
public static String toParams(Map<String, ?> paramMap, Charset charset, boolean isFormUrlEncoded) {
return UrlQuery.of(paramMap, isFormUrlEncoded).build(charset);
}
/**
* URL<br>
* urlurl
*
* <p>URL</p>
*
* @param urlWithParams urlurl
* @param charset
* @return url
* @since 4.0.1
*/
public static String encodeParams(String urlWithParams, Charset charset) {
if (StrUtil.isBlank(urlWithParams)) {
return StrUtil.EMPTY;
}
String urlPart = null; // url部分不包括问号
String paramPart; // 参数部分
final int pathEndPos = urlWithParams.indexOf('?');
if (pathEndPos > -1) {
// url + 参数
urlPart = StrUtil.subPre(urlWithParams, pathEndPos);
paramPart = StrUtil.subSuf(urlWithParams, pathEndPos + 1);
if (StrUtil.isBlank(paramPart)) {
// 无参数返回url
return urlPart;
}
} else if (false == StrUtil.contains(urlWithParams, '=')) {
// 无参数的URL
return urlWithParams;
} else {
// 无URL的参数
paramPart = urlWithParams;
}
paramPart = normalizeParams(paramPart, charset);
return StrUtil.isBlank(urlPart) ? paramPart : urlPart + "?" + paramPart;
}
/**
* URL
*
* <p>URL</p>
*
* @param paramPart
* @param charset
* @return
* @since 4.5.2
*/
public static String normalizeParams(String paramPart, Charset charset) {
if(StrUtil.isEmpty(paramPart)){
return paramPart;
}
final StrBuilder builder = StrBuilder.create(paramPart.length() + 16);
final int len = paramPart.length();
String name = null;
int pos = 0; // 未处理字符开始位置
char c; // 当前字符
int i; // 当前字符位置
for (i = 0; i < len; i++) {
c = paramPart.charAt(i);
if (c == '=') { // 键值对的分界点
if (null == name) {
// 只有=前未定义name时被当作键值分界符否则做为普通字符
name = (pos == i) ? StrUtil.EMPTY : paramPart.substring(pos, i);
pos = i + 1;
}
} else if (c == '&') { // 参数对的分界点
if (pos != i) {
if (null == name) {
// 对于像&a&这类无参数值的字符串我们将name为a的值设为""
name = paramPart.substring(pos, i);
builder.append(RFC3986.QUERY_PARAM_NAME.encode(name, charset)).append('=');
} else {
builder.append(RFC3986.QUERY_PARAM_NAME.encode(name, charset)).append('=')
.append(RFC3986.QUERY_PARAM_VALUE.encode(paramPart.substring(pos, i), charset)).append('&');
}
name = null;
}
pos = i + 1;
}
}
// 结尾处理
if (null != name) {
builder.append(URLUtil.encodeQuery(name, charset)).append('=');
}
if (pos != i) {
if (null == name && pos > 0) {
builder.append('=');
}
builder.append(URLUtil.encodeQuery(paramPart.substring(pos, i), charset));
}
// 以&结尾则去除之
int lastIndex = builder.length() - 1;
if ('&' == builder.charAt(lastIndex)) {
builder.delTo(lastIndex);
}
return builder.toString();
}
/**
* URLMapPost
*
* @param paramsStr Path
* @param charset
* @return Map
* @since 5.2.6
*/
public static Map<String, String> decodeParamMap(String paramsStr, Charset charset) {
final Map<CharSequence, CharSequence> queryMap = UrlQuery.of(paramsStr, charset).getQueryMap();
if (MapUtil.isEmpty(queryMap)) {
return MapUtil.empty();
}
return Convert.toMap(String.class, String.class, queryMap);
}
/**
* URLMapPost
*
* @param paramsStr Path
* @param charset
* @return Map
*/
public static Map<String, List<String>> decodeParams(String paramsStr, String charset) {
return decodeParams(paramsStr, charset, false);
}
/**
* URLMapPost
*
* @param paramsStr Path
* @param charset
* @param isFormUrlEncoded x-www-form-urlencoded'+'
* @return Map
* @since 5.8.12
*/
public static Map<String, List<String>> decodeParams(String paramsStr, String charset, boolean isFormUrlEncoded) {
return decodeParams(paramsStr, CharsetUtil.charset(charset), isFormUrlEncoded);
}
/**
* URL QueryStringMap
*
* @param paramsStr Path
* @param charset
* @return Map
* @since 5.2.6
*/
public static Map<String, List<String>> decodeParams(String paramsStr, Charset charset) {
return decodeParams(paramsStr, charset, false);
}
/**
* URLMapPost
*
* @param paramsStr Path
* @param charset
* @param isFormUrlEncoded x-www-form-urlencoded'+'
* @return Map
*/
public static Map<String, List<String>> decodeParams(String paramsStr, Charset charset, boolean isFormUrlEncoded) {
final Map<CharSequence, CharSequence> queryMap =
UrlQuery.of(paramsStr, charset, true, isFormUrlEncoded).getQueryMap();
if (MapUtil.isEmpty(queryMap)) {
return MapUtil.empty();
}
final Map<String, List<String>> params = new LinkedHashMap<>();
queryMap.forEach((key, value) -> {
final List<String> values = params.computeIfAbsent(StrUtil.str(key), k -> new ArrayList<>(1));
// 一般是一个参数
values.add(StrUtil.str(value));
});
return params;
}
/**
* URLGET<br>
* urlurl
*
* @param url URL
* @param form
* @param charset
* @param isEncodeParams
* @return URL
*/
public static String urlWithForm(String url, Map<String, Object> form, Charset charset, boolean isEncodeParams) {
if (isEncodeParams && StrUtil.contains(url, '?')) {
// 在需要编码的情况下如果url中已经有部分参数则编码之
url = encodeParams(url, charset);
}
// url和参数是分别编码的
return urlWithForm(url, toParams(form, charset), charset, false);
}
/**
* URLGET
*
* @param url URL
* @param queryString
* @param charset
* @param isEncode
* @return
*/
public static String urlWithForm(String url, String queryString, Charset charset, boolean isEncode) {
if (StrUtil.isBlank(queryString)) {
// 无额外参数
if (StrUtil.contains(url, '?')) {
// url中包含参数
return isEncode ? encodeParams(url, charset) : url;
}
return url;
}
// 始终有参数
final StrBuilder urlBuilder = StrBuilder.create(url.length() + queryString.length() + 16);
int qmIndex = url.indexOf('?');
if (qmIndex > 0) {
// 原URL带参数则对这部分参数单独编码如果选项为进行编码
urlBuilder.append(isEncode ? encodeParams(url, charset) : url);
if (false == StrUtil.endWith(url, '&')) {
// 已经带参数的情况下追加参数
urlBuilder.append('&');
}
} else {
// 原url无参数则不做编码
urlBuilder.append(url);
if (qmIndex < 0) {
// 无 '?' 追加之
urlBuilder.append('?');
}
}
urlBuilder.append(isEncode ? encodeParams(queryString, charset) : queryString);
return urlBuilder.toString();
}
/**
* Http<br>
* ContentType
*
* @param conn HTTP
* @return
*/
public static String getCharset(HttpURLConnection conn) {
if (conn == null) {
return null;
}
return getCharset(conn.getContentType());
}
/**
* Http<br>
* ContentType
*
* @param contentType Content-Type
* @return
* @since 5.2.6
*/
public static String getCharset(String contentType) {
if (StrUtil.isBlank(contentType)) {
return null;
}
return ReUtil.get(CHARSET_PATTERN, contentType, 1);
}
/**
* <br>
* 使charsetUTF-8isGetCharsetFromContenttrue
*
* @param in
* @param charset
* @param isGetCharsetFromContent
* @return
*/
public static String getString(InputStream in, Charset charset, boolean isGetCharsetFromContent) {
final byte[] contentBytes = IoUtil.readBytes(in);
return getString(contentBytes, charset, isGetCharsetFromContent);
}
/**
* <br>
* 使charsetUTF-8isGetCharsetFromContenttrue
*
* @param contentBytes byte
* @param charset
* @param isGetCharsetFromContent
* @return
*/
public static String getString(byte[] contentBytes, Charset charset, boolean isGetCharsetFromContent) {
if (null == contentBytes) {
return null;
}
if (null == charset) {
charset = CharsetUtil.CHARSET_UTF_8;
}
String content = new String(contentBytes, charset);
if (isGetCharsetFromContent) {
final String charsetInContentStr = ReUtil.get(META_CHARSET_PATTERN, content, 1);
if (StrUtil.isNotBlank(charsetInContentStr)) {
Charset charsetInContent = null;
try {
charsetInContent = Charset.forName(charsetInContentStr);
} catch (Exception e) {
if (StrUtil.containsIgnoreCase(charsetInContentStr, "utf-8") || StrUtil.containsIgnoreCase(charsetInContentStr, "utf8")) {
charsetInContent = CharsetUtil.CHARSET_UTF_8;
} else if (StrUtil.containsIgnoreCase(charsetInContentStr, "gbk")) {
charsetInContent = CharsetUtil.CHARSET_GBK;
}
// ignore
}
if (null != charsetInContent && false == charset.equals(charsetInContent)) {
content = new String(contentBytes, charsetInContent);
}
}
}
return content;
}
/**
* MimeType
*
* @param filePath
* @param defaultValue MimeTypenull
* @return MimeType
* @see FileUtil#getMimeType(String)
* @since 4.6.5
*/
public static String getMimeType(String filePath, String defaultValue) {
return ObjectUtil.defaultIfNull(getMimeType(filePath), defaultValue);
}
/**
* MimeType
*
* @param filePath
* @return MimeType
* @see FileUtil#getMimeType(String)
*/
public static String getMimeType(String filePath) {
return FileUtil.getMimeType(filePath);
}
/**
* bodyContent-Type
*
* <pre>
* 1. application/json
* 1. application/xml
* </pre>
*
* @param body
* @return Content-Typenull
* @see aiyh.utils.tool.cn.hutool.http.ContentType#get(String)
* @since 3.2.0
*/
public static String getContentTypeByRequestBody(String body) {
final aiyh.utils.tool.cn.hutool.http.ContentType contentType = ContentType.get(body);
return (null == contentType) ? null : contentType.toString();
}
/**
* Http
*
* @param port
* @return {@link SimpleServer}
* @since 5.2.6
*/
public static SimpleServer createServer(int port) {
return new SimpleServer(port);
}
/**
*
* <pre>
* Basic YWxhZGRpbjpvcGVuc2VzYW1l
* </pre>
*
* @param username
* @param password
* @param charset ASCII
* @return
* @since 5.4.6
*/
public static String buildBasicAuth(String username, String password, Charset charset) {
final String data = username.concat(":").concat(password);
return "Basic " + Base64.encode(data, charset);
}
/**
* Cookie
*
* @see GlobalCookieManager#setCookieManager(CookieManager)
* @since 5.6.5
*/
public static void closeCookie() {
GlobalCookieManager.setCookieManager(null);
}
}

View File

@ -0,0 +1,10 @@
package aiyh.utils.tool.cn.hutool.http;
/**
* Http
*
* @author Looly
*/
public enum Method {
GET, POST, HEAD, OPTIONS, PUT, DELETE, TRACE, CONNECT, PATCH
}

View File

@ -0,0 +1,185 @@
package aiyh.utils.tool.cn.hutool.http;
import aiyh.utils.tool.cn.hutool.core.convert.Convert;
import aiyh.utils.tool.cn.hutool.core.io.IORuntimeException;
import aiyh.utils.tool.cn.hutool.core.io.IoUtil;
import aiyh.utils.tool.cn.hutool.core.io.resource.MultiResource;
import aiyh.utils.tool.cn.hutool.core.io.resource.Resource;
import aiyh.utils.tool.cn.hutool.core.io.resource.StringResource;
import aiyh.utils.tool.cn.hutool.core.util.StrUtil;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
/**
* Multipart/form-data<br>
* RFC2388
*
* @author looly
* @since 5.7.17
*/
public class MultipartOutputStream extends OutputStream {
private static final String CONTENT_DISPOSITION_TEMPLATE = "Content-Disposition: form-data; name=\"{}\"\r\n";
private static final String CONTENT_DISPOSITION_FILE_TEMPLATE = "Content-Disposition: form-data; name=\"{}\"; filename=\"{}\"\r\n";
private static final String CONTENT_TYPE_FILE_TEMPLATE = "Content-Type: {}\r\n";
private final OutputStream out;
private final Charset charset;
private final String boundary;
private boolean isFinish;
/**
* 使
*
* @param out HTTP
* @param charset
*/
public MultipartOutputStream(OutputStream out, Charset charset) {
this(out, charset, HttpGlobalConfig.getBoundary());
}
/**
*
*
* @param out HTTP
* @param charset
* @param boundary
* @since 5.7.17
*/
public MultipartOutputStream(OutputStream out, Charset charset, String boundary) {
this.out = out;
this.charset = charset;
this.boundary = boundary;
}
/**
* Multipart<br>
* <pre>
* --(boundary)[]
* Content-Disposition: form-data; name="参数名"[]
* []
* []
* </pre>
* <p>
*
*
* <pre>
* --(boundary)[]
* Content-Disposition: form-data; name="表单名"; filename="文件名"[]
* Content-Type: MIME[]
* []
* []
* </pre>
*
* @param formFieldName
* @param value
* @return this
* @throws IORuntimeException IO
*/
public MultipartOutputStream write(String formFieldName, Object value) throws IORuntimeException {
// 多资源
if (value instanceof MultiResource) {
for (Resource subResource : (MultiResource) value) {
write(formFieldName, subResource);
}
return this;
}
// --分隔符(boundary)[换行]
beginPart();
if (value instanceof Resource) {
appendResource(formFieldName, (Resource) value);
} else {
appendResource(formFieldName,
new StringResource(Convert.toStr(value), null, this.charset));
}
write(StrUtil.CRLF);
return this;
}
@Override
public void write(int b) throws IOException {
this.out.write(b);
}
/**
*
*
* @throws IORuntimeException IO
*/
public void finish() throws IORuntimeException {
if (!isFinish) {
write(StrUtil.format("--{}--\r\n", boundary));
this.isFinish = true;
}
}
@Override
public void close() {
finish();
IoUtil.close(this.out);
}
/**
* MultipartResource{@link HttpResource}
*
* @param formFieldName
* @param resource
* @throws IORuntimeException IO
*/
private void appendResource(String formFieldName, Resource resource) throws IORuntimeException {
final String fileName = resource.getName();
// Content-Disposition
if (null == fileName) {
// Content-Disposition: form-data; name="参数名"[换行]
write(StrUtil.format(CONTENT_DISPOSITION_TEMPLATE, formFieldName));
} else {
// Content-Disposition: form-data; name="参数名"; filename="文件名"[换行]
write(StrUtil.format(CONTENT_DISPOSITION_FILE_TEMPLATE, formFieldName, fileName));
}
// Content-Type
if (resource instanceof HttpResource) {
final String contentType = ((HttpResource) resource).getContentType();
if (StrUtil.isNotBlank(contentType)) {
// Content-Type: 类型[换行]
write(StrUtil.format(CONTENT_TYPE_FILE_TEMPLATE, contentType));
}
} else if (StrUtil.isNotEmpty(fileName)) {
// 根据name的扩展名指定互联网媒体类型默认二进制流数据
write(StrUtil.format(CONTENT_TYPE_FILE_TEMPLATE,
HttpUtil.getMimeType(fileName, ContentType.OCTET_STREAM.getValue())));
}
// 内容
write("\r\n");
resource.writeTo(this);
}
/**
* part:<br>
* <pre>
* --(boundary)[]
* </pre>
*/
private void beginPart() {
// --分隔符(boundary)[换行]
write("--", boundary, StrUtil.CRLF);
}
/**
*
*
* @param objs
*/
private void write(Object... objs) {
IoUtil.write(this, this.charset, false, objs);
}
}

View File

@ -0,0 +1,189 @@
package aiyh.utils.tool.cn.hutool.http;
/**
*
*
* @author Looly
*/
interface Status {
/**
* HTTP Status-Code 200: OK.
*/
int HTTP_OK = 200;
/**
* HTTP Status-Code 201: Created.
*/
int HTTP_CREATED = 201;
/**
* HTTP Status-Code 202: Accepted.
*/
int HTTP_ACCEPTED = 202;
/**
* HTTP Status-Code 203: Non-Authoritative Information.
*/
int HTTP_NOT_AUTHORITATIVE = 203;
/**
* HTTP Status-Code 204: No Content.
*/
int HTTP_NO_CONTENT = 204;
/**
* HTTP Status-Code 205: Reset Content.
*/
int HTTP_RESET = 205;
/**
* HTTP Status-Code 206: Partial Content.
*/
int HTTP_PARTIAL = 206;
/* 3XX: relocation/redirect */
/**
* HTTP Status-Code 300: Multiple Choices.
*/
int HTTP_MULT_CHOICE = 300;
/**
* HTTP Status-Code 301: Moved Permanently.
*/
int HTTP_MOVED_PERM = 301;
/**
* HTTP Status-Code 302: Temporary Redirect.
*/
int HTTP_MOVED_TEMP = 302;
/**
* HTTP Status-Code 303: See Other.
*/
int HTTP_SEE_OTHER = 303;
/**
* HTTP Status-Code 304: Not Modified.
*/
int HTTP_NOT_MODIFIED = 304;
/**
* HTTP Status-Code 305: Use Proxy.
*/
int HTTP_USE_PROXY = 305;
/* 4XX: client error */
/**
* HTTP Status-Code 400: Bad Request.
*/
int HTTP_BAD_REQUEST = 400;
/**
* HTTP Status-Code 401: Unauthorized.
*/
int HTTP_UNAUTHORIZED = 401;
/**
* HTTP Status-Code 402: Payment Required.
*/
int HTTP_PAYMENT_REQUIRED = 402;
/**
* HTTP Status-Code 403: Forbidden.
*/
int HTTP_FORBIDDEN = 403;
/**
* HTTP Status-Code 404: Not Found.
*/
int HTTP_NOT_FOUND = 404;
/**
* HTTP Status-Code 405: Method Not Allowed.
*/
int HTTP_BAD_METHOD = 405;
/**
* HTTP Status-Code 406: Not Acceptable.
*/
int HTTP_NOT_ACCEPTABLE = 406;
/**
* HTTP Status-Code 407: Proxy Authentication Required.
*/
int HTTP_PROXY_AUTH = 407;
/**
* HTTP Status-Code 408: Request Time-Out.
*/
int HTTP_CLIENT_TIMEOUT = 408;
/**
* HTTP Status-Code 409: Conflict.
*/
int HTTP_CONFLICT = 409;
/**
* HTTP Status-Code 410: Gone.
*/
int HTTP_GONE = 410;
/**
* HTTP Status-Code 411: Length Required.
*/
int HTTP_LENGTH_REQUIRED = 411;
/**
* HTTP Status-Code 412: Precondition Failed.
*/
int HTTP_PRECON_FAILED = 412;
/**
* HTTP Status-Code 413: Request Entity Too Large.
*/
int HTTP_ENTITY_TOO_LARGE = 413;
/**
* HTTP Status-Code 414: Request-URI Too Large.
*/
int HTTP_REQ_TOO_LONG = 414;
/**
* HTTP Status-Code 415: Unsupported Media Type.
*/
int HTTP_UNSUPPORTED_TYPE = 415;
/* 5XX: server error */
/**
* HTTP Status-Code 500: Internal Server Error.
*/
int HTTP_INTERNAL_ERROR = 500;
/**
* HTTP Status-Code 501: Not Implemented.
*/
int HTTP_NOT_IMPLEMENTED = 501;
/**
* HTTP Status-Code 502: Bad Gateway.
*/
int HTTP_BAD_GATEWAY = 502;
/**
* HTTP Status-Code 503: Service Unavailable.
*/
int HTTP_UNAVAILABLE = 503;
/**
* HTTP Status-Code 504: Gateway Timeout.
*/
int HTTP_GATEWAY_TIMEOUT = 504;
/**
* HTTP Status-Code 505: HTTP Version Not Supported.
*/
int HTTP_VERSION = 505;
}

View File

@ -0,0 +1,40 @@
package aiyh.utils.tool.cn.hutool.http.body;
import aiyh.utils.tool.cn.hutool.core.io.IoUtil;
import java.io.OutputStream;
/**
* bytesHttp request bodyrest bodyJSONXML
*
* @author looly
* @since 5.7.17
*/
public class BytesBody implements RequestBody {
private final byte[] content;
/**
* Http request body
*
* @param content body
* @return BytesBody
*/
public static BytesBody create(byte[] content) {
return new BytesBody(content);
}
/**
*
*
* @param content Body
*/
public BytesBody(byte[] content) {
this.content = content;
}
@Override
public void write(OutputStream out) {
IoUtil.write(out, false, content);
}
}

View File

@ -0,0 +1,38 @@
package aiyh.utils.tool.cn.hutool.http.body;
import aiyh.utils.tool.cn.hutool.core.net.url.UrlQuery;
import aiyh.utils.tool.cn.hutool.core.util.StrUtil;
import java.nio.charset.Charset;
import java.util.Map;
/**
* application/x-www-form-urlencoded body
*
* @author looly
* @since 5.7.17
*/
public class FormUrlEncodedBody extends BytesBody {
/**
* Http request body
*
* @param form
* @param charset
* @return FormUrlEncodedBody
*/
public static FormUrlEncodedBody create(Map<String, Object> form, Charset charset) {
return new FormUrlEncodedBody(form, charset);
}
/**
*
*
* @param form
* @param charset
*/
public FormUrlEncodedBody(Map<String, Object> form, Charset charset) {
super(StrUtil.bytes(UrlQuery.of(form, true).build(charset), charset));
}
}

View File

@ -0,0 +1,89 @@
package aiyh.utils.tool.cn.hutool.http.body;
import aiyh.utils.tool.cn.hutool.core.io.IoUtil;
import aiyh.utils.tool.cn.hutool.core.map.MapUtil;
import aiyh.utils.tool.cn.hutool.http.ContentType;
import aiyh.utils.tool.cn.hutool.http.HttpGlobalConfig;
import aiyh.utils.tool.cn.hutool.http.MultipartOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.Map;
/**
* Multipart/form-data<br>
* RFC2388
*
* @author looly
* @since 5.3.5
*/
public class MultipartBody implements RequestBody {
private static final String CONTENT_TYPE_MULTIPART_PREFIX = ContentType.MULTIPART.getValue() + "; boundary=";
/**
*
*/
private final Map<String, Object> form;
/**
*
*/
private final Charset charset;
/**
*
*/
private final String boundary = HttpGlobalConfig.getBoundary();
/**
* MultipartBody
*
* @param form
* @param charset
* @return MultipartBody
*/
public static MultipartBody create(Map<String, Object> form, Charset charset) {
return new MultipartBody(form, charset);
}
/**
* MultipartContent-Type
*
* @return MultipartContent-Type
*/
public String getContentType() {
return CONTENT_TYPE_MULTIPART_PREFIX + boundary;
}
/**
*
*
* @param form
* @param charset
*/
public MultipartBody(Map<String, Object> form, Charset charset) {
this.form = form;
this.charset = charset;
}
/**
* Multiparty
*
* @param out out
*/
@Override
public void write(OutputStream out) {
final MultipartOutputStream stream = new MultipartOutputStream(out, this.charset, this.boundary);
if (MapUtil.isNotEmpty(this.form)) {
this.form.forEach(stream::write);
}
stream.finish();
}
@Override
public String toString() {
final ByteArrayOutputStream out = new ByteArrayOutputStream();
write(out);
return IoUtil.toStr(out, this.charset);
}
}

View File

@ -0,0 +1,32 @@
package aiyh.utils.tool.cn.hutool.http.body;
import aiyh.utils.tool.cn.hutool.core.io.IoUtil;
import java.io.OutputStream;
/**
*
*/
public interface RequestBody {
/**
*
*
* @param out out
*/
void write(OutputStream out);
/**
* {@link OutputStream}
*
* @param out {@link OutputStream}
* @since 5.7.17
*/
default void writeClose(OutputStream out) {
try {
write(out);
} finally {
IoUtil.close(out);
}
}
}

View File

@ -0,0 +1,6 @@
/**
*
*
* @author looly
*/
package aiyh.utils.tool.cn.hutool.http.body;

View File

@ -0,0 +1,109 @@
package aiyh.utils.tool.cn.hutool.http.cookie;
import aiyh.utils.tool.cn.hutool.core.io.IORuntimeException;
import aiyh.utils.tool.cn.hutool.core.util.URLUtil;
import aiyh.utils.tool.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;
/**
* CookieHutool
*
* @author Looly
* @since 4.5.15
*/
public class GlobalCookieManager {
/** Cookie管理 */
private static CookieManager cookieManager;
static {
cookieManager = new CookieManager(new ThreadLocalCookieStore(), CookiePolicy.ACCEPT_ALL);
}
/**
* {@link CookieManager}
*
* @param customCookieManager {@link CookieManager}
*/
public static void setCookieManager(CookieManager customCookieManager) {
cookieManager = customCookieManager;
}
/**
* {@link CookieManager}
*
* @return {@link CookieManager}
*/
public static CookieManager getCookieManager() {
return cookieManager;
}
/**
* Cookie
*
* @param conn HTTP
* @return Cookie
* @since 4.6.9
*/
public static List<HttpCookie> getCookies(aiyh.utils.tool.cn.hutool.http.HttpConnection conn) {
return cookieManager.getCookieStore().get(getURI(conn));
}
/**
* CookieHttpCookie
*
* @param conn {@link aiyh.utils.tool.cn.hutool.http.HttpConnection}
*/
public static void add(aiyh.utils.tool.cn.hutool.http.HttpConnection conn) {
if (null == cookieManager) {
// 全局Cookie管理器关闭
return;
}
Map<String, List<String>> cookieHeader;
try {
cookieHeader = cookieManager.get(getURI(conn), new HashMap<>(0));
} catch (IOException e) {
throw new IORuntimeException(e);
}
// 不覆盖模式回填Cookie头这样用户定义的Cookie将优先
conn.header(cookieHeader, false);
}
/**
* Cookie
*
* @param conn {@link aiyh.utils.tool.cn.hutool.http.HttpConnection}
*/
public static void store(aiyh.utils.tool.cn.hutool.http.HttpConnection conn) {
if (null == cookieManager) {
// 全局Cookie管理器关闭
return;
}
try {
cookieManager.put(getURI(conn), conn.headers());
} catch (IOException e) {
throw new IORuntimeException(e);
}
}
/**
* URLURI
*
* @param conn HttpConnection
* @return URI
*/
private static URI getURI(HttpConnection conn) {
return URLUtil.toURI(conn.getUrl());
}
}

View File

@ -0,0 +1,75 @@
package aiyh.utils.tool.cn.hutool.http.cookie;
import java.net.CookieManager;
import java.net.CookieStore;
import java.net.HttpCookie;
import java.net.URI;
import java.util.List;
/**
* 线Cookie线Cookie使Cookie<br>
* <p>
* https://stackoverflow.com/questions/16305486/cookiemanager-for-multiple-threads
*
* @author looly
* @since 4.1.18
*/
public class ThreadLocalCookieStore implements CookieStore {
private final static ThreadLocal<CookieStore> STORES = new ThreadLocal<CookieStore>() {
@Override
protected synchronized CookieStore initialValue() {
/* InMemoryCookieStore */
return (new CookieManager()).getCookieStore();
}
};
/**
* 线CookieStore
*
* @return CookieStore
*/
public CookieStore getCookieStore() {
return STORES.get();
}
/**
* 线Cookie
*
* @return this
*/
public ThreadLocalCookieStore removeCurrent() {
STORES.remove();
return this;
}
@Override
public void add(URI uri, HttpCookie cookie) {
getCookieStore().add(uri, cookie);
}
@Override
public List<HttpCookie> get(URI uri) {
return getCookieStore().get(uri);
}
@Override
public List<HttpCookie> getCookies() {
return getCookieStore().getCookies();
}
@Override
public List<URI> getURIs() {
return getCookieStore().getURIs();
}
@Override
public boolean remove(URI uri, HttpCookie cookie) {
return getCookieStore().remove(uri, cookie);
}
@Override
public boolean removeAll() {
return getCookieStore().removeAll();
}
}

View File

@ -0,0 +1,6 @@
/**
* Cookie
*
* @author looly
*/
package aiyh.utils.tool.cn.hutool.http.cookie;

View File

@ -0,0 +1,6 @@
/**
* Hutool-httpJDKHttpUrlConnectionHTTPSCookie使Http
*
* @author looly
*/
package aiyh.utils.tool.cn.hutool.http;

View File

@ -0,0 +1,57 @@
package aiyh.utils.tool.cn.hutool.http.server;
import aiyh.utils.tool.cn.hutool.core.util.CharsetUtil;
import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.HttpExchange;
import java.io.Closeable;
import java.nio.charset.Charset;
/**
* HttpServerHttpExchange
*
* @author looly
* @since 5.2.6
*/
public class HttpServerBase implements Closeable {
final static Charset DEFAULT_CHARSET = CharsetUtil.CHARSET_UTF_8;
final HttpExchange httpExchange;
/**
*
*
* @param httpExchange {@link HttpExchange}
*/
public HttpServerBase(HttpExchange httpExchange) {
this.httpExchange = httpExchange;
}
/**
* {@link HttpExchange}
*
* @return {@link HttpExchange}
*/
public HttpExchange getHttpExchange() {
return this.httpExchange;
}
/**
* {@link HttpContext}
*
* @return {@link HttpContext}
* @since 5.5.7
*/
public HttpContext getHttpContext() {
return getHttpExchange().getHttpContext();
}
/**
* {@link HttpExchange#close()}
*/
@Override
public void close() {
this.httpExchange.close();
}
}

View File

@ -0,0 +1,442 @@
package aiyh.utils.tool.cn.hutool.http.server;
import aiyh.utils.tool.cn.hutool.core.collection.CollUtil;
import aiyh.utils.tool.cn.hutool.core.io.IORuntimeException;
import aiyh.utils.tool.cn.hutool.core.io.IoUtil;
import aiyh.utils.tool.cn.hutool.core.map.CaseInsensitiveMap;
import aiyh.utils.tool.cn.hutool.core.map.multi.ListValueMap;
import aiyh.utils.tool.cn.hutool.core.net.NetUtil;
import aiyh.utils.tool.cn.hutool.core.net.multipart.MultipartFormData;
import aiyh.utils.tool.cn.hutool.core.net.multipart.UploadSetting;
import aiyh.utils.tool.cn.hutool.core.util.ArrayUtil;
import aiyh.utils.tool.cn.hutool.core.util.CharsetUtil;
import aiyh.utils.tool.cn.hutool.core.util.StrUtil;
import aiyh.utils.tool.cn.hutool.http.Header;
import aiyh.utils.tool.cn.hutool.http.HttpUtil;
import aiyh.utils.tool.cn.hutool.http.Method;
import aiyh.utils.tool.cn.hutool.http.useragent.UserAgent;
import aiyh.utils.tool.cn.hutool.http.useragent.UserAgentUtil;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpCookie;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* Http{@link HttpExchange}
*
* @author looly
* @since 5.2.6
*/
public class HttpServerRequest extends HttpServerBase {
private Map<String, HttpCookie> cookieCache;
private ListValueMap<String, String> paramsCache;
private MultipartFormData multipartFormDataCache;
private Charset charsetCache;
private byte[] bodyCache;
/**
*
*
* @param httpExchange {@link HttpExchange}
*/
public HttpServerRequest(HttpExchange httpExchange) {
super(httpExchange);
}
/**
* Http Method
*
* @return Http Method
*/
public String getMethod() {
return this.httpExchange.getRequestMethod();
}
/**
* GET
*
* @return GET
*/
public boolean isGetMethod() {
return aiyh.utils.tool.cn.hutool.http.Method.GET.name().equalsIgnoreCase(getMethod());
}
/**
* POST
*
* @return POST
*/
public boolean isPostMethod() {
return Method.POST.name().equalsIgnoreCase(getMethod());
}
/**
* URI
*
* @return URI
*/
public URI getURI() {
return this.httpExchange.getRequestURI();
}
/**
* Path
*
* @return
*/
public String getPath() {
return getURI().getPath();
}
/**
*
*
* @return
*/
public String getQuery() {
return getURI().getQuery();
}
/**
* header
*
* @return header
*/
public Headers getHeaders() {
return this.httpExchange.getRequestHeaders();
}
/**
* header
*
* @param headerKey KEY
* @return header
*/
public String getHeader(aiyh.utils.tool.cn.hutool.http.Header headerKey) {
return getHeader(headerKey.toString());
}
/**
* header
*
* @param headerKey KEY
* @return header
*/
public String getHeader(String headerKey) {
return getHeaders().getFirst(headerKey);
}
/**
* header
*
* @param headerKey KEY
* @param charset
* @return header
*/
public String getHeader(String headerKey, Charset charset) {
final String header = getHeader(headerKey);
if (null != header) {
return CharsetUtil.convert(header, CharsetUtil.CHARSET_ISO_8859_1, charset);
}
return null;
}
/**
* Content-Type
*
* @return Content-Type
*/
public String getContentType() {
return getHeader(aiyh.utils.tool.cn.hutool.http.Header.CONTENT_TYPE);
}
/**
* 使UTF-8
*
* <pre>
* 1Content-Typetext/html;charset=utf-8
* </pre>
*
* @return UTF-8
*/
public Charset getCharset() {
if (null == this.charsetCache) {
final String contentType = getContentType();
final String charsetStr = aiyh.utils.tool.cn.hutool.http.HttpUtil.getCharset(contentType);
this.charsetCache = CharsetUtil.parse(charsetStr, DEFAULT_CHARSET);
}
return this.charsetCache;
}
/**
* User-Agent
*
* @return User-Agent
*/
public String getUserAgentStr() {
return getHeader(aiyh.utils.tool.cn.hutool.http.Header.USER_AGENT);
}
/**
* User-Agentnull
*
* @return User-Agentnull
*/
public UserAgent getUserAgent() {
return UserAgentUtil.parse(getUserAgentStr());
}
/**
* Cookie
*
* @return cookie
*/
public String getCookiesStr() {
return getHeader(Header.COOKIE);
}
/**
* Cookie
*
* @return Cookie
*/
public Collection<HttpCookie> getCookies() {
return getCookieMap().values();
}
/**
* CookieMapCookieHttpCookie
*
* @return CookieMap
*/
public Map<String, HttpCookie> getCookieMap() {
if (null == this.cookieCache) {
cookieCache = Collections.unmodifiableMap(CollUtil.toMap(
NetUtil.parseCookies(getCookiesStr()),
new CaseInsensitiveMap<>(),
HttpCookie::getName));
}
return cookieCache;
}
/**
* CookieHttpCookie
*
* @param cookieName Cookie
* @return HttpCookie
*/
public HttpCookie getCookie(String cookieName) {
return getCookieMap().get(cookieName);
}
/**
* Multipart
*
* @return Multipart
*/
public boolean isMultipart() {
if (!isPostMethod()) {
return false;
}
final String contentType = getContentType();
if (StrUtil.isBlank(contentType)) {
return false;
}
return contentType.toLowerCase().startsWith("multipart/");
}
/**
* formjsonxml<br>
* 使{@link #getCharset()}使UTF-8
*
* @return
*/
public String getBody() {
return getBody(getCharset());
}
/**
* formjsonxml
*
* @param charset
* @return
*/
public String getBody(Charset charset) {
return StrUtil.str(getBodyBytes(), charset);
}
/**
* bodybytes
*
* @return bodybytes
*/
public byte[] getBodyBytes() {
if (null == this.bodyCache) {
this.bodyCache = IoUtil.readBytes(getBodyStream(), true);
}
return this.bodyCache;
}
/**
*
*
* @return
*/
public InputStream getBodyStream() {
return this.httpExchange.getRequestBody();
}
/**
*
*
* @param name
* @return
* @since 5.5.8
*/
public String getParam(String name) {
return getParams().get(name, 0);
}
/**
*
*
* @param name
* @return
* @since 5.5.8
*/
public List<String> getParams(String name) {
return getParams().get(name);
}
/**
* Map
*
* @return map
*/
public ListValueMap<String, String> getParams() {
if (null == this.paramsCache) {
this.paramsCache = new ListValueMap<>();
final Charset charset = getCharset();
// 解析URL中的参数
final String query = getQuery();
if (StrUtil.isNotBlank(query)) {
this.paramsCache.putAll(aiyh.utils.tool.cn.hutool.http.HttpUtil.decodeParams(query, charset, false));
}
// 解析multipart中的参数
if (isMultipart()) {
this.paramsCache.putAll(getMultipart().getParamListMap());
} else {
// 解析body中的参数
final String body = getBody();
if (StrUtil.isNotBlank(body)) {
this.paramsCache.putAll(HttpUtil.decodeParams(body, charset, true));
}
}
}
return this.paramsCache;
}
/**
* IP
*
* <p>
* Header:
*
* <pre>
* 1X-Forwarded-For
* 2X-Real-IP
* 3Proxy-Client-IP
* 4WL-Proxy-Client-IP
* </pre>
*
* <p>
* otherHeaderNamesHeader<br>
* 使IPHttpNginxIP
* </p>
*
* @param otherHeaderNames HttpNginx
* @return IP
*/
public String getClientIP(String... otherHeaderNames) {
String[] headers = {"X-Forwarded-For", "X-Real-IP", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR"};
if (ArrayUtil.isNotEmpty(otherHeaderNames)) {
headers = ArrayUtil.addAll(headers, otherHeaderNames);
}
return getClientIPByHeader(headers);
}
/**
* IP
*
* <p>
* headerNamesHeader<br>
* 使IPHttpNginxIP
* </p>
*
* @param headerNames HttpNginx
* @return IP
* @since 4.4.1
*/
public String getClientIPByHeader(String... headerNames) {
String ip;
for (String header : headerNames) {
ip = getHeader(header);
if (!NetUtil.isUnknown(ip)) {
return NetUtil.getMultistageReverseProxyIp(ip);
}
}
ip = this.httpExchange.getRemoteAddress().getHostName();
return NetUtil.getMultistageReverseProxyIp(ip);
}
/**
* MultiPart
*
* @return MultipartFormData
* @throws IORuntimeException IO
* @since 5.3.0
*/
public MultipartFormData getMultipart() throws IORuntimeException {
if (null == this.multipartFormDataCache) {
this.multipartFormDataCache = parseMultipart(new UploadSetting());
}
return this.multipartFormDataCache;
}
/**
* multipart/form-data <br>
* <br>
*
*
* @param uploadSetting
* @return MultiPart
* @throws IORuntimeException IO
* @since 5.3.0
*/
public MultipartFormData parseMultipart(UploadSetting uploadSetting) throws IORuntimeException {
final MultipartFormData formData = new MultipartFormData(uploadSetting);
try {
formData.parseRequestStream(getBodyStream(), getCharset());
} catch (IOException e) {
throw new IORuntimeException(e);
}
return formData;
}
}

View File

@ -0,0 +1,429 @@
package aiyh.utils.tool.cn.hutool.http.server;
import aiyh.utils.tool.cn.hutool.core.io.FileUtil;
import aiyh.utils.tool.cn.hutool.core.io.IORuntimeException;
import aiyh.utils.tool.cn.hutool.core.io.IoUtil;
import aiyh.utils.tool.cn.hutool.core.util.ObjectUtil;
import aiyh.utils.tool.cn.hutool.core.util.StrUtil;
import aiyh.utils.tool.cn.hutool.core.util.URLUtil;
import aiyh.utils.tool.cn.hutool.http.ContentType;
import aiyh.utils.tool.cn.hutool.http.Header;
import aiyh.utils.tool.cn.hutool.http.HttpStatus;
import aiyh.utils.tool.cn.hutool.http.HttpUtil;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import java.io.*;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
/**
* Http
*/
public class HttpServerResponse extends HttpServerBase {
private Charset charset;
/**
* Http
*/
private boolean isSendCode;
/**
*
*
* @param httpExchange {@link HttpExchange}
*/
public HttpServerResponse(HttpExchange httpExchange) {
super(httpExchange);
}
/**
* HTTPContent-Length0Transfer-encoding: chunked
*
* @param httpStatusCode HTTPHttpStatus
* @return this
*/
public HttpServerResponse send(int httpStatusCode) {
return send(httpStatusCode, 0);
}
/**
*
*
* @return this
*/
public HttpServerResponse sendOk() {
return send(aiyh.utils.tool.cn.hutool.http.HttpStatus.HTTP_OK);
}
/**
*
*
* @param bodyLength 0Transfer-encoding: chunked
* @return this
* @since 5.5.7
*/
public HttpServerResponse sendOk(int bodyLength) {
return send(aiyh.utils.tool.cn.hutool.http.HttpStatus.HTTP_OK, bodyLength);
}
/**
* 404
*
* @param content text/html
* @return this
*/
public HttpServerResponse send404(String content) {
return sendError(HttpStatus.HTTP_NOT_FOUND, content);
}
/**
*
*
* @param errorCode HTTPHttpStatus
* @param content text/html
* @return this
*/
public HttpServerResponse sendError(int errorCode, String content) {
send(errorCode);
setContentType(aiyh.utils.tool.cn.hutool.http.ContentType.TEXT_HTML.toString());
return write(content);
}
/**
* HTTP
*
* @param httpStatusCode HTTPHttpStatus
* @param bodyLength 0Transfer-encoding: chunked
* @return this
*/
public HttpServerResponse send(int httpStatusCode, long bodyLength) {
if (this.isSendCode) {
throw new IORuntimeException("Http status code has been send!");
}
try {
this.httpExchange.sendResponseHeaders(httpStatusCode, bodyLength);
} catch (IOException e) {
throw new IORuntimeException(e);
}
this.isSendCode = true;
return this;
}
/**
*
*
* @return
*/
public Headers getHeaders() {
return this.httpExchange.getResponseHeaders();
}
/**
*
*
* @param header key
* @param value
* @return this
*/
public HttpServerResponse addHeader(String header, String value) {
getHeaders().add(header, value);
return this;
}
/**
*
*
* @param header key
* @param value
* @return this
*/
public HttpServerResponse setHeader(aiyh.utils.tool.cn.hutool.http.Header header, String value) {
return setHeader(header.getValue(), value);
}
/**
*
*
* @param header key
* @param value
* @return this
*/
public HttpServerResponse setHeader(String header, String value) {
getHeaders().set(header, value);
return this;
}
/**
*
*
* @param header key
* @param value
* @return this
*/
public HttpServerResponse setHeader(String header, List<String> value) {
getHeaders().put(header, value);
return this;
}
/**
*
*
* @param headers map
* @return this
*/
public HttpServerResponse setHeaders(Map<String, List<String>> headers) {
getHeaders().putAll(headers);
return this;
}
/**
* Content-Type:text/html;charset=utf-8<br>
* charsetcharsetcharset{@link #setCharset(Charset)}
*
* @param contentType Content-Type
* @return this
*/
public HttpServerResponse setContentType(String contentType) {
if (null != contentType && null != this.charset) {
if (!contentType.contains(";charset=")) {
contentType = ContentType.build(contentType, this.charset);
}
}
return setHeader(aiyh.utils.tool.cn.hutool.http.Header.CONTENT_TYPE, contentType);
}
/**
* Content-Length
*
* @param contentLength Content-Length
* @return this
*/
public HttpServerResponse setContentLength(long contentLength) {
return setHeader(aiyh.utils.tool.cn.hutool.http.Header.CONTENT_LENGTH, String.valueOf(contentLength));
}
/**
*
*
* @param charset
* @return this
*/
public HttpServerResponse setCharset(Charset charset) {
this.charset = charset;
return this;
}
/**
*
*
* @param name
* @param value
* @return this
*/
public HttpServerResponse setAttr(String name, Object value) {
this.httpExchange.setAttribute(name, value);
return this;
}
/**
*
*
* @return
*/
public OutputStream getOut() {
if (!this.isSendCode) {
sendOk();
}
return this.httpExchange.getResponseBody();
}
/**
*
*
* @return
*/
public PrintWriter getWriter() {
final Charset charset = ObjectUtil.defaultIfNull(this.charset, DEFAULT_CHARSET);
return new PrintWriter(new OutputStreamWriter(getOut(), charset));
}
/**
*
*
* @param data
* @param contentType Content-Type
* @return this
*/
public HttpServerResponse write(String data, String contentType) {
setContentType(contentType);
return write(data);
}
/**
*
*
* @param data
* @return this
*/
public HttpServerResponse write(String data) {
final Charset charset = ObjectUtil.defaultIfNull(this.charset, DEFAULT_CHARSET);
return write(StrUtil.bytes(data, charset));
}
/**
*
*
* @param data
* @param contentType
* @return this
*/
public HttpServerResponse write(byte[] data, String contentType) {
setContentType(contentType);
return write(data);
}
/**
*
*
* @param data
* @return this
*/
public HttpServerResponse write(byte[] data) {
final ByteArrayInputStream in = new ByteArrayInputStream(data);
return write(in, in.available());
}
/**
*
*
* @param in
* @param contentType
* @return this
* @since 5.2.6
*/
public HttpServerResponse write(InputStream in, String contentType) {
return write(in, 0, contentType);
}
/**
*
*
* @param in
* @param length 0Transfer-encoding: chunked
* @param contentType
* @return this
* @since 5.2.7
*/
public HttpServerResponse write(InputStream in, int length, String contentType) {
setContentType(contentType);
return write(in, length);
}
/**
*
*
* @param in
* @return this
*/
public HttpServerResponse write(InputStream in) {
return write(in, 0);
}
/**
*
*
* @param in
* @param length 0Transfer-encoding: chunked
* @return this
*/
public HttpServerResponse write(InputStream in, int length) {
if (!isSendCode) {
sendOk(Math.max(0, length));
}
OutputStream out = null;
try {
out = this.httpExchange.getResponseBody();
IoUtil.copy(in, out);
} finally {
IoUtil.close(out);
IoUtil.close(in);
}
return this;
}
/**
*
*
* @param file
* @return this
* @since 5.2.6
*/
public HttpServerResponse write(File file) {
return write(file, null);
}
/**
*
*
* @param file
* @param fileName
* @return this
* @since 5.5.8
*/
public HttpServerResponse write(File file, String fileName) {
final long fileSize = file.length();
if (fileSize > Integer.MAX_VALUE) {
throw new IllegalArgumentException("File size is too bigger than " + Integer.MAX_VALUE);
}
if (StrUtil.isBlank(fileName)) {
fileName = file.getName();
}
final String contentType = ObjectUtil.defaultIfNull(HttpUtil.getMimeType(fileName), "application/octet-stream");
BufferedInputStream in = null;
try {
in = FileUtil.getInputStream(file);
write(in, (int) fileSize, contentType, fileName);
} finally {
IoUtil.close(in);
}
return this;
}
/**
*
*
* @param in
* @param contentType
* @param fileName
* @since 5.2.6
*/
public void write(InputStream in, String contentType, String fileName) {
write(in, 0, contentType, fileName);
}
/**
*
*
* @param in
* @param length
* @param contentType
* @param fileName
* @return this
* @since 5.2.7
*/
public HttpServerResponse write(InputStream in, int length, String contentType, String fileName) {
final Charset charset = ObjectUtil.defaultIfNull(this.charset, DEFAULT_CHARSET);
if (!contentType.startsWith("text/")) {
// 非文本类型数据直接走下载
setHeader(Header.CONTENT_DISPOSITION, StrUtil.format("attachment;filename={}", URLUtil.encode(fileName, charset)));
}
return write(in, length, contentType);
}
}

View File

@ -0,0 +1,226 @@
package aiyh.utils.tool.cn.hutool.http.server;
import aiyh.utils.tool.cn.hutool.core.io.IORuntimeException;
import aiyh.utils.tool.cn.hutool.core.lang.Console;
import aiyh.utils.tool.cn.hutool.core.thread.GlobalThreadPool;
import aiyh.utils.tool.cn.hutool.core.util.StrUtil;
import aiyh.utils.tool.cn.hutool.http.server.action.Action;
import aiyh.utils.tool.cn.hutool.http.server.action.RootAction;
import aiyh.utils.tool.cn.hutool.http.server.filter.HttpFilter;
import aiyh.utils.tool.cn.hutool.http.server.filter.SimpleFilter;
import aiyh.utils.tool.cn.hutool.http.server.handler.ActionHandler;
import com.sun.net.httpserver.*;
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
/**
* Http{@link HttpServer}
*
* @author looly
* @since 5.2.5
*/
public class SimpleServer {
private final HttpServer server;
private final List<Filter> filters;
/**
*
*
* @param port
*/
public SimpleServer(int port) {
this(new InetSocketAddress(port));
}
/**
*
*
* @param hostname
* @param port
*/
public SimpleServer(String hostname, int port) {
this(new InetSocketAddress(hostname, port));
}
/**
*
*
* @param address
*/
public SimpleServer(InetSocketAddress address) {
this(address, null);
}
/**
*
*
* @param address
* @param configurator https使SSLTLS
*/
public SimpleServer(InetSocketAddress address, HttpsConfigurator configurator) {
try {
if (null != configurator) {
final HttpsServer server = HttpsServer.create(address, 0);
server.setHttpsConfigurator(configurator);
this.server = server;
} else {
this.server = HttpServer.create(address, 0);
}
} catch (IOException e) {
throw new IORuntimeException(e);
}
setExecutor(GlobalThreadPool.getExecutor());
filters = new ArrayList<>();
}
/**
* <br>
*
*
* <ul>
* <li>{@link #setRoot(File)} </li>
* <li>{@link #setRoot(String)} </li>
* <li>{@link #createContext(String, HttpHandler)} </li>
* <li>{@link #addHandler(String, HttpHandler)}</li>
* <li>{@link #addAction(String, Action)} </li>
* </ul>
*
* @param filter {@link Filter}
* @return this
* @since 5.5.7
*/
public SimpleServer addFilter(Filter filter) {
this.filters.add(filter);
return this;
}
/**
* <br>
*
*
* <ul>
* <li>{@link #setRoot(File)} </li>
* <li>{@link #setRoot(String)} </li>
* <li>{@link #createContext(String, HttpHandler)} </li>
* <li>{@link #addHandler(String, HttpHandler)}</li>
* <li>{@link #addAction(String, Action)} </li>
* </ul>
*
* @param filter {@link Filter}
* @return this
* @since 5.5.7
*/
public SimpleServer addFilter(HttpFilter filter) {
return addFilter(new SimpleFilter() {
@Override
public void doFilter(HttpExchange httpExchange, Chain chain) throws IOException {
filter.doFilter(new HttpServerRequest(httpExchange), new HttpServerResponse(httpExchange), chain);
}
});
}
/**
*
*
* @param path :/a/b a/b
* @param handler
* @return this
* @see #createContext(String, HttpHandler)
*/
public SimpleServer addHandler(String path, HttpHandler handler) {
createContext(path, handler);
return this;
}
/**
* 访使{@link HttpHandler}
*
* @param path :/a/b a/b
* @param handler
* @return {@link HttpContext}
* @since 5.5.7
*/
public HttpContext createContext(String path, HttpHandler handler) {
// 非/开头的路径会报错
path = StrUtil.addPrefixIfNot(path, StrUtil.SLASH);
final HttpContext context = this.server.createContext(path, handler);
// 增加整体过滤器
context.getFilters().addAll(this.filters);
return context;
}
/**
* root
*
* @param root
* @return this
*/
public SimpleServer setRoot(String root) {
return setRoot(new File(root));
}
/**
* root
*
* @param root
* @return this
*/
public SimpleServer setRoot(File root) {
return addAction("/", new RootAction(root));
}
/**
*
*
* @param path
* @param action
* @return this
*/
public SimpleServer addAction(String path, Action action) {
return addHandler(path, new ActionHandler(action));
}
/**
* 线
*
* @param executor {@link Executor}
* @return this
*/
public SimpleServer setExecutor(Executor executor) {
this.server.setExecutor(executor);
return this;
}
/**
* HttpServer
*
* @return {@link HttpServer}
*/
public HttpServer getRawServer() {
return this.server;
}
/**
*
*
* @return {@link InetSocketAddress}
*/
public InetSocketAddress getAddress() {
return this.server.getAddress();
}
/**
* Http线
*/
public void start() {
final InetSocketAddress address = getAddress();
Console.log("Hutool Simple Http Server listen on 【{}:{}】", address.getHostName(), address.getPort());
this.server.start();
}
}

View File

@ -0,0 +1,26 @@
package aiyh.utils.tool.cn.hutool.http.server.action;
import aiyh.utils.tool.cn.hutool.http.server.HttpServerRequest;
import aiyh.utils.tool.cn.hutool.http.server.HttpServerResponse;
import java.io.IOException;
/**
* <br>
* PathActiondoAction
*
* @author Looly
* @since 5.2.6
*/
@FunctionalInterface
public interface Action {
/**
*
*
* @param request
* @param response
* @throws IOException IO
*/
void doAction(HttpServerRequest request, HttpServerResponse response) throws IOException;
}

View File

@ -0,0 +1,86 @@
package aiyh.utils.tool.cn.hutool.http.server.action;
import aiyh.utils.tool.cn.hutool.core.collection.CollUtil;
import aiyh.utils.tool.cn.hutool.core.io.FileUtil;
import aiyh.utils.tool.cn.hutool.http.server.HttpServerRequest;
import aiyh.utils.tool.cn.hutool.http.server.HttpServerResponse;
import java.io.File;
import java.util.List;
/**
* path
*
* @author looly
* @since 5.2.6
*/
public class RootAction implements Action {
public static final String DEFAULT_INDEX_FILE_NAME = "index.html";
private final File rootDir;
private final List<String> indexFileNames;
/**
*
*
* @param rootDir
*/
public RootAction(String rootDir) {
this(new File(rootDir));
}
/**
*
*
* @param rootDir
*/
public RootAction(File rootDir) {
this(rootDir, DEFAULT_INDEX_FILE_NAME);
}
/**
*
*
* @param rootDir
* @param indexFileNames
*/
public RootAction(String rootDir, String... indexFileNames) {
this(new File(rootDir), indexFileNames);
}
/**
*
*
* @param rootDir
* @param indexFileNames
* @since 5.4.0
*/
public RootAction(File rootDir, String... indexFileNames) {
this.rootDir = rootDir;
this.indexFileNames = CollUtil.toList(indexFileNames);
}
@Override
public void doAction(HttpServerRequest request, HttpServerResponse response) {
final String path = request.getPath();
File file = FileUtil.file(rootDir, path);
if (file.exists()) {
if (file.isDirectory()) {
for (String indexFileName : indexFileNames) {
// 默认读取主页
file = FileUtil.file(file, indexFileName);
if (file.exists() && file.isFile()) {
response.write(file);
}
}
} else {
final String name = request.getParam("name");
response.write(file, name);
}
}
response.send404("404 Not Found !");
}
}

View File

@ -0,0 +1,6 @@
/**
* {@link com.sun.net.httpserver.HttpServer}
*
* @author looly
*/
package aiyh.utils.tool.cn.hutool.http.server.action;

View File

@ -0,0 +1,27 @@
package aiyh.utils.tool.cn.hutool.http.server.filter;
import aiyh.utils.tool.cn.hutool.http.server.HttpServerRequest;
import aiyh.utils.tool.cn.hutool.http.server.HttpServerResponse;
import com.sun.net.httpserver.Filter;
import java.io.IOException;
/**
* {@link Filter} 使
*
* @author looly
* @since 5.5.7
*/
@FunctionalInterface
public interface HttpFilter {
/**
*
*
* @param req {@link aiyh.utils.tool.cn.hutool.http.server.HttpServerRequest}
* @param res {@link aiyh.utils.tool.cn.hutool.http.server.HttpServerResponse}
* @param chain {@link Filter.Chain}
* @throws IOException IO
*/
void doFilter(HttpServerRequest req, HttpServerResponse res, Filter.Chain chain) throws IOException;
}

View File

@ -0,0 +1,17 @@
package aiyh.utils.tool.cn.hutool.http.server.filter;
import com.sun.net.httpserver.Filter;
/**
*
*
* @author looly
* @since 5.5.7
*/
public abstract class SimpleFilter extends Filter {
@Override
public String description() {
return "Anonymous Filter";
}
}

View File

@ -0,0 +1,4 @@
/**
* {@link com.sun.net.httpserver.Filter}
*/
package aiyh.utils.tool.cn.hutool.http.server.filter;

View File

@ -0,0 +1,38 @@
package aiyh.utils.tool.cn.hutool.http.server.handler;
import aiyh.utils.tool.cn.hutool.http.server.HttpServerRequest;
import aiyh.utils.tool.cn.hutool.http.server.HttpServerResponse;
import aiyh.utils.tool.cn.hutool.http.server.action.Action;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import java.io.IOException;
/**
* ActionHttpHandlerAction
*
* @author looly
* @since 5.2.6
*/
public class ActionHandler implements HttpHandler {
private final Action action;
/**
*
*
* @param action Action
*/
public ActionHandler(Action action) {
this.action = action;
}
@Override
public void handle(HttpExchange httpExchange) throws IOException {
action.doAction(
new HttpServerRequest(httpExchange),
new HttpServerResponse(httpExchange)
);
httpExchange.close();
}
}

View File

@ -0,0 +1,4 @@
/**
* {@link com.sun.net.httpserver.HttpHandler}
*/
package aiyh.utils.tool.cn.hutool.http.server.handler;

View File

@ -0,0 +1,6 @@
/**
* Http
*
* @author looly
*/
package aiyh.utils.tool.cn.hutool.http.server;

View File

@ -0,0 +1,25 @@
package aiyh.utils.tool.cn.hutool.http.ssl;
import aiyh.utils.tool.cn.hutool.core.io.IORuntimeException;
import aiyh.utils.tool.cn.hutool.core.net.SSLProtocols;
/**
* androidSSL<br>
* HttpUrlConnection[GithubPage]
*
* <p>
* SSL
*
* @author MikaGuraNTK
*/
public class AndroidSupportSSLFactory extends CustomProtocolsSSLFactory {
// Android低版本不重置的话某些SSL访问就会失败
private static final String[] protocols = {
SSLProtocols.SSLv3, SSLProtocols.TLSv1, SSLProtocols.TLSv11, SSLProtocols.TLSv12};
public AndroidSupportSSLFactory() throws IORuntimeException {
super(protocols);
}
}

View File

@ -0,0 +1,97 @@
package aiyh.utils.tool.cn.hutool.http.ssl;
import aiyh.utils.tool.cn.hutool.core.io.IORuntimeException;
import aiyh.utils.tool.cn.hutool.core.net.SSLUtil;
import aiyh.utils.tool.cn.hutool.core.util.ArrayUtil;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
/**
* SSLSocketFactory
*
* @author looly
*/
public class CustomProtocolsSSLFactory extends SSLSocketFactory {
private final String[] protocols;
private final SSLSocketFactory base;
/**
*
*
* @param protocols
* @throws IORuntimeException IO
*/
public CustomProtocolsSSLFactory(String... protocols) throws IORuntimeException {
this.protocols = protocols;
this.base = SSLUtil.createSSLContext(null).getSocketFactory();
}
@Override
public String[] getDefaultCipherSuites() {
return base.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return base.getSupportedCipherSuites();
}
@Override
public Socket createSocket() throws IOException {
final SSLSocket sslSocket = (SSLSocket) base.createSocket();
resetProtocols(sslSocket);
return sslSocket;
}
@Override
public SSLSocket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
final SSLSocket socket = (SSLSocket) base.createSocket(s, host, port, autoClose);
resetProtocols(socket);
return socket;
}
@Override
public Socket createSocket(String host, int port) throws IOException {
final SSLSocket socket = (SSLSocket) base.createSocket(host, port);
resetProtocols(socket);
return socket;
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
final SSLSocket socket = (SSLSocket) base.createSocket(host, port, localHost, localPort);
resetProtocols(socket);
return socket;
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
final SSLSocket socket = (SSLSocket) base.createSocket(host, port);
resetProtocols(socket);
return socket;
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
final SSLSocket socket = (SSLSocket) base.createSocket(address, port, localAddress, localPort);
resetProtocols(socket);
return socket;
}
/**
*
*
* @param socket SSLSocket
*/
private void resetProtocols(SSLSocket socket) {
if (ArrayUtil.isNotEmpty(this.protocols)) {
socket.setEnabledProtocols(this.protocols);
}
}
}

View File

@ -0,0 +1,14 @@
package aiyh.utils.tool.cn.hutool.http.ssl;
/**
* SSLSocketFactory
*
* @author Looly
* @since 5.1.2
*/
public class DefaultSSLFactory extends CustomProtocolsSSLFactory {
public DefaultSSLFactory() {
}
}

View File

@ -0,0 +1,32 @@
package aiyh.utils.tool.cn.hutool.http.ssl;
import aiyh.utils.tool.cn.hutool.core.util.StrUtil;
import javax.net.ssl.SSLSocketFactory;
/**
* SSL使
*
* @author looly
* @since 5.1.2
*/
public class DefaultSSLInfo {
/**
*
*/
public static final aiyh.utils.tool.cn.hutool.http.ssl.TrustAnyHostnameVerifier TRUST_ANY_HOSTNAME_VERIFIER;
/**
* SSLSocketFactory
*/
public static final SSLSocketFactory DEFAULT_SSF;
static {
TRUST_ANY_HOSTNAME_VERIFIER = new TrustAnyHostnameVerifier();
if (StrUtil.equalsIgnoreCase("dalvik", System.getProperty("java.vm.name"))) {
// 兼容android低版本SSL连接
DEFAULT_SSF = new AndroidSupportSSLFactory();
} else {
DEFAULT_SSF = new DefaultSSLFactory();
}
}
}

View File

@ -0,0 +1,95 @@
package aiyh.utils.tool.cn.hutool.http.ssl;
import aiyh.utils.tool.cn.hutool.core.net.SSLContextBuilder;
import aiyh.utils.tool.cn.hutool.core.net.SSLProtocols;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
/**
* SSLSocketFactory
*
* @author Looly
* @see SSLContextBuilder
* @deprecated 使 {@link SSLContextBuilder}
*/
@Deprecated
public class SSLSocketFactoryBuilder implements SSLProtocols {
SSLContextBuilder sslContextBuilder;
/**
*
*/
public SSLSocketFactoryBuilder() {
this.sslContextBuilder = SSLContextBuilder.create();
}
/**
* SSLSocketFactoryBuilder
*
* @return SSLSocketFactoryBuilder
*/
public static SSLSocketFactoryBuilder create() {
return new SSLSocketFactoryBuilder();
}
/**
*
*
* @param protocol
* @return
*/
public SSLSocketFactoryBuilder setProtocol(String protocol) {
this.sslContextBuilder.setProtocol(protocol);
return this;
}
/**
*
*
* @param trustManagers TrustManager
* @return
*/
public SSLSocketFactoryBuilder setTrustManagers(TrustManager... trustManagers) {
this.sslContextBuilder.setTrustManagers(trustManagers);
return this;
}
/**
* JSSE key managers
*
* @param keyManagers JSSE key managers
* @return
*/
public SSLSocketFactoryBuilder setKeyManagers(KeyManager... keyManagers) {
this.sslContextBuilder.setKeyManagers(keyManagers);
return this;
}
/**
* SecureRandom
*
* @param secureRandom SecureRandom
* @return
*/
public SSLSocketFactoryBuilder setSecureRandom(SecureRandom secureRandom) {
this.sslContextBuilder.setSecureRandom(secureRandom);
return this;
}
/**
* SSLSocketFactory
*
* @return SSLSocketFactory
* @throws NoSuchAlgorithmException
* @throws KeyManagementException Key
*/
public SSLSocketFactory build() throws NoSuchAlgorithmException, KeyManagementException {
return this.sslContextBuilder.buildChecked().getSocketFactory();
}
}

View File

@ -0,0 +1,17 @@
package aiyh.utils.tool.cn.hutool.http.ssl;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
/**
* https
*
* @author Looly
*/
public class TrustAnyHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;// 直接返回true
}
}

View File

@ -0,0 +1,6 @@
/**
* SSL
*
* @author looly
*/
package aiyh.utils.tool.cn.hutool.http.ssl;

View File

@ -0,0 +1,140 @@
package aiyh.utils.tool.cn.hutool.http.useragent;
import aiyh.utils.tool.cn.hutool.core.collection.CollUtil;
import aiyh.utils.tool.cn.hutool.core.util.ReUtil;
import java.util.List;
import java.util.regex.Pattern;
/**
*
*
* @author looly
* @since 4.2.1
*/
public class Browser extends UserAgentInfo {
private static final long serialVersionUID = 1L;
/**
*
*/
public static final Browser Unknown = new Browser(NameUnknown, null, null);
/**
*
*/
public static final String Other_Version = "[\\/ ]([\\d\\w\\.\\-]+)";
/**
*
*/
public static final List<Browser> browers = CollUtil.newArrayList(
// 部分特殊浏览器是基于安卓、Iphone等的需要优先判断
// 企业微信 企业微信使用微信浏览器内核,会包含 MicroMessenger 所以要放在前面
new Browser("wxwork", "wxwork", "wxwork\\/([\\d\\w\\.\\-]+)"),
// 微信
new Browser("MicroMessenger", "MicroMessenger", Other_Version),
// 微信小程序
new Browser("miniProgram", "miniProgram", Other_Version),
// QQ浏览器
new Browser("QQBrowser", "MQQBrowser", "MQQBrowser\\/([\\d\\w\\.\\-]+)"),
// 钉钉PC端浏览器
new Browser("DingTalk-win", "dingtalk-win", "DingTalk\\(([\\d\\w\\.\\-]+)\\)"),
// 钉钉内置浏览器
new Browser("DingTalk", "DingTalk", "AliApp\\(DingTalk\\/([\\d\\w\\.\\-]+)\\)"),
// 支付宝内置浏览器
new Browser("Alipay", "AlipayClient", "AliApp\\(AP\\/([\\d\\w\\.\\-]+)\\)"),
// 淘宝内置浏览器
new Browser("Taobao", "taobao", "AliApp\\(TB\\/([\\d\\w\\.\\-]+)\\)"),
// UC浏览器
new Browser("UCBrowser", "UC?Browser", "UC?Browser\\/([\\d\\w\\.\\-]+)"),
// XiaoMi 浏览器
new Browser("MiuiBrowser", "MiuiBrowser|mibrowser", "MiuiBrowser\\/([\\d\\w\\.\\-]+)"),
// 夸克浏览器
new Browser("Quark", "Quark", Other_Version),
// 联想浏览器
new Browser("Lenovo", "SLBrowser", "SLBrowser/([\\d\\w\\.\\-]+)"),
new Browser("MSEdge", "Edge|Edg", "(?:edge|Edg|EdgA)\\/([\\d\\w\\.\\-]+)"),
new Browser("Chrome", "chrome", Other_Version),
new Browser("Firefox", "firefox", Other_Version),
new Browser("IEMobile", "iemobile", Other_Version),
new Browser("Android Browser", "android", "version\\/([\\d\\w\\.\\-]+)"),
new Browser("Safari", "safari", "version\\/([\\d\\w\\.\\-]+)"),
new Browser("Opera", "opera", Other_Version),
new Browser("Konqueror", "konqueror", Other_Version),
new Browser("PS3", "playstation 3", "([\\d\\w\\.\\-]+)\\)\\s*$"),
new Browser("PSP", "playstation portable", "([\\d\\w\\.\\-]+)\\)?\\s*$"),
new Browser("Lotus", "lotus.notes", "Lotus-Notes\\/([\\w.]+)"),
new Browser("Thunderbird", "thunderbird", Other_Version),
new Browser("Netscape", "netscape", Other_Version),
new Browser("Seamonkey", "seamonkey", Other_Version),
new Browser("Outlook", "microsoft.outlook", Other_Version),
new Browser("Evolution", "evolution", Other_Version),
new Browser("MSIE", "msie", "msie ([\\d\\w\\.\\-]+)"),
new Browser("MSIE11", "rv:11", "rv:([\\d\\w\\.\\-]+)"),
new Browser("Gabble", "Gabble", Other_Version),
new Browser("Yammer Desktop", "AdobeAir", "([\\d\\w\\.\\-]+)\\/Yammer"),
new Browser("Yammer Mobile", "Yammer[\\s]+([\\d\\w\\.\\-]+)", "Yammer[\\s]+([\\d\\w\\.\\-]+)"),
new Browser("Apache HTTP Client", "Apache\\\\-HttpClient", "Apache\\-HttpClient\\/([\\d\\w\\.\\-]+)"),
new Browser("BlackBerry", "BlackBerry", "BlackBerry[\\d]+\\/([\\d\\w\\.\\-]+)")
);
/**
*
*
* @param name
* @param regex
* @param versionRegex
* @since 5.7.4
*/
synchronized public static void addCustomBrowser(String name, String regex, String versionRegex) {
browers.add(new Browser(name, regex, versionRegex));
}
private Pattern versionPattern;
/**
*
*
* @param name
* @param regex
* @param versionRegex
*/
public Browser(String name, String regex, String versionRegex) {
super(name, regex);
if (Other_Version.equals(versionRegex)) {
versionRegex = name + versionRegex;
}
if (null != versionRegex) {
this.versionPattern = Pattern.compile(versionRegex, Pattern.CASE_INSENSITIVE);
}
}
/**
*
*
* @param userAgentString User-Agent
* @return
*/
public String getVersion(String userAgentString) {
if (isUnknown()) {
return null;
}
return ReUtil.getGroup1(this.versionPattern, userAgentString);
}
/**
*
*
* @return
*/
public boolean isMobile() {
final String name = this.getName();
return "PSP".equals(name) ||
"Yammer Mobile".equals(name) ||
"Android Browser".equals(name) ||
"IEMobile".equals(name) ||
"MicroMessenger".equals(name) ||
"miniProgram".equals(name) ||
"DingTalk".equals(name);
}
}

View File

@ -0,0 +1,62 @@
package aiyh.utils.tool.cn.hutool.http.useragent;
import aiyh.utils.tool.cn.hutool.core.collection.CollUtil;
import aiyh.utils.tool.cn.hutool.core.util.ReUtil;
import java.util.List;
import java.util.regex.Pattern;
/**
*
*
* @author looly
* @since 4.2.1
*/
public class Engine extends UserAgentInfo {
private static final long serialVersionUID = 1L;
/** 未知 */
public static final Engine Unknown = new Engine(NameUnknown, null);
/**
*
*/
public static final List<Engine> engines = CollUtil.newArrayList(
new Engine("Trident", "trident"),
new Engine("Webkit", "webkit"),
new Engine("Chrome", "chrome"),
new Engine("Opera", "opera"),
new Engine("Presto", "presto"),
new Engine("Gecko", "gecko"),
new Engine("KHTML", "khtml"),
new Engine("Konqueror", "konqueror"),
new Engine("MIDP", "MIDP")
);
private final Pattern versionPattern;
/**
*
*
* @param name
* @param regex
*/
public Engine(String name, String regex) {
super(name, regex);
this.versionPattern = Pattern.compile(name + "[/\\- ]([\\d\\w.\\-]+)", Pattern.CASE_INSENSITIVE);
}
/**
*
*
* @param userAgentString User-Agent
* @return
* @since 5.7.4
*/
public String getVersion(String userAgentString) {
if (isUnknown()) {
return null;
}
return ReUtil.getGroup1(this.versionPattern, userAgentString);
}
}

View File

@ -0,0 +1,107 @@
package aiyh.utils.tool.cn.hutool.http.useragent;
import aiyh.utils.tool.cn.hutool.core.collection.CollUtil;
import aiyh.utils.tool.cn.hutool.core.util.ReUtil;
import java.util.List;
import java.util.regex.Pattern;
/**
*
*
* @author looly
* @since 4.2.1
*/
public class OS extends UserAgentInfo {
private static final long serialVersionUID = 1L;
/**
*
*/
public static final OS Unknown = new OS(NameUnknown, null);
/**
*
*/
public static final List<OS> oses = CollUtil.newArrayList(//
new OS("Windows 10 or Windows Server 2016", "windows nt 10\\.0", "windows nt (10\\.0)"),//
new OS("Windows 8.1 or Windows Server 2012R2", "windows nt 6\\.3", "windows nt (6\\.3)"),//
new OS("Windows 8 or Windows Server 2012", "windows nt 6\\.2", "windows nt (6\\.2)"),//
new OS("Windows Vista", "windows nt 6\\.0", "windows nt (6\\.0)"), //
new OS("Windows 7 or Windows Server 2008R2", "windows nt 6\\.1", "windows nt (6\\.1)"), //
new OS("Windows 2003", "windows nt 5\\.2", "windows nt (5\\.2)"), //
new OS("Windows XP", "windows nt 5\\.1", "windows nt (5\\.1)"), //
new OS("Windows 2000", "windows nt 5\\.0", "windows nt (5\\.0)"), //
new OS("Windows Phone", "windows (ce|phone|mobile)( os)?", "windows (?:ce|phone|mobile) (\\d+([._]\\d+)*)"), //
new OS("Windows", "windows"), //
new OS("OSX", "os x (\\d+)[._](\\d+)", "os x (\\d+([._]\\d+)*)"), //
new OS("Android", "Android", "Android (\\d+([._]\\d+)*)"),//
new OS("Android", "XiaoMi|MI\\s+", "\\(X(\\d+([._]\\d+)*)"),//
new OS("Linux", "linux"), //
new OS("Wii", "wii", "wii libnup/(\\d+([._]\\d+)*)"), //
new OS("PS3", "playstation 3", "playstation 3; (\\d+([._]\\d+)*)"), //
new OS("PSP", "playstation portable", "Portable\\); (\\d+([._]\\d+)*)"), //
new OS("iPad", "\\(iPad.*os (\\d+)[._](\\d+)", "\\(iPad.*os (\\d+([._]\\d+)*)"), //
new OS("iPhone", "\\(iPhone.*os (\\d+)[._](\\d+)", "\\(iPhone.*os (\\d+([._]\\d+)*)"), //
new OS("YPod", "iPod touch[\\s\\;]+iPhone.*os (\\d+)[._](\\d+)", "iPod touch[\\s\\;]+iPhone.*os (\\d+([._]\\d+)*)"), //
new OS("YPad", "iPad[\\s\\;]+iPhone.*os (\\d+)[._](\\d+)", "iPad[\\s\\;]+iPhone.*os (\\d+([._]\\d+)*)"), //
new OS("YPhone", "iPhone[\\s\\;]+iPhone.*os (\\d+)[._](\\d+)", "iPhone[\\s\\;]+iPhone.*os (\\d+([._]\\d+)*)"), //
new OS("Symbian", "symbian(os)?"), //
new OS("Darwin", "Darwin\\/([\\d\\w\\.\\-]+)", "Darwin\\/([\\d\\w\\.\\-]+)"), //
new OS("Adobe Air", "AdobeAir\\/([\\d\\w\\.\\-]+)", "AdobeAir\\/([\\d\\w\\.\\-]+)"), //
new OS("Java", "Java[\\s]+([\\d\\w\\.\\-]+)", "Java[\\s]+([\\d\\w\\.\\-]+)")//
);
/**
*
*
* @param name
* @param regex
* @param versionRegex
* @since 5.7.4
*/
synchronized public static void addCustomOs(String name, String regex, String versionRegex) {
oses.add(new OS(name, regex, versionRegex));
}
private Pattern versionPattern;
/**
*
*
* @param name
* @param regex
*/
public OS(String name, String regex) {
this(name, regex, null);
}
/**
*
*
* @param name
* @param regex
* @param versionRegex
* @since 5.7.4
*/
public OS(String name, String regex, String versionRegex) {
super(name, regex);
if (null != versionRegex) {
this.versionPattern = Pattern.compile(versionRegex, Pattern.CASE_INSENSITIVE);
}
}
/**
*
*
* @param userAgentString User-Agent
* @return
*/
public String getVersion(String userAgentString) {
if (isUnknown() || null == this.versionPattern) {
// 无版本信息
return null;
}
return ReUtil.getGroup1(this.versionPattern, userAgentString);
}
}

View File

@ -0,0 +1,147 @@
package aiyh.utils.tool.cn.hutool.http.useragent;
import aiyh.utils.tool.cn.hutool.core.collection.CollUtil;
import java.util.ArrayList;
import java.util.List;
/**
*
*
* @author looly
* @since 4.2.1
*/
public class Platform extends UserAgentInfo {
private static final long serialVersionUID = 1L;
/**
*
*/
public static final Platform Unknown = new Platform(NameUnknown, null);
/**
* Iphone
*/
public static final Platform IPHONE = new Platform("iPhone", "iphone");
/**
* ipod
*/
public static final Platform IPOD = new Platform("iPod", "ipod");
/**
* ipad
*/
public static final Platform IPAD = new Platform("iPad", "ipad");
/**
* android
*/
public static final Platform ANDROID = new Platform("Android", "android");
/**
* android
*/
public static final Platform GOOGLE_TV = new Platform("GoogleTV", "googletv");
/**
* Windows Phone
*/
public static final Platform WINDOWS_PHONE = new Platform("Windows Phone", "windows (ce|phone|mobile)( os)?");
/**
*
*/
public static final List<Platform> mobilePlatforms = CollUtil.newArrayList(//
WINDOWS_PHONE, //
IPAD, //
IPOD, //
IPHONE, //
new Platform("Android", "XiaoMi|MI\\s+"), //
ANDROID, //
GOOGLE_TV, //
new Platform("htcFlyer", "htc_flyer"), //
new Platform("Symbian", "symbian(os)?"), //
new Platform("Blackberry", "blackberry") //
);
/**
*
*/
public static final List<Platform> desktopPlatforms = CollUtil.newArrayList(//
new Platform("Windows", "windows"), //
new Platform("Mac", "(macintosh|darwin)"), //
new Platform("Linux", "linux"), //
new Platform("Wii", "wii"), //
new Platform("Playstation", "playstation"), //
new Platform("Java", "java") //
);
/**
*
*/
public static final List<Platform> platforms;
static {
platforms = new ArrayList<>(13);
platforms.addAll(mobilePlatforms);
platforms.addAll(desktopPlatforms);
}
/**
*
*
* @param name
* @param regex
*/
public Platform(String name, String regex) {
super(name, regex);
}
/**
*
*
* @return
*/
public boolean isMobile() {
return mobilePlatforms.contains(this);
}
/**
* IphoneiPod
*
* @return IphoneiPod
* @since 5.2.3
*/
public boolean isIPhoneOrIPod() {
return this.equals(IPHONE) || this.equals(IPOD);
}
/**
* IphoneiPod
*
* @return IphoneiPod
* @since 5.2.3
*/
public boolean isIPad() {
return this.equals(IPAD);
}
/**
* IOSIPhoneIPodIPad
*
* @return IOSIPhoneIPodIPad
* @since 5.2.3
*/
public boolean isIos() {
return isIPhoneOrIPod() || isIPad();
}
/**
* AndroidAndroidGoogle TV
*
* @return AndroidAndroidGoogle TV
* @since 5.2.3
*/
public boolean isAndroid() {
return this.equals(ANDROID) || this.equals(GOOGLE_TV);
}
}

View File

@ -0,0 +1,196 @@
package aiyh.utils.tool.cn.hutool.http.useragent;
import java.io.Serializable;
/**
* User-Agent
*
* @author looly
* @since 4.2.1
*/
public class UserAgent implements Serializable {
private static final long serialVersionUID = 1L;
/**
*
*/
private boolean mobile;
/**
*
*/
private aiyh.utils.tool.cn.hutool.http.useragent.Browser browser;
/**
*
*/
private String version;
/**
*
*/
private aiyh.utils.tool.cn.hutool.http.useragent.Platform platform;
/**
*
*/
private aiyh.utils.tool.cn.hutool.http.useragent.OS os;
/**
*
*/
private String osVersion;
/**
*
*/
private aiyh.utils.tool.cn.hutool.http.useragent.Engine engine;
/**
*
*/
private String engineVersion;
/**
*
*
* @return
*/
public boolean isMobile() {
return mobile;
}
/**
*
*
* @param mobile
*/
public void setMobile(boolean mobile) {
this.mobile = mobile;
}
/**
*
*
* @return
*/
public aiyh.utils.tool.cn.hutool.http.useragent.Browser getBrowser() {
return browser;
}
/**
*
*
* @param browser
*/
public void setBrowser(Browser browser) {
this.browser = browser;
}
/**
*
*
* @return
*/
public aiyh.utils.tool.cn.hutool.http.useragent.Platform getPlatform() {
return platform;
}
/**
*
*
* @param platform
*/
public void setPlatform(Platform platform) {
this.platform = platform;
}
/**
*
*
* @return
*/
public aiyh.utils.tool.cn.hutool.http.useragent.OS getOs() {
return os;
}
/**
*
*
* @param os
*/
public void setOs(OS os) {
this.os = os;
}
/**
*
*
* @return
* @since 5.7.4
*/
public String getOsVersion() {
return this.osVersion;
}
/**
*
*
* @param osVersion
* @since 5.7.4
*/
public void setOsVersion(String osVersion) {
this.osVersion = osVersion;
}
/**
*
*
* @return
*/
public aiyh.utils.tool.cn.hutool.http.useragent.Engine getEngine() {
return engine;
}
/**
*
*
* @param engine
*/
public void setEngine(Engine engine) {
this.engine = engine;
}
/**
*
*
* @return
*/
public String getVersion() {
return version;
}
/**
*
*
* @param version
*/
public void setVersion(String version) {
this.version = version;
}
/**
*
*
* @return
*/
public String getEngineVersion() {
return engineVersion;
}
/**
*
*
* @param engineVersion
*/
public void setEngineVersion(String engineVersion) {
this.engineVersion = engineVersion;
}
}

View File

@ -0,0 +1,114 @@
package aiyh.utils.tool.cn.hutool.http.useragent;
import aiyh.utils.tool.cn.hutool.core.util.ReUtil;
import java.io.Serializable;
import java.util.regex.Pattern;
/**
* User-agent
*
* @author looly
* @since 4.2.1
*/
public class UserAgentInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**
*
*/
public static final String NameUnknown = "Unknown";
/** 信息名称 */
private final String name;
/** 信息匹配模式 */
private final Pattern pattern;
/**
*
*
* @param name
* @param regex
*/
public UserAgentInfo(String name, String regex) {
this(name, (null == regex) ? null : Pattern.compile(regex, Pattern.CASE_INSENSITIVE));
}
/**
*
*
* @param name
* @param pattern
*/
public UserAgentInfo(String name, Pattern pattern) {
this.name = name;
this.pattern = pattern;
}
/**
*
*
* @return
*/
public String getName() {
return name;
}
/**
*
*
* @return
*/
public Pattern getPattern() {
return pattern;
}
/**
*
*
* @param content User-Agent
* @return
*/
public boolean isMatch(String content) {
return ReUtil.contains(this.pattern, content);
}
/**
* Unknown
*
* @return Unknown
*/
public boolean isUnknown() {
return NameUnknown.equals(this.name);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final UserAgentInfo other = (UserAgentInfo) obj;
if (name == null) {
return other.name == null;
} else return name.equals(other.name);
}
@Override
public String toString() {
return this.name;
}
}

View File

@ -0,0 +1,108 @@
package aiyh.utils.tool.cn.hutool.http.useragent;
import aiyh.utils.tool.cn.hutool.core.util.StrUtil;
/**
* User-Agent
*
* @author looly
* @since 4.2.1
*/
public class UserAgentParser {
/**
* User-Agent
*
* @param userAgentString User-Agent
* @return {@link UserAgent}
*/
public static UserAgent parse(String userAgentString) {
if (StrUtil.isBlank(userAgentString)) {
return null;
}
final UserAgent userAgent = new UserAgent();
// 浏览器
final aiyh.utils.tool.cn.hutool.http.useragent.Browser browser = parseBrowser(userAgentString);
userAgent.setBrowser(browser);
userAgent.setVersion(browser.getVersion(userAgentString));
// 浏览器引擎
final aiyh.utils.tool.cn.hutool.http.useragent.Engine engine = parseEngine(userAgentString);
userAgent.setEngine(engine);
userAgent.setEngineVersion(engine.getVersion(userAgentString));
// 操作系统
final aiyh.utils.tool.cn.hutool.http.useragent.OS os = parseOS(userAgentString);
userAgent.setOs(os);
userAgent.setOsVersion(os.getVersion(userAgentString));
// 平台
final aiyh.utils.tool.cn.hutool.http.useragent.Platform platform = parsePlatform(userAgentString);
userAgent.setPlatform(platform);
userAgent.setMobile(platform.isMobile() || browser.isMobile());
return userAgent;
}
/**
*
*
* @param userAgentString User-Agent
* @return
*/
private static aiyh.utils.tool.cn.hutool.http.useragent.Browser parseBrowser(String userAgentString) {
for (aiyh.utils.tool.cn.hutool.http.useragent.Browser browser : aiyh.utils.tool.cn.hutool.http.useragent.Browser.browers) {
if (browser.isMatch(userAgentString)) {
return browser;
}
}
return Browser.Unknown;
}
/**
*
*
* @param userAgentString User-Agent
* @return
*/
private static aiyh.utils.tool.cn.hutool.http.useragent.Engine parseEngine(String userAgentString) {
for (aiyh.utils.tool.cn.hutool.http.useragent.Engine engine : aiyh.utils.tool.cn.hutool.http.useragent.Engine.engines) {
if (engine.isMatch(userAgentString)) {
return engine;
}
}
return Engine.Unknown;
}
/**
*
*
* @param userAgentString User-Agent
* @return
*/
private static aiyh.utils.tool.cn.hutool.http.useragent.OS parseOS(String userAgentString) {
for (aiyh.utils.tool.cn.hutool.http.useragent.OS os : aiyh.utils.tool.cn.hutool.http.useragent.OS.oses) {
if (os.isMatch(userAgentString)) {
return os;
}
}
return OS.Unknown;
}
/**
*
*
* @param userAgentString User-Agent
* @return
*/
private static aiyh.utils.tool.cn.hutool.http.useragent.Platform parsePlatform(String userAgentString) {
for (aiyh.utils.tool.cn.hutool.http.useragent.Platform platform : aiyh.utils.tool.cn.hutool.http.useragent.Platform.platforms) {
if (platform.isMatch(userAgentString)) {
return platform;
}
}
return Platform.Unknown;
}
}

View File

@ -0,0 +1,20 @@
package aiyh.utils.tool.cn.hutool.http.useragent;
/**
* User-Agent
*
* @author looly
*/
public class UserAgentUtil {
/**
* User-Agent
*
* @param userAgentString User-Agent
* @return {@link UserAgent}
*/
public static UserAgent parse(String userAgentString) {
return UserAgentParser.parse(userAgentString);
}
}

View File

@ -0,0 +1,6 @@
/**
* User-Agent
*
* @author looly
*/
package aiyh.utils.tool.cn.hutool.http.useragent;

View File

@ -0,0 +1,654 @@
package aiyh.utils.tool.cn.hutool.http.webservice;
import aiyh.utils.tool.cn.hutool.core.collection.CollUtil;
import aiyh.utils.tool.cn.hutool.core.io.IoUtil;
import aiyh.utils.tool.cn.hutool.core.map.MapUtil;
import aiyh.utils.tool.cn.hutool.core.util.ObjectUtil;
import aiyh.utils.tool.cn.hutool.core.util.StrUtil;
import aiyh.utils.tool.cn.hutool.core.util.XmlUtil;
import aiyh.utils.tool.cn.hutool.http.HttpBase;
import aiyh.utils.tool.cn.hutool.http.HttpGlobalConfig;
import aiyh.utils.tool.cn.hutool.http.HttpRequest;
import aiyh.utils.tool.cn.hutool.http.HttpResponse;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.soap.*;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
/**
* SOAP
*
* <p>
* SOAPHTTP
* SOAPXML{@link #getMsgStr(boolean)}
* <p>
* 使
*
* <pre>
* SoapClient client = SoapClient.create(url)
* .setMethod(methodName, namespaceURI)
* .setCharset(CharsetUtil.CHARSET_GBK)
* .setParam(param1, "XXX");
*
* String response = client.send(true);
*
* </pre>
*
* @author looly
* @since 4.5.4
*/
public class SoapClient extends HttpBase<SoapClient> {
/**
* XMLContent-Type
* soap1.1 : text/xml
* soap1.2 : application/soap+xml
* soap1.1soap1.2: https://www.cnblogs.com/qlqwjy/p/7577147.html
*/
private static final String CONTENT_TYPE_SOAP11_TEXT_XML = "text/xml;charset=";
private static final String CONTENT_TYPE_SOAP12_SOAP_XML = "application/soap+xml;charset=";
/**
* URL
*/
private String url;
/**
*
*/
private int connectionTimeout = aiyh.utils.tool.cn.hutool.http.HttpGlobalConfig.getTimeout();
/**
*
*/
private int readTimeout = HttpGlobalConfig.getTimeout();
/**
*
*/
private MessageFactory factory;
/**
* SOAP
*/
private SOAPMessage message;
/**
*
*/
private SOAPBodyElement methodEle;
/**
* URI
*/
private final String namespaceURI;
/**
* Soap
* soap1.1 : text/xml
* soap1.2 : application/soap+xml
*/
private final SoapProtocol protocol;
/**
* SOAP使soap1.1
*
* @param url WSURL
* @return this
*/
public static SoapClient create(String url) {
return new SoapClient(url);
}
/**
* SOAP
*
* @param url WSURL
* @param protocol {@link SoapProtocol}
* @return this
*/
public static SoapClient create(String url, SoapProtocol protocol) {
return new SoapClient(url, protocol);
}
/**
* SOAP
*
* @param url WSURL
* @param protocol {@link SoapProtocol}
* @param namespaceURI URI
* @return this
* @since 4.5.6
*/
public static SoapClient create(String url, SoapProtocol protocol, String namespaceURI) {
return new SoapClient(url, protocol, namespaceURI);
}
/**
* 使soap1.1
*
* @param url WSURL
*/
public SoapClient(String url) {
this(url, SoapProtocol.SOAP_1_1);
}
/**
*
*
* @param url WSURL
* @param protocol {@link SoapProtocol}
*/
public SoapClient(String url, SoapProtocol protocol) {
this(url, protocol, null);
}
/**
*
*
* @param url WSURL
* @param protocol {@link SoapProtocol}
* @param namespaceURI URI
* @since 4.5.6
*/
public SoapClient(String url, SoapProtocol protocol, String namespaceURI) {
this.url = url;
this.namespaceURI = namespaceURI;
this.protocol = protocol;
init(protocol);
}
/**
*
*
* @param protocol {@link SoapProtocol}
* @return this
*/
public SoapClient init(SoapProtocol protocol) {
// 创建消息工厂
try {
this.factory = MessageFactory.newInstance(protocol.getValue());
// 根据消息工厂创建SoapMessage
this.message = factory.createMessage();
} catch (SOAPException e) {
throw new SoapRuntimeException(e);
}
return this;
}
/**
* SOAP
*
* <p>
* serMethodsetParam
*
* @return this
* @since 4.6.7
*/
public SoapClient reset() {
try {
this.message = factory.createMessage();
} catch (SOAPException e) {
throw new SoapRuntimeException(e);
}
this.methodEle = null;
return this;
}
/**
*
*
* @param charset
* @return this
* @see #charset(Charset)
*/
public SoapClient setCharset(Charset charset) {
return this.charset(charset);
}
@Override
public SoapClient charset(Charset charset) {
super.charset(charset);
try {
this.message.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, this.charset());
this.message.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "true");
} catch (SOAPException e) {
// ignore
}
return this;
}
/**
* Webservice
*
* @param url Webservice
* @return this
*/
public SoapClient setUrl(String url) {
this.url = url;
return this;
}
/**
* SOAP{@link SOAPHeaderElement}
*
* @param name
* @param actorURI
* @param roleUri RoleURI
* @param mustUnderstand
* @param relay relay
* @return {@link SOAPHeaderElement}
* @since 5.4.4
*/
public SOAPHeaderElement addSOAPHeader(QName name, String actorURI, String roleUri, Boolean mustUnderstand, Boolean relay) {
final SOAPHeaderElement ele = addSOAPHeader(name);
try {
if (StrUtil.isNotBlank(roleUri)) {
ele.setRole(roleUri);
}
if (null != relay) {
ele.setRelay(relay);
}
} catch (SOAPException e) {
throw new SoapRuntimeException(e);
}
if (StrUtil.isNotBlank(actorURI)) {
ele.setActor(actorURI);
}
if (null != mustUnderstand) {
ele.setMustUnderstand(mustUnderstand);
}
return ele;
}
/**
* SOAP{@link SOAPHeaderElement}
*
* @param localName
* @return {@link SOAPHeaderElement}
* @since 5.4.7
*/
public SOAPHeaderElement addSOAPHeader(String localName) {
return addSOAPHeader(new QName(localName));
}
/**
* SOAP{@link SOAPHeaderElement}
*
* @param localName
* @param value
* @return {@link SOAPHeaderElement}
* @since 5.4.7
*/
public SOAPHeaderElement addSOAPHeader(String localName, String value) {
final SOAPHeaderElement soapHeaderElement = addSOAPHeader(localName);
soapHeaderElement.setTextContent(value);
return soapHeaderElement;
}
/**
* SOAP{@link SOAPHeaderElement}
*
* @param name
* @return {@link SOAPHeaderElement}
* @since 5.4.4
*/
public SOAPHeaderElement addSOAPHeader(QName name) {
SOAPHeaderElement ele;
try {
ele = this.message.getSOAPHeader().addHeaderElement(name);
} catch (SOAPException e) {
throw new SoapRuntimeException(e);
}
return ele;
}
/**
*
*
* @param name
* @param params
* @param useMethodPrefix 使
* @return this
*/
public SoapClient setMethod(Name name, Map<String, Object> params, boolean useMethodPrefix) {
return setMethod(new QName(name.getURI(), name.getLocalName(), name.getPrefix()), params, useMethodPrefix);
}
/**
*
*
* @param name
* @param params
* @param useMethodPrefix 使
* @return this
*/
public SoapClient setMethod(QName name, Map<String, Object> params, boolean useMethodPrefix) {
setMethod(name);
final String prefix = useMethodPrefix ? name.getPrefix() : null;
final SOAPBodyElement methodEle = this.methodEle;
for (Entry<String, Object> entry : MapUtil.wrap(params)) {
setParam(methodEle, entry.getKey(), entry.getValue(), prefix);
}
return this;
}
/**
* <br>
* 使:<br>
* xmlnsnamespaceURI
*
* @param methodName
* @return this
*/
public SoapClient setMethod(String methodName) {
return setMethod(methodName, ObjectUtil.defaultIfNull(this.namespaceURI, XMLConstants.NULL_NS_URI));
}
/**
* <br>
* 使:<br>
* xmlnsnamespaceURI
*
* @param methodName
* @param namespaceURI URI
* @return this
*/
public SoapClient setMethod(String methodName, String namespaceURI) {
final List<String> methodNameList = StrUtil.split(methodName, ':');
final QName qName;
if (2 == methodNameList.size()) {
qName = new QName(namespaceURI, methodNameList.get(1), methodNameList.get(0));
} else {
qName = new QName(namespaceURI, methodName);
}
return setMethod(qName);
}
/**
*
*
* @param name
* @return this
*/
public SoapClient setMethod(QName name) {
try {
this.methodEle = this.message.getSOAPBody().addBodyElement(name);
} catch (SOAPException e) {
throw new SoapRuntimeException(e);
}
return this;
}
/**
* 使
*
* @param name
* @param value Map{@link SOAPElement}
* @return this
*/
public SoapClient setParam(String name, Object value) {
return setParam(name, value, true);
}
/**
*
*
* @param name
* @param value Map{@link SOAPElement}
* @param useMethodPrefix 使
* @return this
*/
public SoapClient setParam(String name, Object value, boolean useMethodPrefix) {
setParam(this.methodEle, name, value, useMethodPrefix ? this.methodEle.getPrefix() : null);
return this;
}
/**
* 使
*
* @param params
* @return this
* @since 4.5.6
*/
public SoapClient setParams(Map<String, Object> params) {
return setParams(params, true);
}
/**
*
*
* @param params
* @param useMethodPrefix 使
* @return this
* @since 4.5.6
*/
public SoapClient setParams(Map<String, Object> params, boolean useMethodPrefix) {
for (Entry<String, Object> entry : MapUtil.wrap(params)) {
setParam(entry.getKey(), entry.getValue(), useMethodPrefix);
}
return this;
}
/**
* <br>
*
*
* @return {@link SOAPBodyElement}
* @since 4.5.6
*/
public SOAPBodyElement getMethodEle() {
return this.methodEle;
}
/**
* SOAP {@link SOAPMessage}
*
* @return {@link SOAPMessage}
* @since 4.5.6
*/
public SOAPMessage getMessage() {
return this.message;
}
/**
* SOAP
*
* @param pretty
* @return
*/
public String getMsgStr(boolean pretty) {
return SoapUtil.toString(this.message, pretty, this.charset);
}
/**
* SOAPXML
*
* @param out
* @return this
* @since 4.5.6
*/
public SoapClient write(OutputStream out) {
try {
this.message.writeTo(out);
} catch (SOAPException | IOException e) {
throw new SoapRuntimeException(e);
}
return this;
}
/**
* <br>
*
*
* <pre>
* 1.
* 2.
* </pre>
*
* @param milliseconds
* @return this
* @see #setConnectionTimeout(int)
* @see #setReadTimeout(int)
*/
public SoapClient timeout(int milliseconds) {
setConnectionTimeout(milliseconds);
setReadTimeout(milliseconds);
return this;
}
/**
*
*
* @param milliseconds
* @return this
* @since 4.5.6
*/
public SoapClient setConnectionTimeout(int milliseconds) {
this.connectionTimeout = milliseconds;
return this;
}
/**
*
*
* @param milliseconds
* @return this
* @since 4.5.6
*/
public SoapClient setReadTimeout(int milliseconds) {
this.readTimeout = milliseconds;
return this;
}
/**
* WebserviceSOAP
*
* @return
*/
public SOAPMessage sendForMessage() {
final aiyh.utils.tool.cn.hutool.http.HttpResponse res = sendForResponse();
final MimeHeaders headers = new MimeHeaders();
for (Entry<String, List<String>> entry : res.headers().entrySet()) {
if (StrUtil.isNotEmpty(entry.getKey())) {
headers.setHeader(entry.getKey(), CollUtil.get(entry.getValue(), 0));
}
}
try {
return this.factory.createMessage(headers, res.bodyStream());
} catch (IOException | SOAPException e) {
throw new SoapRuntimeException(e);
} finally {
IoUtil.close(res);
}
}
/**
* WebserviceSOAP
*
* @return
*/
public String send() {
return send(false);
}
/**
* WebserviceSOAP
*
* @param pretty
* @return
*/
public String send(boolean pretty) {
final String body = sendForResponse().body();
return pretty ? XmlUtil.format(body) : body;
}
// -------------------------------------------------------------------------------------------------------- Private method start
/**
*
*
* @return
*/
public HttpResponse sendForResponse() {
return HttpRequest.post(this.url)//
.setFollowRedirects(true)//
.setConnectionTimeout(this.connectionTimeout)
.setReadTimeout(this.readTimeout)
.contentType(getXmlContentType())//
.header(this.headers())
.body(getMsgStr(false))//
.executeAsync();
}
/**
* Content-Type
*
* @return Content-Type
*/
private String getXmlContentType() {
switch (this.protocol) {
case SOAP_1_1:
return CONTENT_TYPE_SOAP11_TEXT_XML.concat(this.charset.toString());
case SOAP_1_2:
return CONTENT_TYPE_SOAP12_SOAP_XML.concat(this.charset.toString());
default:
throw new SoapRuntimeException("Unsupported protocol: {}", this.protocol);
}
}
/**
*
*
* @param ele
* @param name
* @param value
* @param prefix {@code null}使
* @return {@link SOAPElement}
*/
@SuppressWarnings("rawtypes")
private static SOAPElement setParam(SOAPElement ele, String name, Object value, String prefix) {
final SOAPElement childEle;
try {
if (StrUtil.isNotBlank(prefix)) {
childEle = ele.addChildElement(name, prefix);
} else {
childEle = ele.addChildElement(name);
}
} catch (SOAPException e) {
throw new SoapRuntimeException(e);
}
if (null != value) {
if (value instanceof SOAPElement) {
// 单个子节点
try {
ele.addChildElement((SOAPElement) value);
} catch (SOAPException e) {
throw new SoapRuntimeException(e);
}
} else if (value instanceof Map) {
// 多个字节点
Entry entry;
for (Object obj : ((Map) value).entrySet()) {
entry = (Entry) obj;
setParam(childEle, entry.getKey().toString(), entry.getValue(), prefix);
}
} else {
// 单个值
childEle.setValue(value.toString());
}
}
return childEle;
}
// -------------------------------------------------------------------------------------------------------- Private method end
}

View File

@ -0,0 +1,35 @@
package aiyh.utils.tool.cn.hutool.http.webservice;
import javax.xml.soap.SOAPConstants;
/**
* SOAP
*
* @author looly
*/
public enum SoapProtocol {
/** SOAP 1.1协议 */
SOAP_1_1(SOAPConstants.SOAP_1_1_PROTOCOL),
/** SOAP 1.2协议 */
SOAP_1_2(SOAPConstants.SOAP_1_2_PROTOCOL);
/**
*
*
* @param value {@link SOAPConstants}
*/
SoapProtocol(String value) {
this.value = value;
}
private final String value;
/**
*
*
* @return
*/
public String getValue() {
return this.value;
}
}

View File

@ -0,0 +1,32 @@
package aiyh.utils.tool.cn.hutool.http.webservice;
import aiyh.utils.tool.cn.hutool.core.util.StrUtil;
/**
* SOAP
*
* @author xiaoleilu
*/
public class SoapRuntimeException extends RuntimeException {
private static final long serialVersionUID = 8247610319171014183L;
public SoapRuntimeException(Throwable e) {
super(e.getMessage(), e);
}
public SoapRuntimeException(String message) {
super(message);
}
public SoapRuntimeException(String messageTemplate, Object... params) {
super(StrUtil.format(messageTemplate, params));
}
public SoapRuntimeException(String message, Throwable throwable) {
super(message, throwable);
}
public SoapRuntimeException(Throwable throwable, String messageTemplate, Object... params) {
super(StrUtil.format(messageTemplate, params), throwable);
}
}

View File

@ -0,0 +1,91 @@
package aiyh.utils.tool.cn.hutool.http.webservice;
import aiyh.utils.tool.cn.hutool.core.exceptions.UtilException;
import aiyh.utils.tool.cn.hutool.core.util.CharsetUtil;
import aiyh.utils.tool.cn.hutool.core.util.XmlUtil;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
/**
* SOAP
*
* @author looly
* @since 4.5.7
*/
public class SoapUtil {
/**
* SOAP使soap1.1
*
* @param url WSURL
* @return {@link aiyh.utils.tool.cn.hutool.http.webservice.SoapClient}
*/
public static aiyh.utils.tool.cn.hutool.http.webservice.SoapClient createClient(String url) {
return aiyh.utils.tool.cn.hutool.http.webservice.SoapClient.create(url);
}
/**
* SOAP
*
* @param url WSURL
* @param protocol {@link SoapProtocol}
* @return {@link aiyh.utils.tool.cn.hutool.http.webservice.SoapClient}
*/
public static aiyh.utils.tool.cn.hutool.http.webservice.SoapClient createClient(String url, SoapProtocol protocol) {
return aiyh.utils.tool.cn.hutool.http.webservice.SoapClient.create(url, protocol);
}
/**
* SOAP
*
* @param url WSURL
* @param protocol {@link SoapProtocol}
* @param namespaceURI URI
* @return {@link aiyh.utils.tool.cn.hutool.http.webservice.SoapClient}
* @since 4.5.6
*/
public static aiyh.utils.tool.cn.hutool.http.webservice.SoapClient createClient(String url, SoapProtocol protocol, String namespaceURI) {
return SoapClient.create(url, protocol, namespaceURI);
}
/**
* {@link SOAPMessage}
*
* @param message SOAP
* @param pretty
* @return SOAP XML
*/
public static String toString(SOAPMessage message, boolean pretty) {
return toString(message, pretty, CharsetUtil.CHARSET_UTF_8);
}
/**
* {@link SOAPMessage}
*
* @param message SOAP
* @param pretty
* @param charset
* @return SOAP XML
* @since 4.5.7
*/
public static String toString(SOAPMessage message, boolean pretty, Charset charset) {
final ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
message.writeTo(out);
} catch (SOAPException | IOException e) {
throw new SoapRuntimeException(e);
}
String messageToString;
try {
messageToString = out.toString(charset.toString());
} catch (UnsupportedEncodingException e) {
throw new UtilException(e);
}
return pretty ? XmlUtil.format(messageToString) : messageToString;
}
}

View File

@ -0,0 +1,6 @@
/**
* Webservice
*
* @author looly
*/
package aiyh.utils.tool.cn.hutool.http.webservice;

View File

@ -0,0 +1,61 @@
package com.api.youhong.ai.ihgzhouji.taskele.contoller;
import aiyh.utils.ApiResult;
import aiyh.utils.Util;
import com.api.youhong.ai.ihgzhouji.taskele.service.TaskElementService;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import org.apache.log4j.Logger;
import weaver.hrm.HrmUserVarify;
import weaver.hrm.User;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import java.util.Map;
/**
* <h1></h1>
*
* <p>create: 2023/5/4 17:13</p>
*
* @author youHong.ai
*/
@Path("aiyh/ihg/task")
public class TaskElementController {
private final Logger log = Util.getLogger();
private final TaskElementService service = new TaskElementService();
@Path("/list-get")
@GET
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public String getList(@Context HttpServletRequest request, @Context HttpServletResponse response) {
User user = HrmUserVarify.getUser(request, response);
try {
return ApiResult.success(service.getList(user));
} catch (Exception e) {
log.error("get task list error!\n" + Util.getErrString(e));
return ApiResult.error("system error!");
}
}
@Path("/search-list")
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public String searchList(@Context HttpServletRequest request,
@Context HttpServletResponse response,
@RequestBody Map<String, Object> params,
@QueryParam("id") String configId) {
User user = HrmUserVarify.getUser(request, response);
try {
return ApiResult.success(service.getList(user, params,configId));
} catch (Exception e) {
log.error("get task list error!\n" + Util.getErrString(e));
return ApiResult.error("system error!");
}
}
}

View File

@ -0,0 +1,43 @@
package com.api.youhong.ai.ihgzhouji.taskele.entity;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
/**
* <h1></h1>
*
* <p>create: 2023/5/4 17:35</p>
*
* @author youHong.ai
*/
@Getter
@Setter
@ToString
@EqualsAndHashCode
public class IhgTaskElementConfigItem {
/** id */
private String id;
/** 标题 */
private String title;
/** 单位 */
private String unit;
/** 标题英文 */
private String titleEn;
/** 单位英文 */
private String unitEn;
/** icon */
private String icon;
/** 激活icon */
private String iconActive;
/** 查看权限 */
private String viewAuthority;
/** 数据来源 */
private String dataSource;
/** 跳转链接 */
private String link;
/** 数据来源值 */
private String customerValue;
}

View File

@ -0,0 +1,97 @@
package com.api.youhong.ai.ihgzhouji.taskele.mapper;
import aiyh.utils.annotation.recordset.*;
import com.api.youhong.ai.ihgzhouji.taskele.entity.IhgTaskElementConfigItem;
import weaver.hrm.User;
import java.util.List;
import java.util.Map;
/**
* <h1></h1>
*
* <p>create: 2023/5/4 17:23</p>
*
* @author youHong.ai
*/
@SqlMapper
public interface TaskElementMapper {
/**
* <h2></h2>
*
* @return
*/
@Select("select * from uf_ihg_el_config ")
@Associations({
@Association(
property = "icon",
column = "icon",
id = @Id(methodId = 1, value = String.class)),
@Association(
property = "iconActive",
column = "icon_active",
id = @Id(methodId = 1, value = String.class))
})
List<IhgTaskElementConfigItem> selectConfig();
/**
* <h2> </h2>
*
* @param configId id
* @return
*/
@Select("select * from uf_ihg_el_config where id = #{configId}")
@Associations({
@Association(
property = "icon",
column = "icon",
id = @Id(methodId = 1, value = String.class)),
@Association(
property = "iconActive",
column = "icon_active",
id = @Id(methodId = 1, value = String.class))
})
IhgTaskElementConfigItem selectConfig(@ParamMapper("configId") String configId);
/**
* <h2></h2>
*
* @param id docId
* @return
*/
@Select("select concat('/weaver/weaver.file.FileDownload?fileid=',IMAGEFILEID) from docimagefile where DOCID = #{id}")
@AssociationMethod(1)
String selectImageFileId(String id);
/**
* <h2></h2>
*
* @param viewAuthoritySql sql
* @param user
* @param map
* @param where
* @return
*/
@Select(custom = true)
List<Map<String, Object>> selectAuthority(@SqlString String viewAuthoritySql,
@ParamMapper("user") User user,
@ParamMapper("param") Map<String, Object> map);
/**
* <h2></h2>
*
* @param customerValue sql
* @param item
* @param user
* @param where
* @return
*/
@Select(custom = true)
List<Map<String, Object>> selectWorkList(@SqlString String customerValue,
@ParamMapper("param") Map<String, Object> item,
@ParamMapper("user") User user,
@ParamMapper("where") Map<String, Object> where);
}

View File

@ -0,0 +1,30 @@
package com.api.youhong.ai.ihgzhouji.taskele.mapstruct;
import com.api.youhong.ai.ihgzhouji.taskele.entity.IhgTaskElementConfigItem;
import com.api.youhong.ai.ihgzhouji.taskele.vo.IhgTaskElementVo;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
/**
* <h1>vopojo</h1>
*
* <p>create: 2023/5/6 11:11</p>
*
* @author youHong.ai
*/
@Mapper
public interface TaskElementMapstruct {
TaskElementMapstruct INSTANCE = Mappers.getMapper(TaskElementMapstruct.class);
/**
* <h2>entityvo</h2>
*
* @param item
* @return vo
*/
@Mapping(target = "size", ignore = true)
@Mapping(target = "list", ignore = true)
IhgTaskElementVo entity2Vo(IhgTaskElementConfigItem item);
}

View File

@ -0,0 +1,20 @@
package com.api.youhong.ai.ihgzhouji.taskele.service;
import com.api.youhong.ai.ihgzhouji.taskele.entity.IhgTaskElementConfigItem;
import weaver.hrm.User;
import java.util.List;
import java.util.Map;
/**
* <h1></h1>
*
* <p>create: 2023/5/5 17:42</p>
*
* @author youHong.ai
*/
public interface TaskElementGetValueInterface {
List<Map<String, Object>> getValue(IhgTaskElementConfigItem taskElementConfigItem,
Map<String, Object> param, User user);
}

View File

@ -0,0 +1,160 @@
package com.api.youhong.ai.ihgzhouji.taskele.service;
import aiyh.utils.Util;
import aiyh.utils.excention.CustomerException;
import aiyh.utils.tool.cn.hutool.core.collection.CollectionUtil;
import aiyh.utils.tool.cn.hutool.core.lang.Assert;
import aiyh.utils.tool.cn.hutool.core.util.StrUtil;
import com.api.youhong.ai.ihgzhouji.taskele.entity.IhgTaskElementConfigItem;
import com.api.youhong.ai.ihgzhouji.taskele.mapper.TaskElementMapper;
import com.api.youhong.ai.ihgzhouji.taskele.mapstruct.TaskElementMapstruct;
import com.api.youhong.ai.ihgzhouji.taskele.vo.IhgTaskElementVo;
import weaver.hrm.User;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* <h1>service</h1>
*
* <p>create: 2023/5/4 17:17</p>
*
* @author youHong.ai
*/
public class TaskElementService {
private final TaskElementMapper mapper = Util.getMapper(TaskElementMapper.class);
public List<IhgTaskElementVo> getList(User user) {
List<IhgTaskElementConfigItem> ihgTaskElementConfItemList = mapper.selectConfig();
if (CollectionUtil.isEmpty(ihgTaskElementConfItemList)) {
return Collections.emptyList();
}
Map<IhgTaskElementConfigItem, List<Map<String, Object>>> taskConfigMap = new HashMap<>();
// 设置查询基础参数
Map<String, Object> map = new HashMap<>(8);
map.put("currentDate", Util.getTime("yyyy-MM-dd"));
map.put("currentTime", Util.getTime("HH:mm:ss"));
// 查询每个item的可查看权限并进行过滤
for (IhgTaskElementConfigItem ihgTaskElementConfItem : ihgTaskElementConfItemList) {
String viewAuthoritySql = ihgTaskElementConfItem.getViewAuthority();
List<Map<String, Object>> authorityList = mapper.selectAuthority(viewAuthoritySql, user, map);
if (CollectionUtil.isNotEmpty(authorityList)) {
taskConfigMap.put(ihgTaskElementConfItem, authorityList);
}
}
// 查询数据
List<IhgTaskElementVo> result = new ArrayList<>();
for (Map.Entry<IhgTaskElementConfigItem, List<Map<String, Object>>> entry : taskConfigMap.entrySet()) {
IhgTaskElementConfigItem taskElementConfigItem = entry.getKey();
List<Map<String, Object>> authorityList = entry.getValue();
List<Map<String, Object>> workList = queryWorkList(taskElementConfigItem, authorityList, user, "", Collections.emptyMap());
IhgTaskElementVo ihgTaskElementVo = TaskElementMapstruct.INSTANCE.entity2Vo(taskElementConfigItem);
ihgTaskElementVo.setList(workList);
ihgTaskElementVo.setSize(workList.size());
if (user.getLanguage() == 8) {
ihgTaskElementVo.setTitle(taskElementConfigItem.getTitleEn());
ihgTaskElementVo.setUnit(taskElementConfigItem.getUnitEn());
}
result.add(ihgTaskElementVo);
}
return result;
}
private List<Map<String, Object>> queryWorkList(IhgTaskElementConfigItem taskElementConfigItem,
List<Map<String, Object>> authorityList,
User user, String whereStr,
Map<String, Object> whereMap) {
String dataSource = taskElementConfigItem.getDataSource();
String customerValue = taskElementConfigItem.getCustomerValue();
if (StrUtil.isBlank(customerValue)) {
throw new CustomerException("自定义sql或自定义接口不能为空");
}
List<Map<String, Object>> result = new ArrayList<>();
for (Map<String, Object> item : authorityList) {
if ("0".equals(dataSource)) {
// 自定义sql
customerValue += " " + whereStr;
List<Map<String, Object>> list = mapper.selectWorkList(customerValue, item, user, whereMap);
if (CollectionUtil.isNotEmpty(list)) {
result.addAll(list);
}
} else {
// 自定义接口
Map<String, String> map = Util.parseCusInterfacePathParam(customerValue);
map.put("whereStr", whereStr);
if (CollectionUtil.isNotEmpty(whereMap)) {
for (Map.Entry<String, Object> entry : whereMap.entrySet()) {
map.put(entry.getKey(), Util.null2String(entry.getValue()));
}
}
String classPath = map.remove("_ClassPath");
item.putAll(map);
TaskElementGetValueInterface instance = Util.getClassInstance(classPath, TaskElementGetValueInterface.class);
List<Map<String, Object>> list = instance.getValue(taskElementConfigItem, item, user);
if (CollectionUtil.isNotEmpty(list)) {
result.addAll(list);
}
}
}
// 去重
result = result.stream()
.filter(distinctByKey(item -> item.get("id")))
.collect(Collectors.toList());
return result;
}
static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Map<Object, Boolean> seen = new ConcurrentHashMap<>(8);
return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
/**
* <h2></h2>
*
* @param user
* @param params
* @return
*/
public IhgTaskElementVo getList(User user, Map<String, Object> params, String configId) {
Assert.notBlank(configId, "查询配置表Id为空");
IhgTaskElementConfigItem ihgTaskElementConfItem = mapper.selectConfig(configId);
if (Objects.isNull(ihgTaskElementConfItem)) {
return null;
}
// 设置查询基础参数
Map<String, Object> map = new HashMap<>(8);
map.put("currentDate", Util.getTime("yyyy-MM-dd"));
map.put("currentTime", Util.getTime("HH:mm:ss"));
StringBuilder builder = new StringBuilder();
for (Map.Entry<String, Object> entry : params.entrySet()) {
Map<String, Object> valueMap = (Map<String, Object>) entry.getValue();
String key = Util.null2String(valueMap.get("key"));
String value = Util.null2String(valueMap.get("value"));
if (StrUtil.isNotBlank(value)) {
builder.append(" and ").append(key).append(" = ").append("#{where.").append(key).append("}");
map.put(key, value);
}
}
String whereStr = builder.toString();
// 查询可查看权限并进行过滤
String viewAuthoritySql = ihgTaskElementConfItem.getViewAuthority();
List<Map<String, Object>> authorityList = mapper.selectAuthority(viewAuthoritySql, user, map);
if (CollectionUtil.isEmpty(authorityList)) {
return null;
}
// 查询数据
List<Map<String, Object>> workList = this.queryWorkList(ihgTaskElementConfItem, authorityList, user, whereStr, map);
IhgTaskElementVo ihgTaskElementVo = TaskElementMapstruct.INSTANCE.entity2Vo(ihgTaskElementConfItem);
ihgTaskElementVo.setList(workList);
ihgTaskElementVo.setSize(workList.size());
if (user.getLanguage() == 8) {
ihgTaskElementVo.setTitle(ihgTaskElementConfItem.getTitleEn());
ihgTaskElementVo.setUnit(ihgTaskElementConfItem.getUnitEn());
}
return ihgTaskElementVo;
}
}

View File

@ -0,0 +1,41 @@
package com.api.youhong.ai.ihgzhouji.taskele.vo;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.util.List;
import java.util.Map;
/**
* <h1></h1>
*
* <p>create: 2023/5/4 17:35</p>
*
* @author youHong.ai
*/
@Getter
@Setter
@ToString
public class IhgTaskElementVo {
/** id */
private String id;
/** 标题 */
private String title;
/** 单位 */
private String unit;
/** icon */
private String icon;
/** 激活icon */
private String iconActive;
/** 跳转链接 */
private String link;
/** 数据长度 */
private Integer size;
/** 数据 */
private List<Map<String, Object>> list;
}

View File

@ -0,0 +1,73 @@
package com.api.youhong.ai.yashilandai.openbill.controller;
import aiyh.utils.ApiResult;
import aiyh.utils.Util;
import com.api.youhong.ai.yashilandai.openbill.service.OpenTheBillService;
import org.apache.log4j.Logger;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
import java.net.URLEncoder;
/**
* <h1>api</h1>
*
* <p>create: 2023/4/25 10:09</p>
*
* @author youHong.ai
*/
@Path("/ayh/estee-Lauder/open-bill")
public class OpenTheBillController {
private final OpenTheBillService service = new OpenTheBillService();
private final Logger log = Util.getLogger();
@Path("/data/get")
@GET
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public String dataGet(@QueryParam("startDate") String startDate, @QueryParam("endDate") String endDate,
@QueryParam("orderNo") String orderNo) {
try {
return ApiResult.success(service.getOpenBillListData(startDate, endDate, orderNo));
} catch (Exception e) {
log.error("get open the bill data error!" + Util.getErrString(e));
return ApiResult.error("system error!");
}
}
@Path("/data/export")
@GET
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@Consumes(MediaType.APPLICATION_JSON)
@SuppressWarnings("all")
public Response export(@QueryParam("startDate") String startDate, @QueryParam("endDate") String endDate,
@QueryParam("orderNo") String orderNo) {
try {
// File file = service.exportExcel();
// StreamingOutput streamingOutput = output -> {
// try (InputStream input = Files.newInputStream(file.toPath())) {
// IOUtils.copy(input, output);
// }
// };
// // 获取文件大小
// long fileSize = file.length();
StreamingOutput streamingOutput = outputStream -> {
service.exportExcel(outputStream, startDate, endDate,orderNo);
};
String fileName = new String(("疑似拆单数据-" + Util.getTime("yyyy-MM-dd") + ".xlsx"));
String encodedFileName = URLEncoder.encode(fileName, "UTF-8");
Response.ResponseBuilder builder = Response.ok(streamingOutput)
// 指定编码方式为 UTF-8
.header("Content-Disposition", "attachment; filename*=UTF-8''" + encodedFileName);
return builder.build();
} catch (Exception e) {
log.error("导出excel文件失败" + Util.getErrString(e));
return Response.ok(ApiResult.error("导出文件失败!"), MediaType.APPLICATION_JSON).build();
}
}
}

View File

@ -1,38 +0,0 @@
package com.api.youhong.ai.yashilandai.openbill.controller;
import aiyh.utils.ApiResult;
import aiyh.utils.Util;
import com.api.youhong.ai.yashilandai.openbill.service.OpenThenBillService;
import org.apache.log4j.Logger;
import javax.ws.rs.Consumes;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
/**
* <h1>api</h1>
*
* <p>create: 2023/4/25 10:09</p>
*
* @author youHong.ai
*/
@Path("/ayh/estee-Lauder/open-bill")
public class OpenThenBillController {
private final OpenThenBillService service = new OpenThenBillService();
private final Logger log = Util.getLogger();
@Path("/data/get")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public String dataGet() {
try {
return ApiResult.success(service.getOpenBillListData());
} catch (Exception e) {
log.error("get open the bill data error!" + Util.getErrString(e));
return ApiResult.error("system error!");
}
}
}

View File

@ -0,0 +1,69 @@
package com.api.youhong.ai.yashilandai.openbill.mapper;
import aiyh.utils.annotation.recordset.*;
import com.api.youhong.ai.yashilandai.openbill.pojo.ConditionDetail;
import com.api.youhong.ai.yashilandai.openbill.pojo.ConditionEntity;
import java.util.List;
import java.util.Map;
/**
* <h1></h1>
*
* <p>create: 2023/4/25 10:15</p>
*
* @author youHong.ai
*/
@SqlMapper
public interface OpenTheBillMapper {
/**
* <h2></h2>
*
* @param tableName
* @return
*/
@Select("select * from $t{tableName}")
List<Map<String, Object>> selectList(@ParamMapper("tableName") String tableName);
@Select("select * from $t{tableName} where $t{dateField} between #{startDate} and #{endDate} $t{condition}")
List<Map<String, Object>> selectList(@ParamMapper("tableName") String tableName,
@ParamMapper("startDate") String startDate,
@ParamMapper("endDate") String endDate,
@ParamMapper("dateField") String dateField,
@ParamMapper("condition") String condition);
/**
* <h2></h2>
*
* @param id id
* @return
*/
@Select("select * from uf_ncotjcs where id = #{id}")
@CollectionMappings({
@CollectionMapping(property = "list",
column = "id",
id = @Id(methodId = 1, value = String.class))
})
ConditionEntity selectCondition(@ParamMapper("id") String id);
/**
* <h2></h2>
*
* @param mainId id
* @return
*/
@Select("select * from uf_ncotjcs_dt1 where mainid = #{mainId}")
@CollectionMethod(1)
List<ConditionDetail> selectConditionDetail(@ParamMapper("mainId") String mainId);
/**
* <h2>workflowId requestId</h2>
*
* @param requestId requestId
* @return workflowId
*/
@Select("select WORKFLOWID from workflow_requestbase where REQUESTID = #{requestId}")
String selectWorkflowId(@ParamMapper("requestId") String requestId);
}

View File

@ -1,26 +0,0 @@
package com.api.youhong.ai.yashilandai.openbill.mapper;
import aiyh.utils.annotation.recordset.Select;
import aiyh.utils.annotation.recordset.SqlMapper;
import java.util.List;
import java.util.Map;
/**
* <h1></h1>
*
* <p>create: 2023/4/25 10:15</p>
*
* @author youHong.ai
*/
@SqlMapper
public interface OpenThenBillMapper {
/**
* <h2></h2>
*
* @return
*/
@Select("select * from v_online")
List<Map<String, Object>> selectList();
}

View File

@ -0,0 +1,23 @@
package com.api.youhong.ai.yashilandai.openbill.pojo;
import aiyh.utils.annotation.recordset.SqlDbFieldAnn;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
public class ConditionDetail {
private Integer id;
@SqlDbFieldAnn("tjmc")
private String conditionName;
@SqlDbFieldAnn("tjzdmc")
private String conditionFieldName;
@SqlDbFieldAnn("tjgx")
private Integer conditionType;
@SqlDbFieldAnn("tjzdz")
private String conditionValue;
}

View File

@ -0,0 +1,26 @@
package com.api.youhong.ai.yashilandai.openbill.pojo;
import aiyh.utils.annotation.recordset.SqlDbFieldAnn;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.util.List;
/**
* <h1></h1>
*
* <p>create: 2023/4/25 15:07</p>
*
* @author youHong.ai
*/
@Getter
@Setter
@ToString
public class ConditionEntity {
private Integer id;
@SqlDbFieldAnn("mxbjgx")
private String condition;
private List<ConditionDetail> list;
}

View File

@ -0,0 +1,572 @@
package com.api.youhong.ai.yashilandai.openbill.service;
import aiyh.utils.ScriptUtil;
import aiyh.utils.Util;
import aiyh.utils.excention.CustomerException;
import aiyh.utils.tool.Assert;
import aiyh.utils.tool.cn.hutool.core.collection.CollectionUtil;
import aiyh.utils.tool.cn.hutool.core.util.StrUtil;
import aiyh.utils.tool.org.apache.commons.jexl3.JexlException;
import com.alibaba.fastjson.JSON;
import com.api.youhong.ai.yashilandai.openbill.mapper.OpenTheBillMapper;
import com.api.youhong.ai.yashilandai.openbill.pojo.ConditionDetail;
import com.api.youhong.ai.yashilandai.openbill.pojo.ConditionEntity;
import com.api.youhong.ai.yashilandai.openbill.util.ExcelCell;
import com.api.youhong.ai.yashilandai.openbill.util.ExcelPort;
import com.api.youhong.ai.yashilandai.openbill.util.ExcelRow;
import org.apache.log4j.Logger;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import java.io.OutputStream;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* <h1>service</h1>
*
* <p>create: 2023/4/25 10:12</p>
*
* @author youHong.ai
*/
public class OpenTheBillService {
private final OpenTheBillMapper mapper = Util.getMapper(OpenTheBillMapper.class);
private final Logger log = Util.getLogger();
public Map<String, Object> getOpenBillListData(String startDate, String endDate, String orderNo) {
return getData(startDate, endDate, orderNo);
}
public void exportExcel(OutputStream outputStream, String startDate, String endDate, String orderNo) {
Map<String, Object> data = getData(startDate, endDate, orderNo);
Map<String, Object> head = (Map<String, Object>) data.get("head");
List<Map<String, Object>> body = (List<Map<String, Object>>) data.get("body");
List<ExcelRow> list = new ArrayList<>();
List<ExcelCell> excelHeadCellList = new ArrayList<>();
List<String> fieldList = new ArrayList<>();
ExcelRow excelRow = new ExcelRow();
excelRow.setRowHeight(21F);
excelRow.setDataList(excelHeadCellList);
list.add(excelRow);
List<String> headFieldList = (List<String>) head.get("field");
List<String> headTitleList = (List<String>) head.get("title");
for (int i = 0; i < headFieldList.size(); i++) {
String title = headTitleList.get(i);
String field = headFieldList.get(i);
ExcelCell excelCell = new ExcelCell();
excelCell.setValue(title);
excelHeadCellList.add(excelCell);
fieldList.add(field);
}
for (Map<String, Object> item : body) {
ExcelRow excelBodyRow = new ExcelRow();
List<ExcelCell> excelCellList = new ArrayList<>();
for (String key : fieldList) {
Object value = item.get(key);
ExcelCell excelCell = new ExcelCell();
excelCell.setValue(value);
excelCellList.add(excelCell);
}
excelBodyRow.setDataList(excelCellList);
list.add(excelBodyRow);
}
Map<Integer, CellStyle> headStyle = new HashMap<>();
Map<Integer, CellStyle> singularLine = new HashMap<>();
Map<Integer, CellStyle> evenNumberLine = new HashMap<>();
ExcelPort.exportFile("疑似拆单-" + Util.getTime("yyyy-MM-dd"), list,
outputStream,
this::setHeaderStyle,
this::setBodyStyle,
headStyle, singularLine, evenNumberLine);
}
private CellStyle setHeaderStyle(SXSSFWorkbook workbook,
Integer rowIndex,
Integer colIndex,
SXSSFRow row,
SXSSFCell cell,
SXSSFSheet sheet, Map<Integer, CellStyle> headStyle,
Map<Integer, CellStyle> headStyle2) {
if (headStyle.containsKey(colIndex)) {
return headStyle.get(colIndex);
}
// 设置表格单元格格式
CellStyle cellStyle = workbook.createCellStyle();
cellStyle.setAlignment(HorizontalAlignment.CENTER);
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
cellStyle.setBorderRight(BorderStyle.THIN);
cellStyle.setRightBorderColor(IndexedColors.BLACK.getIndex());
cellStyle.setBorderLeft(BorderStyle.THIN);
cellStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex());
cellStyle.setBorderTop(BorderStyle.THIN);
cellStyle.setTopBorderColor(IndexedColors.BLACK.getIndex());
cellStyle.setBorderBottom(BorderStyle.THIN);
cellStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex());
cellStyle.setWrapText(true);
// 设置字体格式
Font font = workbook.createFont();
font.setFontName("微软雅黑");
font.setFontHeightInPoints((short) 14);
font.setBold(true);
font.setColor(HSSFColor.HSSFColorPredefined.WHITE.getIndex());
int columnWidth = sheet.getColumnWidth(colIndex);
String value = cell.getStringCellValue();
/** 计算字符串中中文字符的数量 */
int count = chineseCharCountOf(value);
/**在该列字符长度的基础上加上汉字个数计算列宽 */
int length = (value.length() - count) * 256 + (count + 4) * 512;
length = length * font.getFontHeightInPoints() / 11;
if (length >= columnWidth && length < 256 * 256) {
sheet.setColumnWidth(colIndex, length);
}
cellStyle.setFont(font);
cellStyle.setFillBackgroundColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
cellStyle.setFillPattern(FillPatternType.BRICKS);
headStyle.put(colIndex, cellStyle);
return cellStyle;
}
private CellStyle setBodyStyle(SXSSFWorkbook workbook,
Integer rowIndex,
Integer colIndex,
SXSSFRow row,
SXSSFCell cell,
SXSSFSheet sheet, Map<Integer, CellStyle> singularLine, Map<Integer, CellStyle> evenNumberLine) {
int columnWidth = sheet.getColumnWidth(colIndex);
String value = cell.getStringCellValue();
/** 计算字符串中中文字符的数量 */
int count = chineseCharCountOf(value);
/**在该列字符长度的基础上加上汉字个数计算列宽 */
int length = (value.length() - count) * 256 + (count + 4) * 512;
length = length * 10 / 11;
if (length >= columnWidth && length < 256 * 256) {
sheet.setColumnWidth(colIndex, length);
}
if (rowIndex % 2 == 1) {
if (singularLine.containsKey(colIndex)) {
return singularLine.get(colIndex);
}
CellStyle cellStyle = getCellStyle(workbook, rowIndex, colIndex, cell, sheet);
singularLine.put(colIndex, cellStyle);
return cellStyle;
} else {
if (evenNumberLine.containsKey(colIndex)) {
return evenNumberLine.get(colIndex);
}
CellStyle cellStyle = getCellStyle(workbook, rowIndex, colIndex, cell, sheet);
// 设置字体格式
Font font = workbook.createFont();
font.setFontName("微软雅黑");
font.setFontHeightInPoints((short) 10);
cellStyle.setFont(font);
evenNumberLine.put(colIndex, cellStyle);
return cellStyle;
}
}
private CellStyle getCellStyle(SXSSFWorkbook workbook, Integer rowIndex, Integer colIndex, SXSSFCell cell, SXSSFSheet sheet) {
// 设置表格单元格格式
CellStyle style = workbook.createCellStyle();
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setAlignment(HorizontalAlignment.CENTER);
style.setBorderRight(BorderStyle.THIN);
style.setRightBorderColor(IndexedColors.BLACK.getIndex());
style.setBorderLeft(BorderStyle.THIN);
style.setLeftBorderColor(IndexedColors.BLACK.getIndex());
style.setBorderTop(BorderStyle.THIN);
style.setTopBorderColor(IndexedColors.BLACK.getIndex());
style.setBorderBottom(BorderStyle.THIN);
style.setBottomBorderColor(IndexedColors.BLACK.getIndex());
style.setWrapText(true);
// if (rowIndex % 2 == 1) {
// XSSFColor color = new XSSFColor(new java.awt.Color(242, 242, 242), new DefaultIndexedColorMap());
// style.setFillBackgroundColor(color.getIndex());
// style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
// }
return style;
}
/**
*
* <a hrft="https://www.cnblogs.com/straybirds/p/6392306.html">unicode</a>
*
* @param input
* @return
*/
private static int chineseCharCountOf(String input) {
// 汉字数量
int count = 0;
if (null != input) {
String regEx = "[\\u4e00-\\u9fa5]";
Pattern p = Pattern.compile(regEx);
Matcher m = p.matcher(input);
int len = m.groupCount();
// 获取汉字个数
while (m.find()) {
for (int i = 0; i <= len; i++) {
count = count + 1;
}
}
}
return count;
}
public Map<String, Object> getData(String startDate, String endDate, String orderNo) {
Map<String, Object> config = Util.readProperties2Map("esteeLauderExcelExport", "export");
Assert.notEmpty(config, "esteeLauderExcelExport.properties文件读取配置为空请检查配置信息");
List<Map<String, Object>> dataList;
String condition = "";
if (StrUtil.isNotBlank(orderNo)) {
condition = " and " + Util.null2String(config.get("orderNo")) + " like '%" + orderNo.replace("%'", "''") + "'";
}
if (StrUtil.isNotBlank(startDate) && StrUtil.isNotBlank(endDate)) {
dataList = mapper.selectList(Util.null2String(config.get("tableName")),
startDate, endDate,
Util.null2String(config.get("createDate")),
condition);
} else {
dataList = mapper.selectList(Util.null2String(config.get("tableName")));
}
Object head = config.get("head");
Map<String, Object> result = new HashMap<>(16);
result.put("head", head);
if (CollectionUtil.isEmpty(dataList)) {
return result;
}
calculationCondition(dataList, config);
List<List<Map<String, Object>>> groupData = groupData(dataList, config);
List<Map<String, Object>> groupDataList = new ArrayList<>();
AtomicInteger n = new AtomicInteger(1);
for (int i = 0; i < groupData.size(); i++) {
List<Map<String, Object>> list = groupData.get(i);
int finalI = i;
list.forEach(item -> {
item.put("groupId", finalI);
item.put("no", n.getAndIncrement());
});
calculationOpenBill(list, config);
groupDataList.addAll(list);
}
// for (List<Map<String, Object>> list : groupData) {
// calculationOpenBill(list, config);
//
// groupDataList.addAll(list);
// }
result.put("body", groupDataList);
return result;
}
private void calculationOpenBill(List<Map<String, Object>> list, Map<String, Object> config) {
String orderTypeKey = Util.null2String(config.get("orderType"));
String finalOrderType = "";
for (Map<String, Object> item : list) {
String orderType = Util.null2String(item.get(orderTypeKey));
if (StrUtil.isNotBlank(finalOrderType)) {
if (!finalOrderType.equals(orderType)) {
throw new CustomerException("分组条件中存在不同流程数据,请检查分组逻辑以及分组条件组合逻辑是否保证分组正确!");
}
} else {
finalOrderType = orderType;
}
}
boolean flag = false;
String finalBgm = "";
for (Map<String, Object> item : list) {
String bgm = Util.null2String(item.get(Util.null2String(config.get("bgmKey"))));
if (StrUtil.isNotBlank(finalBgm)) {
if (!finalBgm.equals(bgm)) {
flag = true;
break;
}
} else {
finalBgm = bgm;
}
}
if (!flag) {
// 所有分组bgm都一样
if (finalBgm.equals("Y")) {
// 都过了bgm
for (Map<String, Object> item : list) {
item.put(Util.null2String(config.get("openBillKey")), "");
}
} else {
// 都没过bgm计算条件
calculationOpenBillN(list, config);
}
} else {
// 不全部都是y或者n
for (Map<String, Object> item : list) {
item.put(Util.null2String(config.get("openBillKey")), "全部订单总金额达到GM审批标准拆分后无法到达GM审批节点。");
}
}
}
private void calculationOpenBillN(List<Map<String, Object>> list, Map<String, Object> config) {
Map<String, Object> fristMap = list.get(0);
String orderType = Util.null2String(fristMap.get(Util.null2String(config.get("orderType"))));
Map<String, Object> condition = (Map<String, Object>) config.get("condition");
Map<String, Object> conditionInfo = (Map<String, Object>) condition.get(orderType);
if (Objects.isNull(conditionInfo)) {
return;
}
String id = Util.null2String(conditionInfo.get("id"));
ConditionEntity conditionEntity = mapper.selectCondition(id);
if (Objects.isNull(conditionEntity)) {
return;
}
List<ConditionDetail> conditionDetailList = conditionEntity.getList();
if (CollectionUtil.isEmpty(conditionDetailList)) {
return;
}
List<Boolean> booleanList = new ArrayList<>();
Map<String, Object> mapping = (Map<String, Object>) conditionInfo.get("mapping");
Map<String, Object> totalMap = new HashMap<>();
for (Map.Entry<String, Object> entry : mapping.entrySet()) {
String key = entry.getKey();
double totalValue = 0.0;
for (Map<String, Object> item : list) {
String value = Util.null2String(entry.getValue());
Object o = "";
if (StrUtil.isNotBlank(value)) {
try {
o = ScriptUtil.invokeScript(value, item);
} catch (JexlException e) {
log.error("执行脚本失败:=》" + e.getMessage());
}
}
try {
double v = Double.parseDouble(Util.null2String("".equals(Util.null2String(o)) ? null : Util.null2String(o), "0.0"));
totalValue += v;
} catch (Exception e) {
log.error("求和转换失败:" + JSON.toJSONString(entry));
log.error("item" + JSON.toJSONString(item));
throw new CustomerException("求和字段转化失败!", e);
}
}
totalMap.put(key, totalValue);
}
for (Map.Entry<String, Object> entry : totalMap.entrySet()) {
for (ConditionDetail conditionDetail : conditionDetailList) {
Integer conditionType = conditionDetail.getConditionType();
String value = Util.null2String(entry.getValue());
String conditionValue = conditionDetail.getConditionValue();
boolean b = this.compareCondition(conditionType, value, conditionValue);
booleanList.add(b);
}
}
boolean flag = false;
String conditionType = conditionEntity.getCondition();
if ("0".equals(conditionType)) {
// 或者
for (Boolean aBoolean : booleanList) {
if (aBoolean) {
flag = true;
break;
}
}
} else if ("1".equals(conditionType)) {
// 且
for (Boolean aBoolean : booleanList) {
if (!aBoolean) {
flag = true;
break;
}
}
}
// 拆单
if (flag) {
for (Map<String, Object> item : list) {
item.put(Util.null2String(config.get("openBillKey")), "全部订单总金额达到GM审批标准拆分后无法到达GM审批节点。");
}
} else {
for (Map<String, Object> item : list) {
item.put(Util.null2String(config.get("openBillKey")), "");
}
}
}
private boolean compareCondition(Integer conditionType, String value, String conditionValue) {
boolean res = false;
double valueNum = 0.0;
double conditionValueNum = 0.0;
if (conditionType < 5) {
valueNum = Double.parseDouble(value);
conditionValueNum = Double.parseDouble(conditionValue);
}
switch (conditionType) {
case 0:
if (conditionValueNum > valueNum) {
res = true;
}
break;
case 1:
if (conditionValueNum >= valueNum) {
res = true;
}
break;
case 2:
if (conditionValueNum < valueNum) {
res = true;
}
break;
case 3:
if (conditionValueNum <= valueNum) {
res = true;
}
break;
case 4:
if (conditionValueNum == valueNum) {
res = true;
}
break;
case 5:
if (!Objects.equals(conditionValue, "") && conditionValue.contains(value)) {
res = true;
}
break;
case 6:
if (Objects.equals(conditionValue, "")) {
res = true;
} else if (!conditionValue.contains(value)) {
res = true;
}
break;
case 7:
if (!Objects.equals(conditionValue, "") && conditionValue.equals(value)) {
res = true;
}
default:
break;
}
return res;
}
private void calculationCondition(List<Map<String, Object>> dataList, Map<String, Object> config) {
for (Map<String, Object> map : dataList) {
// 订单分类
String orderType = Util.null2String(map.get(Util.null2String(config.get("orderType"))));
// 订单用途
String orderUse = Util.null2String(map.get(Util.null2String(config.get("orderUse"))));
// shipTo
String shipTo = Util.null2String(map.get(Util.null2String(config.get("shipTo"))));
// 成本中心
String costCenter = Util.null2String(map.get(Util.null2String(config.get("costCenter"))));
// sku
String sku = Util.null2String(map.get(Util.null2String(config.get("sku"))));
String condition = "";
switch (orderType) {
case "2": {
// 内部领用
// orderUse + " " + shipTo + " " + costCenter + " " + sku
// condition = "订单用途:" + orderUse + " " + "ShipTo" + shipTo + " CostCenter" + costCenter + " sku" + sku;
condition = orderUse + " " + shipTo + "" + costCenter + "" + sku;
}
break;
case "1":
case "3":
case "4": {
// 第三方 + 柜台订单
// orderUse + ":" + shipTo + ":" + sku
// condition = "订单用途:" + orderUse + " " + "ShipTo" + shipTo + " sku" + sku + " 订单分类:" + orderType;
condition = orderUse + "" + shipTo + "" + sku + "" + orderType;
}
break;
default:
break;
}
map.put(Util.null2String(config.get("conditionKey")), condition);
}
}
private List<List<Map<String, Object>>> groupData(List<Map<String, Object>> dataList, Map<String, Object> config) {
// 根据condition进行分组
Map<String, List<Map<String, Object>>> typeMap =
dataList.stream()
.collect(Collectors.groupingBy(
item -> String.valueOf(
item.get(
Util.null2String(config.get("conditionKey"))
)
)
)
);
// 对每个type的数据进行日期分组
List<List<Map<String, Object>>> result = new ArrayList<>();
DateFormat dateFormat = new SimpleDateFormat(Util.null2String(config.get("createType")));
for (String type : typeMap.keySet()) {
List<Map<String, Object>> typeDataList = typeMap.get(type);
typeDataList.sort((o1, o2) -> {
try {
Date date1 = dateFormat.parse(o1.get(Util.null2String(config.get("createDate"))).toString());
Date date2 = dateFormat.parse(o2.get(Util.null2String(config.get("createDate"))).toString());
return date1.compareTo(date2);
} catch (ParseException e) {
log.error("日期格式化出错,排序失败!");
return 0;
}
});
Map<String, Object> baseData = typeDataList.get(0);
Date baseDate;
try {
baseDate = dateFormat.parse(baseData.get(Util.null2String(config.get("createDate"))).toString());
} catch (ParseException e) {
throw new CustomerException("日期转换异常!", e);
}
List<Map<String, Object>> groupList = new ArrayList<>();
groupList.add(baseData);
for (int i = 1; i < typeDataList.size(); i++) {
Map<String, Object> data = typeDataList.get(i);
Date date;
try {
date = dateFormat.parse(data.get(Util.null2String(config.get("createDate"))).toString());
} catch (ParseException e) {
throw new CustomerException("日期转换异常!", e);
}
if (date == null || baseDate == null) {
continue;
}
if (Math.abs(date.getTime() - baseDate.getTime()) <= 7 * 24 * 60 * 60 * 1000) {
groupList.add(data);
} else {
baseDate = date;
result.add(groupList);
groupList = new ArrayList<>();
groupList.add(data);
}
}
if (groupList.size() > 0) {
result.add(groupList);
}
}
return result;
}
}

View File

@ -1,30 +0,0 @@
package com.api.youhong.ai.yashilandai.openbill.service;
import aiyh.utils.Util;
import com.api.youhong.ai.yashilandai.openbill.mapper.OpenThenBillMapper;
import java.util.List;
import java.util.Map;
/**
* <h1></h1>
*
* <p>create: 2023/4/25 10:12</p>
*
* @author youHong.ai
*/
public class OpenThenBillService {
private final OpenThenBillMapper mapper = Util.getMapper(OpenThenBillMapper.class);
public Object getOpenBillListData() {
return null;
}
public List<Map<String, Object>> getData() {
List<Map<String, Object>> dataList = mapper.selectList();
return null;
}
}

View File

@ -0,0 +1,18 @@
package com.api.youhong.ai.yashilandai.openbill.util;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
/**
* <h1></h1>
*
* <p>create: 2023/4/19 10:48</p>
*
* @author youHong.ai
*/
@Getter
@Setter
@ToString
public class ExcelBody extends ExcelCell {
}

View File

@ -0,0 +1,23 @@
package com.api.youhong.ai.yashilandai.openbill.util;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
/**
* <h1></h1>
*
* <p>create: 2023/4/19 10:49</p>
*
* @author youHong.ai
*/
@Getter
@Setter
@ToString
public class ExcelCell {
/** 表头名称 */
private Object value;
/** 单元格格式 */
private IExcelCellStyleCreator cellStyle;
}

View File

@ -0,0 +1,20 @@
package com.api.youhong.ai.yashilandai.openbill.util;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
/**
* <h1>excel</h1>
*
* <p>create: 2023/4/19 10:46</p>
*
* @author youHong.ai
*/
@Getter
@Setter
@ToString
public class ExcelHead extends ExcelCell {
}

View File

@ -0,0 +1,135 @@
package com.api.youhong.ai.yashilandai.openbill.util;
import aiyh.utils.Util;
import aiyh.utils.tool.cn.hutool.core.collection.CollectionUtil;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* <h1>excel</h1>
*
* <p>create: 2023/4/19 10:39</p>
*
* @author youHong.ai
*/
public class ExcelPort {
public static void exportFile(String sheetName, List<ExcelRow> dataList,
OutputStream outputStream,
IExcelCellStyleCreator headStyle,
IExcelCellStyleCreator bodyStyle,
Map<Integer, CellStyle> headStyleMap,
Map<Integer, CellStyle> singularLine,
Map<Integer, CellStyle> evenNumberLine) {
SXSSFWorkbook workbook = new SXSSFWorkbook();
createSheet(sheetName, workbook, dataList, headStyle, bodyStyle, headStyleMap, singularLine, evenNumberLine);
// String excel = Util.getTempFilePath("excel", ".xlsx");
try {
workbook.write(outputStream);
// workbook.write(Files.newOutputStream(Paths.get(excel)));
// return new File(excel);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static String export(String sheetName, List<ExcelRow> dataList,
IExcelCellStyleCreator headStyle,
IExcelCellStyleCreator bodyStyle, Map<Integer, CellStyle> headStyleMap,
Map<Integer, CellStyle> singularLine,
Map<Integer, CellStyle> evenNumberLine) {
SXSSFWorkbook workbook = new SXSSFWorkbook();
createSheet(sheetName, workbook, dataList, headStyle, bodyStyle, headStyleMap, singularLine, evenNumberLine);
String excel = Util.getTempFilePath("excel", ".xlsx");
try {
workbook.write(Files.newOutputStream(Paths.get(excel)));
} catch (IOException e) {
throw new RuntimeException(e);
}
return excel;
}
public static String export(List<ExcelSheet> sheetList,
IExcelCellStyleCreator headStyle,
IExcelCellStyleCreator bodyStyle, Map<Integer, CellStyle> headStyleMap,
Map<Integer, CellStyle> singularLine,
Map<Integer, CellStyle> evenNumberLine) {
SXSSFWorkbook workbook = new SXSSFWorkbook();
for (ExcelSheet excelSheet : sheetList) {
createSheet(excelSheet.getSheetName(), workbook, excelSheet.getDataList(), headStyle, bodyStyle, headStyleMap, singularLine, evenNumberLine);
}
String excel = Util.getTempFilePath("excel", ".xlsx");
try {
workbook.write(Files.newOutputStream(Paths.get(excel)));
} catch (IOException e) {
throw new RuntimeException(e);
}
return excel;
}
private static void createSheet(String sheetName, SXSSFWorkbook wb, List<ExcelRow> dataList,
IExcelCellStyleCreator headStyle,
IExcelCellStyleCreator bodyStyle,
Map<Integer, CellStyle> headStyleMap,
Map<Integer, CellStyle> singularLine,
Map<Integer, CellStyle> evenNumberLine) {
SXSSFSheet sheet = wb.createSheet(sheetName);
createDate(sheet, wb, dataList, headStyle, bodyStyle, headStyleMap, singularLine, evenNumberLine);
}
private static void createDate(SXSSFSheet sheet, SXSSFWorkbook wb, List<ExcelRow> dataList,
IExcelCellStyleCreator headStyle,
IExcelCellStyleCreator bodyStyle,
Map<Integer, CellStyle> headStyleMap,
Map<Integer, CellStyle> singularLine,
Map<Integer, CellStyle> evenNumberLine) {
if (CollectionUtil.isEmpty(dataList) || dataList.size() < 1) {
return;
}
for (int i = 0; i < dataList.size(); i++) {
ExcelRow excelRow = dataList.get(i);
SXSSFRow row = sheet.createRow(i);
if (!Objects.isNull(excelRow.getRowHeight()) && excelRow.getRowHeight() > 0) {
row.setHeightInPoints(excelRow.getRowHeight());
}
List<ExcelCell> rowData = excelRow.getDataList();
for (int j = 0; j < rowData.size(); j++) {
ExcelCell cellValue = rowData.get(j);
SXSSFCell cell = row.createCell(j);
CellStyle style = null;
XSSFRichTextString text = new XSSFRichTextString(Util.null2String(cellValue.getValue()));
cell.setCellValue(text);
// sheet.trackAllColumnsForAutoSizing();
// sheet.autoSizeColumn(i);
if (i == 0) {
if (Objects.nonNull(headStyle)) {
style = headStyle.createStyle(wb, i, j, row, cell, sheet, headStyleMap, null);
}
} else {
if (Objects.nonNull(bodyStyle)) {
style = bodyStyle.createStyle(wb, i, j, row, cell, sheet, singularLine, evenNumberLine);
}
}
if (Objects.nonNull(style)) {
cell.setCellStyle(style);
}
}
}
}
}

View File

@ -0,0 +1,23 @@
package com.api.youhong.ai.yashilandai.openbill.util;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.util.List;
/**
* <h1></h1>
*
* <p>create: 2023/4/19 10:56</p>
*
* @author youHong.ai
*/
@Getter
@Setter
@ToString
public class ExcelRow {
private Float rowHeight;
private List<ExcelCell> dataList;
}

View File

@ -0,0 +1,22 @@
package com.api.youhong.ai.yashilandai.openbill.util;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.util.List;
/**
* <h1>excel</h1>
*
* <p>create: 2023/4/19 11:14</p>
*
* @author youHong.ai
*/
@Getter
@Setter
@ToString
public class ExcelSheet {
private String sheetName;
private List<ExcelRow> dataList;
}

View File

@ -0,0 +1,28 @@
package com.api.youhong.ai.yashilandai.openbill.util;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import java.util.Map;
/**
* <h1></h1>
*
* <p>create: 2023/4/19 13:53</p>
*
* @author youHong.ai
*/
@FunctionalInterface
public interface IExcelCellStyleCreator {
CellStyle createStyle(SXSSFWorkbook workbook,
Integer rowIndex,
Integer colIndex,
SXSSFRow row,
SXSSFCell cell,
SXSSFSheet sheet, Map<Integer, CellStyle> style2,
Map<Integer, CellStyle> style1);
}

View File

@ -756,7 +756,7 @@ public class DealWithMapping extends ToolUtil {
} else {
value = Util.null2String(mainMap.get(fieldName));
if ("".equals(value)) {
value = Util.null2String(detailMap.get(fieldNameLower));
value = Util.null2String(mainMap.get(fieldNameLower));
}
}

View File

@ -172,22 +172,19 @@ public class VoucherPayableNewAction extends SafeCusBaseAction {
}
headKeys = sortKey(headKeys);
for (String headKey : headKeys) {
sb.append(heads.get(headKey)).append("\t");
sb.append(Util.null2String(heads.get(headKey)).replace("&nbsp;", " ")).append("\t");
}
sb.deleteCharAt(sb.lastIndexOf("\t"));
sb.append("\r\n");
log.info("头写入的数据:" + sb);
// 写入借方信息
writeList(debit, sb);
log.info("debit写入的数据:" + sb);
// 写入贷方信息
writeList(creditSide, sb);
log.info("creditSide写入的数据:" + sb);
String filePath = getFilePath();
try {
OutputStreamWriter out = new OutputStreamWriter(
Files.newOutputStream(Paths.get(filePath)), StandardCharsets.UTF_8);
out.write(sb.toString());
out.write(sb.toString().replace("&nbsp;", " "));
out.close();
} catch (IOException e) {

View File

@ -84,7 +84,7 @@ public class VoucherPayableService {
StringBuilder voucherDetailBuilder = new StringBuilder();
List<List<VoucherItem>> voucherDetail = voucherData.getVoucherDetail();
for (List<VoucherItem> voucherItems : voucherDetail) {
voucherDetailBuilder.append(appendVoucherItems(voucherItems))
voucherDetailBuilder.append(appendVoucherItems(voucherItems).replace("&nbsp;", " "))
.append("\r\n");
}
String voucherDetailStr = voucherDetailBuilder.substring(0, voucherDetailBuilder.lastIndexOf("\r\n"));
@ -95,8 +95,8 @@ public class VoucherPayableService {
// ));
OutputStreamWriter out = new OutputStreamWriter(
Files.newOutputStream(Paths.get(filePath)), StandardCharsets.UTF_8);
out.write(voucherHeadStr);
out.write(voucherDetailStr);
out.write(voucherHeadStr.replace("&nbsp;", " "));
out.write(voucherDetailStr.replace("&nbsp;", " "));
out.close();
// writer.write(voucherHeadStr);
// writer.write(voucherDetailStr);
@ -118,7 +118,7 @@ public class VoucherPayableService {
List<VoucherItem> voucherItems = voucherDetail.get(i);
if (i == 0) {
for (VoucherItem voucherItem : voucherItems) {
voucherHeadBuilder.append(voucherItem.getName())
voucherHeadBuilder.append(voucherItem.getName().replace("&nbsp;", " "))
.append("\t");
}
voucherHeadBuilder = new StringBuilder(voucherHeadBuilder
@ -126,7 +126,7 @@ public class VoucherPayableService {
}
for (VoucherItem voucherItem : voucherItems) {
voucherHeadBuilder.append(voucherItem.getValue())
voucherHeadBuilder.append(Util.null2String(voucherItem.getValue()).replace("&nbsp;", " "))
.append("\t");
}
if (i < voucherDetail.size() - 1) {
@ -142,7 +142,7 @@ public class VoucherPayableService {
try {
OutputStreamWriter out = new OutputStreamWriter(
Files.newOutputStream(Paths.get(filePath)), StandardCharsets.UTF_8);
out.write(voucherHaredStr);
out.write(voucherHaredStr.replace("&nbsp;", " "));
out.close();
// BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
// Files.newOutputStream(Paths.get(filePath))
@ -186,7 +186,7 @@ public class VoucherPayableService {
// ));
OutputStreamWriter out = new OutputStreamWriter(
Files.newOutputStream(Paths.get(filePath)), StandardCharsets.UTF_8);
out.write(voucherHeadStr);
out.write(voucherHeadStr.replace("&nbsp;", " "));
// writer.write(voucherHeadStr);
// writer.flush();
// writer.close();

View File

@ -88,12 +88,12 @@ public class CaElectronicSignatureAction extends SafeCusBaseAction {
}
Map<String, Object> responseMap = responeVo.getResponseMap();
String documentNo = Util.null2String(responseMap.get("document_no"));
String pdf = Util.null2String(responseMap.get("pdf"));
String pdf = Util.null2String(responseMap.get("ofd"));
InputStream inputStream = base64ContentToFile(pdf);
String docCategorys = Util.getDocCategorysByTable(String.valueOf(workflowId), signFileField, billTable);
String[] docCategoryArr = docCategorys.split(",");
int docCategory = Integer.parseInt(docCategoryArr[docCategoryArr.length - 1]);
int docId = Util.createDoc(Strings.isNullOrEmpty(docName.get()) ? "sign.pdf" : docName.get(), docCategory, inputStream, 1);
int docId = Util.createDoc(Strings.isNullOrEmpty(docName.get()) ? "sign.ofd" : docName.get(), docCategory, inputStream, 1);
docName.remove();
writeBack(documentNo, billTable, requestId, docId);
} catch (Exception e) {

View File

@ -9,6 +9,7 @@ import weaver.file.ImageFileManager;
import weaver.xiao.commons.config.interfacies.CusInterfaceGetValue;
import weaver.youhong.ai.intellectualproperty.action.CaElectronicSignatureAction;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Base64;
import java.util.Map;
@ -35,9 +36,14 @@ public class FileToBase64CusGetValue implements CusInterfaceGetValue {
}
DocImageInfo docImageInfo = Util.selectImageInfoByDocId(currentValue);
InputStream inputStream = ImageFileManager.getInputStreamById(docImageInfo.getImageFileId());
byte[] src = new byte[inputStream.available()];
inputStream.read(src);
String fileBase64 = Base64.getEncoder().encodeToString(src);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
byte[] data = outputStream.toByteArray();
String fileBase64 = Base64.getEncoder().encodeToString(data);
CaElectronicSignatureAction.docName.set(docImageInfo.getImageFileName());
return fileBase64;
} catch (Exception e) {

View File

@ -0,0 +1,112 @@
#导出设置
export.tableName=v_yscd
#订单分类
export.orderType=ddlx
#订单用途
export.orderUse=ddyt
# 点单编号
export.orderNo=ddbh
#shipto
export.shipTo=shipto
# 疑似拆单
export.openBillKey=openBill
# 日期时间字段
export.createDate=createdate
# 日期格式化类型
export.createType=yyyy-MM-dd
#成本中心
export.costCenter=cbzxyh
# 条件key
export.conditionKey=condition
#流水号-requestId
export.requestId=lcid
# bgm字段
export.bgmKey=bgm
# 条件参数id配置
export.condition.1.id=42
export.condition.2.id=42
export.condition.3.id=42
export.condition.4.id=42
#条件参数字段映射关系
export.condition.1.mapping.giftsQty=sl
export.condition.1.mapping.giftsTotalCost=kxpmxzlsj
export.condition.2.mapping.giftsQty=sl
export.condition.2.mapping.giftsTotalCost=kxpmxzlsj
export.condition.3.mapping.giftsQty=sl
export.condition.3.mapping.giftsTotalCost=kxpmxzlsj
export.condition.4.mapping.giftsQty=sl
export.condition.4.mapping.giftsTotalCost=kxpmxzlsj
#sku
export.sku=sku
#导出表头设置
export.head.title[0]=序号
export.head.field[0]=no
export.head.title[1]=分组编号
export.head.field[1]=groupId
export.head.title[2]=ID
export.head.field[2]=id
export.head.title[3]=条件
export.head.field[3]=condition
export.head.title[4]=疑似拆单
export.head.field[4]=openBill
export.head.title[5]=流水号
export.head.field[5]=lcid
export.head.title[6]=shipTo
export.head.field[6]=shipto
export.head.title[7]=推送时间
export.head.field[7]=insertTime
export.head.title[8]=审批开始时间
export.head.field[8]=createdate
export.head.title[9]=申请提交时间
export.head.field[9]=sqtjrq
export.head.title[10]=审批开始时间
export.head.field[10]=LASTOPERATEDATE
export.head.title[11]=收方限制
export.head.field[11]=ddlxms
export.head.title[12]=部门团队
export.head.field[12]=SPART
export.head.title[13]=品牌部门
export.head.field[13]=yjpp
export.head.title[14]=订单编号
export.head.field[14]=ddbh
export.head.title[15]=订单说明
export.head.field[15]=ddsm
export.head.title[16]=备注
export.head.field[16]=bz
export.head.title[17]=成本中心-sap
export.head.field[17]=KOSTL
export.head.title[18]=成本中心-用户
export.head.field[18]=cbzxyh
export.head.title[19]=财务科目
export.head.field[19]=cwkm
export.head.title[20]=审批开始时间
export.head.field[20]=LASTOPERATEDATE
export.head.title[21]=活动编号
export.head.field[21]=hdbh
export.head.title[22]=businessKey
export.head.field[22]=businesskey
export.head.title[23]=申请人
export.head.field[23]=SQRRLZY
export.head.title[24]=订单类型
export.head.field[24]=AUART
export.head.title[25]=订单用途
export.head.field[25]=VKAUS
export.head.title[26]=收货人
export.head.field[26]=KUNNRSHIPTO
export.head.title[27]=收货人地址
export.head.field[27]=shdz
export.head.title[28]=收货编号
export.head.field[28]=hwbh
export.head.title[29]=收货类型
export.head.field[29]=fl
export.head.title[30]=收货中文名
export.head.field[30]=ZWMS
export.head.title[31]=数量
export.head.field[31]=SL
export.head.title[32]=零售总额
export.head.field[32]=kxpmxzlsj
export.head.title[33]=订单分类
export.head.field[33]=ddlx
export.head.title[34]=gbm
export.head.field[34]=bgm

View File

@ -1,7 +1,10 @@
package com.api.aiyh_pcn.common_fadada.contraller;
import aiyh.utils.Util;
import com.alibaba.fastjson.JSON;
import com.api.aiyh_pcn.common_fadada.service.CommonFaService;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import org.apache.log4j.Logger;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
@ -20,15 +23,35 @@ import java.util.Map;
@Path("/common_fadada/callback")
public class CommonFaCallbackController {
@Path("/dealers/callback")
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public String dealersCallback(@RequestBody Map<String, Object> params) {
Map<String, Object> result = new HashMap<>();
result.put("code", 200);
result.put("msg", "操作成功!");
return JSON.toJSONString(result);
}
private final CommonFaService service = new CommonFaService();
private final Logger log = Util.getLogger();
@Path("/dealers/callback")
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public String dealersCallback(@RequestBody Map<String, Object> params) {
Map<String, Object> result = new HashMap<>();
result.put("code", 200);
result.put("msg", "操作成功!");
return JSON.toJSONString(result);
}
@Path("/submit/callback")
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public String submitCallback(@RequestBody Map<String, Object> params) {
Map<String, Object> result = new HashMap<>();
result.put("code", 200);
result.put("msg", "操作成功!");
try {
service.submitCallback(params);
} catch (Exception e) {
log.error("流程回调处理失败!" + Util.getErrString(e));
}
return JSON.toJSONString(result);
}
}

Some files were not shown because too many files have changed in this diff Show More