1. 程式人生 > >netty整合springMVC,實現高效的HTTP服務請求

netty整合springMVC,實現高效的HTTP服務請求

參考http://blog.csdn.net/imlsz/article/details/42673507的程式碼,謝謝!不過在處理返回servlet的結果時候,按照上文的方法不行。

首先,你必須要了解netty,說簡單點:客戶端通過TCP連結和伺服器建立長連線,client和server都是通過管道(ChannelPipeline)的addLast方法的新增順序來處理接收或者傳送的資料。這個和struts的filter的doFilter原理類似,處理完一個filter,如果後面還有其他的filter,就將資料chain.doFilter來繼續處理。

然後,說說netty怎麼來整合springMVC:當client和server建立連線後,我們在addLast的某個類中將client發來的請求,讓DispatcherServlet來處理,然後將處理後的結果通過ChannelHandlerContext或者Channel將,結果writeAndFlush到client。

1.寫一個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"); // 繫結埠,開始接收進來的連線 ChannelFuture f = b.bind(port).sync(); // 等待伺服器 socket 關閉 。在這個例子中,這不會發生,但你可以優雅地關閉你的伺服器。 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發來的請求

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<String, String>  parammap = getRequestParams(ctx,fullHttpRequest);
        if(flag && ctx.channel().isActive()){
            //HTTP請求、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&&parammap.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請求、get請求的引數儲存到map中
     */
    private Map<String, String> getRequestParams(ChannelHandlerContext ctx, HttpRequest req){
        Map<String, String>requestParams=new HashMap<String, String>();
        // 處理get請求  
        if (req.getMethod() == HttpMethod.GET) {
            QueryStringDecoder decoder = new QueryStringDecoder(req.getUri());  
            Map<String, List<String>> parame = decoder.parameters();  
            Iterator<Entry<String, List<String>>> iterator = parame.entrySet().iterator();
            while(iterator.hasNext()){
                Entry<String, List<String>> next = iterator.next();
                requestParams.put(next.getKey(), next.getValue().get(0));
            }
        }
         // 處理POST請求  
        if (req.getMethod() == HttpMethod.POST) {
            HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(  
                    new DefaultHttpDataFactory(false), req);  
            List<InterfaceHttpData> 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並啟動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
            
           

相關推薦

netty整合springMVC實現高效HTTP服務請求

參考http://blog.csdn.net/imlsz/article/details/42673507的程式碼,謝謝!不過在處理返回servlet的結果時候,按照上文的方法不行。 首先,你必須要了解netty,說簡單點:客戶端通過TCP連結和伺服器建立長連線

Zuul中整合Swagger2實現對源服務API測試

前言 我們知道,Swagger2整合到專案中,可以非常方便地進行介面測試,是前後端對接效率提高。現在,我們可以在Zuul中整合Swagger2,通過Zuul配置檔案配置的對映路徑,來生成源服務介面的測

Shiro 整合SpringMVC 並且實現許可權管理登入和登出

Apache Shiro是Java的一個安全框架。目前,使用Apache Shiro的人越來越多,因為它相當簡單,對比Spring Security,可能沒有Spring Security做的功能強大,但是在實際工作時可能並不需要那麼複雜的東西,所以使用小而簡單

SpringMVC整合quartz實現定時任務

首先,我用的是maven下載jar包 <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artif

SpringBoot2 高階案例(14) : 整合 Drools規則引擎實現高效的業務規則

一、Drools引擎簡介 1、基礎簡介 Drools是一個基於java的規則引擎,開源的,可以將複雜多變的規則從硬編碼中解放出來,以規則指令碼的形式存放在檔案中,使得規則的變更不需要修正程式碼重啟機器就可以立即在線上環境生效。具有易於訪問企業策略、易於調整以及易於管理的特點,作為開源業務規則引擎,符合業內

Spring(五):Spring&Struts2&Hibernate整合實現查詢Employee信息

view event last .html ssh tla url 配置文件 hid 背景:   基於之前兩篇文章《Spring(三):Spring整合Hibernate》、《Spring(四):Spring整合Hibernate,之後整合Struts2》,了解了

Spring Boot 整合 Elasticsearch實現 function score query 權重分查詢

search 小寫 業務 jpg 啟動會 last cti cal agen 摘要: 原創出處 www.bysocket.com 「泥瓦匠BYSocket 」歡迎轉載,保留摘要,謝謝! 『 預見未來最好的方式就是親手創造未來 – 《史蒂夫·喬布斯

jmeter通過BeanShell 腳本實現http請求參數的加密

一個 sha 下載源碼 功能 mage 使用 1-1 one 裏的 jmeter一直是一款很好的接口和性能測試工具,它是開源的,不需要為此支付任何費用,而且可以下載源碼,可以在修改源代碼並在此基礎上拓展自己的功能或插件,它可以跟ant和jenkins結合起來搭建自己的自動化

Spring中整合Cage實現驗證碼功能

ger 類型 body match exce sub pom esp rec 1.pom.xml中添加Cage依賴。 <dependency> <groupId>com.github.cage</groupId

從零實現一個http服務

retrieve vba ilove ext TP 應用場景 註釋 end HA 我始終覺得,天生的出身很重要,但後天的努力更加重要,所以如今的很多“科班”往往不如後天努力的“非科班”。所以,我們需要重新給“專業”和“專家”下一個定義:所謂專業,就是別人搞你不搞,這就是你的

Python實現簡單HTTP服務器(一)

recv ati listen bind ESS 內容 text code 讀取內容 一.返回固定內容 # coding:utf-8 import socket from multiprocessing import Process def handle_clien

Python 進行 SSH 操作實現本地與服務器的鏈接進行文件的上傳和下載

enc 項目介紹 use 解讀 數據庫文件 需要 toad 鏈接 {} Python 進行 SSH 操作,實現本地與服務器的鏈接,進行文件的上傳和下載 2018年5月26日 19:03 閱讀 375 評論 7 我本地和服務器的連接一直使用的是 Xshell 5,

Linux6.5中配置PXE自動裝機實現批量裝機服務

linu type 大量 oss 9.png tex 技術 批量裝機 watermark 為了增加工作效率,我們在進行linux裝機時,在面臨大量裸機的情況下, PXE自動裝機的作用尤為顯著,能夠大大減少我們工作壓力,增加工作效率。 安裝環境:linux6.5一臺,w

springboot2整合easypoi實現Excel匯入匯出

1.新增Maven依賴 <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-base</artifactId> <v

Springboot整合curator實現分散式鎖(zookeeper)

0.linux安裝啟動zookeeper yum install nc wget http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.10/zookeeper-3.4.10.tar.gz tar -zxvf zookeepe

node+mysql+ajax+javascript搭建一套服務介面實現前後臺數據請求

node+mysql+ajax+javascript搭建一套服務介面,實現前後臺數據請求 效果圖如下所示: 啟動服務 get請求 查詢mysql資料庫 express介紹 Express 基於

SSM整合Shiro實現系統的認證管理和許可權管理?

資料: 一、首先匯入依賴: <!--spring的版本號--> <spring-version>4.3.13.RELEASE</spring-version> <!--mybatis的版本號

springboot整合redis實現session共享

   一直對serssion的共享有著很大的疑惑,對於我現在的工作的地方,所在的部門,因為沒有前臺頁面,純屬後臺。所以,不會存在session的共享問題。但是出於好奇,也是心裡的疑惑,今天也動手實驗了下。      

SpringBoot整合RabbitMQ實現訊息傳送和消費

下載安裝Erlang和RabbitMQ Erlang和RabbitMQ:https://www.cnblogs.com/theRhyme/p/10069611.html   專案建立和依賴 推薦SpringCloud專案線上建立:https://start.spring.io/ 不用上面這

spring mvc攔截器實現統計http請求的後臺執行時間

使用兩種方式,實現攔截http請求的後臺執行時間。 廢話不多說直接上程式碼 /** * Http請求時間統計 * 攔截所有請求 */ public class HttpRquestTimeInterceptor extends HandlerInterceptorAdapter { Threa