亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringBoot之@Controller和@RequestMapping的實(shí)現(xiàn)原理解讀

 更新時(shí)間:2025年04月19日 09:26:58   作者:西魏陶淵明  
這篇文章主要介紹了SpringBoot之@Controller和@RequestMapping的實(shí)現(xiàn)原理,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

SpringBoot之@Controller和@RequestMapping的實(shí)現(xiàn)原理

干貨分享,SpringBoot中Web接口資源是如何被管理起來(lái)呢?

一個(gè)請(qǐng)求,通過(guò)在瀏覽器上輸入了一個(gè)url,是如何被SpringWeb匹配到對(duì)應(yīng)的方法的呢?

帶著這個(gè)疑問(wèn)我們來(lái)學(xué)習(xí)本篇。

瀏覽器的請(qǐng)求,是如何被映射到后端服務(wù)的方法上呢?

后端服務(wù)使用SpringBoot只使用了一個(gè)注解就提供了web服務(wù)的實(shí)現(xiàn)原理是什么呢?

@RestController
public class TestController {

    @GetMapping("/name")
    public String name(HttpServletRequest request){
        return request.toString();
    }
}

帶著上面的疑問(wèn),小編通過(guò)源碼的方式帶你一看究竟吧。 為了能讓各位童鞋更好的更容易的理解。第一趴我們先來(lái)補(bǔ)充點(diǎn)知識(shí)點(diǎn)。

一、注解派生概念

在java體系中,類是可以被繼承,接口可以被實(shí)現(xiàn)。但是注解沒(méi)有這些概念,而是有一個(gè)派生的概念。舉例,注解A。被標(biāo)記了在注解B頭上,那么我們可以說(shuō)注解B就是注解A的派生。

下面我們舉一個(gè)例子:

@RestController
public class PostController {

    @ApiOperation(value = "查詢Bbs所有文章")
    @PostMapping(value = "/query/bbs/posts", produces = MediaType.APPLICATION_JSON_VALUE)
    public Result<PostAllResponse> queryBbsPostAll(@RequestBody PostAllSelectRequest postAllSelectRequest) {
        return postBiz.queryBbsPostAll(postAllSelectRequest);
    }

    public static void main(String[] args) {
        Method queryBbsPostAll = ClassUtils.getMethod(PostController.class, "queryBbsPostAll",PostAllSelectRequest.class);
        PostMapping annotation = AnnotationUtils.findAnnotation(queryBbsPostAll, PostMapping.class);
        ///query/bbs/posts
        System.out.println(StringUtils.arrayToCommaDelimitedString(annotation.value()));
        //application/json
        System.out.println(StringUtils.arrayToCommaDelimitedString(annotation.produces()));
        //是否包含RequestMapping: true
        System.out.println("是否包含RequestMapping: "+AnnotatedElementUtils.hasAnnotation(queryBbsPostAll,RequestMapping.class));

        RequestMapping mergedAnnotation = AnnotatedElementUtils.getMergedAnnotation(queryBbsPostAll, RequestMapping.class);
        ///query/bbs/posts
        System.out.println(StringUtils.arrayToCommaDelimitedString(mergedAnnotation.value()));
    }
}
  • queryBbsPostAll是用了PostMapping類進(jìn)行標(biāo)記是一個(gè)POST資源
  • 我們通過(guò)main方法里面可以知道。通過(guò)反射我們能拿到Method上的PostMapping注解信息。
  • 但是看這一行AnnotatedElementUtils.hasAnnotation(queryBbsPostAll,RequestMapping.class)為什么也是true呢?

沒(méi)錯(cuò)因?yàn)镻ostMapping是RequestMapping的派生注解。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping(method = RequestMethod.POST)
public @interface PostMapping {
   ...
}

請(qǐng)記住這個(gè)小的知識(shí)點(diǎn),后面的邏輯會(huì)用到。因?yàn)橄旅婧笥写罅康脑创a,為了方便標(biāo)注,小編使用截圖的形式,在截圖上會(huì)加上注釋信息。 ?

二、進(jìn)入正題,跟進(jìn)源碼解析請(qǐng)求Method

通過(guò)跟進(jìn)源碼,我們會(huì)發(fā)現(xiàn)這樣一個(gè)類。AbstractHandlerMethodMapping。其實(shí)現(xiàn)了實(shí)現(xiàn) InitializingBean接口。在當(dāng)前 Bean初始化時(shí)候會(huì)執(zhí)行afterPropertiesSet -> initHandlerMethods。

public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {

    @Override
    public void afterPropertiesSet() {
        initHandlerMethods();
    }
    
    /**
  * Scan beans in the ApplicationContext, detect and register handler methods.
  * @see #getCandidateBeanNames()
  * @see #processCandidateBean
  * @see #handlerMethodsInitialized
  */
    protected void initHandlerMethods() {
        for (String beanName : getCandidateBeanNames()) {
            if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
                processCandidateBean(beanName);
            }
        }
        handlerMethodsInitialized(getHandlerMethods());
    }
}

RequestMappingHandlerMapping解析Method上的RequestMapping信息

