整站下载器 做网站地图,网页建站网站申请,wordpress必须安装php,门户型网站怎么建设目录 一、Swagger 简介1. 什么是 Swagger#xff1f;2. 如何使用 Swagger3. Springboot 中swagger的使用示例1. maven 引入安装2. java配置 二、Swagger UI存在的缺点1.不够方便直观2.请求的参数没有缓存3.不够美观4.如果是JWT 无状态登录#xff0c;Swagger使用起来就没有那… 目录 一、Swagger 简介1. 什么是 Swagger2. 如何使用 Swagger3. Springboot 中swagger的使用示例1. maven 引入安装2. java配置 二、Swagger UI存在的缺点1.不够方便直观2.请求的参数没有缓存3.不够美观4.如果是JWT 无状态登录Swagger使用起来就没有那么丝滑了 三、封装以及讨论封装组件代码封装解决无状态登录问题1. 我们往swagger-bootstrap-ui的右上角加一个按钮点击出现弹框来配置自动获取登录token2.javascript 脚本部分实现 总结 一、Swagger 简介
Swagger 是一款用于 API 设计、构建、文档化和测试的开源工具。它提供了一整套的解决方案帮助开发者更好地构建和管理 RESTful APIs。以下是对 Swagger 的简要介绍
1. 什么是 Swagger
Swagger 是一个规范和完整的框架用于生成、描述、调用和可视化 RESTful Web 服务。它基于 OpenAPI 规范以前称为 Swagger 规范该规范定义了 API 的结构。
2. 如何使用 Swagger
定义 API使用 Swagger Editor 编写 OpenAPI 规范文件描述 API 的端点、请求参数、响应格式等。生成文档通过 Swagger UI 或 Swagger Codegen生成可视化的 API 文档。集成到项目在项目中集成 Swagger 的相关工具比如在 Spring Boot 项目中使用 springfox-swagger2 和 springfox-swagger-ui 依赖自动生成和托管 API 文档。
3. Springboot 中swagger的使用示例
以下是一个使用 Swagger 注解的简单示例展示了如何在 Spring Boot 应用中集成 Swagger
1. maven 引入安装
dependencygroupIdio.springfox/groupIdartifactIdspringfox-swagger2/artifactIdversion2.9.2/version
/dependency
dependencygroupIdio.springfox/groupIdartifactIdspringfox-swagger-ui/artifactIdversion2.9.2/version
/dependency2. java配置
EnableSwagger2
Configuration
public class SwaggerConfig {Beanpublic Docket createRestApi() {return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.basePackage(com.efficientnotes.boot.web)).paths(PathSelectors.any()).build();}private ApiInfo apiInfo() {return new ApiInfoBuilder().title(Efficient notes api platform).description(apis).termsOfServiceUrl(http://localhost:9000/).contact(yh4494sina.com).version(1.0).build();}}title title就是swagger页面上展示的title比如交ERP api平台 description 详情介绍 termsOfServiceUrl 机构首页地址 contact 联系方式 version 版本号
Spring security 排除拦截:
Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers(/swagger-ui.html).permitAll().antMatchers(/webjars/**).permitAll().antMatchers(/swagger-resources/**).permitAll().antMatchers(/v2/*).permitAll().antMatchers(/csrf).permitAll().antMatchers(/).permitAll().anyRequest().authenticated().and().formLogin();}
}控制器示例
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;RestController
Api(value 示例API, description 这是一个示例API)
public class ExampleController {GetMapping(/hello)ApiOperation(value 问候接口, notes 通过传递名字来获得问候语)public String hello(ApiParam(value 用户的名字, required true) RequestParam String name) {return Hello, name !;}
}在完成上述步骤后启动 Spring Boot 应用并访问 http://localhost:8080/swagger-ui.html即可查看自动生成的 API 文档。 Swagger 是一个强大且灵活的工具集为开发者提供了方便、高效的 API 管理解决方案。通过标准化和自动化它极大地简化了 API 开发和维护的过程。 图 ①
二、Swagger UI存在的缺点
1.不够方便直观
swagger ui 布局是上下瀑布式的比如我访问完A接口想访问B接口访问完B接口想继续访问A接口就必须往上翻接口少还好操作。接口多的话来回就很烦。
2.请求的参数没有缓存
比如我想掉一个post接口来伪造一条数据第一次访问完成之后刷新页面后第二次还要重新造数据就很麻烦命名我只需要改部分字段重新请求就行结果每次都要重新填写报文。字段躲起来兼职就是折磨。
3.不够美观
不用多说当然一个工具类产品美观并不重要但是美观的产品还是能给人带来心情愉悦的体验就像你旁边坐着一位漂亮女孩你整天心情都会好很多。不管如何对我来说工具颜值还是挺重要的。
4.如果是JWT 无状态登录Swagger使用起来就没有那么丝滑了
因为JWT无状态登录这种需要每次在请求的Header中带上TOKENSwagger可没那么只能给你登录接口返回的token带过去这样就导致无状态session的情况下Swagger的调试功能等于瘫痪状态。
三、封装以及讨论 我们来讨论下如何解决上述一些缺陷给Swagger换一层皮并且将Swagger封装成组件 很久以前我就关注过一些swaggerui的项目了比较优秀的是swagger-bootstrap-ui。现在好像升级过不叫这个名字了但我保存了一份之前的swagger-bootstrap-ui的代码。github的地址是https://github.com/xiaoymin/swagger-bootstrap-ui直接可以下载的地址: swagger-bootstrap-ui。
这份UI解决了上述中前三个问题不够方便直观、请求的参数没有缓存、不够美观虽然不是太好看但也还好吧如果对外观还是不够满意的话可以自己修改下样式盖起来也很方便我会在下面的文章中进行讨论和介绍。那么我们先看下具体的ui长什么样子。 图②
看起来是不是比图 ①要舒服多了。那么我们在下面异步异步的讨论如何将这个ui封装成一个组件可以直接引用以及如何解决缺陷的第四点JWT无状态登录如何自动拼装token。
封装组件
现在我们有了前端代码可以参考swagger原生的ui就是做成的一个jar包引入的这个jar包就拥有了swagger-ui。我们也参考下这种方式前后端代码结合自动配置项目引入我们的依赖就能直接拥有提供接口文档的能力。
代码封装
我们想让我们的组件提供完整的swagger能力那么首先我们自己的封装的swagger组件中要引入所有的swagger的依赖。
dependenciesdependencygroupIdio.springfox/groupIdartifactIdspringfox-swagger2/artifactIdversion2.9.2/versionexclusionsexclusionartifactIdspring-context/artifactIdgroupIdorg.springframework/groupId/exclusionexclusionartifactIdspring-aop/artifactIdgroupIdorg.springframework/groupId/exclusionexclusionartifactIdjackson-annotations/artifactIdgroupIdcom.fasterxml.jackson.core/groupId/exclusionexclusionartifactIdslf4j-api/artifactIdgroupIdorg.slf4j/groupId/exclusionexclusionartifactIdspring-beans/artifactIdgroupIdorg.springframework/groupId/exclusion/exclusions/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactId/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-webmvc/artifactId/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactId/dependency
/dependenciesswagger2是通过EnableSwagger2来启用swagger我们也可以写一个注解来做这件事情引用我们自己定义的注解就可以自动配置启用我们的swagger组件。
EnableAllensSwagger
Documented
Retention(RetentionPolicy.RUNTIME)
Target(ElementType.TYPE)
Import(SwaggerConfig.class)
public interface EnableAllensSwagger {
}然后我们需要将所有的配置都配置好提供我们自己自定义的配置出去然需要引入的应用项目配置我们提供的配置来自定义Swagger。
SwaggerProperties
/*** SwaggerProperties** author allens* since 2024/5/21*/
Component
ConfigurationProperties(prefix allens.swagger)
Setter
Getter
public class SwaggerProperties {private String packages;private String title;private String description;private String termsOfServiceUrl;private String version;private String contact;
}SwaggerConfig 通过这个类来做组件的autoconfig当Springboot中启用EnableAllensSwagger注解的时候Import(SwaggerConfig.class)就会自动加载注入 SwaggerConfig,SwaggerConfig回去扫描com.allens.swagger下的所有bean来自动加载组件。
EnableSwagger2
Configuration
ComponentScan(com.allens.swagger)
EnableConfigurationProperties(SwaggerProperties.class)
public class SwaggerConfig {ResourceSwaggerProperties swaggerProperties;Beanpublic Docket createRestApi() {return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.basePackage(swaggerProperties.getPackages())).paths(PathSelectors.any()).build();}private ApiInfo apiInfo() {return new ApiInfoBuilder().title(swaggerProperties.getTitle()).description(swaggerProperties.getDescription()).termsOfServiceUrl(swaggerProperties.getTermsOfServiceUrl()).contact(swaggerProperties.getContact()).version(swaggerProperties.getVersion()).build();}}接着我们需要把前端的代码copy到项目中同时项目打包的时候可以把swagger-bootstrap-ui打包到jar包中同时我们需要访问/${servletContextPath}/doc.html的时候可以正常访问到前端界面。
① 拷贝swagger-boot-ui 到项目中
② 配置路由映射规则,如果是SpringSecurity也是要忽略doc.html//webjars/**这两个地址。
Configuration
public class SwaggerWebMvcConfig implements WebMvcConfigurer {Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler(doc.html).addResourceLocations(classpath:/resources/);registry.addResourceHandler(/webjars/**).addResourceLocations(classpath:/resources/webjars/);}
}Override
protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().and().csrf().disable().exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests().antMatchers( /doc.html,/webjars/**,/v2/api-docs/**,/swagger-resources/**).anonymous().anyRequest().authenticated();http.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);// 添加CORS filterhttp.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);http.addFilterBefore(corsFilter, LogoutFilter.class);
}然后我们就可以直接到项目中引入我们的组件并且配置了
dependencygroupIdcom.efficientnotes/groupIdartifactIdallens-swagger/artifactIdversion1.0-SNAPSHOT/version
/dependencyyml文件配置:
allens:swagger:packages: com.efficientnotes.boot.webtitle: Efficient notes api platformdescription: apistermsOfServiceUrl: http://localhost:9000/version: 1.0contact: allenssina.com启动服务并访问: http://localhost:9000/${servletContextPath}/doc.html
解决无状态登录问题
如果说你的项目是Session模式的方案那么到这里就结束了。但假如说你是无状态登录的方案那么就要继续往下看了。无状态登录我们需要把token塞进header中进行请求那么我们就需要拦截截取登录接口的报文中的token。而且每次请求的时候都要把header中的token拼接上去。 注意只有无状态JWT模式才需要这样做!!! 1. 我们往swagger-bootstrap-ui的右上角加一个按钮点击出现弹框来配置自动获取登录token 点击之后是一个弹窗这个弹窗会要求输入登录接口路径、登录token提取路径以及Token名称。如果走自动获取HeaderJSON是不需要填的。如果想手动塞Header那么可以使用JSON格式塞TOKEN塞进行去这种方式不需要配置登录接口路径和登录token提取路径以及token名称。
登录接口路径 你系统的登录接口路径登录接口提取路径 json path比如登录接口返回的是{“data”: {token: “xxx”, “other”: “ok”},“msg”: “”}那么登录接口提取路径为data.tokenTOKEN名称 接口请求需要携带的Header Token名称Header JSON 有两种情况如果不填上述三个配置header JSON就可以手动设置设置完成之后每次请求都会自动携带你配置的Header上去。如果配置了上述三个配置那么每次自动获取完登录的TOKEN之后会自动带出来。 来看看代码怎么实现的 doc.html
div classsbu-header-right stylemargin-top:12pxdiv classcol-sm-6button stylebackground: #0d5aa7 onclickshowPromoteDefaultHeader() typebutton classbtn btn-info通用头设置/button/div
/div2.javascript 脚本部分实现
function showPromoteDefaultHeader() {var test layer.open({type: 1, // page 层类型area: [700px, 500px],title: 配置头信息,shade: 0.6, // 遮罩透明度shadeClose: true, // 点击遮罩区域关闭弹层maxmin: true, // 允许全屏最小化anim: 0, // 0-6 的动画形式-1 不开启content:div classallens-dialogdiv classelementspan登录接口路径/spaninput idallens-dialog-login-interface-name nameloginInterfaceName //divdiv classelementspan登录token提取路径/spaninput idallens-dialog-json-path namejsonPath //divdiv classelementspanTOKEN名称/spaninput idallens-dialog-token-name nametokenName //divdiv classelementspanHeader JSON/spantextarea idallens-dialog-header-json stylewidth: 100%; cols10 rows8 name id/textarea/divbutton classbtn btn-primary btn-lg idallens-dialog-submit提交/button/div});function notEmpty (variable) {if (variable null || variable undefined || variable ) {// 变量为空return false;}return true;}var button document.querySelector(#layui-layer test #allens-dialog-submit);var loginInterFaceName document.querySelector(#layui-layer test #allens-dialog-login-interface-name);var jsonPath document.querySelector(#layui-layer test #allens-dialog-json-path);var headerJson document.querySelector(#layui-layer test #allens-dialog-header-json);var tokenName document.querySelector(#layui-layer test #allens-dialog-token-name);button.onclick () {if (notEmpty(loginInterFaceName)) {localStorage.setItem(LOGININTERFACENAME, loginInterFaceName.value)}if (notEmpty(jsonPath)) {localStorage.setItem(JSONPATH, jsonPath.value)}if (notEmpty(headerJson)) {localStorage.setItem(HEADERJSON, headerJson.value)}if (notEmpty(tokenName)) {localStorage.setItem(TOKENNAME, tokenName.value)}layer.close(test);}// text.setAttribute(placeholder, 格式为JSON:{headerName: headerValue})var data localStorage.getItem(HEADERJSON);if (data) {const jsonObject JSON.parse(data);const jsonString JSON.stringify(jsonObject, null, 2);headerJson.value jsonString;}loginInterFaceName.value localStorage.getItem(LOGININTERFACENAME)jsonPath.value localStorage.getItem(JSONPATH)tokenName.value localStorage.getItem(TOKENNAME)
}可以下载下源码看下具体的实现暂时只支持CSDN下载后续我会传到github。https://download.csdn.net/download/yh4494/89335880
总结
至此我们讨论的四个swagger的缺点就全部解决了当然你也可以自己去修改样式源码都有的怎么该都可以只要不要有大的bug就行。甚至可以上传到中央仓库给大家使用。