自定义一个简单的SpringMVC框架

思路分析

  • 在服务器启动时,就扫描包下所有类:得到有注解@Controller的类
    • 反射生成这个类的实例对象:object
    • 遍历类里所有的方法,得到方法对象:method
    • 获取每个方法上@RequestMapping配置的映射路径:mappingPath
    • 把方法对象method和类实例对象object,封装成对象:MvcMethod
    • mappingPath为key,MvcMethod对象为value,保存到一个Map中
  • 当客户端请求到DispatcherServlet
    • 获取请求的资源路径:path
    • 从Map容器中找到对应的MvcMethod
    • 反射执行MvcMethod中的方法对象
实现
@Controller注解
package com.lily.SpringMVC_02;

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 Controller {
}
@RequestMapping
package com.lily.SpringMVC_02;

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

/**
 * 功能描述:〈用在业务控制器的方法上,用来声明 方法的路径〉
 */
@Target(ElementType.METHOD)             //元注解: 表示在方法总运行
@Retention(RetentionPolicy.RUNTIME)   //元注解: 表示保留到运行阶段
public @interface RequestMapping {
    String value();                     //配置的映射路径
}
MvcMethod
package com.lily.SpringMVC_02;/*
@Author:李正铠
@Date:2020年03月02日21时13分
*/
import java.lang.reflect.Method;
public class MvcMethod {
    private Method method;
    private Object object;

    public MvcMethod() {
    }

    public MvcMethod(Method method, Object object) {
        this.method = method;
        this.object = object;
    }

    public Method getMethod() {
        return method;
    }

    public void setMethod(Method method) {
        this.method = method;
    }

    public Object getObject() {
        return object;
    }

    public void setObject(Object object) {
        this.object = object;
    }
}
DispatcherServlet
/**
package com.lily.SpringMVC_02;/*
@Author:李正铠
@Date:2020年03月02日22时26分
*/

import com.lily.util.ClassScannerUtils;

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;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@WebServlet(urlPatterns = "*.do", loadOnStartup = 1)
public class DispatcherServlet extends HttpServlet {
    /**
     * 功能描述:〈重写init方法,配置注解:loadOnStartup,当值是整数,代表服务器启动时执行init方法〉
     */
    private Map<String, MvcMethod> map = new HashMap<>();

    @Override
    public void init() throws ServletException {
        try {
            List<Class<?>> classsFromPackage = ClassScannerUtils.getClasssFromPackage("com.lily.web");
            for (Class<?> clazz : classsFromPackage) {
                boolean isController = clazz.isAnnotationPresent(Controller.class);
                if (!isController) {
                    System.out.println(clazz + "类没有Controller注解");
                    continue;
                }
                Object object = clazz.newInstance();
                Method[] methods = clazz.getMethods();
                for (Method method : methods) {
                    boolean isRequestMapping = method.isAnnotationPresent(RequestMapping.class);
                    if (isRequestMapping) {
                        RequestMapping getRequestMapping = method.getAnnotation(RequestMapping.class);
                        String MappingPath = getRequestMapping.value();
                        MvcMethod mvcMethod = new MvcMethod(method, object);
                        map.put(MappingPath, mvcMethod);
                    }
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String uri = request.getRequestURI();
        String contextPath = request.getContextPath();
        String substring = uri.substring(contextPath.length(), uri.lastIndexOf("."));
        MvcMethod mvcMethod = map.get(substring);
        try {
            mvcMethod.getMethod().invoke(mvcMethod.getObject(), request, response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

ClassScannerUtils

package com.lily.util;

import java.io.File;
import java.io.FileFilter;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;


public class ClassScannerUtils {

    /**
     * 获得包下面的所有的class
     *
     * @param
     * @return List包含所有class的实例
     */
    public static List<Class<?>> getClasssFromPackage(String packageName) {
        List clazzs = new ArrayList<>();
        // 是否循环搜索子包
        boolean recursive = true;
        // 包名对应的路径名称
        String packageDirName = packageName.replace('.', '/');
        Enumeration<URL> dirs;

        try {
            dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
            while (dirs.hasMoreElements()) {

                URL url = dirs.nextElement();
                String protocol = url.getProtocol();
                if ("file".equals(protocol)) {
                    String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
                    findClassInPackageByFile(packageName, filePath, recursive, clazzs);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return clazzs;
    }

    /**
     * 在package对应的路径下找到所有的class
     */
    public static void findClassInPackageByFile(String packageName, String filePath, final boolean recursive,
                                                List<Class<?>> clazzs) {
        File dir = new File(filePath);
        if (!dir.exists() || !dir.isDirectory()) {
            return;
        }
        // 在给定的目录下找到所有的文件,并且进行条件过滤
        File[] dirFiles = dir.listFiles(new FileFilter() {

            public boolean accept(File file) {
                boolean acceptDir = recursive && file.isDirectory();// 接受dir目录
                boolean acceptClass = file.getName().endsWith("class");// 接受class文件
                return acceptDir || acceptClass;
            }
        });

        for (File file : dirFiles) {
            if (file.isDirectory()) {
                findClassInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive, clazzs);
            } else {
                String className = file.getName().substring(0, file.getName().length() - 6);
                try {
                    clazzs.add(Thread.currentThread().getContextClassLoader().loadClass(packageName + "." + className));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }


}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值