深入刨析tomcat 之---第1篇,解决第1,2章bug 页面不显示内容Hello. Roses are red.

writedby 张艳涛,

第一个问题是不显示index.html网页

19年才开始学java的第二个月,就开始第一遍看这本书,我估计当初,做第一章的一个案例,自己写代码,和验证就得一天吧,当初就发现了这个问题,chrome浏览器不显示localhost:8080/index.html页面,还特意在培训班的课堂上问了下,老师说是web服务器没有写http头,这个老师一眼就看出来了,还行;但通过ie浏览器就没这个问题,真是服气了~~~

先贴下解决这个问题的代码

package com.zyt.tomcat.ex01;

import java.io.*;

public class Response {
    private static final int  BUFFER_SIZE=1024;
    Request request;
    OutputStream output;

    public Response(OutputStream output) {
        this.output = output;
    }

    public void setRequest(Request request) {
        this.request = request;
    }
    public void sendStaticResource() throws IOException{
        byte[] bytes = new byte[BUFFER_SIZE];
        FileInputStream fis=null;
        File file = new File(HttpServer.WEB_ROOT, request.getUri());
        PrintWriter out=null;
        try {
            if (file.exists()) {
                out = new PrintWriter(output);
                fis = new FileInputStream(file);
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                int ch = fis.read(bytes, 0, BUFFER_SIZE);
                while (ch != -1) {
                    baos.write(bytes,0,ch);
                    ch = fis.read(bytes, 0, BUFFER_SIZE);
                }
                byte[] array = baos.toByteArray();
                out.println("HTTP/1.1 200 OK");
                out.println("Server: Molly");
                out.println("Content-Type: text/html; charset=UTF-8");
                out.println("Content-Length: "+array.length);
                out.println("");
                out.flush();
                output.write(array,0,array.length);


            }else {
                // file not found
                String errorMessage = "HTTP/1.1 404 File Not Found
" +
                        "Content-Type: text/html
" +
                        "Content-Length: 23
" +
                        "
" +
                        "<h1>File Not Found</h1>";
                output.write(errorMessage.getBytes());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                fis.close();
            }
        }
    }
}

你别看这小段内容,其中有一个问题就是,你要写Content-Length的值,如果你先写http头,在读头文件,那你就没法知道文件的大小的值了,这里采取了一个第三变量array来保存文件的内容,这样子就可以先写http头内容,完成之后,接着写文件内容;

这全网独一份,不过我也是在java并发编程的艺术这边书上参考了4.4章,

再顺便提另外一个问题,这个index.html的代码如下

<html>
<head>
<title>Welcome to BrainySoftware</title>
</head>
<body>
<img src="./images/logo.gif">
<br>
Welcome to BrainySoftware.
</body>
</html>

这个图片加载的标签img src="",这个是加载静资源,要说的是静态资源是通过浏览器先接受index.html文件的内容,解析之后再进行了一次http请求得到了jpg图片

并不是一次返回全部内容,看证据,

浏览器端

服务器端

第二个问题是: 浏览器输入 http://localhost:8080/servlet/PrimitiveServlet ,不显示内容

问题描述,这个问题是,第二章的第一案例,加载servlet类,实现动态加载,这个问题,大概在2020年的4月份自己想解决,想了好几天都没想到方法.

这个问题也是一样,他的PrimitiveServlet代码主要是如下,他也没有写http头

import javax.servlet.*;
import java.io.IOException;
import java.io.PrintWriter;

public class PrimitiveServlet implements Servlet {

  public void init(ServletConfig config) throws ServletException {
    System.out.println("init");
  }

  public void service(ServletRequest request, ServletResponse response)
    throws ServletException, IOException {
    System.out.println("from service");
    PrintWriter out = response.getWriter();
    out.println("Hello. Roses are red.");
    out.print("Violets are blue.");
  }

  public void destroy() {
    System.out.println("destroy");
  }

  public String getServletInfo() {
    return null;
  }
  public ServletConfig getServletConfig() {
    return null;
  }

}

去年4月份想的方法是,在

            servlet = ((Servlet) myClass.newInstance());
            servlet.service(((ServletRequest) request), ((ServletResponse) response));

