Spring 带 servlet 的云 Zuul-api 2.5

Spring cloud Zuul with servlet-api 2.5

  1. @EnableZuulProxy 在 servlet 2.5 容器下不起作用。是否有任何解决方法可以让 spring-cloud zuul 在 servet 2.5 容器下工作?

  2. 我也找不到@EnableZuulProxy的注解处理器。请提供 class propesses @EnableZuulProxy 以便我可以更好地理解此注释的真正作用。

@EnableZuulProxy 来自 Spring Cloud,它基于 Spring Boot,即 Servlet 3.0 及更高版本。如果您需要使用 Servlet 2.5,您可以直接使用 Netflix API。

@EnableZuulProxy 是用 @Import(ZuulProxyConfiguration.class) 进行元注释的,所以我猜这就是你说 "propesses" 的意思?如果您不知道 @Import 是什么,请继续阅读 Spring。

Spring Cloud 在 servlet 3.0 上是 运行。也就是说,可以在 servlet 2.5 上获得 @EnableZuulProxy 运行ning。我必须为此想出一个破解方法,因为我必须在 Tomcat 6.

中让它工作

主要问题是由于 ZuulConfiguration.class,它有以下方法:

@Bean
@ConditionalOnMissingBean(name = "zuulServlet")    
public ServletRegistrationBean zuulServlet() { ... }

这里的问题是 ServletRegistrationBean 使用 javax.servlet.Registration$Dynamic,直到 Servlet 3.0 才可用。这导致 NoClassDefFoundError.

要解决此问题,请使用 spring-boot-legacy 项目首先注册一个 DispatcherServlet。其次,您必须手动创建一个 zuul servlet。

web.xml

<?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>

我找到了删除自动 servlet 注册的最佳方法,就是逐字复制名为 ZuulOverrideConfigZuulConfig,然后删除 zuulServlet() 方法。这是因为 ZuulProxyConfiguration 扩展了 ZuulConfiguration,即使我试图覆盖它,它似乎也创建了 bean。我不是 100% 了解这背后的机制,所以可能有更好的方法。

我在 ZuulOverrideConfig 中所做的第二个更改是调用 ZuulFilterInitializer 的扩展实现,称为“LegacyZuulFilterInitializer”。这是因为出于某种原因,Zuul servlet 正在被创建,并且能够被调用,但是没有过滤器被 bootstrapped。这个扩展是一种让过滤器达到 bootstrap.

的 hacky 方式

接下来,我创建了一个名为 ZuulLegacyProxyConfiguraitonZuulProxyConfiguration 副本,并扩展了 ZuulOverrideConfig.class

最后,我对Applicationclass注释如下。

@EnableCircuitBreaker
@EnableDiscoveryClient
@Import(ZuulLegacyProxyConfiguration.class)
@SpringBootApplication
public class Application {....}

经过所有这些 hack 之后,实现终于按预期工作了。我不建议长时间使用它,因为它很老套。迁移到新版本时,您不会自动获得配置 class 更新,而且我不能保证某些东西不会随机损坏!

这是使用 Spring Cloud 1.1。4.RELEASE

Gist of all the code.