解决页面重定向跳转到原有系统问题,基本路由功能完成

This commit is contained in:
wanggeng888 2021-04-25 21:53:35 +08:00
parent f68dafdff8
commit 3706152447
13 changed files with 163 additions and 72 deletions

View File

@ -1,8 +1,7 @@
package ink.wgink.gateway.component;
import ink.wgink.gateway.consts.ISystemConst;
import ink.wgink.gateway.dao.route.IRouteDao;
import ink.wgink.gateway.filter.local.CommonFilters;
import ink.wgink.gateway.filter.local.CommonFiltersDefinition;
import ink.wgink.gateway.pojo.route.Route;
import ink.wgink.gateway.util.UUIDUtil;
import org.springframework.cloud.gateway.filter.FilterDefinition;
@ -98,13 +97,11 @@ public class MongoRouteDefinitionRepository implements RouteDefinitionRepository
* @return
*/
private List<FilterDefinition> listFilterDefinition(Route route) {
CommonFilters commonFilters = new CommonFilters();
CommonFiltersDefinition commonFiltersDefinition = new CommonFiltersDefinition();
// 定义过滤器
List<FilterDefinition> filterDefinitions = new ArrayList<>();
// 添加重写过滤
filterDefinitions.add(commonFilters.rewriteFilterDefinition(route));
// 去除前缀
// filterDefinitions.add(commonFilters.setPathFilterDefinition(route));
// 重写响应头中的location解决重定向问题
filterDefinitions.add(commonFiltersDefinition.rewriteLocationResponseHeader(route));
return filterDefinitions;
}

View File

@ -20,5 +20,6 @@ public interface ISystemConst {
String ADMIN_ROUTER_PREFIX = "/wg";
String PAGE_LOGIN = "/wg/login.html";
String ROUTE_PREFIX = "/gw";
String ROOT_PATH_PREFIX = "/*";
}

View File

@ -1,55 +0,0 @@
package ink.wgink.gateway.filter.local;
import ink.wgink.gateway.consts.ISystemConst;
import ink.wgink.gateway.pojo.route.Route;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.SetPathGatewayFilterFactory;
import java.util.HashMap;
import java.util.Map;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: CommonFilters
* @Description: 通用过滤器
* @Author: WangGeng
* @Date: 2021/4/24 20:31
* @Version: 1.0
**/
public class CommonFilters {
/**
* 重写过滤器
*
* @param route
* @return
*/
public FilterDefinition rewriteFilterDefinition(Route route) {
FilterDefinition rewritePathFilterDefinition = new FilterDefinition();
Map<String, String> rewritePathFilterDefinitionMap = new HashMap<>(4);
rewritePathFilterDefinitionMap.put(RewritePathGatewayFilterFactory.REGEXP_KEY, ISystemConst.ROUTE_PREFIX + "/?(?<segment>.*)");
rewritePathFilterDefinitionMap.put(RewritePathGatewayFilterFactory.REPLACEMENT_KEY, "/$\\{segment}");
rewritePathFilterDefinition.setArgs(rewritePathFilterDefinitionMap);
rewritePathFilterDefinition.setName("RewritePath");
return rewritePathFilterDefinition;
}
/**
* 设置路径过滤器去除前缀
*
* @param route
* @return
*/
public FilterDefinition setPathFilterDefinition(Route route) {
FilterDefinition setPathFilterDefinition = new FilterDefinition();
Map<String, String> setPathFilterDefinitionMap = new HashMap<>(2);
setPathFilterDefinitionMap.put(SetPathGatewayFilterFactory.TEMPLATE_KEY, route.getPath().replaceFirst(ISystemConst.ROUTE_PREFIX, "/"));
setPathFilterDefinition.setArgs(setPathFilterDefinitionMap);
setPathFilterDefinition.setName("SetPath");
return setPathFilterDefinition;
}
}

View File

