buildscript {
ext{
springBootVersion = '2.1.7.RELEASE'
}
repositories {
maven{ url 'http://nexus.d17w.cn:9092/nexus/content/groups/public'}
maven{ url 'http://repo.spring.io/libs-milestone'}
}
dependencies {
classpath ( "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
classpath ( "io.spring.gradle:dependency-management-plugin:1.0.8.RELEASE")
classpath ( "com.bmuschko:gradle-cargo-plugin:2.6.1")
}
}
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group 'com.claimplat'
version = '1.0.0'
sourceCompatibility = 1.8
targetCompatibility = 1.8
tasks.withType(JavaCompile){
options.encoding = "UTF-8"
}
def env = System.getProperty("package.environment") ?: "dev"
repositories {
maven{ url 'http://nexus.d17w.cn:9092/nexus/content/groups/public'}
maven{ url 'http://repo.spring.io/libs-milestone'}
}
dependencyManagement{
imports {
mavenBom 'org.springframework.cloud:spring-cloud-dependencies:Greenwich.SR2'
}
}
dependencies {
compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-config'
compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-netflix-eureka-client'
compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-gateway'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-webflux'
compile group: 'org.springframework.boot', name: 'spring-boot-autoconfigure'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-logging'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-aop'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-actuator'
compile group: 'org.springframework.boot', name: 'spring-boot-devtools'
testCompile group: 'org.springframework.boot', name: 'spring-boot-starter-test'
testCompile group: 'junit', name: 'junit'
}
注:添加依赖后需要刷新gradle工程(下载依赖)
主启动类如下:
@EnableDiscoveryClient
@SpringBootApplication
public class GatewayApplication implements ApplicationListener{
private static final Logger LOGGER = LoggerFactory.getLogger(GatewayApplication.class);
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
@Override
public void onApplicationEvent(ApplicationEvent event) {
if(event instanceof ApplicationEnvironmentPreparedEvent) {
LOGGER.info("初始化环境变量");
}else if(event instanceof ApplicationPreparedEvent) {
LOGGER.info("初始化完成");
}else if(event instanceof ContextRefreshedEvent) {
LOGGER.info("应用刷新");
}else if(event instanceof ApplicationReadyEvent) {
LOGGER.info("应用已启动完成");
}else if(event instanceof ContextStartedEvent) {
LOGGER.info("应用启动");
}else if(event instanceof ContextStoppedEvent) {
LOGGER.info("应用停止");
}else if(event instanceof ContextClosedEvent) {
LOGGER.info("应用关闭");
}else {
//LOGGER.info("其他事件"+event.toString());
}
}
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route(r -> r.path("/serviceApi/**").filters(f -> f.filter(new MonitoringGatewayFilter()))
.uri("lb://claimplat-service-API"))
.route(r -> r.path("/offline/**").filters(f -> f.filter(new MonitoringGatewayFilter()))
.uri("lb://claimplat-offline"))
.route(r -> r.order(11000).path("/baidu")
.filters(f -> f.addRequestHeader("x-request-uuid", UUID.randomUUID().toString())
.filter(new MonitoringGatewayFilter()))
.uri("https://www.baidu.com"))
.build();
}
@Bean
public RouterFunction defaultRouterFunction(){
RouterFunction route = RouterFunctions.route(RequestPredicates.path("ack"),
request -> ServerResponse.ok().body(BodyInserters.fromObject("ack ok")));
return route;
}
}
filter类如下:
public class MonitoringGatewayFilter implements GatewayFilter,Ordered{
private static final Logger logger = LoggerFactory.getLogger(MonitoringGatewayFilter.class);
@Override
public int getOrder() {
return -2;
}
@Override
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
URI requestURI = exchange.getRequest().getURI();
String requestUUID = UUID.randomUUID().toString();
LocalDateTime beginDateTime = LocalDateTime.now();
//添加x-request-uuid请求头
ServerHttpRequest request = exchange.getRequest().mutate().header("x-request-uuid", requestUUID).build();
ServerWebExchange newExchange = exchange.mutate().request(request).build();
return chain.filter(newExchange).then(Mono.defer(() -> {
if(logger.isInfoEnabled()) {
LocalDateTime endDateTime = LocalDateTime.now();
Duration duration = Duration.between(beginDateTime,endDateTime);
String clientIp = RequestUtil.getClientIp(request);
logger.info("请求的uuid={},请求的ip={},请求的url={},消耗的时间{}ms",requestUUID,clientIp,
requestURI.getPath(),duration.toMillis());
}
return Mono.empty();
}));
}
}
util类如下:
public class RequestUtil {
private static Logger logger = LoggerFactory.getLogger(RequestUtil.class);
/**获取请求主机IP地址,若通过代理进来则透过防火墙获取真实IP地址
* @param request
* @return
*/
public static String getClientIp(ServerHttpRequest request) {
try {
String ip = request.getHeaders().getFirst("X-Real-IP");
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
if(StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeaders().getFirst("X-Forwarded-For");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeaders().getFirst("Proxy-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeaders().getFirst("WL-Proxy-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeaders().getFirst("HTTP-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeaders().getFirst("HTTP-X-Forwarded-For");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddress().getHostString();
}
}else if (ip.length() > 15) {
String[] ips = ip.split(",");
for(int index = 0; index < ips.length; index++) {
String strIP = (String) ips[index];
if(!("unknown".equalsIgnoreCase(strIP))) {
ip = strIP;
break;
}
}
}
return ip;
} catch (Exception e) {
logger.error("获取IP地址发生错误",e);
return "";
}
}
}
application.properties配置文件如下:
package.environment=dev
debug=false
server.port=3562
spring.application.name=claimplat-gateway
#eureka client config
eureka.client.serviceUrl.defaultZone=http://localhost:8761/claimplat-eureka/eureka/
eureka.instance.preferIpAddress=true
spring.cloud.gateway.locator.enabled=true
最后,Run As运行(需先运行Eureka再运行Gateway网关)