1.调整资源位置

2.完善功能
This commit is contained in:
wanggeng888 2021-05-16 21:11:03 +08:00
parent b15e672eb3
commit 8799ea2078
52 changed files with 970 additions and 252 deletions

View File

@ -1,10 +1,13 @@
package ink.wgink.gateway.component;
import ink.wgink.gateway.consts.ISystemConst;
import ink.wgink.gateway.dao.route.IRouteDao;
import ink.wgink.gateway.filter.local.CommonFiltersDefinition;
import ink.wgink.gateway.pojo.route.Route;
import ink.wgink.gateway.util.UUIDUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.filter.factory.*;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.handler.predicate.RoutePredicateFactory;
import org.springframework.cloud.gateway.route.RouteDefinition;
@ -100,8 +103,10 @@ public class MongoRouteDefinitionRepository implements RouteDefinitionRepository
CommonFiltersDefinition commonFiltersDefinition = new CommonFiltersDefinition();
// 定义过滤器
List<FilterDefinition> filterDefinitions = new ArrayList<>();
// 重写响应头中的location解决重定向问题
filterDefinitions.add(commonFiltersDefinition.rewriteLocationResponseHeader(route));
// 设置路径过滤器
if (!StringUtils.isBlank(route.getSetPath())) {
filterDefinitions.add(commonFiltersDefinition.setPath(route));
}
return filterDefinitions;
}

View File

@ -0,0 +1,29 @@
package ink.wgink.gateway.dao.log;
import ink.wgink.gateway.pojo.log.RequestLog;
import org.springframework.data.mongodb.repository.Aggregation;
import org.springframework.data.mongodb.repository.Query;
import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: IRequestLogDao
* @Description: 请求日志
* @Author: wanggeng
* @Date: 2021/5/15 3:02 下午
* @Version: 1.0
*/
@Repository
public interface IRequestLogDao extends ReactiveMongoRepository<RequestLog, String> {
String COLLECTION_NAME = "log_request";
@Aggregation("[{$match: {gmtCreate: {$gte: 'startTime', $lte: 'endTime'}}}, {$group: {_id: '$gmtCreate', num_tutorial: {$sum: 1}}}, {$sort: {gmtCreate: -1}}]")
List<RequestLog> countByStartTimeAndEndTime(String startTime, String endTime);
}

View File

@ -1,45 +0,0 @@
package ink.wgink.gateway.filter.global;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.net.URI;
import java.util.concurrent.atomic.AtomicInteger;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: CountGolbalFilter
* @Description: 计数过滤器
* @Author: WangGeng
* @Date: 2021/4/13 12:10
* @Version: 1.0
**/
@Slf4j
@Component
public class CountGlobalFilter implements GlobalFilter, Ordered {
private AtomicInteger count = new AtomicInteger(0);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
URI uri = exchange.getRequest().getURI();
System.out.println();
System.out.println("uri: " + uri);
System.out.println("count: "+ count.getAndAdd(1));
System.out.println();
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 10000;
}
}

View File

@ -0,0 +1,94 @@
package ink.wgink.gateway.filter.global;
import ink.wgink.gateway.dao.log.IRequestLogDao;
import ink.wgink.gateway.handler.log.RequestLogHandler;
import ink.wgink.gateway.pojo.log.RequestLog;
import lombok.extern.slf4j.Slf4j;
import org.reactivestreams.Publisher;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.net.URI;
import java.util.concurrent.atomic.AtomicInteger;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: CountGolbalFilter
* @Description: 计数过滤器
* @Author: WangGeng
* @Date: 2021/4/13 12:10
* @Version: 1.0
**/
@Slf4j
@Component
public class RequestLogGlobalFilter implements GlobalFilter, Ordered {
private RequestLogHandler requestLogHandler;
public RequestLogGlobalFilter(RequestLogHandler requestLogHandler) {
this.requestLogHandler = requestLogHandler;
}
@Override
public Mono<Void> filter(ServerWebExchange serverWebExchange, GatewayFilterChain gatewayFilterChain) {
ServerHttpRequest serverHttpRequest = serverWebExchange.getRequest();
ServerHttpResponse serverHttpResponse = serverWebExchange.getResponse();
// 其它情况一律放行并做日志处理
RequestLog requestLog = buildRequestLog(serverHttpRequest);
return gatewayFilterChain.filter(serverWebExchange.mutate().response(new ServerHttpResponseDecorator(serverHttpResponse) {
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
if (body instanceof Flux) {
requestLog.setResponseCode(this.getStatusCode().value());
requestLog.setEndTime(System.currentTimeMillis());
requestLog.setUsedTime(requestLog.getEndTime() - requestLog.getStartTime());
requestLogHandler.save(requestLog);
Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
return super.writeWith(fluxBody.map(dataBuffer -> {
byte[] content = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(content);
// String responseResult = new String(content, Charset.forName("UTF-8"));
return super.bufferFactory().wrap(content);
}));
}
return super.writeWith(body);
}
}).build());
}
@Override
public int getOrder() {
// 调整到-10保证过滤器在执行时路径没有被修改
return -10;
}
/**
* 构建请求日志
*
* @param serverHttpRequest
* @return
*/
private RequestLog buildRequestLog(ServerHttpRequest serverHttpRequest) {
URI uri = serverHttpRequest.getURI();
RequestLog requestLog = new RequestLog();
requestLog.setMethod(serverHttpRequest.getMethod().name());
requestLog.setHost(uri.getHost());
requestLog.setPort(uri.getPort());
requestLog.setPath(uri.getPath());
requestLog.setQueryParams(uri.getQuery());
requestLog.setScheme(uri.getScheme());
requestLog.setStartTime(System.currentTimeMillis());
return requestLog;
}
}

View File

