tomcat原理分析与简单实现
tomcat原理分析与简单实现
https://blog.csdn.net/u014795347/article/details/52328221
1.tomcat实际是运行在jvm中的一个进程。我们把它定义为【中间件】,顾名思义,他是一个在java项目与jvm之间的
中间容器。我们的web项目没有入口方法(main方法),那么他是如何运行起来并为客户端返回数据的呢?
2.web项目[就javaee而讲]的本质,是一大堆的资源文件和方法。其中没有main方法,意味着web项目中的方法不会自动
运行起来。
3.这样,我们想想也知道,我们把web项目部署进tomcat的webapp中的目的是很明确的,那就是希望tomcat去调用我们
写好的方法去为客户端返回需要的资源和数据。
4.tomcat可以运行起来,并调用我们写好的方法。那么,tomcat一定有一个main方法。
5.对于tomcat而言,它并不知道我们会有什么样的方法,这些都只是在项目被部署进webapp下后才确定的,由此分析,
必然用到了java的反射来实现类的动态加载、实例化、获取方法、调用方法。
6.那么tomcat如何确定调用什么方法呢。这取却于客户端的请求,举个栗子:
【http://127.0.0.1:8080/a/b/c.htm?a=1&b=2】这样的一个请求,通过http协议,使用GET方法在浏览器发往本机的8080端口,
携带的参数包含两部分a.方法,包含此方法的路径【/a/b/c.htm】,这里的方法为c,以htm标注,/a/b代表路径
这样可以允许在不同路径下存在同名方法,更可以唯一定位一个方法。b.参数,包含参数名和参数值【a=1&b=2】
通过这样的方法,要调用哪个方法,以及需要什么参数,我们的tomcat一目了然。
7.综上所述,我们有下面的总结:
a.tomcat需要main方法启动。
b.tomcat需要监听本机上的某个端口。
c.tomcat需要抓取此端口上来自客户端的链接并获得请求调用的方法与参数。
d.tomcat需要根据请求调用的方法,动态地加载方法所在的类,完成累的实例化并通过该实例获得需要的方法最终将请求
传入方法执行。
e.将结果返回给客户端(jsp/html页面、json/xml字符串)。
二、模型实现
1.Main.java
- package cn.wwyxxmiemie.littletomcat;
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.lang.reflect.Constructor;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
- import java.net.ServerSocket;
- import java.net.Socket;
- import cn.wwyxxmiemie.littletomcat.exclass.ExClass;
- import cn.wwyxxmiemie.littletomcat.util.ClintRequestBean;
- /**
- * 这是littletomcat的类,是整个容器的入口类
- * 程序在这个类的main方法启动
- * @author 卫卫羊习习
- */
- public class Main {
- /**
- * 容器主方法
- * @param args
- * @throws InstantiationException
- * @throws ClassNotFoundException
- * @throws SecurityException
- * @throws NoSuchMethodException
- */
- public static void main(String[] args) throws InstantiationException {
- System.out.println("little_tomcat_is_running!");
- try {
- ServerSocket serverSocket = new ServerSocket(80);
- while (true) {
- //服务器每接受一次请求,创建一个socket对象
- Socket socket = serverSocket.accept();
- BufferedReader bReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
- String line = bReader.readLine();
- if (!(null==line)) {
- ClintRequestBean requestBean = new ClintRequestBean(line);
- System.out.println("客户端请求:"+requestBean.toReadString());
- System.out.println("请求参数[路径]:"+requestBean.getRequestParm().get("path"));
- System.out.println("请求参数[参数表]:"+requestBean.getRequestParm().get("attrs"));
- ClassLoader classLoader = ClassLoader.getSystemClassLoader();
- try {
- classLoader.loadClass("cn.wwyxxmiemie.littletomcat.exclass.ExClass");
- System.out.println("动态加载ExClass类--成功");
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- System.out.println("动态加载ExClass类--失败");
- }
- Class<?> exClass = null;
- try {
- exClass = Class.forName("cn.wwyxxmiemie.littletomcat.exclass.ExClass");
- System.out.println("动态初始化ExClass类--成功");
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- System.out.println("动态初始化ExClass类--失败");
- }
- Method method;
- try {
- method = exClass.getMethod("test", null);
- System.out.println("得到ExClass对象的"+method.getName()+"方法");
- try {
- System.out.println("执行ExClass对象的"+method.getName()+"方法");
- method.invoke(exClass.newInstance(), null);
- } catch (IllegalAccessException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IllegalArgumentException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- } catch (NoSuchMethodException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (SecurityException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- bReader.close();
- socket.close();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
2.ClintRequestBean.Java
- package cn.wwyxxmiemie.littletomcat.util;
- import java.util.HashMap;
- import java.util.Map;
- /**
- * 客户端请求实体
- * 用于封装客户端的链接数据
- * @author 卫卫羊习习
- */
- public class ClintRequestBean {
- //以一个请求举例:http://127.0.0.1/www/qqq/eee
- private String protocol;//协议类型(eg:http)
- private String protocolVersion;//协议版本(eg:1.1)
- private String data;//请求数据(eg:/www/qqq/eee)
- private String method;//请求方法:(eg:GET)
- /**
- * 客户端请求实体构造方法
- * @param protocol 协议类型 (eg:http)
- * @param protocolVersion 协议版本 (eg:1.1)
- * @param data 请求数据 (eg:/www/qqq/eee)【必须以‘/’分隔】
- * @param method 请求方法 (eg:GET)
- */
- public ClintRequestBean(String protocol, String protocolVersion, String data, String method) {
- super();
- this.protocol = protocol;
- this.protocolVersion = protocolVersion;
- this.data = data;
- this.method = method;
- }
- /**
- * 客户端请求实体构造方法
- * @param request 请求链接,一般针对一条完整的http链接
- */
- public ClintRequestBean(String request){
- super();
- String [] requestString = request.split(" ");
- this.method = requestString[0];
- this.data = requestString[1];
- String [] proAndVer = requestString[2].split("/");
- this.protocol = proAndVer[0];
- this.protocolVersion = proAndVer[1];
- }
- /**
- * 转化为可读String用于分析请求
- * @return
- */
- public String toReadString(){
- return "ClintRequestBean [protocol=" + protocol + ", protocolVersion=" + protocolVersion + ", data=" + data
- + ", method=" + method + "]";
- }
- /**
- * 得到请求的参数
- * @return map[请求路径|参数map]
- */
- public Map<String, Object> getRequestParm(){
- Map<String,Object> map = new HashMap<>();
- String [] parms = data.split("\\?");
- map.put("path", parms[0]);
- Map<String, String> attrs = new HashMap<>();
- String[] kvs = parms[1].split("&");
- for (String string : kvs) {
- String [] kv = string.split("=");
- attrs.put(kv[0], kv[1]);
- }
- map.put("attrs", attrs);
- return map;
- }
- public String getProtocol() {
- return protocol;
- }
- public void setProtocol(String protocol) {
- this.protocol = protocol;
- }
- public String getProtocolVersion() {
- return protocolVersion;
- }
- public void setProtocolVersion(String protocolVersion) {
- this.protocolVersion = protocolVersion;
- }
- public String getData() {
- return data;
- }
- public void setData(String data) {
- this.data = data;
- }
- public String getMethod() {
- return method;
- }
- public void setMethod(String method) {
- this.method = method;
- }
- @Override
- public String toString() {
- return this.method+" "+this.data+" "+this.protocol+"/"+this.protocolVersion;
- }
- }
3.ExClass.java 用于编译生成ExClass.class文件,供littletomcat动态加载
- package cn.wwyxxmiemie.littletomcat.exclass;
- /**
- * 测试类,被主容器动态调用
- * @author 卫卫羊习习
- */
- public class ExClass {
- /**
- * 测试方法
- */
- public void test(){
- System.out.println("ExClass.test()方法被调用");
- }
- }
三、检测
在浏览器发出如下http请求
【http://127.0.0.1/qqq/www/eee/?a=1&b=2】
littletomcat反映如下
四、注
以上代码并没有实现选择方法,但类的加载实则参数为字符串,大家理解原理就好
tomcat原理分析与简单实现的更多相关文章
- Shiro框架 (原理分析与简单实现)
Shiro框架(原理分析与简单实现) 有兴趣的同学也可以阅读我之前分享的:Java权限管理(授权与认证)CRM权限管理 (PS : 这篇博客里面的实现方式没有使用框架,完全是手写的授权与认证,可以 ...
- vue2.0 双向绑定原理分析及简单实现
Vue用了有一段时间了,每当有人问到Vue双向绑定是怎么回事的时候,总是不能给大家解释的很清楚,正好最近有时间把它梳理一下,让自己理解的更清楚,下次有人问我的时候,可以侃侃而谈. 一.首先介绍Obje ...
- spring之mvc原理分析及简单模拟实现
在之前的一篇博客中已经简单的实现了spring的IOC和DI功能,本文将在之前的基础上实现mvc功能. 一 什么是MVC MVC简单的说就是一种软件实现的设计模式,将整个系统进行分层,M(model ...
- Xss漏洞原理分析及简单的讲解
感觉百度百科 针对XSS的讲解,挺不错的,转载一下~ XSS攻击全称跨站脚本攻击,是为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XS ...
- Tomcat源码分析——请求原理分析(下)
前言 本文继续讲解TOMCAT的请求原理分析,建议朋友们阅读本文时首先阅读过<TOMCAT源码分析——请求原理分析(上)>和<TOMCAT源码分析——请求原理分析(中)>.在& ...
- Tomcat源码分析——请求原理分析(中)
前言 在<TOMCAT源码分析——请求原理分析(上)>一文中已经介绍了关于Tomcat7.0处理请求前作的初始化和准备工作,请读者在阅读本文前确保掌握<TOMCAT源码分析——请求原 ...
- Tomcat源码分析——请求原理分析(上)
前言 谈起Tomcat的诞生,最早可以追溯到1995年.近20年来,Tomcat始终是使用最广泛的Web服务器,由于其使用Java语言开发,所以广为Java程序员所熟悉.很多人早期的J2EE项目,由程 ...
- tomcat原理解析(一):一个简单的实现
tomcat原理解析(一):一个简单的实现 https://blog.csdn.net/qiangcai/article/details/60583330 2017年03月07日 09:54:27 逆 ...
- Servlet过滤器介绍之原理分析
zhangjunhd 的BLOG 写留言去学院学习发消息 加友情链接进家园 加好友 博客统计信息 51CTO博客之星 用户名:zhangjunhd 文章数:110 评论数:858 访问量:19 ...
随机推荐
- # 20155327 2016-2017-4 《Java程序设计》第七周学习总结
20155327 2016-2017-4 <Java程序设计>第七周学习总结 教材学习内容总结 了解Lambda语法 包含三个部分 一个括号内用逗号分隔的形式参数,参数是函数式接口里面方法 ...
- css3动画与js动画的区别
css与 js动画 优缺点比较 我们经常面临一个抉择:到底使用JavaScript还是CSS动画,下面做一下对比 JS动画 缺点:(1)JavaScript在浏览器的主线程中运行,而主线程中还有其 ...
- oracle 11g 建库 建表 增 删 改 查 约束
一.建库 1.(点击左上角带绿色+号的按钮) 2.(进入这个界面,passowrd为密码.填写完后点击下面一排的Test按钮进行测试,无异常就点击Connect) 二.建表 1-1. create t ...
- 【vue】Vue调试神器vue-devtools安装
转载:https://segmentfault.com/a/1190000009682735 前言 vue-devtools是一款基于chrome游览器的插件,用于调试vue应用,这可以极大地提高我们 ...
- SQLite数据库学习小结——native层实现
1. SQlite概述 SQLite是一款轻量.快速.跨平台的嵌入式数据库,是遵守ACID(注:ACID指数据库事务正确执行的四个基本要素的缩写.包含:原子性(Atomicity).一致性(Consi ...
- java开发中的常见类和对象-建议阅读时间3分钟
1.Dao 数据访问对象 此对象用于访问数据库.实现类一般用于用于操作数据库! 一般操作修改,添加,删除数据库操作的步骤很相似,就写了一个公共类DAO类 ,修改,添加,删除数据库操作时 直接调用公共类 ...
- js 验证代码部分的简单实现
接上面的文章. 我们已经简单的设计了关于如何进行处理了,但是如何进行校验呢,代码也是比较简单的因为我们使用的是asp.net 简单并且功能强大. 我们同样使用的是HttpResponse,简单的模拟代 ...
- /etc/inittab 学习
1.文件内容 2.内容讲解 http://www.2cto.com/os/201108/98426.html init的进程号是1(ps -aux | less),从这一点就能看出,init进程是系统 ...
- MySQL · 特性分析 · 优化器 MRR & BKA【转】
MySQL · 特性分析 · 优化器 MRR & BKA 上一篇文章咱们对 ICP 进行了一次全面的分析,本篇文章小编继续为大家分析优化器的另外两个选项: MRR & batched_ ...
- S5PV210 移植无线wifi网卡 MT7601
一.准备工作 1.MT7601驱动下载 点击下载 2.插入usb WiFi 启动开发板linux,lsusb查看usb驱动 Bus 001 Device 003: ID 148f:7601看到的是该驱 ...