Spring Cloud Gateway修改请求和响应body的内容,2024年阿里Java高级面试题及答案

#服务端口

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;

}

/**

  • 根据用户ID获取用户名称的方法,可以按实际情况来内部实现,例如查库或缓存,或者远程调用

  • @param userId

  • @return

*/

private String mockUserName(int userId) {

return “user-” + userId;

}

@Override

public Publisher 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

修改响应body

  • 接下来开发修改响应body的代码

  • 新增RewriteFunction接口的实现类ResponseBodyRewrite.java

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 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:

在这里插入图片描述

代码配置路由和yml配置是否可以混搭?

  • 前面有两个问题,接下来回答第二个,咱们在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配置可以混搭

在这里插入图片描述

如何处理异常

  • 还有个问题必须要面对:修改请求或者响应body的过程中,如果发现问题需要提前返回错误(例如必要的字段不存在),代码该怎么写?

  • 咱们修改请求body的代码集中在RequestBodyRewrite.java,增加下图红框内容:

在这里插入图片描述

  • 再来试试,这次请求参数中不包含user-id,收到Gateway返回的错误信息如下图:

在这里插入图片描述

  • 看看控制台,能看到代码中抛出的异常信息:

在这里插入图片描述

  • 此时,聪明的您应该发现问题所在了:咱们想告诉客户端具体的错误,但实际上客户端收到的是被Gateway框架处理后的内容

  • 篇幅所限,上述问题从分析到解决的过程,就留给下一篇文章吧

  • 本篇的最后,请容许欣宸唠叨两句,聊聊为何要网关来修改请求和响应body的内容,如果您没兴趣还请忽略

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

惊喜

最后还准备了一套上面资料对应的面试题(有答案哦)和面试时的高频面试算法题(如果面试准备时间不够,那么集中把这些算法题做完即可,命中率高达85%+)

image.png

image.png

agZ-1711956775945)]
[外链图片转存中…(img-nWxofWRB-1711956775945)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-KJVqP50M-1711956775946)]

惊喜

最后还准备了一套上面资料对应的面试题(有答案哦)和面试时的高频面试算法题(如果面试准备时间不够,那么集中把这些算法题做完即可,命中率高达85%+)

[外链图片转存中…(img-8ZhIPugL-1711956775946)]

[外链图片转存中…(img-efDVLoSX-1711956775947)]

  • 15
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值