将接口传递给控制器​​构造函数的问题

时间:2019-02-17 16:06:21

标签: spring spring-boot spring-jdbc

我是Spring的新手。以下是我面临的问题。请帮忙。

启动开发工具时,出现以下错误

tacos.web.DesignTacoController中的构造函数的参数0需要一个类型为“ taco.data.IngredientRepository”的bean。

操作:

考虑在您的配置中定义类型为“ taco.data.IngredientRepository”的bean。

IngredientRepository.java

package taco.data;

import tacos.Ingredient;

public interface IngredientRepository {

    Iterable<Ingredient> findAll();

    Ingredient findOne(String id);

    Ingredient save(Ingredient ingredient);

}

JdbcIngredientRepository.java

package taco.data;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import tacos.Ingredient;

@Repository
public class JdbcIngredientRepository implements IngredientRepository {


    private JdbcTemplate jdbc;

    @Autowired
    public JdbcIngredientRepository (JdbcTemplate jdbc) {
        this.jdbc = jdbc;
    }

    @Override
    public Iterable<Ingredient> findAll() {
        return jdbc.query("SELECT ID, NAME, TYPE FROM INGREDIENT", this::mapRowToIngredient);
    }

    @Override
    public Ingredient findOne(String id) {
        return jdbc.queryForObject("SELECT ID, NAME, TYPE FROM INGREDIENT WHERE ID=?", this::mapRowToIngredient, id);
    }

    @Override
    public Ingredient save(Ingredient ingredient) {
        jdbc.update("INSERT INTO INGREDIENT VALUES (?,?,?)", ingredient.getId(), ingredient.getId(), ingredient.getType());
        return ingredient;
    }

    private Ingredient mapRowToIngredient(ResultSet rs, int rowNum)
            throws SQLException {
        return new Ingredient(rs.getString("id"), rs.getString("name"), Ingredient.Type.valueOf(rs.getString("type")));
    }

}

DesignTacoController.java

package tacos.web;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;

import lombok.extern.slf4j.Slf4j;
import taco.data.IngredientRepository;
import tacos.Ingredient;
import tacos.Ingredient.Type;
import tacos.Taco;

@Slf4j
@Controller
@RequestMapping("/design")
@SessionAttributes("order")
public class DesignTacoController {

    private final IngredientRepository ingredientRepo;

    @Autowired
    public DesignTacoController(IngredientRepository ingredientRepo) {
        this.ingredientRepo = ingredientRepo;
    }

    @GetMapping
    public String showDesignForm(Model model) {


        List<Ingredient> ingredients = new ArrayList<>();
        ingredientRepo.findAll().forEach(i -> ingredients.add(i));

        Type[] types = Ingredient.Type.values();
        for (Type type : types) {
            model.addAttribute(type.toString().toLowerCase(),
            filterByType(ingredients, type));
        }
        model.addAttribute("design", new Taco());
        return "design";

    }

    @PostMapping
    public String processDesign(@Valid Taco design, Errors errors) {
        if(errors.hasErrors()) {
            return "design";
        }

        log.info("Processing Design " + design);

        return "redirect:/orders/current";
    }

    public List<Ingredient> filterByType (List<Ingredient> actualList, Type type) {
        return actualList.stream().filter(ingredient -> type.equals(ingredient.getType())).collect(Collectors.toList());
    }
}

SpringBoot引导程序类

package tacos;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
public class TacoCloudApplication {

    public static void main(String[] args) {
        SpringApplication.run(TacoCloudApplication.class, args);
    }

}

Github Project Link

1 个答案:

答案 0 :(得分:1)

问题

TacoCloudApplication看不到在@Component包之外定义的任何@Repository@Componenttacos)。

来自Spring Boot Reference Guide

  

单个@SpringBootApplication注释可用于启用这三个功能,即:

     
      
  • @EnableAutoConfiguration:启用Spring Boot的自动配置机制
  •   
  • @ComponentScan:启用@Component扫描在应用程序所在的程序包上
  •   
  • @Configuration:允许在上下文中注册额外的bean或导入其他配置类
  •   

它只能看到@Component包下面定义的tacos

解决方案

JdbcIngredientRepository移至以tacos开头的软件包。

使您的应用程序结构变为:

└── tacos
    ├── data
    │   ├── IngredientRepository.java
    │   └── JdbcIngredientRepository.java
    ├── Ingredient.java
    ├── Order.java
    ├── TacoCloudApplication.java
    ├── Taco.java
    └── web
    ├── DesignTacoController.java
    ├── OrderController.java
    └── WebConfig.java

或添加

@ComponentScans(
    value = {
        @ComponentScan("tacos"),
        @ComponentScan("taco")
    }
)

转到TacoCloudApplication类。

另请参阅: