阿里 做网站北京市住房建设网站

news/2025/10/7 1:33:11/文章来源:
阿里 做网站,北京市住房建设网站,农家乐网站源码,苏州网上注册公司网址SpringBoot教程(十六) | SpringBoot集成swagger#xff08;全网最全#xff09; 一. 接口文档概述 swagger是当下比较流行的实时接口文文档生成工具。接口文档是当前前后端分离项目中必不可少的工具#xff0c;在前后端开发之前#xff0c;后端要先出接口文档#xff0c…SpringBoot教程(十六) | SpringBoot集成swagger全网最全 一. 接口文档概述 swagger是当下比较流行的实时接口文文档生成工具。接口文档是当前前后端分离项目中必不可少的工具在前后端开发之前后端要先出接口文档前端根据接口文档来进行项目的开发双方开发结束后在进行联调测试。 所以接口文档其实就是开发之前双方之间的一种约定。通常接口文档分为离线的和实时的。离线的接口文档工具有 word(相当于没说) YAPI, 小幺鸡等这种文档需要程序员在上面编写也一般具备接口测试功能。通常是由开发人员先在离线接口文档上编写信息然后交给前端人员参照开发。最大的弊端是当我们的接口程序发生变动时需要回过头来维护上面的内容很麻烦是真的麻烦。 实时接口文档就是可以根据我们的代码来自动生成相应的接口文档优点就是我们的代码发生变化时生成的接口文档也会自动更新无需我们关注修改主需要按时发布即可。但是由于是根据代码自动生成的所以最大的弊端就是代码侵入性强需要我们在项目代码中集成生成接口文档的相关代码。实时接口文档现在的方案有很多但是swagger还是其中比较有影响力的一个。 二. SpringBoot集成swagger2 官网地址 swagger.io 当然官网都是英文的看起来还是比较麻烦的。建议大家直接按照我的步骤来还是很简单的。 同时在说一点 swagger分为swagger2 和swagger3两个常用版本。二者区别不是很大主要对于依赖和注解进行了优化。swagger2需要引入2个jar包swagger3只需要一个用起来没有什么大的区别。下面以swagger2为例。 2.1 引入依赖 xml复制代码dependencygroupIdio.springfox/groupIdartifactIdspringfox-swagger2/artifactIdversion2.9.2/version /dependency dependencygroupIdio.springfox/groupIdartifactIdspringfox-swagger-ui/artifactIdversion2.9.2/version /dependency2.2 引入配置 首先需要添加一个注解 EnableSwagger2。 这个注解我们可以添加到SpringBoot的启动类上也可以自定义一个配置类放到上面。添加了这个注解以后就代表我们已经在项目中开启了Swagger的功能。 我们采用第二种方式自己定义一个配置类正好还可以添加一个Docket配置。 所谓Docket配置就是一组(一个项目或一个版本)接口文档的配置比如设置名称 联系人等等。 我们在config文件夹下添加一个SwaggerConfig类。 java复制代码Configuration EnableSwagger2 public class SwaggerConfig {/*** 设置多个** Bean* public Docket appApi() {** ListParameter pars new ArrayList();* ParameterBuilder token new ParameterBuilder();* token.name(token).description(用户令牌).modelRef(new ModelRef(string)).parameterType(header).required(false)* .build();* pars.add(token.build());** return new Docket(DocumentationType.SWAGGER_2).select().paths(regex(/app/.*)).build()* .globalOperationParameters(pars).apiInfo(pdaApiInfo()).useDefaultResponseMessages(false)* .enable(enableSwagger)* .groupName(appApi);** }** Bean* public Docket adminApi() {** ListParameter pars new ArrayList();* ParameterBuilder token new ParameterBuilder();* token.name(token).description(用户令牌).modelRef(new ModelRef(string)).parameterType(header).required(false)* .build();* pars.add(token.build());* return new Docket(DocumentationType.SWAGGER_2).select().paths(regex(/admin/.*)).build()* .globalOperationParameters(pars).apiInfo(pdaApiInfo()).useDefaultResponseMessages(false)* .enable(enableSwagger)* .groupName(adminApi);** }*** return*/Beanpublic Docket createRestApi() {return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.basePackage(com.lsqingfeng.action.swagger.controller)).paths(PathSelectors.any()).build().globalOperationParameters(setHeaderToken());}private ApiInfo apiInfo() {return new ApiInfoBuilder().title(action-swagger).description(swagger实战).termsOfServiceUrl().version(1.0).build();}/*** Description: 设置swagger文档中全局参数* param* Date: 2020/9/11 10:15* return: java.util.Listspringfox.documentation.service.Parameter*/private ListParameter setHeaderToken() {ListParameter pars new ArrayList();ParameterBuilder userId new ParameterBuilder();userId.name(token).description(用户TOKEN).modelRef(new ModelRef(string)).parameterType(header).required(true).build();pars.add(userId.build());return pars;} }上面就是一个配置案例 还设置了一个setToken方法代表生成文档的所有接口中都要包含一个header类型的token参数。 2.3 给Controller 添加注解 我们接口文档的直接描述主要就是在Controller这一层比如这个接口的功能参数的名称返回值的名称等。这些值我们都需要在Controller上通过给方法上请求参数和返回参数上添加对应的注解swagger才能帮我们生成相应的接口文档。这也就是我前面提到的对现有代码的侵入性。 我们来写一个案例。 首先先创建一个vo的包里边写我们的请求和相应参数使用JavaBean定义出请求和响应的数据结构。注意这里要添加相应的注解 请求类 java复制代码package com.lsqingfeng.springboot.vo;import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data;/*** className: SwaggerReqVO* description:* author: sh.Liu* date: 2022-03-22 19:19*/ Data ApiModel(创建Swagger请求参数) public class SwaggerReqVO {ApiModelProperty(id)private Integer id;ApiModelProperty(姓名)private String name;ApiModelProperty(性别)private Integer gender; }响应类 java复制代码package com.lsqingfeng.springboot.vo;import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data;/*** className: SwaggerResVO* description:* author: sh.Liu* date: 2022-03-22 19:20*/ Data ApiModel(创建Swagger响应结果) public class SwaggerResVO {ApiModelProperty(id)private Integer id;ApiModelProperty(姓名)private String name;ApiModelProperty(性别)private Integer gender;ApiModelProperty(啥啥)private String what; }这里分别使用了 ApiModel注解和 ApiModelProperty 注解定义了实体的名称和字段的名称方便生成接口文档时展示。 再来看Controller: java复制代码package com.lsqingfeng.springboot.controller;import com.lsqingfeng.springboot.vo.SwaggerReqVO; import com.lsqingfeng.springboot.vo.SwaggerResVO; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.*;/*** className: SwaggerController* description: swagger 接口测试* author: sh.Liu* date: 2022-03-22 19:18*/ RestController RequestMapping(/swagger) Api(value 用户接口, tags {用户接口}) public class SwaggerController {ApiOperation(新增用户)PostMapping(save)public String save(RequestBody SwaggerReqVO req) {return success;}GetMapping(getById)ApiOperation(根据条件查询用户)public SwaggerResVO getById(RequestBody SwaggerResVO req) {return new SwaggerResVO();} }这里使用了Api注解和 ApiOperation注解分别标注了接口组名和接口的名称。现在我们启动项目。 发现报了这个错误。 上网查询原因说是SpringBoot2.6版本和Swagger2.9.2不兼容导致的。 也有人说是由于guava这个包的版本过低导致的。 我都分别试了一下替换了guava的高版本依赖问题还是存在。 这个问题的主要原因确实是SpringBoot版本过高导致。如果你用的是SpringBoot2.5.x及之前版本是没有问题的。 Spring Boot 2.6.X使用PathPatternMatcher匹配路径Swagger引用的Springfox使用的路径匹配是基于AntPathMatcher的。 所以要想解决添加配置将springBoot MVC的路劲匹配模式修改一下即可。 在springBoot配置文件中添加配置 properties 复制代码spring.mvc.pathmatch.matching-strategyANT_PATH_MATCHER如果是yml格式的配置文件 再次启动问题解决。 访问地址 ip:端口号/swagger-ui.html 正常情况就可以看到我们的界面了。一会再说非正常情况。由于我们只给用户接口添加了注解所有用户接口是可以直接观察中文文档的。而剩下的两个接口由于没添加注解所以都是以默认的形式展示的。 点开接口我们可以看到接口中的想详细信息 点击model,可以看到字段的中文描述。点击 Try it out,就可以直接调试接口。同时注意接口中都让填一个token,这就是我们之前的设置成效了。 截止到目前其实swagger的集成就已经完毕了主要就是根据我们的注解生成文档并且可以在线调用调试。开发的时候我们只需要把Controller这一层的请求和响应以及方法描述等内容先开发完毕就可以提供给前端让他们参照开发了。 2.4 [404]问题解决 正常情况我们按照上面的步骤就可以出现页面但是有些时候可能是由于springBoot的版本过高导致的我们输入之前的地址出现404的情况这个主要是由于项目中无法读取到swagger依赖包下的页面导致的。如果出现了这个问题我们可以添加一个配置类让他实现WebMvcConfigurer 接口在添加一个方法 java复制代码Override public void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler(/**).addResourceLocations(classpath:/static/);registry.addResourceHandler(swagger-ui.html).addResourceLocations(classpath:/META-INF/resources/);registry.addResourceHandler(/webjars/**).addResourceLocations(classpath:/META-INF/resources/webjars/); }完整代码如下 java复制代码package com.lsqingfeng.springboot.config;import com.lsqingfeng.springboot.interceptor.TokenInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/*** className: WebMvcConfig* description:webMvc配置* author: sh.Liu* date: 2022-01-13 09:51*/ Configuration public class WebMvcConfig implements WebMvcConfigurer {Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler(/**).addResourceLocations(classpath:/static/);registry.addResourceHandler(swagger-ui.html).addResourceLocations(classpath:/META-INF/resources/);registry.addResourceHandler(/webjars/**).addResourceLocations(classpath:/META-INF/resources/webjars/);} }这个时候在启动就可以了 2.5 替换UI 上面的整个过程已经完成了但是生成的接口文档的页面其实很多人不太喜欢觉得不太符合国人的使用习惯所有又有一些大神提供了其他的UI测试页面。这个页面的使用还是比较广泛的。 修改方式只需引入一个依赖包 xml复制代码dependencygroupIdcom.github.xiaoymin/groupIdartifactIdswagger-bootstrap-ui/artifactIdversion1.9.6/version /dependency然后把刚才实现的那个的那个方法再添加一条 java复制代码registry.addResourceHandler(doc.html).addResourceLocations(classpath:/META-INF/resources/);完成代码 java复制代码package com.lsqingfeng.springboot.config;import com.lsqingfeng.springboot.interceptor.TokenInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/*** className: WebMvcConfig* description:webMvc配置* author: sh.Liu* date: 2022-01-13 09:51*/ Configuration public class WebMvcConfig implements WebMvcConfigurer {// Override // public void addInterceptors(InterceptorRegistry registry) { // //拦截 // registry.addInterceptor(new TokenInterceptor()) // .addPathPatterns(/**) // .excludePathPatterns(/login); // }Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler(/**).addResourceLocations(classpath:/static/);registry.addResourceHandler(swagger-ui.html).addResourceLocations(classpath:/META-INF/resources/);registry.addResourceHandler(/webjars/**).addResourceLocations(classpath:/META-INF/resources/webjars/);registry.addResourceHandler(doc.html).addResourceLocations(classpath:/META-INF/resources/);} }重新启动项目 访问路径发生了变化** ip:端口号/doc.html** 页面出现了。我们在看看我们的用户接口 这个风格确实更加的直观同时也是可以直接进行调试的。大部分的swagger都用的这个风格的文档。 三. SpringBoot集成swagger3 上面已经很详细的讲解了swagger2的集成方式而swagger3的集成方式更加的简洁一些。 首先引入依赖 xml复制代码dependencygroupIdio.springfox/groupIdartifactIdspringfox-boot-starter/artifactIdversion3.0.0/version /dependency然后是替换注解 swagger2使用的开启注解是 EnableSwagger2 而在swagger3中这个注解要换成 EnableOpenApi 配置类 java复制代码import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.oas.annotations.EnableOpenApi; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket;Configuration public class SwaggerConfig {Beanpublic Docket createRestApi() {return new Docket(DocumentationType.OAS_30) // v2 不同.select().apis(RequestHandlerSelectors.basePackage(com.example.swaggerv3.controller)) // 设置扫描路径.build();} }要注意里边的版本类型换成了 OAS_30, 就是swagger3的意思。 OAS 是 OpenAPI Specification 的简称翻译成中文就是 OpenAPI 说明书。 同时访问地址原始地址也就是没换UI的地址 localhost:8080/swagger-ui/index.html这个要和swagger2区分开。 swagger3的原始UI风格也发生了一些变化 同时swagger3也是可以更换UI的。方法和swagger2一样。 四. swaggerUI 拦截器和跨域冲突处理 如果我们的项目中有关于跨域的处理同时还有拦截器然后还要使用swagger这种情况大家要注意了有可能我们的拦截器会将swagger中的页面路径拦截掉导致swagger页面出不来当我们在拦截器中把swagger的页面排除掉的时候也有可能会导致跨域配置的失效。 详细的解决方案可以看我之前写过的一篇博客 lsqingfeng.blog.csdn.net/article/det… 具体解决方案简单提一下 拦截器 java复制代码/*** 拦截器配置** author liuShuai*/ Configuration public class InterceptorConfig implements WebMvcConfigurer {Beanpublic TokenInterceptor tokenInterceptor() {return new TokenInterceptor();}Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(tokenInterceptor()).addPathPatterns(/**).excludePathPatterns(/user/login).excludePathPatterns(/user/downloadExcel).excludePathPatterns(/swagger-resources/**, /webjars/**, /v2/**, /swagger-ui.html/**);}Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler(swagger-ui.html).addResourceLocations(classpath:/META-INF/resources/);registry.addResourceHandler(/webjars/**).addResourceLocations(classpath:/META-INF/resources/webjars/);} }跨域配置 java复制代码import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter;/*** className: CorsConfig* description:* author: sh.Liu* date: 2020-12-02 10:16*/ Configuration public class CorsConfig {Beanpublic CorsFilter corsFilter() {CorsConfiguration config new CorsConfiguration();config.addAllowedOrigin(*);config.setAllowCredentials(true);config.addAllowedMethod(*);config.addAllowedHeader(*);UrlBasedCorsConfigurationSource configSource new UrlBasedCorsConfigurationSource();configSource.registerCorsConfiguration(/**, config);return new CorsFilter(configSource);} }用这两种方式去配置就可以让他们和平共处了。 另 配套项目代码已托管中gitCode: gitcode.net/lsqingfeng/… 分支 feautre/MybatisPlus 所有文章也会在微信公众号首发更新欢迎关注 一缕82年的清风 五. 写在最后 截止到本篇文章关于SpringBoot的系列学习笔记已经更新了十六篇也基本上要和大家说再见了。感谢大家的一路支持。这十六篇文章主要面向SpringBoot的实战性学习上基本很少会介绍一些原理性的概念。也已经集成目前大部分主流的框架和中间件。如果大家对于Spring中一些生命周期初始化过程类加载原理和常用注解不太了解因为这一个部分很少介绍建议大家结合我之前写的Spring5系列教程一起学习里边介绍了Spring IOC和AOP的核心概念。 这个系列的教程就更新到这里了后面可能就不会在继续更新这个系列了。下个目标我可能准备写一个SpringCloud的系列教程主要针对alibaba版本中的一些组件用法。但是由于最近公司比较忙可能更新的会比较慢。希望大家多多支持。 心怀感恩不说再见咱们下个系列见

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

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

