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.mzph.cn/news/3486.shtml

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

相关文章

自动驾驶商用驶入“快车道”,汽车软件厂商如何“抢市”?

L3级及以上自动驾驶的商业化进程正在驶入“快车道”。 一方面&#xff0c;高阶自动驾驶的相关法规及标准不断出台&#xff0c;为自动驾驶行业的发展注入了“强心剂”。 比如工业和信息化部副部长辛国斌就曾表示&#xff0c;将启动智能网联汽车准入和上路通行试点&#xff0c;…

【云原生】k8s之包管理器Helm

前言 每个成功的软件平台都有一个优秀的打包系统&#xff0c;比如Debian、Ubuntu 的 apt&#xff0c;RedHat、CentOS 的 yum。Helm 则是 Kubernetes上 的包管理器&#xff0c;方便我们更好的管理应用。 1.Helm的相关知识 1.1 Helm的简介与了解 Helm本质就是让K8s的应用管理&…

PostgreSQL 的就业前景如何?

PostgreSQL的就业前景非常广阔&#xff0c;它是一种功能强大、可靠且开源的关系型数据库管理系统。以下是说明PostgreSQL就业前景的几个关键点&#xff1a; 1.高需求&#xff1a;随着企业和组织对数据存储和管理的需求不断增长&#xff0c;对数据库专业人员的需求也在持续上升…

Python 算法基础篇之数组和列表:创建、访问、添加和删除元素

Python 算法基础篇之数组和列表&#xff1a;创建、访问、添加和删除元素 引用 1. 数组的概念和创建2. 列表的概念和创建3. 访问数组和列表中的元素4. 添加和删除元素 a ) 添加元素 b ) 删除元素 总结 引用 在算法和数据结构中&#xff0c;数组和列表是常见的数据结构&#xff…

Tomcat工作原理

一、Tomcat架构 ### 说明&#xff1a; Server&#xff1a;表示整个 Tomcat Catalina servlet 容器&#xff0c;Server 中可以有多个 Service。&#xff08;可以通过telenet 8005后连接后输入“SHUTDOWN” 注意这里是大写&#xff0c;来关闭服务&#xff09;Service&#xff1…

Microsoft Update Assistant导致 MAC 电脑内存占用过高解决方案

目录 问题: 排查原因: 解决方案: 问题: 一直很苦恼,每次开机隔会发下电脑内存就 100%了,这次找了下原因,也记录下. 排查原因: 通过 mac 自带的活动监视器,发现居然是Microsoft Update Assistant它导致的 解决方案: 那这样就简单了,这个应该是 word,execl 的一个自动更新程序…

Spring 事务控制

1. 编程式事务控制相关对象 1.1 平台事务管理器 1.2 事务定义对象 1.3 事务状态对象 关系&#xff1a; PlatformTransactionManager TransactionManager TransactionStatus 2. 基于XML的声明式事务控制 切点&#xff1a;&#xff08;目标对象&#xff09;业务方法&#xff…

OpenCv之Canny

目录 一、自适应阈值 二、边缘检测Canny 一、自适应阈值 引入前提:在前面的部分我们使用是全局闻值&#xff0c;整幅图像采用同一个数作为闻值。当时这种方法并不适应与所有情况&#xff0c;尤其是当同一幅图像上的不同部分的具有不同亮度时。这种情况下我们需要采用自适应闻…

C# OpenCvSharp 直方图均衡化 图像去雾

直方图 直方图均衡化 自适应的直方图均衡化 全局直方图均衡化 局部直方图均衡化 对比度调整 代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using Sy…

手打 小份 kubernetes v1.27.3 集群

文章目录 1. 准备2. yum3. 安装 ansible4. 互信5. hosts6. 关闭防火墙、swap、selinux7. 配置系统文件句柄数8. 启用ipvs9. 修改内核参数10. 安装 containerd11. 安装nerdctl12. kubernetes yum13. 部署 kubernetes13.1 安装工具13.2 初始化配置 14. 部署 master15. 部署 node1…

