



package com.qcby.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)// 表示该注解只能用于类上
@Retention(RetentionPolicy.RUNTIME)// 表示该注解在运行时存在
public @interface ZFLServlet {
String url()default "";
}
package com.qcby.config;
import com.qcby.annotation.ZFLServlet;
import com.qcby.servlet.HttpServlet;
import com.qcby.util.SearchClassUtil;
import java.util.HashMap;
import java.util.List;
public class TomcatRoute {
public static HashMap<String, HttpServlet> routes = new HashMap<>();
static {
List<String> paths = SearchClassUtil.searchClass();//获取全路径名
//根据全路径生成对象
for (String path : paths) {
try {
Class clazz = Class.forName(path);//生成类对象
ZFLServlet webServlet = (ZFLServlet) clazz.getDeclaredAnnotation(ZFLServlet.class);
System.out.println(webServlet.url());
routes.put(webServlet.url(), (HttpServlet) clazz.getDeclaredConstructor().newInstance());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
package com.qcby.myweb;
import com.qcby.annotation.ZFLServlet;
import com.qcby.requset.HttpServletRequest;
import com.qcby.response.HttpServletResponse;
import com.qcby.servlet.HttpServlet;
import java.io.IOException;
@ZFLServlet(url = "/delete")
public class DeleteServlet extends HttpServlet {
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) {
super.doPost(request, response);
}
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
super.doGet(request, response);
}
}
package com.qcby.myweb;
import com.qcby.annotation.ZFLServlet;
import com.qcby.requset.HttpServletRequest;
import com.qcby.response.HttpServletResponse;
import com.qcby.servlet.HttpServlet;
import java.io.IOException;
@ZFLServlet(url = "/insert")
public class InsertServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) {
System.out.println("我是insert......");
}
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) {
super.doPost(request, response);
}
}
package com.qcby.servlet;
import com.qcby.requset.HttpServletRequest;
import com.qcby.response.HttpServletResponse;
import java.io.IOException;
public abstract class HttpServlet implements servlet{
public void doPost(HttpServletRequest request, HttpServletResponse response) {}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
}
@Override
public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
if (request.getMethod().equals("GET")){
doGet(request,response);
} else if (request.getMethod().equals("POST")) {
doPost(request,response);
}
}
}
package com.qcby.requset;
public class HttpServletRequest {
private String url;
private String method;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
}
package com.qcby.response;
import com.qcby.util.FileUtil;
import com.qcby.util.ResponseUtil;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
public class HttpServletResponse {
//输出流
private OutputStream outputStream;
public HttpServletResponse(OutputStream outputStream) {
this.outputStream = outputStream;
}
/**
* 返回动态资源
* @param context
*/
public void write(String context) throws IOException {
outputStream.write(context.getBytes());
}
/**
* 返回静态资源
*/
public void writeHtml(String path) throws Exception {
String resourcesPath = FileUtil.getResoucePath(path);
File file = new File(resourcesPath);
if(file.exists()){
//静态文件存在
System.out.println("静态文件存在");
FileUtil.writeFile(file,outputStream);
}else {
System.out.println("静态文件不存在");
write(ResponseUtil.getResponseHeader404());
}
}
}
package com.qcby.servlet;
import com.qcby.requset.HttpServletRequest;
import com.qcby.response.HttpServletResponse;
import java.io.IOException;
public abstract class HttpServlet implements servlet{
public void doPost(HttpServletRequest request, HttpServletResponse response) {}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
}
@Override
public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
if (request.getMethod().equals("GET")){
doGet(request,response);
} else if (request.getMethod().equals("POST")) {
doPost(request,response);
}
}
}
package com.qcby.servlet;
import com.qcby.requset.HttpServletRequest;
import com.qcby.response.HttpServletResponse;
import java.io.IOException;
public interface servlet {
public void service(HttpServletRequest request, HttpServletResponse response) throws IOException;
}
package com.qcby.util;
import java.io.*;
public class FileUtil {
public static boolean witeFile(InputStream inputStream, OutputStream outputStream){
boolean success = false ;
BufferedInputStream bufferedInputStream ;
BufferedOutputStream bufferedOutputStream;
try {
bufferedInputStream = new BufferedInputStream(inputStream);
bufferedOutputStream = new BufferedOutputStream(outputStream);
bufferedOutputStream.write(ResponseUtil.responseHeader200.getBytes());
int count = 0;
while (count == 0){
count = inputStream.available();
}
int fileSize = inputStream.available();
long written = 0;
int beteSize = 1024;
byte[] bytes = new byte[beteSize];
while (written < fileSize){
if(written + beteSize > fileSize){
beteSize = (int)(fileSize - written);
bytes = new byte[beteSize];
}
bufferedInputStream.read(bytes);
bufferedOutputStream.write(bytes);
bufferedOutputStream.flush();
written += beteSize;
}
success = true;
} catch (IOException e) {
e.printStackTrace();
}
return success;
}
public static boolean writeFile(File file,OutputStream outputStream) throws Exception{
return witeFile(new FileInputStream(file),outputStream);
}
public static String getResoucePath(String path){
String resource = FileUtil.class.getResource("/").getPath();
return resource + "\\" + path;
}
}
package com.qcby.util;
/**
* 设置响应头
*/
public class ResponseUtil {
public static final String responseHeader200 = "HTTP/1.1 200 \r\n"+
"Content-Type:text/html\r\n"+"\r\n";
public static String getResponseHeader404(){
return "HTTP/1.1 404 \r\n"+
"Content-Type:text/html\r\n"+"\r\n" + "404";
}
public static String getResponseHeader200(String context){
return "HTTP/1.1 200\r\n"+
"Content-Type:text/html\r\n"+"\r\n" + context;
}
}
package com.qcby.util;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
public class SearchClassUtil {
public static List<String> classPaths = new ArrayList<>();
public static List<String> searchClass() {
// 需要扫描的包名
String basePack = "com.qcby.myweb";
try {
// 使用字符串替换
Enumeration<URL> resources = SearchClassUtil.class.getClassLoader().getResources(basePack.replace(".", "/"));
while (resources.hasMoreElements()) {
URL url = resources.nextElement();
String protocol = url.getProtocol();
if ("file".equals(protocol)) {
String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
doPath(new File(filePath), basePack);
} else if ("jar".equals(protocol)) {
// 处理JAR包情况
System.out.println("暂未完整处理JAR包情况");
}
}
} catch (IOException e) {
e.printStackTrace();
}
return classPaths;
}
/**
* 该方法会得到所有的类,将类的绝对路径写入到classPaths中
*
* @param file 当前文件或目录
* @param basePack 基础包名
*/
private static void doPath(File file, String basePack) {
if (file.isDirectory()) {
File[] files = file.listFiles();
if (files != null) {
for (File subFile : files) {
doPath(subFile, basePack);
}
}
} else if (file.getName().endsWith(".class")) {
String classFilePath = file.getAbsolutePath();
// 使用字符串替换
classFilePath = classFilePath.substring(classFilePath.indexOf(basePack.replace(".", File.separator)));
classFilePath = classFilePath.replace(File.separator, ".");
classFilePath = classFilePath.substring(0, classFilePath.length() - 6);
classPaths.add(classFilePath);
}
}
public static void main(String[] args) {
List<String> paths = searchClass();
for (String path : paths) {
System.out.println(path);
}
}
}
package com.qcby;
import com.qcby.config.TomcatRoute;
import com.qcby.requset.HttpServletRequest;
import com.qcby.response.HttpServletResponse;
import com.qcby.servlet.HttpServlet;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
public class MyTomcat {
static HashMap<String, HttpServlet> routes = TomcatRoute.routes; //tomcat路由\
/**
* 分发器
*/
public void dispatch(HttpServletRequest request ,HttpServletResponse response) throws IOException {
HttpServlet servlet = routes.get(request.getUrl()); //
if(servlet!=null){ //说明请求的就是我们的servlet
servlet.service(request,response);
}
}
/**
* socket 启动
* @throws IOException
*/
public void start() throws IOException {
ServerSocket serverSocket = new ServerSocket(8080); //1.指定监听的端口号
//2.对端口进行监听
while (true){
Socket socket = serverSocket.accept();//阻塞监听
//3.打开输入流,解析客户端发来的内容
InputStream inputStream = socket.getInputStream(); //输入流
HttpServletRequest request = new HttpServletRequest();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); //将字节流转换成字符流
String str = reader.readLine();
request.setMethod(str.split("\\s")[0]);
request.setUrl(str.split("\\s")[1]);
//4.打开输出流
OutputStream outputStream = socket.getOutputStream();
HttpServletResponse response = new HttpServletResponse(outputStream);
dispatch(request,response);
}
}
//socket
public static void main(String[] args) throws IOException {
MyTomcat myTomcat = new MyTomcat();
myTomcat.start();
}
}