相关文章

网站开发工具蜡笔小新网页设计制作网站大一素材

作为一个站长,当你的网站流量逐渐变大时,就会发现目前的主机无法满足正常需要,就要更换更高一级的云主机或VPS主机,新手就需要使用WinSCP和Putty,来管理主机。IIS7服务器管理工具可以批量管理、定时上传下载、同步操作…

网站建设公司自适应源码互联网技术发展现状

macOs系统安装软件的疑问 所有问题mac系统文件结构我用mac安装软件,不用像windows一样创建文件夹吗只能安装到Applications文件夹吗安装程序的指南和提供的安装选项是什么软件安装在Applications下的/appName文件夹,它的所有数据都会在该文件夹吗如果卸载…

网站开发公司怎么找客户开发工具在哪里 word

汇编语言应该是我们如今学的最“低级”的语言了,由于如今不会再有人去学机器语言了。而汇编语言还在一些硬件或者嵌入式设备上使用并开发着。下面资料是为了大学的汇编考试整理的资料,如今与大家分享,希望能给大家提供帮助。 汇编语言程序设计…

牛客刷题-Day8

动态规划1:线性dp、背包问题,区间 https://ac.nowcoder.com/acm/contest/24213?from=acdiscuss牛客刷题-Day8 今日刷题:\(1036-1040\) 1036 凸多边形的划分 题目描述 给定一个具有 \(N\) 个顶点的凸多边形,将顶点…

