1.pom依赖
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.42.Final</version>
</dependency>
2.创建一个Http的服务器
当前编写http服务器参考这个地址:参考搭建http服务器
package com.hy.netty.server;
import com.hy.netty.server.handler.NettyHTTPServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
/**
* @description
* @author hy
* @date 2019-10-08
*/
public class NettyServer {
private int port;
private final EventLoopGroup bossGroup;
private final EventLoopGroup workerGroup;
public NettyServer(int port) {
this.port = port;
this.bossGroup = new NioEventLoopGroup();
this.workerGroup = new NioEventLoopGroup();
}
//启动当前netty服务器的方法
public void start() throws Exception {
ServerBootstrap b = new ServerBootstrap();
// 创建nettyServer的处理器
final NettyHTTPServerHandler nettyServerHandler = new NettyHTTPServerHandler();
b.group(bossGroup, workerGroup) // 向当前的服务启动中添加组
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline()
.addLast(new HttpServerCodec())
.addLast("httpAggregator",new HttpObjectAggregator(512*1024))
.addLast(nettyServerHandler);
}
}).option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture future = b.bind(port).sync();
if (future.isSuccess()) {
System.out.println("服务端启动成功");
} else {
System.out.println("服务端启动失败");
future.cause().printStackTrace();
}
future.channel().closeFuture().sync();
}
public static void main(String[] args) throws Exception {
int port = 8080;
new NettyServer(port).start();// 创建一个Netty服务并使用8080端口,然后启动
}
}
注意如果使用netty作为一个http的服务器(当前只作为一个api调用并获得结果,类似webservice)的时候需要添加:.addLast(new HttpServerCodec())否者不会解析
3.创建一个专门处理的Http服务器的类
import java.util.Date;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.util.CharsetUtil;
/**
* @description 创建自己的Netty服务处理器,用于处理当前Http中的请求中接受的请求的数据
* @author hy
* @date 2019-10-08
*/
@Sharable
public class NettyHTTPServerHandler extends SimpleChannelInboundHandler<FullHttpRequest>{ // (1)
@Override
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest fullHttpRequest) throws Exception {
System.out.println("uri:"+fullHttpRequest.uri());
HttpMethod method = fullHttpRequest.method();
System.out.println("当前请求的方式:"+method.name());
ByteBuf in = fullHttpRequest.content();
byte[] bs = in.array();
System.out.println(new String(bs,"UTF-8"));
//这里使用发送json数据返回
String msg="{\"result\":\"success\",\"uri\":\""+fullHttpRequest.uri()+"\"}";
FullHttpResponse httpResponse=new DefaultFullHttpResponse(
HttpVersion.HTTP_1_1,
HttpResponseStatus.OK,
Unpooled.copiedBuffer(msg, CharsetUtil.UTF_8));
httpResponse.headers()
.set(HttpHeaderNames.CONNECTION,"Keep-Alive")
/* .set(HttpHeaderNames.CONTENT_ENCODING,"gzip") */
.set(HttpHeaderNames.CONTENT_TYPE, "text/json; charset=UTF-8")
.set(HttpHeaderNames.DATE,new Date())
.set(HttpHeaderNames.SERVER,"BWS/1.1")
.set(HttpHeaderNames.SET_COOKIE,"delPer=0; path=/; domain=.baidu.com");
//发送请求
ctx.writeAndFlush(httpResponse).addListener(ChannelFutureListener.CLOSE);
}
}
注意:
1.当前的Http请求处理类中必须添加@Sharable注解,否者使用浏览器访问的时候会报错
2.注意响应的格式问题:.set(HttpHeaderNames.CONTENT_ENCODING,“gzip”) 不用添加!
4.访问结果
5.问题
发现当前响应的格式是有要求的:
1.查看访问www.baidu.com的response
1.发现当前返回的结果必须有一个响应状态码( 200 OK
),和一个http协议(HTTP/1.1)以及最后的响应上下文类型(Content-Type: text/html)
2.如果发送不匹配的响应报文,当前的浏览器默认是不解析的!
开始修改header
httpResponse.headers()
.set(HttpHeaderNames.CONTENT_TYPE, "text/json; charset=UTF-8");
只添加一条数据:响应的数据格式,结果可以访问
6.使用前面的HttpClient访问当前的netty的Http服务器
对于不懂HttpClient的参考我的这篇博文:ApacheHttpClient:初次使用的简单Demo(用来访问百度)
由于本人封装了当前的httpclient所以这里就是简化的访问代码
这里已经出现了当前netty的响应结果:success
服务器结果:
7.总结
1.通过搭建自己的netty的HTTP服务器
可以发现当前的netty的确很简单就实现了我们的要求,接收请求和响应请求都比较简单
!
2.响应的时候需要注意响应报文的问题
!
3.通过当前的httpclient访问netty可以知道访问和接收数据也很简单
,一个传输数据一个接收数据,在网络下进行!
4.通过这个可以知道我们可以利用当前的netty和httpclient实现自己的接口调用伪rpc框架
以上纯属个人见解,如有问题请联系本人!