zoukankan      html  css  js  c++  java
  • 手写MVC实现过程

    一.手写mvc前基础知识

    1.mvc是什么?

    MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring Web MVC也是要简化我们日常Web开发的。

    2.mvc能帮我们做什么?

    1.让我们能非常简单的设计出干净的Web层和薄薄的Web层;

    2.进行更简洁的Web层的开发;

    3.提供强大的约定大于配置的契约式编程支持;

    4.能简单的进行Web层的单元测试;

    5.支持灵活的URL到页面控制器的映射;

    6.非常灵活的数据验证、格式化和数据绑定机制,能使用任何对象进行数据绑定,不必实现特定框架的API

    7.更加简单的异常处理。

    等等...

    3.spring mvc 架构图

    二. 手写mvc实现过程

    1.定义配置标记

    1.@RequestMapping:标识Controller的方法与请求路径和请求方法的映射关系

    2.@RequestParam:请求的方法参数名称

    3.@ResponseBody:用于标记自动对返回值进行json处理

    2.转发控制器

    核心流程:

    1.初始化

    • 1.初始化容器
    • 2.doAop
    • 3.doIoc
    • 4.初始化请求处理器责任链

    2.处理请求

    • 1.创建责任链对象实例

    • 2.通过责任链模式来依次调用请求处理器对请求进行处理

    • 3.对处理结果进行渲染

    package org.simplespring.mvc;
    import org.simplespring.aop.AspectWeaver;
    import org.simplespring.core.BeanContainer;
    import org.simplespring.inject.DependencyInjector;
    import org.simplespring.mvc.processor.RequestProcessor;
    import org.simplespring.mvc.processor.impl.ControllerRequestProcessor;
    import org.simplespring.mvc.processor.impl.JspRequestProcessor;
    import org.simplespring.mvc.processor.impl.PreRequestProcessor;
    import org.simplespring.mvc.processor.impl.StaticResourceRequestProcessor;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 请求转发器
     */
    @WebServlet("/*")
    public class DispatcherServlet extends HttpServlet {
        List<RequestProcessor> PROCESSOR = new ArrayList<>();
    
        /**
         * 初始化
         * 1.初始化容器
         * 2.doAop
         * 3.doIoc
         * 4.初始化请求处理器责任链
         */
        @Override
        public void init(){
            //1.初始化容器
            BeanContainer beanContainer = BeanContainer.getInstance();
            beanContainer.loadBeans("com.zhangtianci");
            new AspectWeaver().doAop();
            new DependencyInjector().doIoc();
            //2.初始化请求处理器责任链
            PROCESSOR.add(new PreRequestProcessor());
            PROCESSOR.add(new StaticResourceRequestProcessor(getServletContext()));
            PROCESSOR.add(new JspRequestProcessor(getServletContext()));
            PROCESSOR.add(new ControllerRequestProcessor());
        }
    
        /**
         * 1.创建责任链对象实例
         * 2.通过责任链模式来依次调用请求处理器对请求进行处理
         * 3.对处理结果进行渲染
         * @param req
         * @param resp
         */
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) {
            //1.创建责任链对象实例
            RequestProcessorChain requestProcessorChain = new RequestProcessorChain(PROCESSOR.iterator(), req, resp);
            //2.通过责任链模式来依次调用请求处理器对请求进行处理
            requestProcessorChain.doRequestProcessorChain();
            //3.对处理结果进行渲染
            requestProcessorChain.doRender();
        }
    }
    

    3.请求处理责任链

    1.以责任链的模式执行注册的请求处理器

    2.委派给特定的Render实例对处理后的结果进行渲染

    package org.simplespring.mvc;
    
    import lombok.Data;
    import lombok.extern.slf4j.Slf4j;
    import org.simplespring.mvc.processor.RequestProcessor;
    import org.simplespring.mvc.render.DefaultResultRender;
    import org.simplespring.mvc.render.InternalErrorResultRender;
    import org.simplespring.mvc.render.ResultRender;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.util.Iterator;
    
    /**
     * 请求处理责任链
     *
     * 1.以责任链的模式执行注册的请求处理器
     * 2.委派给特定的Render实例对处理后的结果进行渲染
     */
    @Data
    @Slf4j
    public class RequestProcessorChain {
        //请求处理器迭代器
        private Iterator<RequestProcessor> requestProcessorIterator;
        //请求request
        private HttpServletRequest request;
        //请求response
        private HttpServletResponse response;
        //http请求方法
        private String requestMethod;
        //http请求路径
        private String requestPath;
        //http响应状态码
        private  int responseCode;
        //请求结果渲染器
        private ResultRender resultRender;
    
        public RequestProcessorChain(Iterator<RequestProcessor> iterator, HttpServletRequest req, HttpServletResponse resp) {
            this.requestProcessorIterator = iterator;
            this.request = req;
            this.response = resp;
            this.requestMethod = req.getMethod();
            this.requestPath = req.getPathInfo();
            this.responseCode  = HttpServletResponse.SC_OK;
        }
        /**
         * 以责任链的模式执行请求链
         */
        public void doRequestProcessorChain() {
            //1.通过迭代器遍历注册的请求处理器实现类列表
            try{
            while(requestProcessorIterator.hasNext()){
                //2.直到某个请求处理器执行后返回为false为止
                if(!requestProcessorIterator.next().process(this)){
                    break;
                }
            }} catch (Exception e){
                //3.期间如果出现异常,则交由内部异常渲染器处理
                this.resultRender = new InternalErrorResultRender(e.getMessage());
                log.error("doRequestProcessorChain error:", e);
            }
    
    
        }
        /**
         * 执行处理器
         */
        public void doRender() {
            //1.如果请求处理器实现类均未选择合适的渲染器,则使用默认的
            if(this.resultRender == null){
                this.resultRender = new DefaultResultRender();
            }
            //2.调用渲染器的render方法对结果进行渲染
            try {
                this.resultRender.render(this);
            } catch (Exception e) {
                log.error("doRender error: ", e);
                throw new RuntimeException(e);
            }
        }
    }
    

    4.定义RequestProcessor矩阵

    定义处理动作规范

    /**
     * 请求执行器接口
     */
    public interface RequestProcessor {
        boolean process(RequestProcessorChain requestProcessorChain) throws Exception;
    }
    

    请求预处理器

    package org.simplespring.mvc.processor.impl;
    
    import lombok.extern.slf4j.Slf4j;
    import org.simplespring.mvc.RequestProcessorChain;
    import org.simplespring.mvc.processor.RequestProcessor;
    
    /**
     * 请求预处理,包括编码以及路径处理
     */
    @Slf4j
    public class PreRequestProcessor implements RequestProcessor {
        @Override
        public boolean process(RequestProcessorChain requestProcessorChain) throws Exception {
            // 1.设置请求编码,将其统一设置成UTF-8
            requestProcessorChain.getRequest().setCharacterEncoding("UTF-8");
            // 2.将请求路径末尾的/剔除,为后续匹配Controller请求路径做准备
            // (一般Controller的处理路径是/aaa/bbb,所以如果传入的路径结尾是/aaa/bbb/,
            // 就需要处理成/aaa/bbb)
            String requestPath = requestProcessorChain.getRequestPath();
            //http://localhost:8080/simpleframework requestPath="/"
            if(requestPath.length() > 1 && requestPath.endsWith("/")){
                requestProcessorChain.setRequestPath(requestPath.substring(0, requestPath.length() - 1));
            }
            log.info("preprocess request {} {}", requestProcessorChain.getRequestMethod(), requestProcessorChain.getRequestPath());
            return true;
        }
    }
    

    静态资源请求处理器

    package org.simplespring.mvc.processor.impl;
    
    import lombok.extern.slf4j.Slf4j;
    import org.simplespring.mvc.RequestProcessorChain;
    import org.simplespring.mvc.processor.RequestProcessor;
    
    import javax.servlet.RequestDispatcher;
    import javax.servlet.ServletContext;
    
    /**
     * 静态资源请求处理,包括但不限于图片、css、以及js文件等 - DefaultServlet
     */
    @Slf4j
    public class StaticResourceRequestProcessor implements RequestProcessor {
        public static final String DEFAULT_TOMCAT_SERVLET = "default";
        public static final String STATIC_RESOURCE_PREFIX = "/static/";
        //tomcat默认请求派发器RequestDispatcher的名称
        RequestDispatcher defaultDispatcher;
    
        public StaticResourceRequestProcessor(ServletContext servletContext) {
            this.defaultDispatcher = servletContext.getNamedDispatcher(DEFAULT_TOMCAT_SERVLET);
            if(this.defaultDispatcher == null){
                throw new RuntimeException("There is no default tomcat servlet");
            }
            log.info("The default servlet for static resource is {}", DEFAULT_TOMCAT_SERVLET);
        }
    
        @Override
        public boolean process(RequestProcessorChain requestProcessorChain) throws Exception {
            //1.通过请求路径判断是否是请求的静态资源 webapp/static
            if(isStaticResource(requestProcessorChain.getRequestPath())){
                //2.如果是静态资源,则将请求转发给default servlet处理
                defaultDispatcher.forward(requestProcessorChain.getRequest(), requestProcessorChain.getResponse());
                return false;
            }
            return true;
        }
        //通过请求路径前缀(目录)是否为静态资源 /static/
        private boolean isStaticResource(String path){
            return path.startsWith(STATIC_RESOURCE_PREFIX);
        }
    }
    

    jsp资源请求处理器

    package org.simplespring.mvc.processor.impl;
    
    import org.simplespring.mvc.RequestProcessorChain;
    import org.simplespring.mvc.processor.RequestProcessor;
    
    import javax.servlet.RequestDispatcher;
    import javax.servlet.ServletContext;
    
    /**
     * jsp资源请求处理
     */
    public class JspRequestProcessor implements RequestProcessor {
    
        //jsp请求的RequestDispatcher的名称
        private static final String JSP_SERVLET = "jsp";
        //Jsp请求资源路径前缀
        private static final String  JSP_RESOURCE_PREFIX = "/templates/";
    
        /**
         * jsp的RequestDispatcher,处理jsp资源
         */
        private RequestDispatcher jspServlet;
    
        public JspRequestProcessor(ServletContext servletContext) {
            jspServlet = servletContext.getNamedDispatcher(JSP_SERVLET);
            if (null == jspServlet) {
                throw new RuntimeException("there is no jsp servlet");
            }
        }
    
        @Override
        public boolean process(RequestProcessorChain requestProcessorChain) throws Exception {
            if (isJspResource(requestProcessorChain.getRequestPath())) {
                jspServlet.forward(requestProcessorChain.getRequest(), requestProcessorChain.getResponse());
                return false;
            }
            return true;
        }
    
        /**
         * 是否请求的是jsp资源
         */
        private boolean isJspResource(String url) {
            return url.startsWith(JSP_RESOURCE_PREFIX);
        }
    
    }
    

    Controller请求处理器

    package org.simplespring.mvc.processor.impl;
    
    import lombok.extern.slf4j.Slf4j;
    import org.simplespring.core.BeanContainer;
    import org.simplespring.mvc.RequestProcessorChain;
    import org.simplespring.mvc.annotation.RequestMapping;
    import org.simplespring.mvc.annotation.RequestParam;
    import org.simplespring.mvc.annotation.ResponseBody;
    import org.simplespring.mvc.processor.RequestProcessor;
    import org.simplespring.mvc.render.JsonResultRender;
    import org.simplespring.mvc.render.ResourceNotFoundResultRender;
    import org.simplespring.mvc.render.ResultRender;
    import org.simplespring.mvc.render.ViewResultRender;
    import org.simplespring.mvc.type.ControllerMethod;
    import org.simplespring.mvc.type.RequestPathInfo;
    import org.simplespring.util.ConverterUtil;
    import org.simplespring.util.ValidationUtil;
    import javax.servlet.http.HttpServletRequest;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.lang.reflect.Parameter;
    import java.util.*;
    import java.util.concurrent.ConcurrentHashMap;
    
    /**
     * Controller请求处理器
     */
    @Slf4j
    public class ControllerRequestProcessor implements RequestProcessor {
        //IOC容器
        private BeanContainer beanContainer;
        //请求和controller方法的映射集合
        private Map<RequestPathInfo, ControllerMethod> pathControllerMethodMap = new ConcurrentHashMap<>();
    
        /**
         * 依靠容器的能力,建立起请求路径、请求方法与Controller方法实例的映射
         */
        public ControllerRequestProcessor() {
            this.beanContainer = BeanContainer.getInstance();
            Set<Class<?>> requestMappingSet = beanContainer.getClassesByAnnotation(RequestMapping.class);
            initPathControllerMethodMap(requestMappingSet);
        }
    
        private void initPathControllerMethodMap(Set<Class<?>> requestMappingSet) {
            if (ValidationUtil.isEmpty(requestMappingSet)) {
                return;
            }
            //1.遍历所有被@RequestMapping标记的类,获取类上面该注解的属性值作为一级路径
            for (Class<?> requestMappingClass : requestMappingSet) {
                RequestMapping requestMapping = requestMappingClass.getAnnotation(RequestMapping.class);
                String basePath = requestMapping.value();
                if (!basePath.startsWith("/")) {
                    basePath = "/" + basePath;
                }
                //2.遍历类里所有被@RequestMapping标记的方法,获取方法上面该注解的属性值,作为二级路径
                Method[] methods = requestMappingClass.getDeclaredMethods();
                if (ValidationUtil.isEmpty(methods)) {
                    continue;
                }
                for (Method method : methods) {
                    if (method.isAnnotationPresent(RequestMapping.class)) {
                        RequestMapping methodRequest = method.getAnnotation(RequestMapping.class);
                        String methodPath = methodRequest.value();
                        if (!methodPath.startsWith("/")) {
                            methodPath = "/" + basePath;
                        }
                        String url = basePath + methodPath;
                        //3.解析方法里被@RequestParam标记的参数,
                        // 获取该注解的属性值,作为参数名,
                        // 获取被标记的参数的数据类型,建立参数名和参数类型的映射
                        Map<String, Class<?>> methodParams = new HashMap<>();
                        Parameter[] parameters = method.getParameters();
                        if (!ValidationUtil.isEmpty(parameters)) {
                            for (Parameter parameter : parameters) {
                                RequestParam param = parameter.getAnnotation(RequestParam.class);
                                //目前暂定为Controller方法里面所有的参数都需要@RequestParam注解
                                if (param == null) {
                                    throw new RuntimeException("The parameter must have @RequestParam");
                                }
                                methodParams.put(param.value(), parameter.getType());
                            }
                        }
                        //4.将获取到的信息封装成RequestPathInfo实例和ControllerMethod实例,放置到映射表里
                        String httpMethod = String.valueOf(methodRequest.method());
                        RequestPathInfo requestPathInfo = new RequestPathInfo(httpMethod, url);
                        if (this.pathControllerMethodMap.containsKey(requestPathInfo)) {
                            log.warn("duplicate url:{} registration,current class {} method{} will override the former one",
                                    requestPathInfo.getHttpPath(), requestMappingClass.getName(), method.getName());
                        }
                        ControllerMethod controllerMethod = new ControllerMethod(requestMappingClass, method, methodParams);
                        this.pathControllerMethodMap.put(requestPathInfo, controllerMethod);
                    }
                }
            }
    
        }
    
        @Override
        public boolean process(RequestProcessorChain requestProcessorChain) throws Exception {
            //1.解析HttpSevletRequest的请求方法,请求路径,获取对应的ControllerMethod实例
            String method = requestProcessorChain.getRequestMethod();
            String path = requestProcessorChain.getRequestPath();
            ControllerMethod controllerMethod = this.pathControllerMethodMap.get(new RequestPathInfo(method, path));
            if (controllerMethod == null) {
                requestProcessorChain.setResultRender(new ResourceNotFoundResultRender(method, path));
                return false;
            }
            //2.解析请求参数,并传递给获取到的ControllerMethod实例去执行
            Object result = invokeControllerMethod(controllerMethod, requestProcessorChain.getRequest());
            //3.根据处理的结果,选择对应的render进行渲染
            setResultRender(result, controllerMethod, requestProcessorChain);
            return true;
        }
    
        /**
         * 根据不同情况设置不同的渲染器
         */
        private void setResultRender(Object result, ControllerMethod controllerMethod, RequestProcessorChain requestProcessorChain) {
            if (result == null) {
                return;
            }
            ResultRender resultRender;
            boolean isJson = controllerMethod.getInvokeMethod().isAnnotationPresent(ResponseBody.class);
            if (isJson) {
                resultRender = new JsonResultRender(result);
            } else {
                resultRender = new ViewResultRender(result);
            }
            requestProcessorChain.setResultRender(resultRender);
        }
    
        private Object invokeControllerMethod(ControllerMethod controllerMethod, HttpServletRequest request) {
            //1.从请求里获取GET或者POST的参数名及其对应的值
            Map<String, String> requestParamMap = new HashMap<>();
            //GET,POST方法的请求参数获取方式
            Map<String, String[]> parameterMap = request.getParameterMap();
            for (Map.Entry<String, String[]> parameter : parameterMap.entrySet()
            ) {
                if (!ValidationUtil.isEmpty(parameter.getValue())) {
                    //只支持一个参数对应一个值的形式
                    requestParamMap.put(parameter.getKey(), parameter.getValue()[0]);
                }
            }
            //2.根据获取到的请求参数名及其对应的值,以及controllerMethod里面的参数和类型的映射关系,去实例化出方法对应的参数
            List<Object> methodParams = new ArrayList<>();
            Map<String, Class<?>> methodParamMap = controllerMethod.getMethodParameters();
            for (String paramName : methodParamMap.keySet()) {
                Class<?> type = methodParamMap.get(paramName);
                String requestValue = requestParamMap.get(paramName);
                Object value;
                //只支持String 以及基础类型char,int,short,byte,double,long,float,boolean,及它们的包装类型
                if (requestValue == null) {
                    //将请求里的参数值转成适配于参数类型的空值
                    value = ConverterUtil.primitiveNull(type);
                } else {
                    value = ConverterUtil.convert(type, requestValue);
                }
                methodParams.add(value);
            }
            //3.执行Controller里面对应的方法并返回结果
            Object controller = beanContainer.getBean(controllerMethod.getControllerClass());
            Method invokeMethod = controllerMethod.getInvokeMethod();
            invokeMethod.setAccessible(true);
            Object result;
            try {
                if (methodParams.size() == 0) {
                    result = invokeMethod.invoke(controller);
                } else {
                    result = invokeMethod.invoke(controller, methodParams.toArray());
                }
            } catch (InvocationTargetException e) {
                //如果是调用异常的话,需要通过e.getTargetException()
                // 去获取执行方法抛出的异常
                throw new RuntimeException(e.getTargetException());
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
            return result;
        }
    }
    

    5.定义Render矩阵

    定义渲染动作规范

    /**
     * 渲染请求结果
     */
    public interface ResultRender {
        //执行渲染
        void render(RequestProcessorChain requestProcessorChain) throws Exception;
    }
    

    默认渲染器

    /**
     * 默认渲染器
     */
    public class DefaultResultRender implements ResultRender {
        @Override
        public void render(RequestProcessorChain requestProcessorChain) throws Exception {
            requestProcessorChain.getResponse().setStatus(requestProcessorChain.getResponseCode());
        }
    }
    

    内部异常渲染器

    /**
     * 内部异常渲染器
     */
    public class InternalErrorResultRender implements ResultRender{
        private String errorMsg;
        public InternalErrorResultRender(String  errorMsg){
            this.errorMsg = errorMsg;
        }
        @Override
        public void render(RequestProcessorChain requestProcessorChain) throws Exception {
            requestProcessorChain.getResponse().sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, errorMsg);
        }
    }
    

    Json渲染器

    package org.simplespring.mvc.render;
    
    import com.google.gson.Gson;
    import org.simplespring.mvc.RequestProcessorChain;
    
    import java.io.PrintWriter;
    
    /**
     * Json渲染器
     */
    public class JsonResultRender implements ResultRender {
        private Object jsonData;
        public JsonResultRender(Object jsonData) {
            this.jsonData = jsonData;
        }
    
        @Override
        public void render(RequestProcessorChain requestProcessorChain) throws Exception {
            // 设置响应头
            requestProcessorChain.getResponse().setContentType("application/json");
            requestProcessorChain.getResponse().setCharacterEncoding("UTF-8");
            // 响应流写入经过gson格式化之后的处理结果
            try(PrintWriter writer = requestProcessorChain.getResponse().getWriter()){
                Gson gson = new Gson();
                writer.write(gson.toJson(jsonData));
                writer.flush();
            }
        }
    }
    

    资源找不到时使用的渲染器

    package org.simplespring.mvc.render;
    
    
    import org.simplespring.mvc.RequestProcessorChain;
    
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * 资源找不到时使用的渲染器
     */
    public class ResourceNotFoundResultRender implements ResultRender {
        private String httpMethod;
        private String httpPath;
        public ResourceNotFoundResultRender(String method, String path) {
            this.httpMethod = method;
            this.httpPath = path;
        }
    
        @Override
        public void render(RequestProcessorChain requestProcessorChain) throws Exception {
            requestProcessorChain.getResponse().sendError(HttpServletResponse.SC_NOT_FOUND,
                    "获取不到对应的请求资源:请求路径[" + httpPath + "]" + "请求方法[" + httpMethod + "]");
        }
    }
    

    页面渲染器

    package org.simplespring.mvc.render;
    
    import org.simplespring.mvc.RequestProcessorChain;
    import org.simplespring.mvc.type.ModelAndView;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.util.Map;
    
    /**
     * 页面渲染器
     */
    public class ViewResultRender implements ResultRender{
        public static final String VIEW_PATH = "/templates/";
        private ModelAndView modelAndView;
        /**
         * 对传入的参数进行处理,并赋值给ModelAndView成员变量
         * @param mv
         */
        public ViewResultRender(Object mv) {
            if(mv instanceof ModelAndView){
                //1.如果入参类型是ModelAndView,则直接赋值给成员变量
                this.modelAndView = (ModelAndView)mv;
            } else if(mv instanceof  String){
                //2.如果入参类型是String,则为视图,需要包装后才赋值给成员变量
                this.modelAndView = new ModelAndView().setView((String)mv);
            } else {
                //3.针对其他情况,则直接抛出异常
                throw new RuntimeException("illegal request result type");
            }
        }
        /**
         * 将请求处理结果按照视图路径转发至对应视图进行展示
         * @param requestProcessorChain
         * @throws Exception
         */
        @Override
        public void render(RequestProcessorChain requestProcessorChain) throws Exception {
            HttpServletRequest request = requestProcessorChain.getRequest();
            HttpServletResponse response = requestProcessorChain.getResponse();
            String path = modelAndView.getView();
            Map<String, Object> model = modelAndView.getModel();
            for(Map.Entry<String, Object> entry : model.entrySet()){
                request.setAttribute(entry.getKey(), entry.getValue());
            }
            //JSP
            request.getRequestDispatcher(VIEW_PATH +path).forward(request, response);
    
        }
    }
    

    6.其他数据封装包装类和工具类

    /**
     * 待执行的Controller及其方法实例和参数的映射
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class ControllerMethod {
        //Controller对应的Class对象
        private Class<?> controllerClass;
        //执行的Controller方法实例
        private Method invokeMethod;
        //方法参数名称以及对应的参数类型
        private Map<String, Class<?>> methodParameters;
    }
    
    /**
     * 存储处理完后的结果数据,以及显示该数据的视图
     */
    public class ModelAndView {
        //页面所在的路径
        @Getter
        private String view;
        //页面的data数据
        @Getter
        private Map<String, Object> model = new HashMap<>();
    
        public ModelAndView setView(String view){
            this.view = view;
            return this;
        }
        //modelAndView.setView("addheadline.jsp").addViewData("aaa", "bbb");
        public ModelAndView addViewData(String attributeName,  Object attributeValue){
            model.put(attributeName, attributeValue);
            return this;
        }
    }
    
    /**
     * 目前支持的请求方法
     */
    public enum RequestMethod {
        GET,
        POST
    }
    
    /**
     * 存储http请求路径和请求方法
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class RequestPathInfo {
        //http请求方法
        private String httpMethod;
        //http请求路径
        private String httpPath;
    }
    
    package org.simplespring.util;
    
    public class ConverterUtil {
        /**
         * 返回基本数据类型的空值
         *需要特殊处理的基本类型即intdoubleshortlongytefloatoolean
         * @param type 参数类型
         * @return 对应的空值
         */
        public static Object primitiveNull(Class<?> type) {
            if (type == int.class || type == double.class ||
                    type == short.class || type == long.class ||
                    type == byte.class || type == float.class) {
                return 0;
            } else if(type == boolean.class){
                return false;
            }
            return null;
        }
        /**
         * String类型转换成对应的参数类型
         *
         * @param type  参数类型
         * @param requestValue 值
         * @return 转换后的Object
         */
        public static Object convert(Class<?> type, String requestValue) {
            if(isPrimitive(type)){
                if(ValidationUtil.isEmpty(requestValue)){
                    return primitiveNull(type);
                }
                if (type.equals(int.class) || type.equals(Integer.class)) {
                    return Integer.parseInt(requestValue);
                } else if (type.equals(String.class)) {
                    return requestValue;
                } else if (type.equals(Double.class) || type.equals(double.class)) {
                    return Double.parseDouble(requestValue);
                } else if (type.equals(Float.class) || type.equals(float.class)) {
                    return Float.parseFloat(requestValue);
                } else if (type.equals(Long.class) || type.equals(long.class)) {
                    return Long.parseLong(requestValue);
                } else if (type.equals(Boolean.class) || type.equals(boolean.class)) {
                    return Boolean.parseBoolean(requestValue);
                } else if (type.equals(Short.class) || type.equals(short.class)) {
                    return Short.parseShort(requestValue);
                } else if (type.equals(Byte.class) || type.equals(byte.class)) {
                    return Byte.parseByte(requestValue);
                }
                return requestValue;
            } else {
                throw new RuntimeException("count not support non primitive type conversion yet");
            }
        }
        /**
         * 判定是否基本数据类型(包括包装类以及String)
         *
         * @param type 参数类型
         * @return 是否为基本数据类型
         */
        private static boolean isPrimitive(Class<?> type) {
            return type == boolean.class
                    || type == Boolean.class
                    || type == double.class
                    || type == Double.class
                    || type == float.class
                    || type == Float.class
                    || type == short.class
                    || type == Short.class
                    || type == int.class
                    || type == Integer.class
                    || type == long.class
                    || type == Long.class
                    || type == String.class
                    || type == byte.class
                    || type == Byte.class
                    || type == char.class
                    || type == Character.class;
        }
    }
    

    总结一下大致流程:

    1.定义配置标记

    1.@RequestMapping:标识Controller的方法与请求路径和请求方法的映射关系

    2.@RequestParam:请求的方法参数名称

    3.@ResponseBody:用于标记自动对返回值进行json处理

    2.转发控制器

    核心流程:

    1.初始化

    • 1.初始化容器
    • 2.doAop
    • 3.doIoc
    • 4.初始化请求处理器责任链

    2.处理请求

    • 1.创建责任链对象实例

    • 2.通过责任链模式来依次调用请求处理器对请求进行处理

    • 3.对处理结果进行渲染

    3.请求处理责任链
    1.以责任链的模式执行注册的请求处理器
    2.委派给特定的Render实例对处理后的结果进行渲染

    4.定义RequestProcessor矩阵

    请求预处理器/静态资源请求处理器/jsp资源请求处理器/Controller请求处理器

    5.定义Render矩阵
    默认渲染器/内部异常渲染器/Json渲染器/资源找不到时使用的渲染器/页面渲染器/

    6.其他数据封装包装类和工具类

    参考博客:https://www.iteye.com/blog/jinnianshilongnian-1594806

  • 相关阅读:
    Django_redis_session
    python_redis操作
    Django_url反向解析
    Django_分页
    Django_cookie与sesstion
    Django 自定义错误页面 403 404...
    Django_设置静态文件、上传文件
    Django设置子路由
    nginx、uwsgi
    CentOS安装MySQL
  • 原文地址:https://www.cnblogs.com/tc971121/p/13491586.html
Copyright © 2011-2022 走看看