spring-gatway的使用方法 gateway自定义404页面 springboo自定义404页面

源码

gitee项目地址: https://gitee.com/gxkj_admin/easyspring
如果对您有帮助,请点赞收藏。谢谢

功能说明:
1:gateway的java代码实现
2:gateway增加权限验证
3:gateway与nacos整合
4:springboot与nacos整合
5:gateway与sentinel整合
6:springboot与sentinel整合

参考文档

  • [spring中文网]https://www.springcloud.cc/spring-cloud-greenwich.html#_addrequestheader_gatewayfilter_factory
  • [官网]https://spring.io/guides/gs/gateway/
  • [官网例子]https://github.com/spring-cloud/spring-cloud-gateway/tree/main/spring-cloud-gateway-sample
  • 熔断后共享线程信息 https://www.cnblogs.com/duanxz/p/10949816.html

实现功能

  • Fluent java实现
  • 自定义应用拦截器
  • 自定义全局拦截器
  • 熔断器功能例子
  • 熔断器上下文地址信息获取
  • 完整代码

代码实现

– 第一版

下列代码主要是实现路由:

import com.example.demogateway.filters.MyPreGatewayFilterFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 参考网址:
 * 	https://www.springcloud.cc/spring-cloud-greenwich.html#_addrequestheader_gatewayfilter_factory
 */
@RestController
@SpringBootApplication
public class DemogatewayApplication {

	@RequestMapping("/hystrixfallback")
	public String hystrixfallback() {
		return "This is a fallback";
	}
	@Autowired
	private MyPreGatewayFilterFactory myPreGatewayFilterFactory;

//  path注意以“/”开头,支持and|or组合使用
//	order属性的数值越低,优先级越高
// 支持host和上传测试
// path可以使用通配符,例如:/foo/**

	@Bean
	public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {

		MyPreGatewayFilterFactory.Config conifg = new MyPreGatewayFilterFactory.Config();

		RouteLocator locator =  builder.routes()
//				支持路径测试
				.route("path_route", r -> r.path("/get")
						.filters(f -> f.filter(myPreGatewayFilterFactory.apply(conifg)))
						.uri("http://httpbin.org:80"))
				.route("host_form_route",
						r -> r.order(2).host("**.myhost.org").and().path("/uploadimg3")
						.filters(f -> f.filter(myPreGatewayFilterFactory.apply(conifg)))
						.uri("http://localhost:81/uploadImg2"))

				.route("path_route_complex", r -> r.path("/uploadimg4")
						.filters(f -> f.filter(myPreGatewayFilterFactory.apply(conifg)))
						.uri("http://localhost:81"))
				.route("hystrix_fallback_route", r -> r.host("*.hystrixfallback.org")
						.filters(f -> f.hystrix(c -> c.setName("slowcmd").setFallbackUri("forward:/hystrixfallback")))
								.uri("http://httpbin.org"))



				.build();
		return locator;
	}
 

	@Bean
	RedisRateLimiter redisRateLimiter() {
		return new RedisRateLimiter(1, 2);
	}

	@Bean
	SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) throws Exception {
		return http.httpBasic().and()
				.csrf().disable()
				.authorizeExchange()
				.pathMatchers("/anything/**").authenticated()
				.anyExchange().permitAll()
				.and()
				.build();
	}

	@Bean
	public MapReactiveUserDetailsService reactiveUserDetailsService() {
		UserDetails user = User.withDefaultPasswordEncoder().username("user").password("password").roles("USER").build();
		return new MapReactiveUserDetailsService(user);
	}

	public static void main(String[] args) {
		SpringApplication.run(DemogatewayApplication.class, args);
	}
}

下列代码主要实现过滤器

package com.example.demogateway.filters;

import com.example.demogateway.utils.ResponseUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import reactor.core.publisher.Mono;
import org.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata;

@Component
public class MyPreGatewayFilterFactory extends AbstractGatewayFilterFactory<MyPreGatewayFilterFactory.Config> {

    private Logger logger = LoggerFactory.getLogger(MyPreGatewayFilterFactory.class);

