@RestControllerpublicclassHelloController{@PatchMapping("/hello")// above statement is a shortcut for below statement// @RequestMapping(value = "/hello", method = RequestMethod.PATCH)publicResponseDatahello(){returnResponseData.success(null);}@PutMapping("/hello")// above statement is a shortcut for below statement// @RequestMapping(value = "/hello", method = RequestMethod.PUT)publicResponseDatahello2(){returnResponseData.success(null);}}
packagejakarta.servlet.http;publicabstractclassHttpServletextendsGenericServlet{// .../**
* Dispatches client requests to the protected service method. There's no need to override this method.
* ...
*/@Overridepublicvoidservice(ServletRequest req,ServletResponse res)throwsServletException,IOException{HttpServletRequest request;HttpServletResponse response;try{
request =(HttpServletRequest) req;
response =(HttpServletResponse) res;}catch(ClassCastException e){thrownewServletException(lStrings.getString("http.non_http"));}service(request, response);}// ...protectedvoidservice(HttpServletRequest req,HttpServletResponse resp)throwsServletException,IOException{String method = req.getMethod();if(method.equals(METHOD_GET)){// ..doGet(req, resp);// ...}elseif(method.equals(METHOD_HEAD)){// ..doHead(req, resp);}elseif(method.equals(METHOD_POST)){doPost(req, resp);}elseif(method.equals(METHOD_PUT)){doPut(req, resp);}elseif(method.equals(METHOD_DELETE)){doDelete(req, resp);}elseif(method.equals(METHOD_OPTIONS)){doOptions(req, resp);}elseif(method.equals(METHOD_TRACE)){doTrace(req, resp);}else{// Note that this means NO servlet supports whatever// method was requested, anywhere on this server.}}// ...}
packageorg.springframework.web.servlet;publicabstractclassHttpServletBeanextendsHttpServletimplementsEnvironmentCapable,EnvironmentAware{// ...// no override service(), subclass `FrameworkServlet` will implement this method// ...}
packageorg.springframework.web.servlet;publicabstractclassFrameworkServletextendsHttpServletBeanimplementsApplicationContextAware{// ...privatestaticfinalSet<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).
*/@Overrideprotectedvoidservice(HttpServletRequest request,HttpServletResponse response)throwsServletException,IOException{if(HTTP_SERVLET_METHODS.contains(request.getMethod())){super.service(request, response);}// PATCH is missing, so process will go hereelse{processRequest(request, response);}}// ...@OverrideprotectedfinalvoiddoGet(HttpServletRequest request,HttpServletResponse response)throwsServletException,IOException{processRequest(request, response);}/**
* Delegate POST requests to {@link #processRequest}.
* @see #doService
*/@OverrideprotectedfinalvoiddoPost(HttpServletRequest request,HttpServletResponse response)throwsServletException,IOException{processRequest(request, response);}/**
* Delegate PUT requests to {@link #processRequest}.
* @see #doService
*/@OverrideprotectedfinalvoiddoPut(HttpServletRequest request,HttpServletResponse response)throwsServletException,IOException{processRequest(request, response);}/**
* Delegate DELETE requests to {@link #processRequest}.
* @see #doService
*/@OverrideprotectedfinalvoiddoDelete(HttpServletRequest request,HttpServletResponse response)throwsServletException,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
*/@OverrideprotectedvoiddoOptions(HttpServletRequest request,HttpServletResponse response)throwsServletException,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,newHttpServletResponseWrapper(response){@OverridepublicvoidsetHeader(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
*/@OverrideprotectedvoiddoTrace(HttpServletRequest request,HttpServletResponse response)throwsServletException,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.
*/protectedfinalvoidprocessRequest(HttpServletRequest request,HttpServletResponse response)throwsServletException,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(),newRequestBindingInterceptor());initContextHolders(request, localeContext, requestAttributes);try{doService(request, response);}catch(ServletException|IOException ex){
failureCause = ex;throw ex;}catch(Throwable ex){
failureCause = ex;thrownewServletException("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);}}// ...protectedabstractvoiddoService(HttpServletRequest request,HttpServletResponse response)throwsException;// ...}
packageorg.springframework.web.servlet;publicclassDispatcherServletextendsFrameworkServlet{// ...@OverrideprotectedvoiddoService(HttpServletRequest request,HttpServletResponse response)throwsException{// ...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")protectedvoiddoDispatch(HttpServletRequest request,HttpServletResponse response)throwsException{// ...try{// ...try{// ...// Determine handler for the current request.// important here
mappedHandler =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.
*/@NullableprotectedHandlerExecutionChaingetHandler(HttpServletRequest request)throwsException{if(this.handlerMappings !=null){for(HandlerMapping mapping :this.handlerMappings){HandlerExecutionChain handler = mapping.getHandler(request);if(handler !=null){return handler;}}}returnnull;}// ...}
packageorg.springframework.web.servlet.handler;publicabstractclassAbstractHandlerMappingextendsWebApplicationObjectSupportimplementsHandlerMapping,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@NullablepublicfinalHandlerExecutionChaingetHandler(HttpServletRequest request)throwsException{Object handler =getHandlerzInternal(request);if(handler ==null){
handler =getDefaultHandler();}if(handler ==null){returnnull;}// Bean name or resolved handler?if(handler instanceofString 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);}elseif(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;}// ...}
packageorg.springframework.web.method;publicclassHandlerMethod{// ...publicHandlerMethodcreateWithResolvedBean(){Object handler =this.bean;// default would go hereif(this.bean instanceofString beanName){Assert.state(this.beanFactory !=null,"Cannot resolve bean name without BeanFactory");
handler =this.beanFactory.getBean(beanName);}returnnewHandlerMethod(this, handler);}// ...}