Spring DI - 自动连接属性在REST服务中为空 [英] Spring DI - Autowired property is null in a REST service

查看:227
本文介绍了Spring DI - 自动连接属性在REST服务中为空的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开始使用Spring DI,但是我正在努力使用依赖注入,更糟糕的是,我甚至不知道为什么对我来说似乎很好。希望你们可以帮助我!



问题是,注释为 @Autowired 的属性始终为 / p>

我有一些项目与Maven结构:




  • com.diegotutor .lessondeliver

  • com.diegotutor.utility



我在Tomcat 7上运行示例



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




  • spring-context 3.2.4

  • spring-web 3.2.4

  • 泽西服务器1.17.1

  • jersey-core 1.17.1

  • jersey-servlet 1.17.1



简单的想法是具有RESTful服务,通过依赖注入可以打印位于位于以下位置的配置文件中的属性的值: D:\\ \\ configuracion.conf。



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

  package com.diegotutor 。效用; 

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实现ConfigService {

属性prop;

public PropertyFileConfigService(final InputStream input)throws IOException {
if(input == null){
throw new IllegalArgumentException(Input stream can not 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输入)throws IOException {
prop = new Properties();
prop.load(input);
}

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

}

而在 com。 diegotutor.lessondeliver 我有RESTful服务,我想使用一个注入的ConfigService实例:

  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( 主机);
返回Hello World!HOST+主机;
// configService IS NULL!
//当它调用getProperty ON IT
}
$


$时,它会影响一个空点b $ b

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

 <?xml version =1.0encoding =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.xsd>

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

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

< / beans>

显然我在 web.xml 这个 com.diegotutor.lessondeliver web应用程序,我想要 service-beans.xml 作为ConfigLocation和一个监听器 ContextLoaderListener ,RESTful服务依赖于ServletContainer



如果我指定上下文:组件扫描在 com.diegotutor 中查找组件,建议这里,我强制通过Spring创建对象,因为不建议使用任何新的语句这里为什么我将注释的configService设为null?为什么Spring无法注入一个的实例com.diegotutor.utility.impl.PropertyFileConfigService



任何帮助将不胜感激!



谢谢



EDITED:



根据要求,我的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_IDversion =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>


解决方案

你是对的!
似乎问题是泽西完全不了解Spring并实例化自己的对象。为了使泽西意识到Spring对象创建(通过依赖注入),我不得不整合Spring + Jersey。



要整合:


  1. 添加maven依赖关系

     < dependency> 
    < groupId> com.sun.jersey.contribs< / groupId>
    < artifactId> jersey-spring< / artifactId>
    < version> 1.17.1< / version>
    <排除>
    < exclude>
    < groupId> org.springframework< / groupId>
    < artifactId> spring-core< / artifactId>
    < / exclusion>
    < exclude>
    < groupId> org.springframework< / groupId>
    < artifactId> spring-beans< / artifactId>
    < / exclusion>
    < exclude>
    < groupId> org.springframework< / groupId>
    < artifactId> spring-context< / artifactId>
    < / exclusion>
    < exclude>
    < groupId> org.springframework< / groupId>
    < artifactId> spring-web< / artifactId>
    < / exclusion>
    < / exclusions>
    < / dependency>




    1. 在web.xml中使用SpringServlet for 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正常工作,对象不再为空。



我对使用maven时的排除项目有一点疑惑这是另一个问题:)



谢谢!


I'm getting started with Spring DI, but I'm struggling with dependency injection and the worse part is that I'm not even sure why as it seems ok to me. Hopefully you guys can help me out!

The problem is that a property annotated as @Autowired is always null

I've got a few projects with Maven structure:

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

I'm running the examples over Tomcat 7

I'm using the following dependencies in my pom.xml:

  • spring-context 3.2.4
  • spring-web 3.2.4
  • jersey-server 1.17.1
  • jersey-core 1.17.1
  • jersey-servlet 1.17.1

The simple idea is to have a RESTful service that through Dependency Injection is able to print out the value of a property located in a config file located at: D:\configuracion.conf.

At com.diegotutor.utility I have the following interface:

package com.diegotutor.utility;

public interface ConfigService {

    public String getProperty(final String propertyName);
}

Implemented by:

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);
}

}

And at com.diegotutor.lessondeliver I have the RESTful service where I would like to use an injected instance of the ConfigService:

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
}
}

Finally at /com.diegotutor.lessondeliver/src/main/webapp/WEB-INF/service-beans.xml I have the following XML application context file, where I use the implementation of ConfigService (PropertyFileConfigService) injecting on it the path for the configuration file to read:

<?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>

Obviously I have specified in the web.xml of this com.diegotutor.lessondeliver web app that I want service-beans.xml as ConfigLocation and a listener ContextLoaderListener, and the RESTful service relies on ServletContainer

If I'm specifying context:component-scan to look for Components in com.diegotutor as suggested here and I'm forcing object creation through Spring by not using any new Statement as suggested here, Why am I getting the annotated configService as null? Why Spring is unable to inject an instance of com.diegotutor.utility.impl.PropertyFileConfigService?

Any help will be much appreciated!

Thank you

EDITED:

As requested, my web.xml is as follows:

<?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>

解决方案

You were right! It seems that the problem is that Jersey is totally unaware of Spring and instantiates its own object. In order to make Jersey aware of Spring object creations (through dependency injection) I had to integrate Spring + Jersey.

To integrate:

  1. Add maven dependencies

    <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>
    

    1. Use SpringServlet for jersey-servlet in web.xml

       <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>
      

Now the @Autowired works properly and the object is not null anymore.

I'm a little bit confused about the exclusions I have to use in maven when using jersey-spring dependency, but that's another issue :)

Thank you!

这篇关于Spring DI - 自动连接属性在REST服务中为空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