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

By simon at 2018-02-28 • 0人收藏 • 54人看过

我正在开始使用Spring DI,但我正在努力解决依赖问题 注射和更糟糕的是,我甚至不知道wh因为它似乎可以 我。希望你们能帮助我! 问题是注释为_ @ Autowired的属性始终是空值 我有几个使用Maven结构的项目:   * com.diegotutor.lessondeliver   * com.diegotutor.utility 我在跑在Tomcat 7上的例子 我在我的pom.xml中使用以下依赖项:   * spring-context 3.2.4   * spring-web 3.2。4   *球衣 - 服务器1.17.1   *运动衫 - 核心1.17.1   * jersey-servlet 1.17.1 简单的想法是有一个RESTful服务粗略的依赖注入 能够打印位于配置文件中的属性的值 在: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.lesson提供我拥有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("host");
    return "Hello World! HOST" + host;
            // configService IS NULL!! 
            //SO IT THROWS A NULLPOINTER EXCEPTION WHEN INVOKING getProperty ON IT
}
}
最后一个t /com.diegotutor.lessondeliver/src/main/webapp/WEB-INF/service-beans.xml我有以下XML应用程序上下文文件, 在那里我使用ConfigService (PropertyFileConfigService)注入的实现它的路径 要读取的配置文件:
<?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>
_显然我在99999999的web.xml中指定了991475网站 应用程序,我想要service-beans.xml作为ConfigLocation和一个监听器 ContextLoaderListener,而RESTful服务依赖于ServletContainer
如果我指定上下文:组件扫描以查找组件 建议使用com.diegotutor [这里](HTTPS:// STAckoverflow.com/questions/17589757/problems-with-autowire- annotation-null),我强制通过Spring不通过Spring创建对象运用 建议任何新的陈述 [这里](https://stackoverflow.com/questions/18091939/autowired-field-get-null), **为什么我获取带注释的configService为空?为什么春天不能 注入com.diegotutor.utility.impl.PropertyFileConfigService的实例? 任何帮助将是亩ch赞赏! 谢谢 编辑: 按照要求,我的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>

5 个回复 | 最后更新于 2018-02-28
2018-02-28   #1

你是对的!看来问题在于泽西完全没有意识到 Spring并实例化它自己的对象。为了让泽西知道 Spring对象创建(通过依赖注入)我必须整合 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作为平台服务器
<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>
现在@Autowir编辑正常工作,并且该对象不再为空。 我对我在maven中使用的排除有些困惑使用jersey-spring依赖,但这是另一个问题:) 谢谢!

2018-02-28   #2

你是对的!看来问题在于泽西完全没有意识到 Spring并实例化它自己的对象。为了让泽西知道 Spring对象创建(通过依赖注入)我必须整合 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作为平台服务器
<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>
现在@Autowir编辑正常工作,并且该对象不再为空。 我对我在maven中使用的排除有些困惑使用jersey-spring依赖,但这是另一个问题:) 谢谢!

2018-02-28   #3

另一种可能的选择是手动调用球衣中的自动装配 资源:

@Context
private ServletContext servletContext;

@PostConstruct
public void init() {
    SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, servletContext);
}
嗯,你会得到一个“手动自动装配”...

2018-02-28   #4

整合春季* * 2(org.glassfish.*):

Maven

一些依赖可能是不必要的,请检查并清除它事情得到了 加工。

    <properties>
        <jersey.version>2.5</jersey.version>
    </properties>

    <!-- Jersey -->
    <dependency>
        <groupId>org.glassfish.jersey.core</groupId>
        <artifactId>jersey-server</artifactId>
        <version>${jersey.version}</version>
    </dependency>

    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <!-- if your container implements Servlet API older than 3.0, use "jersey-container-servlet-core" -->
        <artifactId>jersey-container-servlet</artifactId>
        <version>${jersey.version}</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.core</groupId>
        <artifactId>jersey-client</artifactId>
        <version>${jersey.version}</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.test-framework.providers</groupId>
        <artifactId>jersey-test-framework-provider-inmemory</artifactId>
        <version>${jersey.version}</version>
    </dependency>

    <!-- Jersey + Spring -->
    <dependency>
        <groupId>org.glassfish.jersey.ext</groupId>
        <artifactId>jersey-spring3</artifactId>
        <version>${jersey.version}</version>
        <exclusions>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring-web</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

web.xml

<servlet>
    <servlet-name>my-rest-service</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>my.package.with.rest.services</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>my-rest-service</servlet-name>
    <url-pattern>/api/*</url-pattern>
</servlet-mapping>

applicationContext.xml

在春季升级期间,我不得不移动它从/main/webapp/WEB-INF/到 /main/resources/([details](https://stackoverflow.com/q/12574877/1192987))。

<?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-2.5.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    <context:annotation-config />
    <context:component-scan base-package="my.package.with.rest.services" />
</beans>

示例REST服务冰

public interface MyService
{
    String work(String s);
}

...

@Service
public class MyServiceImpl implements MyService
{
    @Override
    public String work(String s)
    {
        return "Hello, " + s;
    }
}

...

@Path("demo/")
@Component
public class DemoRestService
{
    @Autowired
    private MyService service;

    @GET
    @Path("test")
    public Response test(@FormParam("param") String par)
    {
        try
        {
            String entity = service.work(par);
            return Response.ok(entity).build();
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Epic REST Failure").build();
        }
    }
}

2018-02-28   #5

或者您可以简单地扩展SpringBeanAutoWiringSupport类。喜欢这个: public class DemoRestService extends SpringBeanAutoWiringSupport.通过扩展此支持类,属性你的服务类 可以自动连线。

登录后方可回帖

Loading...