背景
Gateway服务pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
普通服务pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
配置文件
server:
servlet:
context-path: /api
接口url: /test
Gateway服务:context-path失效
正常访问:/test
无法访问:/api/test
普通服务:context-path生效
无法访问:/test
正常访问:/api/test
原因: server.servlet.context-path是webmvc配置。
gateway用的是长连接,netty-webflux,zuul1.0用的就是同步webmvc。
非gateway子项目启动用的是webmvc,gateway启动用的是webflux
spring-boot-start-web和spring-boot-start-webflux相见分外眼红。
不能配置在同一pom.xml,或者不能在同一项目中出现。
解决方案:添加WebFilter
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.WebFilter;
@Configuration
public class ContextPathConfig {
@Bean
@ConditionalOnProperty("server.servlet.context-path")
@Order(Ordered.HIGHEST_PRECEDENCE)
public WebFilter contextPathWebFilter(ServerProperties serverProperties){
String contextPath = serverProperties.getServlet().getContextPath();
return (serverWebExchange, webFilterChain) ->{
ServerHttpRequest request = serverWebExchange.getRequest();
String requestPath = request.getURI().getPath();
if(requestPath.contains(contextPath)){
String newPath = requestPath.replaceFirst(contextPath, "");
ServerHttpRequest newRequest = request.mutate()
.path(newPath).build();
return webFilterChain.filter(serverWebExchange.mutate()
.request(newRequest)
.build()
);
}else {
throw new ResponseStatusException(HttpStatus.NOT_FOUND);
}
};
}
}