Add annotations to dynamically load classes through reflection

develop
xiaoifei 10 months ago
parent 3400ce8bf5
commit d66dc95fee

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -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;
}
}

@ -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;
}
}

@ -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){
}
}
}

@ -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();
}
}

@ -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<Part> 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<String> getHeaderNames() {
return null;
}
@Override
public Enumeration<String> 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<String> 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<String> getParameterNames() {
return null;
}
@Override
public String[] getParameterValues(String s) {
return new String[0];
}
@Override
public Map<String, String[]> 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<Locale> 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;
}
}

@ -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<String> getHeaders(String s) {
return List.of();
}
@Override
public Collection<String> 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;
}
}

@ -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<String, Servlet> urlPatternMapping = new HashMap<String, Servlet>();
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;
}
}

@ -0,0 +1,6 @@
package com.xiaoyi;
import javax.servlet.http.HttpServlet;
public class DefaultServlet extends HttpServlet {
}

@ -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;
}
}

@ -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<String,String> headers = new HashMap<String,String>();//消息行键值对容器
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);
}
/**
* servletdoGetwrite
*/
@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<String, String> 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);
}
/**
* servletdoGetwrite
*/
private void sendResponseMsgBody() {
try {
outputStream.write(getOutputStream().getBytes());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

@ -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());//消息体
// }
//}

@ -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;
}
}

@ -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类进行处理
//匹配servletdoGet
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();
}
}
}

@ -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<String,Context> contextMap = new HashMap<String,Context>();
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<File> 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<File> getAllFilePath(File srcFile){
List<File> fileList = new ArrayList<File>();
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<String, Context> 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){
}
}
}
Loading…
Cancel
Save