在Spring Boot中,如何在上下文路径之外进行重定向?

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

In spring boot, how do I redirect outside of the context-path?

问题

我有一个Spring Boot应用程序,在属性文件中我已经定义了:

server.servlet.context-path= /myapp

如果我访问 http://localhost/myapp,一切都如预期那样显示。但是,如果我访问:http://localhost,我会看到来自Apache Tomcat的标准404错误页面。

如何在Spring Boot中设置从 //myapp 的重定向?

或者等效地:我可以在单个Spring Boot应用程序中设置多个上下文路径吗?

英文:

I have a spring boot application, in the properties file I have defined:

server.servlet.context-path= /myapp

If I go to http://localhost/myapp I see everything as expected. However if I go to: http://localhost I see a standard 404 error page from Apache Tomcat.

How can I setup a redirect from / to /myapp in spring boot?

Alternatively / equivalently: Can I setup multiple context-paths in a single spring-boot application?

答案1

得分: 5

以下是翻译好的部分:

你的问题会导致稍后引用的应用程序出现问题,因为你是从一个网址进入的,每次都会重定向到一个网址... 这是一个不好的方法。

如果我是你,我会在开始时正确设置:在你的Tomcat中创建一个根虚拟主机,并使用根上下文"/"来提供你的应用程序,而不是"/myapp",除非你(或你的客户、老板)想要那样做...

来自使用Apache Tomcat的虚拟主机的示例配置:
来源:https://tecadmin.net/create-virtualhost-in-tomcat/

<Host name="example.com"  appBase="webapps" unpackWARs="true" autoDeploy="true">
 <Alias>www.example.com</Alias>
 
 <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
           prefix="example_access_log" suffix=".txt"
           pattern="%h %l %u %t %r %s %b" />
 
 <Context path="" docBase="/opt/tomcat/webapps/myapp1" debug="0" reloadable="true"/>
</Host>

<Host name="mydomain.org"  appBase="webapps" unpackWARs="true" autoDeploy="true">
 <Alias>www.mydomain.org</Alias>
 
 <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
           prefix="mydomain_access_log" suffix=".txt"
           pattern="%h %l %u %t %r %s %b" />
 
 <Context path="" docBase="/opt/tomcat/webapps/myapp2"
    debug="0" reloadable="true"/>
</Host>
英文:

Your question will result in bad referenced app later because you are arrived on a webname and you are landing everytime on a redirect... Bad way to go.
If I were you, I will put the things correctly at the start : create a root virtualhost inside your Tomcat and serve your application with root "/" context, and not "/myapp", unless you (or your client, boss) want it like that...

Example config from a VirtualHost with Apache Tomcat :
From https://tecadmin.net/create-virtualhost-in-tomcat/

<Host name="example.com"  appBase="webapps" unpackWARs="true" autoDeploy="true">
 <Alias>www.example.com</Alias>
 
 <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
           prefix="example_access_log" suffix=".txt"
           pattern="%h %l %u %t %r %s %b" />
 
 <Context path="" docBase="/opt/tomcat/webapps/myapp1" debug="0" reloadable="true"/>
</Host>

<Host name="mydomain.org"  appBase="webapps" unpackWARs="true" autoDeploy="true">
 <Alias>www.mydomain.org</Alias>
 
 <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
           prefix="mydomain_access_log" suffix=".txt"
           pattern="%h %l %u %t %r %s %b" />
 
 <Context path="" docBase="/opt/tomcat/webapps/myapp2"
    debug="0" reloadable="true"/>
</Host>

答案2

得分: 2

如果您将SpringBoot应用程序打包成jar,则Tomcat将作为默认的嵌入式容器包含在其中。

您无法要求嵌入式Tomcat像独立服务一样托管多个Web应用程序。

因此,我们有两种选择:

  1. 在SpringBoot应用程序前面运行反向代理,例如Nginx

  2. 将SpringBoot应用程序打包为war,并放入某个容器中。

    例如:

    1. 下载Tomcat并使用默认配置启动它。
    2. 构建一个my-app-1.0.0-SNAPSHOT.war,将其重命名为myapp.war,并复制到Tomcat的/webapps目录中。
    3. 您可以访问http://localhost:8080/myapp,Tomcat可以托管/webapps中的所有有效文件夹和war文件。

PS:如果您使用Spring Reactive Web(WebFlux,Netty),第二种方法将不起作用。

更新

以下是我在评论中提到的ServletRegistrationBean的示例代码。

