mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 21:57:56 +08:00
Merge branch 'master' into registry-nacos
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
# changelog
|
||||
|
||||
## 1.13.1
|
||||
|
||||
- 支持json方式请求(application/json)
|
||||
|
||||
## 1.13.0
|
||||
|
||||
|
@@ -1,32 +1,32 @@
|
||||
* [首页](/?t=1563439736156)
|
||||
* [首页](/?t=1563956863130)
|
||||
* 开发文档
|
||||
* [快速体验](files/10010_快速体验.md?t=1563439736157)
|
||||
* [项目接入到SOP](files/10011_项目接入到SOP.md?t=1563439736174)
|
||||
* [新增接口](files/10020_新增接口.md?t=1563439736174)
|
||||
* [业务参数校验](files/10030_业务参数校验.md?t=1563439736174)
|
||||
* [错误处理](files/10040_错误处理.md?t=1563439736174)
|
||||
* [编写文档](files/10041_编写文档.md?t=1563439736174)
|
||||
* [接口交互详解](files/10050_接口交互详解.md?t=1563439736174)
|
||||
* [easyopen支持](files/10070_easyopen支持.md?t=1563439736175)
|
||||
* [使用签名校验工具](files/10080_使用签名校验工具.md?t=1563439736175)
|
||||
* [ISV管理](files/10085_ISV管理.md?t=1563439736175)
|
||||
* [自定义路由](files/10086_自定义路由.md?t=1563439736175)
|
||||
* [路由授权](files/10090_路由授权.md?t=1563439736175)
|
||||
* [接口限流](files/10092_接口限流.md?t=1563439736175)
|
||||
* [监控日志](files/10093_监控日志.md?t=1563439736175)
|
||||
* [SDK开发](files/10095_SDK开发.md?t=1563439736175)
|
||||
* [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1563439736176)
|
||||
* [应用授权](files/10097_应用授权.md?t=1563439736176)
|
||||
* [更改数据节点名称](files/10099_更改数据节点名称.md?t=1563439736176)
|
||||
* [对接前端](files/10100_对接前端.md?t=1563439736176)
|
||||
* [自定义过滤器](files/10102_自定义过滤器.md?t=1563439736176)
|
||||
* [文件上传](files/10104_文件上传.md?t=1563439736176)
|
||||
* [nacos注册中心](files/10106_nacos注册中心.md?t=1563439736176)
|
||||
* [扩展其它注册中心](files/10107_扩展其它注册中心.md?t=1563439736176)
|
||||
* [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1563439736176)
|
||||
* [快速体验](files/10010_快速体验.md?t=1563956863132)
|
||||
* [项目接入到SOP](files/10011_项目接入到SOP.md?t=1563956863153)
|
||||
* [新增接口](files/10020_新增接口.md?t=1563956863153)
|
||||
* [业务参数校验](files/10030_业务参数校验.md?t=1563956863153)
|
||||
* [错误处理](files/10040_错误处理.md?t=1563956863153)
|
||||
* [编写文档](files/10041_编写文档.md?t=1563956863153)
|
||||
* [接口交互详解](files/10050_接口交互详解.md?t=1563956863153)
|
||||
* [easyopen支持](files/10070_easyopen支持.md?t=1563956863154)
|
||||
* [使用签名校验工具](files/10080_使用签名校验工具.md?t=1563956863154)
|
||||
* [ISV管理](files/10085_ISV管理.md?t=1563956863154)
|
||||
* [自定义路由](files/10086_自定义路由.md?t=1563956863154)
|
||||
* [路由授权](files/10090_路由授权.md?t=1563956863154)
|
||||
* [接口限流](files/10092_接口限流.md?t=1563956863154)
|
||||
* [监控日志](files/10093_监控日志.md?t=1563956863154)
|
||||
* [SDK开发](files/10095_SDK开发.md?t=1563956863154)
|
||||
* [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1563956863154)
|
||||
* [应用授权](files/10097_应用授权.md?t=1563956863155)
|
||||
* [更改数据节点名称](files/10099_更改数据节点名称.md?t=1563956863155)
|
||||
* [传统web开发](files/10100_传统web开发.md?t=1563956863155)
|
||||
* [自定义过滤器](files/10102_自定义过滤器.md?t=1563956863155)
|
||||
* [文件上传](files/10104_文件上传.md?t=1563956863155)
|
||||
* [nacos注册中心](files/10106_nacos注册中心.md?t=1563956863155)
|
||||
* [扩展其它注册中心](files/10107_扩展其它注册中心.md?t=1563956863155)
|
||||
* [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1563956863155)
|
||||
* 原理分析
|
||||
* [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1563439736177)
|
||||
* [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1563439736177)
|
||||
* [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1563439736177)
|
||||
* [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1563439736177)
|
||||
* [常见问题](files/90100_常见问题.md?t=1563439736177)
|
||||
* [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1563956863156)
|
||||
* [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1563956863156)
|
||||
* [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1563956863156)
|
||||
* [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1563956863156)
|
||||
* [常见问题](files/90100_常见问题.md?t=1563956863156)
|
||||
|
@@ -1,41 +1,40 @@
|
||||
# 对接前端
|
||||
# 传统web开发
|
||||
|
||||
开放平台一般对接服务端应用,开发者使用SDK来调用接口。
|
||||
理论上来说,只要是客户端程序,都可以调用网关接口。因此,同样可以对接前端应用(H5、小程序、App)。
|
||||
本篇介绍如何使用SOP进行传统web服务开发,即对接前端应用(H5、小程序、App)。
|
||||
|
||||
针对H5页面,配置方式如下:
|
||||
|
||||
- 网关关闭签名校验。`ApiConfig.getInstance().setIgnoreValidate(true);`
|
||||
|
||||
由于是网页调用接口,把秘钥放在前端意义不大,干脆直接关闭签名校验。
|
||||
|
||||
- 设置统一的数据节点
|
||||
- 网关ZuulConfig继承WebappZuulConfiguration类
|
||||
|
||||
```java
|
||||
@Configuration
|
||||
public class ZuulConfig extends AlipayZuulConfiguration {
|
||||
public class ZuulConfig extends WebappZuulConfiguration {
|
||||
|
||||
static {
|
||||
...
|
||||
ApiConfig.getInstance().setIgnoreValidate(true);
|
||||
ApiConfig.getInstance().setDataNameBuilder(new CustomDataNameBuilder());
|
||||
...
|
||||
new ManagerInitializer();
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
设置后,网关统一的返回结果如下:
|
||||
设置完毕,网关不在进行签名验证,网关统一的返回结果如下:
|
||||
|
||||
```json
|
||||
{
|
||||
"result": {
|
||||
...
|
||||
},
|
||||
"sign": "xxxxx"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- 微服务OpenServiceConfig继承WebappServiceConfiguration类
|
||||
|
||||
```java
|
||||
public class OpenServiceConfig extends WebappServiceConfiguration {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
其它内容不变
|
||||
|
||||
- 封装请求工具【可选】
|
||||
|
||||
封装请求,方便调用,针对vue的封装如下:
|
@@ -30,7 +30,7 @@
|
||||
<dependency>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-registry-api</artifactId>
|
||||
<version>1.13.0-SNAPSHOT</version>
|
||||
<version>1.13.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<!-- easyopen starter -->
|
||||
|
@@ -5,7 +5,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-common</artifactId>
|
||||
<version>1.13.0-SNAPSHOT</version>
|
||||
<version>1.13.1-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<properties>
|
||||
|
@@ -5,11 +5,11 @@
|
||||
<parent>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-common</artifactId>
|
||||
<version>1.13.0-SNAPSHOT</version>
|
||||
<version>1.13.1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>sop-gateway-common</artifactId>
|
||||
<version>1.13.0-SNAPSHOT</version>
|
||||
<version>1.13.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>sop-gateway-common</name>
|
||||
|
@@ -1,5 +1,7 @@
|
||||
package com.gitee.sop.gatewaycommon.util;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.apache.commons.fileupload.FileItem;
|
||||
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
|
||||
import org.apache.commons.fileupload.servlet.ServletFileUpload;
|
||||
@@ -35,6 +37,9 @@ public class RequestUtil {
|
||||
public static final String MULTIPART = "multipart/";
|
||||
|
||||
private static final String UTF8 = "UTF-8";
|
||||
private static final String IP_UNKNOWN = "unknown";
|
||||
private static final String IP_LOCAL = "127.0.0.1";
|
||||
private static final int IP_LEN = 15;
|
||||
|
||||
/**
|
||||
* 将get类型的参数转换成map,
|
||||
@@ -114,6 +119,31 @@ public class RequestUtil {
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换json请求到Map,
|
||||
* @param request 请求类型为application/json的Request
|
||||
* @return 返回Map
|
||||
*/
|
||||
public static Map<String, String> convertJsonRequestToMap(HttpServletRequest request) {
|
||||
try {
|
||||
String text = getText(request);
|
||||
JSONObject parseObject = JSON.parseObject(text);
|
||||
Map<String, String> params = new HashMap<>(parseObject.size());
|
||||
for (Map.Entry<String, Object> entry : parseObject.entrySet()) {
|
||||
params.put(entry.getKey(), String.valueOf(entry.getValue()));
|
||||
}
|
||||
return params;
|
||||
} catch (IOException e) {
|
||||
log.error("解析json请求失败", e);
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是文件上传请求
|
||||
* @param request 请求
|
||||
* @return true:是
|
||||
*/
|
||||
public static boolean isMultipart(HttpServletRequest request) {
|
||||
String contentType = request.getContentType();
|
||||
// Don't use this filter on GET method
|
||||
@@ -130,29 +160,32 @@ public class RequestUtil {
|
||||
|
||||
public static String getIP(HttpServletRequest request) {
|
||||
String ipAddress = request.getHeader("x-forwarded-for");
|
||||
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
|
||||
if (ipAddress == null || ipAddress.length() == 0 || IP_UNKNOWN.equalsIgnoreCase(ipAddress)) {
|
||||
ipAddress = request.getHeader("Proxy-Client-IP");
|
||||
}
|
||||
|
||||
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
|
||||
if (ipAddress == null || ipAddress.length() == 0 || IP_UNKNOWN.equalsIgnoreCase(ipAddress)) {
|
||||
ipAddress = request.getHeader("WL-Proxy-Client-IP");
|
||||
}
|
||||
|
||||
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
|
||||
if (ipAddress == null || ipAddress.length() == 0 || IP_UNKNOWN.equalsIgnoreCase(ipAddress)) {
|
||||
ipAddress = request.getRemoteAddr();
|
||||
if ("127.0.0.1".equals(ipAddress)) {
|
||||
if (IP_LOCAL.equals(ipAddress)) {
|
||||
// 根据网卡取本机配置的IP
|
||||
try {
|
||||
InetAddress inet = InetAddress.getLocalHost();
|
||||
ipAddress = inet.getHostAddress();
|
||||
} catch (UnknownHostException var3) {
|
||||
}
|
||||
} catch (UnknownHostException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
if (ipAddress != null && ipAddress.length() > 15 && ipAddress.indexOf(",") > 0) {
|
||||
}
|
||||
|
||||
// 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
|
||||
if (ipAddress != null && ipAddress.length() > IP_LEN) {
|
||||
if (ipAddress.indexOf(",") > 0) {
|
||||
ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
|
||||
}
|
||||
|
||||
}
|
||||
return ipAddress;
|
||||
}
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@ import com.gitee.sop.gatewaycommon.manager.RouteRepositoryContext;
|
||||
import com.gitee.sop.gatewaycommon.zuul.filter.ErrorFilter;
|
||||
import com.gitee.sop.gatewaycommon.zuul.filter.FormBodyWrapperFilterExt;
|
||||
import com.gitee.sop.gatewaycommon.zuul.filter.PostResultFilter;
|
||||
import com.gitee.sop.gatewaycommon.zuul.filter.PreHttpServletRequestWrapperFilter;
|
||||
import com.gitee.sop.gatewaycommon.zuul.filter.PreLimitFilter;
|
||||
import com.gitee.sop.gatewaycommon.zuul.filter.PreValidateFilter;
|
||||
import com.gitee.sop.gatewaycommon.zuul.filter.Servlet30WrapperFilterExt;
|
||||
@@ -43,6 +44,11 @@ public class BaseZuulConfiguration extends AbstractConfiguration {
|
||||
return zuulRouteRepository;
|
||||
}
|
||||
|
||||
@Bean
|
||||
PreHttpServletRequestWrapperFilter preHttpServletRequestWrapperFilter() {
|
||||
return new PreHttpServletRequestWrapperFilter();
|
||||
}
|
||||
|
||||
@Bean
|
||||
FormBodyWrapperFilterExt formBodyWrapperFilterExt() {
|
||||
return new FormBodyWrapperFilterExt();
|
||||
|
@@ -0,0 +1,18 @@
|
||||
package com.gitee.sop.gatewaycommon.zuul.configuration;
|
||||
|
||||
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
|
||||
import com.gitee.sop.gatewaycommon.result.CustomDataNameBuilder;
|
||||
|
||||
/**
|
||||
* 支持传统webapp开发,没有签名验证
|
||||
*
|
||||
* @author tanghc
|
||||
*/
|
||||
public class WebappZuulConfiguration extends BaseZuulConfiguration {
|
||||
|
||||
static {
|
||||
ApiConfig.getInstance().setIgnoreValidate(true);
|
||||
ApiConfig.getInstance().setDataNameBuilder(new CustomDataNameBuilder());
|
||||
ApiConfig.getInstance().setShowReturnSign(false);
|
||||
}
|
||||
}
|
@@ -14,6 +14,12 @@ public abstract class BaseZuulFilter extends ZuulFilter {
|
||||
|
||||
protected Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
public static final int HTTP_SERVLET_REQUEST_WRAPPER_FILTER_ORDER = -2000;
|
||||
|
||||
public static final int SERVLET_30_WRAPPER_FILTER_ORDER = HTTP_SERVLET_REQUEST_WRAPPER_FILTER_ORDER + 1;
|
||||
|
||||
public static final int FORM_BODY_WRAPPER_FILTER_ORDER = SERVLET_30_WRAPPER_FILTER_ORDER + 1;
|
||||
|
||||
/** 签名验证过滤 */
|
||||
public static final int PRE_VALIDATE_FILTER_ORDER = -1000;
|
||||
|
||||
|
@@ -1,26 +1,25 @@
|
||||
package com.gitee.sop.gatewaycommon.zuul.filter;
|
||||
|
||||
import com.gitee.sop.gatewaycommon.util.RequestUtil;
|
||||
import com.netflix.zuul.context.RequestContext;
|
||||
import org.springframework.cloud.netflix.zuul.filters.pre.FormBodyWrapperFilter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public class FormBodyWrapperFilterExt extends FormBodyWrapperFilter {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean shouldFilter() {
|
||||
RequestContext ctx = RequestContext.getCurrentContext();
|
||||
HttpServletRequest request = ctx.getRequest();
|
||||
// 如果是文件上传请求,不需要包装
|
||||
if (RequestUtil.isMultipart(request)) {
|
||||
return false;
|
||||
} else {
|
||||
return super.shouldFilter();
|
||||
}
|
||||
public int filterOrder() {
|
||||
return BaseZuulFilter.FORM_BODY_WRAPPER_FILTER_ORDER;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public boolean shouldFilter() {
|
||||
// RequestContext ctx = RequestContext.getCurrentContext();
|
||||
// HttpServletRequest request = ctx.getRequest();
|
||||
// // 如果是文件上传请求,不需要包装
|
||||
// if (RequestUtil.isMultipart(request)) {
|
||||
// return false;
|
||||
// } else {
|
||||
// return super.shouldFilter();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
@@ -0,0 +1,31 @@
|
||||
package com.gitee.sop.gatewaycommon.zuul.filter;
|
||||
|
||||
import com.netflix.zuul.context.RequestContext;
|
||||
import com.netflix.zuul.exception.ZuulException;
|
||||
import com.netflix.zuul.http.HttpServletRequestWrapper;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 包装一下Request,使得request.getInputStream()方法可以调用多次
|
||||
* @author tanghc
|
||||
*/
|
||||
public class PreHttpServletRequestWrapperFilter extends BaseZuulFilter {
|
||||
@Override
|
||||
protected FilterType getFilterType() {
|
||||
return FilterType.PRE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getFilterOrder() {
|
||||
return HTTP_SERVLET_REQUEST_WRAPPER_FILTER_ORDER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doRun(RequestContext requestContext) throws ZuulException {
|
||||
HttpServletRequest request = requestContext.getRequest();
|
||||
HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper(request);
|
||||
requestContext.setRequest(wrapper);
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -1,24 +1,25 @@
|
||||
package com.gitee.sop.gatewaycommon.zuul.filter;
|
||||
|
||||
import com.gitee.sop.gatewaycommon.util.RequestUtil;
|
||||
import com.netflix.zuul.context.RequestContext;
|
||||
import org.springframework.cloud.netflix.zuul.filters.pre.Servlet30WrapperFilter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public class Servlet30WrapperFilterExt extends Servlet30WrapperFilter {
|
||||
@Override
|
||||
public boolean shouldFilter() {
|
||||
RequestContext ctx = RequestContext.getCurrentContext();
|
||||
HttpServletRequest request = ctx.getRequest();
|
||||
// 如果是文件上传请求,不需要包装
|
||||
if (RequestUtil.isMultipart(request)) {
|
||||
return false;
|
||||
} else {
|
||||
return super.shouldFilter();
|
||||
}
|
||||
public int filterOrder() {
|
||||
return BaseZuulFilter.SERVLET_30_WRAPPER_FILTER_ORDER;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public boolean shouldFilter() {
|
||||
// RequestContext ctx = RequestContext.getCurrentContext();
|
||||
// HttpServletRequest request = ctx.getRequest();
|
||||
// // 如果是文件上传请求,不需要包装
|
||||
// if (RequestUtil.isMultipart(request)) {
|
||||
// return false;
|
||||
// } else {
|
||||
// return super.shouldFilter();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
@@ -1,21 +1,15 @@
|
||||
package com.gitee.sop.gatewaycommon.zuul.param;
|
||||
|
||||
import com.gitee.sop.gatewaycommon.bean.SopConstants;
|
||||
import com.gitee.sop.gatewaycommon.message.ErrorEnum;
|
||||
import com.gitee.sop.gatewaycommon.param.ApiParam;
|
||||
import com.gitee.sop.gatewaycommon.param.BaseParamBuilder;
|
||||
import com.gitee.sop.gatewaycommon.util.RequestUtil;
|
||||
import com.netflix.zuul.context.RequestContext;
|
||||
import com.netflix.zuul.http.HttpServletRequestWrapper;
|
||||
import com.netflix.zuul.http.ServletInputStreamWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.fileupload.servlet.ServletFileUpload;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -33,32 +27,24 @@ public class ZuulParamBuilder extends BaseParamBuilder<RequestContext> {
|
||||
@Override
|
||||
public Map<String, String> buildRequestParams(RequestContext ctx) {
|
||||
HttpServletRequest request = ctx.getRequest();
|
||||
Map<String, String> params = null;
|
||||
|
||||
Map<String, String> params;
|
||||
if (GET.equalsIgnoreCase(request.getMethod())) {
|
||||
params = RequestUtil.convertRequestParamsToMap(request);
|
||||
} else {
|
||||
String contentType = request.getContentType();
|
||||
|
||||
if (contentType == null) {
|
||||
contentType = "";
|
||||
}
|
||||
|
||||
contentType = contentType.toLowerCase();
|
||||
|
||||
// json或者纯文本形式
|
||||
if (contentType.contains(CONTENT_TYPE_JSON) || contentType.contains(CONTENT_TYPE_TEXT)) {
|
||||
throw ErrorEnum.ISV_INVALID_CONTENT_TYPE.getErrorMeta().getException();
|
||||
params = RequestUtil.convertJsonRequestToMap(request);
|
||||
} else if (ServletFileUpload.isMultipartContent(request)) {
|
||||
MultipartRequestWrapper wrapper = new MultipartRequestWrapper(request);
|
||||
ctx.setRequest(wrapper);
|
||||
ctx.getZuulRequestHeaders().put("content-type", wrapper.getContentType());
|
||||
params = RequestUtil.convertMultipartRequestToMap(wrapper);
|
||||
params = RequestUtil.convertMultipartRequestToMap(request);
|
||||
} else {
|
||||
params = RequestUtil.convertRequestParamsToMap(request);
|
||||
}
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
@@ -78,45 +64,4 @@ public class ZuulParamBuilder extends BaseParamBuilder<RequestContext> {
|
||||
return apiParam;
|
||||
}
|
||||
|
||||
public static class MultipartRequestWrapper extends HttpServletRequestWrapper {
|
||||
private HttpServletRequest request;
|
||||
|
||||
private volatile byte[] contentData;
|
||||
|
||||
private MediaType contentType;
|
||||
|
||||
private int contentLength;
|
||||
|
||||
public MultipartRequestWrapper(HttpServletRequest request) {
|
||||
super(request);
|
||||
this.request = request;
|
||||
try {
|
||||
this.contentType = MediaType.valueOf(this.request.getContentType());
|
||||
byte[] input = IOUtils.toByteArray(request.getInputStream());
|
||||
this.contentData = input;
|
||||
this.contentLength = input.length;
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("Cannot convert form data", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return this.contentType.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentLength() {
|
||||
if (super.getContentLength() <= 0) {
|
||||
return super.getContentLength();
|
||||
}
|
||||
return this.contentLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletInputStream getInputStream() throws IOException {
|
||||
return new ServletInputStreamWrapper(this.contentData);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-registry-api</artifactId>
|
||||
<version>1.13.0-SNAPSHOT</version>
|
||||
<version>1.13.1-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
@@ -6,11 +6,11 @@
|
||||
<parent>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-common</artifactId>
|
||||
<version>1.13.0-SNAPSHOT</version>
|
||||
<version>1.13.1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>sop-service-common</artifactId>
|
||||
<version>1.13.0-SNAPSHOT</version>
|
||||
<version>1.13.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>sop-service-common</name>
|
||||
|
@@ -33,7 +33,6 @@ public class AlipayServiceConfiguration extends BaseServiceConfiguration {
|
||||
protected void doAfter() {
|
||||
super.doAfter();
|
||||
SopHandlerMethodArgumentResolver sopHandlerMethodArgumentResolver = ServiceConfig.getInstance().getMethodArgumentResolver();
|
||||
List<HandlerMethodArgumentResolver> defaultArgumentResolvers = requestMappingHandlerAdapter.getArgumentResolvers();
|
||||
sopHandlerMethodArgumentResolver.setResolvers(defaultArgumentResolvers);
|
||||
sopHandlerMethodArgumentResolver.setRequestMappingHandlerAdapter(requestMappingHandlerAdapter);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,14 @@
|
||||
package com.gitee.sop.servercommon.configuration;
|
||||
|
||||
import com.gitee.sop.servercommon.bean.ServiceConfig;
|
||||
|
||||
/**
|
||||
* 通用web
|
||||
* @author tanghc
|
||||
*/
|
||||
public class WebappServiceConfiguration extends BaseServiceConfiguration {
|
||||
static {
|
||||
// 默认版本号为1.0
|
||||
ServiceConfig.getInstance().setDefaultVersion("1.0");
|
||||
}
|
||||
}
|
@@ -24,6 +24,9 @@ import java.util.Set;
|
||||
@Getter
|
||||
public class DefaultRequestMappingEvent implements RequestMappingEvent {
|
||||
|
||||
/** 接口名规则:允许字母、数字、点、下划线 */
|
||||
private static final String REGEX_API_NAME = "^[a-zA-Z0-9\\.\\_\\-]+$";
|
||||
|
||||
private ApiMetaManager apiMetaManager;
|
||||
private Environment environment;
|
||||
|
||||
@@ -85,6 +88,7 @@ public class DefaultRequestMappingEvent implements RequestMappingEvent {
|
||||
if (name == null) {
|
||||
name = buildName(path);
|
||||
}
|
||||
this.checkApiName(name);
|
||||
ServiceApiInfo.ApiMeta apiMeta = new ServiceApiInfo.ApiMeta(name, path, version);
|
||||
apiMeta.setIgnoreValidate(BooleanUtils.toInteger(apiMappingInfo.isIgnoreValidate()));
|
||||
apiMeta.setMergeResult(BooleanUtils.toInteger(apiMappingInfo.isMergeResult()));
|
||||
@@ -94,6 +98,12 @@ public class DefaultRequestMappingEvent implements RequestMappingEvent {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void checkApiName(String name) {
|
||||
if (!name.matches(REGEX_API_NAME)) {
|
||||
throw new IllegalArgumentException("接口名称只允许【字母、数字、点(.)、下划线(_)、减号(-)】,错误接口:" + name);
|
||||
}
|
||||
}
|
||||
|
||||
protected String buildName(String path) {
|
||||
return MappingUtil.buildApiName(path);
|
||||
}
|
||||
|
@@ -32,7 +32,7 @@ public class ServiceZookeeperApiMetaManager implements ApiMetaManager {
|
||||
* zookeeper存放接口路由信息的根目录
|
||||
*/
|
||||
public static final String SOP_SERVICE_ROUTE_PATH = ServiceConstants.SOP_SERVICE_ROUTE_PATH;
|
||||
public static final String PATH_START_CHAR = "/";
|
||||
public static final String PATH_SPLIT = "/";
|
||||
|
||||
private final String routeRootPath = SOP_SERVICE_ROUTE_PATH;
|
||||
|
||||
@@ -60,6 +60,7 @@ public class ServiceZookeeperApiMetaManager implements ApiMetaManager {
|
||||
*/
|
||||
protected void uploadServiceId(Environment environment) {
|
||||
try {
|
||||
this.checkZookeeperNode(serviceId, "serviceId(" + serviceId + ")不能有斜杠字符'/'");
|
||||
ServiceRouteInfo serviceRouteInfo = this.buildServiceRouteInfo();
|
||||
// 保存路径
|
||||
String savePath = routeRootPath + "/" + serviceId;
|
||||
@@ -109,9 +110,11 @@ public class ServiceZookeeperApiMetaManager implements ApiMetaManager {
|
||||
|
||||
protected GatewayRouteDefinition buildGatewayRouteDefinition(ServiceApiInfo serviceApiInfo, ServiceApiInfo.ApiMeta apiMeta) {
|
||||
GatewayRouteDefinition gatewayRouteDefinition = new GatewayRouteDefinition();
|
||||
String routeId = apiMeta.fetchNameVersion();
|
||||
this.checkZookeeperNode(routeId, "接口定义(" + routeId + ")不能有斜杠字符'/'");
|
||||
// 唯一id规则:接口名 + 版本号
|
||||
BeanUtils.copyProperties(apiMeta, gatewayRouteDefinition);
|
||||
gatewayRouteDefinition.setId(apiMeta.fetchNameVersion());
|
||||
gatewayRouteDefinition.setId(routeId);
|
||||
gatewayRouteDefinition.setFilters(Collections.emptyList());
|
||||
String uri = this.buildUri(serviceApiInfo, apiMeta);
|
||||
String path = this.buildServletPath(serviceApiInfo, apiMeta);
|
||||
@@ -129,8 +132,8 @@ public class ServiceZookeeperApiMetaManager implements ApiMetaManager {
|
||||
if (servletPath == null) {
|
||||
servletPath = "";
|
||||
}
|
||||
if (!servletPath.startsWith(PATH_START_CHAR)) {
|
||||
servletPath = PATH_START_CHAR + servletPath;
|
||||
if (!servletPath.startsWith(PATH_SPLIT)) {
|
||||
servletPath = PATH_SPLIT + servletPath;
|
||||
}
|
||||
return servletPath;
|
||||
}
|
||||
@@ -181,11 +184,17 @@ public class ServiceZookeeperApiMetaManager implements ApiMetaManager {
|
||||
List<GatewayRouteDefinition> routeDefinitionList = serviceRouteInfo.getRouteDefinitionList();
|
||||
for (GatewayRouteDefinition routeDefinition : routeDefinitionList) {
|
||||
// 父目录/子目录
|
||||
String savePath = parentPath + PATH_START_CHAR + routeDefinition.getId();
|
||||
String savePath = parentPath + PATH_SPLIT + routeDefinition.getId();
|
||||
String routeDefinitionJson = JSON.toJSONString(routeDefinition);
|
||||
log.info("上传路由配置到zookeeper,路径:{},路由数据:{}", savePath, routeDefinitionJson);
|
||||
this.zookeeperTool.createOrUpdateData(savePath, routeDefinitionJson);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkZookeeperNode(String path, String errorMsg) {
|
||||
if (path.contains(PATH_SPLIT)) {
|
||||
throw new IllegalArgumentException(errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -11,9 +11,9 @@ import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@@ -25,16 +25,15 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
*/
|
||||
public class ApiArgumentResolver implements SopHandlerMethodArgumentResolver {
|
||||
|
||||
private final Map<MethodParameter, HandlerMethodArgumentResolver> argumentResolverCache =
|
||||
new ConcurrentHashMap<>(256);
|
||||
private final Map<MethodParameter, HandlerMethodArgumentResolver> argumentResolverCache = new ConcurrentHashMap<>(256);
|
||||
|
||||
private final ParamValidator paramValidator = new ServiceParamValidator();
|
||||
private ParamValidator paramValidator = new ServiceParamValidator();
|
||||
|
||||
private List<HandlerMethodArgumentResolver> argumentResolvers = Collections.emptyList();
|
||||
private RequestMappingHandlerAdapter requestMappingHandlerAdapter;
|
||||
|
||||
@Override
|
||||
public void setResolvers(List<HandlerMethodArgumentResolver> resolvers) {
|
||||
this.argumentResolvers = resolvers;
|
||||
public void setRequestMappingHandlerAdapter(RequestMappingHandlerAdapter requestMappingHandlerAdapter) {
|
||||
this.requestMappingHandlerAdapter = requestMappingHandlerAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -61,18 +60,19 @@ public class ApiArgumentResolver implements SopHandlerMethodArgumentResolver {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取参数对象,将request中的参数绑定到实体对象中去
|
||||
*
|
||||
* @param methodParameter
|
||||
* @param nativeWebRequest
|
||||
* @return
|
||||
* @return 没有返回null
|
||||
*/
|
||||
protected Object getParamObject(MethodParameter methodParameter, NativeWebRequest nativeWebRequest) {
|
||||
String bizContent = nativeWebRequest.getParameter(ParamNames.BIZ_CONTENT_NAME);
|
||||
Class<?> parameterType = methodParameter.getParameterType();
|
||||
Object bizObj = null;
|
||||
if (bizContent != null) {
|
||||
Class<?> parameterType = methodParameter.getParameterType();
|
||||
bizObj = JSON.parseObject(bizContent, parameterType);
|
||||
}
|
||||
this.bindUploadFile(bizObj, nativeWebRequest);
|
||||
@@ -80,7 +80,7 @@ public class ApiArgumentResolver implements SopHandlerMethodArgumentResolver {
|
||||
}
|
||||
|
||||
/**
|
||||
* 将文件绑定到
|
||||
* 将上传文件对象绑定到属性中
|
||||
*
|
||||
* @param bizObj 业务参数
|
||||
* @param nativeWebRequest
|
||||
@@ -89,9 +89,9 @@ public class ApiArgumentResolver implements SopHandlerMethodArgumentResolver {
|
||||
if (bizObj == null) {
|
||||
return;
|
||||
}
|
||||
if (this.isMultipartRequest(nativeWebRequest)) {
|
||||
Object nativeRequest = nativeWebRequest.getNativeRequest();
|
||||
if (nativeRequest instanceof StandardMultipartHttpServletRequest) {
|
||||
StandardMultipartHttpServletRequest request = (StandardMultipartHttpServletRequest) nativeRequest;
|
||||
MultipartHttpServletRequest request = (MultipartHttpServletRequest) nativeRequest;
|
||||
Class<?> bizClass = bizObj.getClass();
|
||||
ReflectionUtils.doWithFields(bizClass, field -> {
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
@@ -102,10 +102,21 @@ public class ApiArgumentResolver implements SopHandlerMethodArgumentResolver {
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isMultipartRequest(NativeWebRequest nativeWebRequest) {
|
||||
return nativeWebRequest.getNativeRequest() instanceof MultipartHttpServletRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取其它的参数解析器
|
||||
*
|
||||
* @param parameter 业务参数
|
||||
* @return 返回合适参数解析器,没有返回null
|
||||
*/
|
||||
protected HandlerMethodArgumentResolver getOtherArgumentResolver(MethodParameter parameter) {
|
||||
HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
|
||||
if (result == null) {
|
||||
for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) {
|
||||
List<HandlerMethodArgumentResolver> argumentResolvers = this.requestMappingHandlerAdapter.getArgumentResolvers();
|
||||
for (HandlerMethodArgumentResolver methodArgumentResolver : argumentResolvers) {
|
||||
if (methodArgumentResolver instanceof SopHandlerMethodArgumentResolver) {
|
||||
continue;
|
||||
}
|
||||
@@ -119,4 +130,7 @@ public class ApiArgumentResolver implements SopHandlerMethodArgumentResolver {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setParamValidator(ParamValidator paramValidator) {
|
||||
this.paramValidator = paramValidator;
|
||||
}
|
||||
}
|
@@ -1,12 +1,11 @@
|
||||
package com.gitee.sop.servercommon.param;
|
||||
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public interface SopHandlerMethodArgumentResolver extends HandlerMethodArgumentResolver {
|
||||
void setResolvers(List<HandlerMethodArgumentResolver> resolvers);
|
||||
void setRequestMappingHandlerAdapter(RequestMappingHandlerAdapter requestMappingHandlerAdapter);
|
||||
}
|
||||
|
@@ -26,7 +26,7 @@
|
||||
<dependency>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-service-common</artifactId>
|
||||
<version>1.13.0-SNAPSHOT</version>
|
||||
<version>1.13.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
|
@@ -24,7 +24,7 @@
|
||||
<dependency>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-service-common</artifactId>
|
||||
<version>1.13.0-SNAPSHOT</version>
|
||||
<version>1.13.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
|
@@ -29,7 +29,7 @@
|
||||
<dependency>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-service-common</artifactId>
|
||||
<version>1.13.0-SNAPSHOT</version>
|
||||
<version>1.13.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
|
@@ -20,7 +20,7 @@
|
||||
<dependency>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-service-common</artifactId>
|
||||
<version>1.13.0-SNAPSHOT</version>
|
||||
<version>1.13.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<!-- eureka 服务发现 -->
|
||||
<dependency>
|
||||
|
@@ -24,7 +24,7 @@
|
||||
<dependency>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-service-common</artifactId>
|
||||
<version>1.13.0-SNAPSHOT</version>
|
||||
<version>1.13.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
|
@@ -105,10 +105,10 @@ public class AlipayController {
|
||||
public StoryVO getStory2(StoryParam story, HttpServletRequest request) {
|
||||
log.info("获取故事信息参数, story: {}", story);
|
||||
// 获取其它参数
|
||||
System.out.println(request.getParameter("app_id"));
|
||||
String app_id = request.getParameter("app_id");
|
||||
StoryVO storyVO = new StoryVO();
|
||||
storyVO.id = 1L;
|
||||
storyVO.name = "白雪公主";
|
||||
storyVO.name = "白雪公主, app_id:" + app_id;
|
||||
storyVO.gmt_create = new Date();
|
||||
return storyVO;
|
||||
}
|
||||
|
@@ -0,0 +1,94 @@
|
||||
package com.gitee.sop.storyweb.controller;
|
||||
|
||||
import com.gitee.sop.servercommon.annotation.ApiMapping;
|
||||
import com.gitee.sop.servercommon.util.UploadUtil;
|
||||
import lombok.Data;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 传统web开发实例
|
||||
* @author tanghc
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("food")
|
||||
public class TraditionalWebappController {
|
||||
|
||||
|
||||
// http://localhost:8081/getFoodById?id=1 网关入口
|
||||
// http://localhost:2222/food/getFoodById/?id=12 本地入口
|
||||
@ApiMapping(value = "getFoodById", method = RequestMethod.GET)
|
||||
public Food getFoodById(Integer id) {
|
||||
Food food = new Food();
|
||||
food.setId(id);
|
||||
food.setName("香蕉");
|
||||
food.setPrice(new BigDecimal(20.00));
|
||||
return food;
|
||||
}
|
||||
|
||||
// http://localhost:8081/getFoodById?id=2&version=1.1 网关入口
|
||||
// http://localhost:2222/food/getFoodById/?id=12&version=1.1
|
||||
@ApiMapping(value = "getFoodById", method = RequestMethod.GET, version = "1.1")
|
||||
public Food getFoodById2(Integer id) {
|
||||
Food food = new Food();
|
||||
food.setId(id);
|
||||
food.setName("香蕉2");
|
||||
food.setPrice(new BigDecimal(22.00));
|
||||
return food;
|
||||
}
|
||||
|
||||
// http://localhost:8081/getFoodByObj?id=2
|
||||
@ApiMapping(value = "getFoodByObj", method = RequestMethod.GET)
|
||||
public Food getFoodByObj(Food food) {
|
||||
return food;
|
||||
}
|
||||
|
||||
// http://localhost:8081/saveFood
|
||||
@ApiMapping(value = "saveFood", method = RequestMethod.POST)
|
||||
public Food saveFood(@RequestBody Food food) {
|
||||
food.setId(3);
|
||||
return food;
|
||||
}
|
||||
|
||||
@ApiMapping(value = "foodUpload", method = RequestMethod.POST)
|
||||
public Food upload(Food food, HttpServletRequest request) {
|
||||
// 获取上传的文件
|
||||
Collection<MultipartFile> uploadFiles = UploadUtil.getUploadFiles(request);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (MultipartFile multipartFile : uploadFiles) {
|
||||
sb.append(multipartFile.getOriginalFilename());
|
||||
}
|
||||
food.setId(4);
|
||||
food.setName("文件名称+" + sb.toString());
|
||||
return food;
|
||||
}
|
||||
|
||||
@ApiMapping(value = "foodUpload3", method = RequestMethod.POST)
|
||||
public Food upload3(Food food, MultipartFile file) {
|
||||
food.setId(5);
|
||||
food.setName("文件名称+" + file.getOriginalFilename());
|
||||
return food;
|
||||
}
|
||||
|
||||
@RequestMapping(value = "foodUpload2", method = RequestMethod.POST)
|
||||
public Food upload2(Food food, MultipartFile file) {
|
||||
food.setId(4);
|
||||
food.setName("文件名称2+" + file.getOriginalFilename());
|
||||
return food;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Food {
|
||||
private Integer id;
|
||||
private String name;
|
||||
private BigDecimal price;
|
||||
}
|
||||
|
||||
}
|
@@ -23,7 +23,7 @@
|
||||
<dependency>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-gateway-common</artifactId>
|
||||
<version>1.13.0-SNAPSHOT</version>
|
||||
<version>1.13.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<!-- ↓↓↓ 使用spring cloud zuul ↓↓↓ -->
|
||||
|
@@ -32,4 +32,15 @@ public class RedirectController {
|
||||
request.getRequestDispatcher(path).forward(request, response);
|
||||
}
|
||||
|
||||
@RequestMapping("/{method}")
|
||||
public void redirect2(
|
||||
@PathVariable("method") String method
|
||||
, HttpServletRequest request
|
||||
, HttpServletResponse response
|
||||
) throws ServletException, IOException {
|
||||
request.setAttribute(SopConstants.REDIRECT_METHOD_KEY, method);
|
||||
request.setAttribute(SopConstants.REDIRECT_VERSION_KEY, "1.0");
|
||||
request.getRequestDispatcher(path).forward(request, response);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@ import okhttp3.Cookie;
|
||||
import okhttp3.CookieJar;
|
||||
import okhttp3.FormBody;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.MultipartBody;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
@@ -22,13 +23,21 @@ import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* HTTP请求工具
|
||||
*
|
||||
* @author tanghc
|
||||
*/
|
||||
public class OpenHttp {
|
||||
private static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8");
|
||||
|
||||
private Map<String, List<Cookie>> cookieStore = new HashMap<String, List<Cookie>>();
|
||||
|
||||
private OkHttpClient httpClient;
|
||||
|
||||
public OpenHttp() {
|
||||
this(new OpenConfig());
|
||||
}
|
||||
|
||||
public OpenHttp(OpenConfig openConfig) {
|
||||
this.initHttpClient(openConfig);
|
||||
}
|
||||
@@ -69,24 +78,18 @@ public class OpenHttp {
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交表单
|
||||
*
|
||||
* @param url url
|
||||
* @param form 参数
|
||||
* 请求json数据,contentType=application/json
|
||||
* @param url 请求路径
|
||||
* @param json json数据
|
||||
* @param header header
|
||||
* @param method 请求方式,post,get等
|
||||
* @return
|
||||
* @return 返回响应结果
|
||||
* @throws IOException
|
||||
*/
|
||||
public String requestFormBody(String url, Map<String, String> form, Map<String, String> header, String method) throws IOException {
|
||||
FormBody.Builder paramBuilder = new FormBody.Builder(StandardCharsets.UTF_8);
|
||||
for (Map.Entry<String, String> entry : form.entrySet()) {
|
||||
paramBuilder.add(entry.getKey(), entry.getValue());
|
||||
}
|
||||
FormBody formBody = paramBuilder.build();
|
||||
public String requestJson(String url, String json, Map<String, String> header) throws IOException {
|
||||
RequestBody body = RequestBody.create(MEDIA_TYPE_JSON, json);
|
||||
Request.Builder requestBuilder = new Request.Builder()
|
||||
.url(url)
|
||||
.method(method, formBody);
|
||||
.post(body);
|
||||
// 添加header
|
||||
addHeader(requestBuilder, header);
|
||||
|
||||
@@ -101,6 +104,73 @@ public class OpenHttp {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交表单
|
||||
*
|
||||
* @param url url
|
||||
* @param form 参数
|
||||
* @param header header
|
||||
* @param method 请求方式,post,get等
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public String request(String url, Map<String, String> form, Map<String, String> header, String method) throws IOException {
|
||||
Request.Builder requestBuilder = buildRequestBuilder(url, form, method);
|
||||
// 添加header
|
||||
addHeader(requestBuilder, header);
|
||||
|
||||
Request request = requestBuilder.build();
|
||||
Response response = httpClient
|
||||
.newCall(request)
|
||||
.execute();
|
||||
try {
|
||||
return response.body().string();
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static Request.Builder buildRequestBuilder(String url, Map<String, String> form, String method) {
|
||||
switch (method) {
|
||||
case "get":
|
||||
return new Request.Builder()
|
||||
.url(buildHttpUrl(url, form))
|
||||
.get();
|
||||
case "head":
|
||||
return new Request.Builder()
|
||||
.url(buildHttpUrl(url, form))
|
||||
.head();
|
||||
case "put":
|
||||
return new Request.Builder()
|
||||
.url(url)
|
||||
.put(buildFormBody(form));
|
||||
case "delete":
|
||||
return new Request.Builder()
|
||||
.url(url)
|
||||
.delete(buildFormBody(form));
|
||||
default:
|
||||
return new Request.Builder()
|
||||
.url(url)
|
||||
.post(buildFormBody(form));
|
||||
}
|
||||
}
|
||||
|
||||
public static HttpUrl buildHttpUrl(String url, Map<String, String> form) {
|
||||
HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
|
||||
for (Map.Entry<String, String> entry : form.entrySet()) {
|
||||
urlBuilder.addQueryParameter(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return urlBuilder.build();
|
||||
}
|
||||
|
||||
public static FormBody buildFormBody(Map<String, String> form) {
|
||||
FormBody.Builder paramBuilder = new FormBody.Builder(StandardCharsets.UTF_8);
|
||||
for (Map.Entry<String, String> entry : form.entrySet()) {
|
||||
paramBuilder.add(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return paramBuilder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交表单,并且上传文件
|
||||
*
|
||||
@@ -162,4 +232,5 @@ public class OpenHttp {
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -42,7 +42,9 @@ public class OpenRequest {
|
||||
}
|
||||
return openHttp.get(url, header);
|
||||
} else {
|
||||
return openHttp.requestFormBody(url, form, header, requestMethod.name());
|
||||
return openHttp.request(url, form, header, requestMethod.name());
|
||||
// 下面这种方式也可以,以application/json方式请求
|
||||
// return openHttp.requestJson(url, JSON.toJSONString(form), header);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
|
@@ -25,7 +25,7 @@
|
||||
<dependency>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-registry-api</artifactId>
|
||||
<version>1.13.0-SNAPSHOT</version>
|
||||
<version>1.13.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
@@ -24,7 +24,6 @@ import java.util.concurrent.TimeUnit;
|
||||
* @author tanghc
|
||||
*/
|
||||
public class HttpTool {
|
||||
private static final String METHOD_GET = "get";
|
||||
private Map<String, List<Cookie>> cookieStore = new HashMap<String, List<Cookie>>();
|
||||
|
||||
private OkHttpClient httpClient;
|
||||
|
Reference in New Issue
Block a user