java - 使用 Java 通过 HTTP 传输数据

标签 java spring-boot reactive-programming http-live-streaming

我有两个 Java Spring Boot 应用程序,我们将它们命名为 Source 和 Consumer。 Source 有一个 GET 端点 /api/data,它返回无限的数据流。这个想法是从 Consumer 调用它并每隔几秒监听一次数据 block 并且“从不”关闭此连接。我已经制作了一个简单的源代码,现在看起来可以工作:

@RestController
@RequestMapping ("/api")
public class SourceController {

    private final Logger logger = LoggerFactory.getLogger(SourceController.class);

    @GetMapping (value = "/data", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<StreamingResponseBody> data(final HttpServletResponse response) {
        response.setContentType("application/json");
        StreamingResponseBody stream = out -> {
            try {
                for (int i = 0; i < 10; i++) {
                    String content = "{\"counter\":" + i + "}\n";
                    out.write(content.getBytes());
                    logger.info("size: "  + content.getBytes().length);
                    Thread.sleep(1000);
                }
                out.close();
            } catch (final Exception e) {
                logger.error("Exception", e);
            }
        };
        logger.info("steaming response {} ", stream);
        return new ResponseEntity(stream, HttpStatus.OK);
    }
}

我不确定这是否正是我想要的,因为当我使用 Postman 调用它时,执行 return 后 10 秒后就会出现响应。

消费者读取但读取整个响应,而不是逐段读取。

@RestController
@RequestMapping("/api")
public class ConsumerController {

    private final Logger logger = LoggerFactory.getLogger(ConsumerController.class);

    @GetMapping(value = "/consume", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<String> consume() throws IOException {
        URL url = new URL("http://localhost:8080/api/data");
        URLConnection connection = url.openConnection();
        connection.setDoOutput(true);

        BufferedReader in = new BufferedReader(
            new InputStreamReader(connection.getInputStream())
        );

        String decodedString;
        while ((decodedString = in.readLine()) != null) {
            logger.info(decodedString);
        }

        in.close();

        return new ResponseEntity("ok", HttpStatus.OK);
    }
}

最佳答案

源看起来是正确的,但你只是忘记在写入一 block 数据后刷新OutputStream,因此消费者无法立即接收这 block 数据。

因此,在向 OutputStream 写入一些内容后调用 flush() 应该可以解决问题:

 for (int i = 0; i < 10; i++) {
       String content = "{\"counter\":" + i + "}\n";
       out.write(content.getBytes());
       out.flush();
       logger.info("size: "  + content.getBytes().length);
       Thread.sleep(1000);
}

关于java - 使用 Java 通过 HTTP 传输数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58668900/

相关文章:

java - 为非泛型堆栈类编写方法如何工作?

spring - Spring boot 2.0 响应式(Reactive) webflux 配置中的默认线程数

Spring Boot - 应用程序无法使用类路径启动

spring - 负载均衡器没有可供客户端使用的服务器

haskell - 为什么这个 Yampa 弹球会陷入死循环?

ios - 如何将 ReactiveCocoa 与手势识别器一起使用

javascript - 当子组件发生onclick事件时如何重新渲染父组件?

java - 使用正则表达式检查字符串是否以数字字符开头和结尾

java - FFMPEG Extra 只是编解码器信息

java - 如何使用 Firebase 1.0.2 忽略对象模型的新字段