网站开发 博客长沙百度网站制作

1、父组件可以使用 props 把数据传给子组件。 2、子组件可以使用 $emit 触发父组件的自定义事件。 vm.$emit( event, arg ) //触发当前实例上的事件 vm.$on( event, fn );//监听event事件后运行 fn&#xff1b; 例如&#xff1a;子组件&#xff1a; <template><di…

泉州模板做网站厦门酒店网站建设

在本篇博客中&#xff0c;我们将探讨 UserDetailsService 的重要性&#xff0c;以及如何通过实际示例在 Spring Security 中实现它。 理解 UserDetailsService UserDetailsService 是 Spring Security 提供的一个接口&#xff0c;用于在认证过程中获取用户详细信息。DaoAuthe…

石家庄制作网站的公司简介德州网络

在当前的项目中&#xff0c;使用的是stm32mp157&#xff0c;在烧写系统固件时&#xff0c;有少量的板子使用stm32的stm32cubeProgrammer烧录软件&#xff0c;通过USB接口&#xff0c;死活就是烧录不上&#xff0c;烧录到一半&#xff0c;usb直接就断开了&#xff0c;没办法&…

Educational Codeforces Round 183 (Rated for Div. 2)

A. Candies for Nephews 题意:求大于等于\(n\)的最小\(3\)的倍数。点击查看代码 #include <bits/stdc++.h>using i64 = long long;void solve() {int n;std::cin >> n;std::cout << (n + 2) / 3 * …

