【问题标题】:How to get access to ServletContext inside of an @Configuration or @SpringBootApplication class如何访问 @Configuration 或 @SpringBootApplication 类中的 ServletContext
【发布时间】:2018-04-26 16:04:46
【问题描述】:

我正在尝试更新旧的 Spring 应用程序。具体来说,我试图将所有 bean 从旧的 xml 定义的形式中提取出来,并将它们拉成 @SpringBootApplication 格式(同时大大减少了定义的 bean 的总数,因为它们中的许多不需要豆子)。我当前的问题是我不知道如何使 ServletContext 可用于需要它的 bean。

我当前的代码如下所示:

package thing;

import stuff

@SpringBootApplication
public class MyApp {

    private BeanThing beanThing = null;

    @Autowired
    private ServletContext servletContext; 

    public MyApp() {
        // Lots of stuff goes here.
        // no reference to servletContext, though
        // beanThing gets initialized, and mostly populated.
    }

    @Bean public BeanThing getBeanThing() { return beanThing; }

    @PostConstruct
    public void populateContext() {
        // all references to servletContext go here, including the
        // bit where we call the appropriate setters in beanThing
    }
}

我返回的错误:Field servletContext in thing.MyApp required a bean of type 'javax.servlet.ServletContext' that could not be found.

那么...我错过了什么?有什么我应该添加到路径中的吗?我需要实现一些接口吗?我自己无法提供 bean,因为重点是我正在尝试访问我自己没有的 servlet 上下文信息(getContextPath() 和 getRealPath() 字符串)。

【问题讨论】:

    标签: java spring spring-boot autowired postconstruct


    【解决方案1】:

    请注意访问ServletContext 的最佳实践:您不应该在您的主应用程序类中这样做,但是 e. G。控制器。

    否则请尝试以下操作:

    实现ServletContextAware 接口,Spring 将为您注入它。

    删除变量的@Autowired

    添加setServletContext方法。

    @SpringBootApplication
    public class MyApp implements ServletContextAware {
    
        private BeanThing beanThing = null;
    
        private ServletContext servletContext; 
    
        public MyApp() {
            // Lots of stuff goes here.
            // no reference to servletContext, though
            // beanThing gets initialized, and mostly populated.
        }
    
        @Bean public BeanThing getBeanThing() { return beanThing; }
    
        @PostConstruct
        public void populateContext() {
            // all references to servletContext go here, including the
            // bit where we call the appropriate setters in beanThing
        }
    
        public void setServletContext(ServletContext servletContext) {
            this.context = servletContext;
        }
    
    
    }
    

    【讨论】:

    • 所以...我目前在 Intellij IDEA 工作,如果我尝试在不实现抽象方法 setServletContext(ServletContext) 的情况下实现 ServletContextAware,它会抱怨。我可能会利用这一点,我会尝试,但你能在你的回答中以一种或另一种方式解决这个问题吗?
    • 是的,如果你实现了那个接口,你需要添加setServletContext方法。更新了我的答案。
    • 酷。似乎正在工作。事实证明,我设法适应了 setServletContext 本身的逻辑,并且能够完全摆脱 populateContext() 和 @PostConstruct。目前已接受,只要在此过程中不产生其他错误,就会一直接受。
    • 所以......我设法达到了它实际编译和运行的地步......由于我不明白的原因,从未调用过 setServletContext 。你有这方面的知识吗?
    • setServletContext 也没有为我调用,在 Spring Boot Starter 2.2.5 中不起作用
    【解决方案2】:

    让bean变得懒惰并使用参数:

    @Lazy
    @Bean
    public BeanThing getBeanThing(ServletContext servletContext) {
        return new BeanThing(servletContext);
    }
    

    它需要惰性,因为 ServletContext 在创建 MyApp 的实例时将不存在。当ServletContext 可用时,Spring 会在某处记住它,并可以填写参数。

    要完成这项工作,您只需确保在此之前没有请求 bean。

    现在您可能必须在此之前创建需要 BeanThing 的 bean。然后解决方案是注入 Provider<BeanThing> 并确保提供程序仅在 ServletContext 存在之后使用(即不在 @PostConstruct 或类似中)。

    【讨论】:

      猜你喜欢
      • 2020-01-09
      • 2018-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-10
      • 2019-01-25
      相关资源
      最近更新 更多