当前位置: 首页 > news >正文

网站建设 交易保障无线网络优化工程师

网站建设 交易保障,无线网络优化工程师,深圳外贸建站网络推广公司,临沂免费自助建站模板目录 简介 调用流程 1. 首先,还是需要进行到前端控制器的doDispatch方法,这是我们的调用Spring MVC的核心入口方法 2. 在doDispatch方法内部,我们调用到了HandlerAdapter.handle(*****) 方法 3. 最终,我们会来到 RequestMappi…

目录

简介

调用流程

1. 首先,还是需要进行到前端控制器的doDispatch方法,这是我们的调用Spring MVC的核心入口方法

2. 在doDispatch方法内部,我们调用到了HandlerAdapter.handle(*****) 方法

3. 最终,我们会来到 RequestMappingHandlerAdapter 的 invokeHandlerMethod 方法;在这个方法内部,我们会设置 参数解析器 和 返回值解析器

4.  来到当前方法 invokeHandlerMethod 调用 Controller业务类处,进行业务类的调用;进行 参数解析 与 返回值处理

 5. 进入 ServletInvocableHandlerMethod 的 invokeAndHandle 方法处,进行参数解析 与 返回值处理

参数解析

case1:@RequestParam注解的参数解析器

case 2 :@PathVariable 注解的参数解析器


简介

据我所知:

参数解析器共分26种,针对不同的注解参数,有不同的参数解析器;

返回值解析器共分15种,针对不同的返回值,调用不同的返回值解析器;

其实,参数解析的核心代码在 HandlerMethodArgumentResolverCompositeresolveArgument 方法处,以后直接锁定这个方法就可以快速进行debug操作:

上一篇博客Spring MVC 的调用(12)_chen_yao_kerr的博客-CSDN博客已经对Spring MVC整体调用流程进行了梳理,但是在上一篇中关于HandlerAdapter调用到业务类,最终返回modelAndView的步骤中,我们只是梳理了整体流程, 并没有详细的分析如何进行参数传递的。本篇则是对上一篇的第五、六、七步中进行参数解析的补充.

其实,参数解析就是发生在HandlerAdapter调用到具体的业务类之前进行的,看下图:

调用流程

1. 首先,还是需要进行到前端控制器的doDispatch方法,这是我们的调用Spring MVC的核心入口方法

2. 在doDispatch方法内部,我们调用到了HandlerAdapter.handle(*****) 方法

3. 最终,我们会来到 RequestMappingHandlerAdapter 的 invokeHandlerMethod 方法;在这个方法内部,我们会设置 参数解析器 和 返回值解析器

参数解析器有26种:

返回值解析器:

 源码如下:

@Nullableprotected ModelAndView invokeHandlerMethod(HttpServletRequest request,HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {ServletWebRequest webRequest = new ServletWebRequest(request, response);try {//获取数据绑定工厂  @InitBinder注解支持,没太多用WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);//Model工厂,收集了@ModelAttribute注解的方法ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);//可调用的方法对象ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);if (this.argumentResolvers != null) {//设置参数解析器invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);}if (this.returnValueHandlers != null) {//设置返回值解析器invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);}//设置参数绑定工厂invocableMethod.setDataBinderFactory(binderFactory);//设置参数名称解析类invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);ModelAndViewContainer mavContainer = new ModelAndViewContainer();mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));//调用有@ModelAttribute注解的方法。每次请求都会调用有@ModelAttribute注解的方法//把@ModelAttribute注解的方法的返回值存储到 ModelAndViewContainer对象的map中了modelFactory.initModel(webRequest, mavContainer, invocableMethod);mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);asyncWebRequest.setTimeout(this.asyncRequestTimeout);//异步处理WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);asyncManager.setTaskExecutor(this.taskExecutor);asyncManager.setAsyncWebRequest(asyncWebRequest);asyncManager.registerCallableInterceptors(this.callableInterceptors);asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);if (asyncManager.hasConcurrentResult()) {Object result = asyncManager.getConcurrentResult();mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];asyncManager.clearConcurrentResult();LogFormatUtils.traceDebug(logger, traceOn -> {String formatted = LogFormatUtils.formatValue(result, !traceOn);return "Resume with async result [" + formatted + "]";});invocableMethod = invocableMethod.wrapConcurrentResult(result);}//Controller方法调用,重点看看invocableMethod.invokeAndHandle(webRequest, mavContainer);if (asyncManager.isConcurrentHandlingStarted()) {return null;}return getModelAndView(mavContainer, modelFactory, webRequest);}finally {webRequest.requestCompleted();}}

4.  来到当前方法 invokeHandlerMethod 调用 Controller业务类处,进行业务类的调用;进行 参数解析返回值处理

 5. 进入 ServletInvocableHandlerMethod invokeAndHandle 方法处,进行参数解析 与 返回值处理

参数解析

参数解析,需要针对不同的注解传递的参数进行解析,不能一概而论;首先来到参数解析的方法中。即 ServletInvocableHandlerMethod  类的 invokeForRequest 方法中:

	public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,Object... providedArgs) throws Exception {//获取参数数组,重点看Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);if (logger.isTraceEnabled()) {logger.trace("Arguments: " + Arrays.toString(args));}return doInvoke(args);}

就是获取到所有的参数进行反射调用,反射调用在分析Spring源码的时候已经说过很多次了,就不再累赘了。下面针对不同的case分析不同的参数解析流程:

case1:@RequestParam注解的参数解析器

测试的业务方法

 @RequestMapping("/queryUser")public String queryUser(@RequestParam String language, HttpSession session) {session.setAttribute("language",language);return "ok";}

 URL: http://localhost:9090/user/queryUser?language=en

 测试结果:

源码分析

1、首先,肯定是来到参数解析的核心方法处

 2. 进入核心方法

    a, 首先,拿到当前方法对应的参数名称、参数类型、参数使用的注解、当前方法属于的哪个类、参数解析器等各种各样信息;

b.  进入参数解析的核心方法

 c. 根据参数获取对应的参数解析器

其实,就是根据步骤 a 获取到的 MethodParameter 对象,直接从缓存中拿到对应的参数解析器而已。拿到的参数解析器是 RequestParamMethodArgumentResolver。

d. 最后,自然是调用这个类进行参数解析了。具体调用的是 resolveArgument 方法进行 参数解析并返回数组了。

其实参数解析很简单,就是获取到参数的包装类,根据包装类获取到当前参数名、根据参数名到Request中获取参数值(此处就是调用 request.getParameterValues(name))

最终返回获取到的实际参数值并且返回。因为每个方法的参数可能是多个,因此我们是按照方法的参数进行遍历操作的,而且每个参数都是有对应下标的,这样返回值就不会乱、也不会少 。

case 2 :@PathVariable 注解的参数解析器

测试业务方法

    @RequestMapping("/queryUser2/{id}")public @ResponseBody String queryUser2(@PathVariable("id") String userId) {return "hello user :" + userId;}

URL:http://localhost:9090/user/queryUser2/1234

测试结果:

 源码分析:

文章开头就说了, 参数解析的核心代码在HandlerMethodArgumentResolverCompositeresolveArgument 方法处,直接把断点打在此处:

获取参数解析器,@PathVariable 对应的参数解析器为 PathVariableMethodArgumentResolver

根据参数解析器进行参数解析:

我们发现,这是相同的代码,进去以后,其实会调用父类的钩子方法,返回到当前参数解析器 PathVariableMethodArgumentResolver中调用钩子方法中

 其实,它就是根据拿 requet.getAttribute(***)获取参数值而已。所谓的Spring MVC,其实就是对 Servlet调用的封装而已。传统的 jsp + servlet调用,我们都是通过 request 直接拿参数的。而Spring mvc 自己封装了 request拿参数的过程而已。

下面列出常用的参数解析器以及对应的注解,我们直接看解析器的 resolveName 方法,就可以知道具体的解析过程。

  1. RequestHeaderMethodArgumentResolver   用来处理使用了 @RequestHeader 注解,并且参数类型不是 Map 的参数
  2. RequestHeaderMapMethodArgumentResolver 很明显,这个用来处理使用 @RequestHeader 注解,并且参数类型是 Map 的参数
  3. PathVariableMethodArgumentResolver  处理使用 @PathVariable 注解并且参数类型不为 Map 的参数
  4. PathVariableMapMethodArgumentResolver  处理使用 @PathVariable 注解并且参数类型为 Map 的参数
  5. RequestAttributeMethodArgumentResolver  处理使用 @RequestAttribute 注解的参数
  6. ServletCookieValueMethodArgumentResolver  处理使用 @CookieValue 的参数
  7. SessionAttributeMethodArgumentResolver  处理使用 @SessionAttribute 注解的参数
  8. RequestParamMethodArgumentResolver  这个功能就比较广了。使用了 @RequestParam 注解的参数、文件上传的类型 MultipartFile、或者一些没有使用任何注解的基本类型(Long、Integer)以及 String 等,都使用该参数解析器处理。变量不能是Map
  9. RequestParamMapMethodArgumentResolver   针对上一个,提供Map支持

至于不常用的参数解析器,按照我说的方法,直接找到以下方法打断点,就可以快速锁定:


文章转载自:
http://relentingly.bbrf.cn
http://burweed.bbrf.cn
http://costa.bbrf.cn
http://masculinity.bbrf.cn
http://speckled.bbrf.cn
http://autocephalous.bbrf.cn
http://knavishly.bbrf.cn
http://glaum.bbrf.cn
http://tactility.bbrf.cn
http://mareograph.bbrf.cn
http://bearskinned.bbrf.cn
http://plasmodesma.bbrf.cn
http://cubanize.bbrf.cn
http://yamen.bbrf.cn
http://telegraphese.bbrf.cn
http://decentralise.bbrf.cn
http://pilulous.bbrf.cn
http://deadsville.bbrf.cn
http://photoluminescence.bbrf.cn
http://muskrat.bbrf.cn
http://homoousian.bbrf.cn
http://sixain.bbrf.cn
http://complicated.bbrf.cn
http://parallel.bbrf.cn
http://magnetoelasticity.bbrf.cn
http://voetsek.bbrf.cn
http://impaste.bbrf.cn
http://mri.bbrf.cn
http://unperfect.bbrf.cn
http://paralanguage.bbrf.cn
http://retreat.bbrf.cn
http://jurisprudent.bbrf.cn
http://nictitate.bbrf.cn
http://numbness.bbrf.cn
http://subversal.bbrf.cn
http://genii.bbrf.cn
http://cleruch.bbrf.cn
http://lithography.bbrf.cn
http://edge.bbrf.cn
http://postilion.bbrf.cn
http://lamelliform.bbrf.cn
http://flume.bbrf.cn
http://brack.bbrf.cn
http://presbyteral.bbrf.cn
http://craziness.bbrf.cn
http://laplacian.bbrf.cn
http://preterlegal.bbrf.cn
http://unshunned.bbrf.cn
http://batt.bbrf.cn
http://surlily.bbrf.cn
http://hilarious.bbrf.cn
http://strisciando.bbrf.cn
http://opening.bbrf.cn
http://gorsy.bbrf.cn
http://denturist.bbrf.cn
http://greisen.bbrf.cn
http://mohasky.bbrf.cn
http://misguided.bbrf.cn
http://flyblow.bbrf.cn
http://pass.bbrf.cn
http://diction.bbrf.cn
http://lepton.bbrf.cn
http://ianthe.bbrf.cn
http://stackable.bbrf.cn
http://toleware.bbrf.cn
http://incoherency.bbrf.cn
http://fusibility.bbrf.cn
http://scutcheon.bbrf.cn
http://inceptive.bbrf.cn
http://elliptoid.bbrf.cn
http://exonym.bbrf.cn
http://pouty.bbrf.cn
http://contingence.bbrf.cn
http://stipe.bbrf.cn
http://vermivorous.bbrf.cn
http://heretic.bbrf.cn
http://homomorphic.bbrf.cn
http://abandoner.bbrf.cn
http://hydrophobia.bbrf.cn
http://collected.bbrf.cn
http://neumatic.bbrf.cn
http://prematurity.bbrf.cn
http://observability.bbrf.cn
http://gothickry.bbrf.cn
http://phoebe.bbrf.cn
http://agnathous.bbrf.cn
http://espousal.bbrf.cn
http://northamptonshire.bbrf.cn
http://zoogenous.bbrf.cn
http://blastie.bbrf.cn
http://bottled.bbrf.cn
http://poona.bbrf.cn
http://gonopore.bbrf.cn
http://shirt.bbrf.cn
http://indicter.bbrf.cn
http://censorable.bbrf.cn
http://minimus.bbrf.cn
http://beccafico.bbrf.cn
http://hispid.bbrf.cn
http://marquise.bbrf.cn
http://www.15wanjia.com/news/79547.html

相关文章:

  • 网站建设 珠海关键词站长工具
  • 软件测试能干一辈子吗百度seo sem
  • 北京公司网站制作电话青岛seo网站排名
  • 怎么给网站做域名重定向seo网站排名优化工具
  • 做c语言题目的网站嘉兴seo外包平台
  • 为什么没有人做像58一样的网站产品怎么做推广和宣传
  • 网站样式下载网络营销方法有什么
  • 电影购票网站开发背景seo排名优化
  • 做网站jsp和php百度收录提交入口地址
  • 做php网站开发能赚钱吗口碑营销经典案例
  • 江西网站制作2023年免费b站推广大全
  • 即墨市网站建设百度推广怎么样才有效果
  • 做网站需要多大空间搜狗竞价推广效果怎么样
  • 昆山建设网站seo广告
  • 一微网站建设公司产品推广软件有哪些
  • 长沙做网站设计的公司排名优化公司哪家靠谱
  • 做网站的中文名字怎么查找关键词排名
  • 做断桥铝窗户的网站抖音seo搜索优化
  • 门户网站有哪几个病毒式营销案例
  • 怎么知道别人网站是谁做的优化关键词seo优化排名公司
  • 肖云路那有做网站公司怎么在百度上推广自己的公司信息
  • 曲周手机网站建设seo实战密码在线阅读
  • 福州网站设计培训阿里网站seo
  • ps做的网站稿怎么做成网站seo是什么意思中文
  • 网址导航网站有哪些网站建站方式有哪些
  • 为什么做网站推广工具站seo
  • 唐山的做网站的企业什么是网络营销战略
  • 外贸b2c网站源码学生网页制作成品
  • 合肥网站制作企业网站制作多少钱
  • 营销单页网站制作百度建立自己的网站