service方法之前,给out写一个http 头文件,但是没有解决 out.println("Content-Length: " 是多少); 文件长度的值的问题;

自己就一直想一直想,没想出来,今天下午,同意遇到这个问题了,现在可能对java 的知识理解深入了还是怎么开窍了,

发现自己之前提的问题就是一个错误问题,我们在执行servlet.service()方法的时候,service的功能是什么???之前我理解的是servlet

是给浏览器返回网页,这是错误的,在servlet中,你可以只是sout("hello")回头打印一句话,你不给浏览器回复,那么浏览器只是没得到回复,(网页空白)

那么我的servlet功能实现了吗?实现了控制台已经打印了hello,那么如果你要给浏览器回复一个网页,那么你要在service()方法里面写http头文件和httpbody

不应该servletProcessor1.java这个里,在反射调用servket,service 之前写http头文件

更改后的文件为

import javax.servlet.*;
import java.io.IOException;
import java.io.PrintWriter;

public class PrimitiveServlet implements Servlet {

  public void init(ServletConfig config) throws ServletException {
    System.out.println("init");
  }

  public void service(ServletRequest request, ServletResponse response)
    throws ServletException, IOException {
    System.out.println("from service");
    PrintWriter out = response.getWriter();
    out.println("HTTP/1.1 200 OK");
    out.println("Server: Molly");
    out.println("Content-Type: text/html; charset=UTF-8");

    out.println("");
    out.flush();
    out.println("Hello. Roses are red.");
    out.print("Violets are blue.");
  }

  public void destroy() {
    System.out.println("destroy");
  }

  public String getServletInfo() {
    return null;
  }
  public ServletConfig getServletConfig() {
    return null;
  }

}

增加文件如标记所示,这个又遇到一个问题,你得javac编译他,但不能用idea 因为这个类没有包名

所以你要使用javac 带依赖编译,如何编译呢?将源码包中的lib文件方法webroot文件夹下面,运行如下指令

D:wksp_studydesignbookwebroot>javac  -encoding UTF-8 -classpath .;D:wksp_studydesignbookwebrootlib/servlet.jar PrimitiveServlet.java

如果你直接java 类名,会报错,提示

PrimitiveServlet.java:5: 错误: 找不到符号
public class PrimitiveServlet implements Servlet {
^
符号: 类 Servlet
PrimitiveServlet.java:7: 错误: 找不到符号
public void init(ServletConfig config) throws ServletException {
^
符号: 类 ServletConfig
位置: 类 PrimitiveServlet
PrimitiveServlet.java:7: 错误: 找不到符号
public void init(ServletConfig config) throws ServletException {
^
符号: 类 ServletException
位置: 类 PrimitiveServlet
PrimitiveServlet.java:11: 错误: 找不到符号
public void service(ServletRequest request, ServletResponse response)
^
符号: 类 ServletRequest
位置: 类 PrimitiveServlet
PrimitiveServlet.java:11: 错误: 找不到符号
public void service(ServletRequest request, ServletResponse response)

=====================================================

通过如上一番操作,你就能看到如下界面了

结束语:

1,之前打印一章的案例,得慢慢蹭蹭,现在熟练运用了idea的.var .if .nn .try .while 一点代码简直起飞呀,写代码行云流水,真是一种享受;

2,知识是需要循序渐进的,相关知识的积累对当前表面的知识是有很大影响的,比如我问你个问题,jvm的gc是处理垃圾对象,那么垃圾对象是怎么产生的呢? 答案是:  A.func1 调用 B.func2 在调用C.func3 那么程序的栈帧中同时有三个方法栈,每个方法中都有自己的局部变量,每个局部变量对应一个jvm对象,如果你在func3中一直while 那么,这个时候jvm没有垃圾,事实是你func3调用玩了,你返回了,摧毁了func3的栈,局部变量给摧毁了,那么  局部变量 obj= new Obejct();  obj 没了, new Object()还在,那么这个new Object()就是jvm的垃圾,同样,你从func1中返回,那么fucn1,2,3中的局部变量都是垃圾了

3.这是我第三次敲这个案例才醒悟了,没那么简单呢,即使是涛哥这么牛逼的人~~~

原文地址:https://www.cnblogs.com/zytcomeon/p/14950708.html