复杂参数的请求处理的源码分析:
Dbug分析:Map、Model(map、model里面的数据会被放在request的请求域 request.setAttribute)
//前面Dbug个模式省略,直接看一些重要的底层代码 //获取能够处理器Map model的解析器 @Override public boolean supportsParameter(MethodParameter parameter){ parameter.getParameterAnnotations().length==0; } //解析器解析 @Override @Nullable public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception { Assert.state(mavContainer != null, "ModelAndViewContainer is required for model exposure"); return mavContainer.getModel(); } public ModelMap getModel(){ if(useDefaultModel()){ retrun this.defaultModel; } 省略后面源码... } private final ModeMap defaultModel = new BindingAwareModelMap(); //第二次循环Model的时候,也在底层调用了这个方法,说明Map和Model都会返回 BindingAwareModelMap @Override @Nullable public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception { Assert.state(mavContainer != null, "ModelAndViewContainer is required for model exposure"); return mavContainer.getModel(); }
Dbug分析调试一些重要的参数
执行:invokeForRequest方法 ----------->doInvoke(args);
//真正执行目标反复噶 @Nullable protected Object doInvoke(Object... args) throws Exception { //执行源代码,就是你编写的代码(业务逻辑代码) ReflectionUtils.makeAccessible(getBridgedMethod()); try { return getBridgedMethod().invoke(getBean(), args); } 省略部分源码...
获取方法的返回值:returnValue ,获取请求准发的地址:"/table"
获取保存的属性值:mavContainer
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { //returnValue可以获取到当前方法的处理结果:"/table"请求转发 //mavContainer可以获取到属性内保存的参数值 Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs); //设置响应状态 setResponseStatus(webRequest); //省略部分源码... //处理返回结果 //mavContainer保存属性和属性值 //Dbug调试 this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest); } -------------------------------------------------------------------------- //处理返回值 @Override public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { //找到返回值的处理器 HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType); if (handler == null) { throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName()); } //继续深入源码,查看如何处理返回值 handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest); } -------------------------------------------------------------------------- //处理返回值 @Override public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { //如果returnValue(里面保存里返回结果"/table") //如果不存在返回结果,那么就将true保存在mvcContainer if (returnValue == null) { mavContainer.setRequestHandled(true); return; } //将当前的returnValue转化为ModelAndView ModelAndView mav = (ModelAndView) returnValue; if (mav.isReference()) { String viewName = mav.getViewName(); //"/table" mavContainer.setViewName(viewName); //将结果放入到mavContainer当中 ... }
目标方法执行结束之后,将所有的数据放在ModelAndViewContaioner;
包含要去的页面地址view,还有Modl数据
//模型工厂 @Nullable private ModelAndView getModelAndView(ModelAndViewContainer mavContainer, ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception { //更新Model modelFactory.updateModel(webRequest, mavContainer);
//绑定策略 private void updateBindingResult(NativeWebRequest request, ModelMap model) throws Exception { ListkeyNames = new ArrayList<>(model.keySet()); for (String name : keyNames) { Object value = model.get(name); if (value != null && 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()); } } } }
//再次封装 @Nullable private ModelAndView getModelAndView(ModelAndViewContainer mavContainer, ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception { modelFactory.updateModel(webRequest, mavContainer); if (mavContainer.isRequestHandled()) { return null; } //model 保存的是当前对象的属性和值(k,v) //再次封装为mav ModelMap model = mavContainer.getModel(); ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus()); if (!mavContainer.isViewReference()) { mav.setView((View) mavContainer.getView()); } //判断当前数据是否为重定向数据 if (model instanceof RedirectAttributes) { MapflashAttributes = ((RedirectAttributes) model).getFlashAttributes(); HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); if (request != null) { RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes); } } return mav; } //之后这个方法算是执行完毕,返回到RequestMappingHandlerAdapter.java //mav = invokeHandlerMethod(request, response, handlerMethod); //然后继续执行,返回到 //DispatcherServlet.java //当前方法也执行完毕:(真正使用适配器执行目标方法也真正结束了) //mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); //继续进入下一个核心代码 //mappedHandler.applyPostHandle(processedRequest, response, mv);
DispatcherServlet.java
核心方法:mappedHandler.applyPostHandle(processedRequest, response, mv);
//执行拦截器方法 void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv) throws Exception { HandlerInterceptor[] interceptors = getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { for (int i = interceptors.length - 1; i >= 0; i--) { HandlerInterceptor interceptor = interceptors[i]; interceptor.postHandle(request, response, this.handler, mv); } } } //省略部分源码... //处理最终的结果 processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
//做错误处理性格的返回false,继续向下执行 private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception { boolean errorView = false; //省略部分源码... } //省略部分源码... // Did the handler return a view to render? //当前mv保存了属性和属性值,以及请求地址"/table" if (mv != null && !mv.wasCleared()) { //要去那个页面,开始渲染 //Dbug调试,继续深入源码 render(mv, request, response); //省略部分源码...
继续深入源码,看如何渲染页面的
//深入源码查看是如何渲染的 protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception { // Determine locale for request and apply it to the response. Locale locale =(this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale()); response.setLocale(locale); View view; //获取视图名viewName="/table" String viewName = mv.getViewName(); if (viewName != null) { // We need to resolve the view name. //解析视图 //Dbug调试mv.getModelInternal() //结果为:参数和参数值 map map... model model... //深入源码查看是如何解析的 view = resolveViewName(viewName, mv.getModelInternal(), locale, request); //省略部分源码...
//进入视图解析器进行解析 @Nullable protected View resolveViewName(String viewName, @Nullable Mapmodel, Locale locale, HttpServletRequest request) throws Exception { if (this.viewResolvers != null) { for (ViewResolver viewResolver : this.viewResolvers) { //继续查看是如何解析的 View view = viewResolver.resolveViewName(viewName, locale); //省略部分源码...
@Override @Nullable public View resolveViewName(String viewName, Locale locale) throws Exception { //拿到请求域中的全部属性 RequestAttributes attrs = RequestContextHolder.getRequestAttributes(); //省略部分源码... } //省略部分源码... //核心代码 View view = viewResolver.resolveViewName(viewName, locale);
MapmergedModel = createMergedOutputModel(model, request, response);、 //继续进入源码代码,继续查看 protected Map createMergedOutputModel(@Nullable Map model, HttpServletRequest request, HttpServletResponse response) { @SuppressWarnings("unchecked") Map pathVars = (this.exposePathVariables ? (Map ) 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); //声明:mergedModel Map mergedModel = new linkedHashMap<>(size); mergedModel.putAll(this.staticAttributes); if (pathVars != null) { mergedModel.putAll(pathVars); } //如果当前数据不为空,将当前的数据转移的linkedHashMap if (model != null) { mergedModel.putAll(model); } // Expose RequestContext? if (this.requestContextAttribute != null) { mergedModel.put(this.requestContextAttribute, createRequestContext(request, response, mergedModel)); } //最终得到这个linkedHashMap return mergedModel; } //继续执行代码,跳转到AbstractView.java //Dbug调试mergedModel 里面保存的了方法的参数值 map map... model model... Map mergedModel = createMergedOutputModel(model, request, response); //准备响应 prepareResponse(request, response); //渲染合并输出的模型数据 //我们将model中的数据放入到mergedModel,然后有放入到了renderMergedOutputModel()方法里面 renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
@Override protected void renderMergedOutputModel( Mapmodel, HttpServletRequest request, HttpServletResponse response) throws Exception { // Expose the model object as request attributes. //暴露模型作为请求域的属性 //Dbug调试,查看是如何将Map和Model放入的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); // 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 [" + getUrl() + "]"); } rd.include(request, response); } else { // Note: The forwarded resource is supposed to determine the content type itself. if (logger.isDebugEnabled()) { logger.debug("Forwarding to [" + getUrl() + "]"); } rd.forward(request, response); } }
Dbug调试:如何将Model Map放入的request集合中去的
protected void exposeModelAsRequestAttributes(Mapmodel, HttpServletRequest request) throws Exception { model.forEach((name, value) -> { if (value != null) { request.setAttribute(name, value); } else { request.removeAttribute(name); } }); }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)