深入刨析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)
=====================================================
通過如上一番操作,你就能看到如下介面了