免费域名怎么做网站我想做代理商

SnowNLP: 一个简单的中文文本处理库 SnowNLP是一个python写的类库&#xff0c;可以方便的处理中文文本内容&#xff0c;是受到了TextBlob的启发而写的&#xff0c;由于现在大部分的自然语言处理库基本都是针对英文的&#xff0c;于是写了一个方便处理中文的类库&#xff0c;并且…

网站开发维护多少钱软件项目管理考试题及答案

maven打jar包错误 引起错误的原因是在 SpringbootStudyApplication 类中&#xff0c;加入了下面注释中的代码&#xff08;监听项目启动&#xff0c;然后打开浏览器&#xff09;&#xff0c;单纯删掉注释代码是无法解决问题的&#xff0c;可能的原因是由于加入这部分代码而impo…

做猎头要用的网站知乎超简单网页制作模板

文章目录1&#xff0e;命令格式2&#xff0e;命令功能3&#xff0e;命令参数4&#xff0e;命令实例1、文件改名&#xff08; 重命名&#xff09;2、移动文件3、将test目录下的文件text1.txt text2.txt text3.txt移动到目录mv中。4、将文件file1改名为file2&#xff0c;如果file…

长春网站建设那家好如何做网站活动

[js] 使用ajax请求真的不安全吗&#xff1f;为什么&#xff1f; AJAX是发送HTTP请求的一种方式&#xff0c;只不过浏览器给它加了一个同源策略而已。 所以从这一点可以得出一个结论&#xff1a;AJAX本质上安全性和HTTP请求一样个人简介 我是歌谣&#xff0c;欢迎和大家一起交…

