遗留的Spring MVC迁移到Spring Boot

huangapple go评论79阅读模式
英文:

Legacy Spring MVC to Spring Boot

问题

以下是已翻译的内容:

我有一个使用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">

    <!-- 所有Servlet和Filter共享的Root Spring容器定义 -->
    <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();
    // 创建子应用程序上下文
    XmlWebApplicationContext childApplicationContext = new XmlWebApplicationContext();
    childApplicationContext.setConfigLocation("classpath:spring/dispatcherOne-context.xml");
    // 设置父上下文来自前一个方法
    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();
    // 类似于上一个方法...
    // 1. 创建局部应用程序上下文,然后设置父上下文。
}

我添加了childApplicationContext.refresh()以查看bean是否正确加载,但我认为问题在于两个调度程序servlet无法访问父上下文中定义的bean。即使在父上下文中可用,它们仍会抛出bean未找到异常。

是否有解决方法?

或者是否有其他方法可以实现这一点?

英文:

I have a legacy application which uses web.xml configuration.
The web.xml looks something like this.

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;web-app version=&quot;2.5&quot; xmlns=&quot;http://java.sun.com/xml/ns/javaee&quot; xmlns:web=&quot;http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&quot;
	xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&quot;&gt;

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

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

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

To Convert this to Spring Boot Application,

I have done the below changes:

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

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

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

I added childApplicationContext.refresh() to see if the beans were loading properly but what i think is happening is that the two dispatcher servlets are not able to access the beans defined in the parentContext. and are throwing beans not found exception even though they're available in parentContext

Is there a workaround for this?

or is there any other way I can achieve this ?

答案1

得分: 2

创建一个Spring Boot应用程序并重用现有配置,只需按照以下步骤操作,不要手动创建上下文。基本上,您正在尝试通过目前的做法来跳过或绕过Spring Boot。

创建一个使用@SpringBootApplication注释的类,并使用@ImportResource注释,让Spring Boot创建主应用程序上下文。

@SpringBootApplication
@ImportResource("classpath:spring/common-beans-context.xml")
public class 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个DispatcherServlet,您需要添加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;
}
英文:

To create a Spring Boot application and re-using your existing config do the following and don't create a context yourself. You are basically trying to outsmart or work-around Spring Boot with what you are currently doing.

Create a class annotated with @SpringBootApplication and use @ImportResource to let Spring Boot creat the main application context.

@SpringBootApplication
@ImportResource(&quot;classpath:spring/common-beans-context.xml&quot;)
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);
  } 
}

Now as you have 2 DispatcherServlets in your original config you need to add 2 ServletRegistrationBean to set the URL etc.

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

And more or less the same for the second servlet.

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

huangapple
  • 本文由 发表于 2020年10月22日 17:53:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/64479729.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定