debug参数展示,基本功能开发

This commit is contained in:
暮光:城中城
2018-12-13 00:03:28 +08:00
parent a9c86940e2
commit 72d7f64cd6
12 changed files with 1170 additions and 1029 deletions

View File

@@ -1,52 +1,64 @@
package com.zyplayer.doc.manage.framework.config;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.format.datetime.DateFormatter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
@Component
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
format.setLenient(true);
DateFormatter dateFormatter = new DateFormatter();
dateFormatter.setPattern("yyyy-MM-dd HH:mm:ss");
dateFormatter.setLenient(true);
registry.addFormatter(dateFormatter);
}
@Bean
public FastJsonHttpMessageConverter fastJsonHttpMessageConverter() {
FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
List<MediaType> supportedMediaTypes = new ArrayList<>();
supportedMediaTypes.add(new MediaType("application", "json", Charset.forName("UTF-8")));
fastJsonHttpMessageConverter.setSupportedMediaTypes(supportedMediaTypes);
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteDateUseDateFormat);
fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig);
return fastJsonHttpMessageConverter;
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(0, fastJsonHttpMessageConverter());
}
}
package com.zyplayer.doc.manage.framework.config;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import com.zyplayer.doc.manage.framework.interceptor.RequestInfoInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.format.datetime.DateFormatter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
@Component
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
RequestInfoInterceptor requestInfoInterceptor;
@Override
public void addFormatters(FormatterRegistry registry) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
format.setLenient(true);
DateFormatter dateFormatter = new DateFormatter();
dateFormatter.setPattern("yyyy-MM-dd HH:mm:ss");
dateFormatter.setLenient(true);
registry.addFormatter(dateFormatter);
}
@Bean
public FastJsonHttpMessageConverter fastJsonHttpMessageConverter() {
FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
List<MediaType> supportedMediaTypes = new ArrayList<>();
supportedMediaTypes.add(new MediaType("application", "json", Charset.forName("UTF-8")));
fastJsonHttpMessageConverter.setSupportedMediaTypes(supportedMediaTypes);
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteDateUseDateFormat);
fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig);
return fastJsonHttpMessageConverter;
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(0, fastJsonHttpMessageConverter());
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(requestInfoInterceptor).excludePathPatterns("/**/*.js", "/**/*.css", "/**/*.png",
"/**/*.gif", "/**/*.jpg", "/**/*.jpeg", "/**/fonts/*");
}
}

View File

@@ -1,33 +1,107 @@
/*
Navicat Premium Data Transfer
Source Server : 127.0.0.1
Source Server Type : MySQL
Source Server Version : 50624
Source Host : 127.0.0.1:3306
Source Schema : zyplayer-doc-manage
Target Server Type : MySQL
Target Server Version : 50624
File Encoding : 65001
Date: 27/11/2018 20:19:45
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for zyplayer_storage
-- ----------------------------
DROP TABLE IF EXISTS `zyplayer_storage`;
CREATE TABLE `zyplayer_storage` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`doc_key` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`doc_value` varchar(2048) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`creation_time` datetime NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `key`(`doc_key`) USING BTREE COMMENT 'key唯一索引'
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
SET FOREIGN_KEY_CHECKS = 1;
/*
Navicat Premium Data Transfer
Source Server : 127.0.0.1
Source Server Type : MySQL
Source Server Version : 50624
Source Host : 127.0.0.1:3306
Source Schema : zyplayer-doc-manage
Target Server Type : MySQL
Target Server Version : 50624
File Encoding : 65001
Date: 12/12/2018 14:29:09
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for auth_info
-- ----------------------------
DROP TABLE IF EXISTS `auth_info`;
CREATE TABLE `auth_info` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键自增ID',
`auth_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '权限名',
`auth_desc` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '权限说明',
`can_edit` tinyint(4) NULL DEFAULT 1 COMMENT '是否可编辑 0=否 1=是',
`create_uid` bigint(20) NULL DEFAULT NULL COMMENT '创建人',
`creation_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of auth_info
-- ----------------------------
INSERT INTO `auth_info` VALUES (1, 'DOC_ALL', '文档查看权', 0, 1, '2018-12-01 11:40:42');
INSERT INTO `auth_info` VALUES (2, 'AUTH_MANAGE', '权限管理权', 0, 1, '2018-12-01 11:40:42');
INSERT INTO `auth_info` VALUES (3, 'AUTH_ASSIGN', '权限分配权', 0, 1, '2018-12-01 11:40:42');
INSERT INTO `auth_info` VALUES (4, 'USER_MANAGE', '用户管理权', 0, 1, '2018-12-01 11:40:42');
-- ----------------------------
-- Table structure for user_auth
-- ----------------------------
DROP TABLE IF EXISTS `user_auth`;
CREATE TABLE `user_auth` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键自增ID',
`user_id` bigint(20) NULL DEFAULT NULL COMMENT '用户ID',
`auth_id` bigint(20) NULL DEFAULT NULL COMMENT '权限ID',
`create_uid` bigint(20) NULL DEFAULT NULL COMMENT '创建用户ID',
`update_uid` bigint(20) NULL DEFAULT NULL COMMENT '更新用户ID',
`del_flag` tinyint(4) NULL DEFAULT 0 COMMENT '是否删除 0=未删除 1=已删除',
`creation_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of user_auth
-- ----------------------------
INSERT INTO `user_auth` VALUES (1, 1, 1, 1, 1, 0, '2018-12-01 11:41:13', '2018-12-01 11:41:13');
INSERT INTO `user_auth` VALUES (2, 1, 2, 1, 1, 0, '2018-12-01 11:41:13', '2018-12-01 11:41:13');
INSERT INTO `user_auth` VALUES (3, 1, 3, 1, 1, 0, '2018-12-01 11:41:13', '2018-12-01 11:41:13');
INSERT INTO `user_auth` VALUES (4, 1, 4, 1, 1, 0, '2018-12-01 11:41:13', '2018-12-01 11:41:13');
-- ----------------------------
-- Table structure for user_info
-- ----------------------------
DROP TABLE IF EXISTS `user_info`;
CREATE TABLE `user_info` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键自增ID',
`user_no` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户编号,用于登录等',
`password` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '密码',
`user_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名',
`email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮箱',
`avatar` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '头像',
`del_flag` tinyint(4) NULL DEFAULT 0 COMMENT '是否删除 0=未删除 1=已删除',
`create_uid` bigint(20) NULL DEFAULT NULL COMMENT '创建人',
`creation_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of user_info
-- ----------------------------
INSERT INTO `user_info` VALUES (1, 'zyplayer', 'e10adc3949ba59abbe56e057f20f883e', '暮光:城中城', '806783409@qq.com', NULL, 0, NULL, '2018-12-01 11:37:39', NULL);
-- ----------------------------
-- Table structure for zyplayer_storage
-- ----------------------------
DROP TABLE IF EXISTS `zyplayer_storage`;
CREATE TABLE `zyplayer_storage` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`doc_key` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`doc_value` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL,
`creation_time` datetime(0) NULL DEFAULT NULL,
`update_time` datetime(0) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `key`(`doc_key`) USING BTREE COMMENT 'key唯一索引'
) ENGINE = InnoDB AUTO_INCREMENT = 16 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of zyplayer_storage
-- ----------------------------
SET FOREIGN_KEY_CHECKS = 1;

View File

@@ -1,286 +1,330 @@
package com.zyplayer.doc.swagger.controller;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.zyplayer.doc.core.json.DocResponseJson;
import com.zyplayer.doc.core.json.ResponseJson;
import com.zyplayer.doc.swagger.framework.configuration.EnableSwaggerMgUi;
import com.zyplayer.doc.swagger.framework.configuration.SpringContextUtil;
import com.zyplayer.doc.swagger.framework.constant.StorageKeys;
import com.zyplayer.doc.swagger.framework.service.MgStorageService;
import cn.hutool.http.HttpRequest;
import springfox.documentation.swagger.web.SwaggerResource;
/**
* 文档控制器
*
* @author 暮光:城中城
* @since 2018年8月21日
*/
@RestController
@RequestMapping("/swagger-mg-ui/document")
public class MgDocumentController {
private static Logger logger = LoggerFactory.getLogger(MgDocumentController.class);
@Autowired
private MgStorageService storageService;
/**
* 获取所有的文档地址
*
* @author 暮光:城中城
* @since 2018年8月21日
* @return 文档内容
*/
@ResponseBody
@PostMapping(value = "/resourcesList")
public ResponseJson<Set<String>> resourcesList() {
String swaggerResourcesStr = storageService.get(StorageKeys.SWAGGER_RESOURCES_LIST);
Set<String> resourcesSet = new HashSet<>();
if (StringUtils.isNotBlank(swaggerResourcesStr)) {
List<String> resourcesList = JSON.parseArray(swaggerResourcesStr, String.class);
resourcesSet.addAll(resourcesList);
}
return DocResponseJson.ok(resourcesSet);
}
/**
* 获取所有的文档
* @author 暮光:城中城
* @since 2018年8月21日
* @param request request
* @param response response
*/
@ResponseBody
@PostMapping(value = "/docs")
public void docs(HttpServletRequest request, HttpServletResponse response) {
boolean needRestorage = true;
String choiseDocList = request.getParameter("choiseDocList");
// 转成set防止重复
Set<String> resourcesSet = new HashSet<>();
Set<String> swaggerDocsDeleteSet = new HashSet<>();
if (StringUtils.isNotBlank(choiseDocList)) {
needRestorage = false;// 选择的则不再存入
resourcesSet.addAll(Arrays.asList(choiseDocList.split(",")));
} else {
String swaggerResourcesStr = storageService.get(StorageKeys.SWAGGER_RESOURCES_LIST);
String swaggerDocsDeleteStr = storageService.get(StorageKeys.SWAGGER_DOCS_DELETE_LIST);
if (StringUtils.isNotBlank(swaggerResourcesStr)) {
List<String> resourcesList = JSON.parseArray(swaggerResourcesStr, String.class);
resourcesSet.addAll(resourcesList);
} else {
// 默认加上自身的文档
String serverPath = "http://" + request.getServerName() // 服务器地址
+ ":" + request.getServerPort() // 端口号
+ request.getContextPath();
// 是否加入自身的文档
Object object = SpringContextUtil.getBeanWithAnnotation(EnableSwaggerMgUi.class);
EnableSwaggerMgUi swaggerMgUi = object.getClass().getAnnotation(EnableSwaggerMgUi.class);
if (swaggerMgUi == null) {
// 直接通过superclass去找
Class<?> superclass = object.getClass().getSuperclass();
if (superclass != null) {
swaggerMgUi = superclass.getAnnotation(EnableSwaggerMgUi.class);
}
}
if (swaggerMgUi == null) {
// 再通过AopUtils去找
Class<?> targetClass = AopUtils.getTargetClass(object);
if (targetClass != null) {
swaggerMgUi = targetClass.getAnnotation(EnableSwaggerMgUi.class);
}
}
if (swaggerMgUi == null) {
resourcesSet.add(serverPath + "/swagger-resources");
} else {
if (swaggerMgUi.selfDoc()) {
resourcesSet.add(serverPath + "/swagger-resources");
}
// 启动后第一次访问没有数据情况下需要加载进来的swagger-resources地址
String[] defaultResources = swaggerMgUi.defaultResources();
if (defaultResources != null && defaultResources.length > 0) {
resourcesSet.addAll(Arrays.asList(defaultResources));
}
}
}
if (StringUtils.isNotBlank(swaggerDocsDeleteStr)) {
List<String> swaggerDocsDeleteList = JSON.parseArray(swaggerDocsDeleteStr, String.class);
swaggerDocsDeleteSet.addAll(swaggerDocsDeleteList);
}
}
List<Map<String, Object>> swaggerResourceList = new LinkedList<>();
List<String> swaggerResourceStrList = new LinkedList<>();
for (String resourcesUrl : resourcesSet) {
List<SwaggerResource> resourceList = null;
try {
String resourcesStr = HttpRequest.get(resourcesUrl).timeout(3000).execute().body();
resourceList = JSON.parseArray(resourcesStr, SwaggerResource.class);
} catch (Exception e) {
logger.error("获取文档失败:{}{}", resourcesUrl, e.getMessage());
}
if (resourceList == null || resourceList.isEmpty()) {
continue;
}
resourcesUrl = resourcesUrl.substring(0, resourcesUrl.lastIndexOf("/") + 1);
for (SwaggerResource resource : resourceList) {
String location = resource.getLocation();
// 最后一个斜杠在resourcesUrl中已经加上替换掉后面的防止两根斜杠
location = location.startsWith("/") ? location.replaceFirst("/", "") : location;
if (location.indexOf("?") >= 0) {
try {
String encode = URLEncoder.encode(resource.getName(), "utf-8");
location = location.substring(0, location.lastIndexOf("?")) + "?group=" + encode;
} catch (Exception e) {
e.printStackTrace();
}
}
location = resourcesUrl + location;
// 已删除的则不处理
if (swaggerDocsDeleteSet.contains(location)) {
continue;
}
try {
String resourceStr = HttpRequest.get(location).timeout(3000).execute().body();
Map<String, Object> jsonObject = JSON.parseObject(resourceStr, new TypeReference<HashMap<String, Object>>(){});
if (jsonObject == null || jsonObject.isEmpty()) {
continue;
}
jsonObject.put("fullUrl", location);
swaggerResourceList.add(jsonObject);
// 本来想转对象之后赋值但是在此转成JSON字符串之后格式就不是之前的了所有不能转。。。
// 直接字符串拼接,坑真多~
resourceStr = resourceStr.substring(1);
resourceStr = "{\"fullUrl\":\"" + location + "\","
+ "\"domainUrl\":\"" + resourcesUrl + "\","
+ resourceStr;
swaggerResourceStrList.add(resourceStr);
} catch (Exception e) {
logger.error("获取文档失败:{}{}", location, e.getMessage());
}
}
}
if (needRestorage) {
storageService.put(StorageKeys.SWAGGER_RESOURCES_LIST, JSON.toJSONString(resourcesSet));
}
// 用默认的json解析要内存溢出解析不了JSONObject、、就只有这样写了~
DocResponseJson.ok(swaggerResourceStrList).send(response);
}
/**
* 增加/swagger-resources地址
*
* @author 暮光:城中城
* @since 2018年8月21日
* @param resourcesUrl swagger-resources地址
* @return 添加结果
*/
@PostMapping(value = "/addSwaggerResources")
public ResponseJson<Object> addSwaggerResources(String resourcesUrl) {
String swaggerResourcesStr = storageService.get(StorageKeys.SWAGGER_RESOURCES_LIST);
String swaggerDocsDeleteStr = storageService.get(StorageKeys.SWAGGER_DOCS_DELETE_LIST);
Set<String> swaggerDocsDeleteSet = new HashSet<>();
if (StringUtils.isNotBlank(swaggerDocsDeleteStr)) {
List<String> swaggerDocsDeleteList = JSON.parseArray(swaggerDocsDeleteStr, String.class);
swaggerDocsDeleteSet.addAll(swaggerDocsDeleteList);
}
// 转成set防止重复
Set<String> resourcesSet = new HashSet<>();
if (StringUtils.isNotBlank(swaggerResourcesStr)) {
List<String> resourcesList = JSON.parseArray(swaggerResourcesStr, String.class);
resourcesSet.addAll(resourcesList);
}
String resourcesStr = null;
try {
// resourcesStr = HttpRequest.get(resourcesUrl).timeout(3000).execute().body();
// List<SwaggerResource> resourceList = JSON.parseArray(resourcesStr, SwaggerResource.class);
// if (resourceList == null || resourceList.isEmpty()) {
// return DocResponseJson.warn("该地址未找到文档");
// }
// // 重新加入的时候把之前的已删除的回恢复
// String resourcesDomain = resourcesUrl.substring(0, resourcesUrl.lastIndexOf("/") + 1);
// for (SwaggerResource swaggerResource : resourceList) {
// String location = swaggerResource.getLocation();
// // 最后一个斜杠在resourcesUrl中已经加上替换掉后面的防止两根斜杠
// location = location.startsWith("/") ? location.replaceFirst("/", "") : location;
// if (location.indexOf("?") >= 0) {
// try {
// String encode = URLEncoder.encode(swaggerResource.getName(), "utf-8");
// location = location.substring(0, location.lastIndexOf("?")) + "?group=" + encode;
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
// location = resourcesDomain + location;
// swaggerDocsDeleteSet.remove(location);
// }
resourcesSet.add(resourcesUrl);
} catch (Exception e) {
// 暂不想支持直接添加地址
// try {
// SwaggerLocationVo swaggerLocationVo = JSON.parseObject(resourcesStr, SwaggerLocationVo.class);
// if (StringUtils.isNotBlank(swaggerLocationVo.getSwagger())) {
// Set<String> locationSet = new HashSet<>();
// if (StringUtils.isNotBlank(swaggerLocationListStr)) {
// String swaggerLocationListStr = storageService.get(StorageKeys.SWAGGER_LOCATION_LIST);
// List<String> locationList = JSON.parseArray(swaggerLocationListStr, String.class);
// locationSet.addAll(locationList);
// storageService.put(StorageKeys.SWAGGER_LOCATION_LIST, JSON.toJSONString(locationSet));
// }
// } else {
// return DocResponseJson.warn("该地址查找文档失败");
// }
// } catch (Exception e2) {
logger.error("获取文档失败:{}{}", resourcesUrl, e.getMessage());
return DocResponseJson.warn("该地址查找文档失败");
// }
}
storageService.put(StorageKeys.SWAGGER_RESOURCES_LIST, JSON.toJSONString(resourcesSet));
storageService.put(StorageKeys.SWAGGER_DOCS_DELETE_LIST, JSON.toJSONString(swaggerDocsDeleteSet));
return DocResponseJson.ok();
}
/**
* 删除/v2/api-docs
*
* @author 暮光:城中城
* @since 2018年8月21日
* @param docUrl 文档地址
* @return 删除结果
*/
@PostMapping(value = "/deleteSwaggerDoc")
public ResponseJson<Object> deleteSwaggerDoc(String docUrl) {
String swaggerDocsDeleteStr = storageService.get(StorageKeys.SWAGGER_DOCS_DELETE_LIST);
Set<String> swaggerDocsDeleteSet = new HashSet<>();
if (StringUtils.isNotBlank(swaggerDocsDeleteStr)) {
List<String> swaggerDocsDeleteList = JSON.parseArray(swaggerDocsDeleteStr, String.class);
swaggerDocsDeleteSet.addAll(swaggerDocsDeleteList);
}
swaggerDocsDeleteSet.add(docUrl);
storageService.put(StorageKeys.SWAGGER_DOCS_DELETE_LIST, JSON.toJSONString(swaggerDocsDeleteSet));
return DocResponseJson.ok();
}
}
package com.zyplayer.doc.swagger.controller;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.zyplayer.doc.core.json.DocResponseJson;
import com.zyplayer.doc.core.json.ResponseJson;
import com.zyplayer.doc.swagger.controller.vo.SwaggerResourcesInfoVo;
import com.zyplayer.doc.swagger.framework.configuration.EnableSwaggerMgUi;
import com.zyplayer.doc.swagger.framework.configuration.SpringContextUtil;
import com.zyplayer.doc.swagger.framework.constant.StorageKeys;
import com.zyplayer.doc.swagger.framework.service.MgStorageService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
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.SwaggerResource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.*;
/**
* 文档控制器
*
* @author 暮光:城中城
* @since 2018年8月21日
*/
@RestController
@RequestMapping("/swagger-mg-ui/document")
public class MgDocumentController {
private static Logger logger = LoggerFactory.getLogger(MgDocumentController.class);
@Autowired
private MgStorageService storageService;
/**
* 获取所有的文档地址
*
* @author 暮光:城中城
* @since 2018年8月21日
* @return 文档内容
*/
@ResponseBody
@PostMapping(value = "/resourcesList")
public ResponseJson<Set<SwaggerResourcesInfoVo>> resourcesList() {
String swaggerResourcesStr = storageService.get(StorageKeys.SWAGGER_RESOURCES_LIST);
Set<SwaggerResourcesInfoVo> resourcesSet = new HashSet<>();
if (StringUtils.isNotBlank(swaggerResourcesStr)) {
List<SwaggerResourcesInfoVo> resourcesList = JSON.parseArray(swaggerResourcesStr, SwaggerResourcesInfoVo.class);
resourcesSet.addAll(resourcesList);
}
return DocResponseJson.ok(resourcesSet);
}
/**
* 获取所有的文档
* @author 暮光:城中城
* @since 2018年8月21日
* @param request request
* @param response response
*/
@ResponseBody
@PostMapping(value = "/docs")
public void docs(HttpServletRequest request, HttpServletResponse response) {
boolean needRestorage = true;
String choiseDocList = request.getParameter("choiseDocList");
// 转成set防止重复
Set<SwaggerResourcesInfoVo> resourcesSet = new HashSet<>();
Set<String> swaggerDocsDeleteSet = new HashSet<>();
if (StringUtils.isNotBlank(choiseDocList)) {
needRestorage = false;// 选择的则不再存入
for (String url : choiseDocList.split(",")) {
resourcesSet.add(new SwaggerResourcesInfoVo(url));
}
} else {
String swaggerResourcesStr = storageService.get(StorageKeys.SWAGGER_RESOURCES_LIST);
String swaggerDocsDeleteStr = storageService.get(StorageKeys.SWAGGER_DOCS_DELETE_LIST);
if (StringUtils.isNotBlank(swaggerResourcesStr)) {
List<SwaggerResourcesInfoVo> resourcesList = JSON.parseArray(swaggerResourcesStr, SwaggerResourcesInfoVo.class);
resourcesSet.addAll(resourcesList);
} else {
// 默认加上自身的文档
String serverPath = "http://" + request.getServerName() // 服务器地址
+ ":" + request.getServerPort() // 端口号
+ request.getContextPath();
// 是否加入自身的文档
Object object = SpringContextUtil.getBeanWithAnnotation(EnableSwaggerMgUi.class);
EnableSwaggerMgUi swaggerMgUi = object.getClass().getAnnotation(EnableSwaggerMgUi.class);
if (swaggerMgUi == null) {
// 直接通过superclass去找
Class<?> superclass = object.getClass().getSuperclass();
if (superclass != null) {
swaggerMgUi = superclass.getAnnotation(EnableSwaggerMgUi.class);
}
}
if (swaggerMgUi == null) {
// 再通过AopUtils去找
Class<?> targetClass = AopUtils.getTargetClass(object);
if (targetClass != null) {
swaggerMgUi = targetClass.getAnnotation(EnableSwaggerMgUi.class);
}
}
if (swaggerMgUi == null) {
resourcesSet.add(new SwaggerResourcesInfoVo(serverPath + "/swagger-resources"));
} else {
if (swaggerMgUi.selfDoc()) {
resourcesSet.add(new SwaggerResourcesInfoVo(serverPath + "/swagger-resources"));
}
// 启动后第一次访问没有数据情况下需要加载进来的swagger-resources地址
String[] defaultResources = swaggerMgUi.defaultResources();
if (defaultResources != null && defaultResources.length > 0) {
for (String url : defaultResources) {
resourcesSet.add(new SwaggerResourcesInfoVo(url));
}
}
}
}
if (StringUtils.isNotBlank(swaggerDocsDeleteStr)) {
List<String> swaggerDocsDeleteList = JSON.parseArray(swaggerDocsDeleteStr, String.class);
swaggerDocsDeleteSet.addAll(swaggerDocsDeleteList);
}
}
List<Map<String, Object>> swaggerResourceList = new LinkedList<>();
List<String> swaggerResourceStrList = new LinkedList<>();
for (SwaggerResourcesInfoVo resourcesInfoVo : resourcesSet) {
List<SwaggerResource> resourceList = null;
String resourcesUrl = resourcesInfoVo.getUrl();
try {
String resourcesStr = HttpRequest.get(resourcesUrl).timeout(3000).execute().body();
resourceList = JSON.parseArray(resourcesStr, SwaggerResource.class);
} catch (Exception e) {
logger.error("获取文档失败:{}{}", resourcesUrl, e.getMessage());
}
if (resourceList == null || resourceList.isEmpty()) {
continue;
}
resourcesUrl = resourcesUrl.substring(0, resourcesUrl.lastIndexOf("/") + 1);
for (SwaggerResource resource : resourceList) {
String location = resource.getLocation();
// 最后一个斜杠在resourcesUrl中已经加上替换掉后面的防止两根斜杠
location = location.startsWith("/") ? location.replaceFirst("/", "") : location;
if (location.indexOf("?") >= 0) {
try {
String encode = URLEncoder.encode(resource.getName(), "utf-8");
location = location.substring(0, location.lastIndexOf("?")) + "?group=" + encode;
} catch (Exception e) {
e.printStackTrace();
}
}
location = resourcesUrl + location;
// 已删除的则不处理
if (swaggerDocsDeleteSet.contains(location)) {
continue;
}
try {
String resourceStr = HttpRequest.get(location).timeout(3000).execute().body();
Map<String, Object> jsonObject = JSON.parseObject(resourceStr, new TypeReference<HashMap<String, Object>>(){});
if (jsonObject == null || jsonObject.isEmpty()) {
continue;
}
jsonObject.put("fullUrl", location);
swaggerResourceList.add(jsonObject);
// 本来想转对象之后赋值但是在此转成JSON字符串之后格式就不是之前的了所有不能转。。。
// 直接字符串拼接,坑真多~
resourceStr = resourceStr.substring(1);
resourceStr = "{\"fullUrl\":\"" + location + "\","
+ "\"domainUrl\":\"" + resourcesUrl + "\","
+ resourceStr;
swaggerResourceStrList.add(resourceStr);
} catch (Exception e) {
logger.error("获取文档失败:{}{}", location, e.getMessage());
}
}
}
if (needRestorage) {
storageService.put(StorageKeys.SWAGGER_RESOURCES_LIST, JSON.toJSONString(resourcesSet));
}
// 用默认的json解析要内存溢出解析不了JSONObject、、就只有这样写了~
DocResponseJson.ok(swaggerResourceStrList).send(response);
}
/**
* 增加/swagger-resources地址
*
* @author 暮光:城中城
* @since 2018年8月21日
* @param resourcesUrl swagger-resources地址
* @return 添加结果
*/
@PostMapping(value = "/addSwaggerResources")
public ResponseJson<Object> addSwaggerResources(String resourcesUrl) {
String swaggerResourcesStr = storageService.get(StorageKeys.SWAGGER_RESOURCES_LIST);
String swaggerDocsDeleteStr = storageService.get(StorageKeys.SWAGGER_DOCS_DELETE_LIST);
Set<String> swaggerDocsDeleteSet = new HashSet<>();
if (StringUtils.isNotBlank(swaggerDocsDeleteStr)) {
List<String> swaggerDocsDeleteList = JSON.parseArray(swaggerDocsDeleteStr, String.class);
swaggerDocsDeleteSet.addAll(swaggerDocsDeleteList);
}
// 转成set防止重复
Set<SwaggerResourcesInfoVo> resourcesSet = new HashSet<>();
if (StringUtils.isNotBlank(swaggerResourcesStr)) {
List<SwaggerResourcesInfoVo> resourcesList = JSON.parseArray(swaggerResourcesStr, SwaggerResourcesInfoVo.class);
resourcesSet.addAll(resourcesList);
}
try {
String resourcesStr = HttpRequest.get(resourcesUrl).timeout(3000).execute().body();
List<SwaggerResource> resourceList = JSON.parseArray(resourcesStr, SwaggerResource.class);
if (resourceList == null || resourceList.isEmpty()) {
return DocResponseJson.warn("该地址未找到文档");
}
// 重新加入的时候把之前的已删除的回恢复
String resourcesDomain = resourcesUrl.substring(0, resourcesUrl.lastIndexOf("/") + 1);
for (SwaggerResource swaggerResource : resourceList) {
String location = swaggerResource.getLocation();
// 最后一个斜杠在resourcesUrl中已经加上替换掉后面的防止两根斜杠
location = location.startsWith("/") ? location.replaceFirst("/", "") : location;
if (location.indexOf("?") >= 0) {
try {
String encode = URLEncoder.encode(swaggerResource.getName(), "utf-8");
location = location.substring(0, location.lastIndexOf("?")) + "?group=" + encode;
} catch (Exception e) {
e.printStackTrace();
}
}
location = resourcesDomain + location;
swaggerDocsDeleteSet.remove(location);
}
resourcesSet.add(new SwaggerResourcesInfoVo(resourcesUrl));
} catch (Exception e) {
// 暂不想支持直接添加地址
// try {
// SwaggerLocationVo swaggerLocationVo = JSON.parseObject(resourcesStr, SwaggerLocationVo.class);
// if (StringUtils.isNotBlank(swaggerLocationVo.getSwagger())) {
// Set<String> locationSet = new HashSet<>();
// if (StringUtils.isNotBlank(swaggerLocationListStr)) {
// String swaggerLocationListStr = storageService.get(StorageKeys.SWAGGER_LOCATION_LIST);
// List<String> locationList = JSON.parseArray(swaggerLocationListStr, String.class);
// locationSet.addAll(locationList);
// storageService.put(StorageKeys.SWAGGER_LOCATION_LIST, JSON.toJSONString(locationSet));
// }
// } else {
// return DocResponseJson.warn("该地址查找文档失败");
// }
// } catch (Exception e2) {
logger.error("获取文档失败:{}{}", resourcesUrl, e.getMessage());
return DocResponseJson.warn("该地址查找文档失败");
// }
}
storageService.put(StorageKeys.SWAGGER_RESOURCES_LIST, JSON.toJSONString(resourcesSet));
storageService.put(StorageKeys.SWAGGER_DOCS_DELETE_LIST, JSON.toJSONString(swaggerDocsDeleteSet));
return DocResponseJson.ok();
}
/**
* 增加/swagger-resources地址
*
* @author 暮光:城中城
* @since 2018年8月21日
* @param resourcesUrl swagger-resources地址
* @return 添加结果
*/
@PostMapping(value = "/syncDocData")
public ResponseJson<Object> syncDocData(String resourcesUrl) {
String swaggerResourcesStr = storageService.get(StorageKeys.SWAGGER_RESOURCES_LIST);
// 转成set防止重复
Set<SwaggerResourcesInfoVo> resourcesSet = new HashSet<>();
if (StringUtils.isNotBlank(swaggerResourcesStr)) {
List<SwaggerResourcesInfoVo> resourcesList = JSON.parseArray(swaggerResourcesStr, SwaggerResourcesInfoVo.class);
resourcesSet.addAll(resourcesList);
}
try {
String resourcesStr = HttpRequest.get(resourcesUrl).timeout(3000).execute().body();
List<SwaggerResource> resourceList = JSON.parseArray(resourcesStr, SwaggerResource.class);
if (resourceList == null || resourceList.isEmpty()) {
return DocResponseJson.warn("该地址未找到文档");
}
// 重新加入的时候把之前的已删除的回恢复
String resourcesDomain = resourcesUrl.substring(0, resourcesUrl.lastIndexOf("/") + 1);
for (SwaggerResource swaggerResource : resourceList) {
String location = swaggerResource.getLocation();
// 最后一个斜杠在resourcesUrl中已经加上替换掉后面的防止两根斜杠
location = location.startsWith("/") ? location.replaceFirst("/", "") : location;
if (location.indexOf("?") >= 0) {
try {
String encode = URLEncoder.encode(swaggerResource.getName(), "utf-8");
location = location.substring(0, location.lastIndexOf("?")) + "?group=" + encode;
} catch (Exception e) {
e.printStackTrace();
}
}
location = resourcesDomain + location;
}
resourcesSet.add(new SwaggerResourcesInfoVo(resourcesUrl));
} catch (Exception e) {
logger.error("获取文档失败:{}{}", resourcesUrl, e.getMessage());
return DocResponseJson.warn("该地址查找文档失败");
}
storageService.put(StorageKeys.SWAGGER_RESOURCES_LIST, JSON.toJSONString(resourcesSet));
return DocResponseJson.ok();
}
/**
* 删除/v2/api-docs
*
* @author 暮光:城中城
* @since 2018年8月21日
* @param docUrl 文档地址
* @return 删除结果
*/
@PostMapping(value = "/deleteSwaggerDoc")
public ResponseJson<Object> deleteSwaggerDoc(String docUrl) {
String swaggerDocsDeleteStr = storageService.get(StorageKeys.SWAGGER_DOCS_DELETE_LIST);
Set<String> swaggerDocsDeleteSet = new HashSet<>();
if (StringUtils.isNotBlank(swaggerDocsDeleteStr)) {
List<String> swaggerDocsDeleteList = JSON.parseArray(swaggerDocsDeleteStr, String.class);
swaggerDocsDeleteSet.addAll(swaggerDocsDeleteList);
}
swaggerDocsDeleteSet.add(docUrl);
storageService.put(StorageKeys.SWAGGER_DOCS_DELETE_LIST, JSON.toJSONString(swaggerDocsDeleteSet));
return DocResponseJson.ok();
}
}

