【SpringMVC】模拟SpringMVC中DispatcherServlet的底层运行机制

DispatcherServlet本质上就是一个HttpServlet。同时它是SpringMVC中最为核心的一块——前端控制器。它主要用来拦截符合要求的外部请求,并把请求分发到不同的控制器去处理,根据控制器处理后的结果,生成相应的响应发送到客户端。

封装内容

web.xml

<servlet>
	<servlet-name>servletservlet-name>
	<servlet-class>com.test.util.web.DispatcherServletservlet-class>
servlet>
<servlet-mapping>
	<servlet-name>servletservlet-name>
	<url-pattern>*.actionurl-pattern>
servlet-mapping>

Controller.java

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Controller {

}

RequestMapping.java

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMapping {

    String value();

}

ServletNotFoundException.java

public class ServletNotFoundException extends Exception {

    private String message;

    public ServletNotFoundException(String message) {
        super(message);
    }

}

DispatcherServlet.java

public class ServletManager extends HttpServlet {

    // 存储请求和类的对应关系
    private static Map<String, Class> classMap = new HashMap<>();
    // 存储类和类对象的对应关系
    private static Map<Class, Object> objectMap = new HashMap<>();
    // 存储请求和方法的对应关系
    private static Map<String, Method> methodMap = new HashMap<>();

    /**
     *  类加载器加载项目中多个Class文件的步骤:
     *      1.获取类加载器
     *      2.获取执行目录的根目录URL
     *      3.通过根URL深度优先搜索找到所有.class的文件的URL
     *      4.处理URL获取类全名
     *      5.通过反射加载并该Class,执行相关操作
     */
    static {
        try {
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

            Enumeration en = classLoader.getResources("");
            if (en.hasMoreElements()) {
                URL rootURL = (URL) en.nextElement();
                File rootFile = new File(rootURL.getPath());
                analyzePath(rootFile, "");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void analyzePath(File file, String path) {
        if (file == null) {
            return;
        }
        if (file.isDirectory()) {//目录处理
            File[] files = file.listFiles();
            for (File temp : files) {
                analyzePath(temp, path + "." + temp.getName());
            }
        } else {//文件处理
            // 处理 .com.donkfer.orm.Table.class
            try {
                //判断是否为.class文件
                if (file.getName().endsWith(".class")) {
                    String classFullName = path.substring(1, path.lastIndexOf("."));
                    Class clazz = Class.forName(classFullName);
                    // 判断是不是api
                    if (clazz.getAnnotation(Controller.class) != null) {
                        loadClassAndMethods(clazz);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private static void loadClassAndMethods(Class clazz) throws IllegalAccessException, InstantiationException {
        if (clazz != null) {
            Object object = clazz.newInstance();
            Method[] methods = clazz.getDeclaredMethods();
            for (Method method : methods) {
                String requestMapping = method.getAnnotation(RequestMapping.class).value();
                if (requestMapping != null) {
                    classMap.put(requestMapping, clazz);
                    methodMap.put(requestMapping, method);
                    if (objectMap.get(clazz) == null) {
                        objectMap.put(clazz, object);
                    }
                }
            }
        }
    }

    public void executeMethod(HttpServletRequest request, HttpServletResponse response) {
        try {
            request.setCharacterEncoding("utf-8");
            String path = request.getServletPath();
            Method method = methodMap.get(path);
            if (method != null) {
                Class clazz = classMap.get(path);
                Object object = objectMap.get(clazz);
                method.invoke(object, request, response);
            } else {
                throw new ServletNotFoundException("Servlet is not found");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        executeMethod(request, response);
    }

}

封装结果

TestController.java

@Controller
public class TestController {

    @RequestMapping("testOne.action")
    public void testOne(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("testOne执行");
    }

}

你可能感兴趣的:(【SpringMVC】模拟SpringMVC中DispatcherServlet的底层运行机制)