【仿写tomcat】二、扫描java文件,获取带有@WebServlet注解的类

tomcat仿写

项目结构

扫描文件之前当然要确定一下项目结构了,我这里的方案是tomcat和项目同级

项目的话就仿照我们平时使用的结构就好了,我们规定所有的静态资源文件都在webApp目录下存放。

扫描文件

这部分工作我们在仿写spring中已经做过了,我就直接沿用之前的方案了,与之前不同的是我们添加了定位webApp的方法,并且存储在这个工具类里面了,代码如下:

java 复制代码
package com.tomcatServer.utils;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * 扫描工具类
 *
 * @author tomcatProject.ez4sterben
 * @date 2023/08/15
 */
public class ScanUtil {

    public static List<String> javaFiles = new ArrayList<>();
    public static String JAVA = ".java";

    public static String WEB_APP_PATH;

    public static String PROJECT_PATH;


    /**
     * 得到所有java文件
     *
     * @param path 路径
     * @return {@link List}<{@link String}>
     */
    public static List<String> getAllJavaFile(String path){
        getAllFile(new File(path));
        return javaFiles;
    }


    /**
     * 让web应用程序路径
     *
     * @param root 根
     * @return {@link String}
     */
    public static String getWebAppPath(String root){
        File directory = new File(root);
        if (directory.exists() && directory.isDirectory()) {
            findWebAppFolder(directory, "webApp");
        } else {
            System.out.println("Directory does not exist or is not a directory.");
        }
        return PROJECT_PATH;
    }

    /**
     * 找到web应用程序文件夹
     *
     * @param directory        目录
     * @param targetFolderName 目标文件夹名称
     */
    private static void findWebAppFolder(File directory, String targetFolderName) {
        File[] files = directory.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory() && file.getName().equals(targetFolderName)) {
                    PROJECT_PATH = file.getParentFile().getAbsolutePath();
                    WEB_APP_PATH = PROJECT_PATH + "\\webApp";
                } else if (file.isDirectory()) {
                    findWebAppFolder(file, targetFolderName);
                }
            }
        }
    }

    /**
     * 获取所有文件
     *
     * @param file 文件
     */
    public static void getAllFile(File file){
        if (file.isFile()){
            if (file.toString().endsWith(JAVA)) {
                String javaPath = getJavaPath(file);
                javaFiles.add(javaPath);
            }
        }
        if (file.exists() && file.isDirectory()) {
            File[] files = file.listFiles();
            if (files != null) {
                for (File file1 : files) {
                    getAllFile(file1);
                }
            }
        }
    }

    /**
     * 获取java路径
     *
     * @param file 文件
     * @return {@link String}
     */
    private static String getJavaPath(File file) {
        return file.toString().replace("\\",".").split("src.main.java.")[1].replace(".java","");
    }

}

servlet注解

注解这里没什么好说的,自定义一个就行了

java 复制代码
package com.tomcatServer.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * web servlet
 *
 * @author tomcatProject.ez4sterben
 * @date 2023/08/15
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface WebServlet {

    String value() default "";
}

map容器

map容器就是存储servlet实例的地方

java 复制代码
package com.tomcatServer.servlet;

import java.util.HashMap;
import java.util.Map;

/**
 * map存储
 *
 * @author tomcatProject.ez4sterben
 * @date 2023/08/15
 */
public class MapStore {
    public static Map<String,Class<?>> servletMap = new HashMap<>();
}

servlet工具类

目前工具类主要是两个方法,一个是判断java类是否有webservlet注解,另一个是初始化map容器的,将是servlet的类都丢进去,代码逻辑应该很好懂,不需要多说什么。

java 复制代码
package com.tomcatServer.utils;

import com.tomcatServer.annotation.WebServlet;
import com.tomcatServer.servlet.MapStore;

import java.lang.reflect.InvocationTargetException;

/**
 * servlet工具类
 *
 * @author tomcatProject.ez4sterben
 * @date 2023/08/15
 */
public class ServletUtil {

    /**
     * 是web servlet
     *
     * @param className 类名
     * @return {@link Boolean}
     */
    public static Boolean isWebServlet(String className){
        try {
            Class<?> aClass = Class.forName(className);
            WebServlet annotation = aClass.getAnnotation(WebServlet.class);
            if (annotation == null){
                return Boolean.FALSE;
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        return Boolean.TRUE;
    }


    /**
     * 初始化servlet
     *
     * @param className 类名
     */
    public static void initServlet(String className){
        try {
            Class<?> aClass = Class.forName(className);
            String url = aClass.getAnnotation(WebServlet.class).value();
            if (url.startsWith("/")) {
                MapStore.servletMap.put(url,aClass);
            }else {
                MapStore.servletMap.put("/" + url,aClass);
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
}

启动类调用

java 复制代码
package com.tomcatServer;

import com.tomcatServer.utils.MapUtil;
import com.tomcatServer.utils.ScanUtil;

import java.io.IOException;
import java.util.List;

import static com.tomcatServer.utils.ScanUtil.getWebAppPath;

/**
 * tomcat server启动类
 *
 * @author tomcatProject.ez4sterben
 * @date 2023/08/15
 */
public class Main {

    public static String ROOT;

    public static void main(String[] args) throws IOException {
        // 1.初始化根目录
        ROOT = System.getProperty("user.dir");

        // 2.获取webApp的位置
        String webAppPath = getWebAppPath(ROOT);

        // 3.获取所有带有@WebServlet注解的java文件,初始化servlet
        List<String> allJavaFile = ScanUtil.getAllJavaFile(webAppPath);
        for (String s : allJavaFile) {
            if (MapUtil.isWebServlet(s)) {
                ServletUtil.initServlet(s);
            }
        }
        // 4.处理http请求
        
    }
}

到这里基本工作就做完了,下一篇将会带大家完成对http请求的处理

【仿写tomcat】三、通过socket读取http请求信息

相关推荐
Full Stack Developme2 分钟前
Spring 发展历史
java·后端·spring
组合缺一17 分钟前
Java 流程编排新范式 Solon Flow:一个引擎,七种节点,覆盖规则/任务/工作流/AI 编排全场景
java·spring·ai·solon·workflow·flow
largecode20 分钟前
企业号码认证可以线上办理吗?支持线上申请,设置来电显示品牌名
java·python·智能手机·微信公众平台·facebook·paddle·新浪微博
humcomm20 分钟前
2026年 Java 面试新特点
java·开发语言·面试
lili001224 分钟前
CC GUI 插件架构剖析:如何为 JetBrains IDE 打造完整的 AI 编程工作台
java·ide·人工智能·python·架构·ai编程
Royzst28 分钟前
学生信息管理案例
java
爱棋笑谦30 分钟前
单元测试简述
java
音符犹如代码37 分钟前
Docker 一键部署带有 TimescaleDB 插件的 PostgreSQL
java·运维·数据库·后端·docker·postgresql·容器
sleepcattt1 小时前
Java反射技术
java
小锋java12341 小时前
【技术专题】Spring AI 2.0 - Advisors —— 拦截器模式增强AI能力
java·人工智能