diff --git a/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/ZuulServerAutoConfiguration.java b/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/ZuulServerAutoConfiguration.java index 1669f0f..6569a4f 100644 --- a/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/ZuulServerAutoConfiguration.java +++ b/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/ZuulServerAutoConfiguration.java @@ -2,6 +2,8 @@ package com.github.cloud.netflix.zuul; import java.util.Map; +import com.github.cloud.netflix.zuul.filters.RouteLocator; +import com.github.cloud.netflix.zuul.filters.SimpleRouteLocator; import com.github.cloud.netflix.zuul.filters.ZuulProperties; import com.github.cloud.netflix.zuul.filters.post.SendResponseFilter; import com.github.cloud.netflix.zuul.filters.pre.PreDecorationFilter; @@ -17,6 +19,7 @@ import com.netflix.zuul.monitoring.TracerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -39,20 +42,25 @@ public class ZuulServerAutoConfiguration { return new ServletRegistrationBean<>(new ZuulServlet(), zuulProperties.getServletPath()); } + @Bean + public RouteLocator simpleRouteLocator() { + return new SimpleRouteLocator(zuulProperties); + } + /** * pre类型过滤器,根据RouteLocator来进行路由规则的匹配 */ @Bean - public ZuulFilter preDecorationFilter() { - return new PreDecorationFilter(); + public ZuulFilter preDecorationFilter(RouteLocator routeLocator) { + return new PreDecorationFilter(routeLocator); } /** * route类型过滤器,使用ribbon负载均衡器进行http请求 */ @Bean - ZuulFilter ribbonRoutingFilter() { - return new RibbonRoutingFilter(); + ZuulFilter ribbonRoutingFilter(LoadBalancerClient loadBalancerClient) { + return new RibbonRoutingFilter(loadBalancerClient); } /** diff --git a/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/filters/Route.java b/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/filters/Route.java new file mode 100644 index 0000000..d8eb43a --- /dev/null +++ b/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/filters/Route.java @@ -0,0 +1,35 @@ +package com.github.cloud.netflix.zuul.filters; + +/** + * 路由 + * @author derek(易仁川) + * @date 2022/6/28 + */ +public class Route { + + private String path; + + private String location; + + public Route(String path, String location) { + this.path = path; + this.location = location; + } + + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } +} diff --git a/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/filters/RouteLocator.java b/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/filters/RouteLocator.java new file mode 100644 index 0000000..e4b0ee7 --- /dev/null +++ b/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/filters/RouteLocator.java @@ -0,0 +1,16 @@ +package com.github.cloud.netflix.zuul.filters; + +/** + * 路由定位器 + * @author derek(易仁川) + * @date 2022/6/28 + */ +public interface RouteLocator { + + /** + * 获取匹配的路由 + * @param path + * @return + */ + Route getMatchingRoute(String path); +} diff --git a/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/filters/SimpleRouteLocator.java b/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/filters/SimpleRouteLocator.java new file mode 100644 index 0000000..14b9cae --- /dev/null +++ b/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/filters/SimpleRouteLocator.java @@ -0,0 +1,35 @@ +package com.github.cloud.netflix.zuul.filters; + +import java.util.Map; + +import org.springframework.util.AntPathMatcher; +import org.springframework.util.PathMatcher; + +/** + * 路由定位器实现类 + * @author derek(易仁川) + * @date 2022/6/28 + */ +public class SimpleRouteLocator implements RouteLocator { + + private ZuulProperties zuulProperties; + + private PathMatcher pathMatcher = new AntPathMatcher(); + + public SimpleRouteLocator(ZuulProperties zuulProperties) { + this.zuulProperties = zuulProperties; + } + + @Override + public Route getMatchingRoute(String path) { + for (Map.Entry entry : zuulProperties.getRoutes().entrySet()) { + ZuulProperties.ZuulRoute zuulRoute = entry.getValue(); + String pattern = zuulRoute.getPath(); + if (pathMatcher.match(pattern, path)) { + return new Route(path, zuulRoute.getServiceId()); + } + } + + return null; + } +} diff --git a/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/filters/post/SendResponseFilter.java b/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/filters/post/SendResponseFilter.java index f107d93..3d42cc5 100644 --- a/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/filters/post/SendResponseFilter.java +++ b/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/filters/post/SendResponseFilter.java @@ -1,6 +1,11 @@ package com.github.cloud.netflix.zuul.filters.post; +import java.io.OutputStream; + +import javax.servlet.http.HttpServletResponse; + import com.netflix.zuul.ZuulFilter; +import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.exception.ZuulException; import static com.github.cloud.netflix.zuul.filters.support.FilterConstants.POST_TYPE; @@ -25,11 +30,21 @@ public class SendResponseFilter extends ZuulFilter { @Override public boolean shouldFilter() { - return true; + RequestContext requestContext = RequestContext.getCurrentContext(); + return requestContext.getResponseDataStream() != null; } @Override public Object run() throws ZuulException { + RequestContext requestContext = RequestContext.getCurrentContext(); + HttpServletResponse servletResponse = requestContext.getResponse(); + if (servletResponse.getCharacterEncoding() == null) { + servletResponse.setCharacterEncoding("UTF-8"); + } + + OutputStream outStream = servletResponse.getOutputStream(); + + return null; } } diff --git a/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/filters/pre/PreDecorationFilter.java b/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/filters/pre/PreDecorationFilter.java index 672c115..b770d50 100644 --- a/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/filters/pre/PreDecorationFilter.java +++ b/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/filters/pre/PreDecorationFilter.java @@ -1,9 +1,16 @@ package com.github.cloud.netflix.zuul.filters.pre; +import com.github.cloud.netflix.zuul.filters.Route; +import com.github.cloud.netflix.zuul.filters.RouteLocator; import com.netflix.zuul.ZuulFilter; +import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.exception.ZuulException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import static com.github.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE; +import static com.github.cloud.netflix.zuul.filters.support.FilterConstants.REQUEST_URI_KEY; +import static com.github.cloud.netflix.zuul.filters.support.FilterConstants.SERVICE_ID_KEY; /** * pre类型过滤器,根据RouteLocator来进行路由规则的匹配 @@ -12,6 +19,13 @@ import static com.github.cloud.netflix.zuul.filters.support.FilterConstants.PRE_ * @date 2022/6/27 */ public class PreDecorationFilter extends ZuulFilter { + private static Logger logger = LoggerFactory.getLogger(PreDecorationFilter.class); + + private RouteLocator routeLocator; + + public PreDecorationFilter(RouteLocator routeLocator) { + this.routeLocator = routeLocator; + } @Override public String filterType() { @@ -30,6 +44,18 @@ public class PreDecorationFilter extends ZuulFilter { @Override public Object run() throws ZuulException { + RequestContext requestContext = RequestContext.getCurrentContext(); + String requestURI = requestContext.getRequest().getRequestURI(); + //获取匹配的路由 + Route route = routeLocator.getMatchingRoute(requestURI); + if (route != null) { + requestContext.put(REQUEST_URI_KEY, route.getPath()); + requestContext.set(SERVICE_ID_KEY, route.getLocation()); + } + else { + logger.error("获取不到匹配的路由, requestURI: {}", requestContext); + } + return null; } } diff --git a/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/filters/route/RibbonRoutingFilter.java b/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/filters/route/RibbonRoutingFilter.java index 64a05df..00fff10 100644 --- a/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/filters/route/RibbonRoutingFilter.java +++ b/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/filters/route/RibbonRoutingFilter.java @@ -1,9 +1,25 @@ package com.github.cloud.netflix.zuul.filters.route; +import java.io.IOException; +import java.io.InputStream; + +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; + import com.netflix.zuul.ZuulFilter; +import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.exception.ZuulException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; +import org.springframework.cloud.client.loadbalancer.LoadBalancerRequest; +import org.springframework.http.HttpStatus; +import org.springframework.http.client.ClientHttpResponse; + +import static com.github.cloud.netflix.zuul.filters.support.FilterConstants.REQUEST_URI_KEY; import static com.github.cloud.netflix.zuul.filters.support.FilterConstants.ROUTE_TYPE; +import static com.github.cloud.netflix.zuul.filters.support.FilterConstants.SERVICE_ID_KEY; /** * route类型过滤器,使用ribbon负载均衡器进行http请求 @@ -12,6 +28,13 @@ import static com.github.cloud.netflix.zuul.filters.support.FilterConstants.ROUT * @date 2022/6/27 */ public class RibbonRoutingFilter extends ZuulFilter { + private static Logger logger = LoggerFactory.getLogger(RibbonRoutingFilter.class); + + private LoadBalancerClient loadBalancerClient; + + public RibbonRoutingFilter(LoadBalancerClient loadBalancerClient) { + this.loadBalancerClient = loadBalancerClient; + } @Override public String filterType() { @@ -25,11 +48,39 @@ public class RibbonRoutingFilter extends ZuulFilter { @Override public boolean shouldFilter() { - return true; + RequestContext requestContext = RequestContext.getCurrentContext(); + return requestContext.get(SERVICE_ID_KEY) != null; } @Override public Object run() throws ZuulException { - return null; + RequestContext requestContext = RequestContext.getCurrentContext(); + String serviceId = (String) requestContext.get(SERVICE_ID_KEY); + String requestURI = (String) requestContext.get(REQUEST_URI_KEY); + + + HttpServletRequest request = requestContext.getRequest(); + + String method = request.getMethod(); + + ServletInputStream inputStream = null; + try { + inputStream = request.getInputStream(); + } + catch (IOException e) { + logger.error("获取输入流失败", e); + } + + //TODO 构造请求 + LoadBalancerRequest loadBalancerRequest = null; + + ClientHttpResponse response = loadBalancerClient.execute(serviceId, loadBalancerRequest); + int statusCode = response.getRawStatusCode(); + InputStream responseBody = response.getBody(); + + requestContext.setResponseStatusCode(statusCode); + requestContext.setResponseDataStream(responseBody); + + return response; } } diff --git a/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/filters/support/FilterConstants.java b/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/filters/support/FilterConstants.java index 0af4f80..dc5d20d 100644 --- a/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/filters/support/FilterConstants.java +++ b/mini-spring-cloud-netflix-zuul/src/main/java/com/github/cloud/netflix/zuul/filters/support/FilterConstants.java @@ -8,6 +8,9 @@ package com.github.cloud.netflix.zuul.filters.support; */ public interface FilterConstants { + String REQUEST_URI_KEY = "requestURI"; + + String SERVICE_ID_KEY = "serviceId"; //过滤器类型常量----------------------------------- String PRE_TYPE = "pre";