Spring DI - REST 服务中的 Autowired 属性为 null

标签 spring dependency-injection nullpointerexception jersey autowired

我正在开始使用 Spring DI,但我正在努力解决依赖注入(inject)问题,更糟糕的是我什至不知道为什么,因为它对我来说似乎没问题。希望你们能帮助我!

问题是注释为 @Autowired 的属性始终为 null

我有一些具有 Maven 结构的项目:

  • com.diegotutor.lessondeliver
  • com.diegotutor.utility

我正在 Tomcat 7 上运行示例

我在我的 pom.xml 中使用以下依赖项:

  • spring-context 3.2.4
  • spring-web 3.2.4
  • Jersey 服务器 1.17.1
  • Jersey 核心1.17.1
  • Jersey servlet 1.17.1

简单的想法是拥有一个 RESTful 服务,通过依赖注入(inject)能够打印出位于以下位置的配置文件中的属性值:D:\configuracion.conf。

com.diegotutor.utility 我有以下界面:

package com.diegotutor.utility;

public interface ConfigService {

    public String getProperty(final String propertyName);
}

实现者:

package com.diegotutor.utility.impl;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.Properties;

import com.diegotutor.utility.ConfigService;

public class PropertyFileConfigService implements ConfigService{

Properties prop;

public PropertyFileConfigService (final InputStream input) throws IOException {
    if(input == null) {
        throw new IllegalArgumentException("Input stream can't be null");
    }
    prop = new Properties();
    prop.load(input);
}

public PropertyFileConfigService (final String fileName) throws IOException {
    final FileInputStream input = new FileInputStream(fileName);
    prop = new Properties();
    prop.load(input);
}

public PropertyFileConfigService(final Reader input) throws IOException {
    prop = new Properties();
    prop.load(input);
}

public String getProperty(final String propertyName) {
    return prop.getProperty(propertyName);
}

}

com.diegotutor.lessondeliver 我有 RESTful 服务,我想在其中使用 ConfigService 的注入(inject)实例:

package com.diegotutor.lessondeliver;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.diegotutor.utility.ConfigService;

@Path("/")
@Component
public class HelloWorld {

private static final Log log = LogFactory.getLog(HelloWorld.class);

@Autowired
private ConfigService configService;

@Path("/helloworld")
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getHello() {
    String host = configService.getProperty("host");
    return "Hello World! HOST" + host;
            // configService IS NULL!! 
            //SO IT THROWS A NULLPOINTER EXCEPTION WHEN INVOKING getProperty ON IT
}
}

最后在 /com.diegotutor.lessondeliver/src/main/webapp/WEB-INF/service-beans.xml 我有以下 XML 应用程序上下文文件,我在其中使用 ConfigService (PropertyFileConfigService) 注入(inject)配置文件读取的路径:

<?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans.xsd
   http://www.springframework.org/schema/context
   http://www.springframework.org/schema/context/spring-context.xsd">

<bean id="configService" class="com.diegotutor.utility.impl.PropertyFileConfigService">
    <constructor-arg type="java.lang.String"
        value="D:\configuracion.conf" />
</bean>

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

</beans>

显然,我已在此 com.diegotutor.lessondeliver Web 应用程序的 web.xml 中指定了我想要的 service-beans.xml 作为 ConfigLocation 和监听器 ContextLoaderListener,RESTful 服务依赖于 ServletContainer

如果我按照建议指定 context:component-scan 在 com.diegotutor 中查找组件 here我通过 Spring 强制创建对象,不使用建议的任何新语句 here , 为什么我将带注释的 configService 设为 null?为什么 Spring 无法注入(inject) com.diegotutor.utility.impl.PropertyFileConfigService 的实例?

任何帮助将不胜感激!

谢谢

编辑:

根据要求,我的web.xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns="http://java.sun.com/xml/ns/javaee" 
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee     http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
id="WebApp_ID" version="3.0">

 <display-name>com.diegotutor.lessondeliver</display-name>

 <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/service-beans.xml</param-value>
 </context-param>

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

 <servlet>
  <servlet-name>jersey-servlet</servlet-name>
  <servlet-class>
         com.sun.jersey.spi.container.servlet.ServletContainer
  </servlet-class>
  <load-on-startup>1</load-on-startup>
 </servlet>

 <servlet-mapping>
  <servlet-name>jersey-servlet</servlet-name>
  <url-pattern>/rest/*</url-pattern>
 </servlet-mapping>
</web-app>

最佳答案

你说得对! 看来问题是 Jersey 完全不知道 Spring 并实例化了自己的对象。为了让 Jersey 知道 Spring 对象创建(通过依赖注入(inject)),我必须集成 Spring + Jersey。

整合:

  1. 添加maven依赖

    <dependency>
        <groupId>com.sun.jersey.contribs</groupId>
        <artifactId>jersey-spring</artifactId>
        <version>1.17.1</version>
        <exclusions>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring-web</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    
  2. web.xml 中使用 SpringServlet 作为 jersey-servlet

    <servlet>
        <servlet-name>jersey-servlet</servlet-name>
        <servlet-class>
            com.sun.jersey.spi.spring.container.servlet.SpringServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    

现在@Autowired 可以正常工作并且对象不再为空。

我对使用 jersey-spring 依赖项时必须在 Maven 中使用的排除有点困惑,但这是另一个问题:)

谢谢!

关于Spring DI - REST 服务中的 Autowired 属性为 null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59713148/

相关文章:

java - 准备好的语句似乎在 java servlet 中总是返回 null

java - JS、CSS、Images等公共(public)资源放在哪里?

scala - 关于蛋糕图案的问题

java - 无法从 Java 文本文件中读取信息并对其进行排序

c# - 如何在 C# 类库中使用 Ninject

Php,依赖注入(inject) - 杀死静态方法,但不需要 instatize

java - RecyclerView.onMeasure(...) 的空指针异常

java - Spring Boot CORS设置: CrossOrigin annotation works addCorsMappings doesn't

java - JAX-WS 网络服务 : Beans not injected : NullPointerException

java - 使用 Spring Batch 读取 XML 并写入数据库