Ниже приведен пример RestTemplate.
public class SimpleClient {
private final String URL;
private AsyncRestTemplate rest = new AsyncRestTemplate(new Netty4ClientHttpRequestFactory());
private RestTemplate restTemplate = new RestTemplate(new Netty4ClientHttpRequestFactory());
public SimpleClient(String url) {
this.URL = url;
Netty4ClientHttpRequestFactory nettyFactory = new Netty4ClientHttpRequestFactory();
try {
nettyFactory.setSslContext(SslContextBuilder.forClient().build());
} catch (SSLException e) {
e.printStackTrace();
}
rest = new AsyncRestTemplate(nettyFactory);
}
@Override
public ResponseEntity<ResponseData> doSendByPOST(RequestData data,Class<ResponseData> clazz) {
List<HttpMessageConverter<?>> messageConvertors = new ArrayList<>();
messageConvertors.add(new MappingJackson2HttpMessageConverter());
rest.setMessageConverters(messageConvertors);
restTemplate.setMessageConverters(messageConvertors);
HttpHeaders headers = new HttpHeaders();
ObjectMapper objectMapper = new ObjectMapper();
StringWriter writer = new StringWriter();
try {
objectMapper.writeValue(writer, data);
} catch (IOException e) {
e.printStackTrace();
}
headers.set(HttpHeaders.CONTENT_LENGTH,String.valueOf(writer.toString().getBytes(Charset.forName("UTF-8")).length));
headers.set(HttpHeaders.CONTENT_TYPE,"application/json");
HttpEntity<ResponseData> request = new HttpEntity<ResponseData>(headers);
MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>();
try {
parts.add("requestData", objectMapper.writeValueAsString(data));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
// return restTemplate.exchange(this.URL,HttpMethod.POST ,request, clazz, parts);
ListenableFuture<ResponseEntity<ResponseData>> entity = rest.exchange(this.URL,HttpMethod.POST ,request, clazz, parts);
return extractResponseEntity(entity);
}
// ...
}
Netty считывает данные из запроса channelRead method
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof HttpRequest) {
DefaultHttpRequest defaultHttpRequest = (DefaultHttpRequest) msg;
if (EmptyHttpHeaders.is100ContinueExpected(defaultHttpRequest)) {
ctx.write(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,HttpResponseStatus.CONTINUE));
}
boolean keepAlive = EmptyHttpHeaders.isKeepAlive(defaultHttpRequest);
handle = frontController.dispatchRequest(defaultHttpRequest);
}
if (msg instanceof HttpContent) {
HttpContent httpContent = (HttpContent) msg;
ByteArrayOutputStream body = new ByteArrayOutputStream(64);
ByteBuf content = httpContent.content();
if (content.isReadable()) {
//body.write(content.array());
content.readBytes(body,content.readableBytes());
//body.append(content.toString(CharsetUtil.UTF_8));
FullHttpResponse response = handle.handle(body);
if(response == null){
response = prepareDefaultResponse();
}
response.headers().set("content-type", "application/json");
response.headers().set("content-length", response.content().readableBytes());
response.headers().set("connection", HttpHeaderValues.KEEP_ALIVE);
}
if (msg instanceof LastHttpContent) {
//process request
ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
}
}
Код ниже работает нормально, но я думаю, что есть проблема с блокировкой io и неблокированием io. Когда запрос отправлен, я не могу связаться с HttpContent, я получаю HttpRequest как параметр msg. Spring resttemplate ждет ответа, но Netty не заботится:)
if (msg instanceof HttpRequest) {
DefaultHttpRequest defaultHttpRequest = (DefaultHttpRequest) msg;
if (EmptyHttpHeaders.is100ContinueExpected(defaultHttpRequest)) {
ctx.write(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,HttpResponseStatus.CONTINUE));
}
boolean keepAlive = EmptyHttpHeaders.isKeepAlive(defaultHttpRequest);
handle = frontController.dispatchRequest(defaultHttpRequest);
}
Моя проблема заключается в том, как получить ответ от netty-сервера по шаблону отдыха. Я пробовал много способов выполнить полный req/resp. Когда restTemplate запрашивает сервер Netty, он зависает поток, поэтому я не могу перемещаться по распределенной реализации кэша памяти.
Вставка в строку RestTemplate.java: 681
Метод ждет навсегда при использовании Netty4ClientHttpRequestFactory.
response = request.execute();