广州网站优化工具服务静态网站注入

动态代理jdk的Proxy与Spring的CGlib 文章目录 动态代理jdk的Proxy与Spring的CGlib1. 为什么要使用动态代理&#xff1f;2. JDK Proxy 动态代理面向接口的动态代理3. CGlib动态代理4. 两个动态代理的区别 1. 为什么要使用动态代理&#xff1f; 动态代理&#xff1a;在不改变原有…

高三闲话 #2

“那你们现在坐在这,一定是失败了。”小食堂外面有一只猫,每天吃饭都可以看到它趴在那里,被投喂一些食物。不过我在它眼中看不到任何“乞食”的色彩,更像是在等待被“进贡”。我们每天吃完饭回去都要欣赏那只猫,G…

D. Inversion Value of a Permutation edu div2

题意:给出一个排列,其逆序值为:包含至少一个逆序对的子区间数量 给出n和k,要求构造一个长度为n的,逆序值为k的排列 很显然,如果一个排列内,若是有两个位置逆序,那么以这两个位置为起点,找到的所有子区间可能会…

Mineserver

Mineserverhttps://github.com/CoolManBob/mineserver 项目简介(根据 README)名称:Mineserver用途:一个 Minecraft Alpha(早期版 Minecraft) 的 自定义服务器软件,用 C++ 编写,支持 Windows 和 Linux 平台。Gi…

