Created
July 19, 2016 19:19
-
-
Save aglassman/099d7a5fe1914924f4b98928e00d7a05 to your computer and use it in GitHub Desktop.
Spring Cloud - Zuul - On Servlet 2.5
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example; | |
import org.springframework.boot.SpringApplication; | |
import org.springframework.boot.autoconfigure.SpringBootApplication; | |
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; | |
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; | |
import org.springframework.context.annotation.Import; | |
@EnableCircuitBreaker | |
@EnableDiscoveryClient | |
@Import(ZuulLegacyProxyConfiguration.class) | |
@SpringBootApplication | |
public class Application { | |
public static void main(String[] args) { | |
SpringApplication.run(Application.class, args); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
server: | |
port: 4431 | |
context-path: microservice-gateway | |
eureka: | |
client: | |
serviceUrl: | |
defaultZone: http://192.168.5.124:8080/eureka/ | |
zuul: | |
ignored-patterns: /test-service/data/**,/test-service/nodes/** | |
ribbon: | |
ConnectTimeout: 3000 | |
ReadTimeout: 60000 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example; | |
import java.util.Map; | |
import java.util.concurrent.atomic.AtomicBoolean; | |
import org.springframework.cloud.netflix.zuul.ZuulFilterInitializer; | |
import org.springframework.context.Lifecycle; | |
import com.netflix.zuul.ZuulFilter; | |
public class LegacyZuulFilterInitializer extends ZuulFilterInitializer implements Lifecycle | |
{ | |
private boolean running = false; | |
public LegacyZuulFilterInitializer(Map<String, ZuulFilter> filters) | |
{ | |
super(filters); | |
super.contextInitialized(null); | |
} | |
@Override | |
public void start() | |
{ | |
running = true; | |
} | |
@Override | |
public void stop() | |
{ | |
running = false; | |
super.contextDestroyed(null); | |
} | |
@Override | |
public boolean isRunning() | |
{ | |
return running; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example; | |
import org.springframework.boot.builder.SpringApplicationBuilder; | |
import org.springframework.boot.context.web.SpringBootServletInitializer; | |
import org.springframework.context.ConfigurableApplicationContext; | |
public class ServletInitializer extends SpringBootServletInitializer { | |
public static SpringApplicationBuilder app; | |
@Override | |
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { | |
app = application; | |
return application.sources(Application.class); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" | |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> | |
<context-param> | |
<param-name>contextConfigLocation</param-name> | |
<param-value>com.dm.gateway.microservicegateway.Application</param-value> | |
</context-param> | |
<listener> | |
<listener-class>org.springframework.boot.legacy.context.web.SpringBootContextLoaderListener</listener-class> | |
</listener> | |
<filter> | |
<filter-name>ContextLifecycleFilter</filter-name> | |
<filter-class>com.netflix.zuul.context.ContextLifecycleFilter</filter-class> | |
</filter> | |
<filter-mapping> | |
<filter-name>ContextLifecycleFilter</filter-name> | |
<url-pattern>/*</url-pattern> | |
</filter-mapping> | |
<servlet> | |
<servlet-name>appServlet</servlet-name> | |
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> | |
<init-param> | |
<param-name>contextAttribute</param-name> | |
<param-value>org.springframework.web.context.WebApplicationContext.ROOT</param-value> | |
</init-param> | |
<load-on-startup>1</load-on-startup> | |
</servlet> | |
<servlet> | |
<servlet-name>zuul</servlet-name> | |
<servlet-class>com.netflix.zuul.http.ZuulServlet</servlet-class> | |
</servlet> | |
<servlet-mapping> | |
<servlet-name>appServlet</servlet-name> | |
<url-pattern>/*</url-pattern> | |
</servlet-mapping> | |
</web-app> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.boot.actuate.endpoint.Endpoint; | |
import org.springframework.boot.actuate.trace.TraceRepository; | |
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; | |
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | |
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; | |
import org.springframework.cloud.client.actuator.HasFeatures; | |
import org.springframework.cloud.client.discovery.DiscoveryClient; | |
import org.springframework.cloud.client.discovery.event.HeartbeatEvent; | |
import org.springframework.cloud.client.discovery.event.HeartbeatMonitor; | |
import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent; | |
import org.springframework.cloud.client.discovery.event.ParentHeartbeatEvent; | |
import org.springframework.cloud.netflix.ribbon.SpringClientFactory; | |
import org.springframework.cloud.netflix.zuul.RoutesEndpoint; | |
import org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper; | |
import org.springframework.cloud.netflix.zuul.filters.RouteLocator; | |
import org.springframework.cloud.netflix.zuul.filters.TraceProxyRequestHelper; | |
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; | |
import org.springframework.cloud.netflix.zuul.filters.discovery.DiscoveryClientRouteLocator; | |
import org.springframework.cloud.netflix.zuul.filters.discovery.ServiceRouteMapper; | |
import org.springframework.cloud.netflix.zuul.filters.discovery.SimpleServiceRouteMapper; | |
import org.springframework.cloud.netflix.zuul.filters.pre.PreDecorationFilter; | |
import org.springframework.cloud.netflix.zuul.filters.route.RestClientRibbonCommandFactory; | |
import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandFactory; | |
import org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter; | |
import org.springframework.cloud.netflix.zuul.filters.route.SimpleHostRoutingFilter; | |
import org.springframework.cloud.netflix.zuul.web.ZuulHandlerMapping; | |
import org.springframework.context.ApplicationEvent; | |
import org.springframework.context.ApplicationListener; | |
import org.springframework.context.annotation.Bean; | |
import org.springframework.context.annotation.Configuration; | |
/** | |
* @author Spencer Gibb | |
* @author Dave Syer | |
*/ | |
@Configuration | |
public class ZuulLegacyProxyConfiguration extends ZuulOverrideConfig | |
{ | |
@Autowired | |
private SpringClientFactory clientFactory; | |
@Autowired | |
private DiscoveryClient discovery; | |
@Autowired | |
private ServiceRouteMapper serviceRouteMapper; | |
@Override | |
public HasFeatures zuulFeature() | |
{ | |
return HasFeatures.namedFeature("Zuul (Discovery)", com.example.ZuulLegacyProxyConfiguration.class); | |
} | |
@Bean | |
@Override | |
@ConditionalOnMissingBean(RouteLocator.class) | |
public DiscoveryClientRouteLocator routeLocator() | |
{ | |
return new DiscoveryClientRouteLocator(this.server.getServletPrefix(), | |
this.discovery, this.zuulProperties, this.serviceRouteMapper); | |
} | |
@Bean | |
@ConditionalOnMissingBean | |
public RibbonCommandFactory<?> ribbonCommandFactory() | |
{ | |
return new RestClientRibbonCommandFactory(this.clientFactory); | |
} | |
// pre filters | |
@Bean | |
public PreDecorationFilter preDecorationFilter(RouteLocator routeLocator, | |
ProxyRequestHelper proxyRequestHelper) | |
{ | |
return new PreDecorationFilter(routeLocator, | |
this.server.getServletPrefix(), | |
this.zuulProperties, | |
proxyRequestHelper); | |
} | |
// route filters | |
@Bean | |
public RibbonRoutingFilter ribbonRoutingFilter(ProxyRequestHelper helper, | |
RibbonCommandFactory<?> ribbonCommandFactory) | |
{ | |
RibbonRoutingFilter filter = new RibbonRoutingFilter(helper, | |
ribbonCommandFactory); | |
return filter; | |
} | |
@Bean | |
public SimpleHostRoutingFilter simpleHostRoutingFilter(ProxyRequestHelper helper, | |
ZuulProperties zuulProperties) | |
{ | |
return new SimpleHostRoutingFilter(helper, zuulProperties); | |
} | |
@Bean | |
public ApplicationListener<ApplicationEvent> zuulDiscoveryRefreshRoutesListener() | |
{ | |
return new com.example.ZuulLegacyProxyConfiguration.ZuulDiscoveryRefreshListener(); | |
} | |
@Bean | |
@ConditionalOnMissingBean(ServiceRouteMapper.class) | |
public ServiceRouteMapper serviceRouteMapper() | |
{ | |
return new SimpleServiceRouteMapper(); | |
} | |
@Configuration | |
@ConditionalOnMissingClass("org.springframework.boot.actuate.endpoint.Endpoint") | |
protected static class NoActuatorConfiguration | |
{ | |
@Bean | |
public ProxyRequestHelper proxyRequestHelper(ZuulProperties zuulProperties) | |
{ | |
ProxyRequestHelper helper = new ProxyRequestHelper(); | |
helper.setIgnoredHeaders(zuulProperties.getIgnoredHeaders()); | |
helper.setTraceRequestBody(zuulProperties.isTraceRequestBody()); | |
return helper; | |
} | |
} | |
@Configuration | |
@ConditionalOnClass(Endpoint.class) | |
protected static class RoutesEndpointConfiguration | |
{ | |
@Autowired(required = false) | |
private TraceRepository traces; | |
@Bean | |
public RoutesEndpoint zuulEndpoint(RouteLocator routeLocator) | |
{ | |
return new RoutesEndpoint(routeLocator); | |
} | |
@Bean | |
public ProxyRequestHelper proxyRequestHelper(ZuulProperties zuulProperties) | |
{ | |
TraceProxyRequestHelper helper = new TraceProxyRequestHelper(); | |
if (this.traces != null) | |
{ | |
helper.setTraces(this.traces); | |
} | |
helper.setIgnoredHeaders(zuulProperties.getIgnoredHeaders()); | |
helper.setTraceRequestBody(zuulProperties.isTraceRequestBody()); | |
return helper; | |
} | |
} | |
private static class ZuulDiscoveryRefreshListener | |
implements ApplicationListener<ApplicationEvent> | |
{ | |
private HeartbeatMonitor monitor = new HeartbeatMonitor(); | |
@Autowired | |
private ZuulHandlerMapping zuulHandlerMapping; | |
@Override | |
public void onApplicationEvent(ApplicationEvent event) | |
{ | |
if (event instanceof InstanceRegisteredEvent) | |
{ | |
reset(); | |
} | |
else if (event instanceof ParentHeartbeatEvent) | |
{ | |
ParentHeartbeatEvent e = (ParentHeartbeatEvent) event; | |
resetIfNeeded(e.getValue()); | |
} | |
else if (event instanceof HeartbeatEvent) | |
{ | |
HeartbeatEvent e = (HeartbeatEvent) event; | |
resetIfNeeded(e.getValue()); | |
} | |
} | |
private void resetIfNeeded(Object value) | |
{ | |
if (this.monitor.update(value)) | |
{ | |
reset(); | |
} | |
} | |
private void reset() | |
{ | |
this.zuulHandlerMapping.setDirty(true); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example; | |
import java.util.Map; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; | |
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | |
import org.springframework.boot.autoconfigure.web.ErrorController; | |
import org.springframework.boot.autoconfigure.web.ServerProperties; | |
import org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration; | |
import org.springframework.boot.context.properties.EnableConfigurationProperties; | |
import org.springframework.cloud.client.actuator.HasFeatures; | |
import org.springframework.cloud.client.discovery.event.HeartbeatEvent; | |
import org.springframework.cloud.client.discovery.event.HeartbeatMonitor; | |
import org.springframework.cloud.context.scope.refresh.RefreshScopeRefreshedEvent; | |
import org.springframework.cloud.netflix.zuul.RoutesRefreshedEvent; | |
import org.springframework.cloud.netflix.zuul.ZuulFilterInitializer; | |
import org.springframework.cloud.netflix.zuul.filters.RouteLocator; | |
import org.springframework.cloud.netflix.zuul.filters.SimpleRouteLocator; | |
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; | |
import org.springframework.cloud.netflix.zuul.filters.post.SendErrorFilter; | |
import org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter; | |
import org.springframework.cloud.netflix.zuul.filters.pre.DebugFilter; | |
import org.springframework.cloud.netflix.zuul.filters.pre.FormBodyWrapperFilter; | |
import org.springframework.cloud.netflix.zuul.filters.pre.Servlet30WrapperFilter; | |
import org.springframework.cloud.netflix.zuul.filters.pre.ServletDetectionFilter; | |
import org.springframework.cloud.netflix.zuul.filters.route.SendForwardFilter; | |
import org.springframework.cloud.netflix.zuul.web.ZuulController; | |
import org.springframework.cloud.netflix.zuul.web.ZuulHandlerMapping; | |
import org.springframework.context.ApplicationEvent; | |
import org.springframework.context.ApplicationListener; | |
import org.springframework.context.annotation.Bean; | |
import org.springframework.context.annotation.Configuration; | |
import org.springframework.context.annotation.Import; | |
import org.springframework.context.event.ContextRefreshedEvent; | |
import com.netflix.zuul.ZuulFilter; | |
import com.netflix.zuul.http.ZuulServlet; | |
/** | |
* @author Spencer Gibb | |
* @author Dave Syer | |
*/ | |
@Configuration | |
@EnableConfigurationProperties({ ZuulProperties.class }) | |
@ConditionalOnClass(ZuulServlet.class) | |
// Make sure to get the ServerProperties from the same place as a normal web app would | |
@Import(ServerPropertiesAutoConfiguration.class) | |
public class ZuulOverrideConfig { | |
@Autowired | |
protected ZuulProperties zuulProperties; | |
@Autowired | |
protected ServerProperties server; | |
@Autowired(required = false) | |
private ErrorController errorController; | |
@Bean | |
public HasFeatures zuulFeature() { | |
return HasFeatures.namedFeature("Zuul (Simple)", org.springframework.cloud.netflix.zuul.ZuulConfiguration.class); | |
} | |
@Bean | |
@ConditionalOnMissingBean(RouteLocator.class) | |
public RouteLocator routeLocator() { | |
return new SimpleRouteLocator(this.server.getServletPrefix(), | |
this.zuulProperties); | |
} | |
@Bean | |
public ZuulController zuulController() { | |
return new ZuulController(); | |
} | |
@Bean | |
public ZuulHandlerMapping zuulHandlerMapping(RouteLocator routes) { | |
ZuulHandlerMapping mapping = new ZuulHandlerMapping(routes, zuulController()); | |
mapping.setErrorController(this.errorController); | |
return mapping; | |
} | |
@Bean | |
public ApplicationListener<ApplicationEvent> zuulRefreshRoutesListener() { | |
return new com.example.ZuulOverrideConfig.ZuulRefreshListener(); | |
} | |
// pre filters | |
@Bean | |
public ServletDetectionFilter servletDetectionFilter() { | |
return new ServletDetectionFilter(); | |
} | |
@Bean | |
public FormBodyWrapperFilter formBodyWrapperFilter() { | |
return new FormBodyWrapperFilter(); | |
} | |
@Bean | |
public DebugFilter debugFilter() { | |
return new DebugFilter(); | |
} | |
@Bean | |
public Servlet30WrapperFilter servlet30WrapperFilter() { | |
return new Servlet30WrapperFilter(); | |
} | |
// post filters | |
@Bean | |
public SendResponseFilter sendResponseFilter() { | |
return new SendResponseFilter(); | |
} | |
@Bean | |
public SendErrorFilter sendErrorFilter() { | |
return new SendErrorFilter(); | |
} | |
@Bean | |
public SendForwardFilter sendForwardFilter() { | |
return new SendForwardFilter(); | |
} | |
@Configuration | |
protected static class ZuulFilterConfiguration { | |
@Autowired | |
private Map<String, ZuulFilter> filters; | |
@Bean | |
public ZuulFilterInitializer zuulFilterInitializer() { | |
return new LegacyZuulFilterInitializer(this.filters){}; | |
} | |
} | |
private static class ZuulRefreshListener | |
implements ApplicationListener<ApplicationEvent> { | |
@Autowired | |
private ZuulHandlerMapping zuulHandlerMapping; | |
private HeartbeatMonitor heartbeatMonitor = new HeartbeatMonitor(); | |
@Override | |
public void onApplicationEvent(ApplicationEvent event) { | |
if (event instanceof ContextRefreshedEvent | |
|| event instanceof RefreshScopeRefreshedEvent | |
|| event instanceof RoutesRefreshedEvent) { | |
this.zuulHandlerMapping.setDirty(true); | |
} | |
else if (event instanceof HeartbeatEvent) { | |
if (this.heartbeatMonitor.update(((HeartbeatEvent) event).getValue())) { | |
this.zuulHandlerMapping.setDirty(true); | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment