java21 封装Response:
封装Response: /** * 封装响应信息 */ 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); } } 测试: /** * 创建服务器,并启动 * 1、请求 * 2、响应 */ public class Server4 { private ServerSocket server; public static final String CRLF="\r\n"; public static final String BLANK=" "; 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(){ } } 封装Request: /** * 封装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[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 =""; //接收请求参数 //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")){ 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 ; } //2、将请求参数封装到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; } } 测试: /** * 创建服务器,并启动 * 1、请求 * 2、响应 */ public class Server5 { private ServerSocket server; public static final String CRLF="\r\n"; public static final String BLANK=" "; public static void main(String[] args) { Server5 server = new Server5(); 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(); //请求 Request req=new Request(client.getInputStream()); //响应 Response rep=new Response(client.getOutputStream()); rep.println("<html><head><title>HTTP响应示例</title>"); rep.println("</head><body>"); rep.println("欢迎:").println(req.getParameter("uname")).println("回来"); rep.println("</body></html>"); rep.pushToClient(200); } catch (IOException e) { } } /** * 停止服务器 */ public void stop(){ } } 加入Servlet: 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>"); } } /** * 接收客户端 */ private void receive(){ try { Socket client =server.accept(); Servlet serv =new Servlet(); Request req =new Request(client.getInputStream()); Response rep =new Response(client.getOutputStream()); serv.service(req,rep); rep.pushToClient(200); //通过流写出去 } catch (IOException e) { } } 服务端利用多线程: /** * 创建服务器,并启动 * 1、请求 * 2、响应 */ public class Server7 { private ServerSocket server; public static final String CRLF="\r\n"; public static final String BLANK=" "; private boolean isShutDown= false; 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();//启动出错则stop。 } } /** * 接收客户端 */ private void receive(){ try { while(!isShutDown){ new Thread(new Dispatcher(server.accept())).start(); } } catch (IOException e) { stop(); } } /** * 停止服务器 */ public void stop(){ isShutDown=true; CloseUtil.closeSocket(server); } } /** * 一个请求与响应 就一个此对象 */ 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) { code =500;//统一到推送地方去推送。 return ; } } @Override public void run() { Servlet serv =new Servlet(); serv.service(req,rep); try { rep.pushToClient(code); //流推送到客户端 } catch (IOException e) { } try { rep.pushToClient(500); } catch (IOException e) { e.printStackTrace(); } CloseUtil.closeSocket(client); } } 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) { } } }