zoukankan      html  css  js  c++  java
  • 《四 spring源码》手写springmvc

    手写SpringMVC思路

    1.web.xml加载

     为了读取web.xml中的配置,我们用到ServletConfig这个类,它代表当前Servlet在web.xml中的配置信息。通过web.xml中加载我们自己写的MyDispatcherServlet和读取配置文件。

    2、初始化阶段

      在前面我们提到DispatcherServlet的initStrategies方法会初始化9大组件,但是这里将实现一些SpringMVC的最基本的组件而不是全部,按顺序包括:

    • 加载配置文件
    • 扫描用户配置包下面所有的类
    • 拿到扫描到的类,通过反射机制,实例化。并且放到ioc容器中(Map的键值对 beanName-bean) beanName默认是首字母小写
    • 初始化HandlerMapping,这里其实就是把url和method对应起来放在一个k-v的Map中,在运行阶段取出

    3、运行阶段

      每一次请求将会调用doGet或doPost方法,所以统一运行阶段都放在doDispatch方法里处理,它会根据url请求去HandlerMapping中匹配到对应的Method,然后利用反射机制调用Controller中的url对应的方法,并得到结果返回。按顺序包括以下功能:

    • 异常的拦截
    • 获取请求传入的参数并处理参数
    • 通过初始化好的handlerMapping中拿出url对应的方法名,反射调用

    手写SpringMVC基本实现

    /**
     * 手写SpringMVC框架 作者:每特教育-余胜军<br>
     * 
     * @QQ644064779 1.自定义DispatcherServlet<br>
     *              2.servlet init()方法初始化###只会执行一次<br>
     *              ######2.1获取当前包下所有的类<br>
     *              ######2.2初始化当前包下所有的类,使用Java反射机制初始化对象存放在SpringMVC容器中key(beanId)-
     *              value( 当前实例对象) <br>
     *              ######2.3初始化HandlerMapping方法,将url和方法对应上 <br>
     *              ########2.3.1使用Java反射技术读取类的信息,存放在map集合中key为url请求地址,value为对应方法
     *              <br>
     *              ########2.3.2使用Java反射技术读取类的信息,存放在map集合中key为url请求地址,value为对应实例对象
     *              <br>
     *              3.servlet get或者post请求<br>
     *              ######## 3.1.1获取请求地址,使用Java反射技术找到对应的方法和实例对象进行执行 <br>
     */
    public class ExtDispatcherServlet extends HttpServlet {
        // mvc bean key=beanid ,value=对象
        private ConcurrentHashMap<String, Object> mvcBeans = new ConcurrentHashMap<String, Object>();
        // mvc 请求方法 key=requestUrl,value=对象
        private ConcurrentHashMap<String, Object> mvcBeanUrl = new ConcurrentHashMap<String, Object>();
        // mvc 请求方法 key=requestUrl,value=方法
        private ConcurrentHashMap<String, String> mvcMethodUrl = new ConcurrentHashMap<String, String>();
    
        /**
         * 初始化自定义SpringMVC容器
         */
        public void init() throws ServletException {
            try {
                // 1.获取当前包下所有的类
                List<Class<?>> classes = ClassUtil.getClasses("com.itmayiedu.ext.controller");
                // 2.初始化当前包下所有的类,使用Java反射机制初始化对象存放在SpringMVC容器中key(beanId)-value(
                // 当前实例对象)
                findClassMVCBeans(classes);
                // 3.初始化HandlerMapping方法,将url和方法对应上
                handlerMapping(mvcBeans);
    
            } catch (Exception e) {
    
            }
        }
    
        // 2.初始化当前包下所有的类,使用Java反射机制初始化对象存放在SpringMVC容器中key(beanId)-value(
        // 当前实例对象)
        public void findClassMVCBeans(List<Class<?>> classes)
                throws ClassNotFoundException, InstantiationException, IllegalAccessException {
            mvcBeans = new ConcurrentHashMap<String, Object>();
            for (Class<?> classInfo : classes) {
                ExtController extController = classInfo.getDeclaredAnnotation(ExtController.class);
                if (extController != null) {
                    // 默认类名小写 作为bean的名称
                    String beanId = ClassUtil.toLowerCaseFirstOne(classInfo.getSimpleName());
                    mvcBeans.put(beanId, ClassUtil.newInstance(classInfo));
                }
            }
    
        }
    
        // 3.初始化HandlerMapping方法,将url和方法对应上
        public void handlerMapping(ConcurrentHashMap<String, Object> mvcBeans) {
            // 遍历mvc bean对象
            for (Map.Entry<String, Object> entry : mvcBeans.entrySet()) {
                // springmvc 注入object对象
                Object mvcObject = entry.getValue();
                // 判断类上是否有@ExtRequestMapping注解
                Class<? extends Object> classInfo = mvcObject.getClass();
                String requestBaseUrl = null;
                ExtRequestMapping classExtRequestMapping = classInfo.getAnnotation(ExtRequestMapping.class);
                if (classExtRequestMapping != null) {
                    requestBaseUrl = classExtRequestMapping.value();
                }
                // 遍历当前类的所有方法,判断方法上是否有注解
                Method[] declaredMethods = classInfo.getDeclaredMethods();
                for (Method method : declaredMethods) {
                    ExtRequestMapping methodExtRequestMapping = method.getDeclaredAnnotation(ExtRequestMapping.class);
                    if (methodExtRequestMapping != null) {
                        String httpRequestUrl = methodExtRequestMapping.value();
                        mvcBeanUrl.put(requestBaseUrl + httpRequestUrl, mvcObject);
                        mvcMethodUrl.put(requestBaseUrl + httpRequestUrl, method.getName());
                    }
                }
            }
        }
    
        @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 {
            try {
                doDispatch(req, resp);
            } catch (Exception e) {
                // TODO: handle exception
            }
        }
    
        public void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
            // 1.获取请求url地址
            String requestUrl = req.getRequestURI();
            // 2.使用请求url查找对应mvc 控制器bean
            Object object = mvcBeanUrl.get(requestUrl);
            if (object == null) {
                resp.getWriter().println("http ext not found  controller 404");
                return;
            }
            // 3.获取对应的请求方法
            String methodName = mvcMethodUrl.get(requestUrl);
            if (StringUtils.isEmpty(methodName)) {
                resp.getWriter().println("http ext not found Method 404");
                return;
            }
            // 4.使用java反射技术执行方法
            Class<? extends Object> classInfo = object.getClass();
            String resultPage = (String) methodInvoke(classInfo, object, methodName);
            // 5.视图展示
            viewdisplay(resultPage, req, resp);
        }
    
        // 执行方法
        public Object methodInvoke(Class<? extends Object> classInfo, Object object, String methodName) {
            try {
                Method method = classInfo.getMethod(methodName);
                Object result = method.invoke(object);
                return result;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        // 视图展示
        public void viewdisplay(String pageName, HttpServletRequest req, HttpServletResponse res)
                throws ServletException, IOException {
            // 获取后缀信息
            String suffix = ".jsp";
            // 页面目录地址
            String prefix = "/";
            req.getRequestDispatcher(prefix + pageName + suffix).forward(req, res);
        }
    
    }
  • 相关阅读:
    UIButton的遍历
    UIbutton 圆角和边线
    UIbutton 和UIview 切单角
    为运行Microsoft Dynamics CRM 异步处理服务指定账户没有性能计数器权限
    转:细说ASP.NET Windows身份认证
    CRM 模拟用户
    CRM 2016 Get IOrganizationService
    模拟SQL用户 EXECUTE AS USER
    Calling Custom Actions from JavaScript
    processjs Documentation
  • 原文地址:https://www.cnblogs.com/a1304908180/p/10635914.html
Copyright © 2011-2022 走看看