Commit e7febe5c authored by 李成龙's avatar 李成龙

增加网关

parent 865fe5af
...@@ -20,6 +20,55 @@ ...@@ -20,6 +20,55 @@
<artifactId>amos-boot-module-tzs-api</artifactId> <artifactId>amos-boot-module-tzs-api</artifactId>
<version>${amos-biz-boot.version}</version> <version>${amos-biz-boot.version}</version>
</dependency> </dependency>
</dependencies> <!-- spring-cloud网关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--Spring Webflux-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!-- 熔断、降级 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<!--健康监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 限流Redis实现 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<!--springboot2.X默认使用lettuce连接池,需要引入commons-pool2-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!--server-api-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project> </project>
package com.yeejoin.amos.server.gateway.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
import static org.springframework.web.cors.CorsConfiguration.ALL;
@Configuration
public class Cors {
private static final String MAX_AGE = "18000L";
@Bean
public CorsResponseHeaderFilter corsResponseHeaderFilter() {
return new CorsResponseHeaderFilter();
}
@Bean
public WebFilter corsFilter() {
return (ServerWebExchange ctx, WebFilterChain chain) -> {
ServerHttpRequest request = ctx.getRequest();
if (!CorsUtils.isCorsRequest(request)) {
return chain.filter(ctx);
}
HttpHeaders requestHeaders = request.getHeaders();
ServerHttpResponse response = ctx.getResponse();
HttpMethod requestMethod = requestHeaders.getAccessControlRequestMethod();
HttpHeaders headers = response.getHeaders();
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
headers.addAll(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, requestHeaders.getAccessControlRequestHeaders());
if (requestMethod != null) {
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, requestMethod.name());
}
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, ALL);
headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, MAX_AGE);
if (request.getMethod() == HttpMethod.OPTIONS) {
response.setStatusCode(HttpStatus.OK);
return Mono.empty();
}
return chain.filter(ctx);
};
}
}
package com.yeejoin.amos.server.gateway.config;
import java.util.ArrayList;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.NettyWriteResponseFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
public class CorsResponseHeaderFilter implements GlobalFilter, Ordered{
@Override
public int getOrder() {
// 指定此过滤器位于NettyWriteResponseFilter之后
// 即待处理完响应体后接着处理响应头
return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER + 1;
}
@Override
@SuppressWarnings("serial")
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//过滤相同的ACCESS_CONTROL_ALLOW_ORIGIN 和 ACCESS_CONTROL_ALLOW_CREDENTIALS
return chain.filter(exchange).then(Mono.defer(() -> {
exchange.getResponse().getHeaders().entrySet().stream()
.filter(kv -> (kv.getValue() != null && kv.getValue().size() > 1))
.filter(kv -> (kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)
|| kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)))
.forEach(kv ->
{
kv.setValue(new ArrayList<String>() {{add(kv.getValue().get(0));}});
});
return chain.filter(exchange);
}));
}
}
package com.yeejoin.amos.server.gateway.config;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
public class CustomeGatewayFilter implements GatewayFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return null;
}
}
package com.yeejoin.amos.server.gateway.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.StripPrefixGatewayFilterFactory;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class GatewayInfo {
static StripPrefixGatewayFilterFactory stripPrefixGatewayFilterFactory = new StripPrefixGatewayFilterFactory();
static GatewayFilter gatewayFilter;
static {
StripPrefixGatewayFilterFactory.Config config = new StripPrefixGatewayFilterFactory.Config();
config.setParts(1);
gatewayFilter = stripPrefixGatewayFilterFactory.apply(config);
}
// @Value("${elecfire_converter_statton_service}")
// private String elecfire_converter_statton_service;
//
// @Value("${elecfire_converter_statton_patrol}")
// private String elecfire_converter_statton_patrol;
//
// @Value("${elecfire_converter_statton_3dservice}")
// private String elecfire_converter_statton_3dservice;
//
// @Value("${elecfire_converter_statton_duty}")
// private String DUTY_ERUKA_NAME;
//
//
// @Value("${elecfire_converter_statton_aixah}")
// private String AI_XAH_JD;
//
// @Value("${elecfire_converter_statton_equipmanage}")
// private String AMOS_EQUIPMANAGE;
//
// @Value("${visual_morphic}")
// private String visual_morphic;
//
// @Value("${elecfire_converter_statton_intelligentbox}")
// private String AMOS_API_INTELLIGENTBOX;
/**
*
* @param builder
* @return
*/
@Bean
public RouteLocator myRoutes(RouteLocatorBuilder builder) {
return builder.routes().route(p -> p.path("/privilege/**").uri("lb://AMOS-API-PRIVILEGE"))
.route(p -> p.path("/systemctl/**").uri("lb://AMOS-API-SYSTEMCTL"))
.route(p -> p.path("/urule/**").uri("lb://AMOS-API-RULE"))
// .route(p -> p.path("/fireAutoSys/**").uri("lb://" + elecfire_converter_statton_service))
//
// .route(p -> p.path("/patrol/**").uri("lb://" + elecfire_converter_statton_patrol))
//
// // 值班
// .route(p -> p.path("/duty/**").uri("lb://" + DUTY_ERUKA_NAME))
// .route(p -> p.path("/api/common/user/list/**").uri("lb://" + DUTY_ERUKA_NAME))
// // AI消安盒
// .route(p -> p.path("/intelligentbox/**").uri("lb://" + AMOS_API_INTELLIGENTBOX))
// .route(p -> p.path("/tsioservice/**").uri(AI_XAH_JD))
// //队站-装备信息系统
// .route(p -> p.path("/equip/**").uri("lb://" + AMOS_EQUIPMANAGE))
//// .route(p -> p.path("/equip-1225/**").uri("lb://" + AMOS_EQUIPMANAGE))
// //组态
// .route(p -> p.path("/morphic/**").uri("lb://" + visual_morphic))
.build();
}
}
package com.yeejoin.amos.server.gateway.face.model;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* 过滤器模型
* zhuyu 2019-01-17
*/
public class GatewayFilterDefinition {
//Filter Name
private String name;
//对应的路由规则
private Map<String, String> args = new LinkedHashMap<>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Map<String, String> getArgs() {
return args;
}
public void setArgs(Map<String, String> args) {
this.args = args;
}
}
package com.yeejoin.amos.server.gateway.face.model;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* 路由断言模型
* zhuyu 2019-01-17
*/
public class GatewayPredicateDefinition {
//断言对应的Name
private String name;
//配置的断言规则
private Map<String, String> args = new LinkedHashMap<>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Map<String, String> getArgs() {
return args;
}
public void setArgs(Map<String, String> args) {
this.args = args;
}
}
package com.yeejoin.amos.server.gateway.face.model;
import java.util.ArrayList;
import java.util.List;
/**
* 路由模型
* zhuyu 2019-01-17
*/
public class GatewayRouteDefinition {
//路由的Id
private String id;
//路由断言集合配置
private List<GatewayPredicateDefinition> predicates = new ArrayList<>();
//路由过滤器集合配置
private List<GatewayFilterDefinition> filters = new ArrayList<>();
//路由规则转发的目标uri
private String uri;
//路由执行的顺序
private int order = 0;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public List<GatewayPredicateDefinition> getPredicates() {
return predicates;
}
public void setPredicates(List<GatewayPredicateDefinition> predicates) {
this.predicates = predicates;
}
public List<GatewayFilterDefinition> getFilters() {
return filters;
}
public void setFilters(List<GatewayFilterDefinition> filters) {
this.filters = filters;
}
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
}
package com.yeejoin.amos.server.gateway.face.service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/**
* 默认降级处理
*/
@RestController
public class DefaultHystrixController {
@RequestMapping("/defaultfallback")
public Map<String,String> defaultfallback(){
System.out.println("降级操作...");
Map<String,String> map = new HashMap<>();
map.put("resultCode","fail");
map.put("resultMessage","服务异常");
map.put("resultObj","null");
return map;
}
}
package com.yeejoin.amos.server.gateway.face.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
/**
* 动态路由服务
*/
@Service
public class DynamicRouteServiceImpl implements ApplicationEventPublisherAware{
@Autowired
private RouteDefinitionWriter routeDefinitionWriter;
private ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
//增加路由
public String add(RouteDefinition definition) {
routeDefinitionWriter.save(Mono.just(definition)).subscribe();
this.publisher.publishEvent(new RefreshRoutesEvent(this));
return "success";
}
// //更新路由
// public String update(RouteDefinition definition) {
// try {
// delete(definition.getId());
// } catch (Exception e) {
// return "update fail,not find route routeId: "+definition.getId();
// }
// try {
// routeDefinitionWriter.save(Mono.just(definition)).subscribe();
// this.publisher.publishEvent(new RefreshRoutesEvent(this));
// return "success";
// } catch (Exception e) {
// return "update route fail";
// }
// }
// //删除路由
// public Mono<ResponseEntity<Object>> delete(String id) {
// return this.routeDefinitionWriter.delete(Mono.just(id)).then(Mono.defer(() -> {
// return Mono.just(ResponseEntity.ok().build());
// })).onErrorResume((t) -> {
// return t instanceof NotFoundException;
// }, (t) -> {
// return Mono.just(ResponseEntity.notFound().build());
// });
// }
}
package com.yeejoin.amos.server.gateway.face.service;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;
/**
* 路由限流配置
* @author zhuyu
* @date 2019/1/15
*/
@Configuration
public class RateLimiterConfig {
@Bean(value = "remoteAddrKeyResolver")
public KeyResolver remoteAddrKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment