#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. Вот и все 😉