spring - 内存和数据库服务调用是否应该在 (MVC)Controller 中完成?
问题描述
我的功能问题包括一些小细节,例如:
Recipe newRecipe = new Recipe()
newRecipe.setThing1(fromViewRecipe.getSubmittedData())
.
.
.
Recipe savedRecipe = recipeService.saveToDb(...)
recipeService.addRecipeToArrayList(savedRecipe);
是需要处理大量的细节和重复代码。但是我见过的每个教程都让人们用这些细节丰富的东西来加载他们的控制器。
完全删除这些东西并保留在您的服务层中不是最好的吗?
我是否正确遵循 MVC?
控制器
@GetMapping(Mappings.HOME)
public String getHomeView(Model model) { // Took out params and attribs since they dont exist in the model
// until the controller creates them
log.info("Inside getMainView");
Recipe recipe = svc.initNewRecipe(); // Create and initialize a new recipe
model.addAttribute(AttributeNames.RECIPE, recipe);
model.addAttribute(AttributeNames.RECIPE_ID, recipe.getRecipeId()); // should I put 0 here or what LOL
model.addAttribute(AttributeNames.RECIPE_NAME, recipe.getRecipeName()); // "" ?
model.addAttribute(AttributeNames.RECIPE_DATA, recipeData());
log.info("recipe ingredient list size: {}", recipe.getIngredientList().size());
//model.addAttribute(AttributeNames.INGREDIENT_LIST, recipe.getIngredientList());
return ViewNames.HOME;
}
服务
@Slf4j
@Service
public class RecipeServiceImpl implements RecipeService{
@Value("${id.length}")
private int idLength;
@Autowired
private RecipeRepository recipeRepository;
@Autowired
IDManager idManager;
@Autowired
List<Recipe> inMemRecipeList = new ArrayList<>(); // In-memory list of recipes
// Get all Recipes from DB and return ArrayList of Recipes
@Override
public List<Recipe> getAllRecipes() {
// Retrieve recipes from DB and add to In-memory list
for(RecipeEntity recipeDbEntity : recipeRepository.findAll()){
Recipe recipe = new Recipe();
BeanUtils.copyProperties(recipeDbEntity, recipe);
inMemRecipeList.add(recipe);
}
log.info("Returning list from getAllRecipes : {}", inMemRecipeList);
return inMemRecipeList;
}
@Override
public Recipe addRecipeToInMemList(Recipe newRecipe){
getAllRecipes().add(newRecipe); // Add to in memory list
}
// Save a recipe and log
@Override
public RecipeEntity addRecipeToDb(RecipeEntity recipeToSave) {
log.info("Saved recipe with ID: " + savedRecipe.getRecipeId());
return recipeRepository.save(recipeToSave);
}
// == Create new blank Recipe, save to DB and memory and return ==
public Recipe initNewRecipe(){
// Create a new recipe
Recipe newRecipe = new Recipe();
// Create a list for the ingredients,
// add a blank ingredient FOR TESTING to the list
// attach the list to the Recipe
List<Ingredient> ingredientList = new ArrayList<>();
Ingredient blankIngredient = new Ingredient(
0,
0.0,
Unit.CUPS,
""
);
ingredientList.add(blankIngredient);
newRecipe.setIngredientList(ingredientList);
// Save it to DB and return the result
RecipeEntity newRecipeEntity = new RecipeEntity();
BeanUtils.copyProperties(newRecipe, newRecipeEntity);
Recipe returnableRecipe = new Recipe();
addRecipeToInMemList(BeanUtils.copyProperties(addRecipeToDb(newRecipeEntity), returnableRecipe);
return newRecipe;
}
.
.
.
解决方案
In my opinion, yes controller should only have code that is responsible for rendering of view. Any logic or calculations should go to service layer.
One clear benefit of having this separation is when you move out your legacy implementation and starts providing APIs to new js frameworks or other clients, your service layer will still be valid. All you will be required to create is RESTController.
As per Wikipedia, this pattern is designed for code reusability and parallel development. So before creating java classes one must consider separation of concerns, single responsibility and KISS principles. These principles advice to make your classes or method simple and fulfiling only a single responsibility.
This Microsoft Document (though not for Java) indicates what your controller should be.
Service layer in my opinion is part of model. Regarding your question about correct implementation, I suggget moving as much to service layer. You are adding some of the model attributes in your controller, ask yourself
- if it is necessary to have these attributes here.
- why is your model attributes not present in your model definition that you are retrieving from service. e.g. I will again give example of legacy system, which when you change to Rest, will those attributes not be required in your Rest Apis? If the answer is 'yes required' why not move these to service layers.
推荐阅读
- angular - this.mobilityService.currentMessage.subscribe 不是角度单元测试中的函数
- c# - C# Blazor:如何在后面的代码中使用 @typeparam?(有解决方法)
- python-3.x - 文本建议 API 中以毫秒为单位的烧瓶限制器作为用户类型
- kotlin - 在协程之后从函数返回一个值
- amazon-web-services - 为什么即使使用 DependsOn,CloudFormation API 网关也无法说明“REST API 不包含任何方法”?
- python - 根据特定条件应用拆分
- php - 根据缺货状态和一天中的时间在购物车页面上显示 div
- sql - 检查一个表中的多列与另一表中的一列
- vue.js - 如何在 Nuxt.js 的 v-for 循环中使用 SVG 生成?
- sql - SQL Server - 舍入问题