文档章节

SpringMVC 注解开发 底层实现原理模拟

Grey_Gao
 Grey_Gao
发布于 2017/09/08 13:58
字数 507
阅读 8
收藏 0
package com.wuqi.servlet;

import com.wuqi.annotation.*;
import com.wuqi.controller.SpringmvcController;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Created by Shock on 2017/3/23.
 */
public class DispatcherServlet extends HttpServlet{
    private static final long serialVersionUID = 1L;
    List<String> packageNames = new ArrayList<String>();
    // 所有类的实例,key是注解的value,value是所有类的实例
    Map<String, Object> instanceMap = new HashMap<String, Object>();
    Map<String, Object> handerMap = new HashMap<String, Object>();
    public DispatcherServlet() {
        super();
    }

    public void init(ServletConfig config) throws ServletException {
        // 包扫描,获取包中的文件
        scanPackage("com.wuqi");
        try {
            filterAndInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 建立映射关系
        handerMap();
        // 实现注入
        ioc();
    }

    private void filterAndInstance() throws Exception {
        if (packageNames.size() <= 0) {
            return;
        }
        for (String className : packageNames) {
            Class<?> cName = Class.forName(className.replace(".class", "").trim());
            if (cName.isAnnotationPresent(Controller.class)) {
                Object instance = cName.newInstance();
                Controller controller = (Controller) cName.getAnnotation(Controller.class);
                String key = controller.value();
                instanceMap.put(key, instance);
            } else if (cName.isAnnotationPresent(Service.class)) {
                Object instance = cName.newInstance();
                Service service = (Service) cName.getAnnotation(Service.class);
                String key = service.value();
                instanceMap.put(key, instance);
            } else {
                continue;
            }
        }
    }

    private void ioc() {

        if (instanceMap.isEmpty())
            return;
        for (Map.Entry<String, Object> entry : instanceMap.entrySet()) {
            // 拿到里面的所有属性
            Field fields[] = entry.getValue().getClass().getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);// 可访问私有属性
                if (field.isAnnotationPresent(Quatifier.class));
                Quatifier quatifier = field.getAnnotation(Quatifier.class);
                String value = quatifier.value();
                field.setAccessible(true);
                try {
                    field.set(entry.getValue(), instanceMap.get(value));
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
        SpringmvcController wuqi = (SpringmvcController) instanceMap.get("wuqi");
        System.out.print(wuqi);
    }

    /**
     * 扫描包下的所有文件
     *
     * @param Package
     */
    private void scanPackage(String Package) {
        URL url = this.getClass().getClassLoader().getResource("/" + replaceTo(Package));// 将所有的.转义获取对应的路径
        String pathFile = url.getFile();
        File file = new File(pathFile);
        String fileList[] = file.list();
        for (String path : fileList) {
            File eachFile = new File(pathFile + path);
            if (eachFile.isDirectory()) {
                scanPackage(Package + "." + eachFile.getName());
            } else {
                packageNames.add(Package + "." + eachFile.getName());
            }
        }
    }

    /**
     * 建立映射关系
     */
    private void handerMap() {
        if (instanceMap.size() <= 0)
            return;
        for (Map.Entry<String, Object> entry : instanceMap.entrySet()) {
            if (entry.getValue().getClass().isAnnotationPresent(Controller.class)) {
                Controller controller = (Controller) entry.getValue().getClass().getAnnotation(Controller.class);
                String ctvalue = controller.value();
                Method[] methods = entry.getValue().getClass().getMethods();
                for (Method method : methods) {
                    if (method.isAnnotationPresent(RequestMapping.class)) {
                        RequestMapping rm = (RequestMapping) method.getAnnotation(RequestMapping.class);
                        String rmvalue = rm.value();
                        handerMap.put("/" + ctvalue + "/" + rmvalue, method);
                    } else {
                        continue;
                    }
                }
            } else {
                continue;
            }

        }
    }

    private String replaceTo(String path) {
        return path.replaceAll("\\.", "/");
    }

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

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String url = req.getRequestURI();
        String context = req.getContextPath();
        String path = url.replace(context, "");
        Method method = (Method) handerMap.get(path);
        SpringmvcController controller = (SpringmvcController) instanceMap.get(path.split("/")[1]);
        try {
            method.invoke(controller, new Object[] { req, resp, null });
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

DispatcherServlet

感谢原作者的分享,这段代码对于帮助新手了解SpringMVC注解实现非常有用

本文转载自:http://www.cnblogs.com/Shock-W/p/6617068.html

共有 人打赏支持
Grey_Gao
粉丝 0
博文 1
码字总数 0
作品 0
程序员
私信 提问
spring-AOP原理与应用

什么是AOP Spring是解决实际开发中的一些问题: * AOP解决OOP中遇到的一些问题.是OOP的延续和扩展. AOP作用 对程序进行增强:不修改源码的情况下. * AOP可以进行权限校验,日志记录,性能监控,事...

叫我北北
2018/06/29
0
0
Spring Boot系列——Spring Boot如何启动

Spring Boot启动过程 上篇《Spring Boot系列——5分钟构建一个应用》介绍了如何快速创建一个Spring Boot项目并运行。虽然步骤少流程简单,为开发者省去了很多重复性的配置工作,但是其底层实...

Jackie_Zheng
2018/08/26
0
0
Spring Validation实现原理分析

最近要做动态数据的提交处理,即需要分析提交数据字段定义信息后才能明确对应的具体字段类型,进而做数据类型转换和字段有效性校验,然后做业务处理后提交数据库,自己开发一套校验逻辑的话周...

68号小喇叭
2018/07/08
0
0
Spring Boot系列——5分钟构建一个应用

5分钟构建一个应用?没错!一点没有夸张,甚至不用5分钟就可以快速搭建并启动一个应用。 环境配置 1、JDK版本:Java8 2、IDE版本:Intellij IDEA 2018.1 3、系统:MAC OS 构建步骤 1、创建项...

Jackie_Zheng
2018/08/19
0
0
SpringMVC架构原理分析

springmvc框架原理(掌握) 前端控制器、处理器映射器、处理器适配器、视图解析器 springmvc入门程序 目的:对前端控制器、处理器映射器、处理器适配器、视图解析器学习;非注解的处理器映射...

小小蒜头
2017/11/30
0
0

没有更多内容

加载失败,请刷新页面

加载更多

IDE 插件新版本发布,开发效率 “biu” 起来了

近日,Cloud Toolkit正式推出了面向 IntelliJ 和 Eclipse 两个平台的新款插件,本文挑选了其中三个重大特性进行解读,点击文末官网跳转链接,可查看详细的版本说明。 本地应用一键部署到任何...

阿里云云栖社区
22分钟前
5
0
金丝雀发布、滚动发布、蓝绿发布到底有什么差别?关键点是什么?

根据 2017 年的 DevOps 发展报告,高效能组织和低效能组织在软件交付的效率上有数量级上的差异。技术组织的软件交付能力是一种综合能力,涉及众多环节,其中发布是尤为重要的环节。 作为技术...

问题终结者
50分钟前
3
0
Kubernetes Client-go Informer 源码分析

几乎所有的Controller manager 和CRD Controller 都会使用Client-go 的Informer 函数,这样通过Watch 或者Get List 可以获取对应的Object,下面我们从源码分析角度来看一下Client go Informe...

阿里云官方博客
今天
4
0
传统IDC部署网站(三)

11. 重置密码 密钥和密码都支持远程登陆, 二选一 两个都可以登陆, 密钥相对于密码来说,相对安全一点 本地登陆无法是用密钥 修改密码 root 用户 passwd root 修改普通用户 passwd usernam...

miko0089
今天
6
0
bash特性

1.支持别名 alias 2.命令替换 $(COMMANS) 或者 `COMMAND` 3. bash支持的引号: `` :命令替换 "":弱引用,可以实现变量替换 '':强引用,不实现变量替换 4.文件名通配 globbing:(man 7 glo...

忙碌的小蜜蜂
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部