3

私の問題は、Bean でサーブレットコンテキストを取得できないことです。カスタム 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) が起動すると、servletContext == null のため、Nullpointerexception が発生します。

では、なぜ servletcontext が注入されないのでしょうか? ContextLoaderListener を web.xml に登録しています

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

いくつかのスコープがあることがわかりました。問題があるかもしれません。applicationsontext スコープについて簡単に説明するか、リンクをお願いします。手伝ってくれてありがとう。私はこの問題に多くの時間を費やしました。

いくつかのデバッグの後、アプリの起動時に servletcontextaware の setServletContexr メソッドが実際に呼び出されたことを理解しましたが、コントローラーから FileRepository でファイルを保存しようとすると、それはすでに null servletContext フィールドを持つ別のオブジェクトでした。

コントローラーのように、必要なときにカスタム Bean でサーブレット コンテキストを autowier する方法はありますか?

最後に、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) {
4

1 に答える 1

4

ContextLoaderListener は、アプリケーションのグローバルな親コンテキストになる ApplicationContext をロードします。そこには ServletContext はありません。ServletContext は、たとえば DispatcherServlet などの SERVLET の CONTEXT 内にのみ存在します (用語のオーバーロードを許してください)。すべての DispatcherServlet (通常は 1 つだけ) は、ContextLoaderListener によって登録されたグローバルな親コンテキストを指す子コンテキストを登録します。ApplicationContext はクラスローダーに似ています。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 で指定された場所に移動すると、すべてが期待どおりに機能するはずです。

于 2012-05-19T17:13:02.533 に答える