使用Google App Engine运行Spring Boot

请注意以下五点。

使用Spring Boot Legacy

由于AppEngine是Servlet 2.5,所以基于Servlet 3.0的Spring Boot无法运行。
因此,我们将使用适用于2.5的spring-boot-legacy。

compile 'org.springframework.boot:spring-boot-legacy'

剩下的部分就和平常一样依赖于 Web 和 Actuator。

compile 'org.springframework.boot:spring-boot-starter-web'
compile 'org.springframework.boot:spring-boot-starter-actuator'

将 SpringBootContextLoaderListener 放置在 web.xml 文件中。

這是符合Spring公式的Servlet 2.5指南。然而,需要更改以下兩點。

请用您的 Application 类替换 contextConfigLocation。

<?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.kaiinui.appenginetest.Application</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.boot.legacy.context.web.SpringBootContextLoaderListener</listener-class>
    </listener>

    <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-mapping>
        <servlet-name>appServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

在 metricFilter 中不执行过滤操作。

在 Spring 的官方指南中,我们使用 DelegatingFilterProxy 进行过滤操作,但由于与下一条相同的原因,我们将它移除。

如果web.xml按照之前提到的方式配置正确的话,就没有问题。

将 DispatcherServlet 的 publishEvents 设置为 false。

在Spring 4.1版本之后,通过DispatcherServlet的publishEvents方法调用HttpServletResponse的getStatus方法,但是由于该API在2.5版本中没有实现,所以会出现错误。

添加以下 init-param 到 DispatcherServlet 来禁用它。

<init-param>
    <param-name>publishEvents</param-name>
    <param-value>false</param-value>
</init-param>

以上的 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.kaiinui.appenginetest.Application</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.boot.legacy.context.web.SpringBootContextLoaderListener</listener-class>
    </listener>

    <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>
        <init-param>
            <param-name>publishEvents</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>appServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

使用 gmultipart 作为 multipartResolver

由于标准的CommonsMultipartResolver使用文件系统作为临时存储位置,因此我们将其替换。

如果你能够将所有内容读取到内存中,那么任何方式都可以。不过,我们可以使用已经很不错的 gmultipart 库来实现。

repositories {
    maven {
        url 'http://gmultipart.googlecode.com/svn/repo/m2'
    }
}

dependencies {
    compile 'gmultipart:gmultipart:0.4'
}
// @Configuration なクラスで

@Bean(name = "multipartResolver")
public GMultipartResolver multipartResolver() {
    GMultipartResolver resolver = new GMultipartResolver();
    resolver.setMaxUploadSize(100000);

    return resolver;
}

总结

Spring MVC(+ Spring Boot)在许多方面都非常健全,并且易于集成到AppEngine中,所以感觉还不错。

在Java的Web框架中,Play Framework非常受欢迎,但是由于需要进行魔改造才能使用,所以并不太推荐使用。

参考文献

    • http://docs.spring.io/spring-boot/docs/current/reference/html/howto-traditional-deployment.html#howto-servlet-2-5

 

    http://stackoverflow.com/questions/1302072/how-can-i-get-the-http-status-code-out-of-a-servletresponse-in-a-servletfilter
广告
将在 10 秒后关闭
bannerAds