美文网首页
MVC原生实现

MVC原生实现

作者: stutterr | 来源:发表于2017-07-26 19:24 被阅读43次

    JAVAEE实现MVC

    java反射机制基础知识

    Reflection,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods

    实现

    1. 新建一个DispatcherServlet 并且在类下顶一个
    
       public DispatcherServlet() {
          actionConfigs.put("question_list.aciton", new ActionConfig("com.gavin.exam.controller.QuestionController","save"));
       }
    
    2. 将web.xml 中改Servlet的<url-pattern>*.action</url-pattern>

    代表该servlet接收所有以.action结尾的路径。

    3. 新建一个Controller 包 并且新建一个XxxxController 定义方法
    4. 在common 包下在定义一个classaction.config
    package com.gavin.exam.common;
    
    public class ActionConfig {
    
        private String clsssName;
        private String methodName;
        
        public ActionConfig(String clsssName, String methodName) {
            this.clsssName = clsssName;
            this.methodName = methodName;
        }
    
        public String getClsssName() {
            return clsssName;
        }
        
        public void setClsssName(String clsssName) {
            this.clsssName = clsssName;
        }
        
        public String getMethodName() {
            return methodName;
        }
        
        public void setMethodName(String methodName) {
            this.methodName = methodName;
        }
    }
    
    5. 在DispatcherServlet中提取得的地址通过Map查询匹配className 和MethodName。

    通过反射机制来达到通过一个servlet来实现整合其他servlet

        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String uri = request.getRequestURI();
            String requestedUri = uri.substring(request.getContextPath().length() + 1);
            ActionConfig actionConfig = actionConfigs.get(requestedUri);
            if (actionConfig != null) {
                String className = actionConfig.getClsssName();
                System.out.println(className);
                try {
                    //定义传入的参数是类型
                    Class<?>[] param = new Class[2];
                    param[0] = HttpServletRequest.class;
                    param[1] = HttpServletResponse.class;
    
                    //根据class名字找到class并且初始化
                    Class<?> cls = Class.forName(className);
                    Object controller = cls.newInstance();
    
                    //获得Reflect的方法,第一个参数是方法名,第二个参数是参数类型
                    String methodName = actionConfig.getMethodName();
                    Method method = cls.getMethod(methodName,param);
    
                    //定义传入的参数
                    Object[] objects = new Object[2];
                    objects[0] = request;
                    objects[1] = response;
    
                    //开始调用方法,第一个参数是调用该方法的对象,第二个
                    //参数的值
                    method.invoke(controller, objects);
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    

    这样我们就通过反射机制动态的由访问的路径动态的得到了需要调用来处理的类与方法。

    6. controller 中method的实现

    首先,讲双H参数传入方法中。
    public void showList(HttpServletRequest request, HttpServletResponse response) { System.out.println("showList"); }

    之后将servlet中的方法copy到对应方法中,
    如果一个servlet 有get 和 post 两个方法,则对应相应的方法放入。

    7. 实现所有方法后

    DispatcherServlet 中调用get方法

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    
    8. MVC优化之controller移走response

    common包中创建一个classModelAndView。代码如下:

    package com.gavin.exam.common;
    
    public class ModelAndView {
    
       private String view;
       private boolean isRedirect = false;
    
       public String getView() {
           return view;
       }
    
       public void setView(String view) {
           this.view = view;
       }
    
       public boolean isRedirect() {
           return isRedirect;
       }
    
       public void setRedirect(boolean isRedirect) {
           this.isRedirect = isRedirect;
       }
    }
    

    将方法中的返回值设为ModelAndView 并将参数HttpServletResponse response 去掉。在DispatcherServlet 中同样也需要去掉参数与参数类型的传入。
    同时将method.invoke(controller, objects); 的返回值强制转换:
    ModelAndView modelAndView = (ModelAndView)method.invoke(controller, objects);
    取得返回数值,根据相应进行sendRedirect orgetRequestDispatcher

     String view = modelAndView.getView();
                    if (modelAndView.isRedirect) {
                        response.sendRedirect(view);
                    } else {
                        request.getRequestDispatcher(view).forward(request, response);
                    }
    
    8. MVC优化之controller移走response
    1. 定义暂存session的Map

    ModelAndView中再定义一个Map 来暂存session 并设定add和remove方法 提供set

        private Map<String, Object> sessions = new HashMap<String, Object>();
        
        public Map<String, Object> getSessions() {
            return sessions;
        }
    
        public void setSessions(Map<String, Object> sessions) {
            this.sessions = sessions;
        }
    
         public void addSessionAttribute(String key, Object object) {
            sessions.put(key, object);
        }
        
        public void removeSessionAttribute(String key){
            
        }
    
    
    2. 定义暂存request.setAttribute andrequest.getParameter的的Map

    ModelAndView中再定义一个Map 来暂存request的参数 并设定add方法。作坊

        private Map<String, String> requests = new HashMap<String, String>();
    
        public void addRequestAttribute(String key, String value) {
            requests.put(key, value);
        }
    
    
    3.DispatcherServlet 获取暂存在modelAndView中的session
        Map<String,Object> fromControllerSession = modelAndView.getSessions();
        Set<String> keys = fromControllerSession.keySet(); //get all keys from map
        for (String key: keys) {
            session.setAttribute(key, fromControllerSession.get(key));
        }
    
    4.DispatcherServlet 获取暂存在modelAndView中的ReuqetsAttr
                    Map<String,String> fromControllerRequests = modelAndView.getRequests();
                    Set<String> keyRequests = fromControllerRequests.keySet(); //get all keys from map
                    for (String key: keyRequests) {
                        request.setAttribute(key, fromControllerRequests.get(key));
                    }
    
    5. DispatcherServlet 将暂存的session传递到method
        Map<String, Object> SessionMap = new HashMap<String, Object>();
                    
        Enumeration<String> toSessionkeys = session.getAttributeNames();
        while (toSessionkeys.hasMoreElements()) {
                        String toKey = toSessionkeys.nextElement();
                        SessionMap .put(toKey, session.getAttribute(toKey));
        }
    
    6. DispatcherServlet 将Parameter传递到method
        Map<String, String> parameterMap = new HashMap<String, String>();
        Enumeration<String> toReuqestkeys = request.getAttributeNames();
        while (toReuqestkeys.hasMoreElements()) {
                        String toKey = toReuqestkeys.nextElement();
                        parameterMap.put(toKey, request.getParameter(toKey));
        }
    
    7. 将SessionMapparameterMap作为参数传入回到其他Method中。
        //定义传入参数类型
        Class<?>[] param = new Class[2];
        param[0] = Map.class;  
        param[1] = Map.class;
    
        //定义传入的参数
        Object[] objects = new Object[2];
        objects[0] = SessionMap;
        objects[1] = parameterMap;
    
    9 将method中的参数改为(Map<String, String> request, Map<String, Object> session)同时返回类型为ModelAndView1
    10. DispatcherServlet doGet完整代码

    ···
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String uri = request.getRequestURI();
    String requestedUri = uri.substring(request.getContextPath().length() + 1);

        if (StringUtil.isEmpty(requestedUri)) {
            requestedUri = Constants.LOGIN_VIEW;
        }
        ActionConfig actionConfig = actionConfigs.get(requestedUri);
        HttpSession session =request.getSession();
    
        if (actionConfig != null) {
            String className = actionConfig.getClsssName();
            try {
                //定义传入的参数的!类型!
                Class<?>[] param = new Class[2];
                param[0] = Map.class;
                param[1] = Map.class;
    
                Class<?> cls = Class.forName(className);
                Object controller = cls.newInstance();
    
                String methodName = actionConfig.getMethodName();
                Method method = cls.getMethod(methodName, param);
    
    
                //write the session and request and send to method
                Map<String, Object> SessionMap = new HashMap<String, Object>();
                Enumeration<String> toSessionkeys = session.getAttributeNames();
                while (toSessionkeys.hasMoreElements()) {
                    String toKey = toSessionkeys.nextElement();
                    SessionMap.put(toKey, session.getAttribute(toKey));
                }
    
                Map<String, String> parameterMap = new HashMap<String, String>();
                Enumeration<String> toReuqestkeys = request.getAttributeNames();
                while (toReuqestkeys.hasMoreElements()) {
                    String toKey = toReuqestkeys.nextElement();
                    parameterMap.put(toKey, request.getParameter(toKey));
                }
    
                //定义传入的参数
                Object[] objects = new Object[2];
                objects[0] = SessionMap;
                objects[1] = parameterMap;
    
    
                ModelAndView modelAndView = (ModelAndView)method.invoke(controller, objects);
    
                //get the session and requets from modelAndView
                Map<String,Object> fromControllerSession = modelAndView.getSessions();
                Set<String> keys = fromControllerSession.keySet(); //get all keys from map
                for (String key: keys) {
                    session.setAttribute(key, fromControllerSession.get(key));
                }
    
                Map<String,Object> fromControllerRequests = modelAndView.getRequests();
                Set<String> keyRequests = fromControllerRequests.keySet(); //get all keys from map
                for (String key: keyRequests) {
                    request.setAttribute(key, fromControllerRequests.get(key));
                }
    
                String view = modelAndView.getView();
                if (modelAndView.isRedirect) {
                    response.sendRedirect(view);
                } else {
                    request.getRequestDispatcher(view).forward(request, response);
    
                }
    
    
            } catch (Exception e) {
                e.printStackTrace();
                response.sendError(500);
            }
        }
        else {
            response.sendError(404);
        }
    }
    

    ···

    相关文章

      网友评论

          本文标题:MVC原生实现

          本文链接:https://www.haomeiwen.com/subject/sfbgkxtx.html