首钢建设二公司网站博客网站开发背景及作用

之前的表单验证都是用js写的&#xff0c;这里也可以使用tp框架的验证。但是两者比较而言还是js验证比较好&#xff0c;因为tp框架验证会运行后台代码&#xff0c;这样运行速度和效率就会下降。  自动验证是ThinkPHP模型层提供的一种数据验证方法&#xff0c;可以在使用create创…

个人博客公告

由于github部署的网站维护稍微有点繁琐(有点懒了更新了) 原来的域名gannia.top 已经到期了暂时还没有续费的打算(指香港云服务器不清楚怎么推掉域名,想要更换阿里云域名的) 目前暂时还是用着原来的域名 https://t…

一个刚大一的普通大学生

title: 一个刚大一的普通大学生 tags: [] categories:生活 author: Tokepson date: 2025-05-01 00:32:00关于我 一名正在山东上大学的普通大学生(虽然说是在上海成长的。。。) 在多次了解到个人网站领域的信息后,出…

通过利用百度对于外链的检测算法上的缺陷

友情链接欺骗,通过利用百度对于外链的检测算法上的缺陷,可以实现自己的网站所有对外的链接,被判定为“不是站长真正的去推荐”的外链,让百度自动过滤掉这类链接的计算分值。 第四种:快速排名,目前快速排名技术有…