<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Netty整合SpringMVC,實(shí)現(xiàn)高效的HTTP服務(wù)請(qǐng)求

          共 12976字,需瀏覽 26分鐘

           ·

          2022-02-25 16:44



          來(lái)源:blog.csdn.net/shzy1988/article/

          details/78841140


          首先,你必須要了解netty,說(shuō)簡(jiǎn)單點(diǎn):客戶端通過(guò)TCP鏈接和服務(wù)器建立長(zhǎng)連接,client和server都是通過(guò)管道(ChannelPipeline)的addLast方法的添加順序來(lái)處理接收或者發(fā)送的數(shù)據(jù)。

          這個(gè)和struts的filter的doFilter原理類似,處理完一個(gè)filter,如果后面還有其他的filter,就將數(shù)據(jù)chain.doFilter來(lái)繼續(xù)處理。

          然后,說(shuō)說(shuō)netty怎么來(lái)整合springMVC:當(dāng)client和server建立連接后,我們?cè)赼ddLast的某個(gè)類中將client發(fā)來(lái)的請(qǐng)求,讓DispatcherServlet來(lái)處理,然后將處理后的結(jié)果通過(guò)ChannelHandlerContext或者Channel將,結(jié)果writeAndFlush到client。

          1.寫一個(gè)netty sever的java代碼

          package?com.magic.netty.server;

          import?org.slf4j.Logger;
          import?org.slf4j.LoggerFactory;
          import?org.springframework.web.servlet.DispatcherServlet;

          import?io.netty.bootstrap.ServerBootstrap;
          import?io.netty.channel.ChannelFuture;
          import?io.netty.channel.ChannelOption;
          import?io.netty.channel.EventLoopGroup;
          import?io.netty.channel.nio.NioEventLoopGroup;
          import?io.netty.channel.socket.nio.NioServerSocketChannel;

          import?com.magic.netty.HttpServerInitializer;

          public?class?NettyHttpServer?{

          ?public?NettyHttpServer(Integer?port)?{
          ??this.port?=?port;
          ?}
          ?public?NettyHttpServer(Integer?port,?DispatcherServlet?servlet)?{
          ??this.port?=?port;
          ??this.servlet?=?servlet;
          ?}

          ?public?void?start(){
          ??EventLoopGroup?bossGroup?=?new?NioEventLoopGroup();
          ??EventLoopGroup?workerGroup?=?new?NioEventLoopGroup();
          ??try?{
          ???ServerBootstrap?b?=?new?ServerBootstrap();
          ???b.group(bossGroup,?workerGroup)
          ?????.channel(NioServerSocketChannel.class)
          ?????.childHandler(new?HttpServerInitializer(servlet))
          ?????.option(ChannelOption.SO_BACKLOG,?128)
          ?????.childOption(ChannelOption.SO_KEEPALIVE,?true)
          ;

          ???System.out.println("NettyHttpServer?Run?successfully");
          ???//?綁定端口,開始接收進(jìn)來(lái)的連接
          ???ChannelFuture?f?=?b.bind(port).sync();
          ???//?等待服務(wù)器 socket 關(guān)閉?。在這個(gè)例子中,這不會(huì)發(fā)生,但你可以優(yōu)雅地關(guān)閉你的服務(wù)器。
          ???f.channel().closeFuture().sync();
          ??}?catch?(Exception?e)?{
          ???log.error("NettySever?start?fail",e);
          ??}?finally?{
          ???workerGroup.shutdownGracefully();
          ???bossGroup.shutdownGracefully();
          ??}
          ?}
          ?private?int?port;
          ?private?static?Logger?log?=?LoggerFactory.getLogger(NettyHttpServer.class);
          ?private?DispatcherServlet?servlet;
          }

          2.初始化netty的channel管道

          package?com.magic.netty;

          import?org.springframework.web.servlet.DispatcherServlet;

          import?io.netty.channel.ChannelInitializer;
          import?io.netty.channel.ChannelPipeline;
          import?io.netty.channel.socket.SocketChannel;
          import?io.netty.handler.codec.http.HttpContentCompressor;
          import?io.netty.handler.codec.http.HttpObjectAggregator;
          import?io.netty.handler.codec.http.HttpRequestDecoder;
          import?io.netty.handler.codec.http.HttpResponseEncoder;
          import?io.netty.handler.stream.ChunkedWriteHandler;



          public?class?HttpServerInitializer?extends?ChannelInitializer<SocketChannel>?{

          ?public?HttpServerInitializer(DispatcherServlet?servlet)?{
          ??this.servlet?=?servlet;
          ?}
          ?public?HttpServerInitializer()?{
          ??
          ?}

          ?@Override
          ?protected?void?initChannel(SocketChannel?ch)?throws?Exception?{
          ??ChannelPipeline?pipeline?=?ch.pipeline();
          ??pipeline.addLast("decoder",?new?HttpRequestDecoder());
          ??pipeline.addLast("encoder",?new?HttpResponseEncoder());
          ??pipeline.addLast("aggregator",?new?HttpObjectAggregator(2147483647));
          ??pipeline.addLast("chunkedWriter",?new?ChunkedWriteHandler());
          ????????pipeline.addLast("deflater",?new?HttpContentCompressor());
          ????????pipeline.addLast("handler",?new?HttpRequestHandler(servlet));
          ?}
          ?private?DispatcherServlet?servlet;
          }

          3.在handler里面處理client發(fā)來(lái)的請(qǐng)求

          package?com.magic.netty;

          import?java.io.UnsupportedEncodingException;
          import?java.net.URLDecoder;
          import?java.util.HashMap;
          import?java.util.Iterator;
          import?java.util.List;
          import?java.util.Map;
          import?java.util.Map.Entry;

          import?javax.servlet.ServletContext;

          import?io.netty.buffer.ByteBuf;
          import?io.netty.buffer.Unpooled;
          import?io.netty.channel.ChannelFuture;
          import?io.netty.channel.ChannelFutureListener;
          import?io.netty.channel.ChannelHandlerContext;
          import?io.netty.channel.SimpleChannelInboundHandler;
          import?io.netty.handler.codec.http.*;
          import?io.netty.handler.codec.http.multipart.DefaultHttpDataFactory;
          import?io.netty.handler.codec.http.multipart.HttpPostRequestDecoder;
          import?io.netty.handler.codec.http.multipart.InterfaceHttpData;
          import?io.netty.handler.codec.http.multipart.InterfaceHttpData.HttpDataType;
          import?io.netty.handler.codec.http.multipart.MemoryAttribute;
          import?io.netty.util.CharsetUtil;

          import?org.apache.commons.lang3.StringUtils;
          import?org.slf4j.Logger;
          import?org.slf4j.LoggerFactory;
          import?org.springframework.mock.web.MockHttpServletRequest;
          import?org.springframework.mock.web.MockHttpServletResponse;
          import?org.springframework.web.servlet.DispatcherServlet;
          import?org.springframework.web.util.UriComponents;
          import?org.springframework.web.util.UriComponentsBuilder;
          import?org.springframework.web.util.UriUtils;

          public?class?HttpRequestHandler?extends?SimpleChannelInboundHandler<FullHttpRequest>?{

          ????public?HttpRequestHandler(DispatcherServlet?servlet)?{
          ??this.servlet?=?servlet;
          ??this.servletContext?=?servlet.getServletConfig().getServletContext();
          ?}

          ?@Override
          ????public?void?exceptionCaught(ChannelHandlerContext?ctx,?Throwable?e)?throws?Exception?{
          ?????logger.error(e.getMessage(),e);
          ????????ctx.close();
          ????}

          ????protected?void?channelRead0(ChannelHandlerContext?ctx,?FullHttpRequest?fullHttpRequest)?throws?Exception?{
          ?????boolean?flag?=?HttpMethod.POST.equals(fullHttpRequest.getMethod())
          ????????????????||?HttpMethod.GET.equals(fullHttpRequest.getMethod());
          ????????
          ????????Map??parammap?=?getRequestParams(ctx,fullHttpRequest);
          ????????if(flag?&&?ctx.channel().isActive()){
          ????????????//HTTP請(qǐng)求、GET/POST
          ????????????MockHttpServletResponse?servletResponse?=?new?MockHttpServletResponse();
          ????????????MockHttpServletRequest?servletRequest?=new?MockHttpServletRequest(servletContext);
          ????????????//?headers
          ????????????for?(String?name?:?fullHttpRequest.headers().names())?{
          ????????????????for?(String?value?:?fullHttpRequest.headers().getAll(name))?{
          ????????????????????servletRequest.addHeader(name,?value);
          ????????????????}
          ????????????}
          ????????????String?uri?=?fullHttpRequest.getUri();
          ????????????uri?=?new?String(uri.getBytes("ISO8859-1"),?"UTF-8");
          ????????????uri?=?URLDecoder.decode(uri,?"UTF-8");
          ????????????UriComponents?uriComponents?=?UriComponentsBuilder.fromUriString(uri).build();
          ????????????String?path?=?uriComponents.getPath();
          ????????????path?=?URLDecoder.decode(path,?"UTF-8");
          ????????????servletRequest.setRequestURI(path);
          ????????????servletRequest.setServletPath(path);
          ????????????servletRequest.setMethod(fullHttpRequest.getMethod().name());

          ????????????if?(uriComponents.getScheme()?!=?null)?{
          ????????????????servletRequest.setScheme(uriComponents.getScheme());
          ????????????}
          ????????????if?(uriComponents.getHost()?!=?null)?{
          ????????????????servletRequest.setServerName(uriComponents.getHost());
          ????????????}
          ????????????if?(uriComponents.getPort()?!=?-1)?{
          ????????????????servletRequest.setServerPort(uriComponents.getPort());
          ????????????}

          ????????????ByteBuf?content?=?fullHttpRequest.content();
          ????????????content.readerIndex(0);
          ????????????byte[]?data?=?new?byte[content.readableBytes()];
          ????????????content.readBytes(data);
          ????????????servletRequest.setContent(data);

          ????????????try?{
          ????????????????if?(uriComponents.getQuery()?!=?null)?{
          ????????????????????String?query?=?UriUtils.decode(uriComponents.getQuery(),"UTF-8");
          ????????????????????servletRequest.setQueryString(query);
          ????????????????}
          ????????????????if(parammap!=null&¶mmap.size()>0){
          ?????????????????for?(String?key?:?parammap.keySet())?{
          ????????????????????????servletRequest.addParameter(UriUtils.decode(key,"UTF-8"),?UriUtils.decode(parammap.get(key)?==?null???"":?parammap.get(key),?"UTF-8"));
          ????????????????????}
          ????????????????}
          ????????????????
          ????????????}?catch?(UnsupportedEncodingException?ex)?{
          ?????????????ex.printStackTrace();
          ????????????}
          ????????????this.servlet.service(servletRequest,servletResponse);

          ????????????HttpResponseStatus?status?=?HttpResponseStatus.valueOf(servletResponse.getStatus());
          ????????????String?result?=?servletResponse.getContentAsString();
          ????????????result?=?StringUtils.isEmpty(result)?"":result;
          ????????????FullHttpResponse?response?=?new?DefaultFullHttpResponse(HttpVersion.HTTP_1_1,?status,Unpooled.copiedBuffer(result,CharsetUtil.UTF_8));
          ????????????response.headers().set("Content-Type",?"text/json;charset=UTF-8");
          ????????????response.headers().set("Access-Control-Allow-Origin",?"*");
          ????????????response.headers().set("Access-Control-Allow-Headers",?"Content-Type,Content-Length,?Authorization,?Accept,X-Requested-With,X-File-Name");
          ????????????response.headers().set("Access-Control-Allow-Methods",?"PUT,POST,GET,DELETE,OPTIONS");
          ????????????response.headers().set("Content-Length",?Integer.valueOf(response.content().readableBytes()));
          ????????????response.headers().set("Connection",?"keep-alive");
          ????????????ChannelFuture?writeFuture?=?ctx.writeAndFlush(response);
          ????????????writeFuture.addListener(ChannelFutureListener.CLOSE);
          ????????}
          ????}

          ??/**
          ?????*?獲取post請(qǐng)求、get請(qǐng)求的參數(shù)保存到map中
          ?????*/

          ????private?Map?getRequestParams(ChannelHandlerContext?ctx,?HttpRequest?req){
          ????????MaprequestParams=new?HashMap();
          ????????//?處理get請(qǐng)求??
          ????????if?(req.getMethod()?==?HttpMethod.GET)?{
          ????????????QueryStringDecoder?decoder?=?new?QueryStringDecoder(req.getUri());??
          ????????????Map>?parame?=?decoder.parameters();??
          ????????????Iterator>>?iterator?=?parame.entrySet().iterator();
          ????????????while(iterator.hasNext()){
          ????????????????Entry>?next?=?iterator.next();
          ????????????????requestParams.put(next.getKey(),?next.getValue().get(0));
          ????????????}
          ????????}
          ?????????//?處理POST請(qǐng)求??
          ????????if?(req.getMethod()?==?HttpMethod.POST)?{
          ????????????HttpPostRequestDecoder?decoder?=?new?HttpPostRequestDecoder(??
          ????????????????????new?DefaultHttpDataFactory(false),?req);??
          ????????????List?postData?=?decoder.getBodyHttpDatas();?//
          ????????????for(InterfaceHttpData?data:postData){
          ????????????????if?(data.getHttpDataType()?==?HttpDataType.Attribute)?{??
          ????????????????????MemoryAttribute?attribute?=?(MemoryAttribute)?data;??
          ????????????????????requestParams.put(attribute.getName(),?attribute.getValue());
          ????????????????}
          ????????????}
          ????????}
          ????????return?requestParams;
          ????}

          ?private?static?final?Logger?logger?=?LoggerFactory.getLogger(HttpRequestHandler.class);
          ?private?final?DispatcherServlet?servlet;
          ?private?final?ServletContext?servletContext;
          }

          4.初始化servlet并啟動(dòng)netty server

          package?com.magic;

          import?javax.servlet.ServletException;

          import?org.slf4j.Logger;
          import?org.slf4j.LoggerFactory;
          import?org.springframework.context.ApplicationContext;
          import?org.springframework.context.support.ClassPathXmlApplicationContext;
          import?org.springframework.mock.web.MockServletConfig;
          import?org.springframework.web.context.support.XmlWebApplicationContext;
          import?org.springframework.web.servlet.DispatcherServlet;

          import?com.magic.common.config.PropConfig;
          import?com.magic.netty.server.NettyHttpServer;

          public?class?MagicWebServer?{
          ?
          ?private?static?Logger?logger?=?LoggerFactory.getLogger(MagicWebServer.class);

          ?public?static?void?main(String[]?args)?{
          ??ApplicationContext?ctx?=?new?ClassPathXmlApplicationContext("applicationContext.xml");
          ??Integer?port?=?6001;
          ??DispatcherServlet?servlet?=?getDispatcherServlet(ctx);
          ??NettyHttpServer?server?=?new?NettyHttpServer(port,servlet);
          ??server.start();
          ??
          ?}
          ?
          ?public?static?DispatcherServlet?getDispatcherServlet(ApplicationContext?ctx){

          ?????XmlWebApplicationContext?mvcContext?=?new?XmlWebApplicationContext();
          ??mvcContext.setConfigLocation("classpath:spring-servlet.xml");
          ??mvcContext.setParent(ctx);
          ??MockServletConfig?servletConfig?=?new?MockServletConfig(mvcContext.getServletContext(),?"dispatcherServlet");
          ??DispatcherServlet?dispatcherServlet?=?new?DispatcherServlet(mvcContext);
          ??try?{
          ???dispatcherServlet.init(servletConfig);
          ??}?catch?(ServletException?e)?{
          ???e.printStackTrace();
          ??}
          ??return?dispatcherServlet;
          ?}
          }

          5.寫一個(gè)controller,并測(cè)試一波http://127.0.0.1:6001/user/login

          package?com.magic.controller;

          import?java.util.HashMap;
          import?java.util.Map;

          import?org.springframework.stereotype.Controller;
          import?org.springframework.web.bind.annotation.RequestMapping;
          import?org.springframework.web.bind.annotation.ResponseBody;

          import?com.alibaba.fastjson.JSONObject;

          @Controller
          @RequestMapping(value="/user",produces?=?"text/json;charset=utf-8")
          public?class?UserController?extends?BaseController{

          ?@RequestMapping("/login")
          ?@ResponseBody
          ?public?String?login(String?username,String?pwd){
          ??JSONObject?resultJson?=?new?JSONObject();
          ??Map?loginResult?=?new?HashMap();
          ??loginResult.put("username",?username);
          ??loginResult.put("age",?"20");
          ??loginResult.put("sex",?"boy");
          ??
          ??resultJson.put("code",?200);
          ??resultJson.put("msg",?"登錄成功");
          ??resultJson.put("result",?loginResult);
          ??
          ??return?JSONObject.toJSONString(resultJson);
          ?}
          }

          Mark一下,說(shuō)明在coding的時(shí)候遇到的問(wèn)題

          • 代碼中的applicationContext.xmlspring-servlet.xml的按照springMVC的正常配置就行
          • 如果返回到client端的代碼有中文亂碼,那么在requestMapping里面添加produces = “text/json;charset=utf-8”。

          程序汪資料鏈接

          程序汪接的7個(gè)私活都在這里,經(jīng)驗(yàn)整理

          Java項(xiàng)目分享 最新整理全集,找項(xiàng)目不累啦 06版

          堪稱神級(jí)的Spring Boot手冊(cè),從基礎(chǔ)入門到實(shí)戰(zhàn)進(jìn)階

          臥槽!字節(jié)跳動(dòng)《算法中文手冊(cè)》火了,完整版 PDF 開放下載!

          臥槽!阿里大佬總結(jié)的《圖解Java》火了,完整版PDF開放下載!

          字節(jié)跳動(dòng)總結(jié)的設(shè)計(jì)模式 PDF 火了,完整版開放下載!

          歡迎添加程序汪個(gè)人微信 itwang008? 進(jìn)粉絲群或圍觀朋友圈

          瀏覽 24
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  538精品在线观看 | 免费avapp | 成人做爰黄A片免费看直播室男男 | 免费人妻视频 | 色老汉AV一区二区三区 |