亚欧色一区w666天堂,色情一区二区三区免费看,少妇特黄A片一区二区三区,亚洲人成网站999久久久综合,国产av熟女一区二区三区

  • 發布文章
  • 消息中心
點贊
收藏
評論
分享
原創

Springfox與SpringDoc——swagger如何選擇(SpringDoc入門)

2023-02-06 06:47:43
231
0

0.引言

之前寫過一篇關于swagger(實際上(shang)是springfox)的使用(yong)指南(//www.daliqc.cn/developer/article/371704742199365),涵蓋(gai)了本人在(zai)開發與學習(xi)的時候碰(peng)到的各種大(da)坑。但(dan)由于springfox已(yi)經(jing)不更新(xin)了,很多(duo)項目都在(zai)往springdoc遷移

筆者也是花了一些(xie)時間試了一下這個(ge)號稱“把springfox按(an)在地(di)下摩擦(ca)”的springdoc究(jiu)竟好(hao)不(bu)好(hao)使,本文就來簡單介紹下springdoc的使用以及優(you)劣勢

1.引入maven依賴

這里有個(ge)大坑一定要(yao)注意!!!

如果你跟我一樣,現在使用的是springfox,但是想往springdoc遷移,結果試了一下發現還是springfox好用/懶得改那么多注解,還是想換回springfox,一定要把springdoc的maven依賴刪掉!!!不然springboot會默認你用的是springdoc,導致swagger界面出不來

<dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-ui</artifactId>
            <version>1.6.11</version>
 </dependency>

2.springdoc配置類

實際上springdoc的配置非(fei)常簡單,使用的是OpenAPI類與(yu)GroupedOpenApi來(lai)配置

/**
 * SpringDoc API文檔相關配置
 * Created by macro on 2023/02/02.
 */
@Configuration
public class SpringDocConfig {
    @Bean
    public OpenAPI mallTinyOpenAPI() {
        return new OpenAPI()
                .info(new Info().title("CTYUN API")
                        .description("SpringDoc API 演示")
                        .version("v1.0.0")
                        .license(new License().name("Apache 2.0").url("//github.com/")))
                .externalDocs(new ExternalDocumentation()
                        .description("SpringBoot項目")
                        .url("//www.ctyun.com"));
    }

    @Bean
    public GroupedOpenApi adminApi() {
        return GroupedOpenApi.builder()
                .group("admin")
                .pathsToMatch("/**")
                .build();
    }
    //可以創建不同的GroupedOpenApi來判斷不同的controller
    @Bean
    public GroupedOpenApi userApi() {
        return GroupedOpenApi.builder()
                .group("user")
                .pathsToMatch("/user/**")
                .build();
    }
}

3.啟動

默認配(pei)置之后直接進入://localhost:8080/swagger-ui/index.html 即可

注(zhu)意這里與springfox略有不同(//localhost:8080/swagger-ui.html)

4.與SpringFox的注解對照

5.SpringDoc基本注解用法

這(zhe)里(li)轉載一個寫的非常全面的示例接口,原文可以去看://blog.csdn.net/zhenghongcs/article/details/123812583

/**
 * 品牌管理Controller
 * Created by macro on 2019/4/19.
 */
@Tag(name = "PmsBrandController", description = "商品品牌管理")
@Controller
@RequestMapping("/brand")
public class PmsBrandController {
    @Autowired
    private PmsBrandService brandService;

    private static final Logger LOGGER = LoggerFactory.getLogger(PmsBrandController.class);

    @Operation(summary = "獲取所有品牌列表",description = "需要登錄后訪問")
    @RequestMapping(value = "listAll", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<List<PmsBrand>> getBrandList() {
        return CommonResult.success(brandService.listAllBrand());
    }

    @Operation(summary = "添加品牌")
    @RequestMapping(value = "/create", method = RequestMethod.POST)
    @ResponseBody
    @PreAuthorize("hasRole('ADMIN')")
    public CommonResult createBrand(@RequestBody PmsBrand pmsBrand) {
        CommonResult commonResult;
        int count = brandService.createBrand(pmsBrand);
        if (count == 1) {
            commonResult = CommonResult.success(pmsBrand);
            LOGGER.debug("createBrand success:{}", pmsBrand);
        } else {
            commonResult = CommonResult.failed("操作失敗");
            LOGGER.debug("createBrand failed:{}", pmsBrand);
        }
        return commonResult;
    }

    @Operation(summary = "更新指定id品牌信息")
    @RequestMapping(value = "/update/{id}", method = RequestMethod.POST)
    @ResponseBody
    @PreAuthorize("hasRole('ADMIN')")
    public CommonResult updateBrand(@PathVariable("id") Long id, @RequestBody PmsBrand pmsBrandDto, BindingResult result) {
        CommonResult commonResult;
        int count = brandService.updateBrand(id, pmsBrandDto);
        if (count == 1) {
            commonResult = CommonResult.success(pmsBrandDto);
            LOGGER.debug("updateBrand success:{}", pmsBrandDto);
        } else {
            commonResult = CommonResult.failed("操作失敗");
            LOGGER.debug("updateBrand failed:{}", pmsBrandDto);
        }
        return commonResult;
    }

    @Operation(summary = "刪除指定id的品牌")
    @RequestMapping(value = "/delete/{id}", method = RequestMethod.GET)
    @ResponseBody
    @PreAuthorize("hasRole('ADMIN')")
    public CommonResult deleteBrand(@PathVariable("id") Long id) {
        int count = brandService.deleteBrand(id);
        if (count == 1) {
            LOGGER.debug("deleteBrand success :id={}", id);
            return CommonResult.success(null);
        } else {
            LOGGER.debug("deleteBrand failed :id={}", id);
            return CommonResult.failed("操作失敗");
        }
    }

    @Operation(summary = "分頁查詢品牌列表")
    @RequestMapping(value = "/list", method = RequestMethod.GET)
    @ResponseBody
    @PreAuthorize("hasRole('ADMIN')")
    public CommonResult<CommonPage<PmsBrand>> listBrand(@RequestParam(value = "pageNum", defaultValue = "1")
                                                        @Parameter(description = "頁碼") Integer pageNum,
                                                        @RequestParam(value = "pageSize", defaultValue = "3")
                                                        @Parameter(description = "每頁數量") Integer pageSize) {
        List<PmsBrand> brandList = brandService.listBrand(pageNum, pageSize);
        return CommonResult.success(CommonPage.restPage(brandList));
    }

    @Operation(summary = "獲取指定id的品牌詳情")
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    @ResponseBody
    @PreAuthorize("hasRole('ADMIN')")
    public CommonResult<PmsBrand> brand(@PathVariable("id") Long id) {
        return CommonResult.success(brandService.getBrand(id));
    }
}

6.與SpringSecurity的結合

如果項目中使用了SpringSecurity,需要做(zuo)兩個配置來讓springdoc正常使用:

1.在SpringSecurity配(pei)置類中放(fang)行白名單:"/v3/api-docs/**", "/swagger-ui/**"

2.在SpringDoc配置中增加對應內容,如下(xia):

@Configuration
public class SpringDocConfig {

    private static final String SECURITY_SCHEME_NAME = "BearerAuth";

    @Bean
    public OpenAPI managerOpenAPI() {

        return new OpenAPI()
                .info(new Info().title("Galaxy-Cluster-Manager后端接口文檔")
                        .description("提供給前端界面(portal)的接口文檔")
                        .version("v1.0.0")
                        .license(new License().name("galaxy 1.2.0").url("//gitlab.daliqc.cn/hpc/galaxy-parent/-/tree/v1.2.0")))
                .externalDocs(new ExternalDocumentation()
                        .description("彈性高性能計算(CTHPC)")
                        .url("//www.daliqc.cn"))
                //以下是針對SpringSecurity的設置,同時還有設置白名單
                .addSecurityItem(new SecurityRequirement().addList(SECURITY_SCHEME_NAME))
                .components(new Components()
                        .addSecuritySchemes(SECURITY_SCHEME_NAME,
                                new SecurityScheme()
                                        .name(SECURITY_SCHEME_NAME)
                                        .type(SecurityScheme.Type.HTTP)
                                        .scheme("bearer")
                                        .bearerFormat("JWT")));
    }

    @Bean
    public GroupedOpenApi publicApi() {
        return GroupedOpenApi.builder()
                .group("portal")
                .pathsToMatch("/api/**")
                .build();
    }

}

7.SpringDoc使用對象作為Query參數的問題

實際上springfox也會有(you)這個問題,使(shi)用(yong)對象作為query傳參的時候,頁面通常(chang)是這樣(yang)的:

就(jiu)沒有辦法逐個描述參數(shu),也(ye)不能逐個調(diao)試(shi)(只能用(yong)json調(diao)試(shi)),非常(chang)的麻煩(fan);springdoc有一個解(jie)決這個問(wen)題非常(chang)方便的注(zhu)解(jie):@ParameterObject

比如(ru)某一個控制器(qi)的入參是User user,我們只需要在這前面加上注(zhu)解變為:@ParameterObject User user 即可,結果(guo)如(ru)下;

這里也有一個大坑:參數的類型可能會不正確,比如這里我們的id參數實際上是int,但顯示出來是string,這個時候就需要我們在User類的屬性中加上對應的注解,比如:

@Parameter(description = "id傳參(can)",example = "6")

再(zai)重(zhong)啟UI就會發現(xian)參數類(lei)型正確(que)了(le)

8.SpringDoc配置掃包范圍

有的時候(hou)僅(jin)僅(jin)使用(yong)@Hidden并不(bu)(bu)能(neng)滿足我們的需(xu)要(yao),因為可能(neng)需(xu)要(yao)配(pei)置不(bu)(bu)同(tong)group的controller類(lei),這個(ge)時候(hou)就需(xu)要(yao)在(zai)配(pei)置類(lei)中取設置掃(sao)包范圍(wei)代碼如下:

9.SpringDoc的優劣勢

優勢:SpringDoc有著非常好看(kan)的UI,以及比Springfox更加完善(shan)的參數注解體系,看(kan)起來(lai)非常舒服,并且還在不(bu)斷更新與維護中(zhong)

劣勢(shi):一些冷門功(gong)能還不完善,比如:

a.有(you)十個(ge)(ge)接口(kou),他們的(de)url是一樣的(de)但是可(ke)以通(tong)過query參數來分別(bie)(如:@PostMapping(params = "action=QueryUsers"))這個(ge)(ge)時候(hou)springdoc只(zhi)能通(tong)過掃包范(fan)圍配(pei)置,來寫(xie)多個(ge)(ge)GroupOpenApi來解(jie)決,非常的(de)麻煩;springfox可(ke)以在docket創(chuang)建的(de)時候(hou)使用(yong):docket.enableUrlTemplating(true); 這個(ge)(ge)方法即可(ke)解(jie)決

b.springdoc的(de)網絡配(pei)(pei)(pei)置(zhi)可(ke)能會與springfox沖突,如果(guo)遷移,需(xu)要逐(zhu)個嘗試網絡配(pei)(pei)(pei)置(zhi)是(shi)(shi)否合適(主要是(shi)(shi)GsonHttpMessageConverter的(de)配(pei)(pei)(pei)置(zhi))

c.兼容(rong)性(xing)問題仍需要觀望(wang),相對于springfox,springdoc的(de)兼容(rong)性(xing)并沒有那么好,在許多時候可能(neng)會(hui)出現序列化的(de)亂碼問題

 

總結:如果當前項目/工程已經集成了完備的springfox,建議不要輕易嘗試遷移到springdoc,尤其是接口類型比較復雜、springfox配置docket比較多的項目;但如果是從頭開始的項目,由于接口相對比較簡單,可以采用springdoc,畢竟可以獲得更加清晰明了的顯示界面與參數解釋。

 

0條評論
0 / 1000
才開始學技術的小白
23文章數
2粉(fen)絲數
才開始學技術的小白
23 文章 | 2 粉絲
原創

Springfox與SpringDoc——swagger如何選擇(SpringDoc入門)

2023-02-06 06:47:43
231
0

0.引言

之前寫(xie)過一篇關于swagger(實際上(shang)是springfox)的使用指南(//www.daliqc.cn/developer/article/371704742199365),涵蓋了本人(ren)在開(kai)發與學(xue)習(xi)的時候碰到的各(ge)種大坑。但由于springfox已經(jing)不更新了,很多項目都在往springdoc遷移(yi)

筆者也是(shi)花了(le)一些(xie)時間試了(le)一下這(zhe)個號(hao)稱“把springfox按(an)在地下摩擦”的springdoc究竟(jing)好不好使,本(ben)文(wen)就來(lai)簡單介紹下springdoc的使用(yong)以及優劣(lie)勢

1.引入maven依賴

這里(li)有個大坑一(yi)定要注意!!!

如果你跟我一樣,現在使用的是springfox,但是想往springdoc遷移,結果試了一下發現還是springfox好用/懶得改那么多注解,還是想換回springfox,一定要把springdoc的maven依賴刪掉!!!不然springboot會默認你用的是springdoc,導致swagger界面出不來

<dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-ui</artifactId>
            <version>1.6.11</version>
 </dependency>

2.springdoc配置類

實際上(shang)springdoc的配(pei)置非常簡單,使用(yong)的是OpenAPI類與GroupedOpenApi來配(pei)置

/**
 * SpringDoc API文檔相關配置
 * Created by macro on 2023/02/02.
 */
@Configuration
public class SpringDocConfig {
    @Bean
    public OpenAPI mallTinyOpenAPI() {
        return new OpenAPI()
                .info(new Info().title("CTYUN API")
                        .description("SpringDoc API 演示")
                        .version("v1.0.0")
                        .license(new License().name("Apache 2.0").url("//github.com/")))
                .externalDocs(new ExternalDocumentation()
                        .description("SpringBoot項目")
                        .url("//www.ctyun.com"));
    }

    @Bean
    public GroupedOpenApi adminApi() {
        return GroupedOpenApi.builder()
                .group("admin")
                .pathsToMatch("/**")
                .build();
    }
    //可以創建不同的GroupedOpenApi來判斷不同的controller
    @Bean
    public GroupedOpenApi userApi() {
        return GroupedOpenApi.builder()
                .group("user")
                .pathsToMatch("/user/**")
                .build();
    }
}

3.啟動

默認配(pei)置之后直(zhi)接進入://localhost:8080/swagger-ui/index.html 即可

注意這里與(yu)springfox略有不(bu)同(//localhost:8080/swagger-ui.html)

4.與SpringFox的注解對照

5.SpringDoc基本注解用法

這里轉載一個寫(xie)的(de)(de)非常全面的(de)(de)示例(li)接(jie)口(kou),原文可以去看://blog.csdn.net/zhenghongcs/article/details/123812583

/**
 * 品牌管理Controller
 * Created by macro on 2019/4/19.
 */
@Tag(name = "PmsBrandController", description = "商品品牌管理")
@Controller
@RequestMapping("/brand")
public class PmsBrandController {
    @Autowired
    private PmsBrandService brandService;

    private static final Logger LOGGER = LoggerFactory.getLogger(PmsBrandController.class);

    @Operation(summary = "獲取所有品牌列表",description = "需要登錄后訪問")
    @RequestMapping(value = "listAll", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<List<PmsBrand>> getBrandList() {
        return CommonResult.success(brandService.listAllBrand());
    }

    @Operation(summary = "添加品牌")
    @RequestMapping(value = "/create", method = RequestMethod.POST)
    @ResponseBody
    @PreAuthorize("hasRole('ADMIN')")
    public CommonResult createBrand(@RequestBody PmsBrand pmsBrand) {
        CommonResult commonResult;
        int count = brandService.createBrand(pmsBrand);
        if (count == 1) {
            commonResult = CommonResult.success(pmsBrand);
            LOGGER.debug("createBrand success:{}", pmsBrand);
        } else {
            commonResult = CommonResult.failed("操作失敗");
            LOGGER.debug("createBrand failed:{}", pmsBrand);
        }
        return commonResult;
    }

    @Operation(summary = "更新指定id品牌信息")
    @RequestMapping(value = "/update/{id}", method = RequestMethod.POST)
    @ResponseBody
    @PreAuthorize("hasRole('ADMIN')")
    public CommonResult updateBrand(@PathVariable("id") Long id, @RequestBody PmsBrand pmsBrandDto, BindingResult result) {
        CommonResult commonResult;
        int count = brandService.updateBrand(id, pmsBrandDto);
        if (count == 1) {
            commonResult = CommonResult.success(pmsBrandDto);
            LOGGER.debug("updateBrand success:{}", pmsBrandDto);
        } else {
            commonResult = CommonResult.failed("操作失敗");
            LOGGER.debug("updateBrand failed:{}", pmsBrandDto);
        }
        return commonResult;
    }

    @Operation(summary = "刪除指定id的品牌")
    @RequestMapping(value = "/delete/{id}", method = RequestMethod.GET)
    @ResponseBody
    @PreAuthorize("hasRole('ADMIN')")
    public CommonResult deleteBrand(@PathVariable("id") Long id) {
        int count = brandService.deleteBrand(id);
        if (count == 1) {
            LOGGER.debug("deleteBrand success :id={}", id);
            return CommonResult.success(null);
        } else {
            LOGGER.debug("deleteBrand failed :id={}", id);
            return CommonResult.failed("操作失敗");
        }
    }

    @Operation(summary = "分頁查詢品牌列表")
    @RequestMapping(value = "/list", method = RequestMethod.GET)
    @ResponseBody
    @PreAuthorize("hasRole('ADMIN')")
    public CommonResult<CommonPage<PmsBrand>> listBrand(@RequestParam(value = "pageNum", defaultValue = "1")
                                                        @Parameter(description = "頁碼") Integer pageNum,
                                                        @RequestParam(value = "pageSize", defaultValue = "3")
                                                        @Parameter(description = "每頁數量") Integer pageSize) {
        List<PmsBrand> brandList = brandService.listBrand(pageNum, pageSize);
        return CommonResult.success(CommonPage.restPage(brandList));
    }

    @Operation(summary = "獲取指定id的品牌詳情")
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    @ResponseBody
    @PreAuthorize("hasRole('ADMIN')")
    public CommonResult<PmsBrand> brand(@PathVariable("id") Long id) {
        return CommonResult.success(brandService.getBrand(id));
    }
}

6.與SpringSecurity的結合

如果項目中(zhong)使用了(le)SpringSecurity,需要(yao)做兩(liang)個配(pei)置來讓springdoc正常(chang)使用:

1.在SpringSecurity配置類中放行(xing)白名(ming)單:"/v3/api-docs/**", "/swagger-ui/**"

2.在SpringDoc配(pei)置中增加對(dui)應內容,如(ru)下:

@Configuration
public class SpringDocConfig {

    private static final String SECURITY_SCHEME_NAME = "BearerAuth";

    @Bean
    public OpenAPI managerOpenAPI() {

        return new OpenAPI()
                .info(new Info().title("Galaxy-Cluster-Manager后端接口文檔")
                        .description("提供給前端界面(portal)的接口文檔")
                        .version("v1.0.0")
                        .license(new License().name("galaxy 1.2.0").url("//gitlab.daliqc.cn/hpc/galaxy-parent/-/tree/v1.2.0")))
                .externalDocs(new ExternalDocumentation()
                        .description("彈性高性能計算(CTHPC)")
                        .url("//www.daliqc.cn"))
                //以下是針對SpringSecurity的設置,同時還有設置白名單
                .addSecurityItem(new SecurityRequirement().addList(SECURITY_SCHEME_NAME))
                .components(new Components()
                        .addSecuritySchemes(SECURITY_SCHEME_NAME,
                                new SecurityScheme()
                                        .name(SECURITY_SCHEME_NAME)
                                        .type(SecurityScheme.Type.HTTP)
                                        .scheme("bearer")
                                        .bearerFormat("JWT")));
    }

    @Bean
    public GroupedOpenApi publicApi() {
        return GroupedOpenApi.builder()
                .group("portal")
                .pathsToMatch("/api/**")
                .build();
    }

}

7.SpringDoc使用對象作為Query參數的問題

實際上(shang)springfox也會有這(zhe)個問題,使用對象作為query傳參的時(shi)候,頁面通常是這(zhe)樣的:

就沒有辦(ban)法逐個描述參數,也不能(neng)逐個調(diao)試(shi)(只能(neng)用json調(diao)試(shi)),非常的麻煩(fan);springdoc有一個解決(jue)這(zhe)個問(wen)題非常方便的注解:@ParameterObject

比如(ru)某一個控制器(qi)的入參是User user,我們只需要在這(zhe)前面加上注(zhu)解(jie)變為:@ParameterObject User user 即可,結果如(ru)下;

這里也有一個大坑:參數的類型可能會不正確,比如這里我們的id參數實際上是int,但顯示出來是string,這個時候就需要我們在User類的屬性中加上對應的注解,比如:

@Parameter(description = "id傳參",example = "6")

再重啟UI就會發現參數類型正(zheng)確了(le)

8.SpringDoc配置掃包范圍

有的(de)(de)時(shi)候僅僅使用@Hidden并不能滿足我們的(de)(de)需要,因為可(ke)能需要配(pei)置不同group的(de)(de)controller類(lei)(lei),這個時(shi)候就需要在配(pei)置類(lei)(lei)中取(qu)設(she)置掃包范(fan)圍(wei)代碼如下(xia):

9.SpringDoc的優劣勢

優勢:SpringDoc有著非(fei)常好看的UI,以(yi)及比Springfox更加(jia)完善的參數注解體系,看起來非(fei)常舒服,并且還(huan)在不斷更新與(yu)維(wei)護中(zhong)

劣勢:一些冷門功能還不完善(shan),比如:

a.有十(shi)個(ge)(ge)接口,他們的(de)(de)url是(shi)一(yi)樣的(de)(de)但是(shi)可(ke)(ke)以通過(guo)(guo)query參數來分(fen)別(如:@PostMapping(params = "action=QueryUsers"))這(zhe)個(ge)(ge)時候springdoc只(zhi)能通過(guo)(guo)掃包范(fan)圍配(pei)置,來寫(xie)多個(ge)(ge)GroupOpenApi來解決,非(fei)常的(de)(de)麻煩;springfox可(ke)(ke)以在(zai)docket創(chuang)建的(de)(de)時候使用:docket.enableUrlTemplating(true); 這(zhe)個(ge)(ge)方法即(ji)可(ke)(ke)解決

b.springdoc的網絡配(pei)(pei)置(zhi)(zhi)可(ke)能會與springfox沖突,如果遷(qian)移,需要逐(zhu)個嘗(chang)試網絡配(pei)(pei)置(zhi)(zhi)是否(fou)合(he)適(主要是GsonHttpMessageConverter的配(pei)(pei)置(zhi)(zhi))

c.兼容性問題仍需要觀望,相對于springfox,springdoc的兼容性并沒有那么好,在許多時候(hou)可能會出現序(xu)列化的亂碼問題

 

總結:如果當前項目/工程已經集成了完備的springfox,建議不要輕易嘗試遷移到springdoc,尤其是接口類型比較復雜、springfox配置docket比較多的項目;但如果是從頭開始的項目,由于接口相對比較簡單,可以采用springdoc,畢竟可以獲得更加清晰明了的顯示界面與參數解釋。

 

文章來自個人專欄
文(wen)章 | 訂閱
0條評論
0 / 1000
請輸入你的評論
0
0