    public MyPreGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        // grab configuration from Config object
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            String path = request.getPath().toString();
            if(path.equals("dologin") ||"dologout".equals(path)){

                return chain.filter(exchange.mutate().request(request).build());
            }else{
                MultiValueMap<String, String> queryMap =  request.getQueryParams();
                String userName = queryMap.getFirst("userName");
//            String userName = config.getName();
                if(!StringUtils.hasText(userName)){
                    Mono<Void>  info = ResponseUtils.getResponseTextError(exchange,"非法用户,请在参数中使用:userName=xxx来尝试验证");
                    return info;
                }else if(!userName.equals("测试")){
                    Mono<Void>  info = ResponseUtils.getResponseTextError(exchange,"请使用用户名:'测试'进行登录");
                    return info;
                }
                //If you want to build a "pre" filter you need to manipulate the
                //request before calling chain.filter

//            ServerHttpRequest.Builder builder = exchange.getRequest().mutate();

                //use builder to manipulate the request
                return chain.filter(exchange.mutate().request(request).build());
            }

        };
    }

    public static class Config {
        private String name;

        public Config() {
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

}

下面代码主要是个工具:


import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

public class ResponseUtils {
    public static Mono<Void> getResponseTextError(ServerWebExchange exchange, String msg) {
        ServerHttpResponse response = exchange.getResponse();
       String repString = String.format("{\"code\":-1,\"message\",%s}",msg);
        byte[] bits = repString.getBytes(StandardCharsets.UTF_8);
        DataBuffer buffer = response.bufferFactory().wrap(bits);
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        //指定编码,否则在浏览器中会中文乱码
        response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8");
        return response.writeWith(Mono.just(buffer));
    }
}

补充知识:


1: 本地跳转的方法。具体参考HystrixGatewayFilterFactory.java类。参考下面的代码,希望对forward,等有参考实现价值。

protected Observable<Void> resumeWithFallback() {
            if (this.fallbackUri == null) {
                return super.resumeWithFallback();
            } else {
                URI uri = this.exchange.getRequest().getURI();
                boolean encoded = ServerWebExchangeUtils.containsEncodedParts(uri);
                URI requestUrl = UriComponentsBuilder.fromUri(uri).host((String)null).port((String)null).uri(this.fallbackUri).build(encoded).toUri();
                this.exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR, requestUrl);
                ServerHttpRequest request = this.exchange.getRequest().mutate().uri(requestUrl).build();
                ServerWebExchange mutated = this.exchange.mutate().request(request).build();
                return RxReactiveStreams.toObservable(HystrixGatewayFilterFactory.this.dispatcherHandler.handle(mutated));
            }
        }

使用方式在官网的例子里:

.route("hystrix_fallback_route", 
r -> r.host("*.hystrixfallback.org")
.filters(
	f -> f.hystrix(c -> c.setName("slowcmd")
		.setFallbackUri("forward:/hystrixfallback"))
)
.uri("http://httpbin.org"))

2:更多实现功能请参考网址:
[spring中文网]https://www.springcloud.cc/spring-cloud-greenwich.html#_addrequestheader_gatewayfilter_factory。里面有介绍负载均衡、限制次数等业务需求场景,大家可以自己实现。
3: 过滤器: SetPath、RequestSize(控制参数大小)、ModifyRequestBody(修改请求体,只能用java代码实现)、ModifyResponseBody(修改响应主体),GlobalFilter (全局过滤器)、ForwardRoutingFilter(转发过滤器)、LoadBalancerClientFilter(均衡过滤器)
4: 参看网址[spring中文网]中有前置过滤器PreGatewayFilterFactory 、后置过滤器PostGatewayFilterFactory、全局前置过滤器GlobalFilter customGlobalFilter和全局后置过滤器GlobalFilter customGlobalPostFilter 的例子

spring:
  cloud:
    gateway:
      routes:
      - id: setpath_route
        uri: https://example.org
        predicates:
        - Path=/foo/{segment}
        filters:
        - SetPath=/{segment}

