`

使用netty4.0实现Http请求的分发

    博客分类:
  • java
 
阅读更多

思路是使用executor来处理被分发的请求。

 

主类的代码:

 

package com.mytest.main;

import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.mytest.executors.AbstractExecutor;
import com.mytest.executors.HelloExecutor;
import com.mytest.executors.TestExecutor;
import com.mytest.handles.Dispatcher;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
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.HttpServerCodec;
import io.netty.handler.timeout.IdleStateHandler;

public class StartupDisPatchClass {
	private static Logger logger = LoggerFactory.getLogger(StartupDisPatchClass.class);
	
	private void launchServer() {
		EventLoopGroup bossGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors()/2+1);
		EventLoopGroup workerGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors()/2+1);
		
		try {
			//服务启动
			ServerBootstrap b = new ServerBootstrap();
			b.group(bossGroup, workerGroup)
					.channel(NioServerSocketChannel.class)
					.childHandler(this.new ChildChannelHandler())
					.option(ChannelOption.SO_BACKLOG, 1024)
					.option(ChannelOption.SO_REUSEADDR, true)
					.option(ChannelOption.SO_KEEPALIVE, true);
			Channel ch = b.bind(new InetSocketAddress(9000)).sync().channel();
			logger.info("httpserver started on port[" + 9000+ "]");
			ch.closeFuture().sync();
		} catch (InterruptedException e) {
			logger.error(e.getMessage(),e);
		} finally {
			//服务关闭
			bossGroup.shutdownGracefully();
			workerGroup.shutdownGracefully();
		}
	}
	
	public static void main(String [] args) throws InterruptedException {
		new StartupDisPatchClass().launchServer();
		
		
	}
	
	 class ChildChannelHandler extends ChannelInitializer<SocketChannel> {
	        @Override
	        protected void initChannel(SocketChannel arg0) throws Exception {
	        	logger.info("server initChannel..");
	        	
	            ChannelPipeline p = arg0.pipeline();
	            //监控线程空闲事件
	            p.addLast("idleStateHandler", new IdleStateHandler(60, 60, 30));
	            //将httprequest和httpresponse处理合并成一个
	    		p.addLast("ServiceDecoder", new HttpServerCodec());
	    		//控制http消息的组合,参数表示支持的内容最大长度
	    		p.addLast("httpAggregator",new HttpObjectAggregator(1024));
	    		Dispatcher dispatcher = new Dispatcher();
	    		
	    		Map<String, Class<? extends AbstractExecutor>> apiMappings = new HashMap<String, Class<? extends AbstractExecutor>>();
	    		
	    		apiMappings.put("hello", HelloExecutor.class);
	    		apiMappings.put("test", TestExecutor.class);
	    		dispatcher.setApiMappings(apiMappings);
	    		
	    		p.addLast("dispatcher",dispatcher);
	        }
	    }

}

 

 

 

分发器的代码:

 

package com.mytest.handles;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.mytest.executors.AbstractExecutor;
import com.mytest.executors.DefaultExecutor;
import com.mytest.utils.UrlUtil;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.FullHttpRequest;

public class Dispatcher extends ChannelInboundHandlerAdapter {
	private Map<String,Class<? extends AbstractExecutor>> apiMappings = new HashMap<String,Class<? extends AbstractExecutor>>();
	
	public Map<String, Class<? extends AbstractExecutor>> getApiMappings() {
		return apiMappings;
	}

	public void setApiMappings(Map<String, Class<? extends AbstractExecutor>> apiMappings) {
		this.apiMappings = apiMappings;
	}

	@Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof FullHttpRequest) {
        	FullHttpRequest request = (FullHttpRequest) msg;
        	String url = request.getUri();
        	System.out.println(url);
        	ExecutorService executorService =  Executors.newFixedThreadPool(10);
        	String apiName = UrlUtil.getApiName(url);
        	
        	
        	AbstractExecutor executor = null;
        	if (this.apiMappings.containsKey(apiName)) {
        		//实现了分发
        		executor = this.apiMappings.get(apiName).newInstance();
        		
        	}else{
                        //默认处理逻辑
        		executor = new DefaultExecutor();
        	}
        	executor.setCtx(ctx);
    		executor.setMsg(request);
    		executorService.submit(executor);
        	
        }
    }
	
	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		
	}
}

 

excutor抽象类

package com.mytest.executors;


import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;

public abstract class AbstractExecutor extends Thread {
	protected String apiName;
	protected ChannelHandlerContext ctx;
	protected FullHttpRequest msg;
	protected FullHttpResponse response;
	
	public ChannelHandlerContext getCtx() {
		return ctx;
	}


	public void setCtx(ChannelHandlerContext ctx) {
		this.ctx = ctx;
	}


	public FullHttpRequest getMsg() {
		return msg;
	}


	public void setMsg(FullHttpRequest msg) {
		this.msg = msg;
	}
	

	public FullHttpResponse getResponse() {
		return response;
	}


	public void setResponse(FullHttpResponse response) {
		this.response = response;
	}


	public String getApiName() {
		return apiName;
	}


	public void setApiName(String apiName) {
		this.apiName = apiName;
	}


	public abstract boolean preWork();
	public abstract boolean doWork();
	public abstract boolean postWork();


	public final void run() {
		
		boolean flag = this.preWork();
		if (flag==true) {
			this.doWork();
		}
		if (flag== true) {
			this.postWork();
		}
		if (this.msg!= null) {
			System.out.println("From " + this.getApiName() + " executor\t" + msg.getUri());
		}
		
		this.ctx.writeAndFlush(this.getResponse());
		this.ctx.close();
	}
}

 

抽象类的一个子类:默认处理单元

 

package com.mytest.executors;

import io.netty.buffer.Unpooled;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.util.CharsetUtil;

public class DefaultExecutor extends AbstractExecutor {

	@Override
	public boolean preWork() {
		return true;
	}

	@Override
	public boolean doWork() {
		String content = "{\"e\":0,\"api\":\"default\"}";
		FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.copiedBuffer(content.toCharArray(), CharsetUtil.UTF_8));
		this.setApiName("default");
		this.setResponse(response);
		return true;
	}

	@Override
	public boolean postWork() {
		return true;
	}

}

 

还有一个处理url的工具类:

 

package com.mytest.utils;

public class UrlUtil {
	public static String getApiName(String url){
		String result = "";
		try {
			int i = url.lastIndexOf("/");
			String substr = url.substring(i+1);
			int end = substr.indexOf("?");
			if (end >0) {
				result = substr.substring(0,substr.indexOf("?"));
			}else {
				result = substr.substring(0);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}



	public static void main(String [] args ) {
		String url="/hello?uid=1";
		System.out.println(UrlUtil.getApiName(url));
	
		url = "/hello1";
		System.out.println(UrlUtil.getApiName(url));
	}
			
}

 

 

大概是这样。如果需要引入spring的话,还需要自己动动脑筋。以上代码,仅仅是抛砖引玉。

 

 

分享到:
评论

相关推荐

    netty4.0文件分片上传+断点续传+权限校验

    在本文中,我们将深入探讨如何利用Netty 4.0实现文件分片上传、断点续传以及权限校验的功能。 **文件分片上传** 文件分片上传是为了处理大文件传输时,避免一次性加载整个文件到内存中,从而减少内存消耗和提高...

    Netty4.0 http案例

    在这个“Netty4.0 http案例”中,我们将深入探讨如何利用Netty 4.0 实现HTTP服务,以及客户端如何通过HTTP请求与服务器进行交互,特别是在处理JSON格式的数据时。 首先,让我们了解HTTP协议。HTTP(超文本传输协议...

    Netty4.0 jar包 及 源代码 和 例子

    Netty4.0全部jar包.开发时候只需要倒入总的哪一个netty4.0.jar就行了 后缀为resources.jar的全部是源码。 简单的代码例子在netty-example-resources.jar里面。

    Springboot 2.0 整合 Netty 4.0 实现IO异步通讯架构

    Springboot2.0.8集成 netty4 ,使用protobuf作为ping的数据交换,比json更加的小巧,占用数据量更小,可用于任何第三方应用做心跳监控。 已完成功能: - 客户端授权验证(基于protoBuff) - 心跳检测(基于protoBuff) ...

    Netty4.0学习笔记系列之四:混合使用coder和handler

    在本篇Netty4.0学习笔记中,我们将聚焦于如何在实际应用中混合使用`coder`和`handler`,这是Netty框架中非常关键的一部分,对于构建高性能、低延迟的网络应用程序至关重要。Netty是一个用Java编写的异步事件驱动的...

    Netty4.0 官网例子(免费)

    Netty4.0 是其一个重要版本,引入了诸多改进和新特性。 在 Netty4.0 中,主要知识点包括: 1. **ByteBuf**:Netty4.0 引入了 ByteBuf 作为缓冲区,替代了传统的 ByteBuffer。ByteBuf 提供了更高效的内存管理,支持...

    netty4.0工具包

    NIO socket开发,netty4.0工具包。

    netty4.0.45jar包socket和http工具包

    Netty 4.0.45提供了高度优化的NIO(非阻塞I/O)和EPOLL(用于Linux系统的高效I/O)实现,确保了在处理大量并发连接时的性能。 在Socket开发中,Netty的ChannelHandlerContext和EventLoopGroup等概念非常关键。...

    使用Netty4实现多线程的消息分发

    使用 Netty 4 实现多线程的消息分发,可以有效地应对高并发场景,提高服务的响应速度和吞吐量。通过对 EventLoopGroup、EventLoop、ChannelHandler 和 ChannelPipeline 的理解和运用,我们可以构建出强大而灵活的...

    Netty4.0学习笔记系列之三:构建简单的http服务

    在本教程中,我们将探讨如何利用Netty4.0实现一个基本的HTTP服务器。 1. **Netty概述**: - Netty是一个用于快速开发可维护的高性能协议服务器和客户端的开源框架。 - 它提供了一种统一的API来处理多种传输协议,...

    Netty4.0.54英文版API文档

    Netty4.0.54英文版API文档,与官网中文档内容一致,方便用户在离线环境下,开发Netty

    netty4.0中的新变化和注意点鸟窝.pdf

    在 Netty 4.0 中,引入了一系列重大改进和变化,旨在提高性能、可维护性和易用性。以下是这些变化的详细说明: 1. **工程结构的改变**: - 包名从 org.jboss.netty 更改为 io.netty,反映了项目的独立性。 - ...

    netty4.0源码,netty例子,netty api文档

    总结起来,这个压缩包为学习和使用Netty提供了一套完整的资源。通过研究源码、阅读API文档和运行示例,开发者可以掌握Netty的精髓,提升网络编程能力,并在实际项目中发挥出Netty的强大性能。无论你是初学者还是经验...

    Netty4.0学习笔记系列之六:多种通讯协议支持

    在本篇Netty4.0学习笔记系列之六中,我们将深入探讨Netty框架如何支持多种通讯协议,以及它在实现高效、灵活的网络通信中的关键特性。Netty是一个高性能、异步事件驱动的网络应用框架,适用于开发服务器和客户端的...

    Netty4.0学习笔记系列之五:自定义通讯协议

    在本篇“Netty4.0学习笔记系列之五:自定义通讯协议”中,我们将深入探讨如何在Netty框架下构建和实现自己的通信协议。Netty是一个高性能、异步事件驱动的网络应用框架,广泛应用于Java领域的服务器开发,如网络游戏...

    netty4.0 demo

    这个"Netty4.0 demo"压缩包包含了一些Netty 4.0版本的应用示例代码,可以帮助我们更好地理解和学习Netty的工作原理以及如何在实际项目中运用它。 1. **Netty简介** Netty 是由JBOSS组织开发的一个开源项目,最初...

    netty-4.0.28.Final

    Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序dsf。...netty, 4.0.28, Final, jar包, 含源码

    Netty4.0学习笔记系列之二:Handler的执行顺序

    在本篇“Netty4.0学习笔记系列之二:Handler的执行顺序”中,我们将深入探讨Netty中的Handler处理链以及它们的执行流程。 首先,Netty 中的 ChannelHandler 是处理 I/O 事件或拦截 I/O 操作的核心组件。每个 ...

    Netty4.0学习笔记系列之一:Server与Client的通讯

    在Netty中,数据的传输是通过`ByteBuf`实现的,这是一个高效且灵活的字节缓冲区,可以避免不必要的内存复制。`ByteBuf`提供了读写指针管理,方便我们处理不同格式的数据。 此外,Netty还提供了许多内置的协议支持,...

    Netty (netty-netty-4.0.56.Final.tar.gz)

    Netty (netty-netty-4.0.56.Final.tar.gz)是一个 NIO 客户端服务器框架,可以快速轻松地开发协议服务器和客户端等网络应用程序。它极大地简化和流线了网络编程,例如 TCP 和 UDP 套接字服务器。 “快速和简单”并...

Global site tag (gtag.js) - Google Analytics