1. 程式人生 > 其它 >深入刨析tomcat 之---第1篇,解決第1,2章bug 頁面不顯示內容Hello. Roses are red.

深入刨析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\r\n" + "Content-Type: text/html\r\n" + "Content-Length: 23\r\n" + "\r\n" + "<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_study\designbook\webroot>javac  -encoding UTF-8 -classpath .;D:\wksp_study\designbook\webroot\lib/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.這是我第三次敲這個案例才醒悟了,沒那麼簡單呢,即使是濤哥這麼牛逼的人~~~