Java 以下选项(@Service、@Bean或静态方法)之间有什么区别
我有一个关于Spring boot的一般编码问题。 假设您有一个控制器,当用户转到某个页面时,我们从数据库中读取一些数据,我们使用这些数据执行一些业务逻辑,并根据业务逻辑转到不同的页面。有三种方法可以编程。问题是,哪种方法最好,为什么。这样,我试图理解不同的选择。可能还有其他选择,所以如果你有更好的建议,请让我知道。 另一个问题,您总是在Spring中创建Bean/组件,还是有时以Java方式编程类 选项1:静态方法 我在controller类中从db读取数据,在另一个类中,我在静态方法中执行一些业务逻辑,然后返回新字符串。 这看起来像这样: 控制器类:Java 以下选项(@Service、@Bean或静态方法)之间有什么区别,java,spring-boot,Java,Spring Boot,我有一个关于Spring boot的一般编码问题。 假设您有一个控制器,当用户转到某个页面时,我们从数据库中读取一些数据,我们使用这些数据执行一些业务逻辑,并根据业务逻辑转到不同的页面。有三种方法可以编程。问题是,哪种方法最好,为什么。这样,我试图理解不同的选择。可能还有其他选择,所以如果你有更好的建议,请让我知道。 另一个问题,您总是在Spring中创建Bean/组件,还是有时以Java方式编程类 选项1:静态方法 我在controller类中从db读取数据,在另一个类中,我在静态方法中执行一
@Controller
public class TestController {
private final RouteRepository routeRepository;
@Autowired
public TestController (RouteRepository routeRepository) {
this.routeRepository = routeRepository;
}
@GetMapping("/test")
public String getTestController() {
List<Route> route= routeRepository.findAll();
String total= Test.testMethod(route);
return total;
}
}
@Controller
public class TestController {
private final Test test;
@Autowired
public TestController (Test test) {
this.test = test;
}
@GetMapping("/test")
public String getTestController() {
String total= test.testMethod();
return total;
}
}
@Controller
public class TestController {
ApplicationContext context = new AnnotationConfigApplicationContext(ConfigAll.class);
Test test = context.getBean(Test.class);
private final RouteRepository routeRepository;
@Autowired
public TestController (RouteRepository routeRepository) {
this.routeRepository = routeRepository;
}
@GetMapping("/test")
public String getTestController() {
List<Route> routes = routeRepository.findAll();
String total= test.testMethod(routes);
return total;
}
}
业务逻辑类:
public class Test {
public static String testMethod(List<Route> route) {
// do some business logic
return "index";
}
}
@Service
public class Test {
private final RouteRepository routeRepository;
@Autowired
public Test (RouteRepository routeRepository) {
this.routeRepository = routeRepository;
}
public String testMethod() {
List<Route> route= routeRepository.findAll();
// do some business logic
return "index";
}
}
使用选项2,但是您不会返回“index”,而是返回实际的
路由
本身
在引擎盖下,@Controller
,@Service
,@Repository
都是bean,它们不同的一个原因是允许Spring Boot实现“”的思想。这允许您单独测试应用程序的特定部分
例如,如果您有一个路由服务
,您可以完全模拟此服务返回路由
,而无需连接到您的数据库,并将其直接传递到您的表示层,例如,一个带有@WebMvcTest
的Thymeleaf模板,并使用@WebMvcTest对其进行测试。您的表示/HTTP层应该尽可能简单,并且不包含逻辑。逻辑属于@服务
通过使用@服务
,您还可以从@Transactional
之类的注释中获益,这样可以在出现问题时自动回滚工作单元。在选项1中,您只读取存储库中的所有路由,但是如果您还需要更新某些内容,并且您的静态方法引发了一个异常:系统不会回滚更新,因为它已经提交了
根据经验,不要使用静态方法,除非它们是库函数的一部分,例如base64编码器,可以完全隔离测试。静态方法的使用使您的系统难以测试,因为您无法轻松地模拟它们
使用选项3没有任何好处,因为组件扫描和注释会使手动配置变得不必要。我建议使用以下类似微服务的设计,因为您的服务类应该处理业务逻辑:
TestController.java
@RestController
@RequestMapping(path= "test-api")
public call TestController.java
private final TestService testService;
public TestController(TestService testService) {
this.testService = testService;
}
@GetMapping(produces= "application/json")
public ResponseEntity<?> getTestController() {
List<Route> routeList = testService.findAllRoutes();
return ResponseEntity.ok(routeList);
}
}
@RestController
@请求映射(path=“测试api”)
公共调用TestController.java
私人最终测试服务;
公共TestController(TestService TestService){
this.testService=testService;
}
@GetMapping(products=“application/json”)
公共响应getTestController(){
List routeList=testService.findAllRoutes();
返回ResponseEntity.ok(路线列表);
}
}
TestService.java
@Service
public class TestService {
private final TestDAO testRespository;
public TestService(TestRespository testRepository) {
this.testRepository = testRepository;
}
public List<Route> findAllRoutes() {
return testRepository.findAllRoutes();
}
}
@服务
公共类测试服务{
私人最终测试dao testRespository;
公共TestService(TestRespository testRepository){
this.testRepository=testRepository;
}
公共列表findAllRoutes(){
返回testRepository.findAllRoutes();
}
}
TestDAO.java
public interface TestDAO {
List<Route> findAllRoutes();
}
公共接口TestDAO{
列出findAllRoutes();
}
TestDAOImpl.java
@Repository
public class TestDAOImpl implements TestDAO {
private static final String FIND_QUERY = <insert query here>;
@Override
public List<Route> findAllRoutes() {
// Use query and return the list
}
}
@存储库
公共类TestDAOImpl实现TestDAO{
私有静态最终字符串FIND_QUERY=;
@凌驾
公共列表findAllRoutes(){
//使用查询并返回列表
}
}
注意,您将在其构造函数中初始化控制器类和服务类的依赖项。这是由于这样一个事实,即当需要使用Mockito等进行测试时,您可以更轻松地模拟这些对象。现在,当涉及到以下问题时:
假设您有一个控制器,当用户转到某个页面时,
我们从数据库中读取一些数据,用这些数据进行一些业务逻辑
根据业务逻辑,我们会转到不同的页面
由于您要从db返回一个“路由”列表,从技术上讲,您可以处理路由列表,并且只返回ResponseEntity中的一个路由,供客户端使用并在其端重定向
另一种方法是将路由列表返回给客户机,并让客户机的业务逻辑根据您提供给它的路由处理它自己的重定向
public interface TestDAO {
List<Route> findAllRoutes();
}
@Repository
public class TestDAOImpl implements TestDAO {
private static final String FIND_QUERY = <insert query here>;
@Override
public List<Route> findAllRoutes() {
// Use query and return the list
}
}