Tensorflow入门(2)——深度学习框架Tesnsflow 线程+队列+IO操作 文件读取案例

目录 一、二、Tesnsflow入门 & 环境配置 & 认识Tensorflow三、线程与队列与IO操作1.队列实例&#xff1a;完成一个出队列、1、入队列操作(同步操作) 2.队列管理器 创建线程3.线程协调器 管理线程案例&#xff1a;通过队列管理器来实现变量加1&#xff0c;入队&#xff…

使用更少数据训练更好的alpaca

概述 该论文的研究背景是指令微调在大型语言模型中取得了重要的成果&#xff0c;但现有的训练数据质量问题导致模型性能下降。 过去的方法主要是使用低质量的数据进行指令微调&#xff0c;这些数据中存在错误或无关的回答&#xff0c;导致结果误导和训练成本增加。该论文的方…

Redis对象结构 — RedisObject

目录 Redis 键值对数据库的全过程​编辑 RedisObject结构体 Redis的encoding编码方式 type对应的数据对象类型 Redis 键值对数据库的全过程 redisDb 结构&#xff0c;表示 Redis 数据库的结构&#xff0c;结构体里存放了指向了 dict 结构的指针&#xff1b;dict 结构&#…

Windows操纵kafka

这里写目录标题 启动kafk创建一个测试主题查看所有主题查看first详细信息修改分区数(分区数只能增加 不能减少)删除主题生产者生产数据消费命令 启动kafk 安装目录下 .\bin\windows\kafka-server-start.bat .\config\server.properties创建一个测试主题 安装目录下 .\bin\wi…

Revit中墙体的问题,门窗洞口及柱断梁墙

一、如何同时开两道相邻墙的门窗洞口 做外墙装饰的时候&#xff0c;我们很经常为了方便、简洁在已经绘制好的墙体外围再绘制一面墙体&#xff0c;并且添加上材质作为外饰面&#xff0c;提高工作效率;但是遇到有门窗洞口的墙体时&#xff0c;外饰面墙体却没办法直接被门窗剪切&a…

Android APP性能及专项测试

Android篇 1. 性能测试 Android性能测试分为两类&#xff1a; 1、一类为rom版本&#xff08;系统&#xff09;的性能测试 2、一类为应用app的性能测试Android的app性能测试包括的测试项比如&#xff1a; 1、资源消耗 2、内存泄露 3、电量功耗 4、耗时 5、网络流量消耗 6、移动…

【hadoop】部署hadoop的伪分布模式

hadoop的伪分布模式 伪分布模式的特点部署伪分布模式hadoop-env.shhdfs-site.xmlcore-site.xmlmapred-site.xmlyarn-site.xml对NameNode进行格式化启动Hadoop 对部署是否完成进行测试免密码模式免密码模式的原理&#xff08;重要&#xff09;免密码模式的配置 伪分布模式的特点…

东莞-戴尔R540服务器故障告警处理方法

DELL PowerEdge R540服务器故障维修案例&#xff1a;&#xff08;看到文章就是缘分&#xff09; 客户名称&#xff1a;东莞市某街道管理中心 故障机型&#xff1a;DELL R540服务器 故障问题&#xff1a;DELL R540服务器无法开机&#xff0c;前面板亮黄灯&#xff0c;工程师通过…

备战秋招 | 笔试强训9

目录 一、选择题 二、编程题 三、选择题题解 四、编程题题解 一、选择题 1、某函数申明如下&#xff08;&#xff09; void Func(int &nVal1); A. Func(a) B. Func(&a) C. Func(*a) D. Func(&(*a)) 2、C语言中&#xff0c;类ClassA的构造函数和析构函数的执行…

Layui基本功能(增删改查)

话不多说&#xff0c;根据我前面的博客我们直接进行操作。记住以下的文件放置&#xff0c;防止操作出不来. 这是我们要完成的界面及功能 后台功能实现 数据查看 我们在userDao方法里面进行增删改查的方法我们在userAction进行方法的编写R工具类的介绍 查询 userDao方法 因为我…