Spring @RequestMapping 工作原理

Spring @RequestMapping 工作原理

配置基础启动类及Controller类

@SpringBootApplication
public class DemoServiceApplication {public static void main(String[] args) {SpringApplication.run(DemoServiceApplication.class, args);}
}
@RestController
public class HelloController {@PatchMapping("/hello")// above statement is a shortcut for below statement// @RequestMapping(value = "/hello", method = RequestMethod.PATCH)public ResponseData hello() {return ResponseData.success(null);}@PutMapping ("/hello")// above statement is a shortcut for below statement// @RequestMapping(value = "/hello", method = RequestMethod.PUT)public ResponseData hello2() {return ResponseData.success(null);}
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping(method = RequestMethod.PATCH)
public @interface PatchMapping {// ...
}@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping(method = RequestMethod.PUT)
public @interface PutMapping {// ...
}

请求验证

$ curl -X PUT http://localhost:8080/hello

在这里插入图片描述

package jakarta.servlet.http;public abstract class HttpServlet extends GenericServlet {// .../*** Dispatches client requests to the protected service method. There's no need to override this method.* ...*/@Overridepublic void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {HttpServletRequest request;HttpServletResponse response;try {request = (HttpServletRequest) req;response = (HttpServletResponse) res;} catch (ClassCastException e) {throw new ServletException(lStrings.getString("http.non_http"));}service(request, response);}// ...protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String method = req.getMethod();if (method.equals(METHOD_GET)) {// ..doGet(req, resp);// ...} else if (method.equals(METHOD_HEAD)) {// ..doHead(req, resp);} else if (method.equals(METHOD_POST)) {doPost(req, resp);} else if (method.equals(METHOD_PUT)) {doPut(req, resp);} else if (method.equals(METHOD_DELETE)) {doDelete(req, resp);} else if (method.equals(METHOD_OPTIONS)) {doOptions(req, resp);} else if (method.equals(METHOD_TRACE)) {doTrace(req, resp);} else {// Note that this means NO servlet supports whatever// method was requested, anywhere on this server.}}// ...
}
package org.springframework.web.servlet;public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware {// ...// no override service(), subclass `FrameworkServlet` will implement this method// ...
}
package org.springframework.web.servlet;public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {// ...private static final Set<String> HTTP_SERVLET_METHODS =Set.of("DELETE", "HEAD", "GET", "OPTIONS", "POST", "PUT", "TRACE");// .../*** Override the parent class implementation in order to intercept requests* using PATCH or non-standard HTTP methods (WebDAV).*/@Overrideprotected void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {if (HTTP_SERVLET_METHODS.contains(request.getMethod())) {super.service(request, response);} // PATCH is missing, so process will go hereelse {processRequest(request, response);}}// ...@Overrideprotected final void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {processRequest(request, response);}/*** Delegate POST requests to {@link #processRequest}.* @see #doService*/@Overrideprotected final void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {processRequest(request, response);}/*** Delegate PUT requests to {@link #processRequest}.* @see #doService*/@Overrideprotected final void doPut(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {processRequest(request, response);}/*** Delegate DELETE requests to {@link #processRequest}.* @see #doService*/@Overrideprotected final void doDelete(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {processRequest(request, response);}/*** Delegate OPTIONS requests to {@link #processRequest}, if desired.* <p>Applies HttpServlet's standard OPTIONS processing otherwise,* and also if there is still no 'Allow' header set after dispatching.* @see #doService*/@Overrideprotected void doOptions(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {if (this.dispatchOptionsRequest || CorsUtils.isPreFlightRequest(request)) {processRequest(request, response);if (response.containsHeader(HttpHeaders.ALLOW)) {// Proper OPTIONS response coming from a handler - we're done.return;}}// Use response wrapper in order to always add PATCH to the allowed methodssuper.doOptions(request, new HttpServletResponseWrapper(response) {@Overridepublic void setHeader(String name, String value) {if (HttpHeaders.ALLOW.equals(name)) {value = (StringUtils.hasLength(value) ? value + ", " : "") + HttpMethod.PATCH.name();}super.setHeader(name, value);}});}/*** Delegate TRACE requests to {@link #processRequest}, if desired.* <p>Applies HttpServlet's standard TRACE processing otherwise.* @see #doService*/@Overrideprotected void doTrace(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {if (this.dispatchTraceRequest) {processRequest(request, response);if ("message/http".equals(response.getContentType())) {// Proper TRACE response coming from a handler - we're done.return;}}super.doTrace(request, response);}/*** Process this request, publishing an event regardless of the outcome.* <p>The actual event handling is performed by the abstract* {@link #doService} template method.*/protected final void processRequest(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {long startTime = System.currentTimeMillis();Throwable failureCause = null;LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();LocaleContext localeContext = buildLocaleContext(request);RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());initContextHolders(request, localeContext, requestAttributes);try {doService(request, response);}catch (ServletException | IOException ex) {failureCause = ex;throw ex;}catch (Throwable ex) {failureCause = ex;throw new ServletException("Request processing failed: " + ex, ex);}finally {resetContextHolders(request, previousLocaleContext, previousAttributes);if (requestAttributes != null) {requestAttributes.requestCompleted();}logResult(request, response, failureCause, asyncManager);publishRequestHandledEvent(request, response, startTime, failureCause);}}// ...protected abstract void doService(HttpServletRequest request, HttpServletResponse response) throws Exception;// ...
}
package org.springframework.web.servlet;public class DispatcherServlet extends FrameworkServlet {// ...@Overrideprotected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {// ...try {doDispatch(request, response);}finally {// ...}// ...}// .../*** Process the actual dispatching to the handler.* The handler will be obtained by applying the servlet's HandlerMappings in order. * The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters to find the first that supports the handler class. * All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers themselves to decide which methods are acceptable.*/	 @SuppressWarnings("deprecation")protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {// ...try {// ...try {// ...// Determine handler for the current request.// important heremappedHandler = getHandler(processedRequest);// ...// Determine handler adapter for the current request.HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());// ...// Actually invoke the handler.mv = ha.handle(processedRequest, response, mappedHandler.getHandler());if (asyncManager.isConcurrentHandlingStarted()) {return;}applyDefaultViewName(processedRequest, mv);mappedHandler.applyPostHandle(processedRequest, response, mv);}// catch()} //catch()}// .../*** Return the HandlerExecutionChain for this request.* <p>Tries all handler mappings in order.*/@Nullableprotected 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;}// ...
}		
this.handlerMappings = {ArrayList@7649}  size = 50 = {RequestMappingHandlerMapping@6913} 1 = {BeanNameUrlHandlerMapping@7828} 2 = {RouterFunctionMapping@7829} 3 = {SimpleUrlHandlerMapping@7830} 4 = {WelcomePageHandlerMapping@7831} 

展开 0 = {RequestMappingHandlerMapping@6913}

