我如何在 Spring MVC 启动期间找到基础 URL?

How do I find base URL during Spring MVC startup?

潜伏在 Stack Overflow 的程序员。

今天的问题:如何从启动时获取 Spring MVC Framework 中的绝对 baseUrl?

我正在为一个应用程序使用 Spring MVC 框架,我处于这种情况:假设我需要制作 class Foo 的对象,插入到列表中。每个对象都包含一个唯一的 self-link(我在实际应用中使用 org.springframework.hateoas.Link,但这不是重点)。

示例代码:

class Foo{
    private int ID;
    private String absoluteUrl;

    public Foo(int ID, String baseUrl){
        this.ID = ID;
        this.absoluteUrl = baseUrl + ID; 
    }

    public void setAbsoluteUrl(String baseUrl){
        this.absoluteUrl = baseUrl + this.ID;
    }
}

如果我 运行 通过工厂,它可能看起来像这样:

public List<Foo> GenerateFooList(String baseUrlFetchedBySpring){
    List<Foo> list = new ArrayList();
    for (int i = 0; i<100; i++){
    list.add(new Foo(i, baseUrlFetchedBySpring);
    return list;
}

我期望在测试阶段产生的基址是“http://localhost:8000" (or hypothetically, at production, "http://www.fooExample.com”)。

我的问题:我需要在启动时从 Spring MVC 框架获取 baseUrl。

我正在使用的 Spring MVC 应用程序仅通过注释进行配置。我发现可以通过使用 HttpServletRequest.getRequestURL().toString() 获得绝对值 url,但据我了解,应用程序在 启动后收到这些 ,虽然我从一开始就需要 baseUrl。毕竟,Spring API 将 HttpServletRequest 描述为:"Defines an object to provide client request information to a servlet",换句话说,从客户端 after startup.

我当然可以通过在代码中编写一个私有的最终字符串来添加一个静态 baseUrl:

private final String BASE_URL = "http://www.fooExample.com/"

但是如果应用程序的基数-url 随着时间的推移发生变化,如果基数 url 可以由 Spring MVC 自动设置会更好。假设我有一个 Cache-class,它使用依赖注入:

@Repository
class FooCache{

    List<Foo> list;
    SpringObject springObject; // = ???????????

    @Autowired
    public FooCache(SpringObject springObject){
        this.springObject = springObject; // = ???????????
        initCache();
    }

    public void initCache(){
        for (int i = 0; i<100; i++){
        list.add(new Foo(i, springObject.getAbsoluteBaseUrl()); // method = ???????????
    }
}

这正是我要寻找的更多内容:缓存仅在开始时设置一次,使用 Spring 中包含我需要的信息的对象。最有可能的是框架中的一个config-class,但是在网上搜索了一段时间后,我发现的主要是HttpServletRequest相关的解决方案。

我真正在寻找什么 Spring class/object 和方法?或者您还有什么其他建议可以从头开始获取 base_url?

我需要这个的绝对基础 url,而不是相对的。

如果您使用 java 配置和 Servlet 3.0+ 样式(没有 web.xml),您可以有一个 WebApplicationInitializer 实现,例如:

public class MyWebApplicationInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext container) {
        ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet());
        registration.setLoadOnStartup(1);
        registration.addMapping("/example/*");
    }

}

通过这种安排,您可以使用 servletContext.getContextPath() 获得基数 url。

没有请求,你无法知道。您可以使用 InetAddress 并解析主机信息,但我猜这不是您要查找的内容。

假设您有两个域 www.foo.com 和 www.bar.com 指向您的应用程序所在的主机 运行。在启动时你没有任何关于这些的信息,你将不得不进行反向 DNS 搜索。 当您收到请求时,您会知道请求的来源。

您应该根据请求填写链接,这样您就可以摆脱缓存请求范围信息。

您的应用程序没有单个 "base URL"。想一想 - 您可以访问您的生产服务器:

  • 通过不同的域名
  • 通过 IP
  • 通过 SSH 访问它并通过 "localhost"
  • 访问
  • 通过 HTTP 和 HTTPS

如果您不想或不能反映请求的 "base URL",我的建议是为每个环境配置一个 "canonical base URL",例如。在属性中。但这取决于你是否对你的情况有意义。