Spring 4 + 嵌入式 Tomcat 7

标签 spring spring-mvc tomcat embedded-tomcat-7

我尝试使用 Spring Web MVC 4.3.2 和嵌入式 Tomcat 7.0.64 构建一个 Web 应用程序。

我没有设法编写正确的主要方法来启动嵌入式 Tomcat。它适用于发送 @ResponseBody 内容 (JSON) 的 Spring Controller,但对于 JSP View 失败。

public static void main(String[] args) throws Exception {

    String appBase = ".";// What to put here ?

    Tomcat tomcat = new Tomcat();
    String contextPath = "";
    String port = System.getProperty("server.port");
    tomcat.setPort(port == null ? 8080 : Integer.valueOf(port));

    tomcat.getHost().setAppBase(appBase);
    Context context = tomcat.addWebapp(contextPath, appBase);

    // So that it works when in it's launched from IntelliJ or Eclipse
    // Also need that a folder named "META-INF" exists in build/classes/main
    // https://bz.apache.org/bugzilla/show_bug.cgi?id=52853#c19
    ((StandardJarScanner) context.getJarScanner()).setScanAllDirectories(true);

    tomcat.start();
    tomcat.getServer().await();
}

对于 JSP View ,它说:请求的资源不可用 (WEB-INF/views/home.jsp) HTTP 404

如果我将 appBase 变量设置为 JSP 所在的绝对路径,它就可以工作。但是,当然,这不是解决方案,因为它不能在另一台机器上运行。我需要一个相对路径。

如果我将 appBase varibale 设置为 "src/main/webapp",则 Tomcat 无法启动并出现以下错误:java.lang.IllegalArgumentException:文档库 C:\blabla\spring-jsp-embedded-tomcat\tomcat.8080\src\main\webapp\src\main\webapp 不存在或不是可读目录.

此外,使用Gradle fat jar 技术构建的jar 不包含WEB-INF 目录。

我怎样才能制作一个简单的 Spring MVC 应用程序与嵌入式 Tomcat 和 JSP 一起工作(使用 java -cp path/to/my/jar com.app.Launcher 启动)?

build.gradle :

apply plugin: 'java'

sourceCompatibility = 1.7
version = '1.0'

jar {
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}

repositories {
    maven { url "http://repo1.maven.org/maven2" }
}

dependencies {

    compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.6.2'
    compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.6.2'
    compile group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: '2.6.2'

    compile 'org.springframework:spring-webmvc:4.3.2.RELEASE'

    compile 'com.fasterxml.jackson.core:jackson-databind:2.7.0'

    compile 'javax.servlet:javax.servlet-api:3.0.1'
    compile 'javax.servlet.jsp:jsp-api:2.2'
    compile 'javax.servlet:jstl:1.2'

    // Embedded Tomcat
    // 2 mandatory libs
    compile 'org.apache.tomcat.embed:tomcat-embed-core:7.0.64'
    compile 'org.apache.tomcat.embed:tomcat-embed-logging-juli:7.0.64'
    // To enable JSPs
    compile 'org.apache.tomcat.embed:tomcat-embed-jasper:7.0.64'

    testCompile group: 'junit', name: 'junit', version: '4.+'

}

Tomcat 启动器:

public class Launcher {

    public static void main(String[] args) throws Exception {
        String contextPath = "";
        // String appBase = "C:/absolute/path/to/webapp/dir"; // It works but of course I need a relative path
        // String appBase = "."; // Works only for Controller sending back ResponseBody (JSON) but fail to find jsp files
        String appBase = "src/main/webapp"; // Tomcat does not start properly

        Tomcat tomcat = new Tomcat();

        String port = System.getProperty("server.port");
        tomcat.setPort(port == null ? 8080 : Integer.valueOf(port));

        tomcat.getHost().setAppBase(appBase);
        Context context = tomcat.addWebapp(contextPath, appBase);

        // So that it works when in it's launched from IntelliJ or Eclipse
        // Also need that a folder named "META-INF" exists in build/classes/main
        // https://bz.apache.org/bugzilla/show_bug.cgi?id=52853#c19
        ((StandardJarScanner) context.getJarScanner()).setScanAllDirectories(true);

        tomcat.start();
        tomcat.getServer().await();
    }

}

Spring 网络应用初始化程序:

public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] { RootConfig.class };
    }
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] { WebConfig.class };
    }

}

网络配置:

@Configuration
@EnableWebMvc
@ComponentScan("com.app")
public class WebConfig extends WebMvcConfigurerAdapter {

    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        resolver.setExposeContextBeansAsAttributes(true);
        return resolver;
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

}

文件夹结构:

enter image description here

最佳答案

显然,嵌入式 Tomcat 期望静态资源位于 META-INF/resources 目录中。我跟着这个:tutorial我检查了最终 jar 的结构。

所以我修改了 Gradle 构建脚本以将 JSP 放在那里。

sourceSets {
    main {
        resources.srcDirs = ["src/main/webapp"]
        output.resourcesDir = "$buildDir/classes/main/META-INF/resources"
    }
}

现在可以了。但是,我觉得这是一项临时工作。如果有人有更令人满意和更有教育意义的答案,我会很高兴。

关于Spring 4 + 嵌入式 Tomcat 7,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39253813/

相关文章:

Spring 幕后日志记录

spring - 在 Spring Cloud Config 中存储 Spring Cloud Vault token

spring - 使用 Spring 配置文件启用/禁用 web.xml 过滤器

java - 嵌入式 Servlet 3.0 容器使用 ServletContainerInitializer 而不是 web.xml

java - Java 配置中的 Spring Mvc 消息包

java - 如何热部署我的 Java 项目?

apache - 如何将用户名和密码添加到 Apache tomcat?

gwt - 无法弄清楚为什么我不能将 GWT 应用程序部署到 Apache Tomcat 7

java - spring security HTTP状态403-访问被拒绝

java - Spring MVC - 是否有替代方法来显示表单验证错误消息(不使用 @ModelAtrribute 和 @Valid)?