 mappingRegistry = {AbstractHandlerMethodMapping$MappingRegistry@6921} registry = {HashMap@7840}  size = 5{RequestMappingInfo@7864} "{GET [/api/tutorials]}" -> {AbstractHandlerMethodMapping$MappingRegistration@7865} {RequestMappingInfo@7866} "{ [/error], produces [text/html]}" -> {AbstractHandlerMethodMapping$MappingRegistration@7867} {RequestMappingInfo@7868} "{PATCH [/hello]}" -> {AbstractHandlerMethodMapping$MappingRegistration@7869} {RequestMappingInfo@7870} "{ [/error]}" -> {AbstractHandlerMethodMapping$MappingRegistration@7871} {RequestMappingInfo@7872} "{PUT [/hello]}" -> {AbstractHandlerMethodMapping$MappingRegistration@7873} pathLookup = {LinkedMultiValueMap@7841}  size = 3"/api/tutorials" -> {ArrayList@7852}  size = 1"/hello" -> {ArrayList@7854}  size = 2"/error" -> {ArrayList@7856}  size = 2

在这里插入图片描述

package org.springframework.web.servlet.handler;public abstract class AbstractHandlerMapping extends WebApplicationObjectSupportimplements HandlerMapping, Ordered, BeanNameAware {// .../*** Look up a handler for the given request, falling back to the default* handler if no specific one is found.* @param request current HTTP request* @return the corresponding handler instance, or the default handler* @see #getHandlerInternal*/@Override@Nullablepublic final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {Object handler = getHandlerzInternal(request);if (handler == null) {handler = getDefaultHandler();}if (handler == null) {return null;}// Bean name or resolved handler?if (handler instanceof String handlerName) {handler = obtainApplicationContext().getBean(handlerName);}// Ensure presence of cached lookupPath for interceptors and othersif (!ServletRequestPathUtils.hasCachedPath(request)) {initLookupPath(request);}HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);if (logger.isTraceEnabled()) {logger.trace("Mapped to " + handler);}else if (logger.isDebugEnabled() && !DispatcherType.ASYNC.equals(request.getDispatcherType())) {logger.debug("Mapped to " + executionChain.getHandler());}if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {CorsConfiguration config = getCorsConfiguration(handler, request);if (getCorsConfigurationSource() != null) {CorsConfiguration globalConfig = getCorsConfigurationSource().getCorsConfiguration(request);config = (globalConfig != null ? globalConfig.combine(config) : config);}if (config != null) {config.validateAllowCredentials();}executionChain = getCorsHandlerExecutionChain(request, executionChain, config);}return executionChain;}// ...
}
package org.springframework.web.servlet.mvc.method;
public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMethodMapping<RequestMappingInfo> {// ..@Override@Nullableprotected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {// ...return super.getHandlerInternal(request);// ...}// ...	
}
package org.springframework.web.servlet.handler;public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {// ...@Override@Nullableprotected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {String lookupPath = initLookupPath(request);this.mappingRegistry.acquireReadLock();try {HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);}finally {this.mappingRegistry.releaseReadLock();}}// ...@Nullableprotected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {List<Match> matches = new ArrayList<>();List<T> directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath);if (directPathMatches != null) {addMatchingMappings(directPathMatches, matches, request);}if (matches.isEmpty()) {addMatchingMappings(this.mappingRegistry.getRegistrations().keySet(), matches, request);}if (!matches.isEmpty()) {Match bestMatch = matches.get(0);if (matches.size() > 1) {Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));matches.sort(comparator);bestMatch = matches.get(0);if (logger.isTraceEnabled()) {logger.trace(matches.size() + " matching mappings: " + matches);}if (CorsUtils.isPreFlightRequest(request)) {for (Match match : matches) {if (match.hasCorsConfig()) {return PREFLIGHT_AMBIGUOUS_MATCH;}}}else {Match secondBestMatch = matches.get(1);if (comparator.compare(bestMatch, secondBestMatch) == 0) {Method m1 = bestMatch.getHandlerMethod().getMethod();Method m2 = secondBestMatch.getHandlerMethod().getMethod();String uri = request.getRequestURI();throw new IllegalStateException("Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");}}}request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.getHandlerMethod());handleMatch(bestMatch.mapping, lookupPath, request);return bestMatch.getHandlerMethod();}else {return handleNoMatch(this.mappingRegistry.getRegistrations().keySet(), lookupPath, request);}}// ...
}

查看looupPath

lookupPath="/hello"
this.mappingRegistry = {AbstractHandlerMethodMapping$MappingRegistry@6921} registry = {HashMap@7840}  size = 5{RequestMappingInfo@7864} "{GET [/api/tutorials]}" -> {AbstractHandlerMethodMapping$MappingRegistration@7865} {RequestMappingInfo@7866} "{ [/error], produces [text/html]}" -> {AbstractHandlerMethodMapping$MappingRegistration@7867} {RequestMappingInfo@7868} "{PATCH [/hello]}" -> {AbstractHandlerMethodMapping$MappingRegistration@7869} {RequestMappingInfo@7870} "{ [/error]}" -> {AbstractHandlerMethodMapping$MappingRegistration@7871} {RequestMappingInfo@7872} "{PUT [/hello]}" -> {AbstractHandlerMethodMapping$MappingRegistration@7873} pathLookup = {LinkedMultiValueMap@7841}  size = 3"/api/tutorials" -> {ArrayList@7852}  size = 1"/hello" -> {ArrayList@7854}  size = 2"/error" -> {ArrayList@7856}  size = 2

directPathMatches

List<T> directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath);
directPathMatches = {ArrayList@7854}  size = 20 = {RequestMappingInfo@7872} "{PUT [/hello]}"1 = {RequestMappingInfo@7868} "{PATCH [/hello]}"
package org.springframework.web.method;public class HandlerMethod {// ...public HandlerMethod createWithResolvedBean() {Object handler = this.bean;// default would go hereif (this.bean instanceof String beanName) {Assert.state(this.beanFactory != null, "Cannot resolve bean name without BeanFactory");handler = this.beanFactory.getBean(beanName);}return new HandlerMethod(this, handler);}// ...
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/21974.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

yapi的部署和安装

安装Node.js环境 wget https://nodejs.org/dist/v14.15.4/node-v14.15.4-linux-x64.tar.xz 或者直接浏览器下载传输到服务器上。 https://nodejs.org/zh-cn/download/tar -xvf node-v14.15.4-linux-x64.tar.xz 太高版本不行&#xff0c;install会报错。16开头的。 配置环境…

FastAPI 初体验,效率杠杠滴

目录 前言&#xff1a; 1、官网信息 2、环境安装 3、写个demo 4、关注的几个技术点 4.1 路径参数数据接收 4.2 查询参数数据接收 4.3 post 数据接收 4.4 header数据接收 4.5 cookie数据接收 5、总结 5.1 没有使用门槛 5.2 开发效率 5.3 劣势 前言&#xff1a; 写…

Vue简单使用及整合elementui

创建vue工程 在vue工程目录下npm install vue 下载离线vue https://v2.vuejs.org/v2/guide/installation.html 引入工程中 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" c…

C# 参数传递(引用类型参数)

目录 一&#xff0c;引言 二&#xff0c;引用类型参数作为值参数传递 三&#xff0c;引用类型参数作为引用参数传递 一&#xff0c;引言 方法中参数的传递方式主要有值参数传递和引用参数传递&#xff08;ref&#xff0c;out&#xff09;&#xff0c;而参数有可以分为值类型…

构造稀疏矩阵例子

构造稀疏矩阵的目的是在处理具有大量零元素的大规模数据时&#xff0c;节省内存空间和计算资源&#xff0c;并提高计算效率。稀疏矩阵是一种特殊的矩阵&#xff0c;其中包含许多零元素和一些非零元素。 #include "pcl.h" #include "common.h" #include &qu…

设计模式——责任链模式

责任链模式 定义 使多个对象都有机会处理请求&#xff0c;从而避免了请求的发送者和接收者之间的耦合关系。将这些对象连成一条链&#xff0c;并沿着这条链传递该请求&#xff0c;知道有对象处理它为止。 优缺点 优点 能将请求和处理分开。请求者可以不用知道是谁处理的&a…

Java设计模式之结构型-代理模式(UML类图+案例分析)

目录 一、基础概念 二、UML类图 1、静态代理类图 2、动态代理类图 三、角色设计 四、案例分析 1、静态代理 2、JDK动态代理 3、Cglib动态代理 五、总结 一、基础概念 代理模式是一种结构型设计模式&#xff0c;它用一个代理对象来封装一个目标对象&#xff0c;通常…

Python+docx实现python对word文档的编辑

前言&#xff1a; 该模块可以通过python代码来对word文档进行大批量的编辑。docx它提供了一组功能丰富的函数和方法&#xff0c;用于创建、修改和读取Word文档。下面是docx模块中一些常用的函数和方法的介绍&#xff1a; 安装&#xff1a;pip install docx 一、准备一个word文档…

MYSQL执行一条SELECT语句的具体流程

昨天CSDN突然抽风 我一个ctrlz把整篇文章给撤掉了还不能复原 直接心态崩了不想写了 不过这部分果然还是很重要,还是写出来吧 流程图 这里面总共有两层结构Server层 储存引擎 Server 层负责建立连接、分析和执行 SQL。MySQL 大多数的核心功能模块都在这实现&#xff0c;主要包…

WebSocket理解

WebSocket理解 WebSocket定义与HTTP关系相同点:不同点&#xff1a;联系总体过程 HTTP问题长轮询Ajax轮询 WebSocket特点 WebSocket 定义 本质上是TCP的协议 持久化的协议 实现了浏览器和服务器的全双工通信&#xff0c;能更好的节省服务器资源和带宽 与HTTP关系 相同点: 基于…

【bug】flameshot在ubuntu上的4K屏幕,双屏幕上用不了截图

问题 直接在4K屏幕上运行flameshot截图&#xff0c;直接黑屏 主屏 &#xff1a;4K 副屏&#xff1a;2k 解决 2.1长按1-2秒开机键&#xff0c;先回到桌面。 2.2 设置主屏缩放为125% 2.3 设置键盘快捷键命令为env QT_AUTO_SCREEN_SCALE_FACTOR1 flameshot gui 替代flameshot的…

zeppelin的hive使用

zeppelin的hive使用 配置项 default.driver org.apache.hive.jdbc.HiveDriver default.url jdbc:hive2://192.168.xxx.xxx:10000 default.user hiveHive使用&#xff1a;点击create new note Default Interpreter选择hive