自研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);
}