– -- ----- 版本2-- – -----优化点如下:

  1. 使用predicate
  2. 使用断路器
  3. 断路器传递MDC等上下文

参考文档增加:
https://blog.csdn.net/zhanglh046/article/details/78652133

代码如下:

启动类


import com.example.demogateway.filters.MyPreGatewayFilterFactory;
import com.example.demogateway.plugins.HystrixCallableWrapper;
import com.example.demogateway.plugins.MdcAwareCallableWrapper;
import com.example.demogateway.plugins.RequestAttributeAwareCallableWrapper;
import com.example.demogateway.plugins.RequestContextHystrixConcurrencyStrategy;
import com.example.demogateway.predicates.MyRoutePredicateFactory;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.netflix.hystrix.strategy.HystrixPlugins;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.endpoint.SecurityContext;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.gateway.filter.factory.HystrixGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.http.server.PathContainer;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.reactive.DispatcherHandler;
import org.springframework.web.server.ServerWebExchange;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Predicate;

import static org.springframework.web.context.request.RequestAttributes.SCOPE_REQUEST;

/**
 * 参考网址:
 * 	https://www.springcloud.cc/spring-cloud-greenwich.html#_addrequestheader_gatewayfilter_factory
 */
@RestController
@SpringBootApplication
public class DemogatewayApplication {
	private Logger logger = LoggerFactory.getLogger(DemogatewayApplication.class);


	@Bean(name = "requestAttributeAwareCallableWrapper")
	public HystrixCallableWrapper requestAttributeAwareCallableWrapper() {
		return new RequestAttributeAwareCallableWrapper();
	}

	@Bean(name = "mdcAwareCallableWrapper")
	public HystrixCallableWrapper mdcAwareCallableWrapper(){
		return new MdcAwareCallableWrapper();
	}

	@Autowired(required = false)
	private List<HystrixCallableWrapper> wrappers = new ArrayList<>();



	@Autowired
	@Qualifier(value = "requestAttributeAwareCallableWrapper" )
	private  HystrixCallableWrapper requestAttributeAwareCallableWrapper;

	@Autowired
	@Qualifier(value = "mdcAwareCallableWrapper" )
	private  HystrixCallableWrapper mdcAwareCallableWrapper;

	@PostConstruct
	public void init() {
		wrappers.add(requestAttributeAwareCallableWrapper);
		wrappers.add(mdcAwareCallableWrapper);
		HystrixPlugins.getInstance().registerConcurrencyStrategy(new RequestContextHystrixConcurrencyStrategy(wrappers));
	}


	@RequestMapping("/hystrixfallback")
	public String hystrixfallback() {
		SecurityContext s = SecurityContext.NONE ;
		String  traceId = MDC.get("traceId");
		logger.info("hystrixfallback-traceId={}",traceId);

		return "This is a fallback";
	}
	
	@Autowired
	private MyPreGatewayFilterFactory myPreGatewayFilterFactory;
 

//	熔断器
	@Bean
	public HystrixGatewayFilterFactory hystrixGatewayFilterFactory(DispatcherHandler dispatcherHandler) {
		return new HystrixGatewayFilterFactory(dispatcherHandler);
	}



//  path注意以“/”开头,支持and|or组合使用
//	order属性的数值越低,优先级越高
// 支持host和上传测试

