NettyはHTTP demoを実現
15727 ワード
1.プロセス分析の実現履歴書接続読み出しメッセージストリーム 復号Request 業務処理 符号化Response は、メッセージクローズ接続 を返す.
2.nettyにおけるHttpRequestの表示構造
3.nettyにおけるHttpResponseの構造:
4.コード実装
2.nettyにおけるHttpRequestの表示構造
3.nettyにおけるHttpResponseの構造:
4.コード実装
public class HttpServer {
private final int port;
public HttpServer(int port) {
this.port = port;
}
public void run() {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup).option(ChannelOption.SO_BACKLOG, 1024)
.channel(NioServerSocketChannel.class).childOption(ChannelOption.SO_KEEPALIVE, true)
.childOption(ChannelOption.TCP_NODELAY, true).childHandler(new ChannelInitializer() {
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast("codec", new HttpServerCodec()) // HttpRequestDecoder
.addLast("aggregator", new HttpObjectAggregator(1024 * 1024)) //
.addLast("handler", new HttpServerhandler()); // handler
};
});
ChannelFuture future = bootstrap.bind(port).sync();
System.out.println("Netty-http server listening on port " + port);
future.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
public static void main(String[] args) {
new HttpServer(8080).run();
}
}
public class HttpServerhandler extends ChannelHandlerAdapter {
private HttpHeaders headers;
private HttpRequest request;
private FullHttpRequest fullRequest;
private FullHttpResponse response;
private HttpPostRequestDecoder decoder;
private static final HttpDataFactory factory = new DefaultHttpDataFactory(DefaultHttpDataFactory.MAXSIZE);
private static final String FAVICON_ICO = "/favicon.ico";
private static final String SUCCESS = "success";
private static final String ERROR = "error";
private static final String CONNECTION_KEEP_ALIVE = "keep-alive";
private static final String CONNECTION_CLOSE = "close";
private static final Charset cs = Charset.forName("utf-8");
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof HttpRequest) {
try {
request = (HttpRequest) msg;
headers = request.headers();
String uri = request.uri();
System.out.println("http uri: " + uri);
// "/favicon.ico"
if (uri.equals(FAVICON_ICO)) {
return;
}
HttpMethod method = request.method();
if (method.equals(HttpMethod.GET)) {
QueryStringDecoder queryDecoder = new QueryStringDecoder(uri, cs);
Map> uriAttributes = queryDecoder.parameters();
// ( )
for (Map.Entry> attr : uriAttributes.entrySet()) {
for (String attrVal : attr.getValue()) {
System.out.println(attr.getKey() + "=" + attrVal);
}
}
} else if (method.equals(HttpMethod.POST)) {
// POST , , msg FullHttpRequest
fullRequest = (FullHttpRequest) msg;
// Content_Type body
dealWithContentType();
} else {
// ,
}
writeResponse(ctx.channel(), HttpResponseStatus.OK, SUCCESS, false);
} catch (Exception e) {
writeResponse(ctx.channel(), HttpResponseStatus.INTERNAL_SERVER_ERROR, ERROR, true);
} finally {
ReferenceCountUtil.release(msg);
}
} else {
// discard request...
ReferenceCountUtil.release(msg);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
/**
* Content-Type POST ( )
*
* @param headers
* @param content
* @throws Exception
*/
private void dealWithContentType() throws Exception {
String contentType = getContentType();
if (contentType.equals("application/json")) { // HttpJsonDecoder
String jsonStr = fullRequest.content().toString(cs);
JSONObject obj = JSON.parseObject(jsonStr);
for (Entry item : obj.entrySet()) {
System.out.println(item.getKey() + "=" + item.getValue().toString());
}
} else if (contentType.equals("application/x-www-form-urlencoded")) {
// : QueryStringDecoder
// String jsonStr =
// fullRequest.content().toString(Charsets.toCharset(CharEncoding.UTF_8));
// QueryStringDecoder queryDecoder = new QueryStringDecoder(jsonStr,
// false);
// Map> uriAttributes =
// queryDecoder.parameters();
// for (Map.Entry> attr :
// uriAttributes.entrySet()) {
// for (String attrVal : attr.getValue()) {
// System.out.println(attr.getKey() + "=" + attrVal);
// }
// }
// : HttpPostRequestDecoder
initPostRequestDecoder();
List datas = decoder.getBodyHttpDatas();
for (InterfaceHttpData data : datas) {
if (data.getHttpDataType() == HttpDataType.Attribute) {
Attribute attribute = (Attribute) data;
System.out.println(attribute.getName() + "=" + attribute.getValue());
}
}
} else if (contentType.equals("multipart/form-data")) { //
readHttpDataAllReceive();
} else {
// do nothing...
}
}
private void readHttpDataAllReceive() throws Exception {
initPostRequestDecoder();
try {
List datas = decoder.getBodyHttpDatas();
for (InterfaceHttpData data : datas) {
writeHttpData(data);
}
} catch (Exception e) {
// ,
throw new Exception(e);
}
}
private void writeHttpData(InterfaceHttpData data) throws Exception {
// (HttpChunk),
if (data.getHttpDataType() == HttpDataType.FileUpload) {
FileUpload fileUpload = (FileUpload) data;
String fileName = fileUpload.getFilename();
if (fileUpload.isCompleted()) {
//
StringBuffer fileNameBuf = new StringBuffer();
fileNameBuf.append(DiskFileUpload.baseDirectory).append(fileName);
fileUpload.renameTo(new File(fileNameBuf.toString()));
}
}
}
private void writeResponse(Channel channel, HttpResponseStatus status, String msg, boolean forceClose) {
ByteBuf byteBuf = Unpooled.wrappedBuffer(msg.getBytes());
response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, byteBuf);
boolean close = isClose();
if (!close && !forceClose) {
response.headers().add(org.apache.http.HttpHeaders.CONTENT_LENGTH, String.valueOf(byteBuf.readableBytes()));
}
ChannelFuture future = channel.write(response);
if (close || forceClose) {
future.addListener(ChannelFutureListener.CLOSE);
}
}
private String getContentType() {
String typeStr = headers.get("Content-Type").toString();
String[] list = typeStr.split(";");
return list[0];
}
private void initPostRequestDecoder() {
if (decoder != null) {
decoder.cleanFiles();
decoder = null;
}
decoder = new HttpPostRequestDecoder(factory, request, cs);
}
private boolean isClose() {
if (request.headers().contains(org.apache.http.HttpHeaders.CONNECTION, CONNECTION_CLOSE, true) || (request
.protocolVersion().equals(HttpVersion.HTTP_1_0)
&& !request.headers().contains(org.apache.http.HttpHeaders.CONNECTION, CONNECTION_KEEP_ALIVE, true)))
return true;
return false;
}
}