【SpringBoot】5 Swagger

news2024/11/28 19:52:36

官网

https://swagger.io/

介绍

Swagger 是一套基于 OpenAPI 规范构建的开源工具,可以帮助开发者实现设计、构建、记录、使用 Rest API。
Swagger 是一款根据 Restful 风格生成的接口开发文档,并且支持做测试的一款中间软件。
Swagger主要包括三部分:

  • Swagger Editor:基于浏览器的编辑器,开发者可以使用它来编写我们的 OpenAPI 文档。
  • Swagger UI:它会将开发者编写的 OpenAPI 规范呈现为交互式的 API 文档。
  • Swagger CodeGen:它可以通过为 OpenAPI 规范定义的任何 API 生成服务器存根和客户端 SDK 来简化构建过程。

用处:

  • 后端
    • 不用再厚些 WiKi 接口拼接大量参数,避免手写出现的错误。
    • 对代码侵入性低,采用注解的方式,开发简单。
    • 方法参数名修改、增加、减少参数都可以直接生效,不用再手动进行维护。
    • 缺点:增加开发成本,写接口需要再写一套参数配置。
  • 前端
    • 后端只需要定义好接口,swagger会自动生成文档,接口功能、参数一目了然。
    • 联调方便,如果出现问题,可以直接测试接口,实时检查参数和返回值,可以快速定位是前端还是后端的问题。
  • 测试
    • 对于某些没有前端界面 UI 功能,可以用它来测试接口。
    • 操作简单,不用了解具体代码就可以进行操作。

依赖

pom.xml

<!-- 引入swagger3包 -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-boot-starter</artifactId>
    <version>3.0.0</version>
</dependency>

配置类

SwaggerConfig.java

package com.lm.system.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;

import java.util.Collections;
import java.util.List;

/**
 * @Author: DuHaoLin
 * @Date: 2024/7/26
 */
@Configuration
public class SwaggerConfig {

//访问地址: http://localhost:8888/swagger-ui/index.html

    private static final String basePackage = "com.lm.system";

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.OAS_30)
                //设置API文档的基本信息
                .apiInfo(apiInfo())
                //进入API选择器的配置
                .select()
                //设置API选择器的基本包路径,表示只选择该包及其子包中的API进行文档生成。
                .apis(RequestHandlerSelectors.basePackage(basePackage))
                //设置API选择器的路径选择器,表示选择所有路径的API进行文档生成。
                .paths(PathSelectors.any())
                .build()
                //小按钮进行方法的调用
                .securitySchemes(Collections.singletonList(securityScheme()))
                .securityContexts(Collections.singletonList(securityContext()));
    }
    
    //这个是swagger页面中的一个小按钮,可以用来放token。
    //定义API的安全方案
    private SecurityScheme securityScheme() {
        //return new ApiKey("Authorization", "Authorization", "header");
        //创建一个ApiKey对象,传入三个参数,分别为密钥的名称、密钥的描述和认证方式。
        //这里的密钥名称和描述都设置为X-Token,认证方式为header,表示在请求的Header中进行认证。
        return new ApiKey("X-Token", "X-Token", "header");
    }
    
    //定义API的安全上下文。
    private SecurityContext securityContext() {
        return SecurityContext.builder()
                .securityReferences(defaultAuth())  //设置安全上下文的安全引用
                .forPaths(PathSelectors.regex("^(?!auth).*$"))  //设置安全上下文的路径选择器.除了以/auth开头的路径外,所有路径都需要进行安全认证
                .build();
    }
    
    //用于定义API的安全引用
    private List<SecurityReference> defaultAuth() {
        //授权范围的名称设置为global,描述设置为accessEverything,表示具有全局访问权限
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        //将前面创建的authorizationScope对象赋值给数组的第一个元素。
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        //认证方案的名称设置为X-Token.授权范围的数组为前面创建的authorizationScopes数组。
        return Collections.singletonList(
                new SecurityReference("X-Token", authorizationScopes));
    }

    //一些swagger的信息配置
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                //接口标题名
                .title("System接口文档")
                //接口描述
                .description("")
                //版本
                .version("1.0")
                //作者信息
                .contact(new Contact("ldh", "https://www.baidu.com", "ldh_dev@163.com"))
                .build();
    }

}

统一返回结果

依赖

pom.xml

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.20</version>
    <optional>true</optional>
</dependency>

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.9</version>
</dependency>

返回结果类