isHandler 方法判斷是否是web資源類。當(dāng)一個(gè)類被標(biāo)記了 @Controller 或者@RequestMapping。 注意 @RestController 是@Controller的派生類。所以這里只用判斷 @Controller 或者@RequestMapping就行了。

 @Override
 protected boolean isHandler(Class<?> beanType) {
  return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
    AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
 }

detectHandlerMethods方法就是真正開始解析Method的邏輯。通過(guò)解析Method上的 @RequestMapping或者其他派生的注解。生成請(qǐng)求信息。 注意這個(gè)請(qǐng)求信息里面也是有很多邏輯的不過(guò)不是本篇討論的重點(diǎn),就不說(shuō)了。稍微提一下。根據(jù)規(guī)則來(lái)匹配url邏輯就在這里面。

這里我們能看到源碼里拿到了Method并拿到了執(zhí)行這個(gè)Method的實(shí)例Bean。在這里封裝成了HandlerMethod并注冊(cè)到了MappingRegistry中。

在注冊(cè)的過(guò)程中把RequestMapping中的路徑信息同事也放到一個(gè)urlLookup中。key是url,value是Mapping信息。

到這里其實(shí)我們就把本篇的議題就說(shuō)明清楚了。下面我們?cè)诳聪耂pringWeb是如何將http請(qǐng)求信息路由到具體的HandlerMethod的吧。

三、最后串一下請(qǐng)求流程

看了前面的截圖,我們知道Spring是如何把這些Web資源信息給保存起來(lái)的了。然后就看是DispatcherServlet的邏輯了。 首先DispatcherServlet 是一個(gè)Servlet。Servlet相信大家都都知道就不重點(diǎn)說(shuō)原理。 我們直接看doService -> doDispatch 方法

根據(jù)請(qǐng)求路徑,找到從Mapping信息,然后根據(jù)Mapping信息匹配到具體的HandlerMethod。 ok本篇內(nèi)容就到這里。謝謝大家。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Maven繼承父工程時(shí)的relativePath標(biāo)簽解析用法小結(jié)

    Maven繼承父工程時(shí)的relativePath標(biāo)簽解析用法小結(jié)

    relativePath 的作用是為了找到父級(jí)工程的pom.xml,本文主要介紹了Maven繼承父工程時(shí)的relativePath標(biāo)簽解析用法小結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-03-03
  • 詳解Java集合類之HashSet篇

    詳解Java集合類之HashSet篇

    這篇文章主要為大家詳細(xì)介紹一下Java集合類中HashSet的用法,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Java有一定幫助,感興趣的可以了解一下
    2022-07-07
  • Kotlin null的處理詳解

    Kotlin null的處理詳解

    這篇文章主要介紹了Kotlin null的處理詳解的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • java利用udp實(shí)現(xiàn)發(fā)送數(shù)據(jù)

    java利用udp實(shí)現(xiàn)發(fā)送數(shù)據(jù)

    這篇文章主要為大家詳細(xì)介紹了java利用udp實(shí)現(xiàn)發(fā)送數(shù)據(jù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • Java數(shù)據(jù)導(dǎo)入功能之讀取Excel文件實(shí)例

    Java數(shù)據(jù)導(dǎo)入功能之讀取Excel文件實(shí)例

    這篇文章主要介紹了Java數(shù)據(jù)導(dǎo)入功能之讀取Excel文件實(shí)例,本文給出了jar包的下載地址以及讀取Excel文件的代碼實(shí)例,需要的朋友可以參考下
    2015-06-06
  • 超細(xì)講解Java調(diào)用python文件的幾種方式

    超細(xì)講解Java調(diào)用python文件的幾種方式

    有時(shí)候我們?cè)趯慾ava的時(shí)候需要調(diào)用python文件,下面這篇文章主要給大家介紹了關(guān)于Java調(diào)用python文件的幾種方式,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-12-12
  • Java 中的語(yǔ)法糖,真甜

    Java 中的語(yǔ)法糖,真甜

    語(yǔ)法糖(Syntactic sugar),也叫做糖衣語(yǔ)法,是英國(guó)科學(xué)家發(fā)明的一個(gè)術(shù)語(yǔ),通常來(lái)說(shuō)使用語(yǔ)法糖能夠增加程序的可讀性,從而減少程序代碼出錯(cuò)的機(jī)會(huì).這篇文章主要介紹了Java 中的語(yǔ)法糖知識(shí),需要的朋友可以參考下
    2020-12-12
  • mybatis3使用@Select等注解實(shí)現(xiàn)增刪改查操作

    mybatis3使用@Select等注解實(shí)現(xiàn)增刪改查操作

    這篇文章主要介紹了mybatis3使用@Select等注解實(shí)現(xiàn)增刪改查操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-11-11
  • Java解析調(diào)用webservice服務(wù)的返回XML串詳解

    Java解析調(diào)用webservice服務(wù)的返回XML串詳解

    這篇文章主要介紹了Java解析調(diào)用webservice服務(wù)的返回XML串詳解的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07
  • java面向?qū)ο笤O(shè)計(jì)原則之迪米特法則分析詳解

    java面向?qū)ο笤O(shè)計(jì)原則之迪米特法則分析詳解

    這篇文章主要為大家介紹了java面向?qū)ο笤O(shè)計(jì)原則之迪米特法則的示例分析詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,學(xué)有所得
    2021-10-10

最新評(píng)論