@ -40,7 +40,7 @@ public class CommonFiltersDefinition {
}
/**
* 设置路径过滤器去除前缀将路径中的gw删除暂时无用
* 设置路径过滤器
*
* @param route
* @return
@ -48,7 +48,7 @@ public class CommonFiltersDefinition {
public FilterDefinition setPath(Route route) {
FilterDefinition setPath = new FilterDefinition();
Map<String, String> setPathMap = new HashMap<>(2);
setPathMap.put(SetPathGatewayFilterFactory.TEMPLATE_KEY, route.getPath().replaceFirst(ISystemConst.ROUTE_PREFIX, "/"));
setPathMap.put(SetPathGatewayFilterFactory.TEMPLATE_KEY, route.getSetPath());
setPath.setArgs(setPathMap);
setPath.setName("SetPath");
return setPath;

View File

@ -1,20 +1,28 @@
package ink.wgink.gateway.filter.web;
import ink.wgink.gateway.consts.ISystemConst;
import ink.wgink.gateway.handler.log.RequestLogHandler;
import ink.wgink.gateway.pojo.log.RequestLog;
import org.reactivestreams.Publisher;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import org.springframework.web.server.WebSession;
import org.springframework.web.util.pattern.PathPattern;
import org.springframework.web.util.pattern.PathPatternParser;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;

View File

@ -0,0 +1,98 @@
package ink.wgink.gateway.handler.count;
import ink.wgink.gateway.dao.log.IRequestLogDao;
import ink.wgink.gateway.dao.route.IRouteDao;
import ink.wgink.gateway.dao.routetype.IRouteTypeDao;
import ink.wgink.gateway.handler.BaseHandler;
import ink.wgink.gateway.pojo.count.HomeCount;
import ink.wgink.gateway.pojo.count.RequestLogCount;
import ink.wgink.gateway.pojo.log.RequestLog;
import ink.wgink.gateway.pojo.result.SuccessResult;
import ink.wgink.gateway.pojo.result.SuccessResultData;
import ink.wgink.gateway.util.DateUtil;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.time.Duration;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: CountHandler
* @Description: 统计
* @Author: wanggeng
* @Date: 2021/5/15 3:01 下午
* @Version: 1.0
*/
@Service
public class CountHandler extends BaseHandler {
private IRouteTypeDao routeTypeDao;
private IRouteDao routeDao;
private IRequestLogDao requestLogDao;
public CountHandler(IRouteTypeDao routeTypeDao, IRouteDao routeDao, IRequestLogDao requestLogDao) {
this.routeTypeDao = routeTypeDao;
this.routeDao = routeDao;
this.requestLogDao = requestLogDao;
}
/**
* 所有路由类型
*
* @param serverResponse
* @return
*/
public Mono<ServerResponse> countHome(ServerRequest serverResponse) {
return ServerResponse.ok().contentType(MediaType.TEXT_EVENT_STREAM).body(
Flux.interval(Duration.ofSeconds(0), Duration.ofSeconds(15))
.flatMap(second -> routeTypeDao.count()
.flatMap(routeTypeCount -> routeDao.count()
.flatMap(routeCount -> requestLogDao.count()
.flatMap(requestCount -> {
RequestLog requestLogExample = new RequestLog();
requestLogExample.setGmtCreate(DateUtil.getDay());
ExampleMatcher exampleMatcher = ExampleMatcher.matching()
.withMatcher("gmtCreate", ExampleMatcher.GenericPropertyMatcher::contains)
.withIgnoreCase("id");
Example example = Example.of(requestLogExample, exampleMatcher);
return requestLogDao.count(example)
.flatMap(requestTodayCount -> {
HomeCount homeCount = new HomeCount();
homeCount.setRouteTypeCount(routeTypeCount);
homeCount.setRouteCount(routeCount);
homeCount.setRequestCount(requestCount);
homeCount.setRequestTodayCount((Long) requestTodayCount);
return Mono.just(homeCount);
});
})
)
)
),
HomeCount.class);
}
/**
* 最新请求数量列表
*
* @param serverRequest
* @return
*/
// 每分钟跟新依次统计数据
public Mono<ServerResponse> listLastCount(ServerRequest serverRequest) {
return ServerResponse.ok().contentType(MediaType.TEXT_EVENT_STREAM).body(requestLogDao.count().flatMap(count -> {
RequestLogCount requestLogCount = new RequestLogCount();
return Mono.just(requestLogCount);
}), RequestLogCount.class);
}
}

View File

@ -0,0 +1,36 @@
package ink.wgink.gateway.handler.log;
import ink.wgink.gateway.dao.log.IRequestLogDao;
import ink.wgink.gateway.handler.BaseHandler;
import ink.wgink.gateway.pojo.log.RequestLog;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
import java.net.URI;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: RequestLogHandler
* @Description: 请求日志
* @Author: wanggeng
* @Date: 2021/5/15 5:27 下午
* @Version: 1.0
*/
@Service
public class RequestLogHandler extends BaseHandler {
private IRequestLogDao requestLogDao;
public RequestLogHandler(IRequestLogDao requestLogDao) {
this.requestLogDao = requestLogDao;
}
public Mono<Void> save(RequestLog requestLog) {
setSave(requestLog);
requestLogDao.save(requestLog).subscribe();
return Mono.empty();
}
}

View File

