简体   繁体   中英

How to get access to ServletContext inside of an @Configuration or @SpringBootApplication class

I'm attempting to update an old Spring application. Specifically, I'm trying to pull all of the beans out of the old xml-defined form and pull them into a @SpringBootApplication format (while dramatically cutting down on the overall number of beans defined, because many of them did not need to be beans). My current issue is that I can't figure out how to make the ServletContext available to the beans that need it.

My current code looks something like this:

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
    }
}

The error I get back: Field servletContext in thing.MyApp required a bean of type 'javax.servlet.ServletContext' that could not be found.

So... what am I missing? Is there something I'm supposed to be adding to the path? Is there some interface I need to implement? I can't provide the bean myself because the whole point is that I'm trying to access servlet context info (getContextPath() and getRealPath() strings) that I don't myself have.

Please be aware of the best practice for accessing the ServletContext : You shouldn't do it in your main application class, but eg a controller.

Otherwise try the following:

Implement the ServletContextAware interface and Spring will inject it for you.

Remove @Autowired for the variable.

Add setServletContext method.

@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;
    }


}

Make the bean lazy and use a parameter:

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

It needs to be lazy because the ServletContext won't exist when the instance of the MyApp is created. When the ServletContext becomes available, Spring will remember it somewhere and it will be able to fill in the parameter.

To make this work, you just have to make sure the bean isn't requested before that.

Now you might have to create beans which need BeanThing earlier than that. The solution then is to inject a Provider<BeanThing> and make sure the provider is only used after the ServletContext exists (ie not in @PostConstruct or similar).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM