log4j.properties
MyCatServer
package com.yc.tomcat;
import java.net.ServerSocket;
import java.net.Socket;
public class MyCatServer {
public static void main(String[] args) {
MyCatServer mcs = new MyCatServer();
mcs.startServer();
}
public void startServer() {
boolean flag = false;
Map<String, Map<String, String>> map = parseServerXml();
ThreadPoolExecutor executor = null;
int port = 8080;
if (map.get("Connector").get("port") != null) {
port = Integer.parseInt(map.get("Connector").get("port"));
}
boolean openPool = false;
if (map.get("Connector").get("executor") != null && "true".equalsIgnoreCase(map.get("Connector").get("executor"))) {
openPool = true;
}
if (openPool) {
int corePoolSize = Runtime.getRuntime().availableProcessors();
int maxPoolSize = corePoolSize * 2;
long keepAliveTime = 10;
TimeUnit unit = TimeUnit.SECONDS;
BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(maxPoolSize * 4);
ThreadFactory threadFactory = new NameThreadFactory();
RejectedExecutionHandler handler = new MyIgnorePolicy();
executor = new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
executor.prestartAllCoreThreads();
}
try (ServerSocket ss = new ServerSocket(port)) {
while (!flag) {
Socket s = ss.accept();
if (openPool) {
executor.submit(new TaskService(s));
} else {
Thread t = new Thread(new TaskService(s));
t.start();
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (executor != null && openPool) {
executor.shutdown();
}
}
}
private Map<String, Map<String, String>> parseServerXml() {
Map<String, Map<String, String>> map = new ConcurrentHashMap<>();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder builder = factory.newDocumentBuilder();
String basePath = System.getProperty("user.dir");
String serverXmlPath = basePath + File.separator + "conf" + File.separator + "server.xml";
Document doc = builder.parse(serverXmlPath);
NodeList nodeList = doc.getElementsByTagName("Connector");
for (int i = 0; i < nodeList.getLength(); i++) {
Element element = (Element) nodeList.item(i);
Map<String, String> sonMap = new ConcurrentHashMap<>();
sonMap.put("port", element.getAttribute("port"));
sonMap.put("executor", element.getAttribute("executor"));
map.put("Connector", sonMap);
}
} catch (Exception e) {
e.printStackTrace();
}
return map;
}
static class NameThreadFactory implements ThreadFactory {
private final AtomicInteger threadId = new AtomicInteger(1);
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, "线程--" + threadId.getAndIncrement());
System.out.println(t.getName() + "已被创建");
return t;
}
}
public static class MyIgnorePolicy implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
doLog(r, executor);
}
private void doLog(Runnable runnable, ThreadPoolExecutor e) {
System.out.println("线程池:" + e.toString() + runnable.toString() + "被拒绝执行");
}
}
}
TaskService
package com.yc.tomcat;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class TaskService implements Runnable {
private Socket socket;
private InputStream in;
private OutputStream out;
private boolean flag;
private String connection = "close";
public TaskService(Socket socket) {
this.socket = socket;
flag = true;
try {
in = socket.getInputStream();
out = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
flag = false;
}
}
@Override
public void run() {
while (flag) {
try {
HttpServletRequest request = new HttpServletRequest(this.in, socket);
HttpServletResponse response = new HttpServletResponse(request, this.out);
} catch (Exception e) {
e.printStackTrace();
} finally {
if ("close".equals(connection)) {
flag = false;
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
}
HttpServletRequest
package com.yc.tomcat;
import java.io.File;
import java.io.InputStream;
import java.net.Socket;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;
public class HttpServletRequest {
private InputStream in;
private Socket socket;
private String method;
private String requestURL;
private String requestURI;
private String contextPath;
private String queryString;
private Map<String, String[]> parameterMap = new ConcurrentHashMap<>();
private String scheme;
private String protocol;
private String realPath;
public HttpServletRequest(InputStream in, Socket socket) {
this.in = in;
this.socket = socket;
parseRequest();
}
private void parseRequest() {
String requestInfoString = readFromInpuStream();
if (requestInfoString == null || "".equals(requestInfoString)) {
throw new RuntimeException("读取输入流异常");
}
parseRequestInfoString(requestInfoString);
}
private String readFromInpuStream() {
String requestInfoString = null;
StringBuffer sb = new StringBuffer(100 * 1024);
int length = -1;
byte[] bs = new byte[100 * 1024];
try {
length = this.in.read(bs);
} catch (Exception e) {
e.printStackTrace();
length = 0;
}
for (int i = 0; i < length; i++) {
sb.append((char) bs[i]);
}
requestInfoString = sb.toString();
return requestInfoString;
}
private void parseRequestInfoString(String requestInfoString) {
StringTokenizer st = new StringTokenizer(requestInfoString);
this.method = st.nextToken();
this.requestURI = st.nextToken();
int questionIndex = this.requestURI.indexOf("?");
if (questionIndex >= 0) {
this.queryString = this.requestURI.substring(questionIndex + 1);
this.requestURI = this.requestURI.substring(0, questionIndex);
}
this.protocol = st.nextToken();
this.scheme = this.protocol.substring(0, this.protocol.indexOf("/"));
int slashIndex = this.requestURI.indexOf("/", 1);
if (slashIndex >= 0) {
this.contextPath = this.requestURI.substring(0, slashIndex);
} else {
this.contextPath = this.requestURI;
}
this.requestURL = this.scheme + "://" + this.socket.getRemoteSocketAddress() + ":" + this.requestURI;
if (this.queryString != null && this.queryString.length() > 0) {
String[] ps = this.queryString.split("&");
for (String s : ps) {
String[] params = s.split("=");
this.parameterMap.put(params[0], params[1].split(","));
}
}
this.realPath = System.getProperty("user.dir") + File.separator + "webapps";
}
public Socket getSocket() {return socket;}
public String getContextPath() {return contextPath;}
public String getRealPath() {return realPath;}
public String getMethod() {return method;}
public InputStream getIn() {return in;}
public String getRequestURL() {return requestURL;}
public String getRequestURI() {return requestURI;}
public String getQueryString() {return queryString;}
public Map<String, String[]> getParameterMap() {return parameterMap;}
public String getScheme() {return scheme;}
public String getProtocol() {return protocol;}
}
HttpServletResponse
package com.yc.tomcat;
import java.io.*;
public class HttpServletResponse {
private HttpServletRequest request;
private OutputStream out;
public HttpServletResponse(HttpServletRequest request, OutputStream out) {
this.request = request;
this.out = out;
outResult();
}
private void outResult() {
byte[] fileContent = null;
String responseProtocol = null;
String uri = this.request.getRequestURI();
String fileName = this.request.getRealPath() + uri;
File file = new File(fileName);
if (file.exists() == false) {
File file404 = new File(this.request.getRealPath(), "404.html");
fileContent = readFile(file404);
responseProtocol = get404Protocol(fileContent);
} else {
fileContent = readFile(file);
responseProtocol = get200Protocol(fileContent);
}
try {
this.out.write(responseProtocol.getBytes());
this.out.flush();
this.out.write(fileContent);
this.out.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (this.out != null) {
try {
this.out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private byte[] readFile(File file) {
FileInputStream fin = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
fin = new FileInputStream(file);
byte[] bs = new byte[10 * 1024];
int length = -1;
while ((length = fin.read(bs, 0, bs.length)) != -1) {
baos.write(bs, 0, length);
baos.flush();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fin != null) {
try {
fin.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return baos.toByteArray();
}
private String get404Protocol(byte[] fileContent) {
String pro404 = "HTTP/1.1 404\r\n" +
"Content-Type: text/html;charset=utf-8\r\n" +
"Content-Language: zh-CN\r\n" +
"Content-Length: " + fileContent.length + "\r\n\r\n";
return pro404;
}
private String get200Protocol(byte[] fileContent) {
String uri = this.request.getRequestURI();
int index = uri.lastIndexOf(".");
if (index >= 0) {
index = index + 1;
}
String extension = uri.substring(index);
String pro200 = "";
if ("html".equalsIgnoreCase(extension) || "htm".equalsIgnoreCase(extension)) {
pro200 = "HTTP/1.1 200\r\n" +
"Content-Type: text/html\r\n" +
"Content-Length: " + fileContent.length + "\r\n\r\n";
} else if ("css".equalsIgnoreCase(extension)) {
pro200 = "HTTP/1.1 200\r\n" +
"Content-Type: text/css\r\n" +
"Content-Length: " + fileContent.length + "\r\n\r\n";
} else if ("js".equalsIgnoreCase(extension)) {
pro200 = "HTTP/1.1 200\r\n" +
"Content-Type: text/javascript\r\n" +
"Content-Length: " + fileContent.length + "\r\n\r\n";
} else if ("jpg".equalsIgnoreCase(extension) || "jpeg".equalsIgnoreCase(extension)) {
pro200 = "HTTP/1.1 200\r\n" +
"Content-Type: text/jpeg\r\n" +
"Content-Length: " + fileContent.length + "\r\n\r\n";
}
return pro200;
}
}