(1) open system interconnecthtml
OSI是Open System Interconnection的縮寫,意爲開放式系統互聯 。OSI是一個開放性的通訊系統互連參考模型,他是一個定義得很是好的協議規範。OSI模型有7層結構,每層均可以有幾個子層。 OSI的7層從上到下分別是 7 應用層 6 表示層 5 會話層 4 傳輸層 3 網絡層 2 數據鏈路層 1 物理層 ;其中高層(即七、六、五、4層)定義了應用程序的功能,下面3層(即三、二、1層)主要面向經過網絡的端到端的數據流。java
(2) http協議程序員
1、web
HTTP(HyperText Transfer Protocol)是一套計算機經過網絡進行通訊的規則。計算機專家設計出HTTP,使HTTP客戶(如Web瀏覽器)可以從HTTP服務器(Web服務器)請求信息和服務,HTTP目前協議的版本是1.1.HTTP是一種無狀態的協議,無狀態是指Web瀏覽器和Web服務器之間不須要創建持久的鏈接,這意味着當一個客戶端向服務器端發出請求,而後Web服務器返回響應(response),鏈接就被關閉了,在服務器端不保留鏈接的有關信息.HTTP遵循請求(Request)/應答(Response)模型。Web瀏覽器向Web服務器發送請求,Web服務器處理請求並返回適當的應答。全部HTTP鏈接都被構形成一套請求和應答。 編程
HTTP使用內容類型,是指Web服務器向Web瀏覽器返回的文件都有與之相關的類型。全部這些類型在MIME Internet郵件協議上模型化,即Web服務器告訴Web瀏覽器該文件所具備的種類,是HTML文檔、GIF格式圖像、聲音文件仍是獨立的應用程序。大多數Web瀏覽器都擁有一系列的可配置的輔助應用程序,它們告訴瀏覽器應該如何處理Web服務器發送過來的各類內容類型。數組
HTTP通訊機制是在一次完整的HTTP通訊過程當中,Web瀏覽器與Web服務器之間將完成下列7個步驟:瀏覽器
GET /index.html?name=123&pwd=5456 HTTP/1.1
Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Accept-Language: en-US,zh-CN;q=0.5
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; InfoPath.2)
Accept-Encoding: gzip, deflate
Host: localhost:8888
Connection: Keep-Alive安全
POST /index.html HTTP/1.1
Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Accept-Language: en-US,zh-CN;q=0.5
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; InfoPath.2)
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Host: localhost:8888
Content-Length: 17
Connection: Keep-Alive
Cache-Control: no-cache服務器
uname=123&pwd=213&fav=0&fav=1&fav=2網絡
package com.zwj.demo01; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; /** * 建立服務器,並啓動 * @author Administrator * */ public class Server { private ServerSocket server; /** * @param args */ public static void main(String[] args) { Server server = new Server(); server.start(); } /** * 啓動方法 */ public void start(){ try { server = new ServerSocket(8888); this.receive(); } catch (IOException e) { e.printStackTrace(); } } /** * 接收客戶端 */ private void receive(){ try { Socket client =server.accept(); StringBuilder sb =new StringBuilder(); String msg =null; BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream())); while((msg=br.readLine()).length()>0){ sb.append(msg); sb.append("\r\n"); } //接收客戶端的請求信息 String requestInfo =sb.toString().trim(); System.out.println(requestInfo); } catch (IOException e) { //e.printStackTrace(); } } /** * 聽着服務器 */ public void stop(){ } }
package com.zwj.demo01; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; /** * 建立服務器,並啓動 * @author Administrator * */ public class Server2 { private ServerSocket server; /** * @param args */ public static void main(String[] args) { Server2 server = new Server2(); server.start(); } /** * 啓動方法 */ public void start(){ try { server = new ServerSocket(8888); this.receive(); } catch (IOException e) { e.printStackTrace(); } } /** * 接收客戶端 */ private void receive(){ try { Socket client =server.accept(); byte[] data=new byte[20480]; int len =client.getInputStream().read(data); //接收客戶端的請求信息 String requestInfo=new String(data,0,len).trim(); System.out.println(requestInfo); } catch (IOException e) { //e.printStackTrace(); } } /** * 聽着服務器 */ public void stop(){ } } /* POST /log HTTP/1.1 Host: localhost:8888 Connection: keep-alive Content-Length: 17 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 Origin: null Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,* ;q=0.8 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 uname=123&pwd=123 */
<html> <head> <title>登陸</title> </head> <body> <form method="post" action="http://localhost:8888/index.html"> 用戶名:<input type="text" name="uname" id="uname"/> 密碼:<input type="password" name="pwd" id="pwd"/> <input type="submit" value="登陸"/> </form> </body> </html>
帶有響應的服務器名稱
package com.zwj.demo01; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Date; /** * 建立服務器,並啓動 * * 一、請求 * 二、響應 * @author Administrator * */ public class Server3 { private ServerSocket server; //換行控制符號 public static final String CRLF="\r\n"; public static final String BLANK=" "; /** * @param args */ public static void main(String[] args) { Server3 server = new Server3(); server.start(); } /** * 啓動方法 */ public void start(){ try { server = new ServerSocket(8888); this.receive(); } catch (IOException e) { e.printStackTrace(); } } /** * 接收客戶端 */ private void receive(){ try { Socket client =server.accept(); byte[] data=new byte[20480]; int len =client.getInputStream().read(data); //接收客戶端的請求信息 String requestInfo=new String(data,0,len).trim(); System.out.println(requestInfo); //響應 StringBuilder responseContext =new StringBuilder(); responseContext.append("<html><head><title>HTTP響應示例</title>" + "</head><body>Hello bjsxt!</body></html>"); StringBuilder response =new StringBuilder(); //1) HTTP協議版本、狀態代碼、描述 response.append("HTTP/1.1").append(BLANK).append("200").append(BLANK).append("OK").append(CRLF); //2) 響應頭(Response Head) response.append("Server:bjsxt Server/0.0.1").append(CRLF); response.append("Date:").append(new Date()).append(CRLF); response.append("Content-type:text/html;charset=GBK").append(CRLF); //正文長度 :字節長度 response.append("Content-Length:").append(responseContext.toString().getBytes().length).append(CRLF); //3)正文以前 response.append(CRLF); //4)正文 response.append(responseContext); System.out.println(responseContext); //輸出流 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); bw.write(response.toString()); bw.flush(); bw.close(); } catch (IOException e) { } } /** * 聽着服務器 */ public void stop(){ } } /* POST /index.html HTTP/1.1 Host: localhost:8888 Connection: keep-alive Content-Length: 22 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 Origin: null Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*;q=0.8 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 uname=zhouwuji&pwd=123 <html><head><title>HTTP響應示例</title></head><body>Hello bjsxt!</body></html> */
分離response、server
package com.zwj.demo01; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.Socket; import java.util.Date; /** * 封裝響應信息 * @author Administrator * */ public class Response { //兩個常量 public static final String CRLF="\r\n"; public static final String BLANK=" "; //流 private BufferedWriter bw ; //正文 private StringBuilder content; //存儲頭信息 private StringBuilder headInfo; //存儲正文長度 private int len =0; public Response(){ headInfo =new StringBuilder(); content =new StringBuilder(); len =0; } public Response(Socket client){ this(); try { bw= new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); } catch (IOException e) { headInfo=null; } } public Response(OutputStream os){ this(); bw= new BufferedWriter(new OutputStreamWriter(os)); } /** * 構建正文 */ public Response print(String info){ content.append(info); len+=info.getBytes().length; return this; } /** * 構建正文+回車 */ public Response println(String info){ content.append(info).append(CRLF); len+=(info+CRLF).getBytes().length; return this; } /** * 構建響應頭 */ private void createHeadInfo(int code){ //1) HTTP協議版本、狀態代碼、描述 headInfo.append("HTTP/1.1").append(BLANK).append(code).append(BLANK); switch(code){ case 200: headInfo.append("OK"); break; case 404: headInfo.append("NOT FOUND"); break; case 505: headInfo.append("SEVER ERROR"); break; } headInfo.append(CRLF); //2) 響應頭(Response Head) headInfo.append("Server:bjsxt Server/0.0.1").append(CRLF); headInfo.append("Date:").append(new Date()).append(CRLF); headInfo.append("Content-type:text/html;charset=GBK").append(CRLF); //正文長度 :字節長度 headInfo.append("Content-Length:").append(len).append(CRLF); headInfo.append(CRLF); //分隔符 } //推送到客戶端 void pushToClient(int code) throws IOException{ if(null==headInfo){ code =500; } createHeadInfo(code); //頭信息+分割符 bw.append(headInfo.toString()); //正文 bw.append(content.toString()); bw.flush(); } public void close(){ CloseUtil.closeIO(bw); } }
package com.zwj.demo01; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Date; /** * 建立服務器,並啓動 * * 一、請求 * 二、響應 * @author Administrator * */ public class Server4 { private ServerSocket server; public static final String CRLF="\r\n"; public static final String BLANK=" "; /** * @param args */ public static void main(String[] args) { Server4 server = new Server4(); server.start(); } /** * 啓動方法 */ public void start(){ try { server = new ServerSocket(8888); this.receive(); } catch (IOException e) { e.printStackTrace(); } } /** * 接收客戶端 */ private void receive(){ try { Socket client =server.accept(); byte[] data=new byte[20480]; int len =client.getInputStream().read(data); //接收客戶端的請求信息 String requestInfo=new String(data,0,len).trim(); System.out.println(requestInfo); //響應 Response rep=new Response(client.getOutputStream()); rep.println("<html><head><title>HTTP響應示例</title>"); rep.println("</head><body>Hello server!</body></html>"); rep.pushToClient(200); } catch (IOException e) { } } /** * 聽着服務器 */ public void stop(){ } }
package com.zwj.demo01; import java.io.Closeable; import java.net.DatagramSocket; import java.net.ServerSocket; import java.net.Socket; public class CloseUtil { /** * 關閉IO流 */ /* public static void closeIO(Closeable... io){ for(Closeable temp:io){ try { if (null != temp) { temp.close(); } } catch (Exception e) { } } }*/ /** * 使用泛型方法實現關閉IO流 * @param io */ public static <T extends Closeable> void closeIO(T... io){ for(Closeable temp:io){ try { if (null != temp) { temp.close(); } } catch (Exception e) { } } } public static void closeSocket(ServerSocket socket){ try { if (null != socket) { socket.close(); } } catch (Exception e) { } } public static void closeSocket(Socket socket){ try { if (null != socket) { socket.close(); } } catch (Exception e) { } } public static void closeSocket(DatagramSocket socket){ try { if (null != socket) { socket.close(); } } catch (Exception e) { } } }
package com.zwj.demo01; import java.io.IOException; import java.net.Socket; /** * 一個請求與響應 就一個此對象 * @author Administrator * */ public class Dispatcher implements Runnable{ private Socket client; private Request req; private Response rep; private int code=200; Dispatcher(Socket client){ this.client=client; try { req =new Request(client.getInputStream()); rep =new Response(client.getOutputStream()); } catch (IOException e) { //e.printStackTrace(); code =500; return ; } } @Override public void run() { Servlet serv =new Servlet(); serv.service(req,rep); try { rep.pushToClient(code); //推送到客戶端 } catch (IOException e) { //e.printStackTrace(); } try { rep.pushToClient(500); } catch (IOException e) { e.printStackTrace(); } CloseUtil.closeSocket(client); } }
package com.zwj.demo01; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.StringTokenizer; /** * 封裝request * @author Administrator * */ public class Request { //請求方式 private String method; //請求資源 private String url; //請求參數 private Map<String,List<String>> parameterMapValues; //內部 public static final String CRLF="\r\n"; private InputStream is; //請求的信息 private String requestInfo; public Request(){ method =""; url =""; parameterMapValues=new HashMap<String,List<String>>(); requestInfo=""; } public Request(InputStream is){ this(); this.is=is; try { byte[] data = new byte[20480]; int len = is.read(data); requestInfo = new String(data, 0, len); } catch (Exception e) { return ; } //分析請求信息 parseRequestInfo(); } /** * 分析請求信息 */ private void parseRequestInfo(){ if(null==requestInfo ||(requestInfo=requestInfo.trim()).equals("")){ return ; } /** * ===================================== * 從信息的首行分解出 :請求方式 請求路徑 請求參數(get可能存在) * 如:GET /index.html?name=123&pwd=5456 HTTP/1.1 * * 若是爲post方式,請求參數可能在 最後正文中 * * 思路: * 1)請求方式 :找出第一個/ 截取便可 * 2)請求資源:找出第一個/ HTTP/ * ===================================== */ String paramString =""; //接收請求參數 //一、獲取請求方式 String firstLine =requestInfo.substring(0,requestInfo.indexOf(CRLF)); int idx =requestInfo.indexOf("/"); // /的位置 this.method=firstLine.substring(0, idx).trim(); String urlStr =firstLine.substring(idx,firstLine.indexOf("HTTP/")).trim(); if(this.method.equalsIgnoreCase("post")){ this.url=urlStr; paramString=requestInfo.substring(requestInfo.lastIndexOf(CRLF)).trim(); }else if(this.method.equalsIgnoreCase("get")){ if(urlStr.contains("?")){ //是否存在參數 String[] urlArray=urlStr.split("\\?"); this.url=urlArray[0]; paramString=urlArray[1];//接收請求參數 }else{ this.url=urlStr; } } //不存在請求參數 if(paramString.equals("")){ return ; } //二、將請求參數封裝到Map中 parseParams(paramString); } private void parseParams(String paramString){ //分割 將字符串轉成數組 StringTokenizer token=new StringTokenizer(paramString,"&"); while(token.hasMoreTokens()){ String keyValue =token.nextToken(); String[] keyValues=keyValue.split("="); if(keyValues.length==1){ //Arrays.copyOf 擴容 keyValues =Arrays.copyOf(keyValues, 2); keyValues[1] =null; } String key = keyValues[0].trim(); String value = null==keyValues[1]?null:decode(keyValues[1].trim(),"gbk"); //轉換成Map 分揀 if(!parameterMapValues.containsKey(key)){ parameterMapValues.put(key,new ArrayList<String>()); } List<String> values =parameterMapValues.get(key); values.add(value); } } /** * 解決中文 * @param value * @param code * @return */ private String decode(String value,String code){ try { return java.net.URLDecoder.decode(value, code); } catch (UnsupportedEncodingException e) { //e.printStackTrace(); } return null; } /** * 根據頁面的name 獲取對應的多個值 * @param args */ public String[] getParameterValues(String name){ List<String> values=null; if((values=parameterMapValues.get(name))==null){ return null; }else{ return values.toArray(new String[0]); } } /** * 根據頁面的name 獲取對應的單個值 * @param args */ public String getParameter(String name){ String[] values =getParameterValues(name); if(null==values){ return null; } return values[0]; } public String getUrl() { return url; } }
package com.zwj.demo01; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.Socket; import java.util.Date; /** * 封裝響應信息 * @author Administrator * */ public class Response { //兩個常量 public static final String CRLF="\r\n"; public static final String BLANK=" "; //流 private BufferedWriter bw ; //正文 private StringBuilder content; //存儲頭信息 private StringBuilder headInfo; //存儲正文長度 private int len =0; public Response(){ headInfo =new StringBuilder(); content =new StringBuilder(); len =0; } public Response(Socket client){ this(); try { bw= new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); } catch (IOException e) { headInfo=null; } } public Response(OutputStream os){ this(); bw= new BufferedWriter(new OutputStreamWriter(os)); } /** * 構建正文 */ public Response print(String info){ content.append(info); len+=info.getBytes().length; return this; } /** * 構建正文+回車 */ public Response println(String info){ content.append(info).append(CRLF); len+=(info+CRLF).getBytes().length; return this; } /** * 構建響應頭 */ private void createHeadInfo(int code){ //1) HTTP協議版本、狀態代碼、描述 headInfo.append("HTTP/1.1").append(BLANK).append(code).append(BLANK); switch(code){ case 200: headInfo.append("OK"); break; case 404: headInfo.append("NOT FOUND"); break; case 505: headInfo.append("SEVER ERROR"); break; } headInfo.append(CRLF); //2) 響應頭(Response Head) headInfo.append("Server:bjsxt Server/0.0.1").append(CRLF); headInfo.append("Date:").append(new Date()).append(CRLF); headInfo.append("Content-type:text/html;charset=GBK").append(CRLF); //正文長度 :字節長度 headInfo.append("Content-Length:").append(len).append(CRLF); headInfo.append(CRLF); //分隔符 } //推送到客戶端 void pushToClient(int code) throws IOException{ if(null==headInfo){ code =500; } createHeadInfo(code); //頭信息+分割符 bw.append(headInfo.toString()); //正文 bw.append(content.toString()); bw.flush(); } public void close(){ CloseUtil.closeIO(bw); } }
package com.zwj.demo01; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; /** * 建立服務器,並啓動 * * 一、請求 * 二、響應 * @author Administrator * */ public class Server7 { private ServerSocket server; public static final String CRLF="\r\n"; public static final String BLANK=" "; private boolean isShutDown= false; /** * @param args */ public static void main(String[] args) { Server7 server = new Server7(); server.start(); } /** * 啓動方法 */ public void start(){ start(8888); } /** * 指定端口的啓動方法 */ public void start(int port){ try { server = new ServerSocket(port); this.receive(); } catch (IOException e) { //e.printStackTrace(); stop(); } } /** * 接收客戶端 */ private void receive(){ try { while(!isShutDown){ new Thread(new Dispatcher(server.accept())).start(); } } catch (IOException e) { //e.printStackTrace(); stop(); } } /** * 中止服務器 */ public void stop(){ isShutDown=true; CloseUtil.closeSocket(server); } }
package com.zwj.demo01; public class Servlet { public void service(Request req,Response rep){ rep.println("<html><head><title>HTTP響應示例</title>"); rep.println("</head><body>"); rep.println("歡迎:").println(req.getParameter("uname")).println("回來"); rep.println("</body></html>"); } }
package com.zwj.demo01; import java.io.Closeable; import java.net.DatagramSocket; import java.net.ServerSocket; import java.net.Socket; public class CloseUtil { /** * 關閉IO流 */ /* public static void closeIO(Closeable... io){ for(Closeable temp:io){ try { if (null != temp) { temp.close(); } } catch (Exception e) { } } }*/ /** * 使用泛型方法實現關閉IO流 * @param io */ public static <T extends Closeable> void closeIO(T... io){ for(Closeable temp:io){ try { if (null != temp) { temp.close(); } } catch (Exception e) { } } } public static void closeSocket(ServerSocket socket){ try { if (null != socket) { socket.close(); } } catch (Exception e) { } } public static void closeSocket(Socket socket){ try { if (null != socket) { socket.close(); } } catch (Exception e) { } } public static void closeSocket(DatagramSocket socket){ try { if (null != socket) { socket.close(); } } catch (Exception e) { } } }
sax解析xml文件 注:要繼承defaulthandle類 裏面有5個方法 startdocument() 、startelentment()獲得元素名稱 、charcter()獲得values值、endelement()、enddocument() 解析式一行一行解析,
和dom4j是把xml變成dom樹進行解析
package com.bjsxt.xml; import java.io.IOException; import java.util.List; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.SAXException; public class ParseDemo01 { /** * @param args * @throws SAXException * @throws ParserConfigurationException * @throws IOException */ public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException { //一、獲取解析工廠 SAXParserFactory factory=SAXParserFactory.newInstance(); //二、從解析工廠獲取解析器 SAXParser parse =factory.newSAXParser(); //三、加載文檔 Document 註冊處理器 //四、編寫處理器 PersonHandler handler=new PersonHandler(); parse.parse(Thread.currentThread().getContextClassLoader() .getResourceAsStream("com/bjsxt/xml/person.xml") ,handler ); List<Person> persons =handler.getPersons(); for(Person p:persons){ System.out.println(p.getName()+"-->"+p.getAge()); } } }
package com.bjsxt.xml; public class Person { private String name; private int age; public Person() { // TODO Auto-generated constructor stub } public Person(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
<?xml version="1.0" encoding="UTF-8" ?> <persons> <person> <name>至尊寶</name> <age>9000</age> </person> <person> <name>白晶晶</name> <age>7000</age> </person> </persons>
package com.bjsxt.xml; import java.util.ArrayList; import java.util.List; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; /** * 存儲對象 * @author Administrator * */ public class PersonHandler extends DefaultHandler { private List<Person> persons; private Person person; private String tag;//記錄標籤名 @Override public void startDocument() throws SAXException { // TODO Auto-generated method stub //System.out.println("處理文檔開始"); persons =new ArrayList<Person>(); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { System.out.println("開始一個元素" +qName); if(null!=qName){ tag=qName; } if(null!=qName &&qName.equals("person")){ person =new Person(); } } @Override public void characters(char[] ch, int start, int length) throws SAXException { String str =new String(ch,start,length); if(null!=tag &&tag.equals("name")){ //System.out.println(new String(ch,start,length)); person.setName(str); }else if(null!=tag &&tag.equals("age")){ Integer age = Integer.valueOf(str); person.setAge(age); } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { //System.out.println("結束一個元素" +qName); if(qName.equals("person")){ this.persons.add(person); } tag =null; } @Override public void endDocument() throws SAXException { System.out.println("文檔處理結束"); } public List<Person> getPersons() { return persons; } public void setPersons(List<Person> persons) { this.persons = persons; } }
簡單的服務器最終版本
package com.zwj.server; import java.io.IOException; import java.net.Socket; import com.zwj.servlet.Servlet; import com.zwj.util.CloseUtil; /** * 一個請求與響應 就一個此對象 * @author Administrator * */ public class Dispatcher implements Runnable{ private Socket client; private Request req; private Response rep; private int code=200; Dispatcher(Socket client){ this.client=client; try { req =new Request(client.getInputStream()); rep =new Response(client.getOutputStream()); } catch (IOException e) { //e.printStackTrace(); code =500; return ; } } @Override public void run() { try { Servlet serv =WebApp.getServlet(req.getUrl()); if(null==serv){ this.code=404; //找不處處理 }else{ serv.service(req, rep); } rep.pushToClient(code); //推送到客戶端 }catch (Exception e) { e.printStackTrace(); this.code=500; } try { rep.pushToClient(500); } catch (IOException e) { e.printStackTrace(); } req.close(); rep.close(); CloseUtil.closeSocket(client); } }
package com.zwj.server; /* <servlet> <servlet-name>login</servlet-name> <servlet-class>com.bjsxt.server.demo4.LoginServlet</servlet-class> </servlet> */ public class Entity { private String name; private String clz; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getClz() { return clz; } public void setClz(String clz) { this.clz = clz; } }
package com.zwj.server; import java.util.ArrayList; import java.util.List; /* <servlet-mapping> <servlet-name>login</servlet-name> <url-pattern>/login</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>login</servlet-name> <url-pattern>/log</url-pattern> </servlet-mapping> */ public class Mapping { private String name; private List<String> urlPattern; public Mapping(){ urlPattern =new ArrayList<String>(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<String> getUrlPattern() { return urlPattern; } public void setUrlPattern(List<String> urlPattern) { this.urlPattern = urlPattern; } }
package com.zwj.server; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import com.zwj.util.CloseUtil; /** * 封裝request * @author Administrator * */ public class Request { //請求方式 private String method; //請求資源 private String url; //請求參數 private Map<String,List<String>> parameterMapValues; //內部 public static final String CRLF="\r\n"; private InputStream is; private String requestInfo; public Request(){ method =""; url =""; parameterMapValues=new HashMap<String,List<String>>(); requestInfo=""; } public Request(InputStream is){ this(); this.is=is; try { byte[] data = new byte[20480]; int len = is.read(data); requestInfo = new String(data, 0, len); } catch (Exception e) { return ; } //分析請求信息 parseRequestInfo(); } /** * 分析請求信息 */ private void parseRequestInfo(){ if(null==requestInfo ||(requestInfo=requestInfo.trim()).equals("")){ return ; } /** * ===================================== * 從信息的首行分解出 :請求方式 請求路徑 請求參數(get可能存在) * 如:GET /index.html?name=123&pwd=5456 HTTP/1.1 * * 若是爲post方式,請求參數可能在 最後正文中 * * 思路: * 1)請求方式 :找出第一個/ 截取便可 * 2)請求資源:找出第一個/ HTTP/ * ===================================== */ String paramString =""; //接收請求參數 //一、獲取請求方式 String firstLine =requestInfo.substring(0,requestInfo.indexOf(CRLF)); int idx =requestInfo.indexOf("/"); // /的位置 this.method=firstLine.substring(0, idx).trim(); String urlStr =firstLine.substring(idx,firstLine.indexOf("HTTP/")).trim(); if(this.method.equalsIgnoreCase("post")){ this.url=urlStr; paramString=requestInfo.substring(requestInfo.lastIndexOf(CRLF)).trim(); }else if(this.method.equalsIgnoreCase("get")){ if(urlStr.contains("?")){ //是否存在參數 String[] urlArray=urlStr.split("\\?"); this.url=urlArray[0]; paramString=urlArray[1];//接收請求參數 }else{ this.url=urlStr; } } //不存在請求參數 if(paramString.equals("")){ return ; } //二、將請求參數封裝到Map中 parseParams(paramString); } private void parseParams(String paramString){ //分割 將字符串轉成數組 StringTokenizer token=new StringTokenizer(paramString,"&"); while(token.hasMoreTokens()){ String keyValue =token.nextToken(); String[] keyValues=keyValue.split("="); if(keyValues.length==1){ keyValues =Arrays.copyOf(keyValues, 2); keyValues[1] =null; } String key = keyValues[0].trim(); String value = null==keyValues[1]?null:decode(keyValues[1].trim(),"gbk"); //轉換成Map 分揀 if(!parameterMapValues.containsKey(key)){ parameterMapValues.put(key,new ArrayList<String>()); } List<String> values =parameterMapValues.get(key); values.add(value); } } /** * 解決中文 * @param value * @param code * @return */ private String decode(String value,String code){ try { return java.net.URLDecoder.decode(value, code); } catch (UnsupportedEncodingException e) { //e.printStackTrace(); } return null; } /** * 根據頁面的name 獲取對應的多個值 * @param args */ public String[] getParameterValues(String name){ List<String> values=null; if((values=parameterMapValues.get(name))==null){ return null; }else{ return values.toArray(new String[0]); } } /** * 根據頁面的name 獲取對應的單個值 * @param args */ public String getParameter(String name){ String[] values =getParameterValues(name); if(null==values){ return null; } return values[0]; } public String getUrl() { return url; } public void close(){ CloseUtil.closeIO(is); } }
package com.zwj.server; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.Socket; import java.util.Date; import com.zwj.util.CloseUtil; /** * 封裝響應信息 * @author Administrator * */ public class Response { //兩個常量 public static final String CRLF="\r\n"; public static final String BLANK=" "; //流 private BufferedWriter bw ; //正文 private StringBuilder content; //存儲頭信息 private StringBuilder headInfo; //存儲正文長度 private int len =0; public Response(){ headInfo =new StringBuilder(); content =new StringBuilder(); len =0; } public Response(Socket client){ this(); try { bw= new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); } catch (IOException e) { headInfo=null; } } public Response(OutputStream os){ this(); bw= new BufferedWriter(new OutputStreamWriter(os)); } /** * 構建正文 */ public Response print(String info){ content.append(info); len+=info.getBytes().length; return this; } /** * 構建正文+回車 */ public Response println(String info){ content.append(info).append(CRLF); len+=(info+CRLF).getBytes().length; return this; } /** * 構建響應頭 */ private void createHeadInfo(int code){ //1) HTTP協議版本、狀態代碼、描述 headInfo.append("HTTP/1.1").append(BLANK).append(code).append(BLANK); switch(code){ case 200: headInfo.append("OK"); break; case 404: headInfo.append("NOT FOUND"); break; case 505: headInfo.append("SEVER ERROR"); break; } headInfo.append(CRLF); //2) 響應頭(Response Head) headInfo.append("Server:bjsxt Server/0.0.1").append(CRLF); headInfo.append("Date:").append(new Date()).append(CRLF); headInfo.append("Content-type:text/html;charset=GBK").append(CRLF); //正文長度 :字節長度 headInfo.append("Content-Length:").append(len).append(CRLF); headInfo.append(CRLF); //分隔符 } //推送到客戶端 void pushToClient(int code) throws IOException{ if(null==headInfo){ code =500; } createHeadInfo(code); //頭信息+分割符 bw.append(headInfo.toString()); //正文 bw.append(content.toString()); bw.flush(); } public void close(){ CloseUtil.closeIO(bw); } }
package com.zwj.server; import java.io.IOException; import java.net.ServerSocket; import com.zwj.util.CloseUtil; /** * 建立服務器,並啓動 * * 一、請求 * 二、響應 * @author Administrator * java 世界裏能夠不手寫的儘可能用配置,能用約定的就不用配置, 約定>配置>手寫 */ public class Server { private ServerSocket server; public static final String CRLF="\r\n"; public static final String BLANK=" "; private boolean isShutDown= false; /** * @param args */ public static void main(String[] args) { Server server = new Server(); server.start(); } /** * 啓動方法 */ public void start(){ start(8888); } /** * 指定端口的啓動方法 */ public void start(int port){ try { server = new ServerSocket(port); this.receive(); } catch (IOException e) { //e.printStackTrace(); stop(); } } /** * 接收客戶端 */ private void receive(){ try { while(!isShutDown){ new Thread(new Dispatcher(server.accept())).start(); } } catch (IOException e) { //e.printStackTrace(); stop(); } } /** * 中止服務器 */ public void stop(){ isShutDown=true; CloseUtil.closeSocket(server); } }
package com.zwj.server; import java.util.HashMap; import java.util.Map; /** * 上下文 * @author Administrator * */ public class ServletContext { //爲每個servlet取個別名 // login -->com.bjsxt.server.demo03.LoginServlet private Map<String,String> servlet ; //url -->login // /log -->login // /login -->login private Map<String,String> mapping; ServletContext(){ servlet =new HashMap<String,String>(); mapping =new HashMap<String,String>(); } public Map<String, String> getServlet() { return servlet; } public void setServlet(Map<String, String> servlet) { this.servlet = servlet; } public Map<String, String> getMapping() { return mapping; } public void setMapping(Map<String, String> mapping) { this.mapping = mapping; } }
package com.zwj.server; import java.util.List; import java.util.Map; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import com.zwj.servlet.Servlet; public class WebApp { private static ServletContext contxt; static{ try { //獲取解析工廠 SAXParserFactory factory = SAXParserFactory.newInstance(); //獲取解析器 SAXParser sax = factory.newSAXParser(); //指定xml+處理器 WebHandler web = new WebHandler(); sax.parse(Thread.currentThread().getContextClassLoader() .getResourceAsStream("WEB_INFO/web.xml"), web); //將list 轉成Map contxt =new ServletContext(); Map<String,String> servlet =contxt.getServlet(); //servlet-name servlet-class for(Entity entity:web.getEntityList()){ servlet.put(entity.getName(), entity.getClz()); } //url-pattern servlet-name Map<String,String> mapping =contxt.getMapping(); for(Mapping mapp:web.getMappingList()){ List<String> urls =mapp.getUrlPattern(); for(String url:urls ){ mapping.put(url, mapp.getName()); } } } catch (Exception e) { } } public static Servlet getServlet(String url) throws InstantiationException, IllegalAccessException, ClassNotFoundException{ if((null==url)||(url=url.trim()).equals("")){ return null; } //根據字符串(完整路徑)建立對象 //return contxt.getServlet().get(contxt.getMapping().get(url)); String name=contxt.getServlet().get(contxt.getMapping().get(url)); return (Servlet)Class.forName(name).newInstance();//確保空構造存在 } }
package com.zwj.server; import java.util.ArrayList; import java.util.List; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class WebHandler extends DefaultHandler{ private List<Entity> entityList; private List<Mapping> mappingList; private Entity entity; private Mapping mapping; private String beginTag ; private boolean isMap; @Override public void startDocument() throws SAXException { //文檔解析開始 entityList =new ArrayList<Entity>() ; mappingList =new ArrayList<Mapping>() ; } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { //開始元素 if(null!=qName){ beginTag=qName; if(qName.equals("servlet")){ isMap=false; entity=new Entity(); }else if(qName.equals("servlet-mapping")){ isMap=true; mapping=new Mapping(); } } } @Override public void characters(char[] ch, int start, int length) throws SAXException { //處理內容 if(null!=beginTag){ String str =new String(ch,start,length); if(isMap ){ if(beginTag.equals("servlet-name")){ mapping.setName(str); }else if(beginTag.equals("url-pattern")){ mapping.getUrlPattern().add(str); } }else{ if(beginTag.equals("servlet-name")){ entity.setName(str); }else if(beginTag.equals("servlet-class")){ entity.setClz(str); } } } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { //結束元素 if(null!=qName){ if(qName.equals("servlet")){ entityList.add(entity); }else if(qName.equals("servlet-mapping")){ mappingList.add(mapping); } } beginTag=null; } @Override public void endDocument() throws SAXException { //文檔解析結束 } /*public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException { //獲取解析工廠 SAXParserFactory factory =SAXParserFactory.newInstance(); //獲取解析器 SAXParser sax =factory.newSAXParser(); //指定xml+處理器 WebHandler web = new WebHandler(); sax.parse(Thread.currentThread().getContextClassLoader() .getResourceAsStream("com/bjsxt/server/demo4/web.xml") ,web); System.out.println(web.getEntityList()); }*/ public List<Entity> getEntityList() { return entityList; } public void setEntityList(List<Entity> entityList) { this.entityList = entityList; } public List<Mapping> getMappingList() { return mappingList; } public void setMappingList(List<Mapping> mappingList) { this.mappingList = mappingList; } }
package com.zwj.servlet; import com.zwj.server.Request; import com.zwj.server.Response; public class LoginWeb extends Servlet { @Override public void doGet(Request req, Response rep) throws Exception { rep.println("success....."); } @Override public void doPost(Request req, Response rep) throws Exception { // TODO Auto-generated method stub } }
package com.zwj.servlet; import com.zwj.server.Request; import com.zwj.server.Response; /** * 抽象爲一個父類 * @author Administrator * */ public abstract class Servlet { public void service(Request req,Response rep) throws Exception{ this.doGet(req,rep); this.doPost(req,rep); } protected abstract void doGet(Request req,Response rep) throws Exception; protected abstract void doPost(Request req,Response rep) throws Exception; }
package com.zwj.util; import java.io.Closeable; import java.net.DatagramSocket; import java.net.ServerSocket; import java.net.Socket; public class CloseUtil { /** * 關閉IO流 */ /* public static void closeIO(Closeable... io){ for(Closeable temp:io){ try { if (null != temp) { temp.close(); } } catch (Exception e) { } } }*/ /** * 使用泛型方法實現關閉IO流 * @param io */ public static <T extends Closeable> void closeIO(T... io){ for(Closeable temp:io){ try { if (null != temp) { temp.close(); } } catch (Exception e) { } } } public static void closeSocket(ServerSocket socket){ try { if (null != socket) { socket.close(); } } catch (Exception e) { } } public static void closeSocket(Socket socket){ try { if (null != socket) { socket.close(); } } catch (Exception e) { } } public static void closeSocket(DatagramSocket socket){ try { if (null != socket) { socket.close(); } } catch (Exception e) { } } }
<?xml version="1.0" encoding="UTF-8"?> <web-app> <servlet> <servlet-name>login</servlet-name> <servlet-class>com.zwj.servlet.LoginWeb</servlet-class> </servlet> <servlet-mapping> <servlet-name>login</servlet-name> <url-pattern>/g</url-pattern> <url-pattern>/y</url-pattern> </servlet-mapping> </web-app>