栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Tomcat使用Netty实现

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Tomcat使用Netty实现

  • 定义配置文件,指定 url,与对应的执行类
servlet.one.url=/firstServlet.do
servlet.one.className=com.rt.netty.tomcat.servlet.FirstServlet

servlet.two.url=/secondServlet.do
servlet.two.className=com.rt.netty.tomcat.servlet.SecondServlet
  • 读取配置文件,初始化 Servlet 容器
private Map servletMapping = new HashMap();
private Properties webxml = new Properties();
private void init(){
	//加载web.xml文件,同时初始化 ServletMapping对象
	try{
		String WEB_INF = this.getClass().getResource("/").getPath();
		FileInputStream fis = new FileInputStream(WEB_INF + "web.properties");
		webxml.load(fis);
		for (Object k : webxml.keySet()) {
			String key = k.toString();
			if(key.endsWith(".url")){
				String servletName = key.replaceAll("\.url$", "");
				String url = webxml.getProperty(key);
				String className = webxml.getProperty(servletName + ".className");
				RTServlet obj = (RTServlet)Class.forName(className).newInstance();
				servletMapping.put(url, obj);
			}
		}
	}catch(Exception e){
		e.printStackTrace();
	}
}	
  • Netty 启动对本地IP指定端口的监听
//Netty封装了NIO,Reactor模型,Boss,worker
// Boss线程
EventLoopGroup bossGroup = new NioEventLoopGroup();
// Worker线程
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
	// Netty服务
	//ServetBootstrap   ServerSocketChannel
	ServerBootstrap server = new ServerBootstrap();
	// 链路式编程
	server.group(bossGroup, workerGroup)
			// 主线程处理类,看到这样的写法,底层就是用反射
			.channel(NioServerSocketChannel.class)
			// 子线程处理类 , Handler
			.childHandler(new ChannelInitializer() {
				// 客户端初始化处理
				protected void initChannel(SocketChannel client) throws Exception {
					// 无锁化串行编程
					//Netty对HTTP协议的封装,顺序有要求
					// HttpResponseEncoder 编码器
					client.pipeline().addLast(new HttpResponseEncoder());
					// HttpRequestDecoder 解码器
					client.pipeline().addLast(new HttpRequestDecoder());
					// 业务逻辑处理
					client.pipeline().addLast(new RTTomcatHandler());
				}
			})
			// 针对主线程的配置 分配线程最大数量 128
			.option(ChannelOption.SO_BACKLOG, 128)
			// 针对子线程的配置 保持长连接
			.childOption(ChannelOption.SO_KEEPALIVE, true);
	// 启动服务器
	ChannelFuture f = server.bind(port).sync();
	System.out.println("Tomcat 已启动,监听的端口是:" + port);
	f.channel().closeFuture().sync();
}catch (Exception e){
	e.printStackTrace();
}finally {
	// 关闭线程池
	bossGroup.shutdownGracefully();
	workerGroup.shutdownGracefully();
}
  • 处理对指定端口的网络连接
public class RTTomcatHandler extends ChannelInboundHandlerAdapter {
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		if (msg instanceof HttpRequest){
			HttpRequest req = (HttpRequest) msg;
			// 转交给我们自己的request实现
			RTRequest request = new RTRequest(ctx,req);
			// 转交给我们自己的response实现
			RTResponse response = new RTResponse(ctx,req);
			// 实际业务处理
			String url = request.getUrl();
			if(servletMapping.containsKey(url)){
				servletMapping.get(url).service(request, response);
			}else{
				response.write("404 - Not Found");
			}
		}
	}
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
	}
}
  • 封装请求与响应对象
private ChannelHandlerContext ctx;
private HttpRequest req;
public RTRequest(ChannelHandlerContext ctx, HttpRequest r
	this.ctx = ctx;
	this.req = req;
}
public String getUrl() {
	return req.uri();
}
public String getMethod() {
	return req.method().name();
}
public class RTResponse {

	//SocketChannel的封装
	private ChannelHandlerContext ctx;

	private HttpRequest req;

	public RTResponse(ChannelHandlerContext ctx, HttpRequest req) {
		this.ctx = ctx;
		this.req = req;
	}

	public void write(String out) throws Exception {
		try {
			if (out == null || out.length() == 0) {
				return;
			}
			// 设置 http协议及请求头信息
			FullHttpResponse response = new DefaultFullHttpResponse(
				// 设置http版本为1.1
				HttpVersion.HTTP_1_1,
				// 设置响应状态码
				HttpResponseStatus.OK,
				// 将输出值写出 编码为UTF-8
				Unpooled.wrappedBuffer(out.getBytes("UTF-8")));

			response.headers().set("Content-Type", "text/html;");
			// 当前是否支持长连接
//            if (HttpUtil.isKeepAlive(r)) {
//                // 设置连接内容为长连接
//                response.headers().set(CONNECTION, HttpHeaderValues.KEEP_ALIVE);
//            }
			ctx.write(response);
		} finally {
			ctx.flush();
			ctx.close();
		}
	}
}
  • RTServlet 请求分发
public abstract class RTServlet {
	
	public void service(RTRequest request, RTResponse response) throws Exception{
		
		//由service方法来决定,是调用doGet或者调用doPost
		if("GET".equalsIgnoreCase(request.getMethod())){
			doGet(request, response);
		}else{
			doPost(request, response);
		}

	}
	
	public abstract void doGet(RTRequest request, RTResponse response) throws Exception;
	
	public abstract void doPost(RTRequest request, RTResponse response) throws Exception;
}
  • servlet 执行类
	public void doGet(RTRequest request, RTResponse response) throws Exception {
		this.doPost(request, response);
	}

	public void doPost(RTRequest request, RTResponse response) throws Exception {
		response.write("This is rt First Serlvet");
	}

}
public class SecondServlet extends RTServlet {

	public void doGet(RTRequest request, RTResponse response) throws Exception {
		this.doPost(request, response);
	}

	public void doPost(RTRequest request, RTResponse response) throws Exception {
		response.write("This is rt Second Serlvet");
	}

}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/531374.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号