diff --git a/lib/javax.annotation.jar b/lib/javax.annotation.jar new file mode 100644 index 0000000..52dca7f Binary files /dev/null and b/lib/javax.annotation.jar differ diff --git a/lib/javax.ejb.jar b/lib/javax.ejb.jar new file mode 100644 index 0000000..4ebf5ec Binary files /dev/null and b/lib/javax.ejb.jar differ diff --git a/lib/javax.jms.jar b/lib/javax.jms.jar new file mode 100644 index 0000000..d31451a Binary files /dev/null and b/lib/javax.jms.jar differ diff --git a/lib/javax.persistence.jar b/lib/javax.persistence.jar new file mode 100644 index 0000000..21d80e0 Binary files /dev/null and b/lib/javax.persistence.jar differ diff --git a/lib/javax.resource.jar b/lib/javax.resource.jar new file mode 100644 index 0000000..696a234 Binary files /dev/null and b/lib/javax.resource.jar differ diff --git a/lib/javax.servlet.jar b/lib/javax.servlet.jar new file mode 100644 index 0000000..0519e4a Binary files /dev/null and b/lib/javax.servlet.jar differ diff --git a/lib/javax.servlet.jsp.jar b/lib/javax.servlet.jsp.jar new file mode 100644 index 0000000..9c0631c Binary files /dev/null and b/lib/javax.servlet.jsp.jar differ diff --git a/lib/javax.servlet.jsp.jstl.jar b/lib/javax.servlet.jsp.jstl.jar new file mode 100644 index 0000000..7be17cc Binary files /dev/null and b/lib/javax.servlet.jsp.jstl.jar differ diff --git a/lib/javax.transaction.jar b/lib/javax.transaction.jar new file mode 100644 index 0000000..729c695 Binary files /dev/null and b/lib/javax.transaction.jar differ diff --git a/src/MyHttpRequest.java b/src/MyHttpRequest.java deleted file mode 100644 index df36193..0000000 --- a/src/MyHttpRequest.java +++ /dev/null @@ -1,40 +0,0 @@ -import java.io.IOException; -import java.io.InputStream; - -public class MyHttpRequest { - private InputStream inputStream; - private String uri; - - public MyHttpRequest(InputStream inputStream) { - this.inputStream = inputStream; - } - - /** - * 解析流 - */ - public void parse(){ - try { - byte[] bytes = new byte[1024]; - inputStream.read(bytes); - String request = new String(bytes); - parseUri(request); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - /** - * 请求判断 - */ - public void parseUri(String request) { - int index1,index2; - index1 = request.indexOf(" ");//找空格下标 - index2 = request.indexOf(" ",index1+1);//找空格下标2 - uri = request.substring(index1+1,index2);//输出资源位置 - System.out.println(uri); - } - - public String getUri() { - return this.uri; - } -} diff --git a/src/MyHttpResponse.java b/src/MyHttpResponse.java deleted file mode 100644 index c555a6a..0000000 --- a/src/MyHttpResponse.java +++ /dev/null @@ -1,50 +0,0 @@ -import java.io.*; - -public class MyHttpResponse { - private int statusCode; - private String statusMessage; - - private OutputStream outputStream; - - public MyHttpResponse(OutputStream outputStream){ - this.outputStream = outputStream; - } - - public void sendRedirect(String uri){ - //判断资源是否存在 - // 不存在返回404 - // 存在返回目标资源 - File file = new File(System.getProperty("user.dir")+"/WebContent" + uri); - if (file.exists()){ - try { - FileInputStream fileInputStream = new FileInputStream(file); - byte[] bytes = new byte[(int)file.length()]; - fileInputStream.read(bytes); - String result = new String(bytes); -// System.out.println(result); - String response = getResponseMessage("200,",result); - this.outputStream.write(response.getBytes()); - } catch (IOException e) { - throw new RuntimeException(e); - } - - }else { - try { - String error = getResponseMessage("404","404 File Not Found!"); - this.outputStream.write(error.getBytes()); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - } - - public String getResponseMessage(String code, String message){ - return "HTTP/1.1 " + code + "\r\n" + - "Content-Type: text/html\r\n" + - "Content-Length: " + message.length() + - "\r\n" + - "\r\n" + - message; - - } -} diff --git a/src/MyHttpServer.java b/src/MyHttpServer.java deleted file mode 100644 index 3391224..0000000 --- a/src/MyHttpServer.java +++ /dev/null @@ -1,36 +0,0 @@ -import java.io.InputStream; -import java.io.OutputStream; -import java.net.ServerSocket; -import java.net.Socket; - -public class MyHttpServer { - private int port = 8080; - - public void receiving() - { - try{ - //create socket service - ServerSocket serverSocket = new ServerSocket(port); - while(true){ - //获取连接对象 - Socket socket = serverSocket.accept(); - //获取链接对象输入流 - InputStream inputStream = socket.getInputStream(); - //创建request - MyHttpRequest request = new MyHttpRequest(inputStream); - //解析请求 - request.parse(); - //创建响应 - OutputStream outputStream = socket.getOutputStream(); - MyHttpResponse response = new MyHttpResponse(outputStream); - //进行响应 - response.sendRedirect(request.getUri()); - - } - //loop accept requests - }catch (Exception e){ - - } - - } -} diff --git a/src/Test.java b/src/Test.java deleted file mode 100644 index e133076..0000000 --- a/src/Test.java +++ /dev/null @@ -1,7 +0,0 @@ -public class Test { - public static void main(String[] args) { - System.out.println("server startup successfully"); - MyHttpServer server = new MyHttpServer(); - server.receiving(); - } -} diff --git a/src/main/java/com.xiaoyi/AbstractHttpServletRequest.java b/src/main/java/com.xiaoyi/AbstractHttpServletRequest.java new file mode 100644 index 0000000..d328e43 --- /dev/null +++ b/src/main/java/com.xiaoyi/AbstractHttpServletRequest.java @@ -0,0 +1,341 @@ +package com.xiaoyi; + +import javax.servlet.*; +import javax.servlet.http.*; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.Principal; +import java.util.*; + +public class AbstractHttpServletRequest implements HttpServletRequest { + @Override + public Part getPart(String s) throws IOException, ServletException { + return null; + } + + @Override + public Collection getParts() throws IOException, ServletException { + return List.of(); + } + + @Override + public void logout() throws ServletException { + + } + + @Override + public void login(String s, String s1) throws ServletException { + + } + + @Override + public boolean authenticate(HttpServletResponse httpServletResponse) throws IOException, ServletException { + return false; + } + + @Override + public boolean isRequestedSessionIdFromUrl() { + return false; + } + + @Override + public boolean isRequestedSessionIdFromURL() { + return false; + } + + @Override + public boolean isRequestedSessionIdFromCookie() { + return false; + } + + @Override + public boolean isRequestedSessionIdValid() { + return false; + } + + @Override + public HttpSession getSession() { + return null; + } + + @Override + public HttpSession getSession(boolean b) { + return null; + } + + @Override + public String getServletPath() { + return ""; + } + + @Override + public StringBuffer getRequestURL() { + return null; + } + + @Override + public String getRequestURI() { + return ""; + } + + @Override + public String getRequestedSessionId() { + return ""; + } + + @Override + public Principal getUserPrincipal() { + return null; + } + + @Override + public boolean isUserInRole(String s) { + return false; + } + + @Override + public String getRemoteUser() { + return ""; + } + + @Override + public String getQueryString() { + return ""; + } + + @Override + public String getContextPath() { + return ""; + } + + @Override + public String getPathTranslated() { + return ""; + } + + @Override + public String getPathInfo() { + return ""; + } + + @Override + public String getMethod() { + return ""; + } + + @Override + public int getIntHeader(String s) { + return 0; + } + + @Override + public Enumeration getHeaderNames() { + return null; + } + + @Override + public Enumeration getHeaders(String s) { + return null; + } + + @Override + public String getHeader(String s) { + return ""; + } + + @Override + public long getDateHeader(String s) { + return 0; + } + + @Override + public Cookie[] getCookies() { + return new Cookie[0]; + } + + @Override + public String getAuthType() { + return ""; + } + + @Override + public Object getAttribute(String s) { + return null; + } + + @Override + public Enumeration getAttributeNames() { + return null; + } + + @Override + public String getCharacterEncoding() { + return ""; + } + + @Override + public void setCharacterEncoding(String s) throws UnsupportedEncodingException { + + } + + @Override + public int getContentLength() { + return 0; + } + + @Override + public String getContentType() { + return ""; + } + + @Override + public ServletInputStream getInputStream() throws IOException { + return null; + } + + @Override + public String getParameter(String s) { + return ""; + } + + @Override + public Enumeration getParameterNames() { + return null; + } + + @Override + public String[] getParameterValues(String s) { + return new String[0]; + } + + @Override + public Map getParameterMap() { + return Map.of(); + } + + @Override + public String getProtocol() { + return ""; + } + + @Override + public String getScheme() { + return ""; + } + + @Override + public String getServerName() { + return ""; + } + + @Override + public int getServerPort() { + return 0; + } + + @Override + public BufferedReader getReader() throws IOException { + return null; + } + + @Override + public String getRemoteAddr() { + return ""; + } + + @Override + public String getRemoteHost() { + return ""; + } + + @Override + public void setAttribute(String s, Object o) { + + } + + @Override + public void removeAttribute(String s) { + + } + + @Override + public Locale getLocale() { + return null; + } + + @Override + public Enumeration getLocales() { + return null; + } + + @Override + public boolean isSecure() { + return false; + } + + @Override + public RequestDispatcher getRequestDispatcher(String s) { + return null; + } + + @Override + public String getRealPath(String s) { + return ""; + } + + @Override + public int getRemotePort() { + return 0; + } + + @Override + public String getLocalName() { + return ""; + } + + @Override + public String getLocalAddr() { + return ""; + } + + @Override + public int getLocalPort() { + return 0; + } + + @Override + public ServletContext getServletContext() { + return null; + } + + @Override + public AsyncContext startAsync() throws IllegalStateException { + return null; + } + + @Override + public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException { + return null; + } + + @Override + public boolean isAsyncStarted() { + return false; + } + + @Override + public boolean isAsyncSupported() { + return false; + } + + @Override + public AsyncContext getAsyncContext() { + return null; + } + + @Override + public DispatcherType getDispatcherType() { + return null; + } +} diff --git a/src/main/java/com.xiaoyi/AbstractHttpServletResponse.java b/src/main/java/com.xiaoyi/AbstractHttpServletResponse.java new file mode 100644 index 0000000..ad6ade1 --- /dev/null +++ b/src/main/java/com.xiaoyi/AbstractHttpServletResponse.java @@ -0,0 +1,193 @@ +package com.xiaoyi; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Collection; +import java.util.List; +import java.util.Locale; + +public class AbstractHttpServletResponse implements HttpServletResponse { + + @Override + public void addCookie(Cookie cookie) { + + } + + @Override + public boolean containsHeader(String s) { + return false; + } + + @Override + public String encodeURL(String s) { + return ""; + } + + @Override + public String encodeRedirectURL(String s) { + return ""; + } + + @Override + public String encodeUrl(String s) { + return ""; + } + + @Override + public String encodeRedirectUrl(String s) { + return ""; + } + + @Override + public void sendError(int i, String s) throws IOException { + + } + + @Override + public void sendError(int i) throws IOException { + + } + + @Override + public void sendRedirect(String s) throws IOException { + + } + + @Override + public void setDateHeader(String s, long l) { + + } + + @Override + public void addDateHeader(String s, long l) { + + } + + @Override + public void setHeader(String s, String s1) { + + } + + @Override + public void addHeader(String s, String s1) { + + } + + @Override + public void setIntHeader(String s, int i) { + + } + + @Override + public void addIntHeader(String s, int i) { + + } + + @Override + public void setStatus(int i) { + + } + + @Override + public void setStatus(int i, String s) { + + } + + @Override + public int getStatus() { + return 0; + } + + @Override + public String getHeader(String s) { + return ""; + } + + @Override + public Collection getHeaders(String s) { + return List.of(); + } + + @Override + public Collection getHeaderNames() { + return List.of(); + } + + @Override + public String getCharacterEncoding() { + return ""; + } + + @Override + public String getContentType() { + return ""; + } + + @Override + public ServletOutputStream getOutputStream() throws IOException { + return null; + } + + @Override + public PrintWriter getWriter() throws IOException { + return null; + } + + @Override + public void setCharacterEncoding(String s) { + + } + + @Override + public void setContentLength(int i) { + + } + + @Override + public void setContentType(String s) { + + } + + @Override + public void setBufferSize(int i) { + + } + + @Override + public int getBufferSize() { + return 0; + } + + @Override + public void flushBuffer() throws IOException { + + } + + @Override + public void resetBuffer() { + + } + + @Override + public boolean isCommitted() { + return false; + } + + @Override + public void reset() { + + } + + @Override + public void setLocale(Locale locale) { + + } + + @Override + public Locale getLocale() { + return null; + } +} diff --git a/src/main/java/com.xiaoyi/Context.java b/src/main/java/com.xiaoyi/Context.java new file mode 100644 index 0000000..7968df2 --- /dev/null +++ b/src/main/java/com.xiaoyi/Context.java @@ -0,0 +1,31 @@ +package com.xiaoyi; + +import javax.servlet.Servlet; +import java.util.HashMap; +import java.util.Map; + + +/** + * 用于存储每一个应用下有哪些映射 + */ +public class Context { + private String appName; + private Map urlPatternMapping = new HashMap(); + + public Context(String appName) { + this.appName = appName; + } + + public void addUrlPatternMapping(String pattern, Servlet servlet) { + urlPatternMapping.put(pattern, servlet); + } + + public Servlet getByUrlPatternMapping(String urlPattern) { + for(String key : urlPatternMapping.keySet()) { + if(key.contains(urlPattern)) { + return urlPatternMapping.get(key); + } + } + return null; + } +} diff --git a/src/main/java/com.xiaoyi/DefaultServlet.java b/src/main/java/com.xiaoyi/DefaultServlet.java new file mode 100644 index 0000000..39f88f7 --- /dev/null +++ b/src/main/java/com.xiaoyi/DefaultServlet.java @@ -0,0 +1,6 @@ +package com.xiaoyi; + +import javax.servlet.http.HttpServlet; + +public class DefaultServlet extends HttpServlet { +} diff --git a/src/main/java/com.xiaoyi/MyHttpRequest.java b/src/main/java/com.xiaoyi/MyHttpRequest.java new file mode 100644 index 0000000..70f701d --- /dev/null +++ b/src/main/java/com.xiaoyi/MyHttpRequest.java @@ -0,0 +1,68 @@ +package com.xiaoyi; + +import java.io.IOException; +import java.io.InputStream; + +public class MyHttpRequest extends AbstractHttpServletRequest { + private InputStream inputStream; + private String method; + private String url; + private String protocl; + + public MyHttpRequest(InputStream inputStream) { + this.inputStream = inputStream; + } + + /** + * 解析流 + */ + public void parse(){ + try { + byte[] bytes = new byte[1024]; + inputStream.read(bytes); + String request = new String(bytes); + parseMessageLine(request); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * 请求消息行 + */ + public void parseMessageLine(String request) { + System.out.println("---"); + System.out.println(request); + System.out.println("---"); + + if (!request.isEmpty()) { + int index1,index2,index3; + index1 = request.indexOf(" ");//找空格下标 + method = request.substring(0, index1);;//输出方法 + index2 = request.indexOf(" ",index1+1);//找空格下标2 + url = request.substring(index1+1,index2);//输出资源位置 + index3 = request.indexOf("\r\n",index2+1);//找下标3 + protocl = request.substring(index2+1,index3);;//输出协议 + + System.out.println(method + " " + url + " " + protocl); + }else { + System.out.println("空"); + } + + } + + @Override + public String getMethod() { + return method; + } + + @Override + public StringBuffer getRequestURL() { + return new StringBuffer(url); + } + + @Override + public String getProtocol() { + return protocl; + } +} diff --git a/src/main/java/com.xiaoyi/MyHttpResponse.java b/src/main/java/com.xiaoyi/MyHttpResponse.java new file mode 100644 index 0000000..af42857 --- /dev/null +++ b/src/main/java/com.xiaoyi/MyHttpResponse.java @@ -0,0 +1,136 @@ +package com.xiaoyi; + +import javax.servlet.ServletOutputStream; +import java.io.*; +import java.util.HashMap; +import java.util.Map; + +public class MyHttpResponse extends AbstractHttpServletResponse{ + private MyHttpRequest request; + private OutputStream outputStream; + + private int statusCode = 200; + private String message = "OK"; + private Map headers = new HashMap();//消息行键值对容器 + private ResponseServletOutputStream messageBody = new ResponseServletOutputStream();//消息体 + + private final byte SP = ' '; + private final byte CR = '\r'; + private final byte LF = '\n'; + + public MyHttpResponse(MyHttpRequest request, OutputStream outputStream){ + this.request = request; + this.outputStream = outputStream; + } + +// public void sendRedirect(String uri) { +// //判断资源是否存在 +// // 不存在返回404 +// // 存在返回目标资源 +// File file = new File(System.getProperty("user.dir") + "/WebContent" + uri); +// if (file.exists()) { +// try { +// FileInputStream fileInputStream = new FileInputStream(file); +// byte[] bytes = new byte[(int) file.length()]; +// fileInputStream.read(bytes); +// String result = new String(bytes); +//// System.out.println(result); +// String response = getResponseMessage("200,", result); +// this.outputStream.write(response.getBytes()); +// } catch (IOException e) { +// throw new RuntimeException(e); +// } +// } else { +// try { +// String error = getResponseMessage("404", "404 File Not Found!"); +// this.outputStream.write(error.getBytes()); +// } catch (IOException e) { +// throw new RuntimeException(e); +// } +// } +// } + + public String getResponseMessage(String code, String message){ + return "HTTP/1.1 " + code + "\r\n" + + "Content-Type: text/html\r\n" + + "Content-Length: " + message.length() + + "\r\n" + + "\r\n" + + message; + } + + @Override + public void setStatus(int i, String s) { + statusCode = i; + message = s; + } + + @Override + public int getStatus() { + return statusCode; + } + + @Override + public void addHeader(String s, String s1) { + headers.put(s, s1); + } + + /** + * servlet的doGet所write的的消息体 + */ + @Override + public ResponseServletOutputStream getOutputStream() { + return messageBody; + } + + public void complete() { + try{ + sendResponseMsgLine(); + sendResponseMsgHeader(); + sendResponseMsgBody(); +// String response = "Hello World"; +// this.outputStream.write(response.getBytes()); + }catch (Exception e){ + throw new RuntimeException(e); + } + } + + private void sendResponseMsgLine() throws IOException { + outputStream.write(request.getProtocol().getBytes()); + outputStream.write(SP); + outputStream.write(statusCode); + outputStream.write(SP); + outputStream.write(message.getBytes()); + outputStream.write(CR); + outputStream.write(LF); + } + + private void sendResponseMsgHeader() throws IOException { + if (!headers.containsKey("Content-Length")) { + addHeader("Content-Length", String.valueOf(getOutputStream().getPos())); + } + for (Map.Entry entry : headers.entrySet()) { + String key = entry.getKey(); + String value = entry.getValue(); + outputStream.write(key.getBytes()); + outputStream.write(":".getBytes()); + outputStream.write(SP); + outputStream.write(value.getBytes()); + outputStream.write(CR); + outputStream.write(LF); + } + outputStream.write(CR); + outputStream.write(LF); + } + + /** + * 得到servlet的doGet所write的的消息体 + */ + private void sendResponseMsgBody() { + try { + outputStream.write(getOutputStream().getBytes()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/com.xiaoyi/MyServlet.bak b/src/main/java/com.xiaoyi/MyServlet.bak new file mode 100644 index 0000000..08e4520 --- /dev/null +++ b/src/main/java/com.xiaoyi/MyServlet.bak @@ -0,0 +1,17 @@ +//package com.xiaoyi; +// +//import javax.servlet.ServletException; +//import javax.servlet.annotation.WebServlet; +//import javax.servlet.http.HttpServlet; +//import javax.servlet.http.HttpServletRequest; +//import javax.servlet.http.HttpServletResponse; +//import java.io.IOException; +// +//@WebServlet(urlPatterns = "/xiaoifei") +//public class MyServlet extends HttpServlet { +// @Override +// protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { +// resp.addHeader("Content-Type", "text/plain;charset=utf-8"); +// resp.getOutputStream().write("Hello World".getBytes());//消息体 +// } +//} diff --git a/src/main/java/com.xiaoyi/ResponseServletOutputStream.java b/src/main/java/com.xiaoyi/ResponseServletOutputStream.java new file mode 100644 index 0000000..d17604e --- /dev/null +++ b/src/main/java/com.xiaoyi/ResponseServletOutputStream.java @@ -0,0 +1,24 @@ +package com.xiaoyi; + +import javax.servlet.ServletOutputStream; +import java.io.IOException; + +public class ResponseServletOutputStream extends ServletOutputStream { + //存储消息体(因为doGet执行完毕之后才会写入到消息体最终被Socket发送到客户端) + private byte[] messageBody = new byte[1024]; + private int pos = 0; + + @Override + public void write(int b) throws IOException { + messageBody[pos] = (byte)b; + pos++; + } + + public byte[] getBytes(){ + return messageBody; + } + + public int getPos() { + return pos; + } +} diff --git a/src/main/java/com.xiaoyi/SocketProcessor.java b/src/main/java/com.xiaoyi/SocketProcessor.java new file mode 100644 index 0000000..5f3c7a9 --- /dev/null +++ b/src/main/java/com.xiaoyi/SocketProcessor.java @@ -0,0 +1,64 @@ +package com.xiaoyi; + +import javax.servlet.Servlet; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; + +public class SocketProcessor implements Runnable { + private Socket socket; + private Tomcat tomcat; + public SocketProcessor(Socket socket,Tomcat tomcat) { + this.socket = socket; + this.tomcat = tomcat; + } + + @Override + public void run() { + processSocket(socket); + } + + /** + * 处理Socket连接 + */ + private void processSocket(Socket socket){ + try{ + //获取链接对象输入流 + InputStream inputStream = socket.getInputStream(); + //创建request + MyHttpRequest request = new MyHttpRequest(inputStream); + //解析请求 + request.parse(); + + //创建响应 + OutputStream outputStream = socket.getOutputStream(); + MyHttpResponse response = new MyHttpResponse(request,outputStream); + + //实例化servlet对象,使用自带的Servlet类进行处理 + //匹配servlet,doGet + String requestUrl = request.getRequestURL().toString(); + + //System.out.println(requestUrl); + requestUrl = requestUrl.substring(1); + String[] parts = requestUrl.split("/"); + String appName = parts[0]; + Context context = tomcat.getContextMap().get(appName); + + //由于请求了/favicon.ico,会将其解析为应用,所以会导致下标越界 + if(parts.length > 1){ + Servlet servlet = context.getByUrlPatternMapping(parts[1]); + if(servlet != null){ + servlet.service(request, response); + //进行响应 + response.complete(); + }else {//找不到Servlet的情况(返回404) + DefaultServlet defaultServlet = new DefaultServlet(); + defaultServlet.service(request, response); + response.complete(); + } + } + }catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com.xiaoyi/Tomcat.java b/src/main/java/com.xiaoyi/Tomcat.java new file mode 100644 index 0000000..df2610f --- /dev/null +++ b/src/main/java/com.xiaoyi/Tomcat.java @@ -0,0 +1,123 @@ +package com.xiaoyi; + +import javax.servlet.Servlet; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import java.io.File; +import java.net.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class Tomcat { + private int port = 8080; + + /** + * Tomcat下管理的应用映射 + */ + private Map contextMap = new HashMap(); + + public static void main(String[] args) { + Tomcat server = new Tomcat(); + server.deployApps(); + System.out.println("server startup successfully"); + server.start(); + } + + /** + * 部署应用 + */ + private void deployApps() { + File webapps = new File(System.getProperty("user.dir"), "webapps"); + //System.out.println(webapps.getPath());//D:\codes\IdeaProject\MyTomcat\webapps + for (String app : webapps.list()) { + deployApp(webapps,app); + } + } + + /** + * 应用内servlet + */ + private void deployApp(File webapps,String appName){ + Context context = new Context(appName); + + File appDirectory = new File(webapps,appName); + File classesDirectory = new File(appDirectory,"classes"); + //System.out.println(classesDirectory.getPath());//D:\codes\IdeaProject\MyTomcat\webapps\hello\classes + List files = getAllFilePath(classesDirectory); + + //反射加载类判断是否为HttpServlet的子类 + for (File classFile : files) { + String name = classFile.getPath(); + name = name.replace(classesDirectory.getPath() + "\\",""); + name = name.replace(".class",""); + name = name.replace("\\","."); + + try{ + //loadClass + URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{classesDirectory.toURL()}); + Class sClass = urlClassLoader.loadClass(name); + if (HttpServlet.class.isAssignableFrom(sClass)){ + if (sClass.isAnnotationPresent(WebServlet.class)){ + WebServlet annotation = sClass.getAnnotation(WebServlet.class); + String[] urlPatterns = annotation.urlPatterns(); + for (String urlPattern : urlPatterns){ + context.addUrlPatternMapping(urlPattern, (Servlet) sClass.newInstance()); + } + } + } + }catch (ClassNotFoundException e){ + e.printStackTrace(); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } catch (InstantiationException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + contextMap.put(appName,context); + } + + public List getAllFilePath(File srcFile){ + List fileList = new ArrayList(); + File[] files = srcFile.listFiles(); + + if(files!=null){ + for (File file : files) { + if (file.isDirectory()) { + fileList.addAll(getAllFilePath(file)); + } else { + fileList.add(file); + } + } + } + return fileList; + } + + public Map getContextMap() { + return contextMap; + } + + public void start() + { + try{ + ExecutorService executorService = Executors.newFixedThreadPool(20);//线程池 + //create socket service + ServerSocket serverSocket = new ServerSocket(port); + while(true){ + //获取连接对象 + Socket socket = serverSocket.accept(); + //线程池内处理逻辑,保证从消息的处理不阻塞 + executorService.execute(new SocketProcessor(socket,this)); + } + //loop accept requests + }catch (Exception e){ + + } + } +} diff --git a/webapps/hello/classes/com/xiaoyi/MyServlet.class b/webapps/hello/classes/com/xiaoyi/MyServlet.class new file mode 100644 index 0000000..227e935 Binary files /dev/null and b/webapps/hello/classes/com/xiaoyi/MyServlet.class differ