// 在这里使用DispatcherServlet
private ServletRegistrationBean<? extends Servlet> createServletRegistrationBean(
    ApplicationContext context, String name, String... urlMappings) {
  final DispatcherServlet dispatcherServlet = new DispatcherServlet();
  dispatcherServlet.setApplicationContext(context);

  final ServletRegistrationBean<DispatcherServlet> servletRegistrationBean =
      new ServletRegistrationBean<>(dispatcherServlet, urlMappings);
  servletRegistrationBean.setName(name);
  return servletRegistrationBean;
}

@Bean
public ServletRegistrationBean<? extends Servlet> oneContextPath(ApplicationContext context) {
  // 创建应用程序上下文或使用自动配置的上下文
  return createServletRegistrationBean(context, "firstOne", "/*");
}
@Bean
public ServletRegistrationBean<? extends Servlet> anotherContextPath(ApplicationContext context) {
  return createServletRegistrationBean(context, "secondOne", "/myapp/*");
}

就像这个示例一样,我们可以同时运行http GET /foohttp GET /myapp/foo

注意:

  1. 不支持WebFlux。
  2. 如果需要,可以使用自定义的应用程序上下文。
英文:

If you package SpringBoot application as jar, Tomcat would be included as the default embedded container.

You can't ask the embedded Tomcat to host multi web-app like what it could do as a standalone service.

So we have two choice:

  1. Run a reverse proxy in front of your SpringBoot application. Such as Nginx

  2. Package your SpringBoot application as a war, and put it into some container.

    For example:

    1. Download tomcat and start it with default configuration.
    2. Build a my-app-1.0.0-SNAPSHOT.war, rename it to myapp.war and copy it to your tomcat's /webapps directory.
    3. You can visit http://localhost:8080/myapp, tomcat could host all valid folders and wars in /webapps.

PS: If you are using Spring Reactive Web(WebFlux, Netty), the second method wouldn't work.

UPDATE

Here is what I said about ServletRegistrationBean in comments.

  // use DispatcherServlet here
  private ServletRegistrationBean&lt;? extends Servlet&gt; createServletRegistrationBean(
      ApplicationContext context, String name, String... urlMappings) {
    final DispatcherServlet dispatcherServlet = new DispatcherServlet();
    dispatcherServlet.setApplicationContext(context);

    final ServletRegistrationBean&lt;DispatcherServlet&gt; servletRegistrationBean =
        new ServletRegistrationBean&lt;&gt;(dispatcherServlet, urlMappings);
    servletRegistrationBean.setName(name);
    return servletRegistrationBean;
  }

  @Bean
  public ServletRegistrationBean&lt;? extends Servlet&gt; oneContextPath(ApplicationContext context) {
    // create applicationContext or use the auto configured one
    return createServletRegistrationBean(context, &quot;firstOne&quot;, &quot;/*&quot;);
  }
  @Bean
  public ServletRegistrationBean&lt;? extends Servlet&gt; anotherContextPath(ApplicationContext context) {
    return createServletRegistrationBean(context, &quot;secondOne&quot;, &quot;/myapp/*&quot;);
  }

As this example, we can run http GET /foo and http GET /myapp/foo at the same time.

Notes:

  1. WebFlux is NOT supported.
  2. Custom applicationContext if you need.

答案3

得分: 0

以下是翻译好的部分:

有很多选项可以做到这一点,对于外部服务器,可以使用 WebServerFactoryCustomizer

@Bean
public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> webServerFactoryCustomizer() {
return factory -> factory.setContextPath("/context");
}

使用 Spring Boot 1,我们可以创建 EmbeddedServletContainerCustomizer 的实例:

@Bean
public EmbeddedServletContainerCustomizer embeddedServletContainerCustomizer() {
return container -> container.setContextPath("/yourContext");
}

或者使用 Java 系统属性:

public static void main(String[] args) {
System.setProperty("server.servlet.context-path", "/yourContext");
SpringApplication.run(Application.class, args);
}

英文:

You have so many options to do that and for external servers by WebServerFactoryCustomizer

@Bean
public WebServerFactoryCustomizer&lt;ConfigurableServletWebServerFactory&gt;
  webServerFactoryCustomizer() {
    return factory -&gt; factory.setContextPath(&quot;/context&quot;);
}

With Spring Boot 1, we can create an instance of EmbeddedServletContainerCustomizer:

@Bean
public EmbeddedServletContainerCustomizer
  embeddedServletContainerCustomizer() {
    return container -&gt; container.setContextPath(&quot;/yourContext&quot;);
}

Or with java System property

public static void main(String[] args) {
    System.setProperty(&quot;server.servlet.context-path&quot;, &quot;/yourContext&quot;);
    SpringApplication.run(Application.class, args);
}

huangapple
  • 本文由 发表于 2020年8月6日 00:15:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/63269328.html
匿名

发表评论

匿名网友

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

确定