ResultBody.java

package com.lm.system.common;

import com.google.gson.*;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;

import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Collection;
import java.util.Map;

/**
 * @Author: DuHaoLin
 * @Date: 2024/7/26
 */
 
@Data
@Slf4j
@Accessors(chain = true)
@AllArgsConstructor
public class ResultBody<T> implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty("状态码: 404")
    private long status;
    @ApiModelProperty("返回信息")
    private String msg;
    @ApiModelProperty("数据总数")
    private long count;
    @ApiModelProperty("返回数据")
    private T data;

    public static final Gson GSON;

    static {
        final JsonSerializer<LocalDateTime> localDateTimeJsonSerializer = (src, typeOfSrc, context) ->
                new JsonPrimitive(src.withNano(0).atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));

        final JsonSerializer<LocalDate> localDateJsonSerializer = (src, typeOfSrc, context) ->
                new JsonPrimitive(src.format(DateTimeFormatter.ISO_LOCAL_DATE));

        GSON = new GsonBuilder()
                .serializeNulls() //包括空参
                .setPrettyPrinting() //格式化
                .registerTypeAdapter(LocalDateTime.class, localDateTimeJsonSerializer) //类型适配器
                .registerTypeAdapter(LocalDate.class, localDateJsonSerializer) //类型适配器
                .setDateFormat("yyyy-MM-dd HH:mm:ss") //日期格式
                .disableHtmlEscaping() //禁用Http转义
                .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) //小写下划线
                .create();
    }

    @Override
    public String toString() {
        return getReturn();
    }

    private ResultBody() {}

    public static <T> ResultBody<T> build() {
        return createResponse(0, null);
    }

    public static <T, V extends Collection<T>> ResultBody<V> build(V collection) {
        return createResponse(collection.size(), collection);
    }

    public static <T, R> ResultBody<Map<T, R>> build(Map<T, R> map) {
        return createResponse(map.size(), map);
    }

    public static <T> ResultBody<T> build(T map) {
        if (map == null) return build();
        return createResponse(1, map);
    }

    public static <T> ResultBody<T> build(HttpStatus status) {
        return new ResultBody<T>().setStatus(status.value());
    }

    private static <T> ResultBody<T> createResponse(long size, T data) {
        ResultBody<T> resultBody;
        if (size == 0) {
            resultBody = build(HttpStatus.NO_CONTENT);
        } else {
            resultBody = build(HttpStatus.OK);
            resultBody.count = size;
        }
        resultBody.data = data;
        return resultBody;
    }

    public String getReturn() {
        String json = GSON.toJson(this);
        log.info(json);
        return json;
    }

}

接口

将 Usercontroller 改为 UserPageController 。
新建 UserController 类。

UserPageController.java

package com.lm.system.controller;

import com.lm.system.common.User;
import io.swagger.annotations.Api;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * @Author: DuHaoLin
 * @Date: 2024/7/26
 */
@Controller
@Api(tags = "用户页面")
public class UserPageController {

    @GetMapping("userPage")
    public String user(Model model) {
        User user = User.builder()
                .name("Tom")
                .age(18)
                .gender(0)
                .build();
        model.addAttribute("user", user);
        return "user";
    }

}

User.java

package com.lm.system.common;

import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

/**
 * @Author: DuHaoLin
 * @Date: 2024/7/26
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ApiModel("用户实体类")
public class User {

    private Integer id;
    private String name;
    private Integer age;
    private Integer gender; //性别:0男,1女
    private LocalDateTime createTime;
    private LocalDateTime updateTime;

    private Integer deleted; //是否已经删除:0否,1是
    
}

UserController.java

package com.lm.system.controller;

import com.lm.system.common.ResultBody;
import com.lm.system.common.User;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.HttpStatus;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.util.Objects;

/**
 * @Author: DuHaoLin
 * @Date: 2024/7/26
 */
@RestController
@Api(tags = "用户接口")
public class UserController {

    @GetMapping("user")
    @ApiOperation("获取用户信息")
    public String user() {
        User user = User.builder()
                        .name("Tom")
                        .age(18)
                        .gender(0)
                        .build();
        return ResultBody
                .build(HttpStatus.OK)
                .setData(user)
                .setCount(1)
                .getReturn();
    }

}

