<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
HTTP(超文字傳輸協定,英文:HyperText Transfer Protocol,縮寫:HTTP)是基於TCP/IP協定的應用層的協定,常用於分散式、共同作業式和超媒體資訊系統的應用層協定。
http協定的主要特點:
(1)支援CS(使用者端/伺服器)模式。
(2)使用簡單,指定URL並攜帶必要的引數即可。
(3)靈活。傳輸非常多型別的資料物件,通過Content-Type指定即可。
(4)無狀態。
我們日常瀏覽器輸入一個url,請求伺服器就是用的http協定,url的格式如下:
http請求體的組成:
請求方法:
響應狀態碼:
HTTP 1 VS HTTP 2:
http 1不支援長連線,每次請求建立連線,響應後就關閉連線。HTTP2支援長連線,連線複用。
netty提供了對http/https協定的支援,我們可以基於netty很容易寫出http應用程式。
(1)編解碼
(2)請求體FullHttpRequest和響應體FullHttpResponse
FullHttpRequest
FullHttpResponse
(3)HttpObjectAggregator-http訊息聚合器
http的post請求包含3部分:
HttpObjectAggregator能夠把多個部分整合在一個java物件中(另外訊息體比較大的時候,還可能會分成多個訊息,都會被聚合成一個整體物件),方便使用。
整體架構設計:
核心類SimpleHttpServer:
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.HttpRequestDecoder; import io.netty.handler.codec.http.HttpResponseEncoder; import lombok.extern.slf4j.Slf4j; /** * http server based netty * * @author summer * @version $Id: SimpleHttpServer.java, v 0.1 2022年01月26日 9:34 AM summer Exp $ */ @Slf4j public class SimpleHttpServer { /** * host */ private final static String host = "127.0.0.1"; /** * 埠號 */ private final static Integer port = 8085; /** * netty伺服器端啟動方法 */ public void start() { log.info("SimpleHttpServer start begin "); EventLoopGroup bossEventLoopGroup = new NioEventLoopGroup(1); EventLoopGroup workerEventLoopGroup = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap() .group(bossEventLoopGroup, workerEventLoopGroup) .channel(NioServerSocketChannel.class) //開啟tcp nagle演演算法 .childOption(ChannelOption.TCP_NODELAY, true) //開啟長連線 .childOption(ChannelOption.SO_KEEPALIVE, true) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel c) { c.pipeline().addLast(new HttpRequestDecoder()) .addLast(new HttpResponseEncoder()) .addLast(new HttpObjectAggregator(512 * 1024)) .addLast(new SimpleHttpServerHandler()); } }); ChannelFuture channelFuture = serverBootstrap.bind(host, port).sync(); log.info("SimpleHttpServer start at port " + port); channelFuture.channel().closeFuture().sync(); } catch (Exception e) { log.error("SimpleHttpServer start exception,", e); } finally { log.info("SimpleHttpServer shutdown bossEventLoopGroup&workerEventLoopGroup gracefully"); bossEventLoopGroup.shutdownGracefully(); workerEventLoopGroup.shutdownGracefully(); } } }
實際處理請求的netty handler是SimpleHttpServerHandler:
import com.alibaba.fastjson.JSON; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.*; import lombok.extern.slf4j.Slf4j; import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Map; /** * http伺服器端處理handler實現 * * @author summer * @version $Id: SimpleHttpServerHandler.java, v 0.1 2022年01月26日 9:44 AM summer Exp $ */ @Slf4j public class SimpleHttpServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> { @Override protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest fullHttpRequest) { try { log.info("SimpleHttpServerHandler receive fullHttpRequest=" + fullHttpRequest); String result = doHandle(fullHttpRequest); log.info("SimpleHttpServerHandler,result=" + result); byte[] responseBytes = result.getBytes(StandardCharsets.UTF_8); FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_0, HttpResponseStatus.OK, Unpooled.wrappedBuffer(responseBytes)); response.headers().set("Content-Type", "text/html; charset=utf-8"); response.headers().setInt("Content-Length", response.content().readableBytes()); boolean isKeepAlive = HttpUtil.isKeepAlive(response); if (!isKeepAlive) { ctx.write(response).addListener(ChannelFutureListener.CLOSE); } else { response.headers().set("Connection", "keep-alive"); ctx.write(response); } } catch (Exception e) { log.error("channelRead0 exception,", e); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } @Override public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); } /** * 實際處理 * * @param fullHttpRequest HTTP請求引數 * @return */ private String doHandle(FullHttpRequest fullHttpRequest) { if (HttpMethod.GET == fullHttpRequest.method()) { QueryStringDecoder queryStringDecoder = new QueryStringDecoder(fullHttpRequest.uri()); Map<String, List<String>> params = queryStringDecoder.parameters(); return JSON.toJSONString(params); } else if (HttpMethod.POST == fullHttpRequest.method()) { return fullHttpRequest.content().toString(); } return ""; } }
在主執行緒中啟動伺服器端:
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SimplehttpserverApplication { public static void main(String[] args) { SimpleHttpServer simpleHttpServer = new SimpleHttpServer(); simpleHttpServer.start(); SpringApplication.run(SimplehttpserverApplication.class, args); } }
啟動成功:
利用postman工具發起http請求進行測試,這裡簡單測試get請求:
http://127.0.0.1:8085/?name=name1&value=v2
伺服器端紀錄檔也列印出了處理情況,處理正常:
19:24:59.629 [nioEventLoopGroup-3-3] INFO com.summer.simplehttpserver.SimpleHttpServerHandler - SimpleHttpServerHandler receive fullHttpRequest=HttpObjectAggregator$AggregatedFullHttpRequest(decodeResult: success, version: HTTP/1.1, content: CompositeByteBuf(ridx: 0, widx: 0, cap: 0, components=0))
GET /?name=name1&value=v2 HTTP/1.1
User-Agent: PostmanRuntime/7.26.8
Accept: */*
Cache-Control: no-cache
Postman-Token: 7dda7e2d-6f76-4008-8b74-c2b7d78f4b2e
Host: 127.0.0.1:8085
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
content-length: 0
19:24:59.629 [nioEventLoopGroup-3-3] INFO com.summer.simplehttpserver.SimpleHttpServerHandler - SimpleHttpServerHandler,result={"name":["name1"],"value":["v2"]}
到此這篇關於Java基於Netty實現Http server的實戰的文章就介紹到這了,更多相關Java Netty實現Http server內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45