导入netty4的依赖
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.28.Final</version>
</dependency>
服务端
/**
* http服务器
*/
public class Server {
//线程组
private static final EventLoopGroup group = new NioEventLoopGroup();
//服务端启动类
private static final ServerBootstrap bootstrap = new ServerBootstrap();
//监听端口
private static final int PORT = 6789;
private static final ServerHandler serverHandler = new ServerHandler();
//SSL开关
private static final boolean SSL = true;
public static void start() throws InterruptedException, CertificateException, SSLException {
//配置SSL
final SslContext sslCtx;
if (SSL) {
//netty为我们提供的ssl加密,缺省
SelfSignedCertificate ssc = new SelfSignedCertificate();
sslCtx = SslContextBuilder.forServer(ssc.certificate(),
ssc.privateKey()).build();
} else {
sslCtx = null;
}
//设置线程组
bootstrap.group(group)
//设置Nio方式的通道监听客户端连接
.channel(NioServerSocketChannel.class)
//设置端口
.localAddress(new InetSocketAddress(PORT))
.childHandler(new ChannelInitializer<NioSocketChannel>() {
protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
ChannelPipeline pipeline = nioSocketChannel.pipeline();
//验证SSL
if (sslCtx != null) {
pipeline.addLast(sslCtx.newHandler(nioSocketChannel.alloc()));
}
//对http请求进行解码
pipeline.addLast("decode", new HttpRequestDecoder());
//对http请求进行编码
pipeline.addLast("encode", new HttpResponseEncoder());
//对http进行聚合,设置最大聚合字节长度为10M
pipeline.addLast(new HttpObjectAggregator(10 * 1024 * 1024));
//开启http内容压缩
pipeline.addLast(new HttpContentCompressor());
//添加自定义处理器
pipeline.addLast(serverHandler);
}
});
System.out.println("服务端已经启动......");
//阻塞方法,直到监听到指定的端口有连接
ChannelFuture channel = bootstrap.bind().sync();
//关闭通道
channel.channel().closeFuture().sync();
}
public static void main(String[] args) throws InterruptedException, CertificateException, SSLException {
Server.start();
}
}
服务端处理器
/**
* 服务端处理器
*/
@ChannelHandler.Sharable
public class ServerHandler extends ChannelInboundHandlerAdapter {
private static String result = "";
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("已经获取到客户端连接......");
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
FullHttpRequest request = (FullHttpRequest) msg;
try {
String uri = request.uri();
HttpMethod method = request.method();
if (!"/test".equalsIgnoreCase(uri)) {
result = "路径找不到";
send(ctx, HttpResponseStatus.BAD_REQUEST, result);
return;
}
//get请求
if (HttpMethod.GET.equals(method)) {
result = "get请求: " + System.getProperty("line.separator") + RespConstant.getNews();
send(ctx, HttpResponseStatus.OK, result);
} else if (HttpMethod.POST.equals(method)) {
//.....
}
} catch (Exception e) {
e.printStackTrace();
} finally {
request.release();
}
}
//响应
private void send(ChannelHandlerContext ctx, HttpResponseStatus status, String result) {
//聚合响应,并设置http配置
FullHttpResponse response = new DefaultFullHttpResponse(
HttpVersion.HTTP_1_1, status, Unpooled.copiedBuffer(result, CharsetUtil.UTF_8)
);
//设置响应headers
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain;charset=UTF-8");
//添加监听,等所有数据全部响应完了之后再关闭资源
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
}
}
响应工具类
/**
* 响应消息
*/
public class RespConstant {
private static final String[] NEWS = {
"她那时候还太年轻,不知道所有命运赠送的礼物,早已在暗中标好了" +
"价格。——斯蒂芬·茨威格《断头皇后》",
"这是一个最好的时代,也是一个最坏的时代;" +
"这是一个智慧的年代,这是一个愚蠢的年代;\n" +
"这是一个信任的时期,这是一个怀疑的时期;" +
"这是一个光明的季节,这是一个黑暗的季节;\n" +
"这是希望之春,这是失望之冬;" +
"人们面前应有尽有,人们面前一无所有;\n" +
"人们正踏上天堂之路,人们正走向地狱之门。 —— 狄更斯《双城记》",
};
private static final Random R = new Random();
public static String getNews() {
return NEWS[R.nextInt(NEWS.length)];
}
}