【问题标题】:Legacy Spring MVC to Spring Boot旧版 Spring MVC 到 Spring Boot
【发布时间】:2020-10-22 09:53:29
【问题描述】:

我有一个使用 web.xml 配置的旧应用程序。 web.xml 看起来像这样。

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    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">

    <!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:spring/common-beans-context.xml
        </param-value>
    </context-param>

    <servlet>
        <servlet-name>dispatcherOne</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/dispatcherOne-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherOne</servlet-name>
        <url-pattern>/test/*</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>dispatcherTwo</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/dispatcherTwo-context.xml</param-value>
        </init-param>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherTwo</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

要将其转换为 Spring Boot 应用程序,

我做了以下改动:

@Bean
    public XmlWebApplicationContext xmlWebApplicationContext() {
        XmlWebApplicationContext applicationContext = new XmlWebApplicationContext();
        applicationContext.setConfigLocations("classpath:spring/common-beans-context.xml");
        applicationContext.refresh();
        return applicationContext;
    }

@Bean
    public ServletRegistrationBean<DispatcherServlet> mvcTestServlet(XmlWebApplicationContext applicationContext) {
        DispatcherServlet dispatcherServlet = new DispatcherServlet();
        // create child application context
        XmlWebApplicationContext childApplicationContext = new XmlWebApplicationContext();
        childApplicationContext.setConfigLocation("classpath:spring/dispatcherOne-context.xml");
        // set parent from the previous method
        childApplicationContext.setParent(applicationContext);
        dispatcherServlet.setApplicationContext(childApplicationContext);
        childApplicationContext.refresh();
        ServletRegistrationBean<DispatcherServlet> servletRegistrationBean = new ServletRegistrationBean<DispatcherServlet>(
                dispatcherServlet, "/test/*");
        servletRegistrationBean.setName("dispatcherOne");
        servletRegistrationBean.addUrlMappings("/test/*");
        servletRegistrationBean.setLoadOnStartup(1);
        return servletRegistrationBean;
    }

    @Bean
    public ServletRegistrationBean<DispatcherServlet> mvcServlet(XmlWebApplicationContext applicationContext) {
        DispatcherServlet dispatcherServlet = new DispatcherServlet();
        // similar to the previous method..
        // 1. create local applicationContext and then set parent.
    }

我添加了 childApplicationContext.refresh() 以查看 bean 是否正确加载,但我认为发生的是两个调度程序 servlet 无法访问 parentContext 中定义的 bean。并且抛出 bean not found 异常,即使它们在 parentContext 中可用

有解决办法吗?

或者还有其他方法可以实现吗?

【问题讨论】:

    标签: java xml spring spring-boot


    【解决方案1】:

    要创建 Spring Boot 应用程序并重新使用现有配置,请执行以下操作,并且不要自己创建上下文。您基本上是在尝试用您当前正在做的事情来超越或解决 Spring Boot。

    创建一个带有@SpringBootApplication注解的类,并使用@ImportResource让Spring Boot创建主应用上下文。

    @SpringBootApplication
    @ImportResource("classpath:spring/common-beans-context.xml")
    public YourApplication extends SpringBootServletInitializer {
    
      public static void main(String[] args) {
        SpringApplication.run(YourApplication.class, args);
      }
    
      protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(YourApplication.class);
      } 
    }
    

    现在您的原始配置中有 2 个DispatcherServlets,您需要添加 2 个ServletRegistrationBean 来设置 URL 等。

    @Bean
    public ServletRegistrationBean<DispatcherServlet> dispatcherServletOneRegistration() {
      ServletRegistrationBean<DispatcherServlet> registration = new ServletRegistrationBean(new DispatcherServlet(), "/test/*");
      registration.setLoadOnStartup(1);
      registration.setName("dispatcherOne");
      registration.setInitParameters(Collections.singletonMap("contextConfigLocation", "classpath:spring/dispatcherOne-context.xml");
      return registration;
    }
    

    第二个 servlet 或多或少相同。

    @Bean
    public ServletRegistrationBean<DispatcherServlet> dispatcherServletTwoRegistration() {
      ServletRegistrationBean<DispatcherServlet> registration = new ServletRegistrationBean(new DispatcherServlet(), "/");
      registration.setLoadOnStartup(1);
      registration.setName("dispatcherTwo");
      registration.setInitParameters(Collections.singletonMap("contextConfigLocation", "classpath:spring/dispatcherTwo-context.xml");
      return registration;
    }
    

    【讨论】:

    • 好的。我了解您在这里尝试做什么,并且我做了同样的更改,但我看到的是 /WEB-INF/dispatcherOne-context.xml 对应用程序启动没有任何影响。该文件中定义的 bean 没有被加载。我实际上试图为该文件(WEB-INF/dispatcherOneTEST-context.xml)提供错误的名称,但代码仍然没有将其标记为问题。知道是什么原因造成的吗?
    • 为什么需要标记该代码?如果没有加载,则说明您没有正确启动 Spring Boot 应用程序。如前所述,您需要 YourApplication 类并将这 2 个 @Bean 方法放在那里。如果这不起作用,您仍在使用 Spring Boot 而不是使用该框架,但是您的帖子中的信息太少,无法明确说明。
    • 我做了完全相同的事情,但它只是不会加载文件“classpath:spring/dispatcherOne-context.xml”中定义的bean,尽管代码执行方法dispatcherServletOneRegistration没有任何问题。它与方法/文件的名称有什么关系吗?
    • 我还注意到一件事,方法`@Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { System.out.println("test"); // 看看它是否被调用!返回 builder.sources(YourApplication.class); } ` 永远不会被调用。
    • 只有当你将应用程序作为一个war文件部署到你的tomcat servlet时才会被调用(我假设你会因为旧的应用程序而这样做)如果你运行它不会被调用主要方法。如果无法加载文件,它将通过找不到文件的异常。如果没有发生这种情况,则会阻止调用常规 servlet init 方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-08
    • 1970-01-01
    • 2020-03-29
    • 1970-01-01
    • 1970-01-01
    • 2019-05-24
    • 2015-02-19
    相关资源
    最近更新 更多