设为首页 加入收藏

TOP

修改经过Spring Gateway的表单中的Json数据(一)
2023-09-23 15:44:15 】 浏览:106
Tags:经过 Spring Gateway 单中的 Json 数据

背景

使用Spring Cloud Gateway作为网关时有时候一个请求是既包含excel又包含json的表单数据,出于各种层面考虑网关需要获取并更新其中的json数据

依赖

  • Spring Boot版本:2.7.15
  • Hutool: 5.8.21
  • Java: 11

实现逻辑

实现分为2个部分

  1. 使用上文提到的ModifyRequestBodyGatewayFilterFactory类来修改请求体,这样最后就不用我们手动包装
  2. 核心service通过将表单转为String,然后根据其中的boundary进行分割,提取修改json报文部分后再进行组装

注意:示例代码的核心service处理的表单内容只是2个,Json数据的key指定为json,另一个excel文件流

自定义filter

@Component
@Slf4j
public class RequestModifyFilter implements GlobalFilter, Ordered {
    @Autowired
    private ModifyRequestBodyGatewayFilterFactory modifyRequestBodyFilter;
    @Autowired
    private JsonRequestBodyRewriteService jsonRequestBodyRewriteService;
    @Autowired
    private FormDataRequestBodyRewriteService formDataRequestBodyRewriteService;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        MediaType mediaType = exchange.getRequest().getHeaders().getContentType();
        if (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType)) {
            // 纯json报文处理逻辑
            return modifyRequestBodyFilter
                    .apply(
                            new ModifyRequestBodyGatewayFilterFactory.Config()
                                    .setRewriteFunction(byte[].class, byte[].class, jsonRequestBodyRewriteService))
                    .filter(exchange, chain);
        } else if (MediaType.MULTIPART_FORM_DATA.isCompatibleWith(mediaType)) {
            // form表单数据处理
            return modifyRequestBodyFilter
                    .apply(
                            new ModifyRequestBodyGatewayFilterFactory.Config()
                                    .setRewriteFunction(byte[].class, byte[].class, formDataRequestBodyRewriteService))
                    .filter(exchange, chain);
        } else {
            return filter(exchange, chain);
        }

    }

    @Override
    public int getOrder() {
        return OrderConstant.REQUEST_MODIFY_FILTER.getOrder();
    }
}

核心service

@Service
@Slf4j
public class FormDataRequestBodyRewriteService implements RewriteFunction<byte[], byte[]> {
    private final String BOUNDARY_PREFIX_IN_CONTENT_TYPE = "----WebKitFormBoundary";
    private final String BOUNDARY_PREFIX_IN_FORM_DATA = "------WebKitFormBoundary";
    private final String BOUNDARY_SUFFIX = "--\r\n";

    @Override
    public Publisher<byte[]> apply(ServerWebExchange exchange, byte[] body) {
        String finalResultString = "";

        // 将表单转为字符串格式从而根据boundary分割表单数据。注意这里不能用默认编码
        String request = StrUtil.str(body, StandardCharsets.ISO_8859_1);

        // 获取boundary的随机字符信息
        String contentType = exchange.getRequest().getHeaders().getContentType().toString();
        String randomStr = contentType.substring(contentType.indexOf(BOUNDARY_PREFIX_IN_CONTENT_TYPE) + BOUNDARY_PREFIX_IN_CONTENT_TYPE.length());

        // 这里和前端约定json数据的表单key为json
        String keyPart = "^\r\nContent-Disposition: form-data; name=\"json\"";
        Pattern r = Pattern.compile(keyPart);

        // 根据表单内分割线进行分割。并通过关键段落keyPart来找到目标json数据
        String[] split = request.split(BOUNDARY_PREFIX_IN_FORM_DATA + randomStr);
        for (int x = 0; x < split.length - 1; x++) {
            Matcher m = r.matcher(split[x]);
            if (m.find()) {
                // 找到了json报文部分数据
                String originalJsonString = split[x];

                // 找到 JSON 数据的起始和结束位置
                int startIndex = originalJsonString.indexOf("{\"");
                int endIndex = originalJsonString.indexOf("\"}") + 2;
                // 提取 JSON 数据
                String jsonData = originalJsonString.substring(startIndex, endIndex);
                log.info("原始报文为:{}", jsonData);

                JSONObject jsonObject = JSONU
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇JDK21来了!附重要更新说明 下一篇Nginx + Spring Boot 轻松实现负..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目