英文:
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应用程序。
因此,我们有两种选择:
-
在SpringBoot应用程序前面运行反向代理,例如Nginx。
-
将SpringBoot应用程序打包为
war
,并放入某个容器中。例如:
- 下载Tomcat并使用默认配置启动它。
- 构建一个
my-app-1.0.0-SNAPSHOT.war
,将其重命名为myapp.war
,并复制到Tomcat的/webapps
目录中。 - 您可以访问
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 /foo
和http GET /myapp/foo
。
注意:
- 不支持WebFlux。
- 如果需要,可以使用自定义的应用程序上下文。
英文:
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:
-
Run a reverse proxy in front of your SpringBoot application. Such as Nginx
-
Package your SpringBoot application as a
war
, and put it into some container.For example:
- Download tomcat and start it with default configuration.
- Build a
my-app-1.0.0-SNAPSHOT.war
, rename it tomyapp.war
and copy it to your tomcat's/webapps
directory. - 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<? 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) {
// create applicationContext or use the auto configured one
return createServletRegistrationBean(context, "firstOne", "/*");
}
@Bean
public ServletRegistrationBean<? extends Servlet> anotherContextPath(ApplicationContext context) {
return createServletRegistrationBean(context, "secondOne", "/myapp/*");
}
As this example, we can run http GET /foo
and http GET /myapp/foo
at the same time.
Notes:
- WebFlux is NOT supported.
- 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<ConfigurableServletWebServerFactory>
webServerFactoryCustomizer() {
return factory -> factory.setContextPath("/context");
}
With Spring Boot 1, we can create an instance of EmbeddedServletContainerCustomizer:
@Bean
public EmbeddedServletContainerCustomizer
embeddedServletContainerCustomizer() {
return container -> container.setContextPath("/yourContext");
}
Or with java System property
public static void main(String[] args) {
System.setProperty("server.servlet.context-path", "/yourContext");
SpringApplication.run(Application.class, args);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论