使用Java通过HTTP传输数据



我有两个Java Spring Boot应用程序,我们将它们命名为Source和Consumer。Source有一个返回无限数据流的GET端点/api/data。这个想法是从Consumer调用它,每隔几秒钟监听一次数据块,然后"永远"关闭这个连接。我已经做了一个简单的来源,看起来现在工作:

@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);
}
}

源看起来是正确的,但在向其写入一块数据后,您忘记了刷新OutputStream,因此消费者无法立即接收到这一块数据。

因此,在向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);
}

最新更新