1、Client类 启动客户端,建立连接
package com.chenly.bokeyuan.https.client; import io.netty.bootstrap.Bootstrap; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpContentDecompressor; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContextBuilder; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; import lombok.extern.slf4j.Slf4j; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.URI; import java.net.URL; import java.util.Objects; /** * @author: void * @date: 2021-09-10 15:27 * @description: 客户端 建立连接 * @version: 1.0 */ @Slf4j public class Client { private String urlStr; public Client(String urlStr) { this.urlStr = urlStr; } public void start() throws InterruptedException { //线程组 EventLoopGroup group = new NioEventLoopGroup(); //启动类 Bootstrap bootstrap = new Bootstrap(); try { InetSocketAddress inetAddress = null; URI uri = new URI(urlStr); if (Objects.isNull(uri)) { return ; } boolean isSSL = urlStr.contains("https"); try { URL url = new URL(urlStr); String host = url.getHost(); InetAddress address = InetAddress.getByName(host); if (!host.equalsIgnoreCase(address.getHostAddress())) { //域名连接,https默认端口是443,http默认端口是80 inetAddress = new InetSocketAddress(address, isSSL ? 443 : 80); } else { //ip+端口连接 int port = url.getPort(); inetAddress = InetSocketAddress.createUnresolved(host, port); } } catch (Throwable e) { log.error("请求地址不合法:" + e); return; } bootstrap.group(group) .remoteAddress(inetAddress) .channel(NioSocketChannel.class) .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000) .option(ChannelOption.TCP_NODELAY,true) //长连接 .option(ChannelOption.SO_KEEPALIVE,true) .handler(new LoggingHandler(LogLevel.ERROR)) .handler(new ChannelInitializer<Channel>() { @Override protected void initChannel(Channel channel) throws Exception { System.out.println("channelCreated. Channel ID:"+channel.id()); SocketChannel socketChannel = (SocketChannel) channel; socketChannel.config().setKeepAlive(true); socketChannel.config().setTcpNoDelay(true); if (isSSL) { //配置Https通信 SslContext context = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build(); channel.pipeline().addLast(context.newHandler(channel.alloc())); } socketChannel.pipeline() //包含编码器和解码器 .addLast(new HttpClientCodec()) //聚合 .addLast(new HttpObjectAggregator(1024 * 10 * 1024)) //解压 .addLast(new HttpContentDecompressor()) //添加ChannelHandler .addLast(new ClientHandler()); } }); ChannelFuture channelFuture = bootstrap.connect().sync(); channelFuture.channel().closeFuture().sync(); } catch (Exception e) { e.printStackTrace(); } finally { group.shutdownGracefully(); } } public static void main(String[] args) throws InterruptedException { Client client = new Client("https://bjapi.push.jiguang.cn"); client.start(); } }
2、ClientHandler类 发送请求
package com.chenly.bokeyuan.https.client; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.handler.codec.http.*; import io.netty.util.CharsetUtil; import java.net.URI; import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; /** * @author: void * @date: 2021-09-10 15:28 * @description: * @version: 1.0 */ public class ClientHandler extends ChannelInboundHandlerAdapter { /** * 客户端与服务端建立连接时执行 * @param ctx * @throws Exception */ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { //发送请求至服务端 System.out.println("channelActive"); String msg = "{\n" + "\"notification\":\n" + "\t{\n" + "\t\t\"android\":{\n" + "\t\t\"alert\":\"alert-test\",\n" + "\t\t\"title\":\"title-test\",\n" + "\t\t \"style\":1,\n" + "\t\t \"alert_type\":1,\n" + " \"big_text\":\"big text content\"\n" + "\t\t \n" + "\t\t},\n" + "\t\t\"winphone\":{\"alert\":\"alert-test\",\"title\":\"title-test\"},\n" + "\t\t\"ios\":{\"alert\":\"通知\"}\n" + "\t\n" + "\t},\n" + "\"audience\":{\"registration_id\":[\"180fe1da9e6b5af51a0\"]},\n" + "\"options\":{\"apns_production\":false,\"time_to_live\":86400},\t\n" + "\"platform\":\"all\"\n" + "}\n"; Map<String,String> header = new HashMap<>(); header.put("Authorization","Basic NIU3YzE2ZTgxOWU0YjY0MmVjNjg3NWI3OjllOTU2YjdkZmZhNDBhYWU1ZTg4YzVmOQ=="); String url ="https://bjapi.push.jiguang.cn/v3/push"; //配置HttpRequest的请求数据和一些配置信息 HttpRequest request = new ClientHandler().buildRequest(msg,url,true,header); ChannelFuture future = ctx.writeAndFlush(request); future.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { //这里中刷出成功,并不代表客户接收成功,刷出数据成功默认代表已完成发送 System.out.println("http netty client刷出数据结果为:"+future.isSuccess()); } }); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { FullHttpResponse response = (FullHttpResponse) msg; ByteBuf content = response.content(); System.out.println(": content:"+content.toString(CharsetUtil.UTF_8)); } public HttpRequest buildRequest(String msg, String url, boolean isKeepAlive, Map<String,String> headers) throws Exception { URL netUrl = new URL(url); URI uri = new URI(netUrl.getPath()); //构建http请求 DefaultFullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, uri.toASCIIString(), Unpooled.wrappedBuffer(msg.getBytes(StandardCharsets.UTF_8))); //设置请求的host(这里可以是ip,也可以是域名) request.headers().set(HttpHeaderNames.HOST, netUrl.getHost()); //其他头部信息 if (headers != null && !headers.isEmpty()) { for (Map.Entry<String, String> entry : headers.entrySet()) { request.headers().set(entry.getKey(), entry.getValue()); } } //设置返回Json request.headers().set(HttpHeaderNames.CONTENT_TYPE ,"text/json;charset=UTF-8"); //发送的长度 request.headers().set(HttpHeaderNames.CONTENT_LENGTH, request.content().readableBytes()); //是否是长连接 if (isKeepAlive){ request.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE); } return request; } }