mirror of https://github.com/longtai-cn/hippo4j
# Conflicts: # hippo4j-config/src/test/java/cn/hippo4j/config/toolkit/Md5ConfigUtilTest.javapull/804/head
commit
1916185f26
@ -0,0 +1,130 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
~ contributor license agreements. See the NOTICE file distributed with
|
||||||
|
~ this work for additional information regarding copyright ownership.
|
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
~ (the "License"); you may not use this file except in compliance with
|
||||||
|
~ the License. You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!DOCTYPE module PUBLIC
|
||||||
|
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
|
||||||
|
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
|
||||||
|
<module name="Checker">
|
||||||
|
<module name="NewlineAtEndOfFile"/>
|
||||||
|
<module name="RegexpSingleline">
|
||||||
|
<property name="format" value="printStackTrace"/>
|
||||||
|
<property name="message" value="Prohibit invoking printStackTrace in source code !"/>
|
||||||
|
</module>
|
||||||
|
<module name="TreeWalker">
|
||||||
|
<module name="AvoidStarImport">
|
||||||
|
<property name="excludes" value="java.io,java.net,java.lang.Math"/>
|
||||||
|
<property name="allowClassImports" value="false"/>
|
||||||
|
<property name="allowStaticMemberImports" value="true"/>
|
||||||
|
</module>
|
||||||
|
<module name="IllegalImport"/>
|
||||||
|
<module name="RedundantImport"/>
|
||||||
|
<module name="UnusedImports"/>
|
||||||
|
<module name="JavadocType">
|
||||||
|
<property name="allowUnknownTags" value="true"/>
|
||||||
|
<property name="allowMissingParamTags" value="true"/>
|
||||||
|
<message key="javadoc.missing" value="Class Comments: Missing Javadoc Comments"/>
|
||||||
|
</module>
|
||||||
|
<!-- Do not scan method annotations for now -->
|
||||||
|
<!--<module name="JavadocMethod">
|
||||||
|
<property name="tokens" value="METHOD_DEF"/>
|
||||||
|
<property name="allowMissingPropertyJavadoc" value="true"/>
|
||||||
|
<message key="javadoc.missing" value="Method Comments: Missing Javadoc Comments"/>
|
||||||
|
</module>-->
|
||||||
|
<module name="LocalFinalVariableName"/>
|
||||||
|
<module name="LocalVariableName"/>
|
||||||
|
<module name="PackageName">
|
||||||
|
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$" />
|
||||||
|
</module>
|
||||||
|
<module name="StaticVariableName"/>
|
||||||
|
<module name="TypeName"/>
|
||||||
|
<module name="MemberName"/>
|
||||||
|
<module name="MethodName"/>
|
||||||
|
<module name="ParameterName "/>
|
||||||
|
<module name="ConstantName"/>
|
||||||
|
<module name="ArrayTypeStyle"/>
|
||||||
|
<module name="UpperEll"/>
|
||||||
|
<module name="LineLength">
|
||||||
|
<property name="max" value="200"/>
|
||||||
|
</module>
|
||||||
|
<module name="MethodLength">
|
||||||
|
<property name="tokens" value="METHOD_DEF"/>
|
||||||
|
<property name="max" value="150"/>
|
||||||
|
</module>
|
||||||
|
<module name="ParameterNumber">
|
||||||
|
<property name="max" value="5"/>
|
||||||
|
<property name="ignoreOverriddenMethods" value="true"/>
|
||||||
|
<property name="tokens" value="METHOD_DEF"/>
|
||||||
|
</module>
|
||||||
|
<module name="MethodParamPad"/>
|
||||||
|
<module name="TypecastParenPad"/>
|
||||||
|
<module name="NoWhitespaceAfter"/>
|
||||||
|
<module name="NoWhitespaceBefore"/>
|
||||||
|
<module name="OperatorWrap"/>
|
||||||
|
<module name="ParenPad"/>
|
||||||
|
<module name="WhitespaceAfter"/>
|
||||||
|
<module name="WhitespaceAround"/>
|
||||||
|
<module name="ModifierOrder"/>
|
||||||
|
<module name="RedundantModifier"/>
|
||||||
|
<module name="AvoidNestedBlocks"/>
|
||||||
|
<module name="EmptyBlock"/>
|
||||||
|
<module name="LeftCurly"/>
|
||||||
|
<module name="NeedBraces"/>
|
||||||
|
<module name="RightCurly"/>
|
||||||
|
<module name="EmptyStatement"/>
|
||||||
|
<module name="EqualsHashCode"/>
|
||||||
|
<module name="IllegalInstantiation"/>
|
||||||
|
<module name="InnerAssignment"/>
|
||||||
|
<module name="MagicNumber">
|
||||||
|
<property name="ignoreNumbers" value="0, 1, 2"/>
|
||||||
|
<property name="ignoreAnnotation" value="true"/>
|
||||||
|
<property name="ignoreHashCodeMethod" value="true"/>
|
||||||
|
<property name="ignoreFieldDeclaration" value="true"/>
|
||||||
|
</module>
|
||||||
|
<module name="MissingSwitchDefault"/>
|
||||||
|
<module name="SimplifyBooleanExpression"/>
|
||||||
|
<module name="SimplifyBooleanReturn"/>
|
||||||
|
<module name="FinalClass"/>
|
||||||
|
<module name="InterfaceIsType"/>
|
||||||
|
<module name="VisibilityModifier">
|
||||||
|
<property name="packageAllowed" value="true"/>
|
||||||
|
<property name="protectedAllowed" value="true"/>
|
||||||
|
</module>
|
||||||
|
<module name="StringLiteralEquality"/>
|
||||||
|
<module name="NestedForDepth">
|
||||||
|
<property name="max" value="3"/>
|
||||||
|
</module>
|
||||||
|
<module name="NestedIfDepth">
|
||||||
|
<property name="max" value="4"/>
|
||||||
|
</module>
|
||||||
|
<module name="UncommentedMain">
|
||||||
|
<property name="excludedClasses" value=".*Application$"/>
|
||||||
|
</module>
|
||||||
|
<module name="Regexp">
|
||||||
|
<property name="format" value="System\.out\.println"/>
|
||||||
|
<property name="illegalPattern" value="true"/>
|
||||||
|
</module>
|
||||||
|
<module name="ReturnCount">
|
||||||
|
<property name="max" value="4"/>
|
||||||
|
</module>
|
||||||
|
<module name="NestedTryDepth ">
|
||||||
|
<property name="max" value="4"/>
|
||||||
|
</module>
|
||||||
|
<module name="SuperFinalize"/>
|
||||||
|
<module name="SuperClone"/>
|
||||||
|
</module>
|
||||||
|
</module>
|
@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
~ Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
~ contributor license agreements. See the NOTICE file distributed with
|
||||||
|
~ this work for additional information regarding copyright ownership.
|
||||||
|
~ The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
~ (the "License"); you may not use this file except in compliance with
|
||||||
|
~ the License. You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!DOCTYPE suppressions PUBLIC
|
||||||
|
"-//Puppy Crawl//DTD Suppressions 1.1//EN"
|
||||||
|
"http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
|
||||||
|
<suppressions>
|
||||||
|
<suppress checks="MagicNumber" files="ResizableCapacityLinkedBlockingQueue.java"/>
|
||||||
|
<suppress checks="InnerAssignment" files="ResizableCapacityLinkedBlockingQueue.java"/>
|
||||||
|
<suppress checks="StaticVariableName" files="ApplicationContextHolder.java"/>
|
||||||
|
<suppress checks="StaticVariableName" files="JacksonHandler.java"/>
|
||||||
|
<suppress checks="MagicNumber" files="ByteConvertUtil.java"/>
|
||||||
|
</suppressions>
|
@ -1,7 +0,0 @@
|
|||||||
---
|
|
||||||
sidebar_position: 2
|
|
||||||
---
|
|
||||||
|
|
||||||
# 阻塞队列自定义
|
|
||||||
|
|
||||||
同拒绝策略自定义。
|
|
@ -0,0 +1,45 @@
|
|||||||
|
---
|
||||||
|
sidebar_position: 4
|
||||||
|
---
|
||||||
|
|
||||||
|
# 参数默认配置
|
||||||
|
|
||||||
|
曾有多名小伙伴反馈说,项目中线程池一多,配置文件中配置就显得很臃肿。为此 hippo4j-config 开发出了动态线程池默认配置。
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
spring:
|
||||||
|
dynamic:
|
||||||
|
thread-pool:
|
||||||
|
default-executor:
|
||||||
|
core-pool-size: 4
|
||||||
|
maximum-pool-size: 6
|
||||||
|
blocking-queue: ResizableCapacityLinkedBlockingQueue
|
||||||
|
queue-capacity: 1024
|
||||||
|
execute-time-out: 1000
|
||||||
|
keep-alive-time: 9999
|
||||||
|
rejected-handler: AbortPolicy
|
||||||
|
active-alarm: 90
|
||||||
|
capacity-alarm: 85
|
||||||
|
alarm: true
|
||||||
|
allow-core-thread-time-out: true
|
||||||
|
notify:
|
||||||
|
interval: 5
|
||||||
|
receives: chen.ma
|
||||||
|
executors:
|
||||||
|
- thread-pool-id: message-produce
|
||||||
|
- thread-pool-id: message-consume
|
||||||
|
core-pool-size: 80
|
||||||
|
maximum-pool-size: 100
|
||||||
|
execute-time-out: 1000
|
||||||
|
notify:
|
||||||
|
interval: 6
|
||||||
|
receives: chen.ma
|
||||||
|
```
|
||||||
|
|
||||||
|
`spring.dynamic.thread-pool.executors` 层级下,仅需要配置 `thread-pool-id`,其余配置从 `spring.dynamic.thread-pool.default-executor` 读取。
|
||||||
|
|
||||||
|
如果 `spring.dynamic.thread-pool.executors` 下配置和 `spring.dynamic.thread-pool.default-executor` 冲突,以前者为主。
|
||||||
|
|
||||||
|
通过该自定义配置方式,可减少大量重复线程池参数配置项,提高核心配置简洁度。
|
||||||
|
|
||||||
|
提示:`spring.dynamic.thread-pool.default-executor` 层级下参数,不提供动态刷新功能。
|
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.hippo4j.auth.config;
|
||||||
|
|
||||||
|
import cn.hippo4j.auth.filter.RewriteUserInfoApiFilter;
|
||||||
|
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class FilterConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public FilterRegistrationBean<RewriteUserInfoApiFilter> userInfoApiFilterRegistrationBean() {
|
||||||
|
FilterRegistrationBean<RewriteUserInfoApiFilter> registration = new FilterRegistrationBean<>();
|
||||||
|
registration.setFilter(new RewriteUserInfoApiFilter());
|
||||||
|
registration.addUrlPatterns("/*");
|
||||||
|
return registration;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.hippo4j.auth.filter;
|
||||||
|
|
||||||
|
import cn.hippo4j.auth.toolkit.AuthUtil;
|
||||||
|
|
||||||
|
import javax.servlet.*;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When anonymous login is enabled, an error will be reported when viewing the current user information.
|
||||||
|
* Modify the URI to query the default administrator information.
|
||||||
|
*
|
||||||
|
* before:hippo4j/v1/cs/auth/users/info or hippo4j/v1/cs/auth/users/info/xxx
|
||||||
|
* after:hippo4j/v1/cs/auth/users/info/admin
|
||||||
|
*/
|
||||||
|
public class RewriteUserInfoApiFilter implements Filter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
|
||||||
|
boolean enableAuthentication = AuthUtil.enableAuthentication;
|
||||||
|
HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
|
||||||
|
String path = httpRequest.getRequestURI();
|
||||||
|
if (!enableAuthentication && path.contains("users/info")) {
|
||||||
|
httpRequest.getRequestDispatcher("/hippo4j/v1/cs/auth/users/info/admin").forward(servletRequest, servletResponse);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
filterChain.doFilter(servletRequest, servletResponse);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.hippo4j.auth.toolkit;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class AuthUtil {
|
||||||
|
|
||||||
|
public static boolean enableAuthentication;
|
||||||
|
|
||||||
|
@Value("${hippo4j.core.auth.enabled:true}")
|
||||||
|
public void setEnableAuthentication(boolean enabled) {
|
||||||
|
AuthUtil.enableAuthentication = enabled;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.hippo4j.common.constant;
|
||||||
|
|
||||||
|
public class ConfigModifyTypeConstants {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thread pool manager change
|
||||||
|
*/
|
||||||
|
public static final int THREAD_POOL_MANAGER = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thread pool instance change
|
||||||
|
*/
|
||||||
|
public static final int THREAD_POOL_INSTANCE = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Web thread pool change
|
||||||
|
*/
|
||||||
|
public static final int WEB_THREAD_POOL = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapter thread pool change
|
||||||
|
*/
|
||||||
|
public static final int ADAPTER_THREAD_POOL = 4;
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.hippo4j.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Http header constants.
|
||||||
|
*/
|
||||||
|
public interface HttpHeaderConstants {
|
||||||
|
|
||||||
|
String CLIENT_VERSION_HEADER = "Client-Version";
|
||||||
|
|
||||||
|
String USER_AGENT_HEADER = "User-Agent";
|
||||||
|
|
||||||
|
String REQUEST_SOURCE_HEADER = "Request-Source";
|
||||||
|
|
||||||
|
String CONTENT_TYPE = "Content-Type";
|
||||||
|
|
||||||
|
String CONTENT_LENGTH = "Content-Length";
|
||||||
|
|
||||||
|
String ACCEPT_CHARSET = "Accept-Charset";
|
||||||
|
|
||||||
|
String ACCEPT_ENCODING = "Accept-Encoding";
|
||||||
|
|
||||||
|
String CONTENT_ENCODING = "Content-Encoding";
|
||||||
|
|
||||||
|
String CONNECTION = "Requester";
|
||||||
|
|
||||||
|
String REQUEST_ID = "RequestId";
|
||||||
|
|
||||||
|
String REQUEST_MODULE = "Request-Module";
|
||||||
|
}
|
@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.hippo4j.common.constant;
|
||||||
|
|
||||||
|
import cn.hippo4j.common.toolkit.StringUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Http media type.
|
||||||
|
*
|
||||||
|
* @author Rongzhen Yan
|
||||||
|
*/
|
||||||
|
public final class HttpMediaType {
|
||||||
|
|
||||||
|
public static final String APPLICATION_ATOM_XML = "application/atom+xml";
|
||||||
|
|
||||||
|
public static final String APPLICATION_FORM_URLENCODED = "application/x-www-form-urlencoded;charset=UTF-8";
|
||||||
|
|
||||||
|
public static final String APPLICATION_OCTET_STREAM = "application/octet-stream";
|
||||||
|
|
||||||
|
public static final String APPLICATION_SVG_XML = "application/svg+xml";
|
||||||
|
|
||||||
|
public static final String APPLICATION_XHTML_XML = "application/xhtml+xml";
|
||||||
|
|
||||||
|
public static final String APPLICATION_XML = "application/xml;charset=UTF-8";
|
||||||
|
|
||||||
|
public static final String APPLICATION_JSON = "application/json;charset=UTF-8";
|
||||||
|
|
||||||
|
public static final String MULTIPART_FORM_DATA = "multipart/form-data;charset=UTF-8";
|
||||||
|
|
||||||
|
public static final String TEXT_HTML = "text/html;charset=UTF-8";
|
||||||
|
|
||||||
|
public static final String TEXT_PLAIN = "text/plain;charset=UTF-8";
|
||||||
|
|
||||||
|
private HttpMediaType(String type, String charset) {
|
||||||
|
this.type = type;
|
||||||
|
this.charset = charset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* content type.
|
||||||
|
*/
|
||||||
|
private final String type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* content type charset.
|
||||||
|
*/
|
||||||
|
private final String charset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the given String contentType into a {@code MediaType} object.
|
||||||
|
*
|
||||||
|
* @param contentType mediaType
|
||||||
|
* @return MediaType
|
||||||
|
*/
|
||||||
|
public static HttpMediaType valueOf(String contentType) {
|
||||||
|
if (StringUtil.isEmpty(contentType)) {
|
||||||
|
throw new IllegalArgumentException("MediaType must not be empty");
|
||||||
|
}
|
||||||
|
String[] values = contentType.split(";");
|
||||||
|
String charset = Constants.ENCODE;
|
||||||
|
for (String value : values) {
|
||||||
|
if (value.startsWith("charset=")) {
|
||||||
|
charset = value.substring("charset=".length());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new HttpMediaType(values[0], charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use the given contentType and charset to assemble into a {@code MediaType} object.
|
||||||
|
*
|
||||||
|
* @param contentType contentType
|
||||||
|
* @param charset charset
|
||||||
|
* @return MediaType
|
||||||
|
*/
|
||||||
|
public static HttpMediaType valueOf(String contentType, String charset) {
|
||||||
|
if (StringUtil.isEmpty(contentType)) {
|
||||||
|
throw new IllegalArgumentException("MediaType must not be empty");
|
||||||
|
}
|
||||||
|
String[] values = contentType.split(";");
|
||||||
|
return new HttpMediaType(values[0], StringUtil.isEmpty(charset) ? Constants.ENCODE : charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCharset() {
|
||||||
|
return charset;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return type + ";charset=" + charset;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.hippo4j.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Http method constants.
|
||||||
|
*
|
||||||
|
* @author Rongzhen Yan
|
||||||
|
*/
|
||||||
|
public class HttpMethod {
|
||||||
|
|
||||||
|
public static final String GET = "GET";
|
||||||
|
|
||||||
|
public static final String HEAD = "HEAD";
|
||||||
|
|
||||||
|
public static final String POST = "POST";
|
||||||
|
|
||||||
|
public static final String PUT = "PUT";
|
||||||
|
|
||||||
|
public static final String PATCH = "PATCH";
|
||||||
|
|
||||||
|
public static final String DELETE = "DELETE";
|
||||||
|
|
||||||
|
public static final String OPTIONS = "OPTIONS";
|
||||||
|
|
||||||
|
public static final String TRACE = "TRACE";
|
||||||
|
}
|
@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.hippo4j.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Http response code.
|
||||||
|
*
|
||||||
|
* @author Rongzhen Yan
|
||||||
|
*/
|
||||||
|
public interface HttpResponseCode {
|
||||||
|
|
||||||
|
int SC_CONTINUE = 100;
|
||||||
|
|
||||||
|
int SC_SWITCHING_PROTOCOLS = 101;
|
||||||
|
|
||||||
|
int SC_OK = 200;
|
||||||
|
|
||||||
|
int SC_CREATED = 201;
|
||||||
|
|
||||||
|
int SC_ACCEPTED = 202;
|
||||||
|
|
||||||
|
int SC_NON_AUTHORITATIVE_INFORMATION = 203;
|
||||||
|
|
||||||
|
int SC_NO_CONTENT = 204;
|
||||||
|
|
||||||
|
int SC_RESET_CONTENT = 205;
|
||||||
|
|
||||||
|
int SC_PARTIAL_CONTENT = 206;
|
||||||
|
|
||||||
|
int SC_MULTIPLE_CHOICES = 300;
|
||||||
|
|
||||||
|
int SC_MOVED_PERMANENTLY = 301;
|
||||||
|
|
||||||
|
int SC_MOVED_TEMPORARILY = 302;
|
||||||
|
|
||||||
|
int SC_FOUND = 302;
|
||||||
|
|
||||||
|
int SC_SEE_OTHER = 303;
|
||||||
|
|
||||||
|
int SC_NOT_MODIFIED = 304;
|
||||||
|
|
||||||
|
int SC_USE_PROXY = 305;
|
||||||
|
|
||||||
|
int SC_TEMPORARY_REDIRECT = 307;
|
||||||
|
|
||||||
|
int SC_BAD_REQUEST = 400;
|
||||||
|
|
||||||
|
int SC_UNAUTHORIZED = 401;
|
||||||
|
|
||||||
|
int SC_PAYMENT_REQUIRED = 402;
|
||||||
|
|
||||||
|
int SC_FORBIDDEN = 403;
|
||||||
|
|
||||||
|
int SC_NOT_FOUND = 404;
|
||||||
|
|
||||||
|
int SC_METHOD_NOT_ALLOWED = 405;
|
||||||
|
|
||||||
|
int SC_NOT_ACCEPTABLE = 406;
|
||||||
|
|
||||||
|
int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
|
||||||
|
|
||||||
|
int SC_REQUEST_TIMEOUT = 408;
|
||||||
|
|
||||||
|
int SC_CONFLICT = 409;
|
||||||
|
|
||||||
|
int SC_GONE = 410;
|
||||||
|
|
||||||
|
int SC_LENGTH_REQUIRED = 411;
|
||||||
|
|
||||||
|
int SC_PRECONDITION_FAILED = 412;
|
||||||
|
|
||||||
|
int SC_REQUEST_ENTITY_TOO_LARGE = 413;
|
||||||
|
|
||||||
|
int SC_REQUEST_URI_TOO_LONG = 414;
|
||||||
|
|
||||||
|
int SC_UNSUPPORTED_MEDIA_TYPE = 415;
|
||||||
|
|
||||||
|
int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
|
||||||
|
|
||||||
|
int SC_EXPECTATION_FAILED = 417;
|
||||||
|
|
||||||
|
int SC_INTERNAL_SERVER_ERROR = 500;
|
||||||
|
|
||||||
|
int SC_NOT_IMPLEMENTED = 501;
|
||||||
|
|
||||||
|
int SC_BAD_GATEWAY = 502;
|
||||||
|
|
||||||
|
int SC_SERVICE_UNAVAILABLE = 503;
|
||||||
|
|
||||||
|
int SC_GATEWAY_TIMEOUT = 504;
|
||||||
|
|
||||||
|
int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.hippo4j.common.enums;
|
||||||
|
|
||||||
|
public enum VerifyEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* unVerify
|
||||||
|
*/
|
||||||
|
TO_VERIFY(0, "待审核"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* accept
|
||||||
|
*/
|
||||||
|
VERIFY_ACCEPT(1, "审核通过"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* reject
|
||||||
|
*/
|
||||||
|
VERIFY_REJECT(2, "审核拒绝"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* invalid
|
||||||
|
*/
|
||||||
|
VERIFY_INVALID(3, "失效");
|
||||||
|
|
||||||
|
private final Integer verifyStatus;
|
||||||
|
|
||||||
|
private final String desc;
|
||||||
|
|
||||||
|
VerifyEnum(Integer verifyStatus, String desc) {
|
||||||
|
this.verifyStatus = verifyStatus;
|
||||||
|
this.desc = desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDesc() {
|
||||||
|
return this.desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getVerifyStatus() {
|
||||||
|
return this.verifyStatus;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.hippo4j.common.toolkit;
|
||||||
|
|
||||||
|
import cn.hippo4j.common.web.exception.IllegalException;
|
||||||
|
import com.github.dozermapper.core.DozerBeanMapperBuilder;
|
||||||
|
import com.github.dozermapper.core.Mapper;
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
|
||||||
|
import java.beans.IntrospectionException;
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bean util.
|
||||||
|
*/
|
||||||
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
|
public class BeanUtil {
|
||||||
|
|
||||||
|
protected static Mapper BEAN_MAPPER_BUILDER;
|
||||||
|
|
||||||
|
static {
|
||||||
|
BEAN_MAPPER_BUILDER = DozerBeanMapperBuilder.buildDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, S> T convert(S source, Class<T> clazz) {
|
||||||
|
return Optional.ofNullable(source)
|
||||||
|
.map(each -> BEAN_MAPPER_BUILDER.map(each, clazz))
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, S> T convert(S source, T target) {
|
||||||
|
Optional.ofNullable(source)
|
||||||
|
.ifPresent(each -> BEAN_MAPPER_BUILDER.map(each, target));
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, S> List<T> convert(List<S> sources, Class<T> clazz) {
|
||||||
|
return Optional.ofNullable(sources)
|
||||||
|
.map(each -> {
|
||||||
|
List<T> targetList = new ArrayList<T>(each.size());
|
||||||
|
each.forEach(item -> targetList.add(BEAN_MAPPER_BUILDER.map(item, clazz)));
|
||||||
|
return targetList;
|
||||||
|
})
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, S> Set<T> convert(Set<S> sources, Class<T> clazz) {
|
||||||
|
return Optional.ofNullable(sources)
|
||||||
|
.map(each -> {
|
||||||
|
Set<T> targetSize = new HashSet<T>(each.size());
|
||||||
|
each.forEach(item -> targetSize.add(BEAN_MAPPER_BUILDER.map(item, clazz)));
|
||||||
|
return targetSize;
|
||||||
|
})
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T mapToBean(Map<String, Object> map, Class<T> clazz, boolean toCamelCase) {
|
||||||
|
if (clazz == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
T newInstance = clazz.newInstance();
|
||||||
|
return mapToBean(map, newInstance, toCamelCase);
|
||||||
|
} catch (InstantiationException | IllegalAccessException e) {
|
||||||
|
throw new IllegalException("do not create instance for " + clazz.getName(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* map to bean
|
||||||
|
*
|
||||||
|
* @param map map
|
||||||
|
* @param bean obj bean
|
||||||
|
* @param toCamelCase format to camel case
|
||||||
|
* @param <T> bean type
|
||||||
|
* @return T
|
||||||
|
*/
|
||||||
|
public static <T> T mapToBean(Map<String, Object> map, T bean, boolean toCamelCase) {
|
||||||
|
if (bean == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (map.isEmpty()) {
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
Class<?> clazz = bean.getClass();
|
||||||
|
map.forEach((s, o) -> {
|
||||||
|
String name = toCamelCase ? StringUtil.toCamelCase(s, StringUtil.UNDERLINE) : s;
|
||||||
|
Method method = setter(clazz, name);
|
||||||
|
if (method != null) {
|
||||||
|
ReflectUtil.invoke(bean, method, o);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getter for properties
|
||||||
|
*
|
||||||
|
* @param o obj
|
||||||
|
* @param propertiesName name
|
||||||
|
* @return Method for get
|
||||||
|
*/
|
||||||
|
public static Method getter(Class<?> o, String propertiesName) {
|
||||||
|
if (o == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
PropertyDescriptor descriptor = new PropertyDescriptor(propertiesName, o);
|
||||||
|
return descriptor.getReadMethod();
|
||||||
|
} catch (IntrospectionException e) {
|
||||||
|
throw new IllegalException("not find getter for" + propertiesName + "in" + o.getName(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* setter for properties
|
||||||
|
*
|
||||||
|
* @param o obj
|
||||||
|
* @param propertiesName name
|
||||||
|
* @return Method for set
|
||||||
|
*/
|
||||||
|
public static Method setter(Class<?> o, String propertiesName) {
|
||||||
|
if (o == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
PropertyDescriptor descriptor = new PropertyDescriptor(propertiesName, o);
|
||||||
|
return descriptor.getWriteMethod();
|
||||||
|
} catch (IntrospectionException e) {
|
||||||
|
throw new IllegalException("not find setter for" + propertiesName + "in" + o.getName(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.hippo4j.common.toolkit;
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.SimpleTimeZone;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* date and time util
|
||||||
|
*/
|
||||||
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
|
public class DateUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get time zone for this JVM
|
||||||
|
*/
|
||||||
|
private static final TimeZone TIME_ZONE = TimeZone.getDefault();
|
||||||
|
|
||||||
|
public static final String NORM_DATE_PATTERN = "yyyy-MM-dd";
|
||||||
|
|
||||||
|
public static final String NORM_TIME_PATTERN = "HH:mm:ss";
|
||||||
|
|
||||||
|
public static final String NORM_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
|
||||||
|
* represented by this <tt>Date</tt> object.
|
||||||
|
*
|
||||||
|
* @return the number of milliseconds since January 1, 1970, 00:00:00 GMT
|
||||||
|
* represented by this date.
|
||||||
|
*/
|
||||||
|
public static long getTime(LocalDateTime date) {
|
||||||
|
return getTime(date, TIME_ZONE.toZoneId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long getTime(LocalDateTime date, ZoneId zoneId) {
|
||||||
|
return date.atZone(zoneId).toInstant().toEpochMilli();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* modify format to date
|
||||||
|
*
|
||||||
|
* @param date date
|
||||||
|
* @param normTimePattern PATTERN
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public static String format(Date date, String normTimePattern) {
|
||||||
|
SimpleDateFormat zoneFormat = new SimpleDateFormat(normTimePattern);
|
||||||
|
return zoneFormat.format(date);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,341 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.hippo4j.common.toolkit;
|
||||||
|
|
||||||
|
import cn.hippo4j.common.constant.Constants;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.nio.channels.FileChannel;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
|
import java.util.zip.GZIPOutputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IO related tool methods.
|
||||||
|
*
|
||||||
|
* @author nacos
|
||||||
|
*/
|
||||||
|
public class IoUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try decompress by GZIP from stream.
|
||||||
|
*
|
||||||
|
* @param raw compress stream
|
||||||
|
* @return byte array after decompress
|
||||||
|
*/
|
||||||
|
public static byte[] tryDecompress(InputStream raw) throws IOException {
|
||||||
|
try (
|
||||||
|
GZIPInputStream gis = new GZIPInputStream(raw);
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream()) {
|
||||||
|
copy(gis, out);
|
||||||
|
return out.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try decompress by GZIP from byte array.
|
||||||
|
*
|
||||||
|
* @param raw compressed byte array
|
||||||
|
* @return byte array after decompress
|
||||||
|
* @throws Exception exception
|
||||||
|
*/
|
||||||
|
public static byte[] tryDecompress(byte[] raw) throws Exception {
|
||||||
|
if (!isGzipStream(raw)) {
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
try (
|
||||||
|
GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(raw));
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream()) {
|
||||||
|
copy(gis, out);
|
||||||
|
return out.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try compress by GZIP for string.
|
||||||
|
*
|
||||||
|
* @param str strings to be compressed.
|
||||||
|
* @param encoding encoding.
|
||||||
|
* @return byte[]
|
||||||
|
*/
|
||||||
|
public static byte[] tryCompress(String str, String encoding) {
|
||||||
|
if (str == null || str.length() == 0) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
try (GZIPOutputStream gzip = new GZIPOutputStream(out)) {
|
||||||
|
gzip.write(str.getBytes(encoding));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return out.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BufferedReader toBufferedReader(Reader reader) {
|
||||||
|
return reader instanceof BufferedReader ? (BufferedReader) reader : new BufferedReader(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write string to a file.
|
||||||
|
*
|
||||||
|
* @param file file
|
||||||
|
* @param data string
|
||||||
|
* @param encoding encoding of string
|
||||||
|
* @throws IOException io exception
|
||||||
|
*/
|
||||||
|
public static void writeStringToFile(File file, String data, String encoding) throws IOException {
|
||||||
|
try (OutputStream os = new FileOutputStream(file)) {
|
||||||
|
os.write(data.getBytes(encoding));
|
||||||
|
os.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read lines.
|
||||||
|
*
|
||||||
|
* @param input reader
|
||||||
|
* @return list of line
|
||||||
|
* @throws IOException io exception
|
||||||
|
*/
|
||||||
|
public static List<String> readLines(Reader input) throws IOException {
|
||||||
|
BufferedReader reader = toBufferedReader(input);
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
while (true) {
|
||||||
|
String line = reader.readLine();
|
||||||
|
if (null != line) {
|
||||||
|
if (StringUtil.isNotEmpty(line)) {
|
||||||
|
list.add(line.trim());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To string from stream.
|
||||||
|
*
|
||||||
|
* @param input stream
|
||||||
|
* @param encoding charset of stream
|
||||||
|
* @return string
|
||||||
|
* @throws IOException io exception
|
||||||
|
*/
|
||||||
|
@SneakyThrows
|
||||||
|
public static String toString(InputStream input, String encoding) {
|
||||||
|
if (input == null) {
|
||||||
|
return StringUtil.EMPTY;
|
||||||
|
}
|
||||||
|
return (null == encoding) ? toString(new InputStreamReader(input, Constants.ENCODE))
|
||||||
|
: toString(new InputStreamReader(input, encoding));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To string from reader.
|
||||||
|
*
|
||||||
|
* @param reader reader
|
||||||
|
* @return string
|
||||||
|
* @throws IOException io exception
|
||||||
|
*/
|
||||||
|
public static String toString(Reader reader) throws IOException {
|
||||||
|
CharArrayWriter sw = new CharArrayWriter();
|
||||||
|
copy(reader, sw);
|
||||||
|
return sw.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy data.
|
||||||
|
*
|
||||||
|
* @param input source
|
||||||
|
* @param output target
|
||||||
|
* @return copy size
|
||||||
|
* @throws IOException io exception
|
||||||
|
*/
|
||||||
|
public static long copy(Reader input, Writer output) throws IOException {
|
||||||
|
char[] buffer = new char[1 << 12];
|
||||||
|
long count = 0;
|
||||||
|
for (int n = 0; (n = input.read(buffer)) >= 0; ) {
|
||||||
|
output.write(buffer, 0, n);
|
||||||
|
count += n;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy data.
|
||||||
|
*
|
||||||
|
* @param input source
|
||||||
|
* @param output target
|
||||||
|
* @return copy size
|
||||||
|
* @throws IOException io exception
|
||||||
|
*/
|
||||||
|
public static long copy(InputStream input, OutputStream output) throws IOException {
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
int bytesRead;
|
||||||
|
int totalBytes = 0;
|
||||||
|
while ((bytesRead = input.read(buffer)) != -1) {
|
||||||
|
output.write(buffer, 0, bytesRead);
|
||||||
|
|
||||||
|
totalBytes += bytesRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
return totalBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete file or dir.
|
||||||
|
*
|
||||||
|
* <p>If is dir, clean directory, do not delete dir.
|
||||||
|
*
|
||||||
|
* <p>If is file, delete file.
|
||||||
|
*
|
||||||
|
* @param fileOrDir file or dir
|
||||||
|
* @throws IOException io exception
|
||||||
|
*/
|
||||||
|
public static void delete(File fileOrDir) throws IOException {
|
||||||
|
if (fileOrDir == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileOrDir.isDirectory()) {
|
||||||
|
cleanDirectory(fileOrDir);
|
||||||
|
} else {
|
||||||
|
if (fileOrDir.exists()) {
|
||||||
|
boolean isDeleteOk = fileOrDir.delete();
|
||||||
|
if (!isDeleteOk) {
|
||||||
|
throw new IOException("delete fail");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理目录下的内容. Clean content under directory.
|
||||||
|
*
|
||||||
|
* @param directory directory
|
||||||
|
* @throws IOException io exception
|
||||||
|
*/
|
||||||
|
public static void cleanDirectory(File directory) throws IOException {
|
||||||
|
if (!directory.exists()) {
|
||||||
|
String message = directory + " does not exist";
|
||||||
|
throw new IllegalArgumentException(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!directory.isDirectory()) {
|
||||||
|
String message = directory + " is not a directory";
|
||||||
|
throw new IllegalArgumentException(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
File[] files = directory.listFiles();
|
||||||
|
// null if security restricted
|
||||||
|
if (files == null) {
|
||||||
|
throw new IOException("Failed to list contents of " + directory);
|
||||||
|
}
|
||||||
|
|
||||||
|
IOException exception = null;
|
||||||
|
for (File file : files) {
|
||||||
|
try {
|
||||||
|
delete(file);
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
exception = ioe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null != exception) {
|
||||||
|
throw exception;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy File.
|
||||||
|
*
|
||||||
|
* @param source source file path
|
||||||
|
* @param target target file path
|
||||||
|
* @throws IOException io exception
|
||||||
|
*/
|
||||||
|
public static void copyFile(String source, String target) throws IOException {
|
||||||
|
File sf = new File(source);
|
||||||
|
if (!sf.exists()) {
|
||||||
|
throw new IllegalArgumentException("source file does not exist.");
|
||||||
|
}
|
||||||
|
File tf = new File(target);
|
||||||
|
if (!tf.getParentFile().mkdirs()) {
|
||||||
|
throw new RuntimeException("failed to create parent directory.");
|
||||||
|
}
|
||||||
|
if (!tf.exists() && !tf.createNewFile()) {
|
||||||
|
throw new RuntimeException("failed to create target file.");
|
||||||
|
}
|
||||||
|
try (
|
||||||
|
FileChannel sc = new FileInputStream(sf).getChannel();
|
||||||
|
FileChannel tc = new FileOutputStream(tf).getChannel()) {
|
||||||
|
sc.transferTo(0, sc.size(), tc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Judge whether is Gzip stream.
|
||||||
|
*
|
||||||
|
* @param bytes byte array
|
||||||
|
* @return true if is gzip, otherwise false
|
||||||
|
*/
|
||||||
|
public static boolean isGzipStream(byte[] bytes) {
|
||||||
|
|
||||||
|
int minByteArraySize = 2;
|
||||||
|
if (bytes == null || bytes.length < minByteArraySize) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GZIPInputStream.GZIP_MAGIC == ((bytes[1] << 8 | bytes[0]) & 0xFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close http connection quietly.
|
||||||
|
*
|
||||||
|
* @param connection http connection
|
||||||
|
*/
|
||||||
|
public static void closeQuietly(HttpURLConnection connection) {
|
||||||
|
if (connection != null) {
|
||||||
|
try {
|
||||||
|
closeQuietly(connection.getInputStream());
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close closable object quietly.
|
||||||
|
*
|
||||||
|
* @param closeable http connection
|
||||||
|
*/
|
||||||
|
public static void closeQuietly(Closeable closeable) {
|
||||||
|
try {
|
||||||
|
if (closeable != null) {
|
||||||
|
closeable.close();
|
||||||
|
}
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void closeQuietly(Closeable... closeable) {
|
||||||
|
Arrays.stream(closeable).forEach(IoUtil::closeQuietly);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.hippo4j.common.toolkit;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* reference google guava
|
||||||
|
*/
|
||||||
|
public class Joiner {
|
||||||
|
|
||||||
|
private final String separator;
|
||||||
|
|
||||||
|
private Joiner(String separator) {
|
||||||
|
this.separator = Objects.requireNonNull(separator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a joiner which automatically places {@code separator} between consecutive elements.
|
||||||
|
*/
|
||||||
|
public static Joiner on(String separator) {
|
||||||
|
return new Joiner(separator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string containing the string representation of each of {@code parts}, using the
|
||||||
|
* previously configured separator between each.
|
||||||
|
*/
|
||||||
|
public final String join(Object[] parts) {
|
||||||
|
return join(Arrays.asList(parts));
|
||||||
|
}
|
||||||
|
|
||||||
|
public final String join(Iterable<?> parts) {
|
||||||
|
return join(parts.iterator());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string containing the string representation of each of {@code parts}, using the
|
||||||
|
* previously configured separator between each.
|
||||||
|
*/
|
||||||
|
public final String join(Iterator<?> parts) {
|
||||||
|
return appendTo(new StringBuilder(), parts).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final StringBuilder appendTo(StringBuilder builder, Iterator<?> parts) {
|
||||||
|
try {
|
||||||
|
appendTo((Appendable) builder, parts);
|
||||||
|
} catch (IOException impossible) {
|
||||||
|
throw new AssertionError(impossible);
|
||||||
|
}
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <A extends Appendable> A appendTo(A appendable, Iterator<?> parts) throws IOException {
|
||||||
|
Objects.requireNonNull(appendable);
|
||||||
|
if (parts.hasNext()) {
|
||||||
|
appendable.append(toString(parts.next()));
|
||||||
|
while (parts.hasNext()) {
|
||||||
|
appendable.append(separator);
|
||||||
|
appendable.append(toString(parts.next()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return appendable;
|
||||||
|
}
|
||||||
|
|
||||||
|
CharSequence toString(Object part) {
|
||||||
|
Objects.requireNonNull(part);
|
||||||
|
return (part instanceof CharSequence) ? (CharSequence) part : part.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,167 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.hippo4j.common.toolkit;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Dictionary;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map util.
|
||||||
|
*/
|
||||||
|
public class MapUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Null-safe check if the specified Dictionary is empty.
|
||||||
|
*
|
||||||
|
* <p>Null returns true.
|
||||||
|
*
|
||||||
|
* @param map the collection to check, may be null
|
||||||
|
* @return true if empty or null
|
||||||
|
*/
|
||||||
|
public static boolean isEmpty(Map map) {
|
||||||
|
return (map == null || map.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Null-safe check if the specified Dictionary is empty.
|
||||||
|
*
|
||||||
|
* <p>Null returns true.
|
||||||
|
*
|
||||||
|
* @param coll the collection to check, may be null
|
||||||
|
* @return true if empty or null
|
||||||
|
*/
|
||||||
|
public static boolean isEmpty(Dictionary coll) {
|
||||||
|
return (coll == null || coll.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Null-safe check if the specified Dictionary is not empty.
|
||||||
|
*
|
||||||
|
* <p>Null returns false.
|
||||||
|
*
|
||||||
|
* @param map the collection to check, may be null
|
||||||
|
* @return true if non-null and non-empty
|
||||||
|
*/
|
||||||
|
public static boolean isNotEmpty(Map map) {
|
||||||
|
return !isEmpty(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Null-safe check if the specified Dictionary is not empty.
|
||||||
|
*
|
||||||
|
* <p>Null returns false.
|
||||||
|
*
|
||||||
|
* @param coll the collection to check, may be null
|
||||||
|
* @return true if non-null and non-empty
|
||||||
|
*/
|
||||||
|
public static boolean isNotEmpty(Dictionary coll) {
|
||||||
|
return !isEmpty(coll);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put into map if value is not null.
|
||||||
|
*
|
||||||
|
* @param target target map
|
||||||
|
* @param key key
|
||||||
|
* @param value value
|
||||||
|
*/
|
||||||
|
public static void putIfValNoNull(Map target, Object key, Object value) {
|
||||||
|
Objects.requireNonNull(key, "key");
|
||||||
|
if (value != null) {
|
||||||
|
target.put(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put into map if value is not empty.
|
||||||
|
*
|
||||||
|
* @param target target map
|
||||||
|
* @param key key
|
||||||
|
* @param value value
|
||||||
|
*/
|
||||||
|
public static void putIfValNoEmpty(Map target, Object key, Object value) {
|
||||||
|
Objects.requireNonNull(key, "key");
|
||||||
|
if (value instanceof String) {
|
||||||
|
if (StringUtil.isNotEmpty((String) value)) {
|
||||||
|
target.put(key, value);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value instanceof Collection) {
|
||||||
|
if (CollectionUtil.isNotEmpty((Collection) value)) {
|
||||||
|
target.put(key, value);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value instanceof Map) {
|
||||||
|
if (isNotEmpty((Map) value)) {
|
||||||
|
target.put(key, value);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value instanceof Dictionary) {
|
||||||
|
if (isNotEmpty((Dictionary) value)) {
|
||||||
|
target.put(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ComputeIfAbsent lazy load.
|
||||||
|
*
|
||||||
|
* @param target target Map data.
|
||||||
|
* @param key map key.
|
||||||
|
* @param mappingFunction function which is need to be executed.
|
||||||
|
* @param param1 function's parameter value1.
|
||||||
|
* @param param2 function's parameter value1.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static <K, C, V, T> V computeIfAbsent(Map<K, V> target, K key, BiFunction<C, T, V> mappingFunction, C param1,
|
||||||
|
T param2) {
|
||||||
|
Objects.requireNonNull(target, "target");
|
||||||
|
Objects.requireNonNull(key, "key");
|
||||||
|
Objects.requireNonNull(mappingFunction, "mappingFunction");
|
||||||
|
Objects.requireNonNull(param1, "param1");
|
||||||
|
Objects.requireNonNull(param2, "param2");
|
||||||
|
V val = target.get(key);
|
||||||
|
if (val == null) {
|
||||||
|
V ret = mappingFunction.apply(param1, param2);
|
||||||
|
target.put(key, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* remove value, Thread safety depends on whether the Map is a thread-safe Map.
|
||||||
|
*
|
||||||
|
* @param map map
|
||||||
|
* @param key key
|
||||||
|
* @param removeJudge judge this key can be remove
|
||||||
|
* @param <K> key type
|
||||||
|
* @param <V> value type
|
||||||
|
* @return value
|
||||||
|
*/
|
||||||
|
public static <K, V> V removeKey(Map<K, V> map, K key, Predicate<V> removeJudge) {
|
||||||
|
return map.computeIfPresent(key, (k, v) -> removeJudge.test(v) ? null : v);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,199 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.hippo4j.common.toolkit.http;
|
||||||
|
|
||||||
|
import cn.hippo4j.common.constant.Constants;
|
||||||
|
import cn.hippo4j.common.constant.HttpHeaderConstants;
|
||||||
|
import cn.hippo4j.common.constant.HttpMediaType;
|
||||||
|
import cn.hippo4j.common.toolkit.MapUtil;
|
||||||
|
import cn.hippo4j.common.toolkit.StringUtil;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Http header.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||||
|
*/
|
||||||
|
public class Header {
|
||||||
|
|
||||||
|
public static final Header EMPTY = Header.newInstance();
|
||||||
|
|
||||||
|
private final Map<String, String> header;
|
||||||
|
|
||||||
|
private final Map<String, List<String>> originalResponseHeader;
|
||||||
|
|
||||||
|
private static final String DEFAULT_CHARSET = "UTF-8";
|
||||||
|
|
||||||
|
private static final String DEFAULT_ENCODING = "gzip";
|
||||||
|
|
||||||
|
private Header() {
|
||||||
|
header = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||||
|
originalResponseHeader = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||||
|
addParam(HttpHeaderConstants.CONTENT_TYPE, HttpMediaType.APPLICATION_JSON);
|
||||||
|
addParam(HttpHeaderConstants.ACCEPT_CHARSET, DEFAULT_CHARSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Header newInstance() {
|
||||||
|
return new Header();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the key and value to the header.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param value the value
|
||||||
|
* @return header
|
||||||
|
*/
|
||||||
|
public Header addParam(String key, String value) {
|
||||||
|
if (StringUtil.isNotEmpty(key)) {
|
||||||
|
header.put(key, value);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Header setContentType(String contentType) {
|
||||||
|
if (contentType == null) {
|
||||||
|
contentType = HttpMediaType.APPLICATION_JSON;
|
||||||
|
}
|
||||||
|
return addParam(HttpHeaderConstants.CONTENT_TYPE, contentType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Header build() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue(String key) {
|
||||||
|
return header.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getHeader() {
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterator<Map.Entry<String, String>> iterator() {
|
||||||
|
return header.entrySet().iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transfer to KV part list. The odd index is key and the even index is value.
|
||||||
|
*
|
||||||
|
* @return KV string list
|
||||||
|
*/
|
||||||
|
public List<String> toList() {
|
||||||
|
List<String> list = new ArrayList<>(header.size() * 2);
|
||||||
|
Iterator<Map.Entry<String, String>> iterator = iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
Map.Entry<String, String> entry = iterator.next();
|
||||||
|
list.add(entry.getKey());
|
||||||
|
list.add(entry.getValue());
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add all KV list to header. The odd index is key and the even index is value.
|
||||||
|
*
|
||||||
|
* @param list KV list
|
||||||
|
* @return header
|
||||||
|
*/
|
||||||
|
public Header addAll(List<String> list) {
|
||||||
|
if ((list.size() & 1) != 0) {
|
||||||
|
throw new IllegalArgumentException("list size must be a multiple of 2");
|
||||||
|
}
|
||||||
|
for (int i = 0; i < list.size();) {
|
||||||
|
String key = list.get(i++);
|
||||||
|
if (StringUtil.isNotEmpty(key)) {
|
||||||
|
header.put(key, list.get(i++));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add all parameters to header.
|
||||||
|
*
|
||||||
|
* @param params parameters
|
||||||
|
*/
|
||||||
|
public void addAll(Map<String, String> params) {
|
||||||
|
if (MapUtil.isNotEmpty(params)) {
|
||||||
|
for (Map.Entry<String, String> entry : params.entrySet()) {
|
||||||
|
addParam(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set original format response header.
|
||||||
|
*
|
||||||
|
* <p>Currently only corresponds to the response header of JDK.
|
||||||
|
*
|
||||||
|
* @param key original response header key
|
||||||
|
* @param values original response header values
|
||||||
|
*/
|
||||||
|
public void addOriginalResponseHeader(String key, List<String> values) {
|
||||||
|
if (StringUtil.isNotEmpty(key)) {
|
||||||
|
this.originalResponseHeader.put(key, values);
|
||||||
|
addParam(key, values.get(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get original format response header.
|
||||||
|
*
|
||||||
|
* <p>Currently only corresponds to the response header of JDK.
|
||||||
|
*
|
||||||
|
* @return Map original response header
|
||||||
|
*/
|
||||||
|
public Map<String, List<String>> getOriginalResponseHeader() {
|
||||||
|
return this.originalResponseHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCharset() {
|
||||||
|
String acceptCharset = getValue(HttpHeaderConstants.ACCEPT_CHARSET);
|
||||||
|
if (acceptCharset == null) {
|
||||||
|
String contentType = getValue(HttpHeaderConstants.CONTENT_TYPE);
|
||||||
|
acceptCharset = StringUtil.isNotBlank(contentType) ? analysisCharset(contentType) : Constants.ENCODE;
|
||||||
|
}
|
||||||
|
return acceptCharset;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String analysisCharset(String contentType) {
|
||||||
|
String[] values = contentType.split(";");
|
||||||
|
String charset = Constants.ENCODE;
|
||||||
|
if (values.length == 0) {
|
||||||
|
return charset;
|
||||||
|
}
|
||||||
|
for (String value : values) {
|
||||||
|
if (value.startsWith("charset=")) {
|
||||||
|
charset = value.substring("charset=".length());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return charset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
header.clear();
|
||||||
|
originalResponseHeader.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Header{" + "headerToMap=" + header + '}';
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.hippo4j.common.toolkit.http;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a client-side HTTP response.
|
||||||
|
*
|
||||||
|
* @author mai.jh
|
||||||
|
*/
|
||||||
|
public interface HttpClientResponse extends Closeable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the headers of this message.
|
||||||
|
*
|
||||||
|
* @return a corresponding HttpHeaders object (never {@code null})
|
||||||
|
*/
|
||||||
|
Header getHeaders();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the body of the message as an input stream.
|
||||||
|
*
|
||||||
|
* @return String response body
|
||||||
|
*/
|
||||||
|
InputStream getBody();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the HTTP status code.
|
||||||
|
*
|
||||||
|
* @return the HTTP status as an integer
|
||||||
|
*/
|
||||||
|
int getStatusCode();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the HTTP status text of the response.
|
||||||
|
*
|
||||||
|
* @return the HTTP status text
|
||||||
|
*/
|
||||||
|
String getStatusText();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the body As string.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
String getBodyString();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* close response InputStream.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
void close();
|
||||||
|
}
|
@ -0,0 +1,360 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.hippo4j.common.toolkit.http;
|
||||||
|
|
||||||
|
import cn.hippo4j.common.constant.Constants;
|
||||||
|
import cn.hippo4j.common.constant.HttpMediaType;
|
||||||
|
import cn.hippo4j.common.constant.HttpMethod;
|
||||||
|
import cn.hippo4j.common.constant.HttpResponseCode;
|
||||||
|
import cn.hippo4j.common.toolkit.CollectionUtil;
|
||||||
|
import cn.hippo4j.common.toolkit.IoUtil;
|
||||||
|
import cn.hippo4j.common.toolkit.JSONUtil;
|
||||||
|
import cn.hippo4j.common.toolkit.StringUtil;
|
||||||
|
import cn.hippo4j.common.toolkit.logtracing.LogMessage;
|
||||||
|
import cn.hippo4j.common.web.exception.ServiceException;
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static cn.hippo4j.common.constant.HttpHeaderConstants.CONTENT_LENGTH;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Http request utilities.
|
||||||
|
*
|
||||||
|
* @author Rongzhen Yan
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
|
public class HttpUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default connect timeout
|
||||||
|
*/
|
||||||
|
private static final int DEFAULT_CONNECT_TIMEOUT = 10000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default read timeout
|
||||||
|
*/
|
||||||
|
private static final int DEFAULT_READ_TIMEOUT = 30000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a get network request.
|
||||||
|
*
|
||||||
|
* @param url target url
|
||||||
|
* @param headers headers
|
||||||
|
* @param params form data
|
||||||
|
* @param timeout request timeout
|
||||||
|
* @param clazz return the target data type
|
||||||
|
* @param <T> return the target data type
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static <T> T get(String url, Map<String, String> headers, Map<String, String> params, long timeout, Class<T> clazz) {
|
||||||
|
return execute(buildUrl(url, params), HttpMethod.GET, null, headers, timeout, clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a get network request.
|
||||||
|
*
|
||||||
|
* @param url target url
|
||||||
|
* @param params form data
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String get(String url, Map<String, String> params) {
|
||||||
|
return execute(buildUrl(url, params), HttpMethod.GET, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a get network request.
|
||||||
|
*
|
||||||
|
* @param url target url
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String get(String url) {
|
||||||
|
return execute(url, HttpMethod.GET, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a get network request.
|
||||||
|
*
|
||||||
|
* @param url target url
|
||||||
|
* @param clazz return the target data type
|
||||||
|
* @param <T> return the target data type
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static <T> T get(String url, Class<T> clazz) {
|
||||||
|
return JSONUtil.parseObject(get(url), clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a post network request.
|
||||||
|
*
|
||||||
|
* @param url target url
|
||||||
|
* @param body request body
|
||||||
|
* @param clazz return the target data type
|
||||||
|
* @param <T> return the target data type
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static <T> T post(String url, Object body, Class<T> clazz) {
|
||||||
|
String result = post(url, body);
|
||||||
|
return JSONUtil.parseObject(result, clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a post network request.
|
||||||
|
*
|
||||||
|
* @param url target url
|
||||||
|
* @param body request body
|
||||||
|
* @param timeout request timeout
|
||||||
|
* @param clazz return the target data type
|
||||||
|
* @param <T> return the target data type
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static <T> T post(String url, Object body, long timeout, Class<T> clazz) {
|
||||||
|
String result = post(url, body, timeout);
|
||||||
|
return JSONUtil.parseObject(result, clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a post network request.
|
||||||
|
*
|
||||||
|
* @param url target url
|
||||||
|
* @param headers headers
|
||||||
|
* @param params form data
|
||||||
|
* @param timeout request timeout
|
||||||
|
* @param clazz return the target data type
|
||||||
|
* @param <T> return the target data type
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static <T> T post(String url, Map<String, String> headers, Map<String, String> params, long timeout, Class<T> clazz) {
|
||||||
|
return execute(buildUrl(url, params), HttpMethod.POST, null, headers, timeout, clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a post network request.
|
||||||
|
*
|
||||||
|
* @param url target url
|
||||||
|
* @param headers headers
|
||||||
|
* @param body request body
|
||||||
|
* @param timeout request timeout
|
||||||
|
* @param clazz return the target data type
|
||||||
|
* @param <T> return the target data type
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static <T> T post(String url, Map<String, String> headers, Object body, long timeout, Class<T> clazz) {
|
||||||
|
return execute(url, HttpMethod.POST, body, headers, timeout, clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a post network request.
|
||||||
|
*
|
||||||
|
* @param url target url
|
||||||
|
* @param body request body
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String post(String url, Object body) {
|
||||||
|
return execute(url, HttpMethod.POST, body, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a post network request.
|
||||||
|
*
|
||||||
|
* @param url target url
|
||||||
|
* @param body request body
|
||||||
|
* @param timeout request timeout
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String post(String url, Object body, long timeout) {
|
||||||
|
return execute(url, HttpMethod.POST, body, null, timeout, String.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a post network request.
|
||||||
|
*
|
||||||
|
* @param url target url
|
||||||
|
* @param json json data
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String postJson(String url, String json) {
|
||||||
|
return executeJson(url, HttpMethod.POST, json, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a put network request.
|
||||||
|
*
|
||||||
|
* @param url target url
|
||||||
|
* @param body request body
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String put(String url, Object body) {
|
||||||
|
return execute(url, HttpMethod.PUT, body, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a put network request.
|
||||||
|
*
|
||||||
|
* @param url target url
|
||||||
|
* @param body request body
|
||||||
|
* @param headers headers
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String put(String url, Object body, Map<String, String> headers) {
|
||||||
|
return execute(url, HttpMethod.PUT, body, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a complete Url from the query string.
|
||||||
|
*
|
||||||
|
* @param url target url
|
||||||
|
* @param queryParams query params
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@SneakyThrows
|
||||||
|
public static String buildUrl(String url, Map<String, String> queryParams) {
|
||||||
|
if (CollectionUtil.isEmpty(queryParams)) {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
boolean isFirst = true;
|
||||||
|
StringBuilder builder = new StringBuilder(url);
|
||||||
|
for (Map.Entry<String, String> entry : queryParams.entrySet()) {
|
||||||
|
String key = entry.getKey();
|
||||||
|
if (key != null && entry.getValue() != null) {
|
||||||
|
if (isFirst) {
|
||||||
|
isFirst = false;
|
||||||
|
builder.append("?");
|
||||||
|
} else {
|
||||||
|
builder.append("&");
|
||||||
|
}
|
||||||
|
String value = URLEncoder.encode(queryParams.get(key), Constants.ENCODE)
|
||||||
|
.replaceAll("\\+", "%20");
|
||||||
|
builder.append(key)
|
||||||
|
.append("=")
|
||||||
|
.append(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String executeJson(String url, String method, String json, Map<String, String> headers) {
|
||||||
|
if (!JSONUtil.isJson(json)) {
|
||||||
|
log.error(LogMessage.getInstance().setMsg("Http Call error.")
|
||||||
|
.kv("url", url)
|
||||||
|
.kv("method", method)
|
||||||
|
.kv("json", json)
|
||||||
|
.kv2String("headers", JSONUtil.toJSONString(headers)));
|
||||||
|
throw new ServiceException("Invalid http json body, please check it again.");
|
||||||
|
}
|
||||||
|
return execute(url, method, json, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String execute(String url, String method, Object param, Map<String, String> headers) {
|
||||||
|
HttpURLConnection connection = createConnection(url, method);
|
||||||
|
HttpClientResponse response = null;
|
||||||
|
try {
|
||||||
|
response = doExecute(connection, param, headers);
|
||||||
|
return response.getBodyString();
|
||||||
|
} finally {
|
||||||
|
Optional.ofNullable(response).ifPresent(each -> each.close());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> T execute(String url, String method, Object body, Map<String, String> headers, long timeout, Class<T> clazz) {
|
||||||
|
HttpURLConnection connection = createConnection(url, method, timeout);
|
||||||
|
HttpClientResponse response = null;
|
||||||
|
try {
|
||||||
|
response = doExecute(connection, body, headers);
|
||||||
|
if (clazz == String.class) {
|
||||||
|
return (T) response.getBodyString();
|
||||||
|
}
|
||||||
|
return JSONUtil.parseObject(response.getBodyString(), clazz);
|
||||||
|
} finally {
|
||||||
|
Optional.ofNullable(response).ifPresent(each -> each.close());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
private static HttpClientResponse doExecute(HttpURLConnection connection, Object body, Map<String, String> headers) {
|
||||||
|
try {
|
||||||
|
if (headers != null && headers.size() > 0) {
|
||||||
|
for (Map.Entry<String, String> entry : headers.entrySet()) {
|
||||||
|
connection.setRequestProperty(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String bodyString;
|
||||||
|
if (body instanceof String) {
|
||||||
|
bodyString = (String) body;
|
||||||
|
} else {
|
||||||
|
bodyString = JSONUtil.toJSONString(body);
|
||||||
|
}
|
||||||
|
if (!StringUtil.isEmpty(bodyString)) {
|
||||||
|
connection.setDoOutput(true);
|
||||||
|
byte[] b = bodyString.getBytes();
|
||||||
|
connection.setRequestProperty(CONTENT_LENGTH, String.valueOf(b.length));
|
||||||
|
OutputStream outputStream = connection.getOutputStream();
|
||||||
|
outputStream.write(b, 0, b.length);
|
||||||
|
outputStream.flush();
|
||||||
|
IoUtil.closeQuietly(outputStream);
|
||||||
|
}
|
||||||
|
connection.connect();
|
||||||
|
JdkHttpClientResponse response = new JdkHttpClientResponse(connection);
|
||||||
|
if (HttpResponseCode.SC_OK != response.getStatusCode()) {
|
||||||
|
String msg = String.format("HttpPost response code error. [code] %s [url] %s [body] %s", response.getStatusCode(), connection.getURL(), response.getBodyString());
|
||||||
|
throw new ServiceException(msg);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
log.error(LogMessage.getInstance().setMsg("Http call error. ")
|
||||||
|
.kv("url", connection.getURL())
|
||||||
|
.kv("method", connection.getRequestMethod())
|
||||||
|
.kv("body", JSONUtil.toJSONString(body))
|
||||||
|
.kv2String("headers", JSONUtil.toJSONString(headers)), ex);
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
private static HttpURLConnection createConnection(String url, String method) {
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
|
||||||
|
connection.setDoInput(true);
|
||||||
|
connection.setDoOutput(true);
|
||||||
|
connection.setConnectTimeout(DEFAULT_CONNECT_TIMEOUT);
|
||||||
|
connection.setReadTimeout(DEFAULT_READ_TIMEOUT);
|
||||||
|
connection.setRequestMethod(method);
|
||||||
|
connection.setRequestProperty(Constants.CONTENT_TYPE, HttpMediaType.APPLICATION_JSON);
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
private static HttpURLConnection createConnection(String url, String method, long timeout) {
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
|
||||||
|
connection.setDoInput(true);
|
||||||
|
connection.setDoOutput(true);
|
||||||
|
connection.setConnectTimeout(Integer.parseInt(String.valueOf(timeout)));
|
||||||
|
connection.setReadTimeout(Integer.parseInt(String.valueOf(timeout)));
|
||||||
|
connection.setRequestMethod(method);
|
||||||
|
connection.setRequestProperty(Constants.CONTENT_TYPE, HttpMediaType.APPLICATION_JSON);
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue