title: 动手撸一个 mvc 框架3
date: 2020/04/24 15:44
本节内容
继续上节,将找到 RequestMapping 对象并执行整个流程进行实现
请求来了
1、FrameworkServlet 对请求进行的处理
重写了父类的 doGet 和 doPost 方法,将其共同引向一个方法
// ------> 请求来了
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
protected final void processRequest(HttpServletRequest request, HttpServletResponse response) {
// 准备一些环境(本地化、异步、还有一个什么参数不知道干啥用的)
// 调用处理方法
this.doService(request, response);
// 触发一个事件
}
protected abstract void doService(HttpServletRequest request, HttpServletResponse response);
2、DispatcherServlet 实现 doService 方法
public class DispatcherServlet extends FrameworkServlet {
// 处理器映射器集合
private List<HandlerMapping> handlerMappings;
/**
* This implementation calls {@link #initStrategies}.
*/
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
/**
* 初始化此servlet使用的策略对象。
*/
protected void initStrategies(ApplicationContext context) {
// initMultipartResolver(context);
// initLocaleResolver(context);
// initThemeResolver(context);
// 初始化处理器映射器,通过处理器映射器找到对应的方法进行执行
this.initHandlerMappings(context);
// initHandlerAdapters(context);
// initHandlerExceptionResolvers(context);
// initRequestToViewNameTranslator(context);
// initViewResolvers(context);
// initFlashMapManager(context);
}
private void initHandlerMappings(ApplicationContext context) {
String[] bdNames = context.getBeanDefinitionNames(HandlerMapping.class);
this.handlerMappings = Arrays.stream(bdNames)
.map(beanName -> context.getBean(beanName, HandlerMapping.class))
.collect(Collectors.toList());
}
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) {
}
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) {
HandlerExecutionChain mappedHandler = this.getHandler(request);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
return;
}
}
/**
* 根据请求获取【处理链】
*/
private HandlerExecutionChain getHandler(HttpServletRequest request) {
for (HandlerMapping handlerMapping : handlerMappings) {
HandlerExecutionChain handler = handlerMapping.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
}
}
HandlerExecutionChain
public class HandlerExecutionChain {
private final Object handler;
public HandlerExecutionChain(Object handler) {
this.handler = handler;
}
public Object getHandler() {
return handler;
}
}
3、RequestMappingHandlerMapping#getHandler()
public abstract class AbstractHandlerMapping implements HandlerMapping {
/**
* 返回此请求的处理程序和所有拦截器。可以根据请求URL,会话状态或实现类选择的任何因素进行选择。
*/
@Override
public final HandlerExecutionChain getHandler(HttpServletRequest request) {
// 根据请求获取处理程序
Object handler = this.getHandlerInternal(request);
if (handler == null) {
return null;
}
// 如果是实现了 Controller 接口的情况,则从 bf 中取出
// if (handler instanceof String) {
// String handlerName = (String) handler;
// handler = getApplicationContext().getBean(handlerName);
// }
// 这个地方和拦截器有关
// return this.getHandlerExecutionChain(handler, request);
return null;
}
/**
* 查找给定请求的处理程序,如果未找到特定请求,则返回 null。
*/
protected abstract Object getHandlerInternal(HttpServletRequest request);
}
RequestMappingHandlerMapping 的实现
/**
* 查找给定请求的处理程序,如果未找到特定请求,则返回 null。
*/
@Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request) {
List<Match> matches = new ArrayList<>();
String lookupPath = request.getRequestURI();
List<RequestMappingInfo> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
// 如果找到匹配的了,就进行校验,看看是否符合当前请求
if (directPathMatches != null) {
this.addMatchingMappings(directPathMatches, matches, request);
}
// 如果没有找到合适的,说明可能是 @PathVariable 的情况,则把所有的 RequestMappingInfo 交给它进行寻找匹配的。
if (matches.isEmpty()) {
this.addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
}
// 如果匹配的不为空,则取出第一个将它的 handlerMethod 进行返回
if (CollUtil.isNotEmpty(matches)) {
Match bestMatch = matches.get(0);
return bestMatch.handlerMethod;
}
throw new RuntimeException("没有为当前请求找到处理器!");
}
/**
* 对请求方法、请求路径(包括 @PathVariable)【@RequestMapping 相关的内容】进行校验
*/
private void addMatchingMappings(Collection<RequestMappingInfo> mappingInfos, List<Match> matches, HttpServletRequest request) {
for (RequestMappingInfo mappingInfo : mappingInfos) {
RequestMappingInfo info = mappingInfo.getMatchingCondition(request);
if (ObjectUtil.isNotNull(info)) {
matches.add(new Match(info, this.mappingRegistry.getMappings().get(mappingInfo)));
}
}
}
private static class Match {
private final RequestMappingInfo mapping;
private final HandlerMethod handlerMethod;
public Match(RequestMappingInfo mapping, HandlerMethod handlerMethod) {
this.mapping = mapping;
this.handlerMethod = handlerMethod;
}
@Override
public String toString() {
return this.mapping.toString();
}
}