关于最火爆的服务器Tomcat你真的了解吗?
作为Apache 软件基金会的Jakarta 项目中的一个核心项目,Tomcat因技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。接下来我就会为大家分享一下我对Tomcat的理解,希望可以帮到大家。
MyTomcat 接收请求(Request) 想接收浏览发起的请求,需要做几手准备, 1:监听端口(8080), 2:接收浏览器连接(socket连接) 3:解析HTTP请求数据。下面是代码模拟:
第一第二步: 使用httpServer模拟tomcat调度中心
/**
 * 模拟tomcat的核心类
 */public class HttpServer {
    //tomcat项目绝对路径, 所有web项目都丢在webapps目录下
    public static final String WEB_ROOT =
            System.getProperty("user.dir") + File.separator  + "webapps";
    // 模拟tomcat关闭命令
    private static final String SHUTDOWN_CMD = "/SHUTDOWN";
    private boolean shutdown = false;
    //持续监听端口
    @SuppressWarnings("resource")
    public void accept() {
        ServerSocket serverSocket = null;
        try {
            // 启动socket服务, 监听8080端口,
            serverSocket =  new ServerSocket(8080, 1, InetAddress.getByName("127.0.0.1"));
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("启动myTomcat服务器失败:" + e.getMessage(), e);
        }
        // 没接收到关闭命令前一直监听
        while (!shutdown) {
            Socket socket = null;
            InputStream in = null;
            OutputStream out = null;
            try {
                // 接收请求
                socket = serverSocket.accept();
                in = socket.getInputStream();
                out = socket.getOutputStream();
                // 将浏览器发送的请求信息封装成请求对象
                Request request = new Request(in);
                request.parseRequest();
                // 将相应信息封装相应对象
                //此处简单响应一个静态资源文件
                Response response = new Response(out);
                //模拟页面跳转
                response.sendRedircet(request.getUri());
                socket.close();
                //如果是使用关闭命令,停止监听退出
                shutdown = request.getUri().equals(SHUTDOWN_CMD);
            } catch (Exception e) {
                e.printStackTrace();
                continue;
            }
        }
    }
    public static void main(String[] args) {
        new HttpServer().accept();
    }
}
第三步,使用HttpReqeust封装请求相关信息
/**
 * 请求信息封装对象
 */public class Request {
    // 浏览器socket连接的读流
    private InputStream in;
    //请求行信息信息中的uri
    private String uri;
    public Request(InputStream in) {
        this.in = in;
    }
    // 解析浏览器发起的请求
    public void parseRequest() {
        // 暂时忽略文件上传的请求,假设都字符型请求
        byte[] buff = new byte[2048];
        StringBuffer sb = new StringBuffer(2048);
        int len = 0;
        //请求内容
        try {
            len = in.read(buff);
            sb.append(new String(buff, 0, len));
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.print(sb.toString());
        //解析请求行中uri信息
        uri = this.parseUri(sb.toString());
    }
    /**tomcat接收浏览器发起的请求是居于http协议的,请求内容格式:*/
    /**请求行:请求方式   请求uri 协议版本*/
    //GET /index HTTP/1.1
    /**请求头:以key-value形式存在*/
    //Host: localhost:8080
    //Connection: keep-alive
    //Upgrade-Insecure-Requests: 1
    //User-Agent: Mozilla/5.0 .........
    //Accept: text/html,application/xhtml+xml......
    //Accept-Encoding: gzip, deflate, br
    //Accept-Language: zh-CN,zh;q=0.9
    //Cookie: .....
    /**请求体: 请求头回车格一行就是请求体,get方式请求体为空*/
    public String parseUri(String httpContent) {
        //传入的内容解析第一行的请求行即可:
        //请求行格式:  请求方式   请求uri 协议版本     3个内容以空格隔开
        int beginIndex = httpContent.indexOf(" ");
        int endIndex;
        if(beginIndex > -1) {
            endIndex = httpContent.indexOf(" ", beginIndex + 1);
            if(endIndex > beginIndex) {
                return httpContent.substring(beginIndex, endIndex).trim();
            }
        }
        return null;
    }
    public String getUri() {
        return uri;
    }
}
假设,浏览器发起请求:http://localhost:8080/hello/index.html HttpServer中socket通过输入流获取到的数据是:
GET /hello/index.html HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: Hm_lvt_aa5c701f4f646931bf78b6f40b234ef5=1516445118,1516604544,1518416964,1518497222; JSESSIONID=79367FD9A55B9B442C4ED112D10FDAC5
HttpServer 将上述的数据交于HttpRequest对象处理,该对象调用parseRequest解析,获取请求行中的uri 数据, 分析该数据, 得到上下文路径,项目名,资源名。统称资源路径。
上面数据得到: hello 项目下, index.html 资源(没有上下文路径)
响应请求
当从请求信息中获取uri后,进而获取到hello 项目, index.html资源, 响应请求就可以简单认为根据资源路径查找资源,如果找到,使用socket output流直接输出资源数据即可,如果找不到,输出404信息。
 * 处理响应请求对象
public class Response {
    // 浏览器socket连接的写流
    private OutputStream out;
    public Response(OutputStream out) {
        this.out = out;
    }
    public OutputStream getOutputStream() {
        return out;
    }
    //跳转
    public void sendRedircet(String uri) {
        File webPage = new File(HttpServer.WEB_ROOT, uri);
        FileInputStream fis = null;
        StringBuffer sb = new StringBuffer();
        try {
            //找得到页面是
            if(webPage.exists()&& webPage.isFile()) {
                String respHeader = "HTTP/1.1 200 OK\r\n" +
                  "Content-Type: text/html\r\n" +
                  "Content-Length: #{count}\r\n" +
                  "\r\n";
                fis = new FileInputStream(webPage);
                byte[] buff = new byte[2048];
                int len = 0;
                while( (len = fis.read(buff))!= -1) {
                    sb.append(new String(buff, 0, len));
                }
                respHeader=respHeader.replace("#{count}", sb.length()+"");
                System.out.println(respHeader + sb);
                out.write((respHeader + sb).getBytes());
            }else {
                 //页面找不到时
                String errorMessage = "HTTP/1.1 404 File Not Found\r\n" +
                  "Content-Type: text/html\r\n" +
                  "Content-Length: 23\r\n" +
                  "\r\n" +
                  "<h1>File Not Found</h1>";
                out.write(errorMessage.getBytes());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
此处注意, 响应请求数据也必须遵循http协议。 当然,这些内容只是Tomcat中的一部分,想要继续探索关于Tomcat的内容,大家大可继续自行研究或者关注我们,我们也会持续发布相关教程,共同进步。
关于最火爆的服务器Tomcat你真的了解吗?的更多相关文章
- Servlet学习之web服务器Tomcat 详解
		Web服务器是什么 Web服务器是指驻留于因特网上某种类型计算机的程序.当Web浏览器(客户端)连到服务器上并请求文件时,服务器将处理该请求并将文件发送到该浏览器上,附带的信息会告诉浏览器如何查看该文 ... 
- java web服务器tomcat介绍【转载】
		机器矩阵2016-08-10 22:14 java程序员亲切地称他为tom猫,看到这只猫可以说明1 服务器部署成功了 ,2 网络是联通的. 到底这只猫是什么来头呢? tomcat是Apache基金会下 ... 
- Android服务器——TomCat服务器的搭建
		Android服务器--TomCat服务器的搭建 作为一个开发人员,当然是需要自己调试一些程序的,这个时候本地的服务器就十分方便了,一般都会使用TomCat或者IIS服务器,IIS就比较简单了,其实t ... 
- Linux服务器tomcat无法通过ip加端口访问
		Linux服务器tomcat无法通过ip加端口访问 防火墙开放端口 # Firewall configuration written by system-config-firewall# Manual ... 
- Linux服务器tomcat启动很慢
		Linux服务器tomcat启动很慢 步骤: 一:找到 java 位置 whereis java 输出内容(部分):/usr/lib/java ...... 二:进入到 lib 目录 cd /usr ... 
- Spring Boot 揭秘与实战(五) 服务器篇 - 内嵌的服务器 Tomcat剖析
		文章目录 1. 内嵌的 Tomcat,一个Jar包运行 2. 如何定制内嵌 Tomcat3. War 包部署的使用细节 2.1. 设置内嵌Tomcat的端口 2.2. 设置内嵌Tomcat的最大线程数 ... 
- 云服务器+tomcat+mysql+web项目搭建部署
		云服务器+tomcat+mysql+web项目搭建部署 1.老样子,开头墨迹两句. 作为我的第二篇文章,有很多感慨,第一篇人气好低啊,有点小丧气,不过相信我还是经验少,分享的都是浅显的,所以大家可能不 ... 
- 【Tomcat】安装Tomcat服务器&Tomcat的目录结构
		创建时间:6.14 一.安装Tomcat服务器 Tomcat下载ver8的,现在用的多 下载并解压 配置环境变量:(切记!!不然startup那步会闪退) 1.新建系统环境变量: (1)进入根目录,复 ... 
- aarch64环境下,搭建并配置服务器tomcat:
		aarch64环境下,搭建并配置服务器tomcat: 环境说明及下载相关文件: 1. ARM环境:aarch64开发板 2.JDK安装包: jdk-8u231-linux-arm64-vfp-hflt ... 
随机推荐
- 前端性能----页面渲染(DOM)
			CSS会阻塞渲染树的构建,不阻塞DOM构建,但是在CSSOM构建完成之前,页面不会开始渲染(一片空白),CSSOM构建完成后,页面将会显示出内容. DOM(Document Object Model) ... 
- 【游记】CSP2019 垫底记
			考试时候的我: Day 1 做完 \(T1\) 和 \(T2\),还有 \(2.5 h\),我想阿克 \(Day1\).(\(T3\):不,你不想) 不过一会就想出来给每个点 dfs 贪心选一个点,然 ... 
- Spring框架的JDBC模板技术和事物
			Spring框架的JDBC模板技术 技术分析之Spring框架的JDBC模板技术概述 1. Spring框架中提供了很多持久层的模板类来简化编程,使用模板类编写程序会变的简单 ... 
- invoke和begininvoke 区别
			一直对invoke和begininvoke的使用和概念比较混乱,这两天看了些资料,对这两个的用法和原理有了些新的认识和理解. 首先说下,invoke和begininvoke的使用有两种情况: 1. c ... 
- learning java transient 自定义序例化
			public class Person implements java.io.Serializable { private String name; private transient int age ... 
- web 介绍
			Web介绍: w3c:万维网联盟组织,用来制定web标准的机构(组织) web标准:制作网页遵循的规范 web准备规范的分类:结构标准.表现标准.行为标准. 结构:html.表示:css.行为:Jav ... 
- chef test-kitchen Could not load the 'vagrant' driver from the load path 问题解决
			今天使用chef 的kitchen,运行kitchen list 发现了如下错误: >>>>>> ------Exception------- >>&g ... 
- 使用merge-graphql-schemas 进行graphql schema 以及resovler 合并
			merge-graphql-schemas 是一个方便的工具,可以进行schema 以及resovler 的合并处理 一个schema 合并参考demo schema 定义 // ./graphql/ ... 
- CSS块元素
			一.典型代表: Div h1-h6 p ul li 二.特点: 独占一行 可以设置宽高 嵌套(包含)下,子块元素宽度(没有定义情况下)和父块元素宽度默认一致. <style type=" ... 
- SuperHyperMarket(优先队列+重载)
			SuperHyperMarket(优先队列+重载) 具体见代码注释 /* */ #include <iostream> #include <cstring> #include ... 
