简体   繁体   English

如何在Web应用程序中使用Spring自动装配注释

[英]How to use Spring autowire annotation in a web-app

New to Spring, I have rushed into it due to the needs of my project. Spring的新手,由于我的项目需求,我急于加入。 I was successfully able to use most of the features of Spring when using it as a Java application but am not getting the desired results in a web-application. 将Spring用作Java应用程序时,我能够成功使用Spring的大多数功能,但在Web应用程序中未获得预期的结果。

I am trying to initialize my datasource in applicationContext.xml: 我正在尝试在applicationContext.xml中初始化我的数据源:

<context:annotation-config />
<context:component-scan base-package="learn.spring.webapp.dao" />

<bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="org.postgresql.Driver" />
    <property name="url" value="jdbc:postgresql://localhost:5432/postgres" />
    <property name="username" value="postgres" />
    <property name="password" value="postgres" />
</bean>

<bean id="template" class="org.springframework.jdbc.core.JdbcTemplate"
    autowire="constructor" />

web.xml: web.xml中:

 <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>WEB-INF/spring/applicationContext.xml</param-value>
  </context-param>

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

I was successfully able to initialize Spring in my application but fail to autowire jdbctemplate in my dao class. 我可以在应用程序中成功初始化Spring,但是无法在dao类中自动装配jdbctemplate。

package learn.spring.webapp.dao;

import learn.spring.webapp.model.Manga;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

@Component
public class MangaDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    public void insert(Manga manga){
        String sql = "insert into manga_list values (?,?)";
        jdbcTemplate.update(sql,
                new Object[]{manga.getName(), manga.getAuthor()}); //Null Pointer exception
    }
}

I want to autowire the template bean with JdbcTemplate in my dao package. 我想用dao包中的JdbcTemplate自动连接template bean。 I get a NullPointerException when I try to use the JdbcTemplate . 尝试使用JdbcTemplate时出现NullPointerException MangaDao is being called from a servlet. 正在从Servlet调用MangaDao I think I might not be using the autowired annotations correctly. 我想我可能没有正确使用自动装配注释。 Please advice. 请指教。

Edit: 编辑:

The servlet code that calls the DAO is: 调用DAO的servlet代码是:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        MangaDao md=new MangaDao();
        Manga manga=new Manga();
        manga.setName("Bleach");
        manga.setAuthor("Kubo Tite");
        md.insert(manga);
    }

And the stackTrace is as follows: 并且stackTrace如下:

SEVERE: Servlet.service() for servlet TesterServlet threw exception
java.lang.NullPointerException
        at learn.spring.webapp.dao.MangaDao.insert(MangaDao.java:16)
        at learn.spring.webapp.controller.TesterServlet.doGet(TesterServlet.java:33)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
        at java.lang.Thread.run(Thread.java:662)

I suppose code in your servlet is like this: 我想您的servlet中的代码是这样的:

Manga manga = new Manga();
manga.setName(request.getParameter("name"));
manga.setAuthor(request.getParameter("author"));
MangaDao dao = new MangaDao();
dao.insert(manga); // here you get exception;

But autowiring works only if you get bean fron context. 但是,只有在获得bean fron上下文的情况下,自动装配才有效。

MangaDao dao = appContext.getBean(MangaDao.class);
dao.insert(manga); // should be ok;

So where you can get appContext. 因此,您可以在哪里获得appContext。 You should load it from file and store for furure use. 您应该从文件中加载它并存储以备将来使用。 ContextLoaderListener does part of this job for you. ContextLoaderListener为您完成了这项工作。 Then you mere store it in static variable, for example: 然后,您只需将其存储在静态变量中,例如:

@Component
public class AppContext implements ApplicationContextAware {
    private static MangaDao mangaDao = null;
    public static MangaDao getMangaDao() {
        if(mangaDao == null){
            throw new ApplicationContextException("context not initialized");
        }
        return mangaDao;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        mangaDao = applicationContext.getBean(MangaDao.class);
    }
}

Make sure class AppContext goes in package, defined with context:component-scan , it will learn.spring.webapp.dao in your case 确保将AppContext类放入由context:component-scan定义的包中,在您的情况下它将为learn.spring.webapp.dao

And i strongly suggest you to use transactions. 我强烈建议您使用交易。

To answer your updated post: 要回答您更新的帖子:

You have to use the bean you created in your context rather than creating a new instance. 您必须使用在上下文中创建的bean,而不是创建新实例。 Try autowiring your new component and then using that rather than creating a new one in your controller. 尝试自动装配新组件,然后使用它,而不要在控制器中创建一个新组件。

@Autowired MangaDao mangaDao;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    Manga manga=new Manga();
    manga.setName("Bleach");
    manga.setAuthor("Kubo Tite");
    mangaDao.insert(manga);
}

In answer to your original post: 在回答您的原始帖子时:

Looks like you are just missing the right package name in your component scan. 看起来您在组件扫描中只是缺少正确的软件包名称。 Your @Component annotated class is in the learn.spring.webapp.model package and your scan isn't reaching it. 您带@Component注释的类位于learning.spring.webapp.model包中,而您的扫描未到达该类。 Try using a more generic package in the annotation-scan: 尝试在注解扫描中使用更通用的软件包:

<context:component-scan base-package="learn.spring.webapp" />

I would recommend using spring-mvc rather than raw Servlets. 我建议使用spring-mvc而不是原始Servlet。

With spring-mvc you define Controllers instead of Servlets. 使用spring-mvc您可以定义控制器而不是Servlet。 Based on your code a Spring Controller may look something like this: 根据您的代码,Spring Controller可能看起来像这样:

@Controller 
public class MangaController {

    @Autowired
    private MangaDao dao;

    @RequestMapping(value = "/manga/insert", method = RequestMethod.GET)
    public void doGet() {
        Manga manga = new Manga();
        manga.setName("Bleach");
        manga.setAuthor("Kubo Tite");
        dao.insert(manga);
    }
}

Because the Controller is managed by Spring all required dependencies will be injected and ready for use by your code - eliminating the NullPointerException . 由于Controller是由Spring管理的,因此所有必需的依赖项都将被注入并准备好供您的代码使用-消除了NullPointerException

Within your applicationContext.xml , you'd have to include the controller package in the component-scan and also enable the mvc features: applicationContext.xml ,您必须在component-scan中包括控制器包,还必须启用mvc功能:

<mvc:annotation-driven />

I strongly recommend reading this article on getting started with spring-mvc . 我强烈建议您阅读有关spring-mvc入门的文章 It covers all the required steps along with the Spring dependencies you need. 它涵盖了所有必需的步骤以及所需的Spring依赖项。

I'd also recommend taking a look through the Spring Reference documentation , as you'll see, it's very comprehensive! 我还将建议您仔细阅读Spring Reference文档 ,您会发现它非常全面!

I had got same "null" exception until I user "SpringBeanAutowiringSupport" abstract class. 在使用“ SpringBeanAutowiringSupport”抽象类之前,我有同样的“空”异常。 You should extand the class with this abstract class like that: 您应该使用以下抽象类扩展该类:

public class SomeClass extends SpringBeanAutowiringSupport {}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM