Spring MVC 应该由哪一层来决定显示下一个视图?
Which layer should decide to display the next view in Spring MVC?
我正在使用 Spring MVC 框架构建应用程序,但存在一个我无法明确解决的架构问题。我的问题是我不完全理解应用程序的哪一部分(层)应该负责控制流(通过流控制我的意思是连续视图的显示 - 页面)。
Spring MVC 中的控制器是视图和应用程序之间的某种适配器。另一方面,服务是基于业务逻辑实现的。
假设我们有一个控制器支持某个端点:
@GetMapping("/goToPageBasedOnLogic")
public ModelAndView passParametersWithModelAndView() {
ModelAndView modelAndView = null;
// business logic calculates some stuff...
if(fooService.bar()) {
modelAndView = new ModelAndView("viewPageHello");
modelAndView.addObject("message", "hello");
}
else {
modelAndView = new ModelAndView("viewPageGoodbye");
modelAndView.addObject("message", "goodbye");
}
return modelAndView;
}
在上面的例子中,控制器根据fooService的结果决定显示哪个视图,从而管理控制流。如果有很多条件,可能会导致控制器中的代码难看。
让我们考虑下一个例子:
@GetMapping("/goToPageBasedOnLogic")
public ModelAndView passParametersWithModelAndView() {
ModelAndView modelAndView = null;
session.fooBarResult = fooService.bar(); // logic calculates some stuff and saves in session
State newState = stateMachine.sendEvent(PAGE_FINISHED_JOB);
if(newState == State.PAGE_HELLO) {
modelAndView = new ModelAndView("viewPageHello");
modelAndView.addObject("message", "hello");
}
else {
modelAndView = new ModelAndView("viewPageGoodbye");
modelAndView.addObject("message", "goodbye");
}
return modelAndView;
}
在此示例中,显示哪个视图的决定是根据服务和业务逻辑做出的。状态机接收事件,然后根据会话和编码条件,决定 select 下一个视图。然后控制器根据新状态准备正确的视图并 returns 它。控制器对控制流逻辑一无所知。
决定是否显示下一个视图(页面)的解决方案哪种更好?还有其他更有趣的解决方案吗?
我的经验法则是:
服务层应该不知道 UI 的存在。它不应该对 ui 有任何了解,这样服务 class 就会与 ui 解耦,并且可以很容易地在其他上下文中重用(例如将其公开为 API ,另一个新的 ui 在未来等等)所以如果你发现有服务 classes 需要依赖于来自 spring-mvc 或 servlet 等的一些 classes,应该出问题了。
ui相关的逻辑,比如下一个画面是什么,应该放在controller层
控制器层应该保持薄。尝试将尽可能多的业务逻辑代码推送到服务层。
所以控制器层应该决定下一个要显示的视图。放在服务层没有意义。否则服务层将耦合到UI(见我的观点1)
我正在使用 Spring MVC 框架构建应用程序,但存在一个我无法明确解决的架构问题。我的问题是我不完全理解应用程序的哪一部分(层)应该负责控制流(通过流控制我的意思是连续视图的显示 - 页面)。
Spring MVC 中的控制器是视图和应用程序之间的某种适配器。另一方面,服务是基于业务逻辑实现的。
假设我们有一个控制器支持某个端点:
@GetMapping("/goToPageBasedOnLogic")
public ModelAndView passParametersWithModelAndView() {
ModelAndView modelAndView = null;
// business logic calculates some stuff...
if(fooService.bar()) {
modelAndView = new ModelAndView("viewPageHello");
modelAndView.addObject("message", "hello");
}
else {
modelAndView = new ModelAndView("viewPageGoodbye");
modelAndView.addObject("message", "goodbye");
}
return modelAndView;
}
在上面的例子中,控制器根据fooService的结果决定显示哪个视图,从而管理控制流。如果有很多条件,可能会导致控制器中的代码难看。
让我们考虑下一个例子:
@GetMapping("/goToPageBasedOnLogic")
public ModelAndView passParametersWithModelAndView() {
ModelAndView modelAndView = null;
session.fooBarResult = fooService.bar(); // logic calculates some stuff and saves in session
State newState = stateMachine.sendEvent(PAGE_FINISHED_JOB);
if(newState == State.PAGE_HELLO) {
modelAndView = new ModelAndView("viewPageHello");
modelAndView.addObject("message", "hello");
}
else {
modelAndView = new ModelAndView("viewPageGoodbye");
modelAndView.addObject("message", "goodbye");
}
return modelAndView;
}
在此示例中,显示哪个视图的决定是根据服务和业务逻辑做出的。状态机接收事件,然后根据会话和编码条件,决定 select 下一个视图。然后控制器根据新状态准备正确的视图并 returns 它。控制器对控制流逻辑一无所知。
决定是否显示下一个视图(页面)的解决方案哪种更好?还有其他更有趣的解决方案吗?
我的经验法则是:
服务层应该不知道 UI 的存在。它不应该对 ui 有任何了解,这样服务 class 就会与 ui 解耦,并且可以很容易地在其他上下文中重用(例如将其公开为 API ,另一个新的 ui 在未来等等)所以如果你发现有服务 classes 需要依赖于来自 spring-mvc 或 servlet 等的一些 classes,应该出问题了。
ui相关的逻辑,比如下一个画面是什么,应该放在controller层
控制器层应该保持薄。尝试将尽可能多的业务逻辑代码推送到服务层。
所以控制器层应该决定下一个要显示的视图。放在服务层没有意义。否则服务层将耦合到UI(见我的观点1)