1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

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

        共 12976字,需瀏覽 26分鐘

         ·

        2022-02-25 16:44



        來源:blog.csdn.net/shzy1988/article/

        details/78841140


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

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

        然后,說說netty怎么來整合springMVC:當(dāng)client和server建立連接后,我們?cè)赼ddLast的某個(gè)類中將client發(fā)來的請(qǐng)求,讓DispatcherServlet來處理,然后將處理后的結(jié)果通過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)來的連接
        ???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ā)來的請(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一下,說明在coding的時(shí)候遇到的問題

        • 代碼中的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)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            成人无码免费在线观看 | 操逼网址视频 | 汤唯裸体全光无删减 | 91人妻人人澡人人爽人人 | 性生交大片免费看3 | 成人性生活片 | 欧美少妇bb | a黄色视频 | sq调教室虐调教h打开腿玩具 | 欧美色道|