【问题标题】:Spring MVC: autowire ignored in servletsSpring MVC:在 servlet 中忽略自动装配
【发布时间】:2014-07-26 06:13:45
【问题描述】:

由于某些原因,我可以在我的控制器中自动装配,但不能在我创建的 servlet 中。

这是我的 servlet 的顶部:

@Component
public class MyServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {

    @Autowired
    private CobiService cobiService;

在我的 web.xml 这是相关的配置:

    <servlet>
        <servlet-name>convservlet</servlet-name>
        <servlet-class>com.gim.servlets.MyServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>convservlet</servlet-name>
        <url-pattern>/MyServlet</url-pattern>
    </servlet-mapping>

这就是我告诉 spring 扫描组件的方式:

    <context:component-scan base-package="com.gim" />

由于某种原因,我的自动装配对象 cobiService 为空。我忘了什么吗?我应该改变什么?

【问题讨论】:

  • servlet 的完全限定名是什么?是在com.gim 包中吗?
  • com.gim.servlets.MyServlet

标签: java spring servlets model-view-controller


【解决方案1】:

Servlet 不由 Spring 管理,它们由 Servlet 容器(如 Tomcat)管理。因此 Spring 不能以正常的 Spring 方式将依赖项注入到 Servlet 中。但是,您可以执行以下操作:

public class MyServlet extends javax.servlet.http.HttpServlet {

    private CobiService cobiService;

    @Override
    public void init() throws ServletException {
        super.init();
        ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
        cobiService = applicationContext.getBean(CobiService.class);
    }

}

【讨论】:

  • 为什么不直接使用ContextAware 接口?
  • 这是个好主意!您应该使用该代码更新您的答案!
  • 我需要更新我的答案以使用 Servlet 容器而不是 Java EE 容器。我只是找不到合适的术语
  • 我想知道如果类不是 Spring bean,Spring 是否真的会调用 setApplicationContext。如果从未尝试过,但我的猜测是不会,因为我怀疑 Spring 会扫描整个类路径以查找实现接口的类
  • 你说得对,两个实例的问题仍然存在。
【解决方案2】:

你可以覆盖你的 servlet init 方法,然后做

SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext (this);

SpringBeanAutowiringSupport

没必要做

implements javax.servlet.Servlet,因为你正在扩展HttpServlet

【讨论】:

    【解决方案3】:

    创建了两个 servlet。一个是由 servlet 容器/Java EE 容器在应用程序初始化并读取 web.xml 文件中配置的 &lt;servlet&gt; 标记时创建的。另一个将在 Spring IOC 容器在初始化时执行其组件扫描时创建。

    在这种情况下,第一个实例无法参与依赖注入,因为它不是在 Spring IOC 容器中创建的。为了参与依赖注入,一个 bean 必须由 Spring IOC 容器管理。当 servlet 容器/Java EE 容器实例化 servlet 时,它不知道 Spring 的 IOC 容器。

    不幸的是,当一个请求满足在 web.xml 文件中为 servlet 指定的 url-pattern 时,该请求被重定向到由 servlet 容器/Java EE 容器创建的第一个实例,该实例不是 bean,并且不适合自动装配。

    如果您要从 web.xml 中删除 servlet 并向 servlet 添加 @RequestMapping 注释,则第二个实例(这是一个能够利用自动装配的实际 bean)将用于填充指定 url 模式的请求@RequestMapping,但是那时你几乎有一个控制器。

    总而言之,我的建议是遵守 Spring 约定并使用控制器类。控制器类将匹配并超过 Servlet 提供的功能。

    【讨论】:

      猜你喜欢
      • 2017-01-28
      • 1970-01-01
      • 1970-01-01
      • 2013-01-29
      • 2017-11-03
      • 2013-10-19
      • 2012-01-19
      • 1970-01-01
      • 2012-08-04
      相关资源
      最近更新 更多