com.feingto.cloud.kit.HttpKit Maven / Gradle / Ivy
package com.feingto.cloud.kit;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.feingto.cloud.kit.json.JSON;
import lombok.SneakyThrows;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.*;
import org.springframework.web.util.UriTemplate;
import org.springframework.web.util.UriUtils;
import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.URI;
import java.net.URLDecoder;
import java.net.UnknownHostException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.springframework.http.HttpHeaders.CONTENT_TYPE;
/**
* Http 工具类
*
* @author longfei
*/
public class HttpKit {
public static final PathMatcher pathMatcher = new AntPathMatcher();
/**
* 根据 scheme, address, post 生成URL
*
* @param scheme http scheme
* @param address 主机地址
* @param port 端口
*/
public static String getUrl(String scheme, String address, int port) {
return String.format("%s://%s:%s", scheme, address, port);
}
/**
* 根据 scheme, address, post 生成已编码URL
*
* @param scheme http scheme
* @param address 主机地址
* @param port 端口
*/
public static String getEncodeUrl(String scheme, String address, int port) {
return UriUtils.encodePath(getUrl(scheme, address, port), UTF_8);
}
/**
* 获取主机域 Scheme + 域名
*
* @param target url
*/
public static String getHostname(String target) {
URI uri = URI.create(target);
return uri.getScheme().concat("://").concat(uri.getHost());
}
/**
* 根据正则获取主机域 Scheme + 域名
*
* @param target url
*/
public static String getHostname(String target, String regex) {
Matcher matcher = Pattern.compile(regex).matcher(target);
return matcher.find() ? matcher.group(0) : target;
}
/**
* Map转多值Map
*
* @param map MultiValueMap
*/
public static MultiValueMap toMultiValueMap(Map map) {
MultiValueMap multiMap = new LinkedMultiValueMap<>();
map.forEach(multiMap::set);
return multiMap;
}
/**
* 是否包含指定媒体类型
*
* @param headers HttpHeaders
* @param mediaTypes MediaType
*/
public static boolean isMediaType(HttpHeaders headers, MediaType... mediaTypes) {
return Optional.ofNullable(headers.getFirst(CONTENT_TYPE))
.map(MediaType::valueOf)
.map(mediaType -> Arrays.stream(mediaTypes)
.anyMatch(media -> media.includes(mediaType)))
.orElse(false);
}
/**
* 获取参数查询字符串
*
* @param queryParams 查询参数
* @return query string
*/
public static String getQueryString(MultiValueMap queryParams) {
if (queryParams.isEmpty()) {
return "";
}
StringBuilder query = new StringBuilder();
Map singles = new HashMap<>();
for (String param : queryParams.keySet()) {
int i = 0;
for (String value : queryParams.get(param)) {
query.append("&");
query.append(param);
if (!"".equals(value)) {
String key = param;
if (key.contains("\f")) {
key = (Pattern.compile("\f").matcher(key).replaceAll("\f\f"));
}
if (key.contains(":")) {
key = Pattern.compile(":").matcher(key).replaceAll("\f");
}
key = key + i;
singles.put(key, value);
query.append("={");
query.append(key);
query.append("}");
}
i++;
}
}
UriTemplate template = new UriTemplate(query.toString().substring(1));
return template.expand(singles).toString();
}
/**
* 获取查询字符串的参数Map
*
* @param queryString 查询字符串
* @return 查询参数Map
*/
@SneakyThrows
public static Map> getQueryParams(String queryString) {
if (StringUtils.isEmpty(queryString)) {
return new HashMap<>();
}
Map> queryParams = new LinkedMultiValueMap<>();
StringTokenizer tokenizer = new StringTokenizer(queryString, "&");
int i;
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
i = token.indexOf("=");
if (i > 0 && token.length() >= i + 1) {
String name = URLDecoder.decode(token.substring(0, i), UTF_8.name());
String value = URLDecoder.decode(token.substring(i + 1), UTF_8.name());
List valueList = queryParams.computeIfAbsent(name, k -> new LinkedList<>());
valueList.add(value);
} else if (i == -1) {
String name = URLDecoder.decode(token, UTF_8.name());
String value = "";
List valueList = queryParams.computeIfAbsent(name, k -> new LinkedList<>());
valueList.add(value);
}
}
return queryParams;
}
/**
* 追加 query string
*
* @param originalQuery 原有查询参数字符串
* @param appendQuery 追加的查询参数字符串
*/
public static String appendQueryString(String originalQuery, String appendQuery) {
StringBuilder query = new StringBuilder();
if (StringUtils.hasLength(originalQuery)) {
query.append(originalQuery);
if (originalQuery.charAt(originalQuery.length() - 1) != '&' && StringUtils.hasLength(appendQuery)) {
query.append('&');
}
}
if (appendQuery.startsWith("?") || appendQuery.startsWith("&")) {
appendQuery = appendQuery.substring(1);
}
return query.toString() + appendQuery;
}
/**
* request body 字符串追加参数Map
*
* @param requestBody request body
* @param parameters 参数Map
*/
public static JsonNode appendParamsToBody(String requestBody, MultiValueMap parameters) {
JsonNode node = JSON.read(requestBody);
if (MapUtils.isEmpty(parameters)) {
return node;
} else if (node.isObject()) {
ObjectNode result = (ObjectNode) node;
parameters.forEach((key, values) -> {
ArrayNode arrayNode = JSON.JSONArray();
values.forEach(arrayNode::add);
result.putPOJO(key, arrayNode);
});
return result;
} else if (node.isArray()) {
ArrayNode result = (ArrayNode) node;
parameters.forEach((key, values) -> {
ArrayNode arrayNode = JSON.JSONArray();
values.forEach(arrayNode::add);
result.addPOJO(JSON.JSONObject().putPOJO(key, arrayNode));
});
return result;
}
return node;
}
/**
* Json 对象节点递归遍历转换参数Map
*
* @param node JsonNode
* @param parameters MultiValueMap
*/
public static void jsonNodeRecursiveToMap(JsonNode node, MultiValueMap parameters) {
if (node.isValueNode()) {
return;
}
if (node.isObject()) {
Iterator> it = node.fields();
while (it.hasNext()) {
Map.Entry entry = it.next();
if (entry.getValue().isArray()) {
parameters.add(entry.getKey(), entry.getValue().asText());
} else {
parameters.set(entry.getKey(), entry.getValue().asText());
}
jsonNodeRecursiveToMap(entry.getValue(), parameters);
}
}
if (node.isArray()) {
for (JsonNode it : node) {
jsonNodeRecursiveToMap(it, parameters);
}
}
}
/**
* 是否 URI 模板
*
* @param uriTemplate the URI template string
*/
public static boolean isUriTemplate(String uriTemplate) {
return uriTemplate.contains("{") && uriTemplate.contains("}");
}
/**
* 提取URI模板变量, URI模板变量通过大括号('{'和'}')表示
* example: For pattern "/api/v1/test/{id}" and path "/api/v1/test/1", this method will
*
* @param pattern 请求路径表达式
* @param path 请求路径
* @return a map containing "id"->"1".
*/
public static Map extractUriTemplate(String pattern, String path) {
return pathMatcher.extractUriTemplateVariables(pattern, EncodeKit.urlDecode(path));
}
/**
* 解析包含URI模板变量的路径, URI模板变量通过大括号('{'和'}')表示
* example: For pattern "/api/v1/test/{id}" and id "1" -> path "/api/v1/test/1"
*
* @param path 请求路径
* @param uriTemplateVariables URI模板参数
* @return url
*/
public static String combineUriTemplate(String path, Map uriTemplateVariables) {
if (MapUtils.isEmpty(uriTemplateVariables)) {
return path;
}
for (String key : uriTemplateVariables.keySet()) {
path = path.replace("{" + key + "}", uriTemplateVariables.get(key));
}
return path;
}
/**
* 解析包含参数模板变量的路径, 参数模板变量通过井号('#'和'#')表示
* example: For pattern "#path#/test" and #path#: "/api/v1" -> path "/api/v1/test"
*
* @param path 请求路径
* @param paramTemplateVariables 参数模板
* @return url
*/
public static String combineEnvTemplate(String path, List paramTemplateVariables) {
if (CollectionUtils.isEmpty(paramTemplateVariables)) {
return path;
}
for (KeyValue keyValue : paramTemplateVariables) {
path = path.replace("#" + keyValue.getKey() + "#", (String) keyValue.getValue());
}
return path;
}
/**
* 判断是否Ajax请求
*
* @param request HttpServletRequest
*/
public static boolean isAjaxWithRequest(HttpServletRequest request) {
if (Objects.isNull(request)) {
return false;
}
return Objects.isNull(request.getHeader("X-Requested-With")) ?
MediaType.ALL_VALUE.equals(request.getHeader(HttpHeaders.ACCEPT)) ||
StringUtils.hasText(request.getHeader(HttpHeaders.ACCEPT)) &&
request.getHeader(HttpHeaders.ACCEPT).contains(MediaType.APPLICATION_JSON_VALUE) :
request.getHeader("X-Requested-With").equals("XMLHttpRequest");
}
/**
* 获取当前网络ip
*
* @param request HttpServletRequest
*/
public static String getIpAddr(HttpServletRequest request) {
return getIpAddr(request, null);
}
/**
* 获取当前网络ip
*
* @param request HttpServletRequest
*/
public static String getIpAddr(HttpServletRequest request, String headerName) {
if (StringUtils.isEmpty(headerName)) {
headerName = "X-Forwarded-For";
}
String ipAddress = request.getHeader(headerName);
if (StringUtils.isEmpty(ipAddress)) {
ipAddress = request.getRemoteAddr();
// 根据网卡取本机配置的IP
if (ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")) {
try {
ipAddress = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException ignored) {
}
}
}
// 对于通过多个代理的情况, 第一个IP为客户端真实IP, 多个IP按照','分割
if (Objects.nonNull(ipAddress) && ipAddress.contains(",")) {
ipAddress = ipAddress.split(",")[0];
}
return ipAddress;
}
/**
* 获取浏览器类型
*
* @param request HttpServletRequest
*/
public static String getBrowser(HttpServletRequest request) {
String browser = "未知";
if (Objects.nonNull(request)) {
try {
String ua = getUserAgent(request);
int idx;
if (ua.contains("MSIE")) {
idx = ua.indexOf("MSIE");
browser = ua.substring(idx, ua.indexOf(";", idx));
} else if (ua.contains("Edge/")) {
idx = ua.indexOf("Edge/");
browser = ua.substring(idx);
} else if (ua.contains("gecko") && ua.contains("rv:11.0")) {
browser = "MSIE 11.0";
} else if (ua.contains("OPR/")) {
idx = ua.indexOf("OPR/");
browser = ua.substring(idx);
browser = browser.replace("OPR", "Opera");
} else if (ua.contains("Chrome/")) {
idx = ua.indexOf("Chrome");
browser = ua.substring(idx, ua.indexOf(" ", idx));
} else if (ua.contains("Firefox/")) {
idx = ua.indexOf("Firefox/");
browser = ua.substring(idx);
} else if (ua.contains("Safari/")) {
idx = ua.indexOf("Safari/");
browser = ua.substring(idx);
}
} catch (Exception e) {
browser = "未知";
}
}
return browser;
}
/**
* 获取操作系统
*
* @param request HttpServletRequest
*/
public static String getPlatform(HttpServletRequest request) {
String platform = "未知";
if (Objects.nonNull(request)) {
String ua = getUserAgent(request);
if (ua.contains("Windows Phone")) {
platform = "Windows Phone";
} else if (ua.contains("Windows")) {
platform = "Windows";
if (ua.contains("Windows NT 10.0")) {
platform = "Windows 10";
} else if (ua.contains("Windows NT 6.3")) {
platform = "Windows 8.1";
} else if (ua.contains("Windows NT 6.2")) {
platform = "Windows 8";
} else if (ua.contains("Windows NT 6.1")) {
platform = "Windows 7";
} else if (ua.contains("Windows NT 6.0")) {
platform = "Windows Vista";
} else if (ua.contains("Windows NT 5.1")) {
platform = "Windows XP";
}
} else if (ua.contains("iPad")) {
platform = "iPad";
} else if (ua.contains("iPhone")) {
platform = "iPhone";
} else if (ua.contains("Android")) {
platform = "Android";
} else if (ua.contains("Linux")) {
platform = "Linux";
}
}
return platform;
}
/**
* 获取用户代理
*
* @param request HttpServletRequest
*/
private static String getUserAgent(HttpServletRequest request) {
return Objects.nonNull(request)
? request.getHeader(HttpHeaders.USER_AGENT)
: "";
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy