前提:处理器方法被调用并返回了结果 public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { //调用处理器对应的处理器方法 Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs); //设置响应状态,如果在调用处理器方法时发生了错误,用webRequest获取response对象并设置它的状态 setResponseStatus(webRequest); if (returnValue == null) { if (isRequestNotModified(webRequest) || hasResponseStatus() || mavContainer.isRequestHandled()) { //为TRUE标识请求已经结束 mavContainer.setRequestHandled(true); return; } } else if (StringUtils.hasText(this.responseReason)) { mavContainer.setRequestHandled(true); return; } mavContainer.setRequestHandled(false); try { this.returnValueHandlers.handleReturnValue( returnValue, getReturnValueType(returnValue), mavContainer, webRequest); } catch (Exception ex) { if (logger.isTraceEnabled()) { logger.trace(getReturnValueHandlingErrorMessage("Error handling return value", returnValue), ex); } throw ex; } } @Override public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { //遍历寻找能够处理中返回参数类型的处理器,如果没有找到就抛出异常,判断是否能够处理很简单就是调用处理器的support方法 HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType); if (handler == null) { throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName()); } //处理 handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest); } 现在以RequestResponseBodyMethodProcessor为例 这个处理器是判断当前方法上面是否有@ResponseBody,如果有就表示这个方法能够支持处理。@Override public boolean supportsReturnType(MethodParameter returnType) { //判断这个方法对应的类是否有@ResponseBody注解 return (AnnotationUtils.findAnnotation(returnType.getContainingClass(), ResponseBody.class) != null || //判断这个方法上是否有@ResponseBody注解 returnType.getMethodAnnotation(ResponseBody.class) != null); } @Override public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException { //设置requestHandled已经被处理 mavContainer.setRequestHandled(true); // Try even with null return value. ResponseBodyAdvice could get involved. writeWithMessageConverters(returnValue, returnType, webRequest); } protected <T> void writeWithMessageConverters(T returnValue, MethodParameter returnType, NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException { //包装request和response对象 ServletServerHttpRequest inputMessage = createInputMessage(webRequest); ServletServerHttpResponse outputMessage = createOutputMessage(webRequest); writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage); } protected <T> void writeWithMessageConverters(T returnValue, MethodParameter returnType, ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage) throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException { //获取返回值的类型 Class<?> returnValueClass = getReturnValueType(returnValue, returnType); //获取返回值的泛型类型,比如List<String>,那么泛型类型就String.class Type returnValueType = getGenericType(returnType); HttpServletRequest servletRequest = inputMessage.getServletRequest(); //获取浏览器能够接受的类型 List<MediaType> requestedMediaTypes = getAcceptableMediaTypes(servletRequest); //获取返回的类型 List<MediaType> producibleMediaTypes = getProducibleMediaTypes(servletRequest, returnValueClass, returnValueType); if (returnValue != null && producibleMediaTypes.isEmpty()) { throw new IllegalArgumentException("No converter found for return value of type: " + returnValueClass); } Set<MediaType> compatibleMediaTypes = new LinkedHashSet<MediaType>(); for (MediaType requestedType : requestedMediaTypes) { for (MediaType producibleType : producibleMediaTypes) { //寻找兼容的媒体类型 if (requestedType.isCompatibleWith(producibleType)) { //保存两者中认为最好的类型作为兼容类型 compatibleMediaTypes.add(getMostSpecificMediaType(requestedType, producibleType)); } } } //如果兼容类型为空,并且方法返回值又不为空,那么抛出异常,找不到浏览器能够接受的返回类型 if (compatibleMediaTypes.isEmpty()) { if (returnValue != null) { throw new HttpMediaTypeNotAcceptableException(producibleMediaTypes); } return; } List<MediaType> mediaTypes = new ArrayList<MediaType>(compatibleMediaTypes); //对类型进行排序 MediaType.sortBySpecificityAndQuality(mediaTypes); MediaType selectedMediaType = null; for (MediaType mediaType : mediaTypes) { if (mediaType.isConcrete()) { //如果找到不是通配符的媒体类型就作为选择的媒体类型(就是非综合类型,那种不能表示到具体是哪一种类型的,比如MediaType.ALL) selectedMediaType = mediaType; break; } //如果媒体类型是all(就是所有类型)或者是application应用类类型,那么设置成流类型 else if (mediaType.equals(MediaType.ALL) || mediaType.equals(MEDIA_TYPE_APPLICATION)) { selectedMediaType = MediaType.APPLICATION_OCTET_STREAM; break; } } if (selectedMediaType != null) { //去除权衡值,比如application/json;q=0.8,去除后变成application/json selectedMediaType = selectedMediaType.removeQualityValue(); //遍历所有注册的消息转换器,这里和解析参数时是差不多的操作 for (HttpMessageConverter<?> messageConverter : this.messageConverters) { if (messageConverter instanceof GenericHttpMessageConverter) { if (((GenericHttpMessageConverter<T>) messageConverter).canWrite(returnValueType, returnValueClass, selectedMediaType)) { //调用实现了ResponseBodyAdvice的controller,对值进行处理 returnValue = (T) getAdvice().beforeBodyWrite(returnValue, returnType, selectedMediaType, (Class<? extends HttpMessageConverter<?>>) messageConverter.getClass(), inputMessage, outputMessage); if (returnValue != null) { addContentDispositionHeader(inputMessage, outputMessage); ((GenericHttpMessageConverter<T>) messageConverter).write(returnValue, returnValueType, selectedMediaType, outputMessage); if (logger.isDebugEnabled()) { logger.debug("Written [" + returnValue + "] as \"" + selectedMediaType + "\" using [" + messageConverter + "]"); } } return; } } else if (messageConverter.canWrite(returnValueClass, selectedMediaType)) { returnValue = (T) getAdvice().beforeBodyWrite(returnValue, returnType, selectedMediaType, (Class<? extends HttpMessageConverter<?>>) messageConverter.getClass(), inputMessage, outputMessage); if (returnValue != null) { addContentDispositionHeader(inputMessage, outputMessage); ((HttpMessageConverter<T>) messageConverter).write(returnValue, selectedMediaType, outputMessage); if (logger.isDebugEnabled()) { logger.debug("Written [" + returnValue + "] as \"" + selectedMediaType + "\" using [" + messageConverter + "]"); } } return; } } } if (returnValue != null) { throw new HttpMediaTypeNotAcceptableException(this.allSupportedMediaTypes); } } //遍历实现了ResponseBodyAdvice的Controller private <T> Object processBody(Object body, MethodParameter returnType, MediaType contentType, Class<? extends HttpMessageConverter<?>> converterType, ServerHttpRequest request, ServerHttpResponse response) { for (ResponseBodyAdvice<?> advice : getMatchingAdvice(returnType, ResponseBodyAdvice.class)) { //判断是否支持,最后使用outputmessage写出到客户端 if (advice.supports(returnType, converterType)) { body = ((ResponseBodyAdvice<T>) advice).beforeBodyWrite((T) body, returnType, contentType, converterType, request, response); } } return body; } 处理完后返回。 再来看看ModelAndViewMethodReturnValueHandler是这么处理返回值的 @Override public boolean supportsReturnType(MethodParameter returnType) { //处理返回类型是ModelAndView的方法 return ModelAndView.class.isAssignableFrom(returnType.getParameterType()); } @Override public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { //如果返回值为空,那么设置请求结束 if (returnValue == null) { mavContainer.setRequestHandled(true); return; } ModelAndView mav = (ModelAndView) returnValue; //判断视图名是否为String类型 if (mav.isReference()) { //获取视图名称 String viewName = mav.getViewName(); //给视图容器设置视图名称 mavContainer.setViewName(viewName); //如果是重定向视图名称,那么设置重定向表示为true,如果没有重新配置这个handler,并且设置自定的标识符,默认就是判断这个视图名是否以redirect:开头 if (viewName != null && isRedirectViewName(viewName)) { mavContainer.setRedirectModelScenario(true); } } else { //如果视图不是String类型的,那么就是视图对象 View view = mav.getView(); mavContainer.setView(view); //判断是否是smartView,如果是,再判断是否是重定向视图,如果是就设置重定向标识 if (view instanceof SmartView) { if (((SmartView) view).isRedirectView()) { mavContainer.setRedirectModelScenario(true); } } } //将ModelAndView中的属性全部存到ModelAndViewContainer中 mavContainer.addAllAttributes(mav.getModel()); } 接着调用了以下方法 getModelAndView(mavContainer, modelFactory, webRequest); private ModelAndView getModelAndView(ModelAndViewContainer mavContainer, ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception { //更新Model modelFactory.updateModel(webRequest, mavContainer); //如果是json处理方式的,那么这个request已经处理完了,返回null,如果是其他的,需要视图解析的,那么继续。 if (mavContainer.isRequestHandled()) { return null; } //获取model,会根据标识来判断是返回默认model还是重定向model ModelMap model = mavContainer.getModel(); ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model); if (!mavContainer.isViewReference()) { mav.setView((View) mavContainer.getView()); } if (model instanceof RedirectAttributes) { Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes(); HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes); } return mav; } 一下是获取model的方法 public ModelMap getModel() { if (useDefaultModel()) { return this.defaultModel; } else { if (this.redirectModel == null) { this.redirectModel = new ModelMap(); } return this.redirectModel; } } /** * Whether to use the default model or the redirect model. */ private boolean useDefaultModel() { return (!this.redirectModelScenario || (this.redirectModel == null && !this.ignoreDefaultModelOnRedirect)); } 更新Model public void updateModel(NativeWebRequest request, ModelAndViewContainer container) throws Exception { //获取默认的Model,sessionAttribute注释的属性,只有model和modelMap才能用,redirectModel没有用。 ModelMap defaultModel = container.getDefaultModel(); //检查是否已经被清理了,在handlerMethod中可以调用SessionStatus的setComplete方法用于标识要清理数据 if (container.getSessionStatus().isComplete()){ this.sessionAttributesHandler.cleanupAttributes(request); } else { //如果没有被清理就将注解中定义要保存的key存到session中 //储存sessionAttribute,这个功能可以用来做缓存 this.sessionAttributesHandler.storeAttributes(request, defaultModel); } //如果请求没有结束,并且获取的model是默认的model,那么就更新绑定结果 if (!container.isRequestHandled() && container.getModel() == defaultModel) { updateBindingResult(request, defaultModel); } } public void storeAttributes(WebRequest request, Map<String, ?> attributes) { for (String name : attributes.keySet()) { Object value = attributes.get(name); Class<?> attrType = (value != null) ? value.getClass() : null; //判断是否是@SessionAttribute定义的属性名和类型,如果是就存到session中 if (isHandlerSessionAttribute(name, attrType)) { this.sessionAttributeStore.storeAttribute(request, name, value); } } } public void storeAttribute(WebRequest request, String attributeName, Object attributeValue) { Assert.notNull(request, "WebRequest must not be null"); Assert.notNull(attributeName, "Attribute name must not be null"); Assert.notNull(attributeValue, "Attribute value must not be null"); String storeAttributeName = getAttributeNameInSession(request, attributeName); request.setAttribute(storeAttributeName, attributeValue, WebRequest.SCOPE_SESSION); } //更新绑定结果 private void updateBindingResult(NativeWebRequest request, ModelMap model) throws Exception { List<String> keyNames = new ArrayList<String>(model.keySet()); for (String name : keyNames) { Object value = model.get(name); //将绑定结果,比如校验的结果,用于页面展示 if (isBindingCandidate(name, value)) { String bindingResultKey = BindingResult.MODEL_KEY_PREFIX + name; if (!model.containsAttribute(bindingResultKey)) { WebDataBinder dataBinder = this.dataBinderFactory.createBinder(request, value, name); model.put(bindingResultKey, dataBinder.getBindingResult()); } } } } 回到DispatcherServlet 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 { processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request); // Determine handler for the current request. mappedHandler = getHandler(processedRequest); if (mappedHandler == null || mappedHandler.getHandler() == null) { noHandlerFound(processedRequest, response); return; } // Determine handler adapter for the current request. 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()) { logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified); } if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } //调用拦截器的preHandler方法 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } // Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } //如果没有设置视图,那么使用viewNameTranslator获取默认的视图名 applyDefaultViewName(processedRequest, mv); //调用拦截器的postHandle方法 mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } //处理结果 processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { //如果出现异常就触发拦截器的afterCompletion方法 triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Error err) { //如果出现异常就触发拦截器的afterCompletion方法 triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err); } finally { if (asyncManager.isConcurrentHandlingStarted()) { // Instead of postHandle and afterCompletion if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else { // Clean up any resources used by a multipart request. if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } } private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception { boolean errorView = false; if (exception != null) { if (exception instanceof ModelAndViewDefiningException) { logger.debug("ModelAndViewDefiningException encountered", exception); mv = ((ModelAndViewDefiningException) exception).getModelAndView(); } else { //获取handler Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null); //调用异常处理器处理数据。 mv = processHandlerException(request, response, handler, exception); errorView = (mv != null); } } // Did the handler return a view to render? if (mv != null && !mv.wasCleared()) { render(mv, request, response); if (errorView) { WebUtils.clearErrorRequestAttributes(request); } } else { if (logger.isDebugEnabled()) { logger.debug("Null ModelAndView returned to DispatcherServlet with name ‘" + getServletName() + "‘: assuming HandlerAdapter completed request handling"); } } if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { // Concurrent handling started during a forward return; } if (mappedHandler != null) { mappedHandler.triggerAfterCompletion(request, response, null); } } //渲染方法 protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception { // Determine locale for request and apply it to the response. //从request中获取本地信息 Locale locale = this.localeResolver.resolveLocale(request); response.setLocale(locale); View view; //判断mv中设置的视图是视图名称还是视图对象 if (mv.isReference()) { // We need to resolve the view name.如果是视图名称,那么通过视图解析器解析获取视图对象{(protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale, HttpServletRequest request) throws Exception { for (ViewResolver viewResolver : this.viewResolvers) { View view = viewResolver.resolveViewName(viewName, locale); if (view != null) { return view; } } return null; })) view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request); if (view == null) { throw new ServletException("Could not resolve view with name ‘" + mv.getViewName() + "‘ in servlet with name ‘" + getServletName() + "‘"); } } else { // No need to lookup: the ModelAndView object contains the actual View object. view = mv.getView(); if (view == null) { throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " + "View object in servlet with name ‘" + getServletName() + "‘"); } } // Delegate to the View object for rendering. if (logger.isDebugEnabled()) { logger.debug("Rendering view [" + view + "] in DispatcherServlet with name ‘" + getServletName() + "‘"); } try { //调用视图的渲染方法mv.getModelInternal()获取modelMap,我们的设置的参数在里面 view.render(mv.getModelInternal(), request, response); } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name ‘" + getServletName() + "‘", ex); } throw ex; } } InternalResourceViewResolver解析器(jstl) protected AbstractUrlBasedView buildView(String viewName) throws Exception { AbstractUrlBasedView view = (AbstractUrlBasedView) BeanUtils.instantiateClass(getViewClass()); view.setUrl(getPrefix() + viewName + getSuffix()); String contentType = getContentType(); if (contentType != null) { view.setContentType(contentType); } view.setRequestContextAttribute(getRequestContextAttribute()); view.setAttributesMap(getAttributesMap()); Boolean exposePathVariables = getExposePathVariables(); if (exposePathVariables != null) { view.setExposePathVariables(exposePathVariables); } Boolean exposeContextBeansAsAttributes = getExposeContextBeansAsAttributes(); if (exposeContextBeansAsAttributes != null) { view.setExposeContextBeansAsAttributes(exposeContextBeansAsAttributes); } String[] exposedContextBeanNames = getExposedContextBeanNames(); if (exposedContextBeanNames != null) { view.setExposedContextBeanNames(exposedContextBeanNames); } return view; } //合并属性 protected Map<String, Object> createMergedOutputModel(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) { @SuppressWarnings("unchecked") //判断是否要暴露路径变量供视图使用 Map<String, Object> pathVars = (this.exposePathVariables ? (Map<String, Object>) request.getAttribute(View.PATH_VARIABLES) : null); // Consolidate static and dynamic model attributes. int size = this.staticAttributes.size(); size += (model != null ? model.size() : 0); size += (pathVars != null ? pathVars.size() : 0); Map<String, Object> mergedModel = new LinkedHashMap<String, Object>(size); mergedModel.putAll(this.staticAttributes); //将暴露的属性合并到modelMap中 if (pathVars != null) { mergedModel.putAll(pathVars); } if (model != null) { mergedModel.putAll(model); } // Expose RequestContext? if (this.requestContextAttribute != null) { mergedModel.put(this.requestContextAttribute, createRequestContext(request, response, mergedModel)); } //将合并的数据返回 return mergedModel; } //渲染合并的model protected void renderMergedOutputModel( Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { // Expose the model object as request attributes.就是将属性设置到request,如果属性对应的值为空,那么就从request中移除 exposeModelAsRequestAttributes(model, request); // Expose helpers as request attributes, if any. exposeHelpers(request); //如果路径和当前请求的路径一样,那么就抛出错误 // Determine the path for the request dispatcher. String dispatcherPath = prepareForRendering(request, response); //获取请求分发器,request.getDispatcher(diapatcherPath) // Obtain a RequestDispatcher for the target resource (typically a JSP). RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath); if (rd == null) { throw new ServletException("Could not get RequestDispatcher for [" + getUrl() + "]: Check that the corresponding file exists within your web application archive!"); } // If already included or response already committed, perform include, else forward. if (useInclude(request, response)) { response.setContentType(getContentType()); if (logger.isDebugEnabled()) { logger.debug("Including resource [" + getUrl() + "] in InternalResourceView ‘" + getBeanName() + "‘"); } rd.include(request, response); } else { // Note: The forwarded resource is supposed to determine the content type itself. if (logger.isDebugEnabled()) { logger.debug("Forwarding to resource [" + getUrl() + "] in InternalResourceView ‘" + getBeanName() + "‘"); } 请求转发 rd.forward(request, response); } }
原文地址:https://www.cnblogs.com/honger/p/9516930.html
时间: 2024-10-15 20:14:46