功能开发,加入了昨晚失眠到2点想到的功能,文档大一统指日可待~

This commit is contained in:
暮光:城中城
2018-12-16 22:20:30 +08:00
parent 204ba15e11
commit 3a5702c676
18 changed files with 821 additions and 517 deletions

View File

@@ -27,6 +27,9 @@
<velocity.engine.core.version>2.0</velocity.engine.core.version> <velocity.engine.core.version>2.0</velocity.engine.core.version>
<dozer.core.version>6.1.0</dozer.core.version> <dozer.core.version>6.1.0</dozer.core.version>
<alibaba.druid.version>1.1.9</alibaba.druid.version> <alibaba.druid.version>1.1.9</alibaba.druid.version>
<swagger.bootstrap.ui.version>1.8.7</swagger.bootstrap.ui.version>
<springfox.swagger.ui.version>2.9.2</springfox.swagger.ui.version>
<springfox.swagger.version>2.9.2</springfox.swagger.version>
</properties> </properties>
<dependencies> <dependencies>
@@ -72,6 +75,11 @@
<artifactId>dozer-core</artifactId> <artifactId>dozer-core</artifactId>
<version>${dozer.core.version}</version> <version>${dozer.core.version}</version>
</dependency> </dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox.swagger.version}</version>
</dependency>
<!-- 在线文档解析页面 --> <!-- 在线文档解析页面 -->
<dependency> <dependency>
<groupId>com.zyplayer</groupId> <groupId>com.zyplayer</groupId>
@@ -83,6 +91,16 @@
<artifactId>zyplayer-doc-core</artifactId> <artifactId>zyplayer-doc-core</artifactId>
<version>${zyplayer.doc.core.version}</version> <version>${zyplayer.doc.core.version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>${swagger.bootstrap.ui.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox.swagger.ui.version}</version>
</dependency>
<!-- velocity 模板引擎, 默认 --> <!-- velocity 模板引擎, 默认 -->
<dependency> <dependency>
<groupId>org.apache.velocity</groupId> <groupId>org.apache.velocity</groupId>

View File

@@ -33,14 +33,17 @@ public class Application extends SpringBootServletInitializer {
contextPath = (contextPath.length() <= 0 || contextPath.endsWith("/")) ? contextPath : contextPath + "/"; contextPath = (contextPath.length() <= 0 || contextPath.endsWith("/")) ? contextPath : contextPath + "/";
String hostAddress = InetAddress.getLocalHost().getHostAddress(); String hostAddress = InetAddress.getLocalHost().getHostAddress();
String serverPort = env.getProperty("server.port"); String serverPort = env.getProperty("server.port");
String urlCtx = hostAddress + ":" + serverPort + "/" + contextPath;
// 三个UI的名字长度惊人的一致肯定是知道我有强迫症
logger.info("\n----------------------------------------------------------\n\t" + logger.info("\n----------------------------------------------------------\n\t" +
"\t\t地址列表\n\t" + "\t\t地址列表\n\t" +
"文档地址http://{}:{}/{}document.html\n\t" + "zyplayer-doc-swaggerhttp://{}document.html\n\t" +
//"数据库地址http://{}:{}/{}document.html\n " + "swagger-bootstrap-uihttp://{}doc.html\n\t" +
"管理地址http://{}:{}/{}statics/manage/home.html\n" + "springfox-swagger-uihttp://{}swagger-ui.html\n\t" +
//"数据库地址http://{}document.html\n " +
"管理地址http://{}statics/manage/home.html\n" +
"----------------------------------------------------------", "----------------------------------------------------------",
hostAddress, serverPort, contextPath, urlCtx, urlCtx, urlCtx, urlCtx
hostAddress, serverPort, contextPath
); );
} }
} }

View File

@@ -23,9 +23,9 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2;
* @since 2018年11月11日 * @since 2018年11月11日
*/ */
@Configuration @Configuration
@EnableSwagger2 //@EnableSwagger2
@EnableSwaggerMgUi( @EnableSwaggerMgUi(
selfDoc = true,// 是否开启自身的文档 selfDoc = false,// 是否开启自身的文档
defaultResources = {// 启动后第一次访问没有数据情况下需要加载进来的swagger-resources地址 defaultResources = {// 启动后第一次访问没有数据情况下需要加载进来的swagger-resources地址
//"http://localhost:8080/swagger-resources" //"http://localhost:8080/swagger-resources"
} }

View File

@@ -39,7 +39,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
*/ */
@Override @Override
public void configure(WebSecurity web) throws Exception { public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/statics/lib/**", "/css/**", "/js/**", "/img/**", "/swagger-resources", "/v2/api-docs"); web.ignoring().antMatchers("/statics/lib/**", "/css/**", "/js/**", "/img/**");
} }
@Override @Override
@@ -47,7 +47,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
String loginPage = "/statics/manage/login.html"; String loginPage = "/statics/manage/login.html";
http.authorizeRequests().antMatchers("/login/**").permitAll()//为了测试其他功能,设置“ /** ”允许所有请求 http.authorizeRequests().antMatchers("/login/**").permitAll()//为了测试其他功能,设置“ /** ”允许所有请求
.antMatchers("/document.html").hasAuthority("DOC_ALL") .antMatchers("/document.html", "/doc.html").hasAuthority("DOC_ALL")
// 其他地址的访问均需登录 // 其他地址的访问均需登录
.anyRequest().authenticated().and() .anyRequest().authenticated().and()
// 添加验证码验证 // 添加验证码验证

View File

@@ -15,32 +15,30 @@ import javax.servlet.http.HttpServletResponse;
@Component @Component
public class RequestInfoInterceptor implements HandlerInterceptor { public class RequestInfoInterceptor implements HandlerInterceptor {
private static final Logger logger = LoggerFactory.getLogger(RequestInfoInterceptor.class); private static final Logger logger = LoggerFactory.getLogger(RequestInfoInterceptor.class);
private ThreadLocal<Long> startTimeThreadLocal = new ThreadLocal<>(); private ThreadLocal<Long> startTimeThreadLocal = new ThreadLocal<>();
/** /**
* 把当前请求记录到下来 * 把当前请求记录到下来
*/ */
@Override @Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object arg2, Exception arg3) public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object arg2, Exception arg3) {
throws Exception {
long startTime = startTimeThreadLocal.get(); long startTime = startTimeThreadLocal.get();
long totalTime = System.currentTimeMillis() - startTime;// 结束时间 long totalTime = System.currentTimeMillis() - startTime;// 结束时间
logger.error("总耗时:{}ms URI{}", totalTime, request.getRequestURI()); logger.error("总耗时:{}msURI{}", totalTime, request.getRequestURI());
} }
@Override @Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object haddler, public void postHandle(HttpServletRequest request, HttpServletResponse response, Object haddler, ModelAndView modelAndView) {
ModelAndView modelAndView) throws Exception {
} }
/** /**
* 记录请求信息 * 记录请求信息
*/ */
@Override @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) throws Exception { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) {
startTimeThreadLocal.set(System.currentTimeMillis()); startTimeThreadLocal.set(System.currentTimeMillis());
return true; return true;
} }
} }

View File

@@ -38,8 +38,8 @@ demo代码地址
#### 模拟请求拦截 功能: #### 模拟请求拦截 功能:
判断是否是模拟请求,功能需求: 判断是否是模拟请求,功能需求:
很多时候后端定义好了接口,但还未实现,这时前端已经需要数据调试了,这时就需要用到这个过滤器了! 很多时候后端定义好了接口,但还未实现,这时前端已经需要数据调试了,这时就需要用到这个过滤器了!
在页面上先配置好模拟返回的数据然后在url上加入参数mgUiTestFlag=1 在页面上先配置好模拟返回的数据然后在url上加入参数zyplayerApiTest=1
http://192.168.0.249:8082/openApi/case/info?mgUiTestFlag=1 http://192.168.0.249:8082/openApi/case/info?zyplayerApiTest=1
本过滤器就直接返回了之前配置的模拟数据而不用等到后端必须把接口实现之后才能调试或者在前端写一大段测试数据。也可以只复制本项目里的MgUiTestFilter.java代码到被访问的项目里 本过滤器就直接返回了之前配置的模拟数据而不用等到后端必须把接口实现之后才能调试或者在前端写一大段测试数据。也可以只复制本项目里的MgUiTestFilter.java代码到被访问的项目里
笔者的公司后端人较少一个需求需要10个接口需求分析完后首先就把接口、参数、返回值定义好然后一个个的去实现。 笔者的公司后端人较少一个需求需要10个接口需求分析完后首先就把接口、参数、返回值定义好然后一个个的去实现。

View File

@@ -1,220 +1,225 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" <project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.zyplayer</groupId> <groupId>com.zyplayer</groupId>
<artifactId>zyplayer-doc-swagger</artifactId> <artifactId>zyplayer-doc-swagger</artifactId>
<version>2.0.1</version> <version>2.0.1</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>zyplayer-doc-swagger</name> <name>zyplayer-doc-swagger</name>
<description>zyplayer-doc-swagger是swagger-ui的一个前端实现使用简单、解析速度快、走心的设计支持多项目同时展示多种文档目录的展示方案多种自定义配置满足各种使用习惯</description> <description>zyplayer-doc-swagger是swagger-ui的一个前端实现使用简单、解析速度快、走心的设计支持多项目同时展示多种文档目录的展示方案多种自定义配置满足各种使用习惯</description>
<url>https://gitee.com/zyplayer/zyplayer-doc/zyplayer-doc-swagger</url> <url>https://gitee.com/zyplayer/zyplayer-doc/zyplayer-doc-swagger</url>
<developers> <developers>
<developer> <developer>
<id>zyplayer</id> <id>zyplayer</id>
<name>暮光:城中城</name> <name>暮光:城中城</name>
<email>806783409@qq.com</email> <email>806783409@qq.com</email>
<roles> <roles>
<role>Java Development Engineer</role> <role>Java Development Engineer</role>
</roles> </roles>
<timezone>2018-05-22 16:06:06</timezone> <timezone>2018-05-22 16:06:06</timezone>
</developer> </developer>
</developers> </developers>
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.2.RELEASE</version> <version>1.4.2.RELEASE</version>
</parent> </parent>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version> <java.version>1.8</java.version>
<!-- 打包跳过单元测试 --> <!-- 打包跳过单元测试 -->
<skipTests>true</skipTests> <skipTests>true</skipTests>
<destDir>${project.build.outputDirectory}/META-INF/resources/webjars/${project.artifactId}/${project.version}</destDir> <destDir>${project.build.outputDirectory}/META-INF/resources/webjars/${project.artifactId}/${project.version}</destDir>
<zyplayer.doc.core.version>1.0.0</zyplayer.doc.core.version> <zyplayer.doc.core.version>1.0.0</zyplayer.doc.core.version>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.springfox</groupId> <groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId> <artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version> <version>2.7.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId> <artifactId>fastjson</artifactId>
<version>1.2.44</version> <version>1.2.44</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>cn.hutool</groupId> <groupId>cn.hutool</groupId>
<artifactId>hutool-http</artifactId> <artifactId>hutool-http</artifactId>
<version>4.1.8</version> <version>4.1.8</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>commons-lang</groupId> <groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId> <artifactId>commons-lang</artifactId>
<version>2.6</version> <version>2.6</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.zyplayer</groupId> <groupId>commons-io</groupId>
<artifactId>zyplayer-doc-core</artifactId> <artifactId>commons-io</artifactId>
<version>${zyplayer.doc.core.version}</version> <version>2.4</version>
</dependency> </dependency>
</dependencies> <dependency>
<groupId>com.zyplayer</groupId>
<licenses> <artifactId>zyplayer-doc-core</artifactId>
<license> <version>${zyplayer.doc.core.version}</version>
<name>The Apache Software License, Version 2.0</name> </dependency>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url> </dependencies>
</license>
</licenses> <licenses>
<scm> <license>
<connection>scm:git@git.oschina.net:zyplayer/zyplayer-doc-swagger.git</connection> <name>The Apache Software License, Version 2.0</name>
<developerConnection>scm:git@git.oschina.net:zyplayer/zyplayer-doc-swagger.git</developerConnection> <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<url>git@git.oschina.net:zyplayer/zyplayer-doc-swagger.git</url> </license>
</scm> </licenses>
<scm>
<distributionManagement> <connection>scm:git@git.oschina.net:zyplayer/zyplayer-doc-swagger.git</connection>
<snapshotRepository> <developerConnection>scm:git@git.oschina.net:zyplayer/zyplayer-doc-swagger.git</developerConnection>
<id>snapshots</id> <url>git@git.oschina.net:zyplayer/zyplayer-doc-swagger.git</url>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url> </scm>
</snapshotRepository>
<repository> <distributionManagement>
<id>snapshots</id> <snapshotRepository>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url> <id>snapshots</id>
</repository> <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</distributionManagement> </snapshotRepository>
<repository>
<build> <id>snapshots</id>
<resources> <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
<resource> </repository>
<directory>src/main/resources</directory> </distributionManagement>
<targetPath>META-INF/resources/</targetPath>
</resource> <build>
<resource> <resources>
<directory>src/main/java</directory> <resource>
<includes> <directory>src/main/resources</directory>
<include>**/*</include> <targetPath>META-INF/resources/</targetPath>
</includes> </resource>
<excludes> <resource>
<exclude>**/*.java</exclude> <directory>src/main/java</directory>
</excludes> <includes>
<filtering>false</filtering> <include>**/*</include>
</resource> </includes>
<resource> <excludes>
<directory>src/main/webapp</directory> <exclude>**/*.java</exclude>
<includes> </excludes>
<include>**/*</include> <filtering>false</filtering>
</includes> </resource>
<filtering>false</filtering> <resource>
</resource> <directory>src/main/webapp</directory>
</resources> <includes>
<plugins> <include>**/*</include>
<plugin> </includes>
<groupId>org.apache.maven.plugins</groupId> <filtering>false</filtering>
<artifactId>maven-javadoc-plugin</artifactId> </resource>
<version>2.10.2</version> </resources>
<configuration> <plugins>
<aggregate>true</aggregate> <plugin>
</configuration> <groupId>org.apache.maven.plugins</groupId>
<executions> <artifactId>maven-javadoc-plugin</artifactId>
<execution> <version>2.10.2</version>
<id>attach-javadocs</id> <configuration>
<goals> <aggregate>true</aggregate>
<goal>jar</goal> </configuration>
</goals> <executions>
</execution> <execution>
</executions> <id>attach-javadocs</id>
</plugin> <goals>
<plugin> <goal>jar</goal>
<groupId>org.apache.maven.plugins</groupId> </goals>
<artifactId>maven-source-plugin</artifactId> </execution>
<executions> </executions>
<execution> </plugin>
<id>attach-sources</id> <plugin>
<goals> <groupId>org.apache.maven.plugins</groupId>
<goal>jar</goal> <artifactId>maven-source-plugin</artifactId>
</goals> <executions>
</execution> <execution>
</executions> <id>attach-sources</id>
</plugin> <goals>
<plugin> <goal>jar</goal>
<groupId>org.apache.maven.plugins</groupId> </goals>
<artifactId>maven-compiler-plugin</artifactId> </execution>
<configuration> </executions>
<source>1.8</source> </plugin>
<target>1.8</target> <plugin>
<encoding>UTF-8</encoding> <groupId>org.apache.maven.plugins</groupId>
</configuration> <artifactId>maven-compiler-plugin</artifactId>
</plugin> <configuration>
<plugin> <source>1.8</source>
<groupId>org.apache.maven.plugins</groupId> <target>1.8</target>
<artifactId>maven-surefire-plugin</artifactId> <encoding>UTF-8</encoding>
<version>2.18.1</version> </configuration>
<configuration> </plugin>
<skipTests>${skipTests}</skipTests> <plugin>
</configuration> <groupId>org.apache.maven.plugins</groupId>
</plugin> <artifactId>maven-surefire-plugin</artifactId>
</plugins> <version>2.18.1</version>
</build> <configuration>
<profiles> <skipTests>${skipTests}</skipTests>
<profile> </configuration>
<id>release</id> </plugin>
<build> </plugins>
<plugins> </build>
<plugin> <profiles>
<groupId>org.apache.maven.plugins</groupId> <profile>
<artifactId>maven-source-plugin</artifactId> <id>release</id>
<version>2.2.1</version> <build>
<executions> <plugins>
<execution> <plugin>
<phase>package</phase> <groupId>org.apache.maven.plugins</groupId>
<goals> <artifactId>maven-source-plugin</artifactId>
<goal>jar-no-fork</goal> <version>2.2.1</version>
</goals> <executions>
</execution> <execution>
</executions> <phase>package</phase>
</plugin> <goals>
<plugin> <goal>jar-no-fork</goal>
<groupId>org.apache.maven.plugins</groupId> </goals>
<artifactId>maven-javadoc-plugin</artifactId> </execution>
<version>2.10.2</version> </executions>
<configuration> </plugin>
<aggregate>true</aggregate> <plugin>
</configuration> <groupId>org.apache.maven.plugins</groupId>
<executions> <artifactId>maven-javadoc-plugin</artifactId>
<execution> <version>2.10.2</version>
<id>attach-javadocs</id> <configuration>
<goals> <aggregate>true</aggregate>
<goal>jar</goal> </configuration>
</goals> <executions>
</execution> <execution>
</executions> <id>attach-javadocs</id>
</plugin> <goals>
<plugin> <goal>jar</goal>
<groupId>org.apache.maven.plugins</groupId> </goals>
<artifactId>maven-gpg-plugin</artifactId> </execution>
<version>1.6</version> </executions>
<executions> </plugin>
<execution> <plugin>
<phase>verify</phase> <groupId>org.apache.maven.plugins</groupId>
<goals> <artifactId>maven-gpg-plugin</artifactId>
<goal>sign</goal> <version>1.6</version>
</goals> <executions>
</execution> <execution>
</executions> <phase>verify</phase>
</plugin> <goals>
</plugins> <goal>sign</goal>
</build> </goals>
</profile> </execution>
</profiles> </executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project> </project>

View File

@@ -25,6 +25,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
/** /**
* 文档控制器 * 文档控制器
@@ -71,13 +72,13 @@ public class MgDocumentController {
@PostMapping(value = "/docs") @PostMapping(value = "/docs")
public void docs(HttpServletRequest request, HttpServletResponse response) { public void docs(HttpServletRequest request, HttpServletResponse response) {
boolean needRestorage = true; boolean needRestorage = true;
String choiseDocList = request.getParameter("choiseDocList"); String choiceDocList = request.getParameter("choiseDocList");
// 转成set防止重复 // 转成set防止重复
Set<SwaggerResourcesInfoVo> resourcesSet = new HashSet<>(); List<SwaggerResourcesInfoVo> resourcesSet = new LinkedList<>();
Set<String> swaggerDocsDeleteSet = new HashSet<>(); Set<String> swaggerDocsDeleteSet = new HashSet<>();
if (StringUtils.isNotBlank(choiseDocList)) { if (StringUtils.isNotBlank(choiceDocList)) {
needRestorage = false;// 选择的则不再存入 needRestorage = false;// 选择的则不再存入
for (String url : choiseDocList.split(",")) { for (String url : choiceDocList.split(",")) {
resourcesSet.add(new SwaggerResourcesInfoVo(url)); resourcesSet.add(new SwaggerResourcesInfoVo(url));
} }
} else { } else {
@@ -142,6 +143,7 @@ public class MgDocumentController {
if (resourceList == null || resourceList.isEmpty()) { if (resourceList == null || resourceList.isEmpty()) {
continue; continue;
} }
resourcesInfoVo.setResourceList(resourceList);
resourcesUrl = resourcesUrl.substring(0, resourcesUrl.lastIndexOf("/") + 1); resourcesUrl = resourcesUrl.substring(0, resourcesUrl.lastIndexOf("/") + 1);
for (SwaggerResource resource : resourceList) { for (SwaggerResource resource : resourceList) {
String location = resource.getLocation(); String location = resource.getLocation();
@@ -181,6 +183,8 @@ public class MgDocumentController {
} }
} }
if (needRestorage) { if (needRestorage) {
AtomicInteger idIndex = new AtomicInteger(1);
resourcesSet.forEach(val -> val.setId(idIndex.getAndIncrement()));
storageService.put(StorageKeys.SWAGGER_RESOURCES_LIST, JSON.toJSONString(resourcesSet)); storageService.put(StorageKeys.SWAGGER_RESOURCES_LIST, JSON.toJSONString(resourcesSet));
} }
// 用默认的json解析要内存溢出解析不了JSONObject、、就只有这样写了~ // 用默认的json解析要内存溢出解析不了JSONObject、、就只有这样写了~
@@ -205,10 +209,9 @@ public class MgDocumentController {
swaggerDocsDeleteSet.addAll(swaggerDocsDeleteList); swaggerDocsDeleteSet.addAll(swaggerDocsDeleteList);
} }
// 转成set防止重复 // 转成set防止重复
Set<SwaggerResourcesInfoVo> resourcesSet = new HashSet<>(); List<SwaggerResourcesInfoVo> resourcesList = null;
if (StringUtils.isNotBlank(swaggerResourcesStr)) { if (StringUtils.isNotBlank(swaggerResourcesStr)) {
List<SwaggerResourcesInfoVo> resourcesList = JSON.parseArray(swaggerResourcesStr, SwaggerResourcesInfoVo.class); resourcesList = JSON.parseArray(swaggerResourcesStr, SwaggerResourcesInfoVo.class);
resourcesSet.addAll(resourcesList);
} }
try { try {
String resourcesStr = HttpRequest.get(resourcesUrl).timeout(3000).execute().body(); String resourcesStr = HttpRequest.get(resourcesUrl).timeout(3000).execute().body();
@@ -233,7 +236,9 @@ public class MgDocumentController {
location = resourcesDomain + location; location = resourcesDomain + location;
swaggerDocsDeleteSet.remove(location); swaggerDocsDeleteSet.remove(location);
} }
resourcesSet.add(new SwaggerResourcesInfoVo(resourcesUrl)); resourcesList.add(new SwaggerResourcesInfoVo(resourcesUrl, resourceList));
AtomicInteger idIndex = new AtomicInteger(1);
resourcesList.forEach(val -> val.setId(idIndex.getAndIncrement()));
} catch (Exception e) { } catch (Exception e) {
// 暂不想支持直接添加地址 // 暂不想支持直接添加地址
// try { // try {
@@ -254,7 +259,7 @@ public class MgDocumentController {
return DocResponseJson.warn("该地址查找文档失败"); return DocResponseJson.warn("该地址查找文档失败");
// } // }
} }
storageService.put(StorageKeys.SWAGGER_RESOURCES_LIST, JSON.toJSONString(resourcesSet)); storageService.put(StorageKeys.SWAGGER_RESOURCES_LIST, JSON.toJSONString(resourcesList));
storageService.put(StorageKeys.SWAGGER_DOCS_DELETE_LIST, JSON.toJSONString(swaggerDocsDeleteSet)); storageService.put(StorageKeys.SWAGGER_DOCS_DELETE_LIST, JSON.toJSONString(swaggerDocsDeleteSet));
return DocResponseJson.ok(); return DocResponseJson.ok();
} }

View File

@@ -0,0 +1,67 @@
package com.zyplayer.doc.swagger.controller;
import com.alibaba.fastjson.JSON;
import com.zyplayer.doc.swagger.controller.vo.SwaggerResourcesInfoVo;
import com.zyplayer.doc.swagger.framework.constant.Consts;
import com.zyplayer.doc.swagger.framework.constant.StorageKeys;
import com.zyplayer.doc.swagger.framework.service.MgStorageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.swagger.web.ApiKeyVehicle;
import springfox.documentation.swagger.web.SecurityConfiguration;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.UiConfiguration;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
* 承接了所有的ApiResourceController的接口
*
* @author 暮光:城中城
* @since 2018年12月16日
*/
@RestController
public class ZyplayerSwaggerController {
@Autowired
private MgStorageService storageService;
@RequestMapping("/swagger-resources")
public List<SwaggerResource> swaggerResources() {
String swaggerResourcesStr = storageService.get(StorageKeys.SWAGGER_RESOURCES_LIST);
List<SwaggerResourcesInfoVo> resourcesInfoVoList = JSON.parseArray(swaggerResourcesStr, SwaggerResourcesInfoVo.class);
if (resourcesInfoVoList == null || resourcesInfoVoList.isEmpty()) {
return Collections.emptyList();
}
List<SwaggerResource> resourceList = new LinkedList<>();
resourcesInfoVoList.forEach(resource -> {
resource.getResourceList().forEach(val -> {
String location = val.getLocation();
val.setLocation(Consts.ZYPLAYER_PROXY + resource.getId() + location);
});
resourceList.addAll(resource.getResourceList());
});
return resourceList;
}
@ResponseBody
@RequestMapping(value = "/swagger-resources/configuration/security")
public ResponseEntity<SecurityConfiguration> securityConfiguration() {
SecurityConfiguration securityConfiguration = new SecurityConfiguration(null, null, null, null, null, ApiKeyVehicle.HEADER, "api_key", ",");
return new ResponseEntity<>(securityConfiguration, HttpStatus.OK);
}
@ResponseBody
@RequestMapping(value = "/swagger-resources/configuration/ui")
public ResponseEntity<UiConfiguration> uiConfiguration() {
UiConfiguration uiConfiguration = new UiConfiguration(null);
return new ResponseEntity<>(uiConfiguration, HttpStatus.OK);
}
}

View File

@@ -1,197 +1,196 @@
package com.zyplayer.doc.swagger.controller.param; package com.zyplayer.doc.swagger.controller.param;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference; import com.alibaba.fastjson.TypeReference;
import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpRequest;
import cn.hutool.http.Method; import cn.hutool.http.Method;
/** /**
* 请求参数对象 * 请求参数对象
* *
* @author 暮光:城中城 * @author 暮光:城中城
* @since 2018年8月21日 * @since 2018年8月21日
*/ */
public class HttpRequestParam { public class HttpRequestParam {
private String url; private String url;
private String method; private String method;
private String header; private String header;
private String form; private String form;
private String body; private String body;
public String getUrl() { public String getUrl() {
return url; return url;
} }
public void setUrl(String url) { public void setUrl(String url) {
this.url = url; this.url = url;
} }
public String getHeader() { public String getHeader() {
return header; return header;
} }
public void setHeader(String header) { public void setHeader(String header) {
this.header = header; this.header = header;
} }
public String getForm() { public String getForm() {
return form; return form;
} }
public void setForm(String form) { public void setForm(String form) {
this.form = form; this.form = form;
} }
public String getBody() { public String getBody() {
return body; return body;
} }
public void setBody(String body) { public void setBody(String body) {
this.body = body; this.body = body;
} }
public Map<String, String> getHeaderMap() { public Map<String, String> getHeaderMap() {
if (StringUtils.isBlank(header)) { if (StringUtils.isBlank(header)) {
return null; return null;
} }
Map<String, String> headerMap = JSON.parseObject(header, new TypeReference<HashMap<String, String>>() { Map<String, String> headerMap = JSON.parseObject(header, new TypeReference<HashMap<String, String>>() {});
}); return headerMap;
return headerMap; }
}
public Map<String, Object> getFormMap() {
public Map<String, Object> getFormMap() { if (StringUtils.isBlank(form)) {
if (StringUtils.isBlank(form)) { return null;
return null; }
} Map<String, Object> formMap = JSON.parseObject(form, new TypeReference<HashMap<String, Object>>() {});
Map<String, Object> formMap = JSON.parseObject(form, new TypeReference<HashMap<String, Object>>() {}); return formMap;
return formMap; }
}
public void createHttpRequest(HttpRequest request) {
public void createHttpRequest(HttpRequest request) { Map<String, String> headerMap = this.getHeaderMap();
Map<String, String> headerMap = this.getHeaderMap(); if (headerMap != null) {
if (headerMap != null) { request.addHeaders(headerMap);
request.addHeaders(headerMap); if (headerMap.containsKey("Content-Type")) {
if (headerMap.containsKey("Content-Type")) { request.contentType(headerMap.get("Content-Type"));
request.contentType(headerMap.get("Content-Type")); }
} }
} Map<String, Object> formMap = this.getFormMap();
Map<String, Object> formMap = this.getFormMap(); if (formMap != null) {
if (formMap != null) { request.form(formMap);
request.form(formMap); }
} if (StringUtils.isNotBlank(body) && request.getMethod() != Method.GET) {
if (StringUtils.isNotBlank(body) && request.getMethod() != Method.GET) { request.body(body);
request.body(body); }
} }
}
/**
/** * 组装请求
* 组装请求 * @return HttpRequest
* @return HttpRequest */
*/ public HttpRequest createRequest() {
public HttpRequest createRequest() { if("get".equalsIgnoreCase(this.method)) return get();
if("get".equalsIgnoreCase(this.method)) return get(); if("post".equalsIgnoreCase(this.method)) return post();
if("post".equalsIgnoreCase(this.method)) return post(); if("head".equalsIgnoreCase(this.method)) return head();
if("head".equalsIgnoreCase(this.method)) return head(); if("options".equalsIgnoreCase(this.method)) return options();
if("options".equalsIgnoreCase(this.method)) return options(); if("put".equalsIgnoreCase(this.method)) return put();
if("put".equalsIgnoreCase(this.method)) return put(); if("patch".equalsIgnoreCase(this.method)) return patch();
if("patch".equalsIgnoreCase(this.method)) return patch(); if("delete".equalsIgnoreCase(this.method)) return delete();
if("delete".equalsIgnoreCase(this.method)) return delete(); if("trace".equalsIgnoreCase(this.method)) return trace();
if("trace".equalsIgnoreCase(this.method)) return trace(); return get();
return get(); }
}
/**
/** * POST请求
* POST请求 * @return HttpRequest
* @return HttpRequest */
*/ public HttpRequest post() {
public HttpRequest post() { HttpRequest request = HttpRequest.post(this.getUrl());
HttpRequest request = HttpRequest.post(this.getUrl()); this.createHttpRequest(request);
this.createHttpRequest(request); return request;
return request; }
}
/**
/** * GET请求
* GET请求 * @return HttpRequest
* @return HttpRequest */
*/ public HttpRequest get() {
public HttpRequest get() { HttpRequest request = HttpRequest.get(this.getUrl());
HttpRequest request = HttpRequest.get(this.getUrl()); this.createHttpRequest(request);
this.createHttpRequest(request); return request;
return request; }
}
/**
/** * HEAD请求
* HEAD请求 * @return HttpRequest
* @return HttpRequest */
*/ public HttpRequest head() {
public HttpRequest head() { HttpRequest request = HttpRequest.head(this.getUrl());
HttpRequest request = HttpRequest.head(this.getUrl()); this.createHttpRequest(request);
this.createHttpRequest(request); return request;
return request; }
}
/**
/** * OPTIONS请求
* OPTIONS请求 * @return HttpRequest
* @return HttpRequest */
*/ public HttpRequest options() {
public HttpRequest options() { HttpRequest request = HttpRequest.options(this.getUrl());
HttpRequest request = HttpRequest.options(this.getUrl()); this.createHttpRequest(request);
this.createHttpRequest(request); return request;
return request; }
}
/**
/** * PUT请求
* PUT请求 * @return HttpRequest
* @return HttpRequest */
*/ public HttpRequest put() {
public HttpRequest put() { HttpRequest request = HttpRequest.put(this.getUrl());
HttpRequest request = HttpRequest.put(this.getUrl()); this.createHttpRequest(request);
this.createHttpRequest(request); return request;
return request; }
}
/**
/** * PATCH请求
* PATCH请求 * @return HttpRequest
* @return HttpRequest */
*/ public HttpRequest patch() {
public HttpRequest patch() { HttpRequest request = HttpRequest.patch(this.getUrl());
HttpRequest request = HttpRequest.patch(this.getUrl()); this.createHttpRequest(request);
this.createHttpRequest(request); return request;
return request; }
}
/**
/** * DELETE请求
* DELETE请求 * @return HttpRequest
* @return HttpRequest */
*/ public HttpRequest delete() {
public HttpRequest delete() { HttpRequest request = HttpRequest.delete(this.getUrl());
HttpRequest request = HttpRequest.delete(this.getUrl()); this.createHttpRequest(request);
this.createHttpRequest(request); return request;
return request; }
}
/**
/** * TRACE请求
* TRACE请求 * @return HttpRequest
* @return HttpRequest */
*/ public HttpRequest trace() {
public HttpRequest trace() { HttpRequest request = HttpRequest.trace(this.getUrl());
HttpRequest request = HttpRequest.trace(this.getUrl()); this.createHttpRequest(request);
this.createHttpRequest(request); return request;
return request; }
}
public String getMethod() {
public String getMethod() { return method;
return method; }
}
public void setMethod(String method) {
public void setMethod(String method) { this.method = method;
this.method = method; }
}
}
}

View File

@@ -2,50 +2,82 @@ package com.zyplayer.doc.swagger.controller.vo;
import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.RandomUtil;
import com.zyplayer.doc.swagger.framework.constant.StorageKeys; import com.zyplayer.doc.swagger.framework.constant.StorageKeys;
import springfox.documentation.swagger.web.SwaggerResource;
import java.io.Serializable;
import java.util.Date; import java.util.Date;
import java.util.List;
public class SwaggerResourcesInfoVo { public class SwaggerResourcesInfoVo implements Serializable {
private Integer id;
private String url; private String url;
private String storageKey; private String storageKey;
private List<SwaggerResource> resourceList;
private Date creationTime; private Date creationTime;
private Date lastSync; private Date lastSync;
public SwaggerResourcesInfoVo(String url){ public SwaggerResourcesInfoVo() {
}
public SwaggerResourcesInfoVo(String url) {
this.url = url; this.url = url;
this.storageKey = StorageKeys.SWAGGER_OFFLINE_DOC_START + RandomUtil.simpleUUID(); this.storageKey = StorageKeys.SWAGGER_OFFLINE_DOC_START + RandomUtil.simpleUUID();
this.creationTime = new Date(); this.creationTime = new Date();
} }
public SwaggerResourcesInfoVo(String url, List<SwaggerResource> resourceList) {
this.url = url;
this.resourceList = resourceList;
this.storageKey = StorageKeys.SWAGGER_OFFLINE_DOC_START + RandomUtil.simpleUUID();
this.creationTime = new Date();
}
public String getUrl() { public String getUrl() {
return url; return url;
} }
public void setUrl(String url) { public void setUrl(String url) {
this.url = url; this.url = url;
} }
public String getStorageKey() { public String getStorageKey() {
return storageKey; return storageKey;
} }
public void setStorageKey(String storageKey) { public void setStorageKey(String storageKey) {
this.storageKey = storageKey; this.storageKey = storageKey;
} }
public Date getCreationTime() { public Date getCreationTime() {
return creationTime; return creationTime;
} }
public void setCreationTime(Date creationTime) { public void setCreationTime(Date creationTime) {
this.creationTime = creationTime; this.creationTime = creationTime;
} }
public Date getLastSync() { public Date getLastSync() {
return lastSync; return lastSync;
} }
public void setLastSync(Date lastSync) { public void setLastSync(Date lastSync) {
this.lastSync = lastSync; this.lastSync = lastSync;
} }
public List<SwaggerResource> getResourceList() {
return resourceList;
}
public void setResourceList(List<SwaggerResource> resourceList) {
this.resourceList = resourceList;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
} }

View File

@@ -1,26 +1,29 @@
package com.zyplayer.doc.swagger.framework.configuration; package com.zyplayer.doc.swagger.framework.configuration;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import org.springframework.context.annotation.Import; import com.zyplayer.doc.swagger.framework.filter.ZyplayerProxyFilter;
import org.springframework.context.annotation.Import;
@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = { java.lang.annotation.ElementType.TYPE }) @Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Documented @Target(value = {java.lang.annotation.ElementType.TYPE})
@Import({ SwaggerCommonConfiguration.class, SpringContextUtil.class }) @Documented
public @interface EnableSwaggerMgUi { @Import({SwaggerCommonConfiguration.class, SpringContextUtil.class, ZyplayerProxyFilter.class})
public @interface EnableSwaggerMgUi {
/**
* 是否自动把自身的swagger-resources加进来 /**
* @return 配置 * 是否自动把自身的swagger-resources加进来
*/ *
boolean selfDoc() default true; * @return 配置
*/
/** boolean selfDoc() default true;
* 启动后第一次访问没有数据情况下需要加载进来的swagger-resources地址
* @return swagger-resources地址 /**
*/ * 启动后第一次访问没有数据情况下需要加载进来的swagger-resources地址
String[] defaultResources() default {}; *
} * @return swagger-resources地址
*/
String[] defaultResources() default {};
}

View File

@@ -1,25 +1,25 @@
package com.zyplayer.doc.swagger.framework.configuration; package com.zyplayer.doc.swagger.framework.configuration;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
//@EnableAutoConfiguration //@EnableAutoConfiguration
@ComponentScan(basePackages = { @ComponentScan(basePackages = {
"com.zyplayer.doc.swagger.controller", "com.zyplayer.doc.swagger.controller",
"com.zyplayer.doc.swagger.framework.service", "com.zyplayer.doc.swagger.framework.service",
}) })
public class SwaggerCommonConfiguration { public class SwaggerCommonConfiguration {
// 不再默认开启拦截 // 不再默认开启拦截
// @Autowired // @Autowired
// private MgUiTestFilter mgUiTestFilter; // private ZyplayerApiTestFilter mgUiTestFilter;
// //
// @Bean // @Bean
// public FilterRegistrationBean mockTestFilter() { // public FilterRegistrationBean mockTestFilter() {
// FilterRegistrationBean registration = new FilterRegistrationBean(); // FilterRegistrationBean registration = new FilterRegistrationBean();
// registration.setFilter(mgUiTestFilter); // registration.setFilter(mgUiTestFilter);
// registration.addUrlPatterns("/*"); // registration.addUrlPatterns("/*");
// registration.setName("mgUiTestFilter"); // registration.setName("mgUiTestFilter");
// registration.setOrder(2); // registration.setOrder(2);
// return registration; // return registration;
// } // }
} }

View File

@@ -0,0 +1,8 @@
package com.zyplayer.doc.swagger.framework.constant;
public class Consts {
public static final String ZYPLAYER_PROXY = "/zyplayer-proxy/";
public static final String V2_API_DOCS = "/v2/api-docs";
public static final String SWAGGER_RESOURCES = "/swagger-resources";
}

View File

@@ -19,8 +19,8 @@ import com.zyplayer.doc.swagger.framework.service.MgStorageService;
* 有需要此拦截器的请自行拷贝至自身项目需要使过滤器生效文档不再开启@Component<br> * 有需要此拦截器的请自行拷贝至自身项目需要使过滤器生效文档不再开启@Component<br>
* 判断是否是模拟请求功能需求<br> * 判断是否是模拟请求功能需求<br>
* 很多时候后端定义好了接口但还未实现这时前端已经需要数据调试了这时就需要用到这个过滤器了<br> * 很多时候后端定义好了接口但还未实现这时前端已经需要数据调试了这时就需要用到这个过滤器了<br>
* 在页面上先配置好模拟返回的数据然后在url上加入参数mgUiTestFlag=1<br> * 在页面上先配置好模拟返回的数据然后在url上加入参数zyplayerApiTest=1<br>
* http://192.168.0.249:8082/openApi/case/info?mgUiTestFlag=1<br> * http://192.168.0.249:8082/openApi/case/info?zyplayerApiTest=1<br>
* 本过滤器就直接返回了之前配置的模拟数据而不用等到后端必须把接口实现之后才能调试或者在前端写一大段测试数据<br> * 本过滤器就直接返回了之前配置的模拟数据而不用等到后端必须把接口实现之后才能调试或者在前端写一大段测试数据<br>
* <p> * <p>
* 笔者的公司后端人较少一个需求需要10个接口需求分析完后首先就把接口参数返回值定义好然后一个个的去实现 * 笔者的公司后端人较少一个需求需要10个接口需求分析完后首先就把接口参数返回值定义好然后一个个的去实现
@@ -28,7 +28,7 @@ import com.zyplayer.doc.swagger.framework.service.MgStorageService;
* 而不是一味的催后台把各种锅丢给后端然后玩自己的去了浪费各环节等待时间 * 而不是一味的催后台把各种锅丢给后端然后玩自己的去了浪费各环节等待时间
*/ */
//@Component //@Component
public class MgUiTestFilter implements Filter { public class ZyplayerApiTestFilter implements Filter {
@Autowired @Autowired
private MgStorageService mgStorageService; private MgStorageService mgStorageService;
@@ -41,7 +41,7 @@ public class MgUiTestFilter implements Filter {
@Override @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// 需要使用模拟值返回的标记 // 需要使用模拟值返回的标记
String mockTestFlag = request.getParameter("mgUiTestFlag"); String mockTestFlag = request.getParameter("zyplayerApiTest");
if (!"1".equals(mockTestFlag)) { if (!"1".equals(mockTestFlag)) {
// 未开启直接跳过 // 未开启直接跳过
chain.doFilter(request, response); chain.doFilter(request, response);

View File

@@ -0,0 +1,166 @@
package com.zyplayer.doc.swagger.framework.filter;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.zyplayer.doc.swagger.controller.param.HttpRequestParam;
import com.zyplayer.doc.swagger.controller.vo.SwaggerResourcesInfoVo;
import com.zyplayer.doc.swagger.framework.constant.Consts;
import com.zyplayer.doc.swagger.framework.constant.StorageKeys;
import com.zyplayer.doc.swagger.framework.service.MgStorageService;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.HttpCookie;
import java.util.*;
/**
* 请求代理过滤器
* 使得所有的swagger-ui都可以查看所有的文档目标是文档大一统~
*
* @author 暮光:城中城
* @since 2019年12月16日
*/
@Component
public class ZyplayerProxyFilter implements Filter {
private static final Logger logger = LoggerFactory.getLogger(ZyplayerProxyFilter.class);
@Autowired
private MgStorageService mgStorageService;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
public static void main(String[] args) {
// String requestUrl = "http://192.168.0.249:8082/zyplayer-doc-manage/zyplayer-proxy/1/v2/api-docs";
// int proxyIndex = requestUrl.indexOf(Consts.ZYPLAYER_PROXY);
// if (proxyIndex < 0) {
// return;
// }
// String requestUrlEnd = requestUrl.substring(proxyIndex + Consts.ZYPLAYER_PROXY.length());
// int idIndex = requestUrlEnd.indexOf("/");
// String idStr = requestUrlEnd.substring(0, idIndex);
String resource = "{\"swagger\":\"2.0\",\"host\":\"127.0.0.1:8999\",\"basePath\":\"/\",\"tags\":";
resource = resource.replaceFirst("\"basePath\":\".*?\"", "\"basePath\":\"/xxxxx\"");
System.out.println(resource);
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse servletResponse = (HttpServletResponse) response;
String method = httpServletRequest.getMethod();
String requestUrl = httpServletRequest.getRequestURL().toString();
String bodyStr = IOUtils.toString(httpServletRequest.getInputStream(), "utf-8");
int proxyIndex = requestUrl.indexOf(Consts.ZYPLAYER_PROXY);
if (proxyIndex < 0) {
// 不是拦截接口直接跳过
chain.doFilter(request, response);
return;
}
long startTime = System.currentTimeMillis();
String requestUrlEnd = requestUrl.substring(proxyIndex + Consts.ZYPLAYER_PROXY.length());
int idIndex = requestUrlEnd.indexOf("/");
String proxyUrlEnd = requestUrlEnd.substring(idIndex);
String idStr = requestUrlEnd.substring(0, idIndex);
Integer docId = Integer.valueOf(idStr);
String swaggerResourcesStr = mgStorageService.get(StorageKeys.SWAGGER_RESOURCES_LIST);
List<SwaggerResourcesInfoVo> resourcesInfoVoList = JSON.parseArray(swaggerResourcesStr, SwaggerResourcesInfoVo.class);
if (resourcesInfoVoList == null || resourcesInfoVoList.isEmpty()) {
this.send(startTime, requestUrl, servletResponse, "文档为空,请刷新重试");
return;
}
// 找到真正被代理的对象
String proxyUrl = null;
for (SwaggerResourcesInfoVo swaggerResourcesInfoVo : resourcesInfoVoList) {
if (Objects.equals(swaggerResourcesInfoVo.getId(), docId)) {
proxyUrl = swaggerResourcesInfoVo.getUrl();
break;
}
}
if (StringUtils.isBlank(proxyUrl)) {
this.send(startTime, requestUrl, servletResponse, "未找到对应文档,请刷新重试");
return;
}
// 组装URL
proxyUrl = proxyUrl.replace(Consts.SWAGGER_RESOURCES, proxyUrlEnd);
HttpRequestParam param = new HttpRequestParam();
param.setUrl(proxyUrl);
param.setMethod(method);
HttpRequest httpRequest = param.createRequest();
// 组装参数
Map<String, String[]> parameterMap = httpServletRequest.getParameterMap();
if (parameterMap != null && parameterMap.size() > 0) {
for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
httpRequest.form(entry.getKey(), entry.getValue());
}
}
// 请求体
if (StringUtils.isNotBlank(bodyStr)) {
httpRequest.body(bodyStr);
}
// header
Enumeration<String> headerNames = httpServletRequest.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String element = headerNames.nextElement();
httpRequest.header(element, httpServletRequest.getHeader(element));
}
}
// cookies
Cookie[] cookies = httpServletRequest.getCookies();
if (cookies != null && cookies.length > 0) {
List<HttpCookie> httpCookieList = new LinkedList<>();
for (int i = 0; i < cookies.length; i++) {
HttpCookie httpCookie = new HttpCookie(cookies[i].getName(), cookies[i].getValue());
httpCookieList.add(httpCookie);
}
httpRequest.cookie(httpCookieList.toArray(new HttpCookie[]{}));
}
String resultStr = httpRequest.execute().body();
if (proxyUrl.indexOf(Consts.V2_API_DOCS) >= 0) {
// "basePath":"/" 替换成 "basePath":"/zyplayer-doc-manage/zyplayer-proxy/2/",使其走代理接口
ServletContext servletContext = httpServletRequest.getServletContext();
Object ctx = servletContext.getAttribute("ctx");
ctx = (ctx + Consts.ZYPLAYER_PROXY + idStr).replaceAll("//", "/");
resultStr = resultStr.replaceFirst("\"basePath\":\".*?\"", "\"basePath\":\"" + ctx + "\"");
// 替换host为当前项目的
String requestUrlHost = requestUrl.substring(0, proxyIndex + Consts.ZYPLAYER_PROXY.length());
requestUrlHost = requestUrlHost.replace("http://", "");
requestUrlHost = requestUrlHost.substring(0, requestUrlHost.indexOf("/"));
resultStr = resultStr.replaceFirst("\"host\":\".*?\"", "\"host\":\"" + requestUrlHost + "\"");
}
this.send(startTime, proxyUrl, servletResponse, resultStr);
}
public void send(Long startTime, String requestUrl, HttpServletResponse response, String result) throws IOException {
response.setStatus(200);
// response.setContentType("application/json");
response.addHeader("Access-Control-Allow-Origin", "*");
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
response.setHeader("Cache-Control", "no-cache, must-revalidate");
response.getWriter().write(result);
Long totalTime = System.currentTimeMillis() - startTime;
logger.error("代理请求结束,总耗时:{}msURI{}", totalTime, requestUrl);
}
}

View File

@@ -300,8 +300,8 @@
<tr> <tr>
<td class="info">功能说明</td> <td class="info">功能说明</td>
<td> <td>
访问接口时增加参数:mgUiTestFlag=1即可返回下面提交的模拟返回值<br/> 访问接口时增加参数:zyplayerApiTest=1即可返回下面提交的模拟返回值<br/>
需要被访问项目增加<a href="https://gitee.com/zyplayer/zyplayer-doc/blob/master/zyplayer-doc-swagger/src/main/java/com/zyplayer/doc/swagger/framework/filter/MgUiTestFilter.java" target="_blank"> MgUiTestFilter.java</a> 需要被访问项目增加<a href="https://gitee.com/zyplayer/zyplayer-doc/blob/master/zyplayer-doc-swagger/src/main/java/com/zyplayer/doc/swagger/framework/filter/ZyplayerApiTestFilter.java" target="_blank"> ZyplayerApiTestFilter.java</a>
过滤器才能使用,里面逻辑很简单,一看就懂~ 过滤器才能使用,里面逻辑很简单,一看就懂~
</td> </td>
</tr> </tr>

View File

@@ -334,8 +334,8 @@ $("#apiPathTree").on("click", ".show-doc", function(){
$("#postUrlInput").val(data.domain + docUrl); $("#postUrlInput").val(data.domain + docUrl);
// 处理模拟返回 // 处理模拟返回
$("#simulationResultUrl").text(docUrl); $("#simulationResultUrl").text(docUrl);
$("#simulationResultUrlTest").text(data.domain + docUrl + "?mgUiTestFlag=1"); $("#simulationResultUrlTest").text(data.domain + docUrl + "?zyplayerApiTest=1");
$("#simulationResultUrlTest").attr("href", data.domain + docUrl + "?mgUiTestFlag=1"); $("#simulationResultUrlTest").attr("href", data.domain + docUrl + "?zyplayerApiTest=1");
$("#simulationResultText").val(""); $("#simulationResultText").val("");
getStorage('p-simulation-response-' + docUrl, function(data){ getStorage('p-simulation-response-' + docUrl, function(data){
var resultText = getNotEmptyStr(data); var resultText = getNotEmptyStr(data);