赞
踩
目录
2、对于九大组件,前端控制器DispatcherServlet会进行初始化
2)进入到DispatcherServlet的doDispatch()
- protected void initStrategies(ApplicationContext context) {
- initMultipartResolver(context);
- initLocaleResolver(context);
- initThemeResolver(context);
- initHandlerMappings(context);
- initHandlerAdapters(context);
- initHandlerExceptionResolvers(context);
- initRequestToViewNameTranslator(context);
- initViewResolvers(context);
- initFlashMapManager(context);
- }
例如:初始化HandlerMapping(后面需要用到,先了解知道一下就可以哦)
- private void initHandlerMappings(ApplicationContext context) {
- this.handlerMappings = null;
- if (this.detectAllHandlerMappings) {
- // Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
- Map<String, HandlerMapping> matchingBeans =
- BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
- if (!matchingBeans.isEmpty()) {
- this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());
- // We keep HandlerMappings in sorted order.
- OrderComparator.sort(this.handlerMappings);
- }
- }
- else {
- try {
- HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
- this.handlerMappings = Collections.singletonList(hm);
- }
- catch (NoSuchBeanDefinitionException ex) {
- // Ignore, we'll add a default HandlerMapping later.
- }
- }
-
- // Ensure we have at least one HandlerMapping, by registering
- // a default HandlerMapping if no other mappings are found.
- if (this.handlerMappings == null) {
- this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
- if (logger.isDebugEnabled()) {
- logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
- }
- }
- }
***********关键点来喽~~~
组件的初始化: 有些组件初始化在容器中是使用类型找的,有些组件是使用id找的;去容器中找这个组件,如果没有找到就用默认的配置;注意点:如果后面需要自己实现的组件需要在ioc容器中注册,而注册的时候有些组件就需要专门指定的id才可以去注入成功(否则注入不上的)
- 当客户端发送请求时,会被tomcat拦截,进入到doGet或者doPost的方法中去
- 根据继承关系,FrameworkServlet会将基类的HttpServlet的doGet和doPost重写,并且调用doService()
- 前端控制器DispatcherServlet继承FrameworkServlet后重写了doService()方法,经过调用,进入到doDispatch()经过这么一些曲折的寻找,最后终于可以根据源码来探究mvc的流程了
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {HttpServletRequest processedRequest = request;HandlerExecutionChain mappedHandler = null;boolean multipartRequestParsed = false;WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);try {ModelAndView mv = null;Exception dispatchException = null;try {//1、检查是否文件上传请求processedRequest = checkMultipart(request);multipartRequestParsed = processedRequest != request;// Determine handler for the current request.//2、根据当前的请求地址找到那个类能来处理;mappedHandler = getHandler(processedRequest);//3、如果没有找到哪个处理器(控制器)能处理这个请求就404,或者抛异常if (mappedHandler == null || mappedHandler.getHandler() == null) {noHandlerFound(processedRequest, response);return;}// Determine handler adapter for the current request.//4、拿到能执行这个类的所有方法的适配器;(反射工AnnotationMethodHandlerAdapter)HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());// Process last-modified header, if supported by the handler.String method = request.getMethod();boolean isGet = "GET".equals(method);if (isGet || "HEAD".equals(method)) {long lastModified = ha.getLastModified(request, mappedHandler.getHandler());if (logger.isDebugEnabled()) {String requestUri = urlPathHelper.getRequestUri(request);logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);}if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {return;}}if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}try {// Actually invoke the handler.处理(控制)器的方法被调用//控制器(Controller),处理器(Handler)//5、适配器来执行目标方法;//将目标方法执行完成后的返回值作为视图名,设置保存到ModelAndView中//目标方法无论怎么写,最终适配器执行完成以后都会将执行后的信息封装成ModelAndViewmv = ha.handle(processedRequest,response,mappedHandler.getHandler());} finally {if (asyncManager.isConcurrentHandlingStarted()) {return;}}applyDefaultViewName(request, mv);//如果没有视图名设置一个默认的视图名;mappedHandler.applyPostHandle(processedRequest, response, mv);} catch (Exception ex) {dispatchException = ex;}//转发到目标页面;//6、根据方法最终执行完成后封装的ModelAndView;//转发到对应页面,而且ModelAndView中的数据可以从请求域中获取processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);} catch (Exception ex) {triggerAfterCompletion(processedRequest, response, mappedHandler, ex);} catch (Error err) {triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);} finally {if (asyncManager.isConcurrentHandlingStarted()) {// Instead of postHandle and afterCompletionmappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);return;}// Clean up any resources used by a multipart request.if (multipartRequestParsed) {cleanupMultipart(processedRequest);}}}
******由此,可以总结为如下几个大概方面
1.用户发出请求,DispatcherServlet接收请求并拦截请求。 2.调用doDispatch()方法进行处理: 1. getHandler():根据当前请求地址中找到能处理这个请求的目标处理器类(处理器); 1.根据当前请求在HandlerMapping中找到这个请求的映射信息,获取到目标处理器类 2. mappedHandler = getHandler(processedRequest); 2. getHandlerAdapter():根据当前处理器类找到能执行这个处理器方法的适配器; 1.根据当前处理器类,找到当前类的HandlerAdapter (适配器) 2. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler(); 3.使用刚才获取到的适配器(AnnotationMethodHandlerAdapter)执行目标方法; mv = ha.handle(processedRequest,response,mappedHandler.getHandler()); 4.目标方法执行后,会返回-个ModerAndView对象 mv = ha.handle(processedRequest,response,mappedHandler.getHandler(); 5.根据ModerAndView的信息转发到具体页面,并可以在请求域中取出ModerAndView中的模型数据 processDispatchResult(processedRequest, response, mappedHandler, mv,dispatchException);
根据前面的doDispatch(),有两个组件我们需要使用到,那么再来强调一下这两个组件是干嘛的呢?
- HandlerMapping为处理器映射器,保存了每一个处理器能处理哪些请求的映射信息,handlerMap
-
- HandlerAdapter为处理器适配器,能解析注解方法的适配器,其按照特定的规则去执行Handler
**怎么根据当前请求就能找到哪个类能来处理?**
getHandler()会返回目标处理器类的执行链 HandlerMapping:处理器映射:他里面保存了每一个处理器能处理哪些请求的映射信息 handlerMap:ioc容器启动创建Controller对象的时候扫描每个处理器都能处理什么请求,保存在HandlerMapping的handlerMap属性中;下一次请求过来,就来看哪个HandlerMapping中有这个请求映射信息就行
- 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;
- }
注意点:遍历循环的this.handlerMappings里面在初始化前端控制器的时候就有东西了,有指定的处理器能处理就拿到该处理器,并直接返回。
拿到适配器,通过适配器来调用目标方法
- protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
- for (HandlerAdapter ha : this.handlerAdapters) {
- if (logger.isTraceEnabled()) {
- logger.trace("Testing handler adapter [" + ha + "]");
- }
- if (ha.supports(handler)) {
- return ha;
- }
- }
- throw new ServletException("No adapter for handler [" + handler +
- "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
- }
RequestMappingHandlerAdapter适配器:
能解析注解方法的适配器;
处理器类中只要有标了注解的这些方法就能用;
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {//拿到方法的解析器ServletHandlerMethodResolver methodResolver = getMethodResolver(handler);//方法解析器根据当前请求地址找到真正的目标方法Method handlerMethod = methodResolver.resolveHandlerMethod(request);//创建一个方法执行器;ServletHandlerMethodInvoker methodInvoker = new ServletHandlerMethodInvoker(methodResolver);//包装原生的request, response,ServletWebRequest webRequest = new ServletWebRequest(request, response);//创建了一个,隐含模型ExtendedModelMap implicitModel = new BindingAwareModelMap() ;//**重点//真正执行目标方法;目标方法利用反射执行期间确定参数值,提前执行modelattribute等所有的操作都在这个方法中;Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);ModelAndView mav = methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);methodInvoker.updateModelAttributes(handler, (mav != null ? mav.getModel() : null), implicitModel, webRequest);return mav;}
接下来深入到执行目标方法,来看看他们是如何执行的吧
Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);
publicfinal Object invokeHandlerMethod (Method handlerMethod, Object handler,NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {Method handlerMethodToInvoke = BridgeMethodResolver.findBridgedMethod(handlerMethod);try {boolean debug = logger.isDebugEnabled();for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {Object attrValue = this.sessionAttributeStore.retrieveAttribute(webRequest, attrName);if (attrValue != null) {implicitModel.addAttribute(attrName, attrValue);}}//找到所有@ModelAttribute注解标注的方法;for (Method attributeMethod : this.methodResolver.getModelAttributeMethods()) {Method attributeMethodToInvoke = BridgeMethodResolver.findBridgedMethod(attributeMethod);//先确定modelattribute方法执行时要使用的每一个参数的值;Object[] args = resolveHandlerArguments(attributeMethodToInvoke, handler, webRequest, implicitModel);if (debug) {logger.debug("Invoking model attribute method: " + attributeMethodToInvoke);}String attrName = AnnotationUtils.findAnnotation(attributeMethod, ModelAttribute.class).value();if (!"".equals(attrName) && implicitModel.containsAttribute(attrName)) {continue;}ReflectionUtils.makeAccessible(attributeMethodToInvoke);//提前运行ModelAttributeObject attrValue = attributeMethodToInvoke.invoke(handler, args);if ("".equals(attrName)) {Class<?> resolvedType = GenericTypeResolver.resolveReturnType(attributeMethodToInvoke, handler.getClass());attrName = Conventions.getVariableNameForReturnType(attributeMethodToInvoke, resolvedType, attrValue);}//把提前运行的ModelAttribute方法的返回值也放在隐含模型中if (!implicitModel.containsAttribute(attrName)) {implicitModel.addAttribute(attrName, attrValue);}}//再次解析目标方法参数是哪些值Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);if (debug) {logger.debug("Invoking request handler method: " + handlerMethodToInvoke);}ReflectionUtils.makeAccessible(handlerMethodToInvoke);//执行目标方法return handlerMethodToInvoke.invoke(handler, args);}catch (IllegalStateException ex) {// Internal assertion failed (e.g. invalid signature):// throw exception with full handler method context...throw new HandlerMethodInvocationException(handlerMethodToInvoke, ex);}catch (InvocationTargetException ex) {// User-defined @ModelAttribute/@InitBinder/@RequestMapping method threw an exception...ReflectionUtils.rethrowException(ex.getTargetException());return null;}}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。