commit
3e49780fa2
@ -1,32 +1,32 @@ |
|||||||
* [首页](/?t=1563439736156) |
* [首页](/?t=1563956863130) |
||||||
* 开发文档 |
* 开发文档 |
||||||
* [快速体验](files/10010_快速体验.md?t=1563439736157) |
* [快速体验](files/10010_快速体验.md?t=1563956863132) |
||||||
* [项目接入到SOP](files/10011_项目接入到SOP.md?t=1563439736174) |
* [项目接入到SOP](files/10011_项目接入到SOP.md?t=1563956863153) |
||||||
* [新增接口](files/10020_新增接口.md?t=1563439736174) |
* [新增接口](files/10020_新增接口.md?t=1563956863153) |
||||||
* [业务参数校验](files/10030_业务参数校验.md?t=1563439736174) |
* [业务参数校验](files/10030_业务参数校验.md?t=1563956863153) |
||||||
* [错误处理](files/10040_错误处理.md?t=1563439736174) |
* [错误处理](files/10040_错误处理.md?t=1563956863153) |
||||||
* [编写文档](files/10041_编写文档.md?t=1563439736174) |
* [编写文档](files/10041_编写文档.md?t=1563956863153) |
||||||
* [接口交互详解](files/10050_接口交互详解.md?t=1563439736174) |
* [接口交互详解](files/10050_接口交互详解.md?t=1563956863153) |
||||||
* [easyopen支持](files/10070_easyopen支持.md?t=1563439736175) |
* [easyopen支持](files/10070_easyopen支持.md?t=1563956863154) |
||||||
* [使用签名校验工具](files/10080_使用签名校验工具.md?t=1563439736175) |
* [使用签名校验工具](files/10080_使用签名校验工具.md?t=1563956863154) |
||||||
* [ISV管理](files/10085_ISV管理.md?t=1563439736175) |
* [ISV管理](files/10085_ISV管理.md?t=1563956863154) |
||||||
* [自定义路由](files/10086_自定义路由.md?t=1563439736175) |
* [自定义路由](files/10086_自定义路由.md?t=1563956863154) |
||||||
* [路由授权](files/10090_路由授权.md?t=1563439736175) |
* [路由授权](files/10090_路由授权.md?t=1563956863154) |
||||||
* [接口限流](files/10092_接口限流.md?t=1563439736175) |
* [接口限流](files/10092_接口限流.md?t=1563956863154) |
||||||
* [监控日志](files/10093_监控日志.md?t=1563439736175) |
* [监控日志](files/10093_监控日志.md?t=1563956863154) |
||||||
* [SDK开发](files/10095_SDK开发.md?t=1563439736175) |
* [SDK开发](files/10095_SDK开发.md?t=1563956863154) |
||||||
* [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1563439736176) |
* [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1563956863154) |
||||||
* [应用授权](files/10097_应用授权.md?t=1563439736176) |
* [应用授权](files/10097_应用授权.md?t=1563956863155) |
||||||
* [更改数据节点名称](files/10099_更改数据节点名称.md?t=1563439736176) |
* [更改数据节点名称](files/10099_更改数据节点名称.md?t=1563956863155) |
||||||
* [对接前端](files/10100_对接前端.md?t=1563439736176) |
* [传统web开发](files/10100_传统web开发.md?t=1563956863155) |
||||||
* [自定义过滤器](files/10102_自定义过滤器.md?t=1563439736176) |
* [自定义过滤器](files/10102_自定义过滤器.md?t=1563956863155) |
||||||
* [文件上传](files/10104_文件上传.md?t=1563439736176) |
* [文件上传](files/10104_文件上传.md?t=1563956863155) |
||||||
* [nacos注册中心](files/10106_nacos注册中心.md?t=1563439736176) |
* [nacos注册中心](files/10106_nacos注册中心.md?t=1563956863155) |
||||||
* [扩展其它注册中心](files/10107_扩展其它注册中心.md?t=1563439736176) |
* [扩展其它注册中心](files/10107_扩展其它注册中心.md?t=1563956863155) |
||||||
* [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1563439736176) |
* [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1563956863155) |
||||||
* 原理分析 |
* 原理分析 |
||||||
* [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1563439736177) |
* [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1563956863156) |
||||||
* [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1563439736177) |
* [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1563956863156) |
||||||
* [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1563439736177) |
* [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1563956863156) |
||||||
* [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1563439736177) |
* [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1563956863156) |
||||||
* [常见问题](files/90100_常见问题.md?t=1563439736177) |
* [常见问题](files/90100_常见问题.md?t=1563956863156) |
||||||
|
@ -1,41 +1,40 @@ |
|||||||
# 对接前端 |
# 传统web开发 |
||||||
|
|
||||||
开放平台一般对接服务端应用,开发者使用SDK来调用接口。 |
本篇介绍如何使用SOP进行传统web服务开发,即对接前端应用(H5、小程序、App)。 |
||||||
理论上来说,只要是客户端程序,都可以调用网关接口。因此,同样可以对接前端应用(H5、小程序、App)。 |
|
||||||
|
|
||||||
针对H5页面,配置方式如下: |
- 网关ZuulConfig继承WebappZuulConfiguration类 |
||||||
|
|
||||||
- 网关关闭签名校验。`ApiConfig.getInstance().setIgnoreValidate(true);` |
|
||||||
|
|
||||||
由于是网页调用接口,把秘钥放在前端意义不大,干脆直接关闭签名校验。 |
|
||||||
|
|
||||||
- 设置统一的数据节点 |
|
||||||
|
|
||||||
```java |
```java |
||||||
@Configuration |
@Configuration |
||||||
public class ZuulConfig extends AlipayZuulConfiguration { |
public class ZuulConfig extends WebappZuulConfiguration { |
||||||
|
|
||||||
static { |
static { |
||||||
... |
new ManagerInitializer(); |
||||||
ApiConfig.getInstance().setIgnoreValidate(true); |
|
||||||
ApiConfig.getInstance().setDataNameBuilder(new CustomDataNameBuilder()); |
|
||||||
... |
|
||||||
} |
} |
||||||
|
|
||||||
} |
} |
||||||
``` |
``` |
||||||
|
|
||||||
设置后,网关统一的返回结果如下: |
设置完毕,网关不在进行签名验证,网关统一的返回结果如下: |
||||||
|
|
||||||
```json |
```json |
||||||
{ |
{ |
||||||
"result": { |
"result": { |
||||||
... |
... |
||||||
}, |
} |
||||||
"sign": "xxxxx" |
|
||||||
} |
} |
||||||
``` |
``` |
||||||
|
|
||||||
|
- 微服务OpenServiceConfig继承WebappServiceConfiguration类 |
||||||
|
|
||||||
|
```java |
||||||
|
public class OpenServiceConfig extends WebappServiceConfiguration { |
||||||
|
... |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
其它内容不变 |
||||||
|
|
||||||
- 封装请求工具【可选】 |
- 封装请求工具【可选】 |
||||||
|
|
||||||
封装请求,方便调用,针对vue的封装如下: |
封装请求,方便调用,针对vue的封装如下: |
@ -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); |
||||||
|
} |
||||||
|
} |
@ -1,26 +1,25 @@ |
|||||||
package com.gitee.sop.gatewaycommon.zuul.filter; |
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 org.springframework.cloud.netflix.zuul.filters.pre.FormBodyWrapperFilter; |
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest; |
|
||||||
|
|
||||||
/** |
/** |
||||||
* @author tanghc |
* @author tanghc |
||||||
*/ |
*/ |
||||||
public class FormBodyWrapperFilterExt extends FormBodyWrapperFilter { |
public class FormBodyWrapperFilterExt extends FormBodyWrapperFilter { |
||||||
|
|
||||||
|
|
||||||
@Override |
@Override |
||||||
public boolean shouldFilter() { |
public int filterOrder() { |
||||||
RequestContext ctx = RequestContext.getCurrentContext(); |
return BaseZuulFilter.FORM_BODY_WRAPPER_FILTER_ORDER; |
||||||
HttpServletRequest request = ctx.getRequest(); |
|
||||||
// 如果是文件上传请求,不需要包装
|
|
||||||
if (RequestUtil.isMultipart(request)) { |
|
||||||
return false; |
|
||||||
} else { |
|
||||||
return super.shouldFilter(); |
|
||||||
} |
|
||||||
} |
} |
||||||
|
|
||||||
|
// @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; |
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 org.springframework.cloud.netflix.zuul.filters.pre.Servlet30WrapperFilter; |
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest; |
|
||||||
|
|
||||||
/** |
/** |
||||||
* @author tanghc |
* @author tanghc |
||||||
*/ |
*/ |
||||||
public class Servlet30WrapperFilterExt extends Servlet30WrapperFilter { |
public class Servlet30WrapperFilterExt extends Servlet30WrapperFilter { |
||||||
@Override |
@Override |
||||||
public boolean shouldFilter() { |
public int filterOrder() { |
||||||
RequestContext ctx = RequestContext.getCurrentContext(); |
return BaseZuulFilter.SERVLET_30_WRAPPER_FILTER_ORDER; |
||||||
HttpServletRequest request = ctx.getRequest(); |
|
||||||
// 如果是文件上传请求,不需要包装
|
|
||||||
if (RequestUtil.isMultipart(request)) { |
|
||||||
return false; |
|
||||||
} else { |
|
||||||
return super.shouldFilter(); |
|
||||||
} |
|
||||||
} |
} |
||||||
|
|
||||||
|
// @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,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"); |
||||||
|
} |
||||||
|
} |
@ -1,12 +1,11 @@ |
|||||||
package com.gitee.sop.servercommon.param; |
package com.gitee.sop.servercommon.param; |
||||||
|
|
||||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver; |
import org.springframework.web.method.support.HandlerMethodArgumentResolver; |
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; |
||||||
import java.util.List; |
|
||||||
|
|
||||||
/** |
/** |
||||||
* @author tanghc |
* @author tanghc |
||||||
*/ |
*/ |
||||||
public interface SopHandlerMethodArgumentResolver extends HandlerMethodArgumentResolver { |
public interface SopHandlerMethodArgumentResolver extends HandlerMethodArgumentResolver { |
||||||
void setResolvers(List<HandlerMethodArgumentResolver> resolvers); |
void setRequestMappingHandlerAdapter(RequestMappingHandlerAdapter requestMappingHandlerAdapter); |
||||||
} |
} |
||||||
|
@ -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; |
||||||
|
} |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue