5

我已经搜索并尝试了所有我能想到的解决此问题的方法,但 TestService 类中的 Dao 始终为空。我看到 Spring 日志显示注入了 Dao 以及 TestService 类。我曾尝试在 WTP 下运行 Eclipse 以及直接在 Tomcat 中运行。两者都会导致相同的错误。任何人都可以帮助破译导致 TestService 类中 Dao 为空的错误在哪里。

版本:

Jersey 1.8
Spring 3.0.5Release
Tomcat apache-tomcat-7.0.27 
Maven  3.0.3 (r1075438; 2011-02-28 12:31:09-0500)
Java 1.6.0_31

Eclipse Java EE IDE for Web Developers. 
Version: Indigo Service Release 2
Build id: 20120216-1857 

记录 - 显示正在发生的注入(为简洁起见,切断 DEBUG 和 ClassNames)

 Creating shared instance of singleton bean 'dataSource' 
 Creating instance of bean 'dataSource' 
 Eagerly caching bean 'dataSource' to allow for resolving potential circular references 
 Finished creating instance of bean 'dataSource' 
 Creating shared instance of singleton bean 'jdbcTemplate' 
 Creating instance of bean 'jdbcTemplate' 
 Eagerly caching bean 'jdbcTemplate' to allow for resolving potential circular references 
 Returning cached instance of singleton bean 'dataSource' 
 Invoking afterPropertiesSet() on bean with name 'jdbcTemplate' 
 Finished creating instance of bean 'jdbcTemplate' 
 Creating shared instance of singleton bean 'testClassDao' 
 Creating instance of bean 'testClassDao' 
Found injected element on class [test.dao.TestClassDao]: AutowiredMethodElement for public void test.dao.TestClassDao.setDataSource(javax.sql.DataSource) 
 Eagerly caching bean 'testClassDao' to allow for resolving potential circular references 
Processing injected method of bean 'testClassDao': AutowiredMethodElement for public void test.dao.TestClassDao.setDataSource(javax.sql.DataSource) 
 Returning cached instance of singleton bean 'dataSource' 
 Autowiring by type from bean name 'testClassDao' to bean named 'dataSource' 
 Finished creating instance of bean 'testClassDao' 
 Creating shared instance of singleton bean 'testService' 
 Creating instance of bean 'testService' 
Found injected element on class [test.service.admin.TestService]: AutowiredFieldElement for test.dao.TestClassDao test.service.admin.TestService.dao 
 Eagerly caching bean 'testService' to allow for resolving potential circular references 
Processing injected method of bean 'testService': AutowiredFieldElement for test.dao.TestClassDao test.service.admin.TestService.dao 
 Returning cached instance of singleton bean 'testClassDao' 
Autowiring by type from bean name 'testService' to bean named 'testClassDao' 
 Finished creating instance of bean 'testService' 

错误 - TestService.java 中出现空指针异常,因为 TestClassDao 为空

Apr 25, 2012 9:07:04 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [jersey] in context with path [/test-service]     threw exception
java.lang.NullPointerException
at test.service.admin.TestService.createCompanyProfile(TestService.java:35)

TestClassDao.java

package test.dao;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;

import test.domain.TestClass;

@Repository
public class TestClassDao {

    private NamedParameterJdbcTemplate namedParamJdbcTemplate;
    private DataSource dataSource;


    @Autowired 
    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
        this.namedParamJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
    }

    public void insertTestClass(TestClass testClass)
    {       
        String query = "INSERT INTO TEST_CLASS_TABLE(NAME) VALUES (:NAME)";

        MapSqlParameterSource namedParams = new MapSqlParameterSource();

        mapParams(namedParams, testClass);

        namedParamJdbcTemplate.update(query, namedParams);
    }




    private void mapParams(MapSqlParameterSource  namedParams, TestClass testClass)
    {

            namedParams.addValue("NAME", testClass.getName());

    }
}

测试类.java

 package test.domain;
 import java.util.Date;
 import java.util.HashSet;
 import java.util.Set;

public class TestClass  implements java.io.Serializable {
    private String name;

    public TestClass(String name){
        this.name = name;

    }

    public String getName() {
        return this.name;
    }
}

测试服务.java

package test.service.admin;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.UriInfo;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import test.dao.TestClassDao;
import test.domain.TestClass;

@Path("/resttest")
@Component
public class TestService {
    @Context
    UriInfo uriInfo;
    @Context
    Request request;
    @Autowired 
    TestClassDao dao;

    static Logger log = Logger.getLogger(TestService.class);

    @GET
    @Path("/test")
    public String createCompanyProfile() {

        TestClass test = new TestClass("MyTestName");

        dao.insertTestClass(test);

        return "test done";
    }
}

应用程序上下文.xml

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

    <context:annotation-config />

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:1234/testClassDatabase" />
        <property name="username" value="user" />
        <property name="password" value="password" />
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource">
            <ref bean="dataSource" />
        </property>
    </bean>
    <context:component-scan base-package="test"/>
</beans>

web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>
    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

    <servlet>
        <servlet-name>jersey</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-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>  
</web-app>

更新:为网络应用添加了这个,但它没有改变任何东西

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

pom.xml - 我认为问题可能出在哪里,依赖关系或其他东西

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>test-service</groupId>
    <artifactId>test-service</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>Test Service</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <!-- Jersey -->
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.19</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-server</artifactId>
            <version>${jersey.version}</version>
        </dependency>

        <!-- Spring 3 dependencies -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>

        <!-- Jersey + Spring -->
        <dependency>
            <groupId>com.sun.jersey.contribs</groupId>
            <artifactId>jersey-spring</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>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.8.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.16</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>test-service</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <properties>
        <org.springframework.version>3.0.5.RELEASE</org.springframework.version>
        <jersey.version>1.8</jersey.version>
    </properties>
</project>

更新已修复:我的朋友看了看,发现我没有为 com.sun.jersey.config.property.packages 设置参数,一旦我们添加了它,一切都会自动运行。

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:server-context.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>
    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

    <servlet>
        <servlet-name>jersey-serlvet</servlet-name>
        <servlet-class>
            com.sun.jersey.spi.spring.container.servlet.SpringServlet
        </servlet-class>
        <init-param>
            <param-name>
                                 com.sun.jersey.config.property.packages
                        </param-name>
            <param-value>service</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

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

2 回答 2

7

Spring 正在使用 DAO 注入TestService实例,但该实例不是请求所要发送的实例。您正在使用 Jersey 的ServletContainer来托管您的 Jersey 应用程序,它不会以任何方式与 Spring 集成。它将根据需要自行创建实例,这显然不会由 Spring 注入(无论如何都不会进行一些字节码编织)。我建议使用SpringServlet,它是一个 ServletContainer ,它知道如何从 Spring 上下文中获取资源类。那会解决你的问题。

于 2012-04-26T03:51:07.277 回答
0

正如 Ryan 指出的那样 - 您的ServletContainerservlet 不了解 Spring 容器,因此您的@Resource/@Autowired永远不会注入依赖项。

改用SpringServlet,要么将其添加到 web.xml`,要么将其添加到 Spring WebInitializer 中,而不是两者兼而有之。请参阅下面的示例。

这是代码示例web.xml

<servlet>
    <servlet-name>jersey-spring</servlet-name>
    <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>jersey-spring</servlet-name>
    <url-pattern>/resources/*</url-pattern>
    <load-on-startup>1</load-on-startup>
    <init-param>
        <param-name>com.sun.jersey.config.property.packages</param-name>
        <param-value>phonebook.rest</param-value>
    </init-param>
</servlet-mapping>

这是您自定义的代码示例WebInitializer

public class PhonebookApplicationWebInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) throws ServletException {

        AnnotationConfigWebApplicationContext factory = new AnnotationConfigWebApplicationContext();
        // factory.scan("phonebook.configuration");
        factory.register(PhonebookConfiguration.class);

        ServletRegistration.Dynamic dispatcher = container.addServlet("jersey-spring", new SpringServlet());
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/resources/*");
        dispatcher.setInitParameter("com.sun.jersey.config.property.packages", "phonebook.rest");

        container.addListener(new ContextLoaderListener(factory));

    }

}

你可以在这里看到一些关于 Spring+Jersey 集成的好例子: http ://www.mkyong.com/webservices/jax-rs/jersey-spring-integration-example/

于 2014-04-12T02:08:18.613 回答