代码之家  ›  专栏  ›  技术社区  ›  kkk12a9

“BookServiceImpl”中的字段“bookRepository”需要一个类型为“bookRepository”的bean,但找不到该bean

  •  0
  • kkk12a9  · 技术社区  · 2 年前

    我是Spring框架的新手,正在尝试创建 Spring-Boot 与…结合 JSP 制作一个小的网络应用。然而,当我运行程序时,我得到以下错误。

    完整堆栈跟踪:

    2022-01-01 15:31:43.790  INFO 20116 --- [  restartedMain] spring.jsp.JspApplication                : Starting JspApplication using Java 11.0.13 on cudayanh with PID 20116 (C:\Users\PC_1\Desktop\java_spring\spring-boot-jsp\jsp\target\classes started by PC_1 in C:\Users\PC_1\desktop\java_spring\spring-boot-jsp\jsp)
    2022-01-01 15:31:43.791  INFO 20116 --- [  restartedMain] spring.jsp.JspApplication                : No active profile set, falling back to default profiles: default
    2022-01-01 15:31:43.916  INFO 20116 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
    2022-01-01 15:31:43.917  INFO 20116 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
    2022-01-01 15:31:47.098  INFO 20116 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
    2022-01-01 15:31:47.112  INFO 20116 --- [  restartedMain] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
    2022-01-01 15:31:47.112  INFO 20116 --- [  restartedMain] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.56]
    2022-01-01 15:31:47.115  WARN 20116 --- [  restartedMain] o.a.catalina.core.AprLifecycleListener   : This listener must only be nested within Server elements, but is in [TomcatEmbeddedContext].
    2022-01-01 15:31:47.115  INFO 20116 --- [  restartedMain] o.a.catalina.core.AprLifecycleListener   : Loaded Apache Tomcat Native library [1.2.31] using APR version [1.7.0].
    2022-01-01 15:31:47.116  INFO 20116 --- [  restartedMain] o.a.catalina.core.AprLifecycleListener   : APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true], UDS [true].
    2022-01-01 15:31:47.116  INFO 20116 --- [  restartedMain] o.a.catalina.core.AprLifecycleListener   : APR/OpenSSL configuration: useAprConnector [false], useOpenSSL [true]
    2022-01-01 15:31:47.123  INFO 20116 --- [  restartedMain] o.a.catalina.core.AprLifecycleListener   : OpenSSL successfully initialized [OpenSSL 1.1.1l  24 Aug 2021]
    2022-01-01 15:31:47.499  INFO 20116 --- [  restartedMain] org.apache.jasper.servlet.TldScanner     : At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
    2022-01-01 15:31:47.515  INFO 20116 --- [  restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
    2022-01-01 15:31:47.515  INFO 20116 --- [  restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 3596 ms
    2022-01-01 15:31:47.623  WARN 20116 --- [  restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'bookController' defined in file [C:\Users\PC_1\Desktop\java_spring\spring-boot-jsp\jsp\target\classes\spring\jsp\controllers\BookController.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'bookServiceImpl': Unsatisfied dependency expressed through field 'bookRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'spring.jsp.repositories.BookRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value="spring.jsp.repositories.BookRepository")}
    2022-01-01 15:31:47.626  INFO 20116 --- [  restartedMain] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
    2022-01-01 15:31:47.653  INFO 20116 --- [  restartedMain] ConditionEvaluationReportLoggingListener :
    
    Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
    2022-01-01 15:31:47.713 ERROR 20116 --- [  restartedMain] o.s.b.d.LoggingFailureAnalysisReporter   :
    
    ***************************
    APPLICATION FAILED TO START
    ***************************
    
    Description:
    
    Field bookRepository in spring.jsp.services.impl.BookServiceImpl required a bean of type 'spring.jsp.repositories.BookRepository' that could not be found.
    
    The following candidates were found but could not be injected:
            - User-defined bean
            - User-defined bean method 'provideBookRepository' in 'JspConfiguration'
    
    Action:
    
    Consider revisiting the entries above or defining a bean of type 'spring.jsp.repositories.BookRepository' in your configuration.
    

    我试图通过引用和使用其他人提供的一系列解决方案来解决这个问题,比如添加 @Service , @Repository 到实现类。然而,它们都不起作用。

    repositories/BookRepository.java

    public interface BookRepository {
    
        Collection<Book> findAll();
    
        Optional<Book> findById(String isbn);
    
        Book add(Book book);
    }
    

    repositories/impl/InMemoBookRepositoryImpl.java

    @Service
    @Primary
    public class InMemoBookRepositoryImpl implements BookRepository {
    
        @Autowired
        private final Map<String, Book> booksStore;
    
        public InMemoBookRepositoryImpl(Map<String, Book> booksStore) {
            this.booksStore = booksStore;
            this.booksStore.putAll(booksStore);
        }
    
        @Override
        public Collection<Book> findAll() {
            if (this.booksStore.isEmpty()) {
                return Collections.emptyList();
            }
    
            return booksStore.values();
        }
    
        @Override
        public Optional<Book> findById(String isbn) {
            return Optional.ofNullable(booksStore.get(isbn));
        }
    
        @Override
        public Book add(Book book) {
            booksStore.put(book.getIsbn(), book);
            return book;
        }
    }
    

    services/BookService.java

    public interface BookService {
    
        Collection<BookDTO> getBooks();
    
        BookDTO addBook(BookDTO book);
    }
    

    services/impl/BookServiceImpl.java

    @Service
    @Primary
    public class BookServiceImpl implements BookService {
    
        @Autowired
        @Qualifier("spring.jsp.repositories.BookRepository")
        private final BookRepository bookRepository;
    
        public BookServiceImpl(BookRepository bookRepository) {
            this.bookRepository = bookRepository;
        }
    
        @Override
        public Collection<BookDTO> getBooks() {
            return bookRepository.findAll()
                    .stream()
                    .map(BookServiceImpl::convertBookDto)
                    .collect(Collectors.toList());
        }
    
        @Override
        public BookDTO addBook(BookDTO bookDto) {
            final Optional<Book> existingBook = bookRepository.findById(bookDto.getIsbn());
            if (existingBook.isPresent()) {
                throw new DuplicateBookException(bookDto);
            }
    
            final Book savedBook = bookRepository.add(convertToBook(bookDto));
            return convertBookDto(savedBook);
        }
    
        private static BookDTO convertBookDto(Book book) {
            return new BookDTO(book.getIsbn(), book.getName(), book.getAuthor());
        }
    
        private static Book convertToBook(BookDTO bookDto) {
            return new Book(bookDto.getIsbn(), bookDto.getName(), bookDto.getAuthor());
        }
    }
    

    controllers/BookController.java

    @Controller
    @RequestMapping("/book")
    public class BookController {
    
        @Autowired
        @Qualifier("spring.jsp.services.bookService")
        private final BookService bookService;
    
        public BookController(BookService bookService) {
            this.bookService = bookService;
        }
    
        @GetMapping("/books")
        public String getBooks(Model model) {
            model.addAttribute("books", this.bookService.getBooks());
            return "booksList";
        }
    
        @GetMapping("/addBook")
        public String addBook(Model model) {
            model.addAttribute("book", new Book());
            return "addBook";
        }
    
        @PostMapping("/addBook")
        public RedirectView addBook(@ModelAttribute("book") BookDTO bookDto, RedirectAttributes redirectAttributes) {
            final RedirectView redirectView = new RedirectView("/book/addBook", true);
            BookDTO savedBook = bookService.addBook(bookDto);
            redirectAttributes.addFlashAttribute("savedBook", savedBook);
            redirectAttributes.addFlashAttribute("addBookSuccess", true);
    
            return redirectView;
        }
    }
    

    主要方法

    @SpringBootApplication(scanBasePackages = "spring.jsp")
    @EntityScan("spring.jsp")
    @ComponentScan({ "spring.jsp" })
    public class JspApplication extends SpringBootServletInitializer {
    
        @Override
        protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
            return builder.sources(JspApplication.class);
        }
    
        public static void main(String[] args) {
            SpringApplication.run(JspApplication.class, args);
        }
    }
    

    最后是 pom.xml 配置

    <?xml version="1.0" encoding="UTF-8"?>
    <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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
         <!-- <packaging>war</packaging> -->
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.6.2</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>spring</groupId>
        <artifactId>jsp</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>jsp</name>
        <description>Demo project for Spring Boot</description>
        <properties>
            <java.version>11</java.version>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <!--  specifies the Tomcat JSP dependency(jsp parser) -->
            <dependency>
                <groupId>org.apache.tomcat.embed</groupId>
                <artifactId>tomcat-embed-jasper</artifactId>
                <scope>provided</scope>
            </dependency>   
    
            <!--  -->
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>jstl</artifactId>
                <scope>provided</scope>
            </dependency>
    
             <!-- JSTL tag lib -->
            <dependency>
                <groupId>javax.servlet.jsp.jstl</groupId>
                <artifactId>javax.servlet.jsp.jstl-api</artifactId>
                <version>1.2.1</version>
            </dependency>
    
            <!--  running in a Tomcat web container. -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
                <version>2.4.4</version>
                <scope>provided</scope>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <scope>runtime</scope>
                <optional>true</optional>
            </dependency>
    
            <!-- lombok -->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.16.18</version>
                <optional>true</optional>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
    
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>3.8.4</version>
                    <configuration>
                        <testFailureIgnore>true</testFailureIgnore>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <configuration>
                        <excludes>
                            <exclude>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok</artifactId>
                            </exclude>
                        </excludes>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    0 回复  |  直到 2 年前
        1
  •  0
  •   João Dias    2 年前

    尝试简化主类,并依赖注释默认值,如下所示:

    @SpringBootApplication
    @EntityScan("spring.jsp")
    public class JspApplication extends SpringBootServletInitializer {
    
        @Override
        protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
            return builder.sources(JspApplication.class);
        }
    
        public static void main(String[] args) {
            SpringApplication.run(JspApplication.class, args);
        }
    }
    

    @SpringBootApplication 封装 @Configuration , @EnableAutoConfiguration @ComponentScan 注释及其默认属性。的默认值 @组件扫描 意味着包上的所有子包 @组件扫描 是用来扫描的。这就是为什么在项目的基本包中包含主类通常是一种好的做法。