当前位置: 首页 > 知识库问答 >
问题:

如何在Netty Reactor HTTP服务器响应中正确地将Mono作为JSON发送

董和风
2023-03-14

我试图找出如何正确地从Netty Reactor HTTP服务器发送响应,响应度为JSON。

我当前的实现对来自WebClient的请求做出反应,并且应该以某种响应实体状态发送回响应(让我们假设只是HTTP OK)。

不幸的是,我仍然在客户端遇到InvalidDefinitionException,因为没有默认构造函数,所以无法构造实例。

我知道这意味着什么,但例如Spring Webflux也可以有restendpointMono的返回类型,客户端不会出现任何问题。那么,是否有可能在服务器端将实体正确序列化为JSON,并在客户端将其反序列化?

这是我的客户

import org.springframework.web.reactive.function.client.WebClient;

public Mono<ResponseEntity> postRequest(final Object body, final String uri) {
        return webClient.post()
                .uri(uri)
                .contentType(MediaType.APPLICATION_JSON)
                .body(BodyInserters.fromValue(body))
                .exchange()
                .flatMap(clientResponse -> clientResponse.toEntity(ResponseEntity.class));
    }

这是我的服务器

    public void runWithPost(final String endpointPath, final ServerCallback callback) {
        server = HttpServer.create()
                .host(this.host)
                .port(this.port)
                .route(routes ->
                        routes.post(endpointPath, (request, response) ->
                                response.addHeader(CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                                        .sendString(Mono.just(getJSON(callback.handleCallback())))))
                .wiretap(true)
                .bindNow();

        System.out.println("Starting server...");
    }

    private String getJSON(final ResponseEntity responseEntity) {
        String json = StringUtils.EMPTY;
        try {
            json = objectMapper.writeValueAsString(responseEntity);
            System.out.println("Serialized JSON: " + json);
        } catch (final JsonProcessingException ex) {
            System.err.println("JSON serializer error: " + ex.getMessage());
        }

        return json;
    }

这是回调

public interface ServerCallback {

    ResponseEntity handleCallback();

}

和用法

reactiveRestServer.runWithPost("/transaction", () -> ResponseEntity.ok().build());

不幸的是,在客户端,我没有获得HTTP状态OK,但出现反序列化异常:

2020-04-28 16:09:35.345 ERROR 15136 --- [ctor-http-nio-2] c.a.t.t.inbound.ArpMessageServiceImpl    : Type definition error: [simple type, class org.springframework.http.ResponseEntity]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `org.springframework.http.ResponseEntity` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (io.netty.buffer.ByteBufInputStream); line: 1, column: 2]
2020-04-28 16:09:35.349  WARN 15136 --- [ctor-http-nio-2] io.netty.util.ReferenceCountUtil         : Failed to release a message: DefaultLastHttpContent(data: PooledSlicedByteBuf(freed), decoderResult: success)

io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1
    at io.netty.util.internal.ReferenceCountUpdater.toLiveRealRefCnt(ReferenceCountUpdater.java:74) ~[netty-common-4.1.45.Final.jar:4.1.45.Final]

我错过了什么?

共有1个答案

卫弘义
2023-03-14

所以我终于解决了这个问题。对于那些想要解决类似问题的人来说,这里是答案。问题是Spring Webflow将响应实体转换为DefaultFullHttpACK,因此DefaultFullHttpACK包含标头、状态和正文。我通过完全相同的方法解决了这个问题。

    public void runWithPost(final String endpointPath, final ServerCallback callback) {
        if (server == null || server.isDisposed()) {
            server = HttpServer.create()
                    .host(this.host)
                    .port(this.port)
                    .route(routes ->
                            routes.post(endpointPath, (request, response) -> processResponse(response, callback)))
                    .wiretap(true)
                    .bindNow();

            logger.info("Starting server...");
        } else {
            logger.info("Couldn't start server because one is already running!");
        }
    }

而转换就在这里

    private NettyOutbound processResponse(final HttpServerResponse response, final ServerCallback callback) {
        final ResponseEntity responseEntity = callback.handleCallback();

        // set status
        response.status(responseEntity.getStatusCodeValue());

        // set headers
        final HttpHeaders entityHeaders = responseEntity.getHeaders();

        if (!entityHeaders.isEmpty()) {
            entityHeaders.entrySet().stream()
                    .forEach(entry -> response.addHeader(entry.getKey(), buildValue(entry.getValue())));
        }

        if (responseEntity.hasBody()) {
            try {
                final Object body = responseEntity.getBody();

                if (body instanceof String) {
                    return response.sendString(Mono.just((String) body));
                } else {
                    return response.send(Mono.just(Unpooled.wrappedBuffer(getBytesFromObject(body))));
                }
            } catch (final IOException ex) {
                response.status(HttpResponseStatus.INTERNAL_SERVER_ERROR);
                return response.sendString(Mono.just(ex.getMessage()));
            }
        }

        // set body

        return response.send(Mono.empty());
    }

用法如下:

mockReactiveRestServer.runWithPost("/transaction", () -> ResponseEntity.ok().build());
 类似资料:
  • 在我的应用程序中,我使用改型+GSON与服务器通信。但是,服务器响应存在编码问题。 在OkHttp logging interceptor中,服务器响应如下所示,这是可以的: 这是服务器响应JSON的一部分。当响应被Gson反序列化时,反序列化字符串如下所示: null

  • 问题内容: 我目前在phpmyadmin中遇到此错误: 我尝试了Google搜索,并尝试了每种解决方案。不幸的是,对我没有任何帮助。 顺便说一句,我正在使用沼泽服务器。 下面是我从C:\ wamp \ apps \ phpmyadmin3.2.0.1开始的config.inc.php配置文件。 问题答案: mysql的默认端口是3306,您可以尝试将其放入,然后尝试

  • 问题内容: 我正在开发我的第一个Android应用程序。我正在尝试做的是对REST服务的POST请求,我希望此请求的主体为JSON字符串。 我正在使用Google的GSON来生成发送到服务器的JSON。这是执行POST请求的代码: 响应代码为400 BAD REQUEST,我可以从服务器日志中读取信息。尸体未正确发送的地方: 服务器端的代码是一个简单的Seam Rest Service: Andr

  • 如何正确转换dto到json在Java?我这样做就像下面使用: 问题在于格式化字段。在Dto我有我的日期在这种格式:但转换此dto到json字节后,我看到我的拆分为对象与许多属性如下: 在使用之后,我希望将中的所有属性以与转换之前相同的格式进行转换。如何做到这一点? 谢谢你的帮助!

  • 问题内容: 我正在编辑内置的表单。 我在对话框中显示该表单,然后提交。 数据已正确输入数据库。 但是我不知道是否需要将一些寄回。其实我对事情有点困惑。 假设我在表中使用``jQuery添加了一行,当我提交表单时,然后在提交数据之后,我想发回那些行数据,以便我可以动态添加表行以显示添加的数据。 我很困惑如何获取这些数据。 这是我当前的代码: 这只是带有成功消息的模板。 问题答案: Symfony 2

  • 问题内容: 我创建了基本的http服务器,该服务器发送html文件作为响应。我如何也发送CSS文件,以便使用浏览器的客户端将看到使用CSS的HTML? 我有的代码: 我试过的(似乎不起作用-客户端在这里只能看到CSS文件内容): html文件: CSS文件: 我不想在这里使用express(仅用于学习目的) 问题答案: 您在第一个代码段中编写的是一个Web服务器,该Web服务器使用HTML文件的主