commit
3e49780fa2
@ -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的封装如下: |
@ -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; |
||||
|
||||
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();
|
||||
// }
|
||||
// }
|
||||
} |
||||
|
@ -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; |
||||
|
||||
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); |
||||
} |
||||
|
@ -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