通过Java编写一个服务器理解动态Web,静态Web
靜態(tài)Web
說到Servlet自然就要說到Web,Web分為靜態(tài)Web和動態(tài)Web,之前我一直都傻傻分不清兩者的區(qū)別,直到用JAVA編寫了一個服務(wù)器后才明白二者的區(qū)別,所謂靜態(tài)Web,實際上就是指,客戶端要請求的資源文件,服務(wù)器已經(jīng)提前把它放在了文件系統(tǒng)(磁盤)上,看下面用Java實現(xiàn)的一個靜態(tài)Web服務(wù)器 public class HTTPService {private static HashMap<String,Servlet> servletCache = new HashMap<>();public static void init(){servletCache.put("HTTPServlet",new HTTPServlet());}public static void main(String[] args) {init();int port;ServerSocket serversocket;port=8080;try {serversocket = new ServerSocket(port); //默認(rèn)服務(wù)器套接字ip為本地地址System.out.println("服務(wù)器正在監(jiān)聽端口:8080");while (true) {try{Socket socket = serversocket.accept();//會進入阻塞狀態(tài),直到客戶端與服務(wù)器TCP建立System.out.println("建立了與客戶端的一個新的tcp連接,客戶端地址為" + socket.getInetAddress() + ":" + socket.getPort());service(socket);}catch (Exception e){System.out.println("客戶端請求資源不存在");}}} catch (Exception e) {System.out.println("客戶端請求資源不存在");}}public static void service(Socket socket) throws Exception {InputStream socketIn = socket.getInputStream();//獲得客戶端請求信息流Thread.sleep(500); //與客戶端TCP請求已建立,還需要等待客戶端發(fā)送http請求,如果在TCP后立馬響應(yīng)HTTP,socket內(nèi)容可能為空int size = socketIn.available();byte[] buffer = new byte[size];socketIn.read(buffer);String request = new String(buffer);int endIndex = request.indexOf("\r\n");if (endIndex==-1)endIndex = request.length();String firstLineOfRequest = request.substring(0,endIndex);String[] parts = firstLineOfRequest.split(" ");String uri="";String contentType="";if (parts.length>=2){uri = parts[1];}//靜態(tài)webif (uri.indexOf("html") != -1)contentType = "text/html";else if (uri.indexOf("jpg") != -1)contentType = "image/jepg";elsecontentType = "application/octet-stream";String firstLineOfResponse = "HTTP/1.1 200 OK\r\n"; //響應(yīng)行String responseHeader = "Content-Type:" + contentType + "\r\n\r\n";// FileInputStream in = new FileInputStream("E:\\IDEA WORKSPACE\\ServiceDemo\\resources\\index.html");System.out.println(HttpServer.class.getResource(""));InputStream in = HTTPService.class.getResourceAsStream("root/" + uri);System.out.println(HTTPService.class.getResource("root/" + uri));OutputStream output = socket.getOutputStream();output.write(firstLineOfResponse.getBytes());output.write(responseHeader.getBytes());buffer = new byte[1024];int len = 0;while ((len = in.read(buffer)) != -1) {System.out.println(1);output.write(buffer, 0, len);}Thread.sleep(1000);//睡眠1秒,等待客戶端接收http響應(yīng)結(jié)果,socket代表兩者間的tcp連接,如果立馬斷開,客戶端可能就收不到響應(yīng)結(jié)果了socket.close();}}將事先準(zhǔn)備好的index.html文件放在磁盤上,將代碼運行起來,此時HTTPServer就作為一個服務(wù)開始監(jiān)聽電腦上的8080端口了,打開瀏覽器,在url地址欄輸入localhost:8080/index.html,結(jié)果如下:
工作原理如下:
HTTPServer接收到來自客戶端的請求后,就會在磁盤上查找客戶端請求的資源文件,然后把文件響應(yīng)給客戶端,index.html就事先存放在磁盤上,然后當(dāng)瀏覽器請求index.html,HTTPServer就把html文件響應(yīng)給瀏覽器,瀏覽器再解析html文件后,就是我們看到的Hello頁面了。
動態(tài)Web
網(wǎng)上經(jīng)常能看見一句話,動態(tài)Web就是每個用戶看到的東西是不一樣的,這句話沒錯,但是還不太能夠幫助我們理解動態(tài)Web。那么動態(tài)Web到底是什么,動態(tài)Web就是指客戶端可以與服務(wù)器進行交互,并且客戶端請求的資源文件,是由服務(wù)器動態(tài)生成的。舉這么一個例子,假設(shè)D是一個在某城市居住了很久的人,這一天A向D問路X街怎么走,D經(jīng)過思考后,告訴了A,此時B又來問路Y街怎么走,對于C來說,簡直輕而易舉。上述中A,B看作客戶端,D是服務(wù)器,而問路可以看作客戶端向服務(wù)器請求的資源文件,去某城市可以看作是客戶端與服務(wù)器的交互,很明顯,A和B得到的響應(yīng)內(nèi)容都是不同的,服務(wù)器在得到客戶端的請求后,執(zhí)行業(yè)務(wù)邏輯操作,得出了通往某城市怎么走,然后響應(yīng)給客戶端。 public class HTTPService {private static HashMap<String,Servlet> servletCache = new HashMap<>();public static void init(){servletCache.put("HTTPServlet",new HTTPServlet());}public static void main(String[] args) {init();int port;ServerSocket serversocket;port=8080;try {serversocket = new ServerSocket(port); //默認(rèn)服務(wù)器套接字ip為本地地址System.out.println("服務(wù)器正在監(jiān)聽端口:8080");while (true) {try{Socket socket = serversocket.accept();//會進入阻塞狀態(tài),直到客戶端與服務(wù)器TCP建立System.out.println("建立了與客戶端的一個新的tcp連接,客戶端地址為" + socket.getInetAddress() + ":" + socket.getPort());service(socket);}catch (Exception e){System.out.println("客戶端請求資源不存在");}}} catch (Exception e) {System.out.println("客戶端請求資源不存在");}}public static void service(Socket socket) throws Exception {InputStream socketIn = socket.getInputStream();//獲得客戶端請求信息流Thread.sleep(500); //與客戶端TCP請求已建立,還需要等待客戶端發(fā)送http請求,如果在TCP后立馬響應(yīng)HTTP,socket內(nèi)容可能為空int size = socketIn.available();byte[] buffer = new byte[size];socketIn.read(buffer);String request = new String(buffer);int endIndex = request.indexOf("\r\n");if (endIndex==-1)endIndex = request.length();String firstLineOfRequest = request.substring(0,endIndex);String[] parts = firstLineOfRequest.split(" ");String uri="";String contentType="";if (parts.length>=2){uri = parts[1];}System.out.println(uri);if(uri.indexOf("servlet")!=-1){ //動態(tài)webString servletName = "";if (uri.indexOf("?")!=-1)servletName = uri.substring(uri.indexOf("servlet/")+8,uri.indexOf("?"));elseservletName = uri.substring(uri.indexOf("servlet/")+8,uri.length());System.out.println(servletName);Servlet servlet = servletCache.get(servletName);System.out.println(servletCache);System.out.println(servlet);if (servlet == null)throw new Exception();servlet.init();servlet.service(request,socket.getOutputStream());}else {//靜態(tài)webif (uri.indexOf("html") != -1)contentType = "text/html";else if (uri.indexOf("jpg") != -1)contentType = "image/jepg";elsecontentType = "application/octet-stream";String firstLineOfResponse = "HTTP/1.1 200 OK\r\n"; //響應(yīng)行String responseHeader = "Content-Type:" + contentType + "\r\n\r\n";// FileInputStream in = new FileInputStream("E:\\IDEA WORKSPACE\\ServiceDemo\\resources\\index.html");System.out.println(HttpServer.class.getResource(""));InputStream in = HTTPService.class.getResourceAsStream("root/" + uri);System.out.println(HTTPService.class.getResource("root/" + uri));OutputStream output = socket.getOutputStream();output.write(firstLineOfResponse.getBytes());output.write(responseHeader.getBytes());buffer = new byte[1024];int len = 0;while ((len = in.read(buffer)) != -1) {System.out.println(1);output.write(buffer, 0, len);}}Thread.sleep(1000);//睡眠1秒,等待客戶端接收http響應(yīng)結(jié)果,socket代表兩者間的tcp連接,如果立馬斷開,客戶端可能就收不到響應(yīng)結(jié)果了socket.close();}} public class HTTPServlet implements Servlet{@Overridepublic void init() {}@Overridepublic void service(String request, OutputStream out) throws IOException {int endIndex = request.indexOf("/r/n");String firstOfRequest = "";if (endIndex!=-1)firstOfRequest = request.substring(0,endIndex);elsefirstOfRequest = request;String[] parts = firstOfRequest.split(" ");String method = parts[0];String uri = parts[1];String userName="";if (method.equalsIgnoreCase("get")){if (uri.indexOf("username=")!=-1){String[] params = uri.substring(uri.indexOf("?") + 8, uri.length()).split("&");String[] params_parts = params[0].split("=");userName = params_parts[1];}}if (method.equalsIgnoreCase("post")){if (request.indexOf("\r\n\r\n")!=-1){String content = request.substring(request.indexOf("\r\n\r\n"+4,request.length()));if (content.indexOf("username=")!=-1){String[] contentParts = content.split("&");userName = (contentParts[0].split("="))[1];}}}userName = URLDecoder.decode(userName,"utf-8");System.out.println(userName);out.write("HTTP/1.1 200 OK\r\n".getBytes());out.write("Content-Type:text/html\r\n\r\n".getBytes());out.write(("<meta charset=\"UTF-8\"> <h1>Hello,"+userName+"</h1>").getBytes());} } public interface Servlet {public void init();public void service(String request, OutputStream out) throws IOException; }前面說過,動態(tài)Web中服務(wù)器在接收到請求后,會執(zhí)行業(yè)務(wù)邏輯操作,這個業(yè)務(wù)邏輯操作其實就是由服務(wù)器內(nèi)的servlet模塊實現(xiàn)的,下面的圖就是上述的代碼的執(zhí)行原理
如果客戶端的URL訪問的是servlet目錄下,那么就代表是訪問動態(tài)資源,服務(wù)器就會交給servlet處理,否則就會當(dāng)成普通靜態(tài)文件處理,從磁盤上取出響應(yīng)即可。學(xué)習(xí)過一點如何編寫webapp的同學(xué)會發(fā)現(xiàn),上述代碼中的servlet緩沖池(servletCache)與web.xml中的servlet映射很相似,都是通過名字來映射到一個具體的servlet實現(xiàn)類,服務(wù)器動態(tài)加載servlet類實現(xiàn)業(yè)務(wù)邏輯操作也體現(xiàn)了動態(tài)Web的特性。
在瀏覽器的url地址欄輸入http://localhost:8080/servlet/HTTPServlet?username=“王小虎”,結(jié)果如下
在動態(tài)Web中,客戶端可以與服務(wù)器交互,服務(wù)器通過與客戶端的交互,來動態(tài)響應(yīng)客戶端。
總結(jié)
以上是生活随笔為你收集整理的通过Java编写一个服务器理解动态Web,静态Web的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信百度网盘小程序怎么转存到百度网盘Ap
- 下一篇: cd40系列芯片_IC集成电路型号大全及