Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 以下选项(@Service、@Bean或静态方法)之间有什么区别_Java_Spring Boot - Fatal编程技术网

Java 以下选项(@Service、@Bean或静态方法)之间有什么区别

Java 以下选项(@Service、@Bean或静态方法)之间有什么区别,java,spring-boot,Java,Spring Boot,我有一个关于Spring boot的一般编码问题。 假设您有一个控制器,当用户转到某个页面时,我们从数据库中读取一些数据,我们使用这些数据执行一些业务逻辑,并根据业务逻辑转到不同的页面。有三种方法可以编程。问题是,哪种方法最好,为什么。这样,我试图理解不同的选择。可能还有其他选择,所以如果你有更好的建议,请让我知道。 另一个问题,您总是在Spring中创建Bean/组件,还是有时以Java方式编程类 选项1:静态方法 我在controller类中从db读取数据,在另一个类中,我在静态方法中执行一

我有一个关于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
    }
}