栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

手写springMVC2.0版本

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

手写springMVC2.0版本

一.配置web.xml文件

因为没有spring的包,所有用配置文件
这里配置application.properties的地址

二.properties文件

配置项目路径

三.自定义注解

1.@AutoWired

2.@Controller

3.@RequestMapping

4.@RequestParam

5.@Service

这里暂时没有定义@ResponseBody

三.service层

四.controller层

五.DispatcherServlet类代码(重要

使用大量的反射进行操作

public class DDispatcherServlet extends HttpServlet {

    
    private Properties contextConfig=new Properties();
    
    private List classNames=new ArrayList<>();
   
    private Map ioc=new ConcurrentHashMap<>();
    
    private Map handlerMapping=new ConcurrentHashMap<>();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //6.调用,运行阶段
        try {
            doDispatcher(req,resp);
        } catch (Exception e) {
            e.printStackTrace();
            resp.getWriter().write("500"+Arrays.toString(e.getStackTrace()));
        }
    }

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

        //6.调用,运行阶段
        try {
            doDispatcher(req,resp);
        } catch (Exception e) {
            e.printStackTrace();
            resp.getWriter().write("500"+Arrays.toString(e.getStackTrace()));
        }
    }

    private void doDispatcher(HttpServletRequest req, HttpServletResponse resp) throws IOException, InvocationTargetException, IllegalAccessException {
        String url = req.getRequestURI();
        //处理成相对路径
        String contextPath = req.getContextPath();
        url=url.replaceAll(contextPath,"").replaceAll("/+","/");

        if (!handlerMapping.containsKey(url)){
            resp.getWriter().write("404");
        }
        Method method = handlerMapping.get(url);
        //通过反射拿到method所在class
        String beanName =toLowerFirstCase( method.getDeclaringClass().getSimpleName());

        Map params  = req.getParameterMap();
        //获取方法的形参列表
        Class[] parameterTypes = method.getParameterTypes();
        Object[] paramValues= new Object[parameterTypes.length];
        //一维是参数索引,二维是参数注解
        Annotation[][] annotations = method.getParameterAnnotations();

        for (int i = 0; i < parameterTypes.length; i++) {

            Class parameterType = parameterTypes[i];

            if (parameterType==HttpServletRequest.class){
                paramValues[i]=req;
                continue;
            }else if (parameterType==HttpServletResponse.class){
                paramValues[i]=resp;
                continue;
            }else{

                for (Annotation annotation:annotations[i]){
                    //获取参数上的注解
                    DRequestParam requestParam = (DRequestParam) annotation;
                    if (requestParam instanceof DRequestParam){
                        String[] mapValue = params.get(requestParam.value());
                        if (mapValue!=null){
                                //字符串转化
                                Object value = convert(parameterType,Arrays.toString(mapValue) );
                                paramValues[i]=value;
                        }
                    }
                }

            }

        }
        method.invoke(ioc.get(beanName),paramValues);
    }

    
    private Object convert(Class type,String value){
        value = value.replaceAll("\[|\]","")
                .replaceAll("\s",",");

        if (Integer.class==type){
            return Integer.valueOf(value);
        }
        return value;
    }

    
    @Override
    public void init(ServletConfig config) throws ServletException {
        //1.加载配置文件
            doLoadConfig(config.getInitParameter("contextConfigLocation"));

        // 2.扫描相关类
            doScanner(contextConfig.getProperty("scanPackage"));
        //3.初始化扫描到的类,并放入ioc中
            DoInstance();
        //4.完成依赖注入
            doAutoWired();
        //5.初始化HandlerMapping
            initHandlerMapping();

        System.out.println("D Spring frame is init");
    }

    
    private void initHandlerMapping() {
        if (ioc.isEmpty()){
            return;
        }
        Set> entries = ioc.entrySet();
        for (Map.Entry entry : entries) {
            Class clazz = entry.getValue().getClass();
            if (!clazz.isAnnotationPresent(DController.class)){
                continue;
            }
            //保存写在类上的url
            String baseUrl="/";
            if (clazz.isAnnotationPresent(DController.class)){
                DRequestMapping requestMapping = clazz.getAnnotation(DRequestMapping.class);
                baseUrl += requestMapping.value();
            }
            //获取所有public的方法
            Method[] methods = clazz.getMethods();
            for (Method method : methods) {
                if (!method.isAnnotationPresent(DRequestMapping.class)){
                    continue;
                }
                DRequestMapping methodMapping = method.getAnnotation(DRequestMapping.class);
                //如果出现多个斜杆,替换成一个
                String url=(baseUrl+"/"+methodMapping.value()).replaceAll("/+","/");
                //放入映射容器
                handlerMapping.put(url,method);
                System.out.println("url:"+url+":"+method.toString());
            }
        }

    }

    private void doAutoWired() {
        if (ioc.isEmpty()){
            return;
        }

        Set> entries = ioc.entrySet();
        for (Map.Entry entry : entries) {
            //获得一个对象的所有方法
            Field[] fields = entry.getValue().getClass().getDeclaredFields();
            for (Field field : fields) {
                if (field.isAnnotationPresent(DAutowired.class)){
                    DAutowired autowired = field.getAnnotation(DAutowired.class);
                    String beanName = autowired.value().trim();
                    //如果注解默认值为空,则根据类型注入
                    if ("".equals(beanName)){
                        beanName=field.getType().getName();
                    }
                    //赋值
                    try {
                        field.setAccessible(true);
                        field.set(entry.getValue(),ioc.get(beanName));
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }

                }
            }

        }
    }

    private void DoInstance() {
        //初始化,为DI做准备
        if (classNames.isEmpty()){return;}

        for (String className : classNames) {
            try {

                Class clazz = Class.forName(className);

                //加了注解的类需要初始化,这里只举例几个注解
                if (clazz.isAnnotationPresent(DController.class)){
                    Object instance = clazz.getDeclaredConstructor().newInstance();
                    //类名首字母小写
                    String beanName = toLowerFirstCase(clazz.getSimpleName());
                    ioc.put(beanName,instance);
                }else if (clazz.isAnnotationPresent(DService.class)){
                    DService service = clazz.getAnnotation(DService.class);
                    //1.自定义beanName
                    // 获得该注解的默认值
                    String beanName = service.value();

                    //2.默认类名首字母小写
                    if ("".equals(beanName.trim())){
                         beanName = toLowerFirstCase(clazz.getSimpleName());
                    }
                    Object instance = clazz.getDeclaredConstructor().newInstance();
                    //3.根据类型自动注入,扫描该类的所有接口
                    for (Class i:clazz.getInterfaces()){
                        //防止使用相同key名
                        if (ioc.containsKey(i.getName())){
                            throw  new Exception(i.getName()+"该类实例已存在,请更换名字");
                        }
                        ioc.put(i.getName(),instance);
                    }
                }else {
                    continue;
                }

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

    private String toLowerFirstCase(String simpleName) {
        char[] chars = simpleName.toCharArray();
        //大小写字母ASCII码相差32
        if (chars[0]>=65&&chars[0]<=90){
            //说明是一个大写字母
            chars[0] +=32;
        }
        return String.valueOf(chars);
    }

    //扫描相关类
    private void doScanner(String scanPackage) {
        //转化成文件路径:classpath,注意双亲委派机制
        URL url = this.getClass().getClassLoader().getResource(scanPackage.replaceAll("\.","/"));
        File classpath = new File(url.getFile());
        File[] files = classpath.listFiles();
        for (File file : files) {
            if (file.isDirectory()){
                doScanner(scanPackage+"."+file.getName());
            }else {
                if (!file.getName().endsWith(".class")){continue;}
                //得到完整的类名
                String className=(scanPackage+"."+file.getName().replace(".class",""));
                //保存到容器中
                classNames.add(className);
            }
        }
    }

    
    private void doLoadConfig(String contextConfigLocation) {
        InputStream fis=null;
        //直接从类路径下找到Spring主配置文件所在路径
        //将properties文件放到Properties对象中
        fis=this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation);
        try {
            contextConfig.load(fis);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (null!=fis){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/348872.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号