@ -0,0 +1,72 @@
package ink.wgink.gateway.filter.local;
import ink.wgink.gateway.consts.ISystemConst;
import ink.wgink.gateway.pojo.route.Route;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.filter.factory.RewriteLocationResponseHeaderGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.RewriteResponseHeaderGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.SetPathGatewayFilterFactory;
import java.util.HashMap;
import java.util.Map;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: CommonFilters
* @Description: 通用过滤器
* @Author: WangGeng
* @Date: 2021/4/24 20:31
* @Version: 1.0
**/
public class CommonFiltersDefinition {
/**
* 重写过滤器将路径中的gw删除暂时无用
*
* @param route
* @return
*/
public FilterDefinition rewritePath(Route route) {
FilterDefinition rewritePath = new FilterDefinition();
Map<String, String> rewritePathMap = new HashMap<>(4);
rewritePathMap.put(RewritePathGatewayFilterFactory.REGEXP_KEY, ISystemConst.ROUTE_PREFIX + "/?(?<segment>.*)");
rewritePathMap.put(RewritePathGatewayFilterFactory.REPLACEMENT_KEY, "/$\\{segment}");
rewritePath.setArgs(rewritePathMap);
rewritePath.setName("RewritePath");
return rewritePath;
}
/**
* 设置路径过滤器去除前缀将路径中的gw删除暂时无用
*
* @param route
* @return
*/
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, "/"));
setPath.setArgs(setPathMap);
setPath.setName("SetPath");
return setPath;
}
/**
* 重写响应头中的地址信息
*
* @param route
* @return
*/
public FilterDefinition rewriteLocationResponseHeader(Route route) {
FilterDefinition rewriteLocationResponse = new FilterDefinition();
Map<String, String> rewriteLocationResponseMap = new HashMap<>(2);
rewriteLocationResponseMap.put("stripVersionMode", RewriteLocationResponseHeaderGatewayFilterFactory.StripVersion.AS_IN_REQUEST.toString());
rewriteLocationResponseMap.put("hostValue", "Location");
rewriteLocationResponse.setName("RewriteLocationResponseHeader");
return rewriteLocationResponse;
}
}

View File

