MiniCat源码

程序员要提高,阅读优秀的书籍及源码是必不可少的过程。然而,有时源码过于复杂有大量的类配置等,甚至都不知道从哪里开始。这时候,找一个比较简单的类似版本开始阅读也是不错的选择。Tomcat的源码就比较复杂,所以先了解一些其类似产品MiniCat

MiniCat源码

一开始一直不了解Filter是使用函数回调实现的是什么意思?具体是如何实现的!!直到看完了MiniCat源码,才恍然大悟,原来使用函数回调实现是这个意思。希望阅读本博客的人也有所收获。

MiniCat的整体请求流程

1.创建 mini cat 服务器,并初始化服务器配置(TCP端口)
2.初始化 Servlet,Filter 并存储到对应容器
3.处理请求
3.1 接受 TCP 连接
3.2 http 构建,进入 builder方法
3.3 MiniCat 流程执行分发MinicatProcess.doService(this);
3.4 根据url从容器中取出url
3.5 创建过滤链,执行 Filter 过滤器前半部分
3.6 执行完所有的过滤器后,执行 Servlet
3.7 执行过滤器后半部分

从main方法开始,进入init(此为吾后来添加上去的main方法,原并无。执行此方法就可运行当前MiniCat容器,可以在浏览器访问:http://localhost:80/index.do?name=xx 访问到服务(TestServlet)

    public static void main(String[] args) {
		// 放入需要初始化的 Servlet,Filter
		init(
				TestServlet.class, MultipartServlet.class, MiniCatTestServlet.class,
				BaseFilter.class, GeneralFilter.class
		);
	}

从CoreApp的init方法开始(附init方法源码,及详细注释)

public static void init(Class<?>... clazzs) {
		long startTime = System.currentTimeMillis();
		// 初始化 MiniCat 服务器
		MiniCatService miniCatService = new BioService();
		if (MiniCatConfig.MODEL == 2) {
			miniCatService = new NioService();
		}
		System.out.println("引用模式>>" + miniCatService.getClass().getName());
		try {
			if (StringUtil.isNullOrEmpty(clazzs)) {
				System.err.println("初始化Servlet为空");
				return;
			}
			// 打开端口
			miniCatService.openPort(MiniCatConfig.HTTP_PORT, MiniCatConfig.SESSION_TIMEOUT);
			System.out.println("监听端口>>" + MiniCatConfig.HTTP_PORT);
			for (Class<?> clazz : clazzs) {
				if (!MiniCatHttpPart.class.isAssignableFrom(clazz)) {
					continue;
				}
				// 通过注解获取 Servlet 对象
				Servlet servletFlag = clazz.getAnnotation(Servlet.class);
				if (servletFlag != null && !StringUtil.isNullOrEmpty(servletFlag.value())) {
					// 初始化对象
					HttpServlet servlet = (HttpServlet) clazz.getDeclaredConstructor().newInstance();
					System.out.println("注册Servlet>>" + clazz.getName() + ">>" + servletFlag.value());
					// Servlet 容器中,容器使用Map,是因为通过url快速匹配
					ServletContainer.putServlet(servletFlag.value(), servlet);
				}
				// 通过注解获取 Filter 过滤器对象
				Filter filterFlag=clazz.getAnnotation(Filter.class);
				if (filterFlag != null && !StringUtil.isNullOrEmpty(filterFlag.value())) {
					// 初始化过滤器
					HttpFilter filter = (HttpFilter) clazz.getDeclaredConstructor().newInstance();
					// 过滤的url条件
					filter.setMapping(filterFlag.value());
					System.out.println("注册Filter>>" + clazz.getName() + ">>" + filterFlag.value());
					// 存储到过滤器容器中,过滤器容器使用List集合存储,是因为所有的过滤器都要执行
					FilterContainer.pushFilter(filter);
				}
			}
			System.out.println("MiniCat启动完成,耗时>>" + (System.currentTimeMillis() - startTime) + "ms");
			// 处理请求
			miniCatService.doService();
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
具体流程步骤(以BioService为例)
init方法到miniCatService.doService();之前都是在初始化容器配置,及Servlet,Filter
  1. 进入BioService的doService方法,TCP阻塞等待连接
  2. 连接上,执行doServlet方法(使用线程池)构建HttpBuilder
  3. 进入builder方法(new一个HttpRequest对象,HttpRequestHander数据设置,new 一个HttpRespose对象,
public void builder() {
		try {
            // 创建HttpRequest
			buildRequest();
            // request请求头设置
			buildRequestHeader();
            // 创建Respone
			this.response = new HttpServletResponse();
			// 执行分发
			MinicatProcess.doService(this);
			buildResponse();
		} catch (Exception e) {
            // 方法过程了,删除部分捕抓异常代码
			e.printStackTrace();
			try {
				buildResponse(500, "error execution");
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}

	}

分发 MinicatProcess.doService(this); 

public static void doService(HttpBuilder build) throws 	Exception {
			// 根据url从Servlet容器中拿到对应的 servlet 对象
			HttpServlet servlet = ServletContainer.getServlet(build.getRequest().getRequestURI());
            // 创建过滤链
			ApplicationFilterChain chain=new ApplicationFilterChain(servlet);
			// 执行过滤器
			chain.doFilter(build.getRequest(), build.getResponse());
		
	}

进入过滤链方法chain.doFilter(),在方法的最后执行servlet.doService()到Controller中进行处理

	public void doFilter(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 过滤链出来逻辑
		if (pos < FilterContainer.FILTER_CONTAINER.size()) {
			HttpFilter filter = FilterContainer.FILTER_CONTAINER.get(pos++);
			if(!AntUtil.isAntMatch(request.getRequestURI(), filter.getMapping())){
				doFilter(request, response);
				return;
			}
			// 过滤器 doFilter 函数回调(有点类似递归,只是调用的方式不一样)
			filter.doFilter(request, response, this);
			return;
		}
		if (servlet == null) {
			throw new PageNotFoundException("该页面未找到>>" + request.getRequestURI());
		}
		// 过滤链执行完成,执行 servlet 方法(即Controller中的方法)
		servlet.doService(request, response);
	}

即,此就是MiniCat Web服务器中一次请求的过程。到这里也就理解Filter的函数回调是什么意思。感谢开源作者写的MiniCat!!!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值