Исключение неудовлетворенной зависимости Spitter Spring MVC

#java #spring #spring-mvc #action

#java #spring #spring-mvc #Экшен

Вопрос:

Я начинаю с Spring MVC с книги Spring in Action, я выполняю упражнение главы 5 с приложением Spitter, но я получил следующую ошибку:

org.springframework.beans.factory.Исключение UnsatisfiedDependencyException: ошибка при создании компонента с именем ‘spittleController’, определенным в файле [C:xampphtdocs.metadata.pluginsorg.eclipse.wst.server.coretmp1wtpwebappsspitterWEB-INFclassescomspitterwebSpittleController.class] : Неудовлетворенная зависимость, выраженная через аргумент конструктора с индексом 0 типа [com.spitter.data.SpittleRepository]: : Для зависимости не найден соответствующий компонент типа [com.spitter.data.SpittleRepository]: ожидается, что по крайней мере 1 компонент, который квалифицируется как кандидат на автоматическое подключение к этой зависимости. Примечания к зависимостям: {}; вложенным исключением является org.springframework.beans.factory.Исключение NoSuchBeanDefinitionException: для зависимости не найден соответствующий компонент типа [com.spitter.data.SpittleRepository]: ожидается, что по крайней мере 1 компонент, который квалифицируется как кандидат на автоматическое подключение к этой зависимости. Аннотации к зависимостям: {}

Я получил проект здесь, в github:https://github.com/kevingcfcb88/spitter.git

Я уже провожу свое исследование, но, похоже, ничего не работает.

Я использую STS и Maven, это структура приложения:

Структура проекта

Вот мой 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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.spitter.config</groupId>
<artifactId>spitter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>

<name>spitter</name>
<url>http://maven.apache.org</url>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <springframework.version>4.1.5.RELEASE</springframework.version>
</properties>

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>3.8.1</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${springframework.version}</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>javax.servlet.jsp-api</artifactId>          
        <version>2.3.1</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.0</version>
    </dependency>

</dependencies>

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.2</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <warSourceDirectory>src/main/webapp</warSourceDirectory>
                    <warName>spitter</warName>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>
    <finalName>spitter</finalName>
</build>
  

И мои конфигурационные файлы:

SpittrWebAppInitializer.java

  package com.spitter.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] { RootConfig.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] { WebConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }

}
  

WebConfig.java

 package com.spitter.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@EnableWebMvc
@ComponentScan("com.spitter.web")
public class WebConfig extends WebMvcConfigurerAdapter {

    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        resolver.setExposeContextBeansAsAttributes(true);
        return resolver;
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

}
  

RootConfig.java

 package com.spitter.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@Configuration
@ComponentScan(basePackages = { "com.spitter.data" }, excludeFilters = {@Filter(type = FilterType.ANNOTATION, value = EnableWebMvc.class) })
public class RootConfig {

}
  

Комментарии:

1. SplitterRepository — это интерфейс, а не компонент Spring. Итак, ничего нет. Может быть, это должно быть связано с spring-data-jpa?

2. Точно такой же интерфейс, но так, как это сделано в книге.

3. Три варианта: 1. Книга неверна; 2. Ваша интерпретация книги неверна; 3. Код не должен выполняться на данном этапе

4. @mh-dev вы правы. Это должно быть jpa, но в этом коде отсутствуют некоторые другие классы.

Ответ №1:

Как объяснил @mh-dev, вам нужна реализация SpittleRepository . Попробуйте добавить этот класс и посмотрите, может ли ваш код выполняться:

 public class SpittleRepositoryImpl implements SpittleRepository {

  List <Spittle> findSpittles(long max, int count) {
    System.out.println("I need a real implementation! " 
        "I received max as "   max   " and count as "   count   ".");
  }

}
  

Я бы посоветовал перечитать соответствующие разделы книги, чтобы убедиться, что вы ничего не пропустили.

Комментарии:

1. Ничего, это не решит мою проблему, но спасибо. Я уже 10 раз проверил всю главу, и я ничего не нашел о внедрении этого интерфейса.

2. Вы были правы. В книге отсутствуют ее реализации, я использую тот же метод, что и тест для ее реализации.

Ответ №2:

Вам просто нужно добавить реализацию репозитория SpittleRepository с @Repository в заголовке, потому что, хотя вы добавили классы реализации, spring IOC не знает о фактической зависимости, и пример в книге должен был сработать, если бы вы поместили все файлы Java в одну иерархию пакетов с реализацией репозитория.

 @Repository
public class SpittleRepositoryDAO implements SpittleRepository {

    public SpittleRepositoryDAO() {

    }

    @Override
    public List<Spittle> findSpittles(long max, int count) {
        List<Spittle> spittles = new ArrayList<Spittle>();
        for (int i = 0; i < count; i  ) {
            spittles.add(new Spittle("Spittle "   i, new Date()));
        }
        return spittles;
    }
}
  

Ответ №3:

Я знаю этот код. Раньше это вызывало у меня серьезную головную боль 2 года назад. Ошибка в коде Или в его главе.

Перейдите на сайт издателей и загрузите обновленный исходный код. здесь

или

https://www.manning.com/books/spring-in-action-fourth-edition

Комментарии:

1. Это решает мою проблему, спасибо; но почему мой код не работает?

2. Я думаю, это потому, что интерфейс spitterrepository должен расширять Spring Jparepository. Если этого не произойдет, Spring отклонит его, потому что он не рассматривает его как компонент. извините за мой английский.

3. Интерфейс в примере точно такой же, как у меня, и ни один из них не распространяется ни на один класс

4. Тогда все наоборот. SpitterRepository реализуется JdbcSpitterRepository точно так же, как продемонстрировал @Adam Rosini (см. Ответ ниже).

Ответ №4:

Вот реализация репозитория:

 package com.spitter.web;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.spitter.data.SpittleRepository;

@Controller
@RequestMapping("/spittles")
public class SpittleController {

    private SpittleRepository spittleRepository;

    @Autowired
    public SpittleController(SpittleRepository spittleRepository) {
        this.spittleRepository = spittleRepository;
    }

    @RequestMapping(method = RequestMethod.GET)
    public String spittles(Model model) {
        model.addAttribute("spittleList", spittleRepository.findSpittles(Long.MAX_VALUE, 20));
        return "spittles";
    }

}
  

Ответ №5:

да, проблема в том, что вам нужна реализация SpittleRepository. Потому что вы не можете иметь интерфейс как компонент, вы знаете. Компоненту сканирования требуется хотя бы одна его реализация и с аннотацией @Component. Вот и все 😉