【问题标题】:Spring 3 receive servletContext in custom beanSpring 3 在自定义 bean 中接收 servletContext
【发布时间】:2012-05-26 20:57:28
【问题描述】:

我的问题是我无法在我的 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(File file) 启动时,我收到 Nullpointerexception 因为 servletContext == null。

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

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

我发现有一些范围。可能有问题。简要告诉我有关 applicationsontext 范围的信息或提供链接请求。 感谢帮助。我花了很多时间来解决这个问题。

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

有没有办法在我想要的时候在我的自定义 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) {

【问题讨论】:

    标签: java spring autowired inject applicationcontext


    【解决方案1】:

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

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

    您需要做的是将 fileStorage bean 定义“向下”移动到 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 指定的位置,一切都会按您的预期工作。

    【讨论】:

    • 我已将 bean 注册的位置更改为 WEB-INF/spring/webmvc-config.xml 但仅在应用程序启动时才收到 servletContext。当我调用 fileRepository.saveFile() 时,fileRepository 是另一个没有定义 servletContext 的实例。当我使用它时,有没有办法将 servletContext 自动连接到我的 bean。就像在控制器中一样。 @autowired 私有 ServletContext servletContext;谢谢。
    • 可能是我在控制器中获得了类似方法参数的fileRepository的问题。
    • 您是否声称您现在有两个 FileRepository 实例?如果是这样,请查看您在我的 cmets 上下文中围绕 ApplicationContext 层次结构所做的事情。如果另一个未由子上下文定义的 bean 被注入了一个也未在子上下文中定义的 FileRepository,那么该 FileRepository 仍然会出现您原来的问题。您需要确保所有依赖于 ServletContext(或依赖于依赖它的东西等)的东西都在子上下文中定义,而不是在父上下文中。
    猜你喜欢
    • 2013-02-06
    • 2015-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多