user.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Thymeleaf</title>
</head>
<body>
    <span>姓名:</span>
    <span th:text="${user.name}"></span>
    <br />
    <span>年龄:</span>
    <span th:text="${user.age}"></span>
    <br />
    <span>性别:</span>
    <span th:text="${user.gender} == 0 ? '男' : '女'"></span>
</body>
</html>

效果图

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

项目目录结构

在这里插入图片描述

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

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

相关文章

jfif怎么改成jpg?分享给大家三个小技巧!

在数字时代&#xff0c;图片是我们日常生活和工作中不可或缺的一部分。然而&#xff0c;在处理图片时&#xff0c;我们可能会遇到各种格式的问题&#xff0c;比如JFIF格式的图片在某些平台上无法直接打开或编辑。别担心&#xff0c;今天我就给大家分享三个简单实用的小技巧&…

spring自动装配读取引用jar包下的META-INF文件里的类,将其加载进spring启动容器.

总结: 0.ComponentScan默认只扫描同包、子包下的所有类, 因此扫描不到引的其他jar包依赖里的类 1.引的其他jar包依赖里的类想要被spring加载进容器, 在spring2.7之前,要把类的全类名写在自己项目包下的resources/META-INF/spring.factories下的文件中, 从spring boot2.7开…

【Linux】软连接|硬链接|当前路径(.)|上级路径(..)|硬链接不能链接目录

目录 前言 软连接 ​编辑 删除源文件 快捷应用 总结 硬链接 硬链接为何不能链接目录 为什么软连接可以 软硬链接区别 当前路径(.)和上级路径(..) ​编辑 前言 在 Linux 中&#xff0c;文件的存储位置和数据&#xff08;属性内容&#xff09;是由 inode 号来唯一标…

spring源码 bean的生命周期

问&#xff1a;谈谈对spring的理解 答&#xff1a;总分思想&#xff0c;先说对spring的总体认知&#xff0c;再说小一点的比如&#xff1a;IOC,AOP,IOC如何实现&#xff0c;生命周期&#xff0c;循环依赖等 IOC&#xff1a;控制反转 xml和注解创建对象的流程 xm文件通过IO流读…

RVC-AI声音克隆-你的声音不再是唯一

RVC是一个基于Hubert模型的AI语音转换工具&#xff0c;可以实现男女声的互换和降噪。 本文将要介绍RVC的安装和使用方法 首先感谢花儿不哭大佬带来的RVC声音克隆 花儿不哭&#xff1a; 花儿不哭的个人空间-花儿不哭个人主页-哔哩哔哩视频 (bilibili.com) RVC下载地址&#xff…

Elastic 线下 Meetup 将于 2024 年 8 月 25 号在南京举办

2024 Elastic Meetup 南京站活动&#xff0c;由 Elastic、华博集团、新智锦绣联合举办&#xff0c;现诚邀广大技术爱好者及开发者参加。 时间地点 2024 年 8 月 25 日 13:30-18:00 活动地点 南京雨花台区花神大道 17 号 华博智慧园 7 楼 智慧岛会议厅 报名地址 2024 Elasti…

稳态准直太阳光模拟器仪器光伏电池组件IV测试

太阳能模拟器电池IV测试仪、单体测试仪&#xff0c;配备匹配标准的AAA Class稳态太阳能模拟器及相关测试附件&#xff0c;可对太阳能电池片的IV性能进行测量、分级分选等&#xff1b; 介绍 AAA class太阳光模拟器整合完整的IV测量系统&#xff0c;针对各种太阳能电池的性能&a…

Redis学习[3] ——持久化

四. Redis 持久化 4.1 Redis 如何保证数据不丢失&#xff1f; 由于Redis的数据是保存在内存中&#xff0c;而内存中的数据会在Redis重启后丢失。因此&#xff0c;为了保证数据不丢失&#xff0c;Redis实现了数据持久化的机制。这个机制会将内存中的数据存储到磁盘&#xff0c…

【JVM】内存区域、垃圾回收和内存分配策略

文章目录 运行时数据区域程序计数器Java虚拟机栈栈帧Java堆方法区运行时常量池 直接内存 揭秘对象对象的内存布局对象头实例数据对齐填充 对象的访问定位 OutOfMemoryError异常Java堆溢出虚拟机栈和本地方法栈溢出方法区和运行时常量池溢出本机直接内存溢出 对象已死&#xff1…

剪画小程序:什么?刷到陈楚生的视频转换成音频这么简单!

