Spring 3在自定义bean中接收servletContext

时间:2012-05-19 16:25:02

标签: java spring autowired inject applicationcontext

我的问题是我无法在我的bean中获取servletcontext。 我创建了自定义bean“FileRepository”,我需要在那里获取ServletContext。 这是代码

package com.pc.webstore.utils;

import java.io.File;
import java.nio.file.Files;

import javax.servlet.ServletContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.ServletContextAware;
public class FileRepository implements ServletContextAware {

private ServletContext servletContext;

public String saveFile(File file){
    File tempdir = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
            ...
}

@Override
public void setServletContext(ServletContext servletContext) {
    this.servletContext = servletContext;
    }
}

在ApplicationContext.xml中注册

 <bean id="fileStorage" class="com.pc.webstore.utils.FileRepository"/>

当saveFile(文件文件)启动时,我重新发现Nullpointerexception,因为servletContext == null。

那么为什么不注入servletcontext? 我在web.xml中注册了ContextLoaderListener

   <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

我发现有一些范围。可能是问题在那里。请简要介绍一下applicationontext范围或给出链接请求。 感谢帮助。我花了很多时间来解决这个问题。

经过一些调试后,我了解到servletcontextaware的setServletContexr方法实际上是在应用程序启动时调用的,但是当我尝试使用FileRepository从我的控制器存储文件时,它已经是具有null servletContext字段的anather对象。

在我想要的时候,有没有办法在自定义bean中自动跟踪servlet上下文,比如在控制器中?

最后我通过ServletContextAware获取servletContext。我改变了创建fileRepository bean的方式。从这个

public String create(@Valid Item item, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest, FileRepository fileRepository)     {

到这个

@Autowired
private FileRepository fileRepository;

@RequestMapping(method = RequestMethod.POST, produces = "text/html")
public String create(@Valid Item item, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest) {

1 个答案:

答案 0 :(得分:4)

ContextLoaderListener加载一个ApplicationContext,它成为应用程序的全局父上下文。那里没有ServletContext。 ServletContext仅存在于(请原谅术语的重载)SERVLET的CONTEXT中,例如DispatcherServlet。每个DispatcherServlet(通常只有一个)都会注册一个子上下文,该上下文指向ContextLoaderListener注册的全局父上下文。 ApplicationContexts就像类加载器一样。当IOC容器“查找”bean时,每个ApplicationContext都可以向上查看其父级以尝试查找它,但它不能向下看。孩子们也可以从父上下文中覆盖bean定义。

现在......看起来你的问题是你的bean是在没有找到ServletContext的全局父上下文中定义的。 (它不能让孩子看起来“向下”找到它。)

您需要做的是将fileStorage bean定义“down”移动到DispatcherServlet的ApplicationContext中。

在web.xml中定义DispatcherServlet时,通常会指定在何处可以找到定义其子上下文的文件。像这样:

<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:/web-context/*.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

将该bean定义向下移动到contextConfigLocation指定的位置,一切都应该按预期工作。