View File

@@ -1,16 +1,18 @@
package com.zyplayer.doc.swagger.framework.constant;
/**
* 存储数据的KEY常量类
*
* @author 暮光:城中城
* @since 2018年8月21日
*/
public class StorageKeys {
// 所有文档地址
public static final String SWAGGER_RESOURCES_LIST = "swagger-resources-list";
// 已删除的文档
public static final String SWAGGER_DOCS_DELETE_LIST = "swagger-docs-delete-list";
// 所有详细文档地址
public static final String SWAGGER_LOCATION_LIST = "swagger-location-list";
package com.zyplayer.doc.swagger.framework.constant;
/**
* 存储数据的KEY常量类
*
* @author 暮光:城中城
* @since 2018年8月21日
*/
public class StorageKeys {
// 所有文档地址
public static final String SWAGGER_RESOURCES_LIST = "swagger-resources-list";
// 已删除的文档
public static final String SWAGGER_DOCS_DELETE_LIST = "swagger-docs-delete-list";
// 所有详细文档地址
public static final String SWAGGER_LOCATION_LIST = "swagger-location-list";
// 文档的离线数据key
public static final String SWAGGER_OFFLINE_DOC_START = "swagger-offline-doc-";
}

View File

@@ -383,6 +383,7 @@
<script type="text/javascript" src="webjars/mg-ui/js/mg-ui-tag.js"></script>
<script type="text/javascript" src="webjars/mg-ui/js/mg-ui-debug.js"></script>
<script type="text/javascript" src="webjars/mg-ui/js/mg-ui-export.js"></script>
<script type="text/javascript" src="webjars/mg-ui/js/mg-ui-cache-keys.js"></script>
<script type="text/javascript" src="webjars/mg-ui/js/mg-ui.js"></script>
</html>

View File

@@ -3,4 +3,5 @@ var cacheKeys = {
swaggerResourcesList: 'swagger-resources-list',
globalParamList: 'zyplayer-doc-global-param-list',
pRequestObjStart: 'p-request-obj-',
pSimulationResponse: 'p-simulation-response',
}

View File

@@ -10,5 +10,9 @@ var exports = {
exportDocument: function(){
// 定义在mg-ui.js用于打开导出文档框
exportDocument();
},
updateGlobalParam: function(param){
// 更新调试的全局参数变量
debugGlobalParam = param;
}
};

View File

@@ -19,6 +19,8 @@ var projectTreeIdIndex = 1;
var projectLoadingIndex = 0;
// 请求到的文档列表
var documentJsonArr = [];
// 调试的全局参数变量
var debugGlobalParam = [];
// 用户的配置对象
var userSettings = {};
// 默认用户的配置对象
@@ -86,7 +88,7 @@ function getDocumentListByService() {
showGlobalLoadingMessage('等待选择需展示的文档,请选择...', true);
for (var i = 0; i < json.data.length; i++) {
var item = json.data[i];
$("#choiseDocListUl").append('<li value="'+item+'">'+item+'</li>');
$("#choiseDocListUl").append('<li value="'+item.url+'">'+item.url+'</li>');
}
$('#choiseDocModal').modal({moveable:true, backdrop:'static', keyboard: false});
} else {
@@ -159,48 +161,6 @@ $("#changeContentWidth").click(function(){
changeContentWidth(isMinWidth ? 360 : 120);
});
/**
* 修改tree的class
*/
$("input[name='treeShowType']").change(function() {
userSettings.treeShowType = $("input[name='treeShowType']:checked").val();
updateTreeShowType();
storeUserSettings();
});
/**
* 切换url分成一层一层的展示、整个url显示为一层展示
*/
$("input[name='catalogShowType']").change(function() {
userSettings.catalogShowType = $("input[name='catalogShowType']:checked").val();
regeneratePathTree();
storeUserSettings();
});
/**
* 是否展示参数类型
*/
$("input[name='showParamType']").change(function() {
userSettings.showParamType = $("input[name='showParamType']:checked").val();
storeUserSettings();
});
/**
* 是否仅使用上次请求参数
*/
$("input[name='onlyUseLastParam']").change(function() {
userSettings.onlyUseLastParam = $("input[name='onlyUseLastParam']:checked").val();
storeUserSettings();
});
/**
* 是否自动填充请求参数
*/
$("input[name='autoFillParam']").change(function() {
userSettings.autoFillParam = $("input[name='autoFillParam']:checked").val();
storeUserSettings();
});
/**
* 搜索框回车事件
*/
@@ -1030,7 +990,7 @@ function updateTreeShowType() {
* 存储用户设置
*/
function storeUserSettings() {
setStorage('userSettings', userSettings);
setStorage(cacheKeys.userSettings, userSettings);
}
/**
@@ -1046,7 +1006,7 @@ function updateUserSettings(newSetting) {
* @returns
*/
function initUserSettings() {
getStorage('userSettings', function(data) {
getStorage(cacheKeys.userSettings, function(data) {
userSettings = data;
if(isEmpty(userSettings) || isEmptyObject(userSettings)) {
userSettings = defaultUserSettings;
@@ -1057,6 +1017,9 @@ function initUserSettings() {
// 增加文档
getDocumentListByService();
});
getStorage(cacheKeys.globalParamList, function(data) {
debugGlobalParam = data;
});
}
function showGlobalLoadingMessage(text, loading) {

View File

@@ -77,6 +77,7 @@
var app = new Vue({
el: '#app',
data: {
initCount: 5,
catalogShowType: '',
treeShowType: '',
showParamType:'',
@@ -122,12 +123,14 @@
},
}
});
// 存储用户的配置信息
function storeUserSettings(){
setStorage(cacheKeys.userSettings, app.userSettings, function(){
getExport().updateUserSettings(app.userSettings);
});
function storeUserSettings() {
if (app.initCount-- <= 0) {
setStorage(cacheKeys.userSettings, app.userSettings, function () {
getExport().updateUserSettings(app.userSettings);
});
}
}
</script>

View File

@@ -1,5 +1,5 @@
<!doctype html>
<html>
<html xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
@@ -14,15 +14,18 @@
<tr>
<td style="width: 50px;">序号</td>
<td>地址</td>
<td>持久化时间</td>
<td>操作</td>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in swaggerResourcesList" :key="item.id" :data-id="item.id" :data-index="index" >
<td>{{index+1}}</td>
<td>{{item}}</td>
<td>{{item.url}}</td>
<td>{{item.lastSync}}</td>
<td>
<button class="btn btn-danger" type="button" v-on:click="deleteDocUrl($event)">删除</button>
<!--<button class="btn btn-danger" type="button" v-on:click="syncDocData($event)">持久化</button>-->
</td>
</tr>
<tr>
@@ -93,7 +96,8 @@
ajaxTemp(urlBase + "swagger-mg-ui/document/addSwaggerResources", "post", "json", {resourcesUrl: addNewDocumentInput}, function(json){
if(validateResult(json)) {
//window.parent.document.location.reload();
app.swaggerResourcesList.push(addNewDocumentInput);
//app.swaggerResourcesList.push(addNewDocumentInput);
app.refreshList();
$('#addNewDocumentModal').modal('hide');
Toast.success("保存成功,刷新后生效!");
}
@@ -117,6 +121,17 @@
setStorage(cacheKeys.swaggerResourcesList, newDocList, function(){
app.swaggerResourcesList = newDocList;
});
},
syncDocData: function(event){
var tr = $(event.currentTarget).parents("tr");
var index = tr.data("index");
var newDocUrl = app.swaggerResourcesList[index].url;
ajaxTemp(urlBase + "swagger-mg-ui/document/syncDocData", "post", "json", {resourcesUrl: newDocUrl}, function(json){
if(validateResult(json)) {
app.refreshList();
Toast.success("持久化成功!");
}
});
}
},
mounted: function(){

View File

@@ -24,7 +24,7 @@
<tbody>
<tr v-for="(item,index) in globalParamList" :key="item.id" :data-id="item.id" :data-index="index">
<td>
<select class="form-control" v-model:value="item.position">
<select class="form-control" v-model:value="item.paramIn">
<option value="header">header</option>
<option value="form">form</option>
</select>
@@ -81,11 +81,12 @@
},
addGlobalParamLine: function () {
app.globalParamList.push({
position: 'header', key: '', value: ''
paramIn: 'header', key: '', value: ''
});
},
saveAllGlobalParam: function () {
setStorage(cacheKeys.globalParamList, app.globalParamList, function(){
getExport().updateGlobalParam(app.globalParamList);
Toast.success("保存成功!");
});
},