在这个信息爆炸的时代&#xff0c;我们常常在各种平台上刷到自己喜欢的视频&#xff0c;尤其是那些有陈楚生精彩表现的视频。 而有时候&#xff0c;我们可能只想单纯地聆听他的歌声&#xff0c;不想被视频画面所干扰。 你是否曾想过&#xff0c;把刷到的陈楚生的视频转换成音频…

爬虫实战:数据请求与解析(4种不同方式的数据解析)

根据目标网页的结构和内容的复杂性&#xff0c;我们可以选择多种不同的库或工具来提取所需的数据。本文将通过实战案例&#xff0c;介绍如何使用正则表达式、BeautifulSoup、pyquery、XPath 这四种方法从网页中解析数据。 一、准备工作 1.1 确定目标 我们测试的数据是崔庆才…

项目:基于gRPC进行项目的微服务架构改造

文章目录 写在前面基本使用封装客户端封装服务端Zookeeper 写在前面 最近学了一下gRPC进行远程调用的原理&#xff0c;所以把这个项目改造成了微服务分布式的架构&#xff0c;今天也是基本实现好了&#xff0c;代码已提交 这里补充一下文档吧&#xff0c;也算记录一下整个过程…

029-GeoGebra中级篇—一般对象之复数

GeoGebra 支持复数运算和可视化&#xff0c;允许用户在复平面上进行各种操作。用户可以定义复数、进行加减乘除等基本运算&#xff0c;并使用 GeoGebra 的图形工具在复平面上绘制复数的表示&#xff0c;探索复数的几何意义。这使得 GeoGebra 成为学习和研究复数及其应用的有力工…

合并K个有序链表

题目 给你一个链表数组&#xff0c;每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表中&#xff0c;返回合并后的链表。 示例1&#xff1a; 输入&#xff1a; 输出&#xff1a; 示例2&#xff1a; 输入&#xff1a; 输出&#xff1a; 示例3&#xff1a; 输入&…

【Vue3】组件生命周期

【Vue3】组件生命周期 背景简介开发环境开发步骤及源码 背景 随着年龄的增长&#xff0c;很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来&#xff0c;技术出身的人总是很难放下一些执念&#xff0c;遂将这些知识整理成文&#xff0c;以纪念曾经努力学习奋斗的日子。本…

Java从入门初级开发到精通百万级架构师:全套教程 | 学习路线(免费白嫖)

以下是一篇关于Java编程从入门到精通的文章&#xff0c;旨在帮助初学者和有一定基础的程序员系统地学习Java语言及其应用&#xff1a; Java语言编程从入门到精通&#xff1a;Java从入门到项目实战全套教程 Java作为一种广泛使用的编程语言&#xff0c;拥有强大的生态系统和丰富…

「 LaTeX 」如何修改公式底纹颜色

一、前言 小白在论文返修过程中&#xff0c;需要标注出部分公式的修正&#xff0c;因此用到这个代码指令。 二、技术实现 指令代码如下&#xff1a; \mathcolorbox{yellow}{ TEXT } 三、实例 \begin{figure*} \begin{equation} \centering \begin{aligned}\begin{bmatrix}{…

食家巷胡麻饼酥脆滋味,难以抗拒

在美食的浩瀚星空中&#xff0c;食家巷胡麻饼宛如一颗璀璨的明珠&#xff0c;散发着独特而迷人的魅力。食家巷胡麻饼&#xff0c;那金黄酥脆的外皮&#xff0c;宛如一层精心雕琢的铠甲&#xff0c;闪烁着诱人的光泽。上面点缀着密密麻麻的胡麻籽&#xff0c;犹如繁星点点&#…

终端pip安装包后,Pycharm却导入失败?新手别慌,3招搞定!

很多小伙伴在学习Python的过程中,都会遇到这种情况:明明在终端用pip安装好了需要的包,但在Pycharm中导入时却报错。难道是安装姿势不对? 例如在cmd中已经有了pandas,但是去pycharm中导入pandas显示没有 先别急着怀疑人生,这很可能是因为pip安装包的路径和Pycharm项目使用…

Docker容器下面home assistant忘记账号密码怎么重置?

环境&#xff1a; docker ha 问题描述&#xff1a; Docker容器下面home assistant忘记账号密码怎么重置&#xff1f; 解决方案&#xff1a; 你可以按照以下步骤来找回或重置密码&#xff1a; 方法一 (未解决) 停止并删除当前的Home Assistant容器&#xff08;确保你已经保…