手写服务器httpserver_封装分发器_多请求处理_多态_反射JAVA202-204
2016-03-22 23:04
786 查看
来源:http://www.bjsxt.com/
一、S02E202_01手写服务器httpserver_封装分发器
二、S02E203_01手写服务器httpserver_多请求处理_多态
三、S02E204_01手写服务器httpserver_多请求处理_反射
一、S02E202_01手写服务器httpserver_封装分发器
<html> <head> <title>第一个表单</title> </head> <body> <pre> method:请求方式 get/post get:默认方式,数据量小,安全性不高 post:量大,安全性相对高 action:请求的服务器路径 id:编号,前端(用户的浏览器)区分唯一性,js中使用 name:名称,后端(服务器)区分唯一性,获取值 只要提交数据给后台,必须存在name </pre> <form method="post" action="http://localhost:8888/index.html"> 用户名:<input type="text" name="uname" id="name"/> 密码:<input type="password" name="pwd" id="pass"/> 兴趣:<input type="checkbox" name="fav" value="0"/>篮球 <input type="checkbox" name="fav" value="1"/>足球 <input type="checkbox" name="fav" value="2"/>乒乓球 <input type="submit" value="登录"> </form> </body> </html>
package com.test.server; 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.getParameterValue("uname")).println("回来"); rep.println("</body></html>"); } }
package com.test.server; import java.io.IOException; import java.net.Socket; /** * 一个请求与响应,就一个对象 */ 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; try { rep.pushToClient(code); } catch (IOException e1) { //e1.printStackTrace(); } 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 e1) { e1.printStackTrace(); } } try { client.close(); } catch (IOException e) { e.printStackTrace(); } } }
package com.test.server; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; /** * 创建服务器,并启动 * 1、请求 * 2、响应 */ public class ServerForResAndReq2 { private ServerSocket server; private boolean isShutDown = false; public static void main(String[] args) { ServerForResAndReq2 server = new ServerForResAndReq2(); 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; try { server.close(); } catch (IOException e) { e.printStackTrace(); } } }
二、S02E203_01手写服务器httpserver_多请求处理_多态
package com.test.server2; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; /** * 创建服务器,并启动 * 1、请求 * 2、响应 */ public class Server { private ServerSocket server; private boolean isShutDown = false; 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; try { if(!(null==server)){ server.close(); } } catch (IOException e) { //e.printStackTrace(); } } }
package com.test.server2; import java.io.IOException; import java.net.Socket; /** * 一个请求与响应,就一个对象 */ 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; try { rep.pushToClient(code); } catch (IOException e1) { //e1.printStackTrace(); } 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(code); } catch (IOException e1) { e1.printStackTrace(); } } try { client.close(); } catch (IOException e) { //e.printStackTrace(); } } }
package com.test.server2; import java.io.IOException; 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 */ 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[204800]; int len = is.read(data); requestInfo = new String(data,0,len); } catch (IOException e) { return; } //分析请求信息 parseRequestInfo(); } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } /** * 分析请求信息 */ private void parseRequestInfo(){ if((null==requestInfo) || (requestInfo=requestInfo.trim()).equals("")){ return; } /** * ==================================== * 从信息的首行分解出:请求方式 请求路径 请求参数(get可能存在) * 如:GET /index.html?uname=intputUname&pwd=inputPassword HTTP/1.1 * * 如果为post方式,请求参数可能在最后正文中 * ==================================== */ String paramString = "";//接收请求参数 int positionCRLF = 0; positionCRLF = requestInfo.indexOf(CRLF); if (positionCRLF == -1){ return; } //1、获取请求方式 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")){//post方式 this.url = urlStr; paramString = requestInfo.substring(requestInfo.lastIndexOf(CRLF)).trim(); }else if(this.method.equalsIgnoreCase("get")){//get方式 if(urlStr.contains("?")){ String[] urlArray = urlStr.split("\\?"); this.url = urlArray[0]; paramString = urlArray[1];//接收请求参数 }else{ this.url = urlStr; } } //2、将请求参数封装到Map中 parseParams(paramString); } /** * 将请求参数封装到Map中 * @param 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获取对应的多个值 */ 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获取对应的单个值 */ public String getParameterValue(String name){ String[] values = getParameterValues(name); if(null==values){ return null; } return values[0]; } }
package com.test.server2; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.Socket; import java.util.Date; /** * 封装响应信息 */ 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(OutputStream os){ this(); bw = new BufferedWriter(new OutputStreamWriter(os)); } public Response(Socket client){ this(); try { bw = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); } catch (IOException e) { headInfo = null; } } /** * 构建正文 */ public Response print(String info){ content.append(info); len += (info + CRLF).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 500: headInfo.append("Server Error"); break; } headInfo.append(CRLF); //2)响应头(Response Head) headInfo.append("Server:test 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); } /** * 推送到客户端 * @throws IOException */ void pushToClient(int code) throws IOException{ if(null==headInfo){ code = 500; } createHeadInfo(code); //头信息+分割符 bw.append(headInfo.toString()); //正文 bw.append(content.toString()); bw.flush(); bw.close(); } }
package com.test.server2; import java.util.Map; public class WebApp { private static ServletContext contxt; static{ contxt = new ServletContext(); Map<String,String> mapping = contxt.getMapping(); mapping.put("/login", "login"); mapping.put("/log", "login"); mapping.put("/reg", "register"); Map<String,Servlet> servlet = contxt.getServlet(); servlet.put("login", new LoginServlet()); servlet.put("register", new RegisterServlet()); } public static Servlet getServlet(String url){ if(null==url || (url=url.trim()).equals("")){ return null; } return contxt.getServlet().get(contxt.getMapping().get(url)); } }
package com.test.server2; /** * 抽象为一个父类 */ public abstract class Servlet { public void service(Request req,Response rep) throws Exception{ this.doGet(req,rep); this.doPost(req,rep); } public abstract void doGet(Request req,Response rep) throws Exception; public abstract void doPost(Request req,Response rep) throws Exception; }
package com.test.server2; import java.util.HashMap; import java.util.Map; /** * 上下文 */ public class ServletContext { //为每一个servlet取别名 // login-->LoginServlet private Map<String,Servlet> servlet; // url-->login // /log-->login // /login-->login private Map<String,String> mapping; public ServletContext() { servlet = new HashMap<String,Servlet>(); mapping = new HashMap<String,String>(); } public Map<String, Servlet> getServlet() { return servlet; } public void setServlet(Map<String, Servlet> servlet) { this.servlet = servlet; } public Map<String, String> getMapping() { return mapping; } public void setMapping(Map<String, String> mapping) { this.mapping = mapping; } }
package com.test.server2; public class LoginServlet extends Servlet{ @Override public void doGet(Request req,Response rep) throws Exception { String name = req.getParameterValue("uname"); String pwd = req.getParameterValue("pwd"); if(login(name, pwd)){ rep.println("登录成功"); }else{ rep.println("登录失败"); } } public boolean login(String name,String pwd){ return name.equals("test") && pwd.equals("12346"); } @Override public void doPost(Request req,Response rep) throws Exception { } }
package com.test.server2; public class RegisterServlet extends Servlet{ @Override public void doGet(Request req, Response rep) throws Exception { } @Override public void doPost(Request req, Response rep) throws Exception { rep.println("<html><head><title>返回注册</title>"); rep.println("</head><body>"); rep.println("你的用户名为:" + req.getParameterValue("uname")); rep.println("</body></html>"); } }
三、S02E204_01手写服务器httpserver_多请求处理_反射
**以下代码关键性修改:** Map<String,Servlet>改为Map<String,String>
package com.test.server2; import java.util.HashMap; import java.util.Map; /** * 上下文 */ public class ServletContext { //为每一个servlet取别名 // login-->com.test.server2.LoginServlet private Map<String,String> servlet; // url-->login // /log-->login // /login-->login private Map<String,String> mapping; public 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; } }
**以下代码关键性修改:** //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.test.server2; import java.util.Map; public class WebApp { private static ServletContext contxt; static{ contxt = new ServletContext(); Map<String,String> mapping = contxt.getMapping(); mapping.put("/login", "login"); mapping.put("/log", "login"); mapping.put("/reg", "register"); Map<String,String> servlet = contxt.getServlet(); servlet.put("login", "com.test.server2.LoginServlet"); servlet.put("register", "com.test.server2.RegisterServlet"); } 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();//确保空构造存在 } }
相关文章推荐
- 多达 95% 的 HTTPS 链接能被黑客劫持
- 网络基本功(1)--网络传输
- Android Http简单使用实现登录校园网App
- 多播(组播)
- 多播 、IP_ADD_MEMBERSHIP 、IP_MULTICAST_IF
- Java获取网络时间
- Linux C 网络编程——多线程的聊天室实现(服务器端)
- 最简单的基于Flash的流媒体示例:网页播放器(HTTP,RTMP,HLS)
- HTTP学习笔记:HTTP报文
- HTTP学习笔记:URL与资源
- HTTP权威指南学习笔记:连接管理
- Linux网络基础命令
- [疯狂Java]网络:GET/POST请求、设置请求属性、获取响应属性
- 3.19Java基础知识:Socket编程全部,TCPIP
- RHCE7 搭建SAMBA服务实现目录网络共享
- Android网络编程之解析XML格式数据
- [TCPIP]代理arp
- 特殊的HttpApplication事件处理
- Linux-进程间通信(五): 网络套接字
- loadrunner简单使用——HTTP,WebService,Socket压力测试脚本编写