├── static ├── idea.jpeg ├── banner.swf ├── estate.gif ├── 404.html └── news.css ├── out └── production │ └── MyTomCat │ ├── User.class │ ├── Login.class │ ├── servlet │ ├── Cookie.class │ ├── Servlet.class │ ├── HttpServlet.class │ ├── HttpSession.class │ ├── ServletContext.class │ ├── HttpServletRequest.class │ └── HttpServletResponse.class │ └── server │ ├── MyTomcat.class │ ├── Processor.class │ ├── ServerService.class │ ├── DynamicProcessor.class │ └── StaticProcessor.class ├── .idea ├── description.html ├── encodings.xml ├── vcs.xml ├── modules.xml ├── misc.xml ├── compiler.xml ├── inspectionProfiles │ └── Project_Default.xml ├── junitgenerator-prj-settings.xml ├── uiDesigner.xml └── workspace.xml ├── README.md ├── src ├── servlet │ ├── Servlet.java │ ├── ServletContext.java │ ├── HttpSession.java │ ├── HttpServlet.java │ ├── Cookie.java │ ├── HttpServletResponse.java │ └── HttpServletRequest.java ├── server │ ├── Processor.java │ ├── StaticProcessor.java │ ├── MyTomcat.java │ ├── DynamicProcessor.java │ └── ServerService.java ├── User.java └── Login.java └── MyTomCat.iml /static/idea.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itudo/MyTomcat/HEAD/static/idea.jpeg -------------------------------------------------------------------------------- /static/banner.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itudo/MyTomcat/HEAD/static/banner.swf -------------------------------------------------------------------------------- /static/estate.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itudo/MyTomcat/HEAD/static/estate.gif -------------------------------------------------------------------------------- /out/production/MyTomCat/User.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itudo/MyTomcat/HEAD/out/production/MyTomCat/User.class -------------------------------------------------------------------------------- /.idea/description.html: -------------------------------------------------------------------------------- 1 | Simple Java application that includes a class with main() method -------------------------------------------------------------------------------- /out/production/MyTomCat/Login.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itudo/MyTomcat/HEAD/out/production/MyTomCat/Login.class -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MyTomcat 2 | 实现一个简单的Tomcat 3 | 实现功能: 4 | 5 | 1:静态资源请求 6 | 7 | 2:动态请求处理 8 | 9 | 3:session及cookie信息存储 10 | -------------------------------------------------------------------------------- /out/production/MyTomCat/servlet/Cookie.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itudo/MyTomcat/HEAD/out/production/MyTomCat/servlet/Cookie.class -------------------------------------------------------------------------------- /out/production/MyTomCat/server/MyTomcat.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itudo/MyTomcat/HEAD/out/production/MyTomCat/server/MyTomcat.class -------------------------------------------------------------------------------- /out/production/MyTomCat/server/Processor.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itudo/MyTomcat/HEAD/out/production/MyTomCat/server/Processor.class -------------------------------------------------------------------------------- /out/production/MyTomCat/servlet/Servlet.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itudo/MyTomcat/HEAD/out/production/MyTomCat/servlet/Servlet.class -------------------------------------------------------------------------------- /out/production/MyTomCat/servlet/HttpServlet.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itudo/MyTomcat/HEAD/out/production/MyTomCat/servlet/HttpServlet.class -------------------------------------------------------------------------------- /out/production/MyTomCat/servlet/HttpSession.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itudo/MyTomcat/HEAD/out/production/MyTomCat/servlet/HttpSession.class -------------------------------------------------------------------------------- /out/production/MyTomCat/server/ServerService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itudo/MyTomcat/HEAD/out/production/MyTomCat/server/ServerService.class -------------------------------------------------------------------------------- /out/production/MyTomCat/server/DynamicProcessor.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itudo/MyTomcat/HEAD/out/production/MyTomCat/server/DynamicProcessor.class -------------------------------------------------------------------------------- /out/production/MyTomCat/server/StaticProcessor.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itudo/MyTomcat/HEAD/out/production/MyTomCat/server/StaticProcessor.class -------------------------------------------------------------------------------- /out/production/MyTomCat/servlet/ServletContext.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itudo/MyTomcat/HEAD/out/production/MyTomCat/servlet/ServletContext.class -------------------------------------------------------------------------------- /out/production/MyTomCat/servlet/HttpServletRequest.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itudo/MyTomcat/HEAD/out/production/MyTomCat/servlet/HttpServletRequest.class -------------------------------------------------------------------------------- /out/production/MyTomCat/servlet/HttpServletResponse.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itudo/MyTomcat/HEAD/out/production/MyTomCat/servlet/HttpServletResponse.class -------------------------------------------------------------------------------- /static/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Insert title here 6 | 7 | 8 | 404 9 | 10 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/servlet/Servlet.java: -------------------------------------------------------------------------------- 1 | package servlet; 2 | 3 | /** 4 | * @description: Servlet 5 | * @author: WangZhiJun 6 | * @create: 2019-07-26 09:44 7 | **/ 8 | public interface Servlet { 9 | 10 | /** 11 | * servlet初始化 12 | */ 13 | void init(); 14 | /** 15 | * servlet业务处理 16 | */ 17 | void service(HttpServletRequest request, HttpServletResponse response); 18 | } 19 | -------------------------------------------------------------------------------- /src/server/Processor.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import servlet.HttpServletRequest; 4 | import servlet.HttpServletResponse; 5 | 6 | /** 7 | * @description: 处理接口 8 | * @author: WangZhiJun 9 | * @create: 2019-07-26 09:44 10 | **/ 11 | public interface Processor { 12 | /** 处理请求,给出响应 13 | * @param request 请求 14 | * @param response 响应 15 | */ 16 | void process(HttpServletRequest request, HttpServletResponse response); 17 | } 18 | -------------------------------------------------------------------------------- /src/server/StaticProcessor.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import servlet.HttpServletRequest; 4 | import servlet.HttpServletResponse; 5 | 6 | /** 7 | * @description: 静态处理类 8 | * @author: WangZhiJun 9 | * @create: 2019-07-26 09:44 10 | **/ 11 | public class StaticProcessor implements Processor { 12 | 13 | @Override 14 | public void process(HttpServletRequest request, HttpServletResponse response) { 15 | response.sendRedirect(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /MyTomCat.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/servlet/ServletContext.java: -------------------------------------------------------------------------------- 1 | package servlet; 2 | 3 | import java.util.Hashtable; 4 | import java.util.Map; 5 | 6 | /** 7 | * @description: Servlet上下文 8 | * @author: WangZhiJun 9 | * @create: 2019-07-26 09:44 10 | **/ 11 | public class ServletContext { 12 | /** 13 | * servlet容器:存储servlet实例 14 | */ 15 | public static Map servlets = new Hashtable(); 16 | /** 17 | * 存储session信息 18 | */ 19 | static Map sessions = new Hashtable<>(); 20 | } 21 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/servlet/HttpSession.java: -------------------------------------------------------------------------------- 1 | package servlet; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * @description: HttpSession 8 | * @author: WangZhiJun 9 | * @create: 2019-07-26 09:44 10 | **/ 11 | public class HttpSession { 12 | private Map map = new HashMap(); 13 | private String id; 14 | 15 | HttpSession(String id) { 16 | super(); 17 | this.id = id; 18 | } 19 | 20 | 21 | public String getId() { 22 | return id; 23 | } 24 | 25 | public void setAttribute(String name,Object value) { 26 | this.map.put(name, value); 27 | } 28 | 29 | public Object getAttribute(String key) { 30 | return map.get(key); 31 | } 32 | 33 | public void removeAttribute(String name) { 34 | this.map.remove(name); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/servlet/HttpServlet.java: -------------------------------------------------------------------------------- 1 | package servlet; 2 | 3 | /** httpServlet针对http协议 4 | * GET /HTTP/1.1 5 | * @description: 简单Cookie类 6 | * @author: WangZhiJun 7 | * @create: 2019-07-26 09:44 8 | **/ 9 | public abstract class HttpServlet implements Servlet { 10 | @Override 11 | public void init(){} 12 | 13 | protected void doPost(HttpServletRequest request, HttpServletResponse response) {} 14 | 15 | protected void doGet(HttpServletRequest request, HttpServletResponse response) {} 16 | 17 | /** 从request中取出method,判断是get还是post,调用doGet,doPost 18 | * @param request 请求 19 | * @param response 响应 20 | */ 21 | @Override 22 | public void service(HttpServletRequest request, HttpServletResponse response) { 23 | String method = request.getMethod(); 24 | if("GET".equals(method)){ 25 | doGet(request,response); 26 | }else if("POST".equals(method)){ 27 | doPost(request,response); 28 | } 29 | //还有 HEAD TRACE DELETE PUT等方法 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /static/news.css: -------------------------------------------------------------------------------- 1 | #sidebar { 2 | width:266px; 3 | height:850px; 4 | background:#fff; 5 | float:left; 6 | border-right:1px solid #ccc; 7 | } 8 | #sidebar embed { 9 | display:block; 10 | width:220px; 11 | height:200px; 12 | margin:0 auto; 13 | margin-top:20px; 14 | } 15 | #content { 16 | width:600px; 17 | height:850px; 18 | background:#fff; 19 | float:right; 20 | } 21 | #content h1 { 22 | background:url(../images/newsc.gif) no-repeat; 23 | width:123px; 24 | height:27px; 25 | font-size:100%; 26 | text-indent:-9999px; 27 | margin-top:20px; 28 | margin-left:20px; 29 | } 30 | #content ul { 31 | margin-left:20px; 32 | margin-top:10px; 33 | line-height:180%; 34 | } 35 | #content ul li { 36 | padding-left:15px; 37 | background:url(../images/ico.gif) no-repeat left center; 38 | } 39 | #content ul li a { 40 | text-decoration:none; 41 | color:#06f; 42 | } 43 | #content ul li a:hover { 44 | color:#f60; 45 | text-decoration:underline; 46 | } 47 | #content p { 48 | margin-top:30px; 49 | text-align:center; 50 | } -------------------------------------------------------------------------------- /src/servlet/Cookie.java: -------------------------------------------------------------------------------- 1 | package servlet; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * @description: 简单Cookie类 7 | * @author: WangZhiJun 8 | * @create: 2019-07-26 09:44 9 | **/ 10 | public class Cookie implements Serializable{ 11 | private static final long serialVersionUID = -3977915365961941126L; 12 | /** 13 | * cookie的名称 14 | */ 15 | private String name; 16 | /** 17 | * cookie的值 18 | */ 19 | private String value; 20 | //cookie还有path domin maxAge等属性,在此简化使用 21 | 22 | @Override 23 | public String toString() { 24 | return "Cookie [name=" + name + ", value=" + value; 25 | } 26 | public String getName() { 27 | return name; 28 | } 29 | public void setName(String name) { 30 | this.name = name; 31 | } 32 | public String getValue() { 33 | return value; 34 | } 35 | public void setValue(String value) { 36 | this.value = value; 37 | } 38 | 39 | public Cookie(String name, String value) { 40 | super(); 41 | this.name = name; 42 | this.value = value; 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/User.java: -------------------------------------------------------------------------------- 1 | import servlet.HttpServlet; 2 | import servlet.HttpServletRequest; 3 | import servlet.HttpServletResponse; 4 | import servlet.HttpSession; 5 | 6 | import java.io.PrintWriter; 7 | 8 | 9 | /** 10 | * @author WangZhiJun 11 | */ 12 | public class User extends HttpServlet { 13 | 14 | @Override 15 | protected void doPost(HttpServletRequest request, 16 | HttpServletResponse response) { 17 | HttpSession session = request.getSession(); 18 | String username = (String) session.getAttribute("username"); 19 | 20 | PrintWriter out = response.getWriter(); 21 | String jsession = request.getJsessionid(); 22 | if(jsession!=null) { 23 | out.print("HTTP/1.1 200 OK\r\nSet-Cookie: JSESSIONID="+jsession+"\r\n\r\n"); 24 | } else { 25 | out.print("HTTP/1.1 200 OK\r\n\r\n"); 26 | } 27 | out.print(""); 28 | out.print(""); 29 | out.print("welcome! "+ username + "\r\n\r\n"); 30 | out.print("sessionId:" + jsession); 31 | out.print(""); 32 | out.print(""); 33 | out.flush(); 34 | out.close(); 35 | } 36 | 37 | @Override 38 | protected void doGet(HttpServletRequest request, 39 | HttpServletResponse response) { 40 | doPost(request,response); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/server/MyTomcat.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import java.io.IOException; 4 | import java.net.ServerSocket; 5 | import java.net.Socket; 6 | 7 | /** 8 | * @description: Tomcat服务器启动类 9 | * @author: WangZhiJun 10 | * @create: 2019-07-26 09:44 11 | **/ 12 | public class MyTomcat { 13 | 14 | public static void main(String[] args) { 15 | MyTomcat kc = new MyTomcat(); 16 | kc.startServer(); 17 | } 18 | private void startServer() { 19 | System.out.println("服务器准备启动"); 20 | //TODO:在这里加入一个xml解析模块,读取server.xml,读取port信息 21 | int port = getServerPort(); 22 | ServerSocket ss = null; 23 | try { 24 | ss = new ServerSocket(port); 25 | System.out.println("服务器启动成功,监听:"+ss.getLocalPort()+"端口"); 26 | } catch (Exception e) { 27 | e.printStackTrace(); 28 | System.out.println(port+"被占用,服务器启动失败"); 29 | //TODO:自动选定另一个tcp的空闲端口 30 | System.exit(0); 31 | } 32 | 33 | while(true){ 34 | Socket s=null; 35 | try { 36 | s = ss.accept(); 37 | System.out.println("客户端"+s.getRemoteSocketAddress()+"联结上来了"); 38 | //启动线程来处理这个客户端的请求与响应 39 | ServerService server = new ServerService(s); 40 | //TODO:不要显式创建线程,使用线程池 41 | Thread t = new Thread(server); 42 | t.start(); 43 | } catch (IOException e) { 44 | e.printStackTrace(); 45 | System.out.println("客户端"+s.getRemoteSocketAddress()+"掉线了"); 46 | } 47 | } 48 | } 49 | private int getServerPort() { 50 | return 8888; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Login.java: -------------------------------------------------------------------------------- 1 | import servlet.HttpServlet; 2 | import servlet.HttpServletRequest; 3 | import servlet.HttpServletResponse; 4 | import servlet.HttpSession; 5 | import java.io.PrintWriter; 6 | 7 | 8 | /** 9 | * @author WangZhiJun 10 | */ 11 | public class Login extends HttpServlet { 12 | 13 | @Override 14 | protected void doPost(HttpServletRequest request, 15 | HttpServletResponse response) { 16 | String username = request.getParameter("username"); 17 | String password = request.getParameter("password"); 18 | System.out.println(username+"\t"+password); 19 | 20 | System.out.println(request.getCookies()); 21 | 22 | HttpSession session = request.getSession(); 23 | session.setAttribute("username", username); 24 | session.setAttribute("password", password); 25 | 26 | PrintWriter out = response.getWriter(); 27 | String jsession = request.getJsessionid(); 28 | if(jsession!=null) { 29 | out.print("HTTP/1.1 200 OK\r\nSet-Cookie: JSESSIONID="+jsession+"\r\n\r\n"); 30 | } else { 31 | out.print("HTTP/1.1 200 OK\r\n\r\n"); 32 | } 33 | out.print(""); 34 | out.print(""); 35 | out.print("login success! \r\n"); 36 | out.print("sessionId:" + jsession); 37 | out.print(""); 38 | out.print(""); 39 | out.flush(); 40 | out.close(); 41 | } 42 | 43 | @Override 44 | protected void doGet(HttpServletRequest request, 45 | HttpServletResponse response) { 46 | doPost(request,response); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/server/DynamicProcessor.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import servlet.HttpServlet; 4 | import servlet.HttpServletRequest; 5 | import servlet.HttpServletResponse; 6 | import servlet.ServletContext; 7 | 8 | /** 9 | * @description: 动态请求处理类 10 | * @author: WangZhiJun 11 | * @create: 2019-07-26 09:44 12 | **/ 13 | public class DynamicProcessor implements Processor { 14 | 15 | @Override 16 | public void process(HttpServletRequest request, HttpServletResponse response){ 17 | 18 | //1、假设请求的地址为 /hello.action ->对应的是hello 这个servlet 类 19 | //从request中取出getRequestURI 20 | String uri = request.getRequestURI(); 21 | //2、去掉 / 及action 两个部分 ,得到hello ,就是servlet类名 22 | String servletName = uri.substring(1,uri.indexOf(".")); 23 | //单实例实现 ->到Map中判断是否已经存在了这个servlet实例,如果有,则取出这个实例 24 | //利用反射来加载这个类的字节码 URLClassLoader 来加载class 25 | HttpServlet servlet = null; 26 | //没有servlet实例 27 | if(!ServletContext.servlets.containsKey(servletName)){ 28 | try { 29 | Class c = Class.forName(servletName); 30 | //2、利用class实例化newInstance()-> servlet初始化 31 | Object obj = c.newInstance(); 32 | //将servlet放入ServletContext中 33 | ServletContext.servlets.put(servletName, obj); 34 | if(obj instanceof HttpServlet){ 35 | servlet = (HttpServlet)obj; 36 | servlet.init(); 37 | } 38 | } catch (Exception e) { 39 | e.printStackTrace(); 40 | } 41 | }else{ 42 | servlet = (HttpServlet) ServletContext.servlets.get(servletName); 43 | } 44 | servlet.service(request, response); 45 | 46 | } 47 | 48 | } 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/server/ServerService.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import servlet.HttpServletRequest; 4 | import servlet.HttpServletResponse; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.io.OutputStream; 9 | import java.net.Socket; 10 | 11 | /** 12 | * @description: 处理接口 13 | * @author: WangZhiJun 14 | * @create: 2019-07-26 09:44 15 | **/ 16 | public class ServerService implements Runnable{ 17 | private Socket s; 18 | 19 | ServerService(Socket s) { 20 | super(); 21 | this.s = s; 22 | } 23 | 24 | @Override 25 | public void run() { 26 | InputStream iis; 27 | OutputStream oos; 28 | try { 29 | iis = s.getInputStream(); 30 | oos = s.getOutputStream(); 31 | } catch (IOException e) { 32 | e.printStackTrace(); 33 | System.out.println("客户端"+this.s.getRemoteSocketAddress()+"掉线"); 34 | return; 35 | } 36 | //http是一个基于请求与响应的协议 37 | //1、创建一个请求对象 38 | HttpServletRequest request = new HttpServletRequest(iis); 39 | //2、创建一个响应对象 40 | HttpServletResponse response = new HttpServletResponse(request, oos); 41 | String uri = request.getRequestURI(); 42 | //判断是动态的还是静态的请求 43 | Processor processor; 44 | //如果是动态的请求,则创建DynamicProcessor 45 | //未简化时间,此处认为请求信息里有.action为动态请求 46 | if(uri.indexOf(".action")>0){ 47 | processor = new DynamicProcessor(); 48 | }else{ 49 | //如果是静态的请求,则创建StaticProcessor 50 | processor = new StaticProcessor(); 51 | } 52 | processor.process(request, response); 53 | try { 54 | //http是无状态的短连接 55 | s.close(); 56 | } catch (IOException e) { 57 | e.printStackTrace(); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 36 | -------------------------------------------------------------------------------- /src/servlet/HttpServletResponse.java: -------------------------------------------------------------------------------- 1 | package servlet; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.File; 5 | import java.io.FileInputStream; 6 | import java.io.IOException; 7 | import java.io.OutputStream; 8 | import java.io.PrintWriter; 9 | import java.util.Date; 10 | 11 | /** 12 | * @description: HttpServletResponse 13 | * @author: WangZhiJun 14 | * @create: 2019-07-26 09:44 15 | **/ 16 | public class HttpServletResponse { 17 | private HttpServletRequest request; 18 | private OutputStream oos; 19 | 20 | private String webRoot = System.getProperty("user.dir")+File.separator+"static"; 21 | public HttpServletResponse(HttpServletRequest request, OutputStream oos) { 22 | this.request=request; 23 | this.oos = oos; 24 | } 25 | public PrintWriter getWriter(){ 26 | return new PrintWriter(this.oos); 27 | } 28 | 29 | /** 30 | * 响应文件输出HTML,JPEG,gif 31 | * 响应码404,500,200 32 | */ 33 | public void sendRedirect() { 34 | int code = 200; 35 | //1.取出request中的uri 36 | String uri = this.request.getRequestURI(); 37 | File file; 38 | String fileName; 39 | if(uri.endsWith("/")){ 40 | fileName = uri+"index.html"; 41 | }else{ 42 | fileName = uri; 43 | } 44 | file = new File(webRoot,fileName); 45 | //2.拼装file 查看是否存在 46 | //不存在则404 47 | if(!file.exists()){ 48 | file = new File(webRoot,"404.html"); 49 | code = 404; 50 | } 51 | //3、存在,找到这个文件,读出来 52 | //4、发送文件响应,不同的文件返回不同类型 53 | if(file.getName().endsWith(".jpg")){ 54 | send(file,"application/x-jpg",code); 55 | }else if(file.getName().endsWith(".jpe")||file.getName().endsWith(".jpeg")){ 56 | send(file,"image/jpeg",code); 57 | }else if(file.getName().endsWith(".gif")){ 58 | send(file,"image/gif",code); 59 | }else if(file.getName().endsWith(".css")){ 60 | send(file,"text/css",code); 61 | }else if(file.getName().endsWith(".js")){ 62 | send(file,"application/x-javascript",code); 63 | }else if(file.getName().endsWith(".swf")){ 64 | send(file,"application/x-shockwave-flash",code); 65 | }else{ 66 | send(file,"text/html",code); 67 | } 68 | } 69 | 70 | /** 71 | * 返回响应流 72 | */ 73 | private void send(File file, String contentType, int code) { 74 | try { 75 | String responseHeader = genProtocol(file.length(),contentType,code); 76 | byte[] bs = readFile(file); 77 | 78 | this.oos.write(responseHeader.getBytes()); 79 | this.oos.flush(); 80 | this.oos.write(bs); 81 | this.oos.flush(); 82 | } catch (IOException e) { 83 | e.printStackTrace(); 84 | }finally{ 85 | try { 86 | this.oos.close(); 87 | } catch (IOException e) { 88 | e.printStackTrace(); 89 | } 90 | } 91 | } 92 | 93 | /** 94 | * 读取文件 95 | */ 96 | private byte[] readFile(File file) { 97 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 98 | FileInputStream fis = null; 99 | 100 | try { 101 | fis = new FileInputStream(file); 102 | byte[] bs = new byte[1024]; 103 | int length; 104 | while((length = fis.read(bs,0,bs.length))!=-1){ 105 | baos.write(bs, 0, length); 106 | baos.flush(); 107 | } 108 | } catch (Exception e) { 109 | e.printStackTrace(); 110 | }finally{ 111 | try { 112 | fis.close(); 113 | } catch (IOException e) { 114 | e.printStackTrace(); 115 | } 116 | } 117 | return baos.toByteArray(); 118 | } 119 | 120 | /** 121 | * 拼接响应协议 122 | */ 123 | private String genProtocol(long length, String contentType, int code) { 124 | String result = "HTTP/1.1 "+code+" OK\r\n"; 125 | result+="Server: myTomcat\r\n"; 126 | result+="Content-Type: "+contentType+";charset=utf-8\r\n"; 127 | result+="Content-Length: "+length+"\r\n"; 128 | result+="Date: "+new Date()+"\r\n"; 129 | result+="\r\n"; 130 | return result; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /src/servlet/HttpServletRequest.java: -------------------------------------------------------------------------------- 1 | package servlet; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.util.ArrayList; 6 | import java.util.Hashtable; 7 | import java.util.List; 8 | import java.util.Map; 9 | import java.util.UUID; 10 | 11 | /** 12 | * @description: HttpServletRequest 13 | * @author: WangZhiJun 14 | * @create: 2019-07-26 09:44 15 | **/ 16 | public class HttpServletRequest { 17 | 18 | /** 19 | * 请求方法 20 | */ 21 | private String method; 22 | /** 23 | * 请求地址 24 | */ 25 | private String requestURI; 26 | 27 | private String jsessionid = null; 28 | 29 | /** 30 | * 请求体 31 | */ 32 | private String content; 33 | /** 34 | * 请求头 35 | */ 36 | private Map headers = new Hashtable<>(); 37 | /** 38 | * 请求参数 39 | */ 40 | private Map parameter = new Hashtable<>(); 41 | /** 42 | * 请求cookie信息 43 | */ 44 | private List cookies = new ArrayList<>(); 45 | 46 | 47 | public String getJsessionid() { 48 | return jsessionid; 49 | } 50 | public List getCookies() { 51 | return cookies; 52 | } 53 | public String getParameter(String key) { 54 | return parameter.get(key); 55 | } 56 | 57 | public HttpServletRequest(InputStream iis) { 58 | //一次性读完所有请求信息 59 | StringBuilder sb = new StringBuilder(); 60 | int length = -1; 61 | byte[] bs = new byte[100*1024]; 62 | try { 63 | length = iis.read(bs); 64 | } catch (IOException e) { 65 | e.printStackTrace(); 66 | System.out.println("读取客户请求异常"); 67 | } 68 | //将bs中的字节数据转为char 69 | for(int i = 0;i0) { 113 | for(Cookie c:cookies) { 114 | if("JSESSIONID".equals(c.getName())) { 115 | return c.getValue(); 116 | } 117 | } 118 | } 119 | return null; 120 | } 121 | 122 | /** 123 | * headers中取出cookie,然后在解析出cookie对象存在cookies中 124 | */ 125 | private void parseCookie() { 126 | if(headers==null&&headers.size()<=0){ 127 | return; 128 | } 129 | //从headers中取出键为cookie的 130 | String cookieValue = headers.get("Cookie"); 131 | if(cookieValue == null || cookieValue.length()<=0) { 132 | return; 133 | } 134 | String[] cvs = cookieValue.split(": "); 135 | if(cvs.length > 0) { 136 | for(String cv:cvs) { 137 | String[] str = cv.split("="); 138 | if(str.length > 0) { 139 | String key = str[0]; 140 | String value = str[1]; 141 | Cookie c = new Cookie(key,value); 142 | cookies.add(c); 143 | } 144 | } 145 | } 146 | } 147 | private void parseHeader() { 148 | //请求头 149 | String[] parts = this.content.split("\r\n\r\n"); 150 | //GET /请求地址 HTTP/1.1 151 | String[] headerss = parts[0].split("\r\n"); 152 | for(int i = 1;i=1){ 170 | String[] pairs = this.requestURI.substring(index+1).split("&"); 171 | for(String p:pairs){ 172 | String[] po = p.split("="); 173 | parameter.put(po[0], po[1]); 174 | } 175 | } 176 | if(this.method.equals("POST")){ 177 | String[] parts = this.content.split("\r\n\r\n"); 178 | String entity = parts[1]; 179 | String[] pairs = entity.split("&"); 180 | for(String p:pairs){ 181 | String[] po = p.split("="); 182 | parameter.put(po[0], po[1]); 183 | } 184 | } 185 | } 186 | public String getMethod() { 187 | return method; 188 | } 189 | public String getRequestURI() { 190 | return requestURI; 191 | } 192 | public Map getHeaders() { 193 | return headers; 194 | } 195 | 196 | 197 | 198 | } 199 | -------------------------------------------------------------------------------- /.idea/junitgenerator-prj-settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/uiDesigner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 12 | 13 | 14 | server.* 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 162 | 163 | 164 | 165 | kittyCat 166 | webapps 167 | pro 168 | 169 | 170 | 171 | 196 | 197 | 198 | 199 | 200 | true 201 | DEFINITION_ORDER 202 | 203 | 204 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 |