我的第一个框架:简易版SpringMVC

最近从网上看到一篇做迷你SpringMVC的文章,就决定跟着做一下研究一下

下面是具体的代码和解析

一、项目架构

这里我们缩减了注解的量只是用了最基本的几个注解来完成基本的映射调用

同时这里没有模拟持久层的操作,只是完成前端页面到服务层的映射调用

原文使用了Qualifier按名称进行注入,而我习惯使用@Autowired,所以进行了一部分修改

原文链接https://blog.csdn.net/m0_46995061/article/details/106836614

二、注解代码

1.Autowired

根据类型自动装配

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
    public boolean required() default true;
}

2.Controller

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Controller {
    public String value();
}

3.Service

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Service {
    public String value();
}

4.Repository

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Repository {
    public String value();
}

5.RequestMapping

保存映射路径

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMapping {
    public String value();
}

三、DispatcherServelt

该类是SpringMVC的核心,它完成对所有请求的拦截并根据具体的路径去调用对应的方法进行请求的处理

//注解配置Servlet,需要使用servletapi3.0
//拦截所有请求
//设置启动时加载
//将包扫描的路径引入
@WebServlet(name = "dispatcherServlet",urlPatterns = "/*",loadOnStartup = 1,
    initParams = {@WebInitParam(name = "base-package",value = "com.spring.springmvc")})
public class DispatcherServlet extends HttpServlet {
    //扫描的基包
    private String basepackage = "";
    //基包下所有的全限定类名
    private List<String> packageNames = new ArrayList<String>();
    //注解实例化
    private Map<String,Object> instanceMap = new HashMap<>();
    //注解名称
    private Map<String,String> nameMap  = new HashMap<>();
    //url和方法的映射关系
    private Map<String, Method> urlMathodMap = new HashMap<>();
    //Method和全限定类名的映射关系,通过Method找到该方法的对象利用反射执行
    private Map<Method,String> methodPackageMap = new HashMap<>();

    //重写了Servlet初始化方法,完成一整套容器初始化的执行流程
    //这里使用了一点模板模式的概念,只是没有做类的解耦分离
    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        basepackage = config.getInitParameter("base-package");
        try {
            //扫描包下的类
            scanBasePackage(basepackage);
            //实例化所有符合条件的类(注解了几个自定义注解的类)
            instance(packageNames);
            //依赖注入
            executeIOC();
            //生成映射
            handlerUrlMethodMap();
        }catch (Exception ex){

        }
    }

    private void scanBasePackage(String basepackage){
       // System.out.println(basepackage);
        URL url = this.getClass().getClassLoader().getResource(basepackage.replaceAll("\\.","/"));
        File basePackageFile = new File(url.getPath());
        System.out.println("scan:"+basePackageFile);
        File[] childFiles = basePackageFile.listFiles();
        for(File file:childFiles){
            if(file.isDirectory()){
                scanBasePackage(basepackage+"."+file.getName());
            }else if(file.isFile()){
                packageNames.add(basepackage+"."+file.getName().split("\\.")[0]);
                System.out.println(basepackage+"."+file.getName().split("\\.")[0]);
            }
        }
    }

    public void instance(List<String> packageNames) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        if(packageNames.size()<1){
            return;
        }
        for(String string:packageNames){
            Class c = Class.forName(string);

            if(c.isAnnotationPresent(Controller.class)){
                Controller controller = (Controller)c.getAnnotation(Controller.class);
                String controllerName = controller.value();

                nameMap.put(string,controllerName);
                instanceMap.put(controllerName,c.newInstance());
                System.out.println("Controller : "+ string + ", value : "+controller.value());
            }else if(c.isAnnotationPresent(Service.class)){
                Service service = (Service) c.getAnnotation(Service.class);
                String serviceName = service.value();

                nameMap.put(string,serviceName);
                instanceMap.put(serviceName,c.newInstance());
                System.out.println("Service : "+ string + ", value : "+service.value());
            }else if(c.isAnnotationPresent(Repository.class)){
                Repository repository = (Repository) c.getAnnotation(Repository.class);
                String repositoryName = repository.value();

                nameMap.put(string,repositoryName);
                instanceMap.put(repositoryName,c.newInstance());
                System.out.println("Repository : "+ string + ", value : "+repository.value());
            }
        }
    }

    public void executeIOC() throws ClassNotFoundException, IllegalAccessException {
        for (Map.Entry<String, Object> entry : instanceMap.entrySet()) {
            Field[] fields = entry.getValue().getClass().getDeclaredFields();
            for (Field field : fields) {
                if (field.isAnnotationPresent(Autowired.class)) {
                    boolean isRequired = field.getAnnotation(Autowired.class).required();
                    field.setAccessible(true);
                    for(String name:instanceMap.keySet()){
                        Object object = instanceMap.get(name);
                        if(field.getType().isAssignableFrom(object.getClass())){
                            field.set(entry.getValue(),object);
                        }
                    }
                }
            }
        }
    }

    public void handlerUrlMethodMap() throws ClassNotFoundException {
        if(packageNames.size()<1){
            return;
        }

        for(String name:packageNames){
            Class c = Class.forName(name);
            if(c.isAnnotationPresent(Controller.class)){
                Method[] methods = c.getMethods();
                StringBuffer stringBuffer = new StringBuffer();
                if(c.isAnnotationPresent(RequestMapping.class)){
                    RequestMapping requestMapping = (RequestMapping) c.getAnnotation(RequestMapping.class);
                    stringBuffer.append(requestMapping.value());
                }

                for (Method method:methods){
                    //System.out.println("==================");
                    if(method.isAnnotationPresent(RequestMapping.class)){
                        RequestMapping requestMapping = (RequestMapping)method.getAnnotation(RequestMapping.class);
                        stringBuffer.append(requestMapping.value());
                        urlMathodMap.put(stringBuffer.toString(),method);
                        System.out.println(stringBuffer);
                        methodPackageMap.put(method,name);
                    }
                }
            }
        }
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
        String uri = req.getRequestURI();
        String contextPath = req.getContextPath();
        String path = uri.replaceAll(contextPath,"");
        Method method = urlMathodMap.get(path);
        if(method==null){
            Writer writer = resp.getWriter();
            writer.write("网站输入无效404");
        }else{
            String packageName = methodPackageMap.get(method);
            String controllerName =nameMap.get(packageName);
            System.out.println(controllerName);
            System.out.println(instanceMap);

            MyController myController = (MyController) instanceMap.get(controllerName);

            try{
                System.out.println(method.getName());
                method.setAccessible(true);
                method.invoke(myController);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }

    }
}

四、Controller层代码

@Controller("myController")
public class MyController {

    @Autowired
    MyService service;

    @RequestMapping("/aaa")
    public String first(){
        System.out.println("It's controller");
        service.invokeService();
        return "";
    }
}

五、Service层代码

public interface MyService {
    public void invokeService();
}

@Service("myService")
public class MyServiceImpl implements MyService {
    @Override
    public void invokeService() {
        System.out.println("I'ts Service");
    }
}

六、maven依赖

<dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
    </dependency>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

原来是肖某人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值