	@Bean
	public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {

		MyPreGatewayFilterFactory.Config conifg = new MyPreGatewayFilterFactory.Config();


		Consumer<HystrixGatewayFilterFactory.Config> configConsumer = new Consumer<HystrixGatewayFilterFactory.Config>() {
			@Override
			public void accept(HystrixGatewayFilterFactory.Config config) {
				config.setFallbackUri("forward:/hystrixfallback");
				config.setName("test3000");
			}
		};

		RouteLocator locator =  builder.routes()
				.route("predicate_route", r -> r.order(1)
						.predicate(exchange ->{
							//自定义匹配器,如果匹配"/httpbin"开头,则跳转到对应的网站
							ServerHttpRequest request = exchange.getRequest();
							RequestPath requestPath =  request.getPath();
							String requestPathString = requestPath.value().toString();

							boolean isMatch = requestPathString.startsWith("/httpbin");
							return isMatch;

						})
						.filters(f->
								  {
									  return f.removeRequestHeader("Origin")
											  .rewritePath("/httpbin","")
											  .hystrix(configConsumer)
											  ;


								}
						)
						.uri("http://localhost:81"))
//				支持路径测试
				.route("path_route", r -> r.order(2).path("/get")
						.filters(f -> f.filter(myPreGatewayFilterFactory.apply(conifg)))
						.uri("http://httpbin.org:80"))
				.route("host_form_route",
						r -> r.order(3).host("**.myhost.org").and().path("/uploadimg3")
						.filters(f -> f.filter(myPreGatewayFilterFactory.apply(conifg)))
						.uri("http://localhost:81/uploadImg2"))

				.route("path_route_complex", r -> r.order(4).path("/uploadimg4")
						.filters(f -> f.filter(myPreGatewayFilterFactory.apply(conifg)))
						.uri("http://localhost:81"))
				.route("hystrix_fallback_route", r -> r.order(5).host("*.hystrixfallback.org")
						.filters(f -> f.hystrix(c -> c.setName("slowcmd").setFallbackUri("forward:/hystrixfallback")))
								.uri("http://httpbin.org"))




				.build();
		return locator;
	} 
	public static void main(String[] args) {
		SpringApplication.run(DemogatewayApplication.class, args);
	}

}

HystrixCallableWrapper类

import java.util.concurrent.Callable;

public interface HystrixCallableWrapper {

    /**
     * 包装Callable实例
     *
     * @param callable 待包装实例
     * @param <T>      返回类型
     * @return 包装后的实例
     */
    <T> Callable<T> wrap(Callable<T> callable);

}

MdcAwareCallableWrapper类


import org.slf4j.MDC;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;

public class MdcAwareCallableWrapper implements HystrixCallableWrapper {
    @Override
    public <T> Callable<T> wrap(Callable<T> callable) {
        return new MdcAwareCallable<>(callable, MDC.getCopyOfContextMap());
    }

    private class MdcAwareCallable<T> implements Callable<T> {

        private final Callable<T> delegate;

        private final Map<String, String> contextMap;

        public MdcAwareCallable(Callable<T> callable, Map<String, String> contextMap) {
            this.delegate = callable;
            this.contextMap = contextMap != null ? contextMap : new HashMap();
        }

        @Override
        public T call() throws Exception {
            try {
                MDC.setContextMap(contextMap);
                return delegate.call();
            } finally {
                MDC.clear();
            }
        }
    }
}

RequestAttributeAwareCallableWrapper 类


import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.util.concurrent.Callable;

public final class RequestAttributeAwareCallableWrapper implements HystrixCallableWrapper {
    @Override
    public <T> Callable<T> wrap(Callable<T> callable) {
        return new RequestAttributeAwareCallable(callable, RequestContextHolder.getRequestAttributes());
    }

    static class RequestAttributeAwareCallable<T> implements Callable<T> {

        private final Callable<T> delegate;
        private final RequestAttributes requestAttributes;

        RequestAttributeAwareCallable(Callable<T> callable, RequestAttributes requestAttributes) {
            this.delegate = callable;
            this.requestAttributes = requestAttributes;
        }

        @Override
        public T call() throws Exception {
            try {
                RequestContextHolder.setRequestAttributes(requestAttributes);
                return delegate.call();
            } finally {
                RequestContextHolder.resetRequestAttributes();
            }
        }
    }
}

RequestContextHystrixConcurrencyStrategy 类

import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;

import java.util.Collection;
import java.util.Iterator;
import java.util.concurrent.Callable;
public class RequestContextHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {
    private final Collection<HystrixCallableWrapper> wrappers;

    public RequestContextHystrixConcurrencyStrategy(Collection<HystrixCallableWrapper> wrappers) {
        this.wrappers = wrappers;
    }

