我是靠谱客的博主 甜蜜奇迹,这篇文章主要介绍Tomcat初认识Tomcat 初认识,现在分享给大家,希望可以做个参考。

初步认识Tomcat

  • Tomcat 初认识
    • HTTP协议
      • 请求部分
      • 响应部分
    • Socket
      • 请求端
      • 响应端
    • tomcat版本1,获取静态资源
      • 准备工作
      • 原理实现
      • 代码实现
    • tomcat版本2,获取动态资源
      • 准备工作
      • 原理实现
      • 代码实现
    • 总结

Tomcat 初认识

一直在用它,从来没有真正的过理解过它。
决定学习Tomcat,这是看了B站的一个编写Tomcat的视频,当然只是很简单的讲到Socket这一步就结束了。
现在将笔记记录在这里,在学习Tomcat的过程中,告诉自己一句话:

慢慢来

HTTP协议

截至到现在,我觉得HTTP协议超文本传输协议真的对我来说是一种折磨,不过看到视频里的讲解,我觉得对哦~ 。

在这里插入图片描述
就简单来理解,它就是两方传输信息的约定俗成的规则。

HTML协议是一种请求-响应模型

客户端 服务端 你好!请给我demo.html 好的,请接受demo.html 客户端 服务端

服务器端接收到来自客户端的请求,然后将请求的资源返回给客户端。

请求部分

名称例子说明
请求行'GET /demo.html HTTP/1.1'GET:是请求方法;'demo.html’是请求内容;HTTP/1.1 是请求协议以及协议版本
请求头"Host:本次请求的主机路径;User-agent:本次请求的客户端的平台以及浏览器信息;Accept;Accept-Language:Accept-Encoding"
请求体确定用户表单数据向服务器传输的格式Get:没有请求体;Post:由请求体

Accpet:客户端可以接受到的类型的信息;Accept-Language:告诉服务器客户都安可以识别的语言类型;Accept-Encoding:告诉服务器浏览器可以接收到哪些类型的压缩格式数据

响应部分

名称例子说明
响应行' HTTP/1.1 200 OK'HTTP/1.1 是请求协议以及协议版本 状态码 状态描述
响应头"服务端告诉客户端服务端的信息"响应头和响应体之间有一个空行
响应体服务端相应给客户端的内容,可能是html、js、css等

状态码

  1. 200 表示成功
  2. 404 服务器找不到请求的资源
  3. 500 服务器内部的错误

响应头
Date:响应的时间;content-type:响应的内容类型;content-encoding :相应内容采取的压缩格式;content-length:响应内容的长度

Socket

请求端

我们访问 链接,所以只需要实现请求端。

在这里插入图片描述

  Socket socket = null;
  InputStream is = null;  //输入流
  OutputStream ops = null; //输出流
  try {
      //1.建立一个和服务端对应的Socket对象,知名链接服务器端的域名和端口号
      socket = new Socket("www.itcast.cn",80);
      //2.通过socket获取到指定服务端的输出流对象
      ops = socket.getOutputStream();
      //3.获取到输入流
      is = socket.getInputStream();
      //4.将HTTP协议的请求部分发送到服务器
      ops.write("GET /subject/about/index.html HTTP/1.1n".getBytes());  //操作系统默认的编码格式的字符数组
      ops.write("HOST:www.itcast.cnn".getBytes());
      ops.write("n".getBytes());
      //5.接受来自服务器的数据并输出
      int i = is.read();
      while(i!=-1){
          System.out.print((char)i);
          i = is.read();
      }
  } catch (Exception e) {
      e.printStackTrace();
  }finally {
      try {
          //6.释放资源
          if(is!=null){
              is.close();
              is=null;
          }
          if(ops!=null){
              ops.close();
              ops = null;
          }
          if(socket!=null){
              socket.close();
              socket=null;
          }
      } catch (Exception e) {
          e.printStackTrace();
      }
  }

注意:在响应头、响应体、响应行之间都是需要加上换行符n的

响应端

我们直接在浏览器访问hppt://localhost:8080 ,只需要在服务器端实现代码就可以
在这里插入图片描述

   ServerSocket serverSocket = null;
   Socket socket = null;
   OutputStream ops = null;
   try {
       //1.创建ServerSocket对象,监听本机的8080端口
       serverSocket = new ServerSocket(8080);
       while(true){
           //2.等待来自客户端的请求 获取和和客户端对应的Socket对象
           socket = serverSocket.accept();
           //3.通过获取的Socket对象获取到输出流对象
           ops = socket.getOutputStream();
           //4.通过获取的输出流对象将HTML协议的相应部分发送到客户端
           ops.write("HTTP/1.1 200 OKn".getBytes());
           ops.write("Content-Type:text/html;charset=utf-8n".getBytes());
           ops.write("Server:Apache-Coyote/1.1n".getBytes());
           ops.write("nn".getBytes());
           //将响应体放在一个对象里
           StringBuilder sb = new StringBuilder();
           sb.append("<html>");
           sb.append("<head><title>我是标题</title></head>");
           sb.append("<body>");
           sb.append("<h1>i am header 1</h1>");
           sb.append("</body></html>");
           ops.write(sb.toString().getBytes());
           ops.flush();  //这一块实际上没有用,父类的实际上是空的,没有做任何操作
       }
   }catch (Exception e){
       e.printStackTrace();
   }finally {
       try {
           //6.释放资源
           if(ops!=null){
               ops.close();
               ops = null;
           }
           if(socket!=null){
               socket.close();
               socket=null;
           }
       } catch (Exception e) {
           e.printStackTrace();
       }
   }

tomcat版本1,获取静态资源

准备工作

工程下新建WebContent,然后在下面创建demo1.html 和demo2.html文件。
在这里插入图片描述

原理实现

在这里插入图片描述

代码实现

定义变量

//定义一个变量,存放服务端WebContent目录的绝对路径
public static String WEB_ROOT = System.getProperty("user.dir")+"\"+"WebContent";  //   ”“是转义字符    user.dir 工程的根目录
//定义一个变量,用于存放本次请求的静态变量
private static String url="";

主函数

//创建serverSocket对象,监听8080端口
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
OutputStream ops = null;
try{
    serverSocket = new ServerSocket(8080);
    while(true){
        //获取到客户端对应的socket
        socket = serverSocket.accept();
        //获取到输入流对象
        is = socket.getInputStream();
        //获取到输出流对象
        ops = socket.getOutputStream();

        //读取HTTP协议请求的数据  截取客户端访问的资源名称 并赋值给url
        parse(is);

        //发送静态资源
        sendStaticResource(ops);
    }
}catch (Exception e){
    e.printStackTrace();
}finally {
    //6.释放资源
    if(ops!=null){
        ops.close();
        ops = null;
    }
    if(socket!=null){
        socket.close();
        socket=null;
    }
    if(is!=null){
        is.close();
        is = null;
    }
}

解析输入流,获取请求内容并赋值给url

//读取HTTP协议请求的数据  截取客户端访问的资源名称 并赋值给url
private static void parse(InputStream is)throws  IOException {
    //定义一个变量,存放HTTp协议的请求部分
    StringBuilder sb = new StringBuilder(2048);
    //定义一个数组,存放HTTP协议的请求部分
    byte[] buffer = new byte[2048];
    //定义一个变量i,代表存取数据到数组中,数组的大小
    int i=-1;
    //读取客户端发送过来的数据,将数据读取到buffer中,i表示数据量的大小
    i = is.read(buffer);
    //遍历字节数组,将数组中的数据追加到变量connect中
    for(int j=0;j<i;j++){
        sb.append((char)buffer[j]);
    }
    //打印HTTP协议请求部分数据
    System.out.println(sb.toString());
    //截取客户端请求的资源路径demo1.html 赋值给url
    parserUrl(sb.toString());
}