@ -52,7 +52,7 @@ public class WebFluxFilter implements WebFilter {
ServerHttpResponse serverHttpResponse = serverWebExchange.getResponse();
HttpHeaders headers = serverHttpResponse.getHeaders();
// 校验登录的路径管理使用
if(this.isUnPass(serverWebExchange)) {
if (this.isUnPass(serverWebExchange)) {
// 直接放行的路径
if (this.isPass(serverWebExchange)) {
return webFilterChain.filter(serverWebExchange);

View File

@ -1,10 +1,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.handler.BaseHandler;
import ink.wgink.gateway.pojo.result.SuccessResult;
import ink.wgink.gateway.pojo.route.Route;
import ink.wgink.gateway.util.RequestFieldCheckUtil;
import ink.wgink.gateway.util.UUIDUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
@ -56,6 +60,10 @@ public class RouteHandler extends BaseHandler implements ApplicationEventPublish
public Mono<ServerResponse> save(ServerRequest serverRequest) {
Mono<Route> routeMono = serverRequest.bodyToMono(Route.class);
return routeMono.flatMap(route -> {
RequestFieldCheckUtil.check(route);
if (route.getPath().startsWith(ISystemConst.ROOT_PATH_PREFIX)) {
return Mono.error(new ParamsException("根路径不能配置通配符"));
}
setSave(route);
return routeDao.save(route);
}).then(ServerResponse.ok().contentType(MediaType.APPLICATION_JSON_UTF8).body(Flux.just(new SuccessResult()), SuccessResult.class));
@ -86,10 +94,15 @@ public class RouteHandler extends BaseHandler implements ApplicationEventPublish
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("根路径不能配置通配符"));
}
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))

View File

@ -1,5 +1,6 @@
package ink.wgink.gateway.pojo.route;
import ink.wgink.gateway.annoation.CheckEmptyAnnotation;
import ink.wgink.gateway.dao.route.IRouteDao;
import ink.wgink.gateway.pojo.BasePOJO;
import lombok.Data;
@ -24,9 +25,15 @@ import java.io.Serializable;
public class Route extends BasePOJO implements Serializable {
private static final long serialVersionUID = -4892456861969101733L;
@CheckEmptyAnnotation(name = "title")
private String title;
@CheckEmptyAnnotation(name = "说明")
private String summary;
@CheckEmptyAnnotation(name = "映射路径", verifyType = "path")
private String path;
@CheckEmptyAnnotation(name = "被映射服务", verifyType = "url")
private String uri;
@CheckEmptyAnnotation(name = "测试接口", verifyType = "path")
private String testPath;
}

View File

@ -36,9 +36,13 @@ public class RegexUtil {
*/
private static final Pattern PATTERN_EMAIL = Pattern.compile("^([a-zA-Z0-9_\\.\\-])+\\@(([a-zA-Z0-9\\-])+\\.)+([a-zA-Z0-9]{2,4})+$");
/**
* 邮箱
* URL
*/
private static final Pattern PATTERN_URL = Pattern.compile("(^#)|(^http(s*):\\/\\/[^\\s]+)");
/**
* 路径
*/
private static final Pattern PATTERN_PATH = Pattern.compile("\\/[^\\s]*");
/**
* 日期格式
*/
@ -164,6 +168,16 @@ public class RegexUtil {
return PATTERN_URL.matcher(input).matches();
}
/**
* 判断PATH
*
* @param input
* @return
*/
public static boolean isPath(String input) {
return PATTERN_PATH.matcher(input).matches();
}
/**
* 判断日期
*
@ -311,8 +325,4 @@ public class RegexUtil {
return path;
}
public static void main(String[] args) {
System.out.println(isHhMmSs("1111111"));
}
}

View File

@ -229,6 +229,11 @@ public class RequestFieldCheckUtil {
throw new ParamsException(String.format("%s格式非url格式", name));
}
return;
} else if (StringUtils.equals("path", verifyType)) {
if (!RegexUtil.isPath(value)) {
throw new ParamsException(String.format("%s格式非路径格式", name));
}
return;
} else if (StringUtils.equals("number", verifyType)) {
if (!NumberUtils.isNumber(value)) {
throw new ParamsException(String.format("%s格式非数字格式", name));

View File

@ -4,6 +4,10 @@ spring:
cloud:
gateway:
enabled: true
httpclient:
# 支持https转发
ssl:
use-insecure-trust-manager: true
data:
mongodb:
uri: mongodb://127.0.0.1:27017/gateway

View File

@ -127,6 +127,15 @@
return rowData;
}
},
{field: 'testPath', width: 200, title: '测试接口', align: 'center', sort: true,
templet: function (row) {
var rowData = row[this.field];
if (typeof (rowData) === 'undefined' || rowData == null || rowData == '') {
return '-';
}
return '<a href="'+ rowData +'" target="_blank">点击测试</a>';
}
},
{field: 'gmtCreate', width: 180, title: '添加时间', align: 'center', sort: true,
templet: function (row) {
var rowData = row[this.field];

View File

@ -36,14 +36,28 @@
<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">直接访问网关的路径,路径中的变量用{}包含,/p2/{pq1}/{pq2}</div>
<div class="layui-form-mid layui-word-aux">
直接访问网关的路径<br/>
支持通配符p1/**表示p1后的人和路径都匹配<br/>
路径中的变量用{}包含,如:/p2/{pq1}/{pq2}
</div>
</div>
</div>
<div class="layui-form-item">
<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">需要映射的服务器uri路径如http://127.0.0.1:8080</div>
<div class="layui-form-mid layui-word-aux">
需要映射的服务器uri路径<br/>
http://127.0.0.1:8080、http://www.baidu.com、https://www.baidu.com
</div>
</div>
</div>
<div class="layui-form-item">
<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 layui-layout-admin">

View File

@ -36,14 +36,28 @@
<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">直接访问网关的路径,路径中的变量用{}包含,/p2/{pq1}/{pq2}</div>
<div class="layui-form-mid layui-word-aux">
直接访问网关的路径<br/>
支持通配符p1/**表示p1后的人和路径都匹配<br/>
路径中的变量用{}包含,如:/p2/{pq1}/{pq2}
</div>
</div>
</div>
<div class="layui-form-item">
<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">需要映射的服务器uri路径如http://127.0.0.1:8080</div>
<div class="layui-form-mid layui-word-aux">
需要映射的服务器uri路径<br/>
http://127.0.0.1:8080、http://www.baidu.com、https://www.baidu.com
</div>
</div>
</div>
<div class="layui-form-item">
<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 layui-layout-admin">