首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从ServerWebExchange/ServerHttpRequest获取主体作为原始字符串

从ServerWebExchange/ServerHttpRequest获取主体作为原始字符串
EN

Stack Overflow用户
提问于 2022-01-14 09:02:38
回答 1查看 1.7K关注 0票数 0

我需要在控制器中将请求体作为原始JSON字符串。我正在使用Spring WebFlux。如果我能够更改@PostMapper函数签名,那么使用"@RequestBody “获得原始JSON将非常容易。但是我不能这样做,因为它是自动生成的,并且会影响其他处理程序,"@RequestBody学生“也已经存在,我们不能有两个@RequestBody。

代码语言:javascript
运行
复制
@RestController
public class StudentController {
    @PostMapping("/student")
    private void newStudent(@RequestBody Student student,
                            ServerWebExchange exchange) {
        String rawStudent = ServerExchangeUtils.getRequestRawBody(exchange); //idealy like this
        System.out.println(rawStudent);
    }
}

我要找的是“交换”(GetRequestRaw)之类的东西

EN

回答 1

Stack Overflow用户

发布于 2022-04-29 14:51:00

我也有同样的问题,我不能改变信号,因为它是由openapi生成器生成的。

通过将主体缓存在WebFilter中的字符串中,我找到了一个解决方案:

代码语言:javascript
运行
复制
@Slf4j
public class CachingBodyServerHttpRequestDecorator extends ServerHttpRequestDecorator {

private final StringBuilder cachedBody = new StringBuilder();

public CachingBodyServerHttpRequestDecorator(ServerHttpRequest delegate) {
    super(delegate);
}

@Override
public Flux<DataBuffer> getBody() {
    return super.getBody().doOnNext(this::cache);
}

@SneakyThrows
private void cache(DataBuffer buffer) {
    cachedBody.append(UTF_8.decode(buffer.asByteBuffer()));
}

public String getCachedBody() {
    return cachedBody.toString();
}
}


public final class CachingBodyServerWebExchangeDecorator extends ServerWebExchangeDecorator {

private final ServerHttpRequestDecorator requestDecorator;

public CachingBodyServerWebExchangeDecorator(ServerWebExchange delegate) {
    super(delegate);
    this.requestDecorator = new CachingBodyServerHttpRequestDecorator(delegate.getRequest());
}

@Override
public ServerHttpRequest getRequest() {
    return requestDecorator;
}

}


@Component
@Slf4j
public class SetRequestBodyAttribute implements WebFilter {

    private static ServerHttpRequestPredicate requestsToServe =
            MethodServerHttpRequestPredicate.of(HttpMethod.POST)
                    .and(PathServerHttpRequestPredicate.of("/contacts/import"))
                    .or(MethodServerHttpRequestPredicate.of(HttpMethod.PATCH)
                            .and(PathServerHttpRequestPredicate.of("/contacts/{contact_id}")));

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        if (requestsToServe.test(exchange.getRequest())) {
             
        return chain.filter(new CachingBodyServerWebExchangeDecorator(exchange));
        }
        return chain.filter(exchange);
    }
}


@UtilityClass
public class ServerHttpRequestUtils {

    public Mono<String> getBodyAsString(ServerHttpRequest request) {
        return Mono.just(((CachingBodyServerHttpRequestDecorator)exchange.getRequest()).getCachedBody())
    }
}


public interface ServerHttpRequestPredicate {

    boolean test(ServerHttpRequest request);

    @NotNull
    default ServerHttpRequestPredicate and(@NotNull ServerHttpRequestPredicate other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }

    @NotNull
    default ServerHttpRequestPredicate negate() {
        return (t) -> !test(t);
    }

    @NotNull
    default ServerHttpRequestPredicate or(@NotNull ServerHttpRequestPredicate other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }
}

@Value
public class PathServerHttpRequestPredicate implements ServerHttpRequestPredicate {

    public static PathServerHttpRequestPredicate of(String path) {
        return new PathServerHttpRequestPredicate(path);
    }

    PathPattern pathPattern;

    public PathServerHttpRequestPredicate(String path) {
        Assert.notNull(path, "path should not be null!");
        this.pathPattern = PathPatternParser.defaultInstance.parse(path);
    }

    @Override
    public boolean test(ServerHttpRequest request) {
        PathContainer pathContainer = request.getPath().pathWithinApplication();
        PathPattern.PathMatchInfo info = this.pathPattern.matchAndExtract(pathContainer);
        return info != null;
    }
}

@Value(staticConstructor = "of")
public class MethodServerHttpRequestPredicate implements ServerHttpRequestPredicate{

    HttpMethod httpMethod;

    public MethodServerHttpRequestPredicate(HttpMethod httpMethod) {
        Assert.notNull(httpMethod, "httpMethod should not be null!");
        this.httpMethod = httpMethod;
    }

    @Override
    public boolean test(ServerHttpRequest request) {
        return request.getMethod() == httpMethod;
    }
}

在控制器处理程序中,我们可以将主体作为字符串获得,即使它是作为对象注入的。

代码语言:javascript
运行
复制
Mono<String> bodyAsStringMono = ServerHttpRequestUtils .getBodyAsString(exchange);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70708196

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档