自研SpringMVC框架的架构图

DispatcherServlet实现

1、解析请求路径和请求方法

2、依赖容器,建立维护controller方法与请求的映射

3、用适合的Controller方法去处理特定的请求

实现源码如下:

@WebServlet("/*")
public class DispatcherServlet extends HttpServlet {
    List<RequestProcessor> PROCESSOR = new ArrayList<>();
    @Override
    public void init(){
        //1.初始化容器
        BeanContainer beanContainer = BeanContainer.getInstance();
        beanContainer.loadBeans("com.imooc");
        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());
    }
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) {
        //1.创建责任链对象实例
        RequestProcessorChain requestProcessorChain = new RequestProcessorChain(PROCESSOR.iterator(), req, resp);
        //2.通过责任链模式来依次调用请求处理器对请求进行处理
        requestProcessorChain.doRequestProcessorChain();
        //3.对处理结果进行渲染
        requestProcessorChain.doRender();
    }
}

RequestProcessorChain实现


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


/**
     * 以责任链的模式执行请求链
     */
    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);
        }


    }


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


/**
     * 执行处理器
     */
    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);
        }
    }

RequestProcessor实现

接口定义如下


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

其中有四个实现类:


ControllerRequestProcessor:Controller请求处理器,处理doGet、doPost请求


JspRequestProcessor:jsp资源请求处理


PreRequestProcessor:请求预处理,包括编码以及路径处理


StaticResourceRequestProcessor:静态资源请求处理,包括但不限于图片、css、以及js文件等 - DefaultServlet


ResultRender实现

接口定义如下:

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

实现类如下:


DefaultResultRender:默认渲染器


InternalErrorResultRender:内部异常渲染器
JsonResultRender:Json渲染器
@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();
        }
    }
ResourceNotFoundResultRender:资源找不到时使用的渲染器
ViewResultRender:页面渲染器
/**
     * 对传入的参数进行处理,并赋值给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);

    }