《How Tomcat Works》读书笔记(二)
《How Tomcat Works》讀書筆記(二)
這是《How Tomcat Works》第一二章的讀書筆記。第一張主要寫了一個(gè)靜態(tài)資源處理的web服務(wù)器,第二章加了對(duì)servlet的處理。
1. 概述
1.1 架構(gòu)
- HttpServer:表示Http服務(wù)器,與客戶端通信,處理Http請(qǐng)求。
- StaticResourceProcessor:對(duì)靜態(tài)資源請(qǐng)求進(jìn)行處理。
- ServletProcessor:對(duì)Servlet資源請(qǐng)求進(jìn)行處理。
- Request:表示Http請(qǐng)求,實(shí)現(xiàn)了ServletRequest接口。
- Response:表示Http響應(yīng),實(shí)現(xiàn)了ServletResponse接口。
- RequestFacade/ResponseFacade:Request/Response的門面類。
- PrimitiveServlet:表示一個(gè)Servlet類。
處理流程:
1.2 一些代碼
HttpServer處理邏輯:
ServletProcessor中通過類加載器把.class文件動(dòng)態(tài)的加載為Servlet對(duì)象:
1 public void process(Request request, Response response) { 2 String uri = request.getUri(); 3 String servletName = uri.substring(uri.lastIndexOf("/") + 1); 4 URLClassLoader loader = null; 5 try { 6 // create a URLClassLoader 7 URL[] urls = new URL[1]; 8 URLStreamHandler streamHandler = null; 9 File classPath = new File(Constants.WEB_ROOT); 10 // the forming of repository is taken from the 11 // createClassLoader method in 12 // org.apache.catalina.startup.ClassLoaderFactory 13 String repository =(new URL("file", null, 14 classPath.getCanonicalPath() + File.separator)).toString() ; 15 // the code for forming the URL is taken from 16 // the addRepository method in 17 // org.apache.catalina.loader.StandardClassLoader. 18 urls[0] = new URL(null, repository, streamHandler); 19 loader = new URLClassLoader(urls); 20 } catch (IOException e) { 21 } 22 Class myClass = null; 23 try { 24 myClass = loader.loadClass(servletName); 25 } catch (ClassNotFoundException e) { 26 } 27 Servlet servlet = null; 28 try { 29 servlet = (Servlet) myClass.newInstance(); 30 // 使用門面設(shè)計(jì)模式 31 RequestFacade rquestFacade = new RequestFacade(request); 32 ResponseFacade responseFacade = new RespondeFacade(response); 33 // 交由Servlet進(jìn)行處理 34 servlet.service(requestFacade, responseFacade); 35 } 36 }1.3 設(shè)計(jì)模式
在這里使用了門面的設(shè)計(jì)模式,目的是安全性。在StaticResourceProcessor.processor()方法中會(huì)把Request、Response對(duì)象傳給Servelt進(jìn)行處理,在后面程序猿處理Servlet請(qǐng)求時(shí)就可以把ServletRequest向下轉(zhuǎn)型為Request對(duì)象,然后使用不該在此使用的方法,如:parse()方法。所以,在這里使用了門面設(shè)計(jì)模式。
ResponseFacade類:
1 public class ResponseFacade implements ServletResponse { 2 private ServletResponse servletResponse = null; 3 4 // 通過構(gòu)造方法傳入真正的Response,然后向上轉(zhuǎn)型為ServletResponse 5 public ResponseFacade(Response response) { 6 this.servletResponse = response; 7 } 8 /** 9 * 后面都是實(shí)現(xiàn)ServlerResponse接口要實(shí)現(xiàn)的方法,就不寫完了。 10 */ 11 @Override 12 public String getCharacterEncoding() { 13 return servletResponse.getCharacterEncoding(); 14 } 15 @Override 16 public String getContentType() { 17 return servletResponse.getContentType(); 18 }2. 注意
2.1 HTTP協(xié)議
HTTP協(xié)議是應(yīng)用層協(xié)議,它基于TCP/IP協(xié)議進(jìn)行傳輸數(shù)據(jù)。在客戶端與web服務(wù)器解析數(shù)據(jù)時(shí),必須有相關(guān)的頭部數(shù)據(jù)。所以web服務(wù)器給客戶端發(fā)出響應(yīng),該響應(yīng)必須加入頭部數(shù)據(jù)。自己在寫該代碼時(shí),就忘了加頭部數(shù)據(jù),出個(gè)bug,解決了一段時(shí)間才發(fā)現(xiàn)。
PrimitiveServlet的service()方法:
我們平時(shí)使用Servlet開發(fā)時(shí),直接繼承HttpServlet,容器會(huì)自動(dòng)的加上HTTP Response相關(guān)信息。
2.2 MIME類型
HTTP Respose header中有一個(gè)ContentType字段,它要求告訴客戶端該Response正文的內(nèi)容MIME類型,我們可以通過下面的API獲得某一個(gè)文件的MIME類型。
2.2 .class文件
該系統(tǒng)使用到了URLClassLoader加載Class對(duì)象,ClassLoader把字節(jié)碼(.class文件)加載為Class對(duì)象,所以需要編譯好的.class文件。在Idea中Project中有個(gè)out目錄,其中放的就是編譯好的.class文件(只要你使用Idea運(yùn)行過的.java文件)。
3. 代碼
與原書邏輯基本一致,由于自己加入了多線程技術(shù),所以新增了Servlet容器(使用了Map),并且該容器一開始就加載所有的Servlet。
HttpServer:
1 package note1; 2 3 import java.io.IOException; 4 import java.net.ServerSocket; 5 import java.net.Socket; 6 import java.util.concurrent.ExecutorService; 7 import java.util.concurrent.Executors; 8 9 /** 10 * Created by kanyuxia on 2017/4/24. 11 * HttpServer是模擬HTTP服務(wù)器:接受HTTP請(qǐng)求,響應(yīng)靜態(tài)資源或者Servlet資源 12 */ 13 public class HttpServer { 14 /** 15 * HttpServer端口號(hào) 16 */ 17 public static final int PORT = 10086; 18 /** 19 * Http靜態(tài)文件根目錄 20 */ 21 public static final String STATIC_RESOURCE_ROOT = "E:/java/HttpServer/staticresource"; 22 /** 23 * Http中Servlet文件根目錄 24 */ 25 public static final String SERVLET_ROOT = "E:/java/HttpServer/servlet"; 26 /** 27 * 線程池 28 */ 29 private ExecutorService executorService; 30 /** 31 * 線程池大小 32 */ 33 public static final int THREAD_POOL_SIZE = 50; 34 35 HttpServer() { 36 executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE); 37 } 38 39 /** 40 * 啟動(dòng)HttpServer服務(wù)器 41 * 使用了try-with-resource: since jdk1.7 42 */ 43 public void start() { 44 // 創(chuàng)建ServerSocket 45 try (ServerSocket serverSocket = new ServerSocket(PORT)) { 46 while (true) { 47 // 客戶端連接 48 Socket socket = serverSocket.accept(); 49 // 使用線程池處理該socket 50 ServerHandle serverHandle = new ServerHandle(socket); 51 executorService.execute(serverHandle); 52 } 53 } catch (IOException e) { 54 System.out.println(e); 55 } 56 } 57 } View CodeRequest:
1 package note1; 2 3 import javax.servlet.*; 4 import java.io.*; 5 import java.util.Enumeration; 6 import java.util.Locale; 7 import java.util.Map; 8 9 /** 10 * Created by kanyuxia on 2017/4/24 11 * Request類:實(shí)現(xiàn)了ServletRequest接口,如果HTTP請(qǐng)求是Servlet,則服務(wù)器創(chuàng)建ServletRequest和ServletResponse對(duì)象, 12 * 并傳入Servlet的service()方法 13 */ 14 public class Request implements ServletRequest { 15 private final InputStream inputStream; 16 17 private String url; 18 19 public Request(InputStream inputStream) { 20 this.inputStream = inputStream; 21 } 22 23 public String getUrl() { 24 return url; 25 } 26 27 /** 28 * 解析請(qǐng)求URL 29 */ 30 public void parse() { 31 BufferedInputStream in = new BufferedInputStream(inputStream); 32 StringBuilder result = new StringBuilder(1024); 33 byte[] buffer = new byte[1024]; 34 int readNum = 0; 35 try { 36 readNum = in.read(buffer); 37 } catch (IOException e) { 38 e.printStackTrace(); 39 } 40 for (int i = 0; i < readNum; i++) { 41 result.append((char) buffer[i]); 42 } 43 // 解析URL 44 int start = result.toString().indexOf(" ") + 1; 45 int end = result.toString().indexOf(" ", start); 46 this.url = result.toString().substring(start, end); 47 } 48 49 50 @Override 51 public Object getAttribute(String name) { 52 return null; 53 } 54 55 @Override 56 public Enumeration<String> getAttributeNames() { 57 return null; 58 } 59 60 @Override 61 public String getCharacterEncoding() { 62 return null; 63 } 64 65 @Override 66 public void setCharacterEncoding(String env) throws UnsupportedEncodingException { 67 68 } 69 70 @Override 71 public int getContentLength() { 72 return 0; 73 } 74 75 @Override 76 public long getContentLengthLong() { 77 return 0; 78 } 79 80 @Override 81 public String getContentType() { 82 return null; 83 } 84 85 @Override 86 public ServletInputStream getInputStream() throws IOException { 87 return null; 88 } 89 90 @Override 91 public String getParameter(String name) { 92 return null; 93 } 94 95 @Override 96 public Enumeration<String> getParameterNames() { 97 return null; 98 } 99 100 @Override 101 public String[] getParameterValues(String name) { 102 return new String[0]; 103 } 104 105 @Override 106 public Map<String, String[]> getParameterMap() { 107 return null; 108 } 109 110 @Override 111 public String getProtocol() { 112 return null; 113 } 114 115 @Override 116 public String getScheme() { 117 return null; 118 } 119 120 @Override 121 public String getServerName() { 122 return null; 123 } 124 125 @Override 126 public int getServerPort() { 127 return 0; 128 } 129 130 @Override 131 public BufferedReader getReader() throws IOException { 132 return null; 133 } 134 135 @Override 136 public String getRemoteAddr() { 137 return null; 138 } 139 140 @Override 141 public String getRemoteHost() { 142 return null; 143 } 144 145 @Override 146 public void setAttribute(String name, Object o) { 147 148 } 149 150 @Override 151 public void removeAttribute(String name) { 152 153 } 154 155 @Override 156 public Locale getLocale() { 157 return null; 158 } 159 160 @Override 161 public Enumeration<Locale> getLocales() { 162 return null; 163 } 164 165 @Override 166 public boolean isSecure() { 167 return false; 168 } 169 170 @Override 171 public RequestDispatcher getRequestDispatcher(String path) { 172 return null; 173 } 174 175 @Override 176 public String getRealPath(String path) { 177 return null; 178 } 179 180 @Override 181 public int getRemotePort() { 182 return 0; 183 } 184 185 @Override 186 public String getLocalName() { 187 return null; 188 } 189 190 @Override 191 public String getLocalAddr() { 192 return null; 193 } 194 195 @Override 196 public int getLocalPort() { 197 return 0; 198 } 199 200 @Override 201 public ServletContext getServletContext() { 202 return null; 203 } 204 205 @Override 206 public AsyncContext startAsync() throws IllegalStateException { 207 return null; 208 } 209 210 @Override 211 public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException { 212 return null; 213 } 214 215 @Override 216 public boolean isAsyncStarted() { 217 return false; 218 } 219 220 @Override 221 public boolean isAsyncSupported() { 222 return false; 223 } 224 225 @Override 226 public AsyncContext getAsyncContext() { 227 return null; 228 } 229 230 @Override 231 public DispatcherType getDispatcherType() { 232 return null; 233 } 234 } View CodeResponse:
1 package note1; 2 3 import javax.servlet.ServletOutputStream; 4 import javax.servlet.ServletResponse; 5 import java.io.*; 6 import java.net.URLConnection; 7 import java.util.Locale; 8 9 /** 10 * Created by kanyuxia on 2017/4/24. 11 */ 12 public class Response implements ServletResponse { 13 private final Request request; 14 15 private final OutputStream outputStream; 16 17 public Response(Request request, OutputStream outputStream) { 18 this.request = request; 19 this.outputStream = outputStream; 20 } 21 22 /** 23 * 發(fā)送靜態(tài)資源方法 24 * @throws IOException 25 */ 26 public void sendStaticResource() throws IOException { 27 BufferedOutputStream out = new BufferedOutputStream(outputStream); 28 //請(qǐng)求的本地靜態(tài)文件地址 29 File file = new File(HttpServer.STATIC_RESOURCE_ROOT + request.getUrl()); 30 // 文件存在 31 if (file.exists()) { 32 String mimeType = URLConnection.getFileNameMap().getContentTypeFor(file.getName()); 33 String header = "HTTP/1.1 200 OK\r\n" 34 + "Content-Length: " + file.length() + "\r\n" 35 + "Content-Type: " + mimeType + "; charset=UTF-8\r\n" 36 + "\r\n"; 37 // 發(fā)送header 38 out.write(header.getBytes()); 39 out.flush(); 40 // 發(fā)送content 41 byte[] buffer = new byte[1024]; 42 try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(file))) { 43 for (int b = in.read(buffer); b != -1; b = in.read(buffer)) { 44 out.write(buffer, 0, b); 45 out.flush(); 46 } 47 } catch (IOException e) { 48 System.out.println(); 49 } 50 // 關(guān)閉流 51 try { 52 out.close(); 53 } catch (IOException e) { 54 System.out.println(); 55 } 56 return; 57 } 58 // 文件不存在 59 sendNotFound(); 60 } 61 62 public void sendNotFound() { 63 BufferedOutputStream out = new BufferedOutputStream(outputStream); 64 // 文件不存在 65 String header = "HTTP/1.1 404 NOT FOUND\r\n" 66 + "\r\n"; 67 String content = "<html>\r\n" + 68 "<head>" + 69 "</head>" + 70 "<body>" + 71 "File Not Found" + 72 "</body>" + 73 "</html>"; 74 // 發(fā)送數(shù)據(jù) 75 try { 76 out.write(header.getBytes()); 77 out.write(content.getBytes()); 78 out.flush(); 79 } catch (IOException e) { 80 System.out.println(e); 81 } finally { 82 // 關(guān)閉流 83 try { 84 out.close(); 85 } catch (IOException e) { 86 System.out.println(e); 87 } 88 } 89 } 90 91 @Override 92 public String getCharacterEncoding() { 93 return null; 94 } 95 96 @Override 97 public String getContentType() { 98 return null; 99 } 100 101 @Override 102 public ServletOutputStream getOutputStream() throws IOException { 103 return null; 104 } 105 106 @Override 107 public PrintWriter getWriter() throws IOException { 108 return new PrintWriter(outputStream); 109 } 110 111 @Override 112 public void setCharacterEncoding(String charset) { 113 114 } 115 116 @Override 117 public void setContentLength(int len) { 118 119 } 120 121 @Override 122 public void setContentLengthLong(long len) { 123 124 } 125 126 @Override 127 public void setContentType(String type) { 128 129 } 130 131 @Override 132 public void setBufferSize(int size) { 133 134 } 135 136 @Override 137 public int getBufferSize() { 138 return 0; 139 } 140 141 @Override 142 public void flushBuffer() throws IOException { 143 144 } 145 146 @Override 147 public void resetBuffer() { 148 149 } 150 151 @Override 152 public boolean isCommitted() { 153 return false; 154 } 155 156 @Override 157 public void reset() { 158 159 } 160 161 @Override 162 public void setLocale(Locale loc) { 163 164 } 165 166 @Override 167 public Locale getLocale() { 168 return null; 169 } 170 } View CodeRequestFacade與ResponseFacade:
1 package note1; 2 3 import javax.servlet.*; 4 import java.io.BufferedReader; 5 import java.io.IOException; 6 import java.io.UnsupportedEncodingException; 7 import java.util.Enumeration; 8 import java.util.Locale; 9 import java.util.Map; 10 11 /** 12 * Created by kanyuxia on 2017/4/24. 13 */ 14 public class RequestFacade implements ServletRequest { 15 private final ServletRequest servletRequest; 16 17 RequestFacade(Request request) { 18 this.servletRequest = request; 19 } 20 @Override 21 public Object getAttribute(String name) { 22 return servletRequest.getAttribute(name); 23 } 24 25 @Override 26 public Enumeration<String> getAttributeNames() { 27 return servletRequest.getAttributeNames(); 28 } 29 30 @Override 31 public String getCharacterEncoding() { 32 return servletRequest.getCharacterEncoding(); 33 } 34 35 @Override 36 public void setCharacterEncoding(String env) throws UnsupportedEncodingException { 37 servletRequest.setCharacterEncoding(env); 38 } 39 40 @Override 41 public int getContentLength() { 42 return servletRequest.getContentLength(); 43 } 44 45 @Override 46 public long getContentLengthLong() { 47 return servletRequest.getContentLengthLong(); 48 } 49 50 @Override 51 public String getContentType() { 52 return servletRequest.getContentType(); 53 } 54 55 @Override 56 public ServletInputStream getInputStream() throws IOException { 57 return servletRequest.getInputStream(); 58 } 59 60 @Override 61 public String getParameter(String name) { 62 return servletRequest.getParameter(name); 63 } 64 65 @Override 66 public Enumeration<String> getParameterNames() { 67 return servletRequest.getParameterNames(); 68 } 69 70 @Override 71 public String[] getParameterValues(String name) { 72 return servletRequest.getParameterValues(name); 73 } 74 75 @Override 76 public Map<String, String[]> getParameterMap() { 77 return servletRequest.getParameterMap(); 78 } 79 80 @Override 81 public String getProtocol() { 82 return servletRequest.getProtocol(); 83 } 84 85 @Override 86 public String getScheme() { 87 return servletRequest.getScheme(); 88 } 89 90 @Override 91 public String getServerName() { 92 return servletRequest.getServerName(); 93 } 94 95 @Override 96 public int getServerPort() { 97 return servletRequest.getServerPort(); 98 } 99 100 @Override 101 public BufferedReader getReader() throws IOException { 102 return servletRequest.getReader(); 103 } 104 105 @Override 106 public String getRemoteAddr() { 107 return servletRequest.getRemoteAddr(); 108 } 109 110 @Override 111 public String getRemoteHost() { 112 return servletRequest.getRemoteHost(); 113 } 114 115 @Override 116 public void setAttribute(String name, Object o) { 117 servletRequest.setAttribute(name, o); 118 } 119 120 @Override 121 public void removeAttribute(String name) { 122 servletRequest.removeAttribute(name); 123 } 124 125 @Override 126 public Locale getLocale() { 127 return servletRequest.getLocale(); 128 } 129 130 @Override 131 public Enumeration<Locale> getLocales() { 132 return servletRequest.getLocales(); 133 } 134 135 @Override 136 public boolean isSecure() { 137 return servletRequest.isSecure(); 138 } 139 140 @Override 141 public RequestDispatcher getRequestDispatcher(String path) { 142 return servletRequest.getRequestDispatcher(path); 143 } 144 145 @Override 146 public String getRealPath(String path) { 147 return servletRequest.getRealPath(path); 148 } 149 150 @Override 151 public int getRemotePort() { 152 return servletRequest.getRemotePort(); 153 } 154 155 @Override 156 public String getLocalName() { 157 return servletRequest.getLocalName(); 158 } 159 160 @Override 161 public String getLocalAddr() { 162 return servletRequest.getLocalAddr(); 163 } 164 165 @Override 166 public int getLocalPort() { 167 return servletRequest.getLocalPort(); 168 } 169 170 @Override 171 public ServletContext getServletContext() { 172 return servletRequest.getServletContext(); 173 } 174 175 @Override 176 public AsyncContext startAsync() throws IllegalStateException { 177 return servletRequest.startAsync(); 178 } 179 180 @Override 181 public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException { 182 return servletRequest.startAsync(servletRequest, servletResponse); 183 } 184 185 @Override 186 public boolean isAsyncStarted() { 187 return servletRequest.isAsyncStarted(); 188 } 189 190 @Override 191 public boolean isAsyncSupported() { 192 return servletRequest.isAsyncSupported(); 193 } 194 195 @Override 196 public AsyncContext getAsyncContext() { 197 return servletRequest.getAsyncContext(); 198 } 199 200 @Override 201 public DispatcherType getDispatcherType() { 202 return servletRequest.getDispatcherType(); 203 } 204 } 205 206 package note1; 207 208 import javax.servlet.ServletOutputStream; 209 import javax.servlet.ServletResponse; 210 import java.io.IOException; 211 import java.io.PrintWriter; 212 import java.util.Locale; 213 214 /** 215 * Created by kanyuxia on 2017/4/24. 216 */ 217 public class ResponseFacade implements ServletResponse { 218 private final ServletResponse servletResponse; 219 220 ResponseFacade(Response response) { 221 this.servletResponse = response; 222 } 223 224 @Override 225 public String getCharacterEncoding() { 226 return servletResponse.getCharacterEncoding(); 227 } 228 229 @Override 230 public String getContentType() { 231 return servletResponse.getContentType(); 232 } 233 234 @Override 235 public ServletOutputStream getOutputStream() throws IOException { 236 return servletResponse.getOutputStream(); 237 } 238 239 @Override 240 public PrintWriter getWriter() throws IOException { 241 return servletResponse.getWriter(); 242 } 243 244 @Override 245 public void setCharacterEncoding(String charset) { 246 servletResponse.setCharacterEncoding(charset); 247 } 248 249 @Override 250 public void setContentLength(int len) { 251 servletResponse.setContentLength(len); 252 } 253 254 @Override 255 public void setContentLengthLong(long len) { 256 servletResponse.setContentLengthLong(len); 257 } 258 259 @Override 260 public void setContentType(String type) { 261 servletResponse.setContentType(type); 262 } 263 264 @Override 265 public void setBufferSize(int size) { 266 servletResponse.setBufferSize(size); 267 } 268 269 @Override 270 public int getBufferSize() { 271 return servletResponse.getBufferSize(); 272 } 273 274 @Override 275 public void flushBuffer() throws IOException { 276 servletResponse.flushBuffer(); 277 } 278 279 @Override 280 public void resetBuffer() { 281 servletResponse.resetBuffer(); 282 } 283 284 @Override 285 public boolean isCommitted() { 286 return servletResponse.isCommitted(); 287 } 288 289 @Override 290 public void reset() { 291 servletResponse.reset(); 292 } 293 294 @Override 295 public void setLocale(Locale loc) { 296 servletResponse.setLocale(loc); 297 } 298 299 @Override 300 public Locale getLocale() { 301 return servletResponse.getLocale(); 302 } 303 } View CodeStaticResourceProcessor:
1 package chapter2; 2 3 import java.io.IOException; 4 5 /** 6 * Created by kanyuxia on 2017/4/19. 7 * HttpServer靜態(tài)資源處理類 8 */ 9 public class StaticResourceProcessor { 10 /** 11 * 靜態(tài)資源處理方法 12 * @param request 請(qǐng)求對(duì)象 13 * @param response 響應(yīng)對(duì)象 14 */ 15 public void process(Request request, Response response) { 16 try { 17 response.sendStaticResource(); 18 } catch (IOException e) { 19 e.printStackTrace(); 20 } 21 } 22 } View CodeServletProcessor:
1 package note1; 2 3 import javax.servlet.Servlet; 4 import javax.servlet.ServletException; 5 import java.io.IOException; 6 7 /** 8 * Created by kanyuxia on 2017/4/24. 9 * HttpServer Servelt請(qǐng)求處理類 10 */ 11 public class ServletProcessor { 12 /** 13 * 處理Servlet請(qǐng)求方法 14 * @param request 請(qǐng)求對(duì)象 15 * @param response 響應(yīng)對(duì)象 16 */ 17 public void process(Request request, Response response) { 18 String url = request.getUrl(); 19 String servletName = url.substring(url.lastIndexOf("/") + 1); 20 // 從容器中拿到該Servlet 21 Servlet servlet = ServletContainer.container.get(servletName); 22 if (servlet != null) { 23 // 使用門面模式 24 RequestFacade requestFacade = new RequestFacade(request); 25 ResponseFacade responseFacade = new ResponseFacade(response); 26 try { 27 servlet.service(requestFacade, responseFacade); 28 } catch (ServletException e) { 29 e.printStackTrace(); 30 } catch (IOException e) { 31 e.printStackTrace(); 32 } 33 return; 34 } 35 // Servlet不存在 36 response.sendNotFound(); 37 } 38 } View CodePrimitiveServlet:
1 package note1; 2 3 import javax.servlet.*; 4 import java.io.IOException; 5 import java.io.PrintWriter; 6 7 8 /** 9 * Created by kanyuxia on 2017/4/19. 10 */ 11 public class PrimitiveServlet implements Servlet { 12 @Override 13 public void init(ServletConfig config) throws ServletException { 14 System.out.println("Primitive.init()"); 15 } 16 17 @Override 18 public ServletConfig getServletConfig() { 19 return null; 20 } 21 22 @Override 23 public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { 24 String header = "HTTP/1.1 200 OK\r\n" 25 + "Content-Type: text/html;charset=UTF-8\r\n" 26 + "\r\n"; 27 String content = "<html>\r\n" + 28 "<head>" + 29 "</head>" + 30 "<body>" + 31 "Primitive Servlet" + 32 "</body>" + 33 "</html>"; 34 PrintWriter writer = res.getWriter(); 35 writer.write(header); 36 writer.write(content); 37 writer.flush(); 38 writer.close(); 39 } 40 41 @Override 42 public String getServletInfo() { 43 return null; 44 } 45 46 @Override 47 public void destroy() { 48 System.out.println("Primitive.destory()"); 49 } 50 } View CodeServletContainer:
1 package note1; 2 3 import javax.servlet.Servlet; 4 import java.io.File; 5 import java.io.FileFilter; 6 import java.io.IOException; 7 import java.net.URL; 8 import java.net.URLClassLoader; 9 import java.net.URLStreamHandler; 10 import java.util.HashMap; 11 import java.util.Map; 12 13 /** 14 * Created by kanyuxia on 2017/4/24. 15 * Servlet容器:管理Servlet. 16 */ 17 public class ServletContainer { 18 /** 19 * 存放Servlet 20 */ 21 public static Map<String, Servlet> container = new HashMap<>(); 22 23 /** 24 * 初始化所有的Servlet 25 */ 26 @SuppressWarnings("unchecked") 27 public void init() { 28 // 創(chuàng)建URLClassLoader 29 URLClassLoader classLoader = null; 30 try { 31 // 創(chuàng)建URL 32 URL[] urls = new URL[1]; 33 File classPath = new File(HttpServer.SERVLET_ROOT); 34 String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString(); 35 URLStreamHandler streamHandler = null; 36 urls[0] = new URL(null, repository, streamHandler); 37 classLoader = new URLClassLoader(urls); 38 } catch (IOException e) { 39 System.out.println(); 40 } 41 // 獲得指定目錄下的所有.class文件 42 File path = new File(HttpServer.SERVLET_ROOT); 43 File[] files = path.listFiles(new FileFilter() { 44 @Override 45 public boolean accept(File pathname) { 46 return pathname.toString().endsWith(".class"); 47 } 48 }); 49 // 加載所有的.class文件 50 for (File file : files) { 51 String servletName = file.getName().substring(0, file.getName().indexOf(".")); 52 Class<Servlet> servletClass = null; 53 try { 54 servletClass = (Class<Servlet>) classLoader.loadClass(servletName); 55 } catch (ClassNotFoundException e) { 56 e.printStackTrace(); 57 } 58 Servlet servlet = null; 59 try { 60 servlet = servletClass.newInstance(); 61 } catch (InstantiationException e) { 62 e.printStackTrace(); 63 } catch (IllegalAccessException e) { 64 e.printStackTrace(); 65 } 66 ServletContainer.container.put(servletName, servlet); 67 } 68 } 69 } View CodeTest:
1 package note1; 2 3 /** 4 * Created by kanyuxia on 2017/4/24. 5 */ 6 public class Test { 7 public static void main(String[] args) { 8 // 加載Servlet 9 ServletContainer servletContainer = new ServletContainer(); 10 servletContainer.init(); 11 // 啟動(dòng)HttpServer 12 HttpServer httpServer = new HttpServer(); 13 httpServer.start(); 14 } 15 } View Code?
轉(zhuǎn)載于:https://www.cnblogs.com/maying3010/p/6759597.html
總結(jié)
以上是生活随笔為你收集整理的《How Tomcat Works》读书笔记(二)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 嵌入式第一周学习总结
- 下一篇: (一)java多线程之Thread