在这里spring 的bean初始化与注入在这里不在复述,今天就只讲 mvc请求响应的过程。
首先我们确定mvc请求的一个入口,dispatcherServlet 的doservice 方法,这里只讲一些比较重要的一些处理。设置request一些属性,然后调用doDispatch(request, response);在此方法中有以下步骤
1.获取请求的相关处理器:getHandler(processedRequest);
*/
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
@Override
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Object handler = getHandlerInternal(request); //主要是requestmapping 与handlerMethod 映射关系
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
// Bean name or resolved handler?
if (handler instanceof String) {
String handlerName = (String) handler;
handler = getApplicationContext().getBean(handlerName);
}
return getHandlerExecutionChain(handler, request);
}
1.首先我们获取通过request获取请求路径,然后进行路径组装,比如我请求路径http://localhost:7001/UserProject/login/add 红色部分就是其请求路径
2.获取到请求路径调用lookupHandlerMethod,首先根据路径从this.urlMap.get(lookupPath)得到一个path的一个匹配字符串,用于mapping与handlermethod映射的参数,(urlMapping是在AbstractHandlerMethodMapping在初bean始化时进行初始化因为实现了Initializingean 调用public void afterPropertiesSet() {
initHandlerMethods();
}
protected void initHandlerMethods() {
if (logger.isDebugEnabled()) {
logger.debug("Looking for request mappings in application context: " + getApplicationContext());
}
String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
getApplicationContext().getBeanNamesForType(Object.class));
for (String beanName : beanNames) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX) &&
isHandler(getApplicationContext().getType(beanName))){//此方法判断我们过滤的控制器类是否有controller,requestMapping 注解
detectHandlerMethods(beanName);//如果存在此注解,则进行封装,设置方法与请求类的一个映射,然后将handler,mapping,method 进行处理,将其满足条件的处理类与mapping封装到urlmapping容器中this.urlMap.add(pattern, mapping);
}
}
handlerMethodsInitialized(getHandlerMethods());
}
4.然后获取request的相应的adapter HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
5.通过前置applyPreHandle
6.调用处理请求方法mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
调用invokeHandleMethod方法中invokeForRequest 通过策略模式处理请求参数的处理类,根据策略模式调用不同的返回参数处理returnValueHandlers.handleReturnValue()
7.封装modelandview 并且根据参数类型返回页面还是数据,调用requestdispatcher的forward方法,如果为director则进行封装转发
8.调用后置处理器进行资源释放等操作。