    @Override
    public <T> Callable<T> wrapCallable(Callable<T> callable) {
        return new CallableWrapperChain(callable, wrappers.iterator()).wrapCallable();
    }

    private static class CallableWrapperChain<T> {

        private final Callable<T> callable;

        private final Iterator<HystrixCallableWrapper> wrappers;

        CallableWrapperChain(Callable<T> callable, Iterator<HystrixCallableWrapper> wrappers) {
            this.callable = callable;
            this.wrappers = wrappers;
        }

        Callable<T> wrapCallable() {
            Callable<T> delegate = callable;
            while (wrappers.hasNext()) {
                delegate = wrappers.next().wrap(delegate);
            }
            return delegate;
        }
    }
}

MyRoutePredicateFactory 类


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.server.ServerWebExchange;

import java.util.function.Predicate;

public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config> {
    private Logger logger = LoggerFactory.getLogger(MyRoutePredicateFactory.class);
    public MyRoutePredicateFactory() {
        super(Config.class);
    }

    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        // grab configuration from Config object
        return exchange -> {
            //grab the request
            ServerHttpRequest request = exchange.getRequest();
            //take information from the request to see if it
            //matches configuration.
            return matches(config, request);
        };
    }

    private boolean matches(Config config, ServerHttpRequest request) {
        logger.info("请求到达");
        return true;
    }

    public static class Config {
        //Put the configuration properties for your filter here
    }

}

这里做个全局过滤器,测试当熔断时traceId是否传到回调方法里


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.UUID;

import static org.springframework.web.context.request.RequestAttributes.SCOPE_REQUEST;


@Component
public class AccessLogGlobalFilter implements GlobalFilter {
    private Logger log = LoggerFactory.getLogger(AccessLogGlobalFilter.class);
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();

        String path = request.getPath().pathWithinApplication().value();
        String   traceId = getTraceId();
        log.info("traceId={}",traceId);
        MDC.put("traceId",traceId);
        log.info("请求路径:{}", path);
        RequestContextHolder.currentRequestAttributes().setAttribute("traceId", traceId, SCOPE_REQUEST);

        long start = System.currentTimeMillis();

        Mono<Void> rep = null;
        try{
         rep = chain.filter(exchange).then(Mono.fromRunnable(() -> {

            ServerHttpResponse response = exchange.getResponse();
            HttpStatus statusCode = response.getStatusCode();
            long end = System.currentTimeMillis();
            log.info("请求路径:{},响应码:{},耗时:{},traceId="+traceId, path, statusCode,(end-start));
        }));
        }catch (Exception e){
            throw e;
        }finally {
            // 这行不能要,否则熔断跳转后这个就丢失了 MDC.remove("traceId");
        }

        return rep;
    }
    public String getTraceId(){
        String   traceId = MDC.get("traceId");
        if(StringUtils.hasLength(traceId)){
            return traceId;
        }else{
            traceId = UUID.randomUUID().toString().replace("-", "");
            return traceId;
        }
    }
}

配置不同熔断器的响应时间,在application.yml里如下配置

hystrix:
  shareSecurityContext: true
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 2000
    test3000:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 3000

熔断后的上线文传递主要参考的是下列网址:
https://www.cnblogs.com/duanxz/p/10949816.html

pom.xml里的内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.gxkj.easy-spring</groupId>
	<artifactId>easy-spring-gateway</artifactId>
	<version>1.0.5</version>
	<packaging>jar</packaging>

	<name>spring-cloud-gateway-sample</name>
	<description>Demo project for Spring Cloud Gateway</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.2.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<spring-cloud.version>Finchley.RC2</spring-cloud.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-webflux</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-gateway</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-data-redis</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>io.projectreactor</groupId>
			<artifactId>reactor-test</artifactId>
			<scope>test</scope>
		</dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

	<repositories>
		<repository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</repository>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
	</repositories>

	<pluginRepositories>
		<pluginRepository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</pluginRepository>
		<pluginRepository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</pluginRepository>
	</pluginRepositories>


</project>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值