1. What should be done in this chapter
- Complete the writing of request processor interface
- Finish writing the interface of resultrender
- Finish the writing of default render class of faultresultrender
- Complete the writing of the internal exception render class of internalerrorresulterrender
- Complete the jsonresultrender JSON render class
- Complete the writing of the render class used when resourcenotfoundresultrender resource is not found
- Complete the writing of the viewresultrender page render class
- Complete the writing of HTTP request interceptor for dispatcherserservlet
- Complete the writing of requestprocessorchain responsibility chain class
2. The first part
- This part completes the writing of dispatcherservlet and requestprocessorchain classes
2.1 dispatcherservlet class
2.1.1 the code to be completed is as follows:
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
*Do you say that you have no clothes, and you are in the same robe with your son~
*/
@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. Initialize the container
BeanContainer beanContainer = BeanContainer.getInstance();
beanContainer.loadBeans(getHelloFrameworkScanPackages());
new AspectWeaver().doAop();
new DependencyInjector().doIoc();
//2. Initialize the responsibility chain of request processor
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. Create an instance of responsibility chain object
RequestProcessorChain requestProcessorChain = new RequestProcessorChain(PROCESSOR.iterator(), req, resp);
//2. Call the request processor in turn to process the request through the responsibility chain mode
requestProcessorChain.doRequestProcessorChain();
//3. Render the result
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 related code explanation of dspatcherservlet class:
2.2 requestprocessorchain class
2.2.1 the code to be completed is as follows:
package org.myframework.mvc;
/**
* @author wuyiccc
* @date 2020/6/16 18:48
*Do you say that you have no clothes, and you are in the same robe with your son~
*/
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. Execute the registered request processor in the mode of responsibility chain
*2. Delegate to a specific render instance to render the processed results
*/
@Data
@Slf4j
public class RequestProcessorChain {
//Request processor iterator
private Iterator<RequestProcessor> requestProcessorIterator;
private HttpServletRequest request;
private HttpServletResponse response;
//HTTP request method
private String requestMethod;
//HTTP request path
private String requestPath;
//HTTP response status code
private int responseCode;
//Request result render
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;
}
/**
*Executing request chain in the mode of responsibility chain
*/
public void doRequestProcessorChain() {
//1. Iterator traverses the registered request processor to realize class list
try {
while (requestProcessorIterator.hasNext()) {
//2. Until a request processor returns false after execution
if (!requestProcessorIterator.next().process(this)) {
break;
}
}
} catch (Exception e) {
//3. If there is an exception during the process, it will be handled by the internal exception render
this.resultRender = new InternalErrorResultRender(e.getMessage());
log.error("doRequestProcessorChain error: ", e);
}
}
/**
*Executive processor
*/
public void doRender() {
//1. If the request processor implementation class does not select an appropriate render, the default is used
if (this.resultRender == null) {
this.resultRender = new DefaultResultRender();
}
//2. Call render method to render the result
try {
this.resultRender.render(this);
} catch (Exception e) {
log.error("doRender error: ", e);
throw new RuntimeException(e);
}
}
}
3. The second part: the writing of result render
3.1 writing and explanation of the defaultresultrender class:
3.2 writing and explanation of internalerrorresulterrender class:
3.3 writing and explanation of jsonresultrender class:
3.4 writing and explanation of resourcenotfoundresultrender class:
3.5 writing and explanation of viewresultrender class:
GitHub address: https://github.com/wuyiccc/he…