@ -3,10 +3,14 @@ package ink.wgink.gateway.handler.route;
import ink.wgink.gateway.consts.ISystemConst;
import ink.wgink.gateway.dao.route.IRouteDao;
import ink.wgink.gateway.exception.ParamsException;
import ink.wgink.gateway.exception.SearchException;
import ink.wgink.gateway.handler.BaseHandler;
import ink.wgink.gateway.pojo.result.SuccessResult;
import ink.wgink.gateway.pojo.route.Route;
import ink.wgink.gateway.pojo.routetype.RouteType;
import ink.wgink.gateway.util.RegexUtil;
import ink.wgink.gateway.util.RequestFieldCheckUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
@ -52,12 +56,26 @@ public class RouteHandler extends BaseHandler implements ApplicationEventPublish
public Mono<ServerResponse> save(ServerRequest serverRequest) {
Mono<Route> routeMono = serverRequest.bodyToMono(Route.class);
return routeMono.flatMap(route -> {
setSave(route);
RequestFieldCheckUtil.check(route);
if (route.getPath().startsWith(ISystemConst.ROOT_PATH_PREFIX)) {
return Mono.error(new ParamsException("根路径不能配置通配符"));
}
setSave(route);
return routeDao.save(route);
if (route.getPath().startsWith(ISystemConst.ADMIN_ROUTER_PREFIX)) {
return Mono.error(new ParamsException("根路径不能以/wg/*开头"));
}
if (!StringUtils.isBlank(route.getSetPath()) && !RegexUtil.isPath(route.getSetPath())) {
return Mono.error(new ParamsException("设置路径格式错误"));
}
// 判断路径是否存在
Route routeExample = new Route();
routeExample.setPath(route.getPath());
ExampleMatcher exampleMatcher = ExampleMatcher.matching().withMatcher("path", ExampleMatcher.GenericPropertyMatcher::exact).withIgnoreCase("id");
Example example = Example.of(routeExample, exampleMatcher);
return routeDao.findOne(example).flatMap(
r -> Mono.error(new SearchException("路径已经存在"))
).switchIfEmpty(routeDao.save(route));
}).then(ServerResponse.ok().contentType(MediaType.APPLICATION_JSON_UTF8).body(Flux.just(new SuccessResult()), SuccessResult.class));
}
@ -84,24 +102,45 @@ public class RouteHandler extends BaseHandler implements ApplicationEventPublish
public Mono<ServerResponse> update(ServerRequest serverRequest) {
String id = serverRequest.pathVariable("id");
Mono<Route> routeMono = serverRequest.bodyToMono(Route.class);
return routeDao.findById(id).flatMap(
route -> routeMono.flatMap(r -> {
RequestFieldCheckUtil.check(r);
if (r.getPath().startsWith(ISystemConst.ROOT_PATH_PREFIX)) {
return Mono.error(new ParamsException("根路径不能配置通配符"));
return routeDao.findById(id).flatMap(route -> {
setUpdate(route);
return routeMono.flatMap(r -> {
route.setTitle(r.getTitle());
route.setSummary(r.getSummary());
route.setPath(r.getPath());
route.setUri(r.getUri());
route.setTestPath(r.getTestPath());
route.setRouteType(r.getRouteType());
route.setSetPath(r.getSetPath());
RequestFieldCheckUtil.check(r);
if (r.getPath().startsWith(ISystemConst.ROOT_PATH_PREFIX)) {
return Mono.error(new ParamsException("根路径不能配置通配符"));
}
if (r.getPath().startsWith(ISystemConst.ADMIN_ROUTER_PREFIX)) {
return Mono.error(new ParamsException("根路径不能以/wg/*开头"));
}
if (!StringUtils.isBlank(route.getSetPath()) && !RegexUtil.isPath(route.getSetPath())) {
return Mono.error(new ParamsException("设置路径格式错误"));
}
// 检索路径是否存在
Route routeExample = new Route();
routeExample.setPath(r.getPath());
ExampleMatcher exampleMatcher = ExampleMatcher.matching()
.withMatcher("path", ExampleMatcher.GenericPropertyMatcher::exact)
.withIgnoreCase("id");
Example example = Example.of(routeExample, exampleMatcher);
return routeDao.findOne(example).flatMap(er -> {
Route existRoute = (Route) er;
// 如果已经存在
if (!StringUtils.equals(existRoute.getUuid(), id)) {
return Mono.error(new SearchException("路径已经存在"));
}
if (r.getPath().startsWith(ISystemConst.ADMIN_ROUTER_PREFIX)) {
return Mono.error(new ParamsException("根路径不能以/wg/*开头"));
}
route.setTitle(r.getTitle());
route.setSummary(r.getSummary());
route.setPath(r.getPath());
route.setUri(r.getUri());
route.setTestPath(r.getTestPath());
setUpdate(route);
return routeDao.save(route);
}).then(ServerResponse.ok().contentType(MediaType.APPLICATION_JSON_UTF8).body(Flux.just(new SuccessResult()), SuccessResult.class))
).switchIfEmpty(ServerResponse.notFound().build());
}).switchIfEmpty(routeDao.save(route));
});
}).then(ServerResponse.ok().contentType(MediaType.APPLICATION_JSON_UTF8).body(Flux.just(new SuccessResult()), SuccessResult.class));
}
/**
@ -112,17 +151,24 @@ public class RouteHandler extends BaseHandler implements ApplicationEventPublish
*/
public Mono<ServerResponse> list(ServerRequest serverRequest) {
Optional<String> keywords = serverRequest.queryParam("keywords");
Optional<String> routeType = serverRequest.queryParam("routeType");
Route route = new Route();
Example example = Example.of(route);
if (keywords.isPresent()) {
String keywordTrim = keywords.get().trim();
route.setTitle(keywordTrim);
route.setSummary(keywordTrim);
ExampleMatcher exampleMatcher = ExampleMatcher.matchingAny()
if (keywords.isPresent() || routeType.isPresent()) {
if (keywords.isPresent()) {
String keywordTrim = keywords.get().trim();
route.setTitle(keywordTrim);
route.setSummary(keywordTrim);
}
if (routeType.isPresent()) {
String routeTypeTrim = routeType.get().trim();
route.setRouteType(routeTypeTrim);
}
ExampleMatcher exampleMatcher = ExampleMatcher.matching()
.withMatcher("title", ExampleMatcher.GenericPropertyMatcher::contains)
.withMatcher("summary", ExampleMatcher.GenericPropertyMatcher::contains)
.withMatcher("routeType", ExampleMatcher.GenericPropertyMatcher::exact)
.withIgnoreCase("id");
example = Example.of(route, exampleMatcher);
}

View File

@ -53,7 +53,7 @@ public class RouteTypeHandler extends BaseHandler {
RouteType routeTypeExample = new RouteType();
routeTypeExample.setTitle(routeType.getTitle().trim());
ExampleMatcher exampleMatcher = ExampleMatcher.matchingAny().withMatcher("title", ExampleMatcher.GenericPropertyMatcher::exact).withIgnoreCase("id");
ExampleMatcher exampleMatcher = ExampleMatcher.matching().withMatcher("title", ExampleMatcher.GenericPropertyMatcher::exact).withIgnoreCase("id");
Example example = Example.of(routeTypeExample, exampleMatcher);
return routeTypeDao.findOne(example).flatMap(
r -> Mono.error(new SearchException("类型已经存在"))
@ -87,15 +87,16 @@ public class RouteTypeHandler extends BaseHandler {
return routeTypeDao.findById(id).flatMap(routeType -> {
setUpdate(routeType);
return routeTypeMono.flatMap(rt -> {
RequestFieldCheckUtil.check(rt);
routeType.setTitle(rt.getTitle());
routeType.setSummary(rt.getSummary());
RequestFieldCheckUtil.check(rt);
rt.setSummary(null );
ExampleMatcher exampleMatcher = ExampleMatcher.matchingAny()
RouteType routeTypeExample = new RouteType();
routeTypeExample.setTitle(rt.getTitle());
ExampleMatcher exampleMatcher = ExampleMatcher.matching()
.withMatcher("title", ExampleMatcher.GenericPropertyMatcher::exact)
.withIgnoreCase("id");
Example example = Example.of(rt, exampleMatcher);
Example example = Example.of(routeTypeExample, exampleMatcher);
// 查询title是否存在
return routeTypeDao.findOne(example).flatMap(ert -> {
RouteType existRouteType = (RouteType) ert;
@ -125,7 +126,7 @@ public class RouteTypeHandler extends BaseHandler {
routeType.setTitle(keywordTrim);
routeType.setSummary(keywordTrim);
ExampleMatcher exampleMatcher = ExampleMatcher.matchingAny()
ExampleMatcher exampleMatcher = ExampleMatcher.matching()
.withMatcher("title", ExampleMatcher.GenericPropertyMatcher::contains)
.withMatcher("summary", ExampleMatcher.GenericPropertyMatcher::contains)
.withIgnoreCase("id");

View File

@ -0,0 +1,56 @@
package ink.wgink.gateway.pojo.count;
import lombok.ToString;
import org.springframework.data.mongodb.core.mapping.Document;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: HomeCount
* @Description: 首页统计
* @Author: wanggeng
* @Date: 2021/5/15 4:53 下午
* @Version: 1.0
*/
@ToString
@Document
public class HomeCount {
private Long routeTypeCount;
private Long routeCount;
private Long requestCount;
private Long requestTodayCount;
public Long getRouteTypeCount() {
return routeTypeCount == null ? 0 : routeTypeCount;
}
public void setRouteTypeCount(Long routeTypeCount) {
this.routeTypeCount = routeTypeCount;
}
public Long getRouteCount() {
return routeCount == null ? 0 : routeCount;
}
public void setRouteCount(Long routeCount) {
this.routeCount = routeCount;
}
public Long getRequestCount() {
return requestCount == null ? 0 : requestCount;
}
public void setRequestCount(Long requestCount) {
this.requestCount = requestCount;
}
public Long getRequestTodayCount() {
return requestTodayCount == null ? 0 : requestTodayCount;
}
public void setRequestTodayCount(Long requestTodayCount) {
this.requestTodayCount = requestTodayCount;
}
}

View File

@ -0,0 +1,30 @@
package ink.wgink.gateway.pojo.count;
import ink.wgink.gateway.dao.log.IRequestLogDao;
import ink.wgink.gateway.pojo.BasePOJO;
import lombok.Data;
import lombok.ToString;
import org.springframework.data.mongodb.core.mapping.Document;
import java.io.Serializable;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: RequestLog
* @Description: 请求日志
* @Author: wanggeng
* @Date: 2021/5/15 3:03 下午
* @Version: 1.0
*/
@Data
@ToString
@Document(collection = IRequestLogDao.COLLECTION_NAME)
public class RequestLogCount implements Serializable {
private static final long serialVersionUID = 289254213770448241L;
private String gmtCreate;
private Long count;
}

View File

@ -0,0 +1,38 @@
package ink.wgink.gateway.pojo.log;
import ink.wgink.gateway.dao.log.IRequestLogDao;
import ink.wgink.gateway.pojo.BasePOJO;
import lombok.Data;
import lombok.ToString;
import org.springframework.data.mongodb.core.mapping.Document;
import java.io.Serializable;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: RequestLog
* @Description: 请求日志
* @Author: wanggeng
* @Date: 2021/5/15 3:03 下午
* @Version: 1.0
*/
@Data
@ToString
@Document(collection = IRequestLogDao.COLLECTION_NAME)
public class RequestLog extends BasePOJO implements Serializable {
private static final long serialVersionUID = 289254213770448241L;
private String method;
private String scheme;
private String host;
private Integer port;
private String path;
private String queryParams;
private Integer responseCode;
private Long startTime;
private Long endTime;
private Long usedTime;
}

View File

@ -0,0 +1,34 @@
package ink.wgink.gateway.pojo.result;
import lombok.Data;
import lombok.ToString;
import org.springframework.data.mongodb.core.mapping.Document;
/**
* @ClassName: SuccessResult
* @Description: 成功结果
* @Author: WangGeng
* @Date: 2019/3/2 11:52 PM
* @Version: 1.0
**/
@Data
@ToString
@Document
public class SuccessResultData<T> {
private T data;
public SuccessResultData() {}
public SuccessResultData(T data) {
this.data = data;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}

View File

@ -33,6 +33,8 @@ public class Route extends BasePOJO implements Serializable {
private String uri;
@CheckEmptyAnnotation(name = "测试接口", verifyType = "path")
private String testPath;
private String routeType;
private String setPath;
public String getTitle() {
return title == null ? "" : title.trim();
@ -73,4 +75,20 @@ public class Route extends BasePOJO implements Serializable {
public void setTestPath(String testPath) {
this.testPath = testPath;
}
public String getRouteType() {
return routeType == null ? "" : routeType;
}
public void setRouteType(String routeType) {
this.routeType = routeType;
}
public String getSetPath() {
return setPath == null ? "" : setPath;
}
public void setSetPath(String setPath) {
this.setPath = setPath;
}
}

View File

@ -0,0 +1,35 @@
package ink.wgink.gateway.router.count;
import ink.wgink.gateway.consts.ISystemConst;
import ink.wgink.gateway.handler.count.CountHandler;
import ink.wgink.gateway.router.BaseRouter;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: CountRouter
* @Description: 统计
* @Author: wanggeng
* @Date: 2021/5/15 4:36 下午
* @Version: 1.0
*/
@Component
public class CountRouter extends BaseRouter {
@Bean
public RouterFunction<ServerResponse> countRouterFunction(CountHandler countHandler) {
return RouterFunctions.nest(RequestPredicates.path(ISystemConst.ADMIN_ROUTER_PREFIX + "/api/count"),
RouterFunctions
.route(RequestPredicates.GET("/count-home"), countHandler::countHome)
.andRoute(RequestPredicates.GET("list-last-count"), countHandler::listLastCount)
);
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,99 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>测试 - layui</title>
<link rel="stylesheet" href="layui/css/layui.css">
</head>
<body>
<div class="layui-container">
<div class="layui-progress" style="margin: 15px 0 30px;">
<div class="layui-progress-bar" lay-percent="100%"></div>
</div>
<div class="layui-btn-container">
<button class="layui-btn" test-active="test-form">一个按钮</button>
<button class="layui-btn layui-btn-normal" id="test2">当前日期</button>
</div>
<blockquote class="layui-elem-quote" style="margin-top: 30px;">
<div class="layui-text">
<ul>
<li>你当前预览的是:<span>layui-v<span id="version"></span></span></li>
<li>这是一个极其简洁的演示页面</li>
</ul>
</div>
</blockquote>
</div>
<!-- 引入 layui.js 的 <script> 标签最好放置在 html 末尾 -->
<script src="layui/layui.js"></script>
<script>
layui.use(function(){
var layer = layui.layer
,form = layui.form
,laypage = layui.laypage
,element = layui.element
,laydate = layui.laydate
,util = layui.util;
//欢迎信息
layer.msg('Hello World');
//输出版本号
lay('#version').html(layui.v);
//日期
laydate.render({
elem: '#test2'
,value: new Date()
,isInitValue: true
});
//触发事件
util.event('test-active', {
'test-form': function(){
layer.open({
type: 1
,resize: false
,shadeClose: true
,content: ['<ul class="layui-form" style="margin: 10px;">'
,'<li class="layui-form-item">'
,'<label class="layui-form-label">输入框</label>'
,'<div class="layui-input-block">'
,'<input class="layui-input" name="field1">'
,'</div>'
,'</li>'
,'<li class="layui-form-item">'
,'<label class="layui-form-label">选择框</label>'
,'<div class="layui-input-block">'
,'<select name="field2">'
,'<option value="A">A</option>'
,'<option value="B">B</option>'
,'<select>'
,'</div>'
,'</li>'
,'<li class="layui-form-item" style="text-align:center;">'
,'<button type="submit" lay-submit lay-filter="*" class="layui-btn">提交</button>'
,'</li>'
,'</ul>'].join('')
,success: function(layero){
layero.find('.layui-layer-content').css('overflow', 'visible');
form.render().on('submit(*)', function(data){
layer.msg(JSON.stringify(data.field));
});
}
});
}
});
});
</script>
</body>
</html>

View File

@ -1,6 +0,0 @@
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,11
[InternetShortcut]
URL=https://www.layui.com/about/disclaimer.html
IDList=
HotKey=0

View File

@ -4,7 +4,6 @@ html {
.iframe-container {
margin: 15px;
background: #FFFFFF;
}
.iframe-container .iframe-box {
@ -17,6 +16,7 @@ html {
.iframe-container .iframe-breadcrumb-box {
padding: 15px;
border-bottom: 1px solid #F3F3F3;
background-color: #FFFFFF;
}
.list-page-container {
@ -241,3 +241,23 @@ html, body, #LAY_app {
text-align: center;
margin-bottom: 15px;
}
.search-item {
height: 30px !important;
}
.search-item input, .search-item select {
height: 30px !important;
}
.search-item-width-100 {
width: 100px !important;
}
.search-item-width-200 {
width: 200px !important;
}
.search-item-width-300 {
width: 300px !important;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

Before

Width:  |  Height:  |  Size: 299 KiB

After

Width:  |  Height:  |  Size: 299 KiB

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,25 @@
layui.define(function(exports) {
var $ = layui.$;
$.fn.animateNumbers = function(stop, commas, duration, ease) {
return this.each(function() {
var $this = $(this);
var start = parseInt($this.text().replace(/,/g, ""));
commas = (commas === undefined) ? true : commas;
$({value: start}).animate({value: stop}, {
duration: duration == undefined ? 1000 : duration,
easing: ease == undefined ? "swing" : ease,
step: function() {
$this.text(Math.floor(this.value));
if (commas) { $this.text($this.text().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,")); }
},
complete: function() {
if (parseInt($this.text()) !== stop) {
$this.text(stop);
if (commas) { $this.text($this.text().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,")); }
}
}
});
});
};
exports('animate-numbers', null);
});

View File

@ -0,0 +1,151 @@
<!DOCTYPE html>
<html lang="en">
<head>
<base href="/wg/">
<meta charset="utf-8">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="stylesheet" href="assets/layui/css/layui.css"/>
<link rel="stylesheet" href="assets/layui/css/admin.css"/>
<link rel="stylesheet" href="assets/layui/css/admin.css"/>
<style>
#app {padding: 15px 0;}
.layuiadmin-badge {float: right; height: 42px; line-height: 42px;}
.layuiadmin-card-list {padding: 15px;line-height: 38px !important; text-align: right;}
.layuiadmin-card-list .layuiadmin-big-font {font-size: 38px;}
</style>
</head>
<body>
<div id="app">
<div class="layui-row layui-col-space15">
<div class="layui-col-md3 layui-col-sm6 layui-col-xs12">
<div class="layui-card">
<div class="layui-card-header">
累计调用量
<span class="layui-badge layui-bg-cyan layuiadmin-badge"></span>
</div>
<div class="layui-card-body layuiadmin-card-list">
<p id="requestCount" class="layuiadmin-big-font">0</p>
</div>
</div>
</div>
<div class="layui-col-md3 layui-col-sm6 layui-col-xs12">
<div class="layui-card">
<div class="layui-card-header">
今日调用量
<span class="layui-badge layui-bg-green layuiadmin-badge"></span>
</div>
<div class="layui-card-body layuiadmin-card-list">
<p id="requestTodayCount" class="layuiadmin-big-font">0</p>
</div>
</div>
</div>
<div class="layui-col-md3 layui-col-sm6 layui-col-xs12">
<div class="layui-card">
<div class="layui-card-header">
路由类型总量
<span class="layui-badge layui-bg-blue layuiadmin-badge"></span>
</div>
<div class="layui-card-body layuiadmin-card-list">
<p id="routeTypeCount" class="layuiadmin-big-font">0</p>
</div>
</div>
</div>
<div class="layui-col-md3 layui-col-sm6 layui-col-xs12">
<div class="layui-card">
<div class="layui-card-header">
映射路由总量
<span class="layui-badge layui-bg-orange layuiadmin-badge"></span>
</div>
<div class="layui-card-body layuiadmin-card-list">
<p id="routeCount" class="layuiadmin-big-font">0</p>
</div>
</div>
</div>
</div>
<div class="layui-row layui-col-space15">
<div class="layui-col-sm12 layui-col-md6">
<div class="layui-col-sm12">
<div class="layui-card">
<div class="layui-card-body">
<div id="loginEChart" style="width: 100%; height: 267px;"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="assets/js/vue.min.js"></script>
<script type="text/javascript" src="assets/js/echarts.min.js"></script>
<script src="assets/layui/layui.js"></script>
<script>
layui.config({
base: 'assets/layui/modules/'
}).extend({}).use(['layer', 'animate-numbers'], function () {
var $ = layui.$;
new Vue({
el: '#app',
data: {
requestCount: 0,
requestTodayCount: 0,
routeTypeCount: 0,
routeCount: 0
},
watch: {
'requestCount': function(value, old) {
$('#requestCount').animateNumbers(value);
},
'requestTodayCount': function(value, old) {
$('#requestTodayCount').animateNumbers(value);
},
'routeTypeCount': function(value, old) {
$('#routeTypeCount').animateNumbers(value);
},
'routeCount': function(value, old) {
$('#routeCount').animateNumbers(value);
},
},
methods: {
sseCountHome: function() {
var self = this;
var source = new EventSource(top.restAjax.path('api/count/count-home', []));
source.addEventListener('message', function(e) {
var data = JSON.parse(e.data);
self.requestCount = data.requestCount;
self.requestTodayCount = data.requestTodayCount;
self.routeTypeCount = data.routeTypeCount;
self.routeCount = data.routeCount;
});
source.addEventListener('open', function(e) {}, false);
// 响应finish事件主动关闭EventSource
source.addEventListener('finish', function(e) {
source.close();
}, false);
// 异常
source.addEventListener('error', function(e) {
if (e.readyState == EventSource.CLOSED) {
console.log("连接关闭");
} else {
console.log(e);
}
}, false);
},
countHome: function() {
var self = this;
if (window.EventSource) {
self.sseCountHome();
} else {
console.log('浏览器不支持sse');
}
}
},
mounted: function() {
var self = this;
self.countHome();
}
})
});
</script>
</body>
</html>

View File

@ -8,9 +8,8 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="icon" href="assets/favicon.ico" type="image/x-icon"/>
<link rel="stylesheet" href="assets/layui-v2.6.4/layui/css/layui.css"/>
<link rel="stylesheet" href="assets/layui-v2.6.4/layui/css/admin.css"/>
<link rel="stylesheet" href="assets/layui-v2.6.4/layui/css/admin.css"/>
<link rel="stylesheet" href="assets/layui/css/layui.css"/>
<link rel="stylesheet" href="assets/layui/css/admin.css"/>
</head>
<body>
<div class="layui-app">
@ -34,18 +33,18 @@
<div class="iframe-container">
<div class="iframe-breadcrumb-box">
<span id="breadcrumbTitle" class="layui-breadcrumb">
<a href="">首页</a>
<a href="javascript:void(0);" class="menu-item" data-href="home.html">首页</a>
</span>
</div>
<div class="iframe-box">
<iframe id="defaultIFrame" frameborder="0" class="layadmin-iframe"></iframe>
<iframe id="defaultIFrame" frameborder="0" border="0" class="layadmin-iframe"></iframe>
</div>
</div>
</div>
<script src="assets/layui-v2.6.4/layui/layui.js"></script>
<script src="assets/layui/layui.js"></script>
<script>
layui.config({
base: 'assets/layui-v2.6.4/layui/modules/'
base: 'assets/layui/modules/'
}).extend({}).use(['restajax', 'datamessage', 'dialog'], function () {
var $ = layui.$;
var $win = $(window);
@ -57,14 +56,14 @@
function resize() {
$('#defaultIFrame').css({
width: ($win.width() - 30) +'px',
height: ($win.height() - 145) +'px'
height: ($win.height() - 140) +'px'
})
}
resize();
window.onresize = resize;
$('#defaultIFrame').attr('src', 'route/route/list.html');
$('#defaultIFrame').attr('src', 'home.html');
$('.menu-item').on('click', function() {
$('#defaultIFrame').attr('src', this.dataset.href);

View File

@ -8,8 +8,8 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="icon" href="assets/favicon.ico" type="image/x-icon"/>
<link rel="stylesheet" href="assets/layui-v2.6.4/layui/css/layui.css"/>
<link rel="stylesheet" href="assets/layui-v2.6.4/layui/css/admin.css"/>
<link rel="stylesheet" href="assets/layui/css/layui.css"/>
<link rel="stylesheet" href="assets/layui/css/admin.css"/>
<script>
if(top.location != window.location) {
top.location.href = window.location.href;
@ -39,10 +39,10 @@
</div>
</div>
</div>
<script src="assets/layui-v2.6.4/layui/layui.js"></script>
<script src="assets/layui/layui.js"></script>
<script>
layui.config({
base: 'assets/layui-v2.6.4/layui/modules/'
base: 'assets/layui/modules/'
}).extend({}).use(['form', 'restajax', 'datamessage', 'dialog'], function () {
var $ = layui.$;
var $win = $(window);

View File

@ -7,8 +7,8 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="stylesheet" href="assets/font/font-awesome/css/font-awesome.min.css">
<link rel="stylesheet" href="assets/layui-v2.6.4/layui/css/layui.css">
<link rel="stylesheet" href="assets/layui-v2.6.4/layui/css/admin.css"/>
<link rel="stylesheet" href="assets/layui/css/layui.css">
<link rel="stylesheet" href="assets/layui/css/admin.css"/>
</head>
<body>
<div class="layui-anim layui-anim-fadein list-page-container">
@ -40,10 +40,10 @@
</div>
</script>
</div>
<script src="assets/layui-v2.6.4/layui/layui.js"></script>
<script src="assets/layui/layui.js"></script>
<script>
layui.config({
base: 'assets/layui-v2.6.4/layui/modules/'
base: 'assets/layui/modules/'
}).extend({}).use(['layer', 'table'], function () {
var $ = layui.$;
var $win = $(window);
@ -66,9 +66,11 @@
});
}
function initTable() {
top.restAjax.get(top.restAjax.path(tableData.tableUrl, []), {
keywords: $('#keywords').val(),
}, null, function(code, data) {
var params = {};
if($('#keywords').val()) {
params.keywords = $('#keywords').val()
}
top.restAjax.get(top.restAjax.path(tableData.tableUrl, []), params, null, function(code, data) {
tableData.dataArray = [];
for(var i = 0, item; item = data[i++];) {
tableData.dataArray.push(item);
@ -81,10 +83,11 @@
elem: '#dataTable',
id: 'dataTable',
width: '100%',
height: $win.height() - 78,
height: $win.height() - 73,
limit: 20,
limits: [20, 40, 60, 80, 100, 200],
toolbar: '#headerToolBar',
defaultToolbar: [],
cols: [[
{type: 'checkbox', fixed: 'left'},
{field: 'rowNum', width: 80, title: '序号', fixed: 'left', align: 'center', templet: '<span>{{d.LAY_INDEX}}</span>'},

View File

@ -6,8 +6,8 @@
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="stylesheet" href="assets/layui-v2.6.4/layui/css/layui.css">
<link rel="stylesheet" href="assets/layui-v2.6.4/layui/css/admin.css"/>
<link rel="stylesheet" href="assets/layui/css/layui.css">
<link rel="stylesheet" href="assets/layui/css/admin.css"/>
</head>
<body>
<div class="layui-anim layui-anim-fadein">
@ -44,10 +44,10 @@
</div>
</div>
</div>
<script src="assets/layui-v2.6.4/layui/layui.js"></script>
<script src="assets/layui/layui.js"></script>
<script>
layui.config({
base: 'assets/layui-v2.6.4/layui/modules/'
base: 'assets/layui/modules/'
}).extend({}).use(['form', 'laydate', 'laytpl', 'regex'], function(){
var $ = layui.$;
var form = layui.form;

View File

@ -6,8 +6,8 @@
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="stylesheet" href="assets/layui-v2.6.4/layui/css/layui.css">
<link rel="stylesheet" href="assets/layui-v2.6.4/layui/css/admin.css"/>
<link rel="stylesheet" href="assets/layui/css/layui.css">
<link rel="stylesheet" href="assets/layui/css/admin.css"/>
</head>
<body>
<div class="layui-anim layui-anim-fadein">
@ -44,10 +44,10 @@
</div>
</div>
</div>
<script src="assets/layui-v2.6.4/layui/layui.js"></script>
<script src="assets/layui/layui.js"></script>
<script>
layui.config({
base: 'assets/layui-v2.6.4/layui/modules/'
base: 'assets/layui/modules/'
}).extend({}).use(['form', 'laydate', 'laytpl', 'regex'], function(){
var $ = layui.$;
var form = layui.form;

View File

@ -7,15 +7,24 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="stylesheet" href="assets/font/font-awesome/css/font-awesome.min.css">
<link rel="stylesheet" href="assets/layui-v2.6.4/layui/css/layui.css">
<link rel="stylesheet" href="assets/layui-v2.6.4/layui/css/admin.css"/>
<link rel="stylesheet" href="assets/layui/css/layui.css">
<link rel="stylesheet" href="assets/layui/css/admin.css"/>
</head>
<body>
<div class="layui-anim layui-anim-fadein list-page-container">
<div class="test-table-reload-btn">
<div class="layui-inline">
<input type="text" id="keywords" class="layui-input search-item" placeholder="输入关键字">
<input type="text" id="keywords" class="layui-input search-item search-item-width-100" placeholder="输入关键字">
</div>
<div class="layui-inline layui-form search-item search-item-width-100" id="routeTypeTplBox"></div>
<script id="routeTypeTpl" type="text/html">
<select id="routeType" name="routeType" lay-filter="routeTypeFilter">
<option value="">路由分类</option>
{{# for(var i = 0, item; item = d.data[i++];) { }}
<option value="{{item.uuid}}">{{item.title}}</option>
{{# } }}
</select>
</script>
<div class="layui-btn-group">
<button type="button" id="search" class="layui-btn layui-btn-sm">
<i class="fa fa-lg fa-search"></i> 搜索
@ -43,14 +52,16 @@
</div>
</script>
</div>
<script src="assets/layui-v2.6.4/layui/layui.js"></script>
<script src="assets/layui/layui.js"></script>
<script>
layui.config({
base: 'assets/layui-v2.6.4/layui/modules/'
base: 'assets/layui/modules/'
}).extend({}).use(['layer', 'table'], function () {
var $ = layui.$;
var $win = $(window);
var layer = layui.layer;
var laytpl = layui.laytpl;
var form = layui.form;
var table = layui.table;
var laydate = layui.laydate;
var resizeTimeout = null;
@ -59,6 +70,18 @@
dataArray: [],
currentPage: null
}
// 初始化路由类型
function initRouteType() {
top.restAjax.get(top.restAjax.path('api/route-type/list', []), {}, null, function(code, data) {
laytpl(document.getElementById('routeTypeTpl').innerHTML).render({data: data}, function(html) {
document.getElementById('routeTypeTplBox').innerHTML = html;
});
form.render('select');
}, function(code, data) {
top.dialog.msg(data.msg);
});
}
initRouteType();
function reloadTable(currentPage) {
table.reload('dataTable', {
@ -69,9 +92,14 @@
});
}
function initTable() {
top.restAjax.get(top.restAjax.path(tableData.tableUrl, []), {
keywords: $('#keywords').val(),
}, null, function(code, data) {
var params = {};
if($('#keywords').val()) {
params.keywords = $('#keywords').val()
}
if($('#routeType').val()) {
params.routeType = $('#routeType').val();
}
top.restAjax.get(top.restAjax.path(tableData.tableUrl, []), params, null, function(code, data) {
tableData.dataArray = [];
for(var i = 0, item; item = data[i++];) {
tableData.dataArray.push(item);
@ -84,10 +112,11 @@
elem: '#dataTable',
id: 'dataTable',
width: '100%',
height: $win.height() - 78,
height: $win.height() - 73,
limit: 20,
limits: [20, 40, 60, 80, 100, 200],
toolbar: '#headerToolBar',
defaultToolbar: [],
cols: [[
{type: 'checkbox', fixed: 'left'},
{field: 'rowNum', width: 80, title: '序号', fixed: 'left', align: 'center', templet: '<span>{{d.LAY_INDEX}}</span>'},

View File

@ -6,8 +6,8 @@
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="stylesheet" href="assets/layui-v2.6.4/layui/css/layui.css">
<link rel="stylesheet" href="assets/layui-v2.6.4/layui/css/admin.css"/>
<link rel="stylesheet" href="assets/layui/css/layui.css">
<link rel="stylesheet" href="assets/layui/css/admin.css"/>
</head>
<body>
<div class="layui-anim layui-anim-fadein">
@ -21,30 +21,32 @@
<div class="layui-card-body" style="padding: 15px;">
<form class="layui-form layui-form-pane" lay-filter="dataForm">
<div class="layui-form-item">
<label class="layui-form-label">名称</label>
<label class="layui-form-label">映射名称 *</label>
<div class="layui-input-block">
<input type="text" name="title" class="layui-input" lay-verify="required" placeholder="请输入名称">
<input type="text" name="title" class="layui-input" lay-verify="required" placeholder="请输入映射名称">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">描述</label>
<label class="layui-form-label">映射描述 *</label>
<div class="layui-input-block">
<input type="text" name="summary" class="layui-input" lay-verify="required" placeholder="请输入描述">
<input type="text" name="summary" class="layui-input" lay-verify="required" placeholder="请输入映射描述">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">映射路径</label>
<label class="layui-form-label">映射路径 *</label>
<div class="layui-input-block">
<input type="text" name="path" class="layui-input" lay-verify="required|path" placeholder="请输入映射路径">
<div class="layui-form-mid layui-word-aux">
直接访问网关的路径<br/>
不能以 /wg/ 开头 <br/>
根路径不能设置通配符,如:/**<br/>
支持通配符,如:/p1/**表示p1后的人和路径都匹配<br/>
路径中的变量用{}包含,如:/p2/{pq1}/{pq2}
</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">被映射服务</label>
<label class="layui-form-label">被映射服务 *</label>
<div class="layui-input-block">
<input type="text" name="uri" class="layui-input" lay-verify="required|uri" placeholder="请输入服务地址">
<div class="layui-form-mid layui-word-aux">
@ -54,12 +56,38 @@
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">测试接口</label>
<label class="layui-form-label">测试接口 *</label>
<div class="layui-input-block">
<input type="text" name="testPath" class="layui-input" lay-verify="required|path" placeholder="填写测试接口地址">
<input type="text" name="testPath" class="layui-input" lay-verify="path" placeholder="填写测试接口地址">
<div class="layui-form-mid layui-word-aux">填写测试接口地址,如:/p1/a/b/c</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">路由分类</label>
<div class="layui-input-block" id="routeTypeTplBox"></div>
<script id="routeTypeTpl" type="text/html">
<select name="routeType" lay-filter="routeTypeFilter">
<option value="">请选择路由分类</option>
{{# for(var i = 0, item; item = d.data[i++];) { }}
<option value="{{item.uuid}}">{{item.title}}</option>
{{# } }}
</select>
</script>
</div>
<div class="layui-form-item">
<label class="layui-form-label">设置路径</label>
<div class="layui-input-block">
<input type="text" name="setPath" class="layui-input" lay-verify="path" placeholder="请设置路径">
<div class="layui-form-mid layui-word-aux">
网关转发实际地址时的路径,不支持通配符,如:填写 /a 在实际转发时,会把 <b>映射路径</b> 替换为 /a如果是根路径填写 / 即可<br/>
示例说明:<br/>
请求网关的地址为http:127.0.0.1:9999/baidu<br/>
实际的转发地址为https://www.baidu.com<br/>
如果设置路径那么实际的访问方式为https://www.baidu.com/<b>baidu</b>,会导致百度无法找到这个路径<br/>
将路径设置为 / 之后实际的请求路径就变为https://www.baidu.com
</div>
</div>
</div>
<div class="layui-form-item layui-layout-admin">
<div class="layui-input-block">
<div class="footer-button-box layui-btn-group">
@ -72,23 +100,37 @@
</div>
</div>
</div>
<script src="assets/layui-v2.6.4/layui/layui.js"></script>
<script src="assets/layui/layui.js"></script>
<script>
layui.config({
base: 'assets/layui-v2.6.4/layui/modules/'
base: 'assets/layui/modules/'
}).extend({}).use(['form', 'laydate', 'laytpl', 'regex'], function(){
var $ = layui.$;
var form = layui.form;
var layer = layui.layer;
var regex = layui.regex;
var laytpl = layui.laytpl;
var uuid = top.restAjax.params(window.location.href).uuid;
function closeBox() {
parent.layer.close(parent.layer.getFrameIndex(window.name));
}
// 初始化路由类型
function initRouteType() {
top.restAjax.get(top.restAjax.path('api/route-type/list', []), {}, null, function(code, data) {
laytpl(document.getElementById('routeTypeTpl').innerHTML).render({data: data}, function(html) {
document.getElementById('routeTypeTplBox').innerHTML = html;
});
form.render('select', 'dataForm');
}, function(code, data) {
top.dialog.msg(data.msg);
});
}
// 初始化内容
function initData() {
initRouteType();
}
initData();
@ -133,6 +175,9 @@
}
},
path: function(value, item) {
if(!value) {
return;
}
if(!regex.path(value)) {
return '路径格式不正确'
}

View File

@ -6,8 +6,8 @@
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="stylesheet" href="assets/layui-v2.6.4/layui/css/layui.css">
<link rel="stylesheet" href="assets/layui-v2.6.4/layui/css/admin.css"/>
<link rel="stylesheet" href="assets/layui/css/layui.css">
<link rel="stylesheet" href="assets/layui/css/admin.css"/>
</head>
<body>
<div class="layui-anim layui-anim-fadein">
@ -21,30 +21,32 @@
<div class="layui-card-body" style="padding: 15px;">
<form class="layui-form layui-form-pane" lay-filter="dataForm">
<div class="layui-form-item">
<label class="layui-form-label">名称</label>
<label class="layui-form-label">映射名称 *</label>
<div class="layui-input-block">
<input type="text" name="title" class="layui-input" lay-verify="required" placeholder="请输入名称">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">描述</label>
<label class="layui-form-label">映射描述 *</label>
<div class="layui-input-block">
<input type="text" name="summary" class="layui-input" lay-verify="required" placeholder="请输入描述">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">映射路径</label>
<label class="layui-form-label">映射路径 *</label>
<div class="layui-input-block">
<input type="text" name="path" class="layui-input" lay-verify="required|path" placeholder="请输入映射路径">
<div class="layui-form-mid layui-word-aux">
直接访问网关的路径<br/>
不能以 /wg/ 开头 <br/>
根路径不能设置通配符,如:/**<br/>
支持通配符,如:/p1/**表示p1后的人和路径都匹配<br/>
路径中的变量用{}包含,如:/p2/{pq1}/{pq2}
</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">被映射服务</label>
<label class="layui-form-label">被映射服务 *</label>
<div class="layui-input-block">
<input type="text" name="uri" class="layui-input" lay-verify="required|uri" placeholder="请输入服务地址">
<div class="layui-form-mid layui-word-aux">
@ -54,12 +56,38 @@
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">测试接口</label>
<label class="layui-form-label">测试接口 *</label>
<div class="layui-input-block">
<input type="text" name="testPath" class="layui-input" lay-verify="required|path" placeholder="填写测试接口地址">
<div class="layui-form-mid layui-word-aux">填写测试接口地址,如:/p1/a/b/c</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">路由分类</label>
<div class="layui-input-block" id="routeTypeTplBox"></div>
<script id="routeTypeTpl" type="text/html">
<select name="routeType" lay-filter="routeTypeFilter">
<option value="">请选择路由分类</option>
{{# for(var i = 0, item; item = d.data[i++];) { }}
<option value="{{item.uuid}}">{{item.title}}</option>
{{# } }}
</select>
</script>
</div>
<div class="layui-form-item">
<label class="layui-form-label">设置路径</label>
<div class="layui-input-block">
<input type="text" name="setPath" class="layui-input" lay-verify="path" placeholder="请设置路径">
<div class="layui-form-mid layui-word-aux">
网关转发实际地址时的路径,不支持通配符,如:填写 /a 在实际转发时,会把 <b>映射路径</b> 替换为 /a如果是根路径填写 / 即可<br/>
示例说明:<br/>
请求网关的地址为http:127.0.0.1:9999/baidu<br/>
实际的转发地址为https://www.baidu.com<br/>
如果设置路径那么实际的访问方式为https://www.baidu.com/<b>baidu</b>,会导致百度无法找到这个路径<br/>
将路径设置为 / 之后实际的请求路径就变为https://www.baidu.com
</div>
</div>
</div>
<div class="layui-form-item layui-layout-admin">
<div class="layui-input-block">
<div class="footer-button-box layui-btn-group">
@ -72,21 +100,35 @@
</div>
</div>
</div>
<script src="assets/layui-v2.6.4/layui/layui.js"></script>
<script src="assets/layui/layui.js"></script>
<script>
layui.config({
base: 'assets/layui-v2.6.4/layui/modules/'
base: 'assets/layui/modules/'
}).extend({}).use(['form', 'laydate', 'laytpl', 'regex'], function(){
var $ = layui.$;
var form = layui.form;
var layer = layui.layer;
var regex = layui.regex;
var laytpl = layui.laytpl;
var uuid = top.restAjax.params(window.location.href).uuid;
function closeBox() {
parent.layer.close(parent.layer.getFrameIndex(window.name));
}
// 初始化路由类型
function initRouteType(selectValue) {
top.restAjax.get(top.restAjax.path('api/route-type/list', []), {}, null, function(code, data) {
laytpl(document.getElementById('routeTypeTpl').innerHTML).render({data: data}, function(html) {
document.getElementById('routeTypeTplBox').innerHTML = html;
});
form.val('dataForm', {routeType: selectValue});
form.render('select', 'dataForm');
}, function(code, data) {
top.dialog.msg(data.msg);
});
}
// 初始化内容
function initData() {
var loadLayerIndex;
@ -95,6 +137,7 @@
for(var i in data) {
dataFormData[i] = data[i] +'';
}
initRouteType(data.routeType);
form.val('dataForm', dataFormData);
form.render(null, 'dataForm');
}, function(code, data) {
@ -148,6 +191,9 @@
}
},
path: function(value, item) {
if(!value) {
return;
}
if(!regex.path(value)) {
return '路径格式不正确'
}