从零写一个具有IOC-AOP-MVC功能的框架---学习笔记---10. MVC 结果渲染器的编写

1. 本章需要完成的内容

  1. 完成请求处理器接口RequestProcessor的编写
  2. 完成ResultRender渲染器接口的编写
  3. 完成DefultResultRender默认渲染器类的编写
  4. 完成InternalErrorResultRender内部异常渲染器类的编写
  5. 完成JsonResultRender Json渲染器类的编写
  6. 完成ResourceNotFoundResultRender 资源未找到时使用的渲染器类编写
  7. 完成ViewResultRender 页面渲染器类的编写
  8. 完成DispatcherServlet http请求拦截器的编写
  9. 完成RequestProcessorChain 责任链类的编写

2. 第一部分内容

  1. 该部分完成DispatcherServlet与RequestProcessorChain类的编写

2.1 DispatcherServlet类

2.1.1 需要完成的代码如下:
package com.wuyiccc.helloframework.mvc;

import com.wuyiccc.helloframework.aop.AspectWeaver;
import com.wuyiccc.helloframework.core.BeanContainer;
import com.wuyiccc.helloframework.injection.DependencyInjector;
import com.wuyiccc.helloframework.mvc.processor.RequestProcessor;
import com.wuyiccc.helloframework.mvc.processor.impl.ControllerRequestProcessor;
import com.wuyiccc.helloframework.mvc.processor.impl.JspRequestProcessor;
import com.wuyiccc.helloframework.mvc.processor.impl.PreRequestProcessor;
import com.wuyiccc.helloframework.mvc.processor.impl.StaticResourceRequestProcessor;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * @author wuyiccc
 * @date 2020/7/14 21:42
 * 岂曰无衣,与子同袍~
 */
@WebServlet("/*")
@Slf4j
public class DispatcherServlet extends HttpServlet {

    private static final String HELLOFRAMEWORK_CONFIG_FILE = "config/helloframework-config.properties";


    private List<RequestProcessor> PROCESSOR = new ArrayList<>();

    @Override
    public void init() throws ServletException {

        // 1. 初始化容器
        BeanContainer beanContainer = BeanContainer.getInstance();

        beanContainer.loadBeans(getHelloFrameworkScanPackages());
        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) throws ServletException, IOException {
        // 1. 创建责任链对象实例
        RequestProcessorChain requestProcessorChain = new RequestProcessorChain(PROCESSOR.iterator(), req, resp);
        // 2. 通过责任链模式来依次调用请求处理器对请求进行处理
        requestProcessorChain.doRequestProcessorChain();
        // 3. 对处理结果进行渲染
        requestProcessorChain.doRender();
    }

    private String getHelloFrameworkScanPackages() {
        Properties properties = new Properties();
        InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(HELLOFRAMEWORK_CONFIG_FILE);
        try {
            properties.load(in);
        } catch (IOException e) {
            log.warn("The config/helloframework.properties can not load");
            e.printStackTrace();
        }

        String scanPackages = properties.getProperty("helloframework.scan.packages");
        log.info("this is scanPackages: {}", scanPackages);
        return scanPackages;
    }
}


2.1.2 DIspatcherServlet类相关代码讲解:

在这里插入图片描述

在这里插入图片描述

2.2 RequestProcessorChain类

2.2.1 需要完成的代码如下:
package org.myframework.mvc;

/**
 * @author wuyiccc
 * @date 2020/6/16 18:48
 * 岂曰无衣,与子同袍~
 */

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.myframework.mvc.processor.RequestProcessor;
import org.myframework.mvc.render.DefaultResultRender;
import org.myframework.mvc.render.InternalErrorResultRender;
import org.myframework.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;

    private HttpServletRequest request;

    private HttpServletResponse response;

    // http请求方法
    private String requestMethod;

    // http请求路径
    private String requestPath;

    // http响应状态码
    private int responseCode;

    // 请求结果渲染器
    private ResultRender resultRender;


    public RequestProcessorChain(Iterator<RequestProcessor> requestProcessorIterator, HttpServletRequest request, HttpServletResponse response) {
        this.requestProcessorIterator = requestProcessorIterator;
        this.request = request;
        this.response = response;
        this.requestMethod = request.getMethod();
        this.requestPath = request.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);
        }

    }
}


2.2.2 RequestProcessorChain相关代码讲解如下:

在这里插入图片描述

在这里插入图片描述

3. 第二部分需要完成的内容: 结果渲染器的编写

3.1 DefaultResultRender类的编写及讲解:

在这里插入图片描述

3.2 InternalErrorResultRender类的编写及讲解:

在这里插入图片描述

3.3 JsonResultRender类的编写及讲解:

在这里插入图片描述

3.4 ResourceNotFoundResultRender类的编写及讲解:

在这里插入图片描述

3.5 ViewResultRender类的编写及讲解:

在这里插入图片描述
在这里插入图片描述

github地址:https://github.com/wuyiccc/helloframework/

  • 8
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值