截取客户端请求的资源路径demo1.html 赋值给url

//截取客户端请求的资源路径demo1.html 赋值给url
private static void parserUrl(String content) {
     //定义两个变量  ,保存两个空格的位置
     int index1,index2;
     //获取到第一个空格的位置
     index1 = content.indexOf(" ");
     if(index1!=-1){
         index2 = content.indexOf(" ",index1+1);
         if(index2>index1){
             url = content.substring(index1+2,index2);
         }
     }
     System.out.println(url);
 }

发送静态资源

//发送静态资源
private static void sendStaticResource(OutputStream ops) throws  Exception{
    //定义一个字节数组,用于存放本次请求的静态资源demo1.html的内容
    byte[] bytes = new byte[2048];
    //定义一个文件输入流,用户获取本次请求的资源的内容
    FileInputStream fis = null;
    try{
        //创建文件对象File ,代表本次请求的资源demo1.html;
        File file = new File(WEB_ROOT,url);
        //如果文件存在
        if(file.exists()){
            //向客户端输出HTTP协议的响应行  响应头
            ops.write("HTTP/1.1 200 OKn".getBytes());
            ops.write("Server:apache-Coyote/1.1n".getBytes());
            ops.write("Content-type:text/html;charset=utf-8n".getBytes());
            ops.write("n".getBytes());
            //获取到文件输入流对象
            fis = new FileInputStream(file);  //输入流输出流是相对应内存再来说,如果把一个文件的内容
            //写道内存中,则是输入流;如果把一个程序写道文件里,则是相对应的输出流
            int ch = fis.read(bytes);
            while(ch!=-1){
                //将读取到的数组中的内容通过输出流发动到客户端
                ops.write(bytes,0,ch);
                ch = fis.read(bytes);
            }
        }else{
            //如果文件没有
            //向客户按发送不存在
            ops.write("HTTP/1.1 404 not foundn".getBytes());
            ops.write("Server:apache-Coyote/1.1n".getBytes());
            ops.write("Content-type:text/html;charset=utf-8n".getBytes());
            ops.write("n".getBytes());
            ops.write("file not foundn".getBytes());
        }
    }catch (Exception e){
        e.printStackTrace();
    }finally {
        if(fis!=null){
            fis.close();
            fis=null;
        }
    }
}

tomcat版本2,获取动态资源

准备工作

  1. 在webContent中创建一个conf,properties配置文件
  2. 创建一个接口Servlet
  3. 创建两个类AAServlet和BBServlet
    在这里插入图片描述

原理实现

在这里插入图片描述
在这里插入图片描述

代码实现

servlet接口

//所有的服务端 java小程序 要实现的接口
public interface Servlet {
    public void init();
    public void service(InputStream is, OutputStream ops)throws IOException;
    public void destroy();
}

AAServlet类

@Override
public void init() {
    System.out.println("AAServlet init");
}

@Override
public void service(InputStream is, OutputStream ops) throws IOException {
    System.out.println("AAServlet service");
    ops.write("i am from AASERVLET".getBytes());
}

@Override
public void destroy() {
    System.out.println("AAServlet destryoy");
}

conf.properties配置文件

aa = cn.itcast.mytomcat2.AAServlet
bb = cn.itcast.mytomcat2.BBServlet

服务端代码-变量定义

 //服务器端
public static String WEB_ROOT = System.getProperty("user.dir")+"\"+"WebContent";
//变量 对应的key value   获取的请求的内容 所对应的java小程序的路径
public static HashMap<String,String> map = new HashMap<>();
//变量  客户端请求的内容
public static String url="";

服务端代码-静态函数:处理一些在服务器启动的时候就需要获取的配置信息

static{
     //要在服务器启动之前将配置信息加载到map中
     //获取对应的配置文件的内容
     Properties properties = new Properties();
     //加载输入流
     try {
         properties.load(new FileInputStream(new File(WEB_ROOT,"conf.properties")));
         //输出所有的配置信息
         Enumeration en = properties.propertyNames();
         while(en.hasMoreElements()){
             String key = (String)en.nextElement();
             String value = (String)properties.getProperty(key);
             map.put(key,value);
         }

         //二种方法
//            Set set = properties.keySet();
//            Iterator<String> iterator = set.iterator();
//            while (iterator.hasNext()){
//                String key = iterator.next();
//                String value= properties.getProperty(key);
//            }
     } catch (IOException e) {
         e.printStackTrace();
     }

 }

服务端代码-主函数

ServerSocket serverSocket = null;
Socket socket = null;
InputStream is=null;
OutputStream ops = null;
try {
    //创建服务器端监听接口对象
    serverSocket = new ServerSocket(8080);
    //获取到服务器端对应的Socket
    socket = serverSocket.accept();
    //获取输入流
    is = socket.getInputStream();
    //获取输出流
    ops = socket.getOutputStream();
    //读取HTTP协议请求的数据  截取客户端访问的资源名称 并赋值给url
    //判断本次请求的是html静态页面还是动态资源
    parse(is);
    if(null!=url){
        if(url.indexOf(".")!=-1){
            sendStaticResource(ops);
        }else{
            //向客户发送HTTP协议响应头、响应行  发送动态资源
            sendDynamicResource(is,ops);
        }
    }
}catch (Exception e){
    e.printStackTrace();
}finally {

}

服务端代码-解析请求内容,并进行截取获得url 参照上一小节代码
服务端代码-发送动态资源

//给客户端发送动态资源
private static void sendDynamicResource(InputStream is,OutputStream ops) throws Exception {
     try {
         //获取类的路径  并通过反射的机制来运行
         if(map.containsKey(url)){
             Class<?> servletClass = Class.forName(map.get(url));
             //向客户端输出HTTP协议的响应行  响应头
             ops.write("HTTP/1.1 200 OKn".getBytes());
             ops.write("Server:apache-Coyote/1.1n".getBytes());
             ops.write("Content-type:text/html;charset=utf-8n".getBytes());
             ops.write("n".getBytes());
             Method method = servletClass.getDeclaredMethod("init");
             method.invoke(servletClass.newInstance());
             //运行service
             method = servletClass.getDeclaredMethod("service",InputStream.class,OutputStream.class);
             method.invoke(servletClass.newInstance(),is,ops);
             //运行detroy
             method = servletClass.getDeclaredMethod("destroy");
             method.invoke(servletClass.newInstance());

             //第二种映射方法
//                Class class_ = Class.forName(map.get(url));
//                Servlet servlet = (Servlet)class_.newInstance();
//                servlet.init();
//                servlet.service(is, ops);
//                servlet.destroy();


         }else{
             ops.write("HTTP/1.1 404 not foundn".getBytes());
             ops.write("Server:apache-Coyote/1.1n".getBytes());
             ops.write("Content-type:text/html;charset=utf-8n".getBytes());
             ops.write("n".getBytes());
             ops.write("file not foundn".getBytes());
         }
     }catch (Exception e){
         e.printStackTrace();
     }finally {

     }
 }

注意:反射和文件内容读取都是比较基础而且比较重要的

总结

客户端 服务器 ServerSocket Socket InputSteam OutputSteam 1.请求申请localhost:8080/aa 2.监听到8080端口的请求 创建Socket对象,获 取到InputStrea m和OutputStream 3.创建Socket对象 4.获取到InputStream 4.获取到OutputStream 5.通过write将信息返回给客户端 6.服务器响应客户端的请求 解析请求信息,获取 到请求内容,截取它 ,获得Url,判断 Url类型,进行动 态或者静态读取资源 客户端 服务器 ServerSocket Socket InputSteam OutputSteam

最后

以上就是甜蜜奇迹最近收集整理的关于Tomcat初认识Tomcat 初认识的全部内容,更多相关Tomcat初认识Tomcat内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(46)

评论列表共有 0 条评论

立即
投稿
返回
顶部