Python 官方文档:入门教程 => 点击学习
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 作为《sprin
这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos
其次是修改响应,如下图,服务提供方provider-hello的原始响应只有response-tag字段,经过网关时被塞入了gateway-response-tag字段,最终浏览器收到的响应就是response-tag和gateway-response-tag两个字段:
总的来说,今天要做具体事情如下:
在实战过程中,咱们顺便搞清楚两个问题:
源码下载
名称 | 链接 | 备注 |
---|---|---|
项目主页 | https://github.com/zq2599/blog_demos | 该项目在GitHub上的主页 |
git仓库地址(https) | https://github.com/zq2599/blog_demos.git | 该项目源码的仓库地址,https协议 |
git仓库地址(ssh) | git@github.com:zq2599/blog_demos.git | 该项目源码的仓库地址,ssh协议 |
这个git项目中有多个文件夹,本篇的源码在spring-cloud-tutorials文件夹下,如下图红框所示:
spring-cloud-tutorials文件夹下有多个子工程,本篇的代码是gateway-change-body,如下图红框所示:
为了观察Gateway能否按预期去修改请求和响应的body,咱们给服务提供者provider-hello增加一个接口,代码在Hello.java中,如下:
@PostMapping("/change")
public Map<String, Object> change(@RequestBody Map<String, Object> map) {
map.put("response-tag", dateStr());
return map;
}
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("rewrite_request_obj", r -> r.host("*.rewriterequestobj.org")
.filters(f -> f.prefixPath("/httpbin")
.modifyRequestBody(String.class, Hello.class, MediaType.APPLICATION_JSON_VALUE,
(exchange, s) -> return Mono.just(new Hello(s.toUpperCase())))).uri(uri))
.build();
}
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("rewrite_response_upper", r -> r.host("*.rewriteresponseupper.org")
.filters(f -> f.prefixPath("/httpbin")
.modifyResponseBody(String.class, String.class,
(exchange, s) -> Mono.just(s.toUpperCase()))).uri(uri))
.build();
}
套路总结出来了,接下来,咱们一起撸代码?
package com.bolinGCavalry.changebody;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ChangeBodyApplication {
public static void main(String[] args) {
SpringApplication.run(ChangeBodyApplication.class,args);
}
}
配置文件千篇一律:
server:
#服务端口
port: 8081
spring:
application:
name: gateway-change-body
然后是核心逻辑:修改请求body的代码,既RewriteFunction的实现类,代码很简单,将原始的请求body解析成Map对象,取出user-id字段,生成user-name字段放回map,apply方法返回的是个Mono:
package com.bolingcavalry.changebody.function;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.Reactivestreams.Publisher;
import org.springframework.cloud.gateway.filter.factory.rewrite.RewriteFunction;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Map;
@Slf4j
public class RequestBodyRewrite implements RewriteFunction<String, String> {
private ObjectMapper objectMapper;
public RequestBodyRewrite(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
private String mockUserName(int userId) {
return "user-" + userId;
}
@Override
public Publisher<String> apply(ServerWebExchange exchange, String body) {
try {
Map<String, Object> map = objectMapper.readValue(body, Map.class);
// 取得id
int userId = (Integer)map.get("user-id");
// 得到nanme后写入map
map.put("user-name", mockUserName(userId));
// 添加一个key/value
map.put("gateway-request-tag", userId + "-" + System.currentTimeMillis());
return Mono.just(objectMapper.writeValueAsString(map));
} catch (Exception ex) {
log.error("1. json process fail", ex);
// json操作出现异常时的处理
return Mono.error(new Exception("1. json process fail", ex));
}
}
}
然后是按部就班的基于代码实现路由配置,重点是lambda表达式执行modifyRequestBody方法,并且将RequestBodyRewrite作为参数传入:
package com.bolingcavalry.changebody.config;
import com.bolingcavalry.changebody.function.RequestBodyRewrite;
import com.bolingcavalry.changebody.function.ResponseBodyRewrite;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import reactor.core.publisher.Mono;
@Configuration
public class FilterConfig {
@Bean
public RouteLocator routes(RouteLocatorBuilder builder, ObjectMapper objectMapper) {
return builder
.routes()
.route("path_route_change",
r -> r.path("/hello/change")
.filters(f -> f
.modifyRequestBody(String.class,String.class,new RequestBodyRewrite(objectMapper))
)
.uri("http://127.0.0.1:8082"))
.build();
}
}
代码写完了,运行工程gateway-change-body,在postman发起请求,得到响应如下图,红框中可见Gateway添加的内容已成功:
现在修改请求body已经成功,接下来再来修改服务提供者响应的body
package com.bolingcavalry.changebody.function;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.reactivestreams.Publisher;
import org.springframework.cloud.gateway.filter.factory.rewrite.RewriteFunction;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Map;
@Slf4j
public class ResponseBodyRewrite implements RewriteFunction<String, String> {
private ObjectMapper objectMapper;
public ResponseBodyRewrite(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
@Override
public Publisher<String> apply(ServerWebExchange exchange, String body) {
try {
Map<String, Object> map = objectMapper.readValue(body, Map.class);
// 取得id
int userId = (Integer)map.get("user-id");
// 添加一个key/value
map.put("gateway-response-tag", userId + "-" + System.currentTimeMillis());
return Mono.just(objectMapper.writeValueAsString(map));
} catch (Exception ex) {
log.error("2. json process fail", ex);
return Mono.error(new Exception("2. json process fail", ex));
}
}
}
路由配置代码中,lambda表达式里面,filters方法内部调用modifyResponseBody,第三个入参是ResponseBodyRewrite:
package com.bolingcavalry.changebody.config;
import com.bolingcavalry.changebody.function.RequestBodyRewrite;
import com.bolingcavalry.changebody.function.ResponseBodyRewrite;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import reactor.core.publisher.Mono;
@Configuration
public class FilterConfig {
@Bean
public RouteLocator routes(RouteLocatorBuilder builder, ObjectMapper objectMapper) {
return builder
.routes()
.route("path_route_change",
r -> r.path("/hello/change")
.filters(f -> f
.modifyRequestBody(String.class,String.class,new RequestBodyRewrite(objectMapper))
.modifyResponseBody(String.class, String.class, new ResponseBodyRewrite(objectMapper))
)
.uri("http://127.0.0.1:8082"))
.build();
}
}
还记得咱们的第一个问题吗?通过上面的代码,您应该已经看到了答案:用代码配置路由时,多个过滤器的配置方法就是在filters方法中反复调用内置的过滤器相关api,下图红框中的都可以:
运行服务,用Postman验证效果,如下图红框,Gateway在响应body中成功添加了一个key&value:
前面有两个问题,接下来回答第二个,咱们在application.yml中增加一个路由配置:
server:
#服务端口
port: 8081
spring:
application:
name: gateway-change-body
cloud:
gateway:
routes:
- id: path_route_str
uri: http://127.0.0.1:8082
predicates:
- Path=/hello/str
把gateway-change-body服务启动起来,此时已经有了两个路由配置,一个在代码中,一个在yml中,先试试yml中的这个,如下图没问题:
再试试代码配置的路由,如下图,结论是代码配置路由和yml配置可以混搭
看看控制台,能看到代码中抛出的异常信息:
看过开篇的两个图,聪明的您一定发现了问题:为什么要破坏原始数据,一旦系统出了问题如何定位是服务提供方还是网关?
到此这篇关于Spring Cloud Gateway修改请求和响应body的内容的文章就介绍到这了,更多相关Spring Cloud Gateway请求响应body内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
--结束END--
本文标题: 详解Spring Cloud Gateway修改请求和响应body的内容
本文链接: https://lsjlt.com/news/134706.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-03-01
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0