参考:《spring技术内幕》
springmvc相应http请求的过程:
HttpServlet是FrameworkServlet的父类。
HttpServlet 的service方法
注意,这里的request已经封装好了http请求里的所有信息,都是可以从中获取的。
然后通过this.service到
FrameworkServlet---service
然后httpMethod为get方法,所以执行super.service(request, response);
接着就到了HttpServlet的service方法:
然后运行到了这里的this.doget方法
接着就进了FrameworkServlet的doget方法,注意,这里的this是FrameworkServlet,所以这里并不会执行HttpServlet的doget方法。
然后就进入到了FrameworkServlet的processRequest方法
然后进入到FrameworkServlet的doService方法
跟着又进入到doDispatch方法
然后运行到
这里再进入就是跑到了我的controller层的方法里运行了。
。
这里面的关键还是dodispatch方法。里面的运行逻辑是最核心的dispatchservlet里的最核心的dodispatch方法。
https://blog.csdn.net/u012099869/article/details/78848204 这个链接里的
这张图还是很不错的。结构比较清晰一些。
然后回到dodispatch方法:
到 mappedHandler = this.getHandler(processedRequest);
然后进去:
这部分的逻辑是遍历一个list,然后通过request返回一个HandlerExecutionChain 。然后再进HandlerExecutionChain handler = mapping.getHandler(request);
到了AbstractHandlerMapping类
然后先进:Object handler = this.getHandlerInternal(request);
然后进了 AbstractUrlHandlerMapping
然后进lookupHandler
注意:
private final Map<String, Object> handlerMap = new LinkedHashMap();
这个map里面保存了URL请求和controller的映射关系,注意它是在AbstractUrlHandlerMapping类里面的。 这个是在初始化的时候放进去的,然后现在响应请求了,就从里面取出来了。handler里就是封装了对这个请求的操作,比如controller里面的方法。
然后到dispatchservlet里的dodispatch的
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
里,就调用handler里的方法取进行相应的逻辑操作。
然后看看HandlerExecutionChain里面又啥。
它持有一个interceptor链和一个handler对象。这个handler对象实际上就是HTTP请求对应的controller,在持有这个handler对象的同时,还在HandlerExecutionChain中设置一个拦截器链,通过这个拦截器链中的拦截器,可以为handler对象提供功能的增强。
那怎么设置这个拦截器呢?
https://blog.csdn.net/qq_25673113/article/details/79153547
这里对拦截器链又比较好的介绍。感觉可以去学习一下
下面是我的拦截器配置:
<mvc:exclude-mappingpath="/aa/*"/> 排除掉不需要拦截的controller。
这里写了一个前置拦截器把request的整个http请求都输出了,注意return true才能继续执行下去。
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println(request.getMethod());
Map<String, String[]> parameterMap = request.getParameterMap();
for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
String[] aas=entry.getValue();
StringBuilder bb=new StringBuilder();
for(String cc:aas){
bb.append(cc);
}
System.out.println("Key = " + entry.getKey() + ", Value = " + bb);
}
Enumeration<String> headerNames = request.getHeaderNames();
String aa=headerNames.nextElement();
while (aa!=null){
String bb=request.getHeader(aa);
System.out.println(aa+" "+bb);
aa=headerNames.nextElement();
}
return true;
}
}
然后感觉就这样了。
输出如下:
感觉还行,基本达到目标。
现在基本把对一个http请求的基本的操作逻辑都讲了,主要就是dodispatch里的逻辑。没有把视图那方便的东西进行说明。
感觉差不多了,总结一下,注意的重要的东西
一个是DispatcherServlet里的private List<HandlerMapping> handlerMappings; 对象。自己去看那个handlerMappings接口里有啥。
AbstractUrlHandlerMapping里的private final Map<String, Object> handlerMap = new LinkedHashMap(); 把url和handler作为键值放到一个map中。
嗯,今天先到这里了,可能会有很多不到位的地方,发现bug才有更大的收获。
后面补充一个
这里还可以获取访问者的ip地址之类的信息,前面的信息还有cookie之类的。