为了可持续发展的学习,还是决定利用netty做一个简陋的web容器。
先贴一下依赖
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.gee</groupId>
<artifactId>my-webservice-netty</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.16.Final</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
<version>1.18.8</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.41</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 指定maven编译的jdk的版本 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>
1.服务端代码
这里其实没有什么特殊的地方,只是需要使用特定的解码编码器。
HttpRequestDecoder 因为服务端是接受请求,从通道获取到的数据必然是序列化过的,所以需要进行反序列化,因此是解码。
HttpResponseEncoder 因为服务端响应最后要将响应数据写入到通道中,所以是编码器,将数据进行序列化。
HttpObjectAggregator 则是将请求,响应,或者是相关的数据,整合为一个对象。方便获取请求头,响应头等数据。
HttpHandler则是自定义的一个结构体。用于处理业务
package web.server;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
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.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import web.handler.HttpHandler;
public class WebService {
private static final int port = 9527;
public static void main(String args[]) {
start();
}
private static void start() {
EventLoopGroup boss = new NioEventLoopGroup();
EventLoopGroup work = new NioEventLoopGroup();
ServerBootstrap sb = new ServerBootstrap();
sb.group(boss, work).channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new HttpRequestDecoder());
ch.pipeline().addLast(new HttpResponseEncoder());
ch.pipeline().addLast(new HttpObjectAggregator(65536));
ch.pipeline().addLast(new HttpHandler());
}
});
ChannelFuture cf = null;
try {
cf = sb.bind(port).sync();
cf.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
boss.shutdownGracefully();
work.shutdownGracefully();
}
}
}
2.自定义处理器
package web.handler;
import java.util.Arrays;
import java.util.List;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpMethod;
import web.service.UriHandlerService;
public class HttpHandler extends SimpleChannelInboundHandler<FullHttpRequest>{
private static final List<String> methods = Arrays.asList(HttpMethod.GET.name(), HttpMethod.POST.name());
private static final String get_url = "/get/userInfo";
private static final String post_url = "/update/userInfo";
private static final UriHandlerService service = new UriHandlerService();
@Override
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception {
if(!methods.contains(msg.method().name())) {
return;
}
String uri = msg.uri();
if (HttpMethod.GET.name().equals(msg.method().name())) {
if (!uri.equals(get_url)) {
return;
}
service.handleGet(ctx, msg);
}
if (HttpMethod.POST.name().equals(msg.method().name())) {
if (!uri.equals(post_url)) {
return;
}
service.handlePost(ctx, msg);
}
}
}
package web.service;
import com.alibaba.fastjson.JSONObject;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
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.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.util.CharsetUtil;
import web.entity.UserInfo;
public class UriHandlerService {
public void handleGet(ChannelHandlerContext ctx, FullHttpRequest msg) {
UserInfo userInfo = new UserInfo();
userInfo.setId(1);
userInfo.setName("peter");
FullHttpResponse rsp = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
Unpooled.copiedBuffer(JSONObject.toJSON(userInfo).toString().getBytes()));
rsp.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/json; charset=UTF-8");
ctx.writeAndFlush(rsp).addListener(ChannelFutureListener.CLOSE);
}
public void handlePost(ChannelHandlerContext ctx, FullHttpRequest msg) {
ByteBuf contentbb = msg.content();
byte info[] = new byte[contentbb.readableBytes()];
contentbb.readBytes(info);
String infostr = new String(info);
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
Unpooled.copiedBuffer(infostr, CharsetUtil.UTF_8));
// 设置头信息
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/json; charset=UTF-8");
// 响应写回给客户端,并在写入后会断开这个连接
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
}
}
写的比较简单,只是一个简单的demo.
只是模拟get跟post请求。
模拟一下post
网友评论