我是春天mvc的新人,我正在读一本名为spring-mvc-beginners-guide的书。但是项目中存在一些错误,我无法继续。
This is a photo of the project structure
DispatcherServletInitializer.java
package com.packt.webstore.config;
@Configuration
@EnableWebMvc
@ComponentScan("com.packt.webstore")
public class WebApplicationContextConfig extends WebMvcConfigurerAdapter {
@Override
public void configureDefaultServletHandling (DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Bean
public InternalResourceViewResolver getInternalResourceViewResolver() {
InternalResourceViewResolver resolver = new
InternalResourceViewResolver();
resolver.setViewClass(JstlView.class);
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
}
RootApplicationContextConfig.java
package com.packt.webstore.config;
@Configuration
@ComponentScan("com.packt.webstore.controller")
public class RootApplicationContextConfig {
@Bean
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
EmbeddedDatabase db = builder.setType(EmbeddedDatabaseType.HSQL).addScript("db/sql/create-table.sql")
.addScript("db/sql/insert-data.sql").build();
return db;
}
@Bean
public NamedParameterJdbcTemplate getJdbcTemplate() {
return new NamedParameterJdbcTemplate(dataSource());
}
}
WebApplicationContextConfig.java
package com.packt.webstore.config;
@Configuration
@EnableWebMvc
@ComponentScan("com.packt.webstore")
public class WebApplicationContextConfig extends WebMvcConfigurerAdapter {
@Override
public void configureDefaultServletHandling (DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Bean
public InternalResourceViewResolver getInternalResourceViewResolver() {
InternalResourceViewResolver resolver = new
InternalResourceViewResolver();
resolver.setViewClass(JstlView.class);
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
}
HomeController.java
package com.packt.webstore.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HomeController {
@RequestMapping("/")
public String welcome(Model model) {
model.addAttribute("greeting", "Welcome to Web Store!");
model.addAttribute("tagline", "The one and only amazing web store");
return "welcome";
}
}
ProductController.java
package com.packt.webstore.controller;
@Controller
public class ProductController {
@Autowired
private ProductRepository productRepository;
@RequestMapping("/products")
public String list(Model model) {
model.addAttribute("products", productRepository.getAllProducts());
return "products";
}
}
Product.java
package com.packt.webstore.domain;
import java.io.Serializable;
import java.math.BigDecimal;
public class Product implements Serializable {
private static final long serialVersionUID = 3678107792576131001L;
private String productId;
private String name;
private BigDecimal unitPrice;
private String description;
private String manufacturer;
private String category;
private long unitsInStock;
private long unitsInOrder;
private boolean discontinued;
private String condition;
public Product() {
super();
}
public Product(String productId, String name, BigDecimal unitPrice) {
this.productId = productId;
this.name = name;
this.unitPrice = unitPrice;
}
// Here i deleted getters and setter for compact code
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Product other = (Product) obj;
if (productId == null) {
if (other.productId != null)
return false;
} else if (!productId.equals(other.productId))
return false;
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((productId == null) ? 0 : productId.hashCode());
return result;
}
}
ProductRepository.java
package com.packt.webstore.domain.repository;
@ComponentScan
public interface ProductRepository {
List<Product> getAllProducts();
}
InMemoryProductRepository.java
package com.packt.webstore.domain.repository.impl;
@Repository
public class InMemoryProductRepository implements ProductRepository {
@Autowired
private NamedParameterJdbcTemplate jdbcTemplate;
@Override
public List<Product> getAllProducts() {
Map<String, Object> params = new HashMap<String, Object>();
List<Product> result = jdbcTemplate.query("SELECT * FROM products", params, new ProductMapper());
return result;
}
private static final class ProductMapper implements RowMapper<Product> {
public Product mapRow(ResultSet rs, int rowNum) throws SQLException {
Product product = new Product();
product.setProductId(rs.getString("ID"));
product.setName(rs.getString("NAME"));
product.setDescription(rs.getString("DESCRIPTION"));
product.setUnitPrice(rs.getBigDecimal("UNIT_PRICE"));
product.setManufacturer(rs.getString("MANUFACTURER"));
product.setCategory(rs.getString("CATEGORY"));
product.setCondition(rs.getString("CONDITION"));
product.setUnitsInStock(rs.getLong("UNITS_IN_STOCK"));
product.setUnitsInOrder(rs.getLong("UNITS_IN_ORDER"));
product.setDiscontinued(rs.getBoolean("DISCONTINUED"));
return product;
}
}
}
的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">
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
<modelVersion>4.0.0</modelVersion>
<groupId>com.packt</groupId>
<artifactId>webstore</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.0.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>4.0.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-ldap</artifactId>
<version>4.0.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.3.2</version>
</dependency>
</dependencies>
</project>
和stacktrace
GRAVE: Context initialization failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'productController': Unsatisfied dependency expressed through field 'productRepository': No qualifying bean of type [com.packt.webstore.domain.repository.ProductRepository] found for dependency [com.packt.webstore.domain.repository.ProductRepository]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.packt.webstore.domain.repository.ProductRepository] found for dependency [com.packt.webstore.domain.repository.ProductRepository]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:573)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:350)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:775)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:861)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:444)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:326)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4743)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5207)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1419)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.packt.webstore.domain.repository.ProductRepository] found for dependency [com.packt.webstore.domain.repository.ProductRepository]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1398)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1051)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1018)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:570)
... 24 more
ago 11, 2017 8:32:51 AM org.apache.catalina.core.StandardContext listenerStart
GRAVE: Excepción enviando evento inicializado de contexto a instancia de escuchador de clase [org.springframework.web.context.ContextLoaderListener]
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'productController': Unsatisfied dependency expressed through field 'productRepository': No qualifying bean of type [com.packt.webstore.domain.repository.ProductRepository] found for dependency [com.packt.webstore.domain.repository.ProductRepository]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.packt.webstore.domain.repository.ProductRepository] found for dependency [com.packt.webstore.domain.repository.ProductRepository]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:573)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:350)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:775)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:861)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:444)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:326)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4743)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5207)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1419)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.packt.webstore.domain.repository.ProductRepository] found for dependency [com.packt.webstore.domain.repository.ProductRepository]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1398)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1051)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1018)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:570)
... 24 more
ago 11, 2017 8:32:51 AM org.apache.catalina.core.StandardContext startInternal
GRAVE: One or more listeners failed to start. Full details will be found in the appropriate container log file
ago 11, 2017 8:32:51 AM org.apache.catalina.core.StandardContext startInternal
GRAVE: Falló en arranque del Contexto [/webstore] debido a errores previos
ago 11, 2017 8:32:51 AM org.apache.catalina.core.ApplicationContext log
INFORMACIÓN: Closing Spring root WebApplicationContext
ago 11, 2017 8:32:51 AM org.apache.coyote.AbstractProtocol start
INFORMACIÓN: Starting ProtocolHandler ["http-nio-8080"]
ago 11, 2017 8:32:51 AM org.apache.coyote.AbstractProtocol start
INFORMACIÓN: Starting ProtocolHandler ["ajp-nio-8009"]
ago 11, 2017 8:32:51 AM org.apache.catalina.startup.Catalina start
INFORMACIÓN: Server startup in 2681 ms
PD:我删除了一个紧凑代码的导入。如果您需要它们或其他任何东西,请告诉我。提前致谢
答案 0 :(得分:1)
将@ComponentScan("com.packt.webstore.controller")
更改为包含InMemoryProductRepository所在的包。
您的扫描无法找到存储库,因为它只扫描控制器包。
答案 1 :(得分:1)
将@ComponentScan替换为来自公共接口ProductRepository
的@Component答案 2 :(得分:0)
我建议选择正确的方式&#39;在学习Spring Boot。 随着旧书和#39;你可能会得到错误的经历,因此会花费太多时间。 Spring拥有非常有用的 guides ,可以帮助您快速启动。例如:
Serving Web Content with Spring MVC
此外,您可以使用Spring MVC和Spring Data JPA检查我的简单example CRUD应用程序。
答案 3 :(得分:0)
应该是:
@Component
public interface ProductRepository {
List<Product> getAllProducts();
}
@ComponentScan
是不同的东西,它会扫描指定的包并在找到任何注释时创建bean。
另请参阅1个好答案here。