目的: 网络编程在编程领域随处可见,本文尝试手写一个简单的 准备知识: 先说下大致流程: 注意:光理论是不够的,在此送大家十套2020最新Java架构实战教程+大厂面试题库,进裙: 783802103 在裙文件下载一起交流进步哦 XML文件解析的方式有多种,本文以 xml文件中 解析xml文件代码: 对解析结果优化映射服务: 上面只是个简易版的Tomcat雏型,可大致了解到Tomcat的流程,Tomcat无非就是 在基础版本上添加了各种Servlet,Request,Response,Session,Cookie,ServletContext,ServletConfig,EL,JSTL,Filter,Listener,JSP等这些东西,有空再写两章Tomcat源码底层的东西。前言
HttpServer
,了解网络请求后台的大致思路及为学习Tomcat打好基础。
思路
流程图:
代码结构
代码实现
1. XML解析
SAXException
来解析。xml文件信息
<?xml version="1.0" encoding="UTF-8"?> <web-app> <servlet> <servlet-name>login</servlet-name> <servlet-class>com.sowhat.user.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>login</servlet-name> <url-pattern>/login</url-pattern> </servlet-mapping> <servlet> <servlet-name>reg</servlet-name> <servlet-class>com.sowhat.user.RegisterServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>reg</servlet-name> <url-pattern>/r</url-pattern> </servlet-mapping> </web-app>
Servlet类
servlet
体对应的Java类package com.sowhat.server.core; /** * 功能:servlet 映射 <servlet> <servlet-name>login</servlet-name> <servlet-class>com.shsxt.LoginServlet</servlet-class> </servlet> */ public class Entity { private String name; private String clz; public Entity() { // TODO Auto-generated constructor stub } 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; } }
Servlet-mapping类
servlet-mapping
对应的Java类package com.sowhat.server.core; import java.util.HashSet; import java.util.Set; /** * 功能: 请求网址对应的 servlet <servlet-mapping> <servlet-name>login</servlet-name> <url-pattern>/login</url-pattern> <url-pattern>/g</url-pattern> </servlet-mapping> * */ public class Mapping { private String name; private Set<String> patterns ; public Mapping() { patterns = new HashSet<String>(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<String> getPatterns() { return patterns; } public void setPatterns(Set<String> patterns) { this.patterns = patterns; } public void addPattern(String pattern) { this.patterns.add(pattern); } }
WebHandler
WebHandler
package com.sowhat.server.core; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import java.util.ArrayList; import java.util.List; /** * 解析XML文件的 处理器 */ public class WebHandler extends DefaultHandler { private List<Entity> entitys = new ArrayList<Entity>(); private List<Mapping> mappings = new ArrayList<Mapping>(); private Entity entity; private Mapping mapping; private String tag; //存储操作标签 private boolean isMapping = false; @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if (null != qName) { tag = qName; //存储标签名 if (tag.equals("servlet")) { entity = new Entity(); isMapping = false; } else if (tag.equals("servlet-mapping")) { mapping = new Mapping(); isMapping = true; } } } @Override public void characters(char[] ch, int start, int length) throws SAXException { String contents = new String(ch, start, length).trim(); if (null != tag) { //处理了空 if (isMapping) { //操作servlet-mapping if (tag.equals("servlet-name")) { mapping.setName(contents); } else if (tag.equals("url-pattern")) { mapping.addPattern(contents); } } else { //操作servlet if (tag.equals("servlet-name")) { entity.setName(contents); } else if (tag.equals("servlet-class")) { entity.setClz(contents); } } } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if (null != qName) { if (qName.equals("servlet")) { entitys.add(entity); } else if (qName.equals("servlet-mapping")) { mappings.add(mapping); } } tag = null; //tag丢弃了 } public List<Entity> getEntitys() { return entitys; } public List<Mapping> getMappings() { return mappings; } }
WebContext
WebContext
package com.sowhat.server.core; import java.util.HashMap; import java.util.List; import java.util.Map; /*** * 功能: 解析XML结果 HTTP网页请求跟 对应Java代码中哪个类来处理 * 目的: 对XML解析后,以后输入一个请求的网址 就可以返回对应的处理类 */ public class WebContext { private List<Entity> entitys = null; private List<Mapping> mappings = null; //key-->servlet-name value -->servlet-class private Map<String, String> entityMap = new HashMap<String, String>(); //key -->url-pattern value -->servlet-name private Map<String, String> mappingMap = new HashMap<String, String>(); public WebContext(List<Entity> entitys, List<Mapping> mappings) { this.entitys = entitys; this.mappings = mappings; //将entity 的List转成了对应map for (Entity entity : entitys) { entityMap.put(entity.getName(), entity.getClz()); } //将map 的List转成了对应map for (Mapping mapping : mappings) { for (String pattern : mapping.getPatterns()) { mappingMap.put(pattern, mapping.getName()); } } } /** * 通过URL的路径找到了对应class */ public String getClz(String pattern) { String name = mappingMap.get(pattern); return entityMap.get(name); } }
WebApp
package com.sowhat.server.core; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; /** * 统筹 WebContext 跟 WebHandler * */ public class WebApp { private static WebContext webContext; static { try { //SAX解析 //1、获取解析工厂 SAXParserFactory factory = SAXParserFactory.newInstance(); //2、从解析工厂获取解析器 SAXParser parse = factory.newSAXParser(); //3、编写处理器 //4、加载文档 Document 注册处理器 WebHandler handler = new WebHandler(); //5、解析 parse.parse(Thread.currentThread().getContextClassLoader().getResourceAsStream("web.xml"), handler); //获取数据 webContext = new WebContext(handler.getEntitys(), handler.getMappings()); } catch (Exception e) { System.out.println("解析配置文件错误"); } } /** * 通过url获取配置文件对应的servlet * @param url * @return */ public static Servlet getServletFromUrl(String url) { //假设你输入了 /login String className = webContext.getClz("/" + url); Class clz; try { clz = Class.forName(className); Servlet servlet = (Servlet) clz.getConstructor().newInstance(); return servlet; } catch (Exception e) { } return null; } }
2. Request Response
Request 解析
package com.sowhat.server.core; import org.apache.commons.io.IOUtils; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.Socket; import java.util.*; /** * 封装请求协议: 封装请求参数为Map */ public class Request { //协议信息 private String requestInfo; //请求方式 private String method; //请求url private String url; //请求参数 private String queryStr; //存储参数 private Map<String, List<String>> parameterMap; private final String CRLF = "rn"; public Request(Socket client) throws IOException { this(client.getInputStream()); System.out.println("request 构造函数"); } public Request(InputStream is) { parameterMap = new HashMap<String, List<String>>(); byte[] datas = new byte[1024*1024]; int len; try { len = is.read(datas); this.requestInfo = new String(datas,0,len); } catch (IOException e) { e.printStackTrace(); return; } //分解字符串 parseRequestInfo(); } //分解字符串 private void parseRequestInfo() { this.method = this.requestInfo.substring(0, this.requestInfo.indexOf("/")).toLowerCase(); this.method = this.method.trim(); //1)、获取/的位置 int startIdx = this.requestInfo.indexOf("/") + 1; //2)、获取 HTTP/的位置 int endIdx = this.requestInfo.indexOf("HTTP/"); //3)、分割字符串 this.url = this.requestInfo.substring(startIdx, endIdx).trim(); //4)、获取?的位置 int queryIdx = this.url.indexOf("?"); if (queryIdx >= 0) {//表示存在请求参数 String[] urlArray = this.url.split("\?"); this.url = urlArray[0]; queryStr = urlArray[1]; } System.out.println(this.url); if (method.equals("post")) { String qStr = this.requestInfo.substring(this.requestInfo.lastIndexOf(CRLF)).trim(); System.out.println(qStr + "-->"); if (null == queryStr) { queryStr = qStr; } else { queryStr += "&" + qStr; } } queryStr = null == queryStr ? "" : queryStr; System.out.println(method + "-->" + url + "-->" + queryStr); //转成Map fav=1&fav=2&uname=sowhat&age=18&others= convertMap(); } //处理请求参数为Map private void convertMap() { //1、分割字符串 & String[] keyValues = this.queryStr.split("&"); for (String queryStr : keyValues) { //2、再次分割字符串 = String[] kv = queryStr.split("="); kv = Arrays.copyOf(kv, 2); //获取key和value String key = kv[0]; String value = kv[1] == null ? null : decode(kv[1], "utf-8"); //存储到map中 if (!parameterMap.containsKey(key)) { //第一次 parameterMap.put(key, new ArrayList<String>()); } parameterMap.get(key).add(value); } } private String decode(String value, String enc) { try { return java.net.URLDecoder.decode(value, enc); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } public String[] getParameterValues(String key) { List<String> values = this.parameterMap.get(key); if (null == values || values.size() < 1) { return null; } return values.toArray(new String[0]); } public String getParameter(String key) { String[] values = getParameterValues(key); return values == null ? null : values[0]; } public String getMethod() { return method; } public String getUrl() { return url; } public String getQueryStr() { return queryStr; } }
Response 解析
package com.sowhat.server.core; 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 { private BufferedWriter bw; //正文 private StringBuilder content; //协议头(状态行与请求头 回车)信息 private StringBuilder headInfo; private int len; //正文的字节数 private final String BLANK =" "; private final String CRLF = "rn"; private Response() { content =new StringBuilder(); headInfo=new StringBuilder(); len =0; } public Response(Socket client) { this(); try { bw=new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); } catch (IOException e) { e.printStackTrace(); 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; } // 推送响应信息 public void pushToBrowser(int code) throws IOException { if(null ==headInfo) { code = 505; } createHeadInfo(code); bw.append(headInfo); bw.append(content); bw.flush(); } // 构建头信息 private void createHeadInfo(int code) { //1、响应行: HTTP/1.1 200 OK headInfo.append("HTTP/1.1").append(BLANK); headInfo.append(code).append(BLANK); switch(code) { case 200: headInfo.append("OK").append(CRLF); break; case 404: headInfo.append("NOT FOUND").append(CRLF); break; case 505: headInfo.append("SERVER ERROR").append(CRLF); break; } //2、响应头(最后一行存在空行): headInfo.append("Date:").append(new Date()).append(CRLF); headInfo.append("Server:").append("shsxt Server/0.0.1;charset=GBK").append(CRLF); headInfo.append("Content-type:text/html").append(CRLF); headInfo.append("Content-length:").append(len).append(CRLF); headInfo.append(CRLF); } }
3. Servlet
Servlet接口
package com.sowhat.server.core; /** * 服务器小脚本接口 */ public interface Servlet { void service(Request request, Response response); }
LoginServlet
package com.sowhat.server.user; import com.sowhat.server.core.Request; import com.sowhat.server.core.Response; import com.sowhat.server.core.Servlet; public class LoginServlet implements Servlet { @Override public void service(Request request, Response response) { response.print("<html>"); response.print("<head>"); response.print("<meta http-equiv="content-type" content="text/html;charset=utf-8">"); response.print("<title>"); response.print("第一个servlet"); response.print("</title>"); response.print("</head>"); response.print("<body>"); response.print("欢迎回来:" + request.getParameter("uname")); response.print("</body>"); response.print("</html>"); } }
RegisterServlet
package com.sowhat.server.user; import com.sowhat.server.core.Request; import com.sowhat.server.core.Response; import com.sowhat.server.core.Servlet; public class RegisterServlet implements Servlet { @Override public void service(Request request, Response response) { //关注业务逻辑 String uname = request.getParameter("uname"); String[] favs = request.getParameterValues("fav"); response.print("<html>"); response.print("<head>"); response.print("<meta http-equiv="content-type" content="text/html;charset=utf-8">"); response.print("<title>"); response.print("注册成功"); response.print("</title>"); response.print("</head>"); response.print("<body>"); response.println("你注册的信息为:" + uname); response.println("你喜欢的类型为:"); for (String v : favs) { if (v.equals("0")) { response.print("萝莉型"); } else if (v.equals("1")) { response.print("豪放型"); } else if (v.equals("2")) { response.print("经济节约型"); } } response.print("</body>"); response.print("</html>"); } }
package com.sowhat.server.core; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; /** * 统筹 WebContext 跟 WebHandler * */ public class WebApp { private static WebContext webContext; static { try { //SAX解析 //1、获取解析工厂 SAXParserFactory factory = SAXParserFactory.newInstance(); //2、从解析工厂获取解析器 SAXParser parse = factory.newSAXParser(); //3、编写处理器 //4、加载文档 Document 注册处理器 WebHandler handler = new WebHandler(); //5、解析 parse.parse(Thread.currentThread().getContextClassLoader().getResourceAsStream("web.xml"), handler); //获取数据 webContext = new WebContext(handler.getEntitys(), handler.getMappings()); } catch (Exception e) { System.out.println("解析配置文件错误"); } } /** * 通过url获取配置文件对应的servlet * @param url * @return */ public static Servlet getServletFromUrl(String url) { //假设你输入了 /login String className = webContext.getClz("/" + url); Class clz; try { System.out.println(url + "-->" + className + "-->"); clz = Class.forName(className); Servlet servlet = (Servlet) clz.getConstructor().newInstance(); return servlet; } catch (Exception e) { } return null; } }
开启服务
package com.sowhat.server.core; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; /** * 开启一个服务仅此而已 */ public class Server { private ServerSocket serverSocket; private boolean isRunning; public static void main(String[] args) { Server server = new Server(); server.start(); } //启动服务 public void start() { try { serverSocket = new ServerSocket(8888); isRunning = true; receive(); } catch (IOException e) { e.printStackTrace(); System.out.println("服务器启动失败...."); stop(); } } //接受连接处理 public void receive() { while (isRunning) { try { Socket client = serverSocket.accept(); System.out.println("一个客户端建立了连接...."); //多线程处理 new Thread(new Dispatcher(client)).start(); // 此处是 一个服务入口 重点 } catch (IOException e) { e.printStackTrace(); System.out.println("客户端错误"); } } } //停止服务 public void stop() { isRunning = false; try { this.serverSocket.close(); System.out.println("服务器已停止"); } catch (IOException e) { e.printStackTrace(); } } }
HTML
Error.HTML
<html> <head> <meta http-equiv="content-type" content="text/html;charset=utf-8"> <title>404页面</title> </head> <body> <h1>404错误</h1> </body> </html>
index.html
<html> <head> <meta http-equiv="content-type" content="text/html;charset=utf-8"> <title>首页</title> </head> <body> <h1>欢迎使用服务器简易版哈哈</h1> </body> </html>
demo
注意:光理论是不够的,在此送大家十套2020最新Java架构实战教程+大厂面试题库,进裙: 783802103 在裙文件下载一起交流进步哦 延伸
参考
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算