文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

使用SpringMVC请求怎么对handler进行映射

2023-06-14 06:24

关注

这期内容当中小编将会给大家带来有关使用SpringMVC请求怎么对handler进行映射,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

请求映射源码

使用SpringMVC请求怎么对handler进行映射

前台发送给后台的访问请求是如何找到对应的控制器映射并执行后续的后台操作呢,其核心为DispatcherServlet.java与HandlerMapper。在spring boot初始化的时候,将会加载所有的请求与对应的处理器映射为HandlerMapper组件。我们可以在springMVC的自动配置类中找到对应的Bean。

@Bean@Primary@Overridepublic RequestMappingHandlerMapping requestMappingHandlerMapping(  @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,  @Qualifier("mvcConversionService") FormattingConversionService conversionService,  @Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {  // Must be @Primary for MvcUriComponentsBuilder to work  return super.requestMappingHandlerMapping(contentNegotiationManager, conversionService,                       resourceUrlProvider);}@Beanpublic WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext,                              FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {  WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(    new TemplateAvailabilityProviders(applicationContext), applicationContext, getWelcomePage(),    this.mvcProperties.getStaticPathPattern());  welcomePageHandlerMapping.setInterceptors(getInterceptors(mvcConversionService, mvcResourceUrlProvider));  welcomePageHandlerMapping.setCorsConfigurations(getCorsConfigurations());  return welcomePageHandlerMapping;}

请求将首先执行FrameworkServlet下的service方法根据request请求的method找到对应的do**方法。

@Overrideprotected void service(HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {  HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());  if (httpMethod == HttpMethod.PATCH || httpMethod == null) {    processRequest(request, response);  }  else {    //父类根据method参数执行doGet,doPost,doDelete等    super.service(request, response);  }}

而这些do**其都会进入核心方法,以doGet为例。

@Overrideprotected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  //核心方法  processRequest(request, response);}
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {  try {  //进入此核心方法  doService(request, response);}catch (ServletException | IOException ex) {  failureCause = ex;  throw ex;}catch (Throwable ex) {  failureCause = ex;  throw new NestedServletException("Request processing failed", ex);}finally {  resetContextHolders(request, previousLocaleContext, previousAttributes);  if (requestAttributes != null) {    requestAttributes.requestCompleted();  }  logResult(request, response, failureCause, asyncManager);  publishRequestHandledEvent(request, response, startTime, failureCause);}

processRequest()方法中重点在doService(request, response);,而其核心处理逻辑位于DispatchServletl类重写的方法,如下。

@Overrideprotected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { ····   try {     //这里为实际分发控制器的逻辑,其内部是找到对应的handlerMapper     doDispatch(request, response);   }    finally {      if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {        // Restore the original attribute snapshot, in case of an include.        if (attributesSnapshot != null) {          restoreAttributesAfterInclude(request, attributesSnapshot);        }      }      if (requestPath != null) {        ServletRequestPathUtils.clearParsedRequestPath(request);      }    }}

接下来看分发处理逻辑方法,其中重要的方法都使用了原生的注释。接下来分别分析核心源码。

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) {        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 (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {          return;        }      }      if (!mappedHandler.applyPreHandle(processedRequest, response)) {        return;      }      // Actually invoke the handler.      mv = ha.handle(processedRequest, response, mappedHandler.getHandler());      if (asyncManager.isConcurrentHandlingStarted()) {        return;      }      applyDefaultViewName(processedRequest, mv);      mappedHandler.applyPostHandle(processedRequest, response, mv);    }    catch (Exception ex) {      dispatchException = ex;    }    catch (Throwable err) {      // As of 4.3, we're processing Errors thrown from handler methods as well,      // making them available for @ExceptionHandler methods and other scenarios.      dispatchException = new NestedServletException("Handler dispatch failed", err);    }    processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);  }  catch (Exception ex) {    triggerAfterCompletion(processedRequest, response, mappedHandler, ex);  }  catch (Throwable err) {    triggerAfterCompletion(processedRequest, response, mappedHandler,                new NestedServletException("Handler processing failed", 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);      }    }  }}

首先是分析getHandler(),找到对应的处理器映射逻辑。

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {  if (this.handlerMappings != null) {    for (HandlerMapping mapping : this.handlerMappings) {      HandlerExecutionChain handler = mapping.getHandler(request);      if (handler != null) {        return handler;      }    }  }  return null;}

我们将断点标记在getHandler方法上时,可以清除看到handlerMappings,如图。

使用SpringMVC请求怎么对handler进行映射

这里,用户请求与处理器的映射关系都在RequestMapperHandlerMapping中,而欢迎页处理请求则在WelcomePageHanderMapping中进行映射。

以下为RequestMapperHandlerMapping中映射部分截图,可以看到用户的所有请求映射这里面都有:

使用SpringMVC请求怎么对handler进行映射

getHandler()后的方法是通过比较request请求中method与HandlerMapper中相同url下的method,再进行唯一性校验,不通过异常,通过找到唯一的handler。

后续,通过handler找到处理的设配器,通过适配器得到一个ModelAndView对象,这个对象就是最后返回给前端页面的对象。

至此,一个请求完整映射到返回前端结束。

说明:这是实现了FramworkServlet的doService方法,FramworkServlet继承自HttpServlet,并且重写了父类中的doGet(),doPost(),doPut(),doDelete 等方法,在这些重写的方法里都调用了 processRquest() 方法做请求处理,进入processRquest()可以看到里面调用了FramworkServlet中定义的doService() 方法。

上述就是小编为大家分享的使用SpringMVC请求怎么对handler进行映射了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