在 spring-boot 项目中使用 spring mvc xml 项目

Posted

技术标签:

【中文标题】在 spring-boot 项目中使用 spring mvc xml 项目【英文标题】:Use spring mvc xml project inside spring-boot project 【发布时间】:2016-08-13 08:42:55 【问题描述】:

我创建了这个测试项目,由 2 个项目组成:一个使用 spring-boot,一个使用 spring-mvc。它们中的每一个都可以独立工作。 我想要做的是运行 spring-boot 并能够通过加载它的上下文来访问 spring-mvc 项目的网页。 这个项目很简单,我只是想测试一下如何混音。

问题是,当我运行 spring-boot 应用程序时,无法访问 spring-mvc 的页面,因为它没有在构建中添加 webbapp 文件夹(包含 WEB-INF)。 我可以在 spring-boot 应用程序中从 spring-mvc 自动装配服务。

树如下所示:

spring-boot的Application.java类如下:

package hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;

import java.util.Arrays;

@SpringBootApplication
@ComponentScan("org.burdu", "hello")
//@ImportResource("classpath:WEB-INF/spring-core-config.xml", "classpath:WEB-INF/spring-mvc-config.xml")
public class Application 

public static void main(String[] args) 
    ApplicationContext ctx = SpringApplication.run(Application.class, args);

    System.out.println("Let's inspect the beans provided by Spring Boot:");

    String[] beanNames = ctx.getBeanDefinitionNames();
    Arrays.sort(beanNames);
    for (String beanName : beanNames) 
    System.out.println(beanName);
    


根 build.gradle

group 'net.burdu'
version '1.0-SNAPSHOT'

apply plugin: 'java'
apply plugin: 'idea'

sourceCompatibility = 1.8

repositories 
mavenCentral()
mavenLocal()


dependencies 
testCompile group: 'junit', name: 'junit', version: '4.11'

root settings.gradle

rootProject.name = 'testSpringXMLAndBoot'
include 'spring-mvc'
include 'spring-boot'

spring-boot build.gradle

apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'war'
apply plugin: 'spring-boot'

sourceCompatibility = 1.8

repositories 
jcenter()
mavenCentral()


buildscript 
repositories 
    mavenCentral()


dependencies 
    classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.3.RELEASE")



dependencies 
compile("org.springframework.boot:spring-boot-starter-web")
compile project(':spring-mvc')

spring-mvc build.gradle

apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'war'
apply plugin: 'jetty'

sourceCompatibility = 1.8

repositories 
mavenCentral()
mavenLocal()


dependencies 
compile 'ch.qos.logback:logback-classic:1.1.3'
compile 'org.springframework:spring-webmvc:4.1.6.RELEASE'
compile 'javax.servlet:jstl:1.2'


jettyRun
contextPath = ""
httpPort = 8080


jettyRunWar
contextPath = ""
httpPort = 8080

spring-core-config.xml

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:mvc="http://www.springframework.org/schema/mvc"
   xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd ">

<context:component-scan base-package="org.burdu.web" />

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="prefix" value="/WEB-INF/view/" />
    <property name="suffix" value=".jsp" />
</bean>

<mvc:resources mapping="/resources/**" location="/resources/" />

<mvc:annotation-driven />

</beans>

spring-mvc-config.xml

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:mvc="http://www.springframework.org/schema/mvc"
   xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd ">

<context:component-scan base-package="org.burdu.service" />

</beans>

spring-mvc 项目中的 web.xml

<web-app 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"
     version="2.5">

<display-name>Gradle + Spring MVC Hello World + XML</display-name>
<description>Spring MVC web application</description>

<!-- For web context -->
<servlet>
    <servlet-name>hello-dispatcher</servlet-name>
    <servlet-class>
    org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring-mvc-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>hello-dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<!-- For root context -->
<listener>
    <listener-class>
    org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring-core-config.xml</param-value>
</context-param>

</web-app>

spring-boot 中的 HelloController、HelloWorldService 和 WelcomeController 都是简单的 bean。我没有在这里粘贴他们的内容,因为问题已经太长了,但如果需要我可以添加它们。

【问题讨论】:

我想肯定还需要一些配置。您能否将您的项目发布到 github 或直接邮寄给我?如果我实现了,我将对此进行更多研究并发布任何有用的信息。 github.com/Burdu/testSpringXMLAndBoot 【参考方案1】:

我尝试对您的github project 进行这些小改动:

spring-boot/build.gradle:

// This will include files and settings from spring-mvc
war 
    baseName = 'testSpringXMLAndBoot'
    version =  '0.1.0'
    from '../spring-mvc/src/main/webapp'


// tomcat-embed-jasper is for jsp support
dependencies 
    ..
    compile("org.apache.tomcat.embed:tomcat-embed-jasper")
    ..

spring-boot/src/main/java/hello/Application.java:

@SpringBootApplication
@ComponentScan("org.burdu", "hello")
@ImportResource("classpath:WEB-INF/spring-mvc-config.xml") // added this resource back
public class Application 

    public static void main(String[] args) 
        ApplicationContext ctx = SpringApplication.run(Application.class, args);
        ..
    

正在运行:

spring-mvc/gradle jettyRun

仍将在 Jetty 服务器上独立运行 spring-mvcmodule

并运行:

spring-boot/java -jar build/libs/testSpringXMLAndBoot-0.1.0.war

将在spring-boot 中包含spring-mvc 上下文并在嵌入式Tomcat 上运行它们。

【讨论】:

但你仍然无法使用 Spring Boot 中的 Application.main 运行它 你能澄清一下这是什么意思吗?你是如何运行它的? 我的意思是你可以通过简单地运行 Application.main 类从你的 IDE 运行 spring 应用程序。在您提供的替代方案中,您无法做到这一点。【参考方案2】:

我已将合并后的项目导入到我的 IDE 中,但我发现很难将两个项目集成为一个并保持它们的原始性。真正的困难是spring不知道位于lib/spring-mvc.jar的子项目spring-mvc的jar里面的资源。如果我把它解压到子项目spring-boot,还是不行。

后来,我在 spring-boot 中找到了这个关于 JSP limitations 的文档,上面写着:

由于 Tomcat 中的硬编码文件模式,可执行 jar 将无法工作

此外,我的建议是将您的应用程序转换为现代 spring-boot 形式,如下所示:

Convert an existing application to Spring Boot

在这种情况下,您只需按照文档所述将web.xml 中定义的servlet 和过滤器转换为spring bean。此外,spring-core-config.xmlspring-mvc-config.xml 可以保持不变,因为即使它们在嵌入的 jar 中也可以直接导入。这应该很容易。

将应用程序转换为 Spring Boot 后,您也可以完全控制 Web 容器。

最后,如果您真的想一起使用它们,以下文档可能会很有用:

Deploying a WAR in an Old (Servlet 2.5) Container

这一次,您可以在您的web.xml 指定SpringBootContextLoaderListener 作为您的监听器。它可以帮助配置您的应用程序。但是,正如 spring 所说,它仅对将应用程序部署到旧容器中有用。

但是,如果我是你,我会将其转换为 spring-boot 格式。因为它可以简化维护工作。

spring boot默认只允许/,META-INF/resources,resources,public,static目录作为资源加载路径。从这个角度来看,如果您的所有资源都位于这些目录下,它应该可以工作。当然,specifying document root 是必需的。如果您可以容忍提取spring-mvc,我认为这将是解决方案。

如果嵌入jar中定义的spring上下文是你想要的,你可以在classpath之后加一个星号,比如classpath*:WEB-INF/applicationContext.xml。这将在任何 lib jar 中添加任何 WEB-INF/applicationContext.xml。换句话说,您只需在@ImportResource 表达式中的classpath 之后添加一个星号。如果一切顺利,你就在那里。

【讨论】:

谢谢。您可以删除 jsp 部分。想象一下 spring-mvc 应用程序只是 REST 并且在 webapp 中你有 javascript 前端。这可行吗? 我试图将spring-mvc 提取到spring-boot 中,这使它成为spring-boot 的一部分(如果您将spring-mvc 保留为嵌入式jar,File 无法识别资源在spring-mvc)。后来我调试了spring-boot,发现它只允许目录/,META-INF/resources,resources,public,static作为资源加载路径。 我最后改进了我的答案,请看看! 如果你的项目没有web.xml,比如只是一个用于持久化的子项目怎么办?它只有 applicationContext.xml。所以我们会有 spring-mvc、spring-boot 和 spring-persistance。我知道这不是主要问题,但我认为它不会归结为 web.xml。 如果只需要集成嵌入jar中定义的spring上下文,则需要在classpath后面加星号,如classpath*:WEB-INF/applicationContext.xml。这将在任何 lib jar 中添加任何 WEB-INF/applicationContext.xml。您只需在 @ImportResource 表达式中的 classpath 之后添加一个星号。如果一切顺利,你就在那里。

以上是关于在 spring-boot 项目中使用 spring mvc xml 项目的主要内容,如果未能解决你的问题,请参考以下文章

spring-boot+mybatis整合简写

spring-boot结合maven配置不同环境的profile

无法将 spring-boot 2 服务连接到不同容器中的 mysql

让 oauth2 与 spring-boot 和 rest 一起工作

在 spring-boot 项目中使用 spring mvc xml 项目

Spring-boot官方案例分析之data-jpa