java Spring 3 在自定义 bean 中接收 servletContext

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10666949/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 02:01:40  来源:igfitidea点击:

Spring 3 receive servletContext in custom bean

javaspringautowiredinjectapplicationcontext

提问by yaroslav prokipchyn

my problem is that I can't get servletcontext in my bean. I created custom bean "FileRepository" and I need to get ServletContext there. here is the code

我的问题是我无法在 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;
    }
}

registration in ApplicationContext.xml

在 ApplicationContext.xml 中注册

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

when saveFile(File file) starts, I recive Nullpointerexception because servletContext == null.

当 saveFile(File file) 启动时,我收到 Nullpointerexception,因为 servletContext == null。

So why servletcontext does not injected?I have ContextLoaderListener registred in web.xml

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

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

I found that there is some scopes. May be problem is there. Tell me briefly about applicationsontext scope or give the link pleas. Thanks for help. I spent a lot of time for this problem.

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

After some debuging I understood that setServletContexr method of servletcontextaware is actually was called when app starts but when I tried to store file with FileRepository from my controller, it was already anather object with null servletContext field.

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

Is there a way just to autowier servlet context in my custom bean when i want, like in controller?

有没有办法在我想要的时候在我的自定义 bean 中自动执行 servlet 上下文,就像在控制器中一样?

Finaly I get servletContext via ServletContextAware. I change the way of creation fileRepository bean. From this

最后我通过 ServletContextAware 获得了 servletContext。我改变了创建 fileRepository bean 的方式。由此

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

to this

对此

@Autowired
private FileRepository fileRepository;

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

回答by Kent Rancourt

ContextLoaderListener loads an ApplicationContext that becomes the global parent context for the application. There is no ServletContext there. ServletContext only exists within (pardon the overloading of terms) the CONTEXT of a SERVLET- for instance, the DispatcherServlet. Every DispatcherServlet (typically you'd only have one) registers a child context that points back to the global parent context registered by the ContextLoaderListener. ApplicationContexts are like classloaders. When the IOC container goes "looking" for a bean, each ApplicationContext can look "up" to its parent to try to find it, but it can't look down. Children can also override bean definitions from their parent context.

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

Now... it would seem your problem is that your bean is defined in global parent context where there is no ServletContext to be found. (It can't look "down" to its children to find it.)

现在……您的问题似乎是您的 bean 是在全局父上下文中定义的,在该上下文中找不到 ServletContext。(它不能“俯视”它的孩子才能找到它。)

What you need to do is move the fileStorage bean definition "down" into the ApplicationContext for the DispatcherServlet.

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

When you define a DispatcherServlet in your web.xml, you usually specify where it can find the files that define its child context. Like so:

当您在 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>

Move that bean definition down into the location specified by contextConfigLocation and everything should work as you expect.

将该 bean 定义向下移动到 contextConfigLocation 指定的位置,一切都应该如您所愿。