В чем разница между следующими параметрами (@Service, @Bean или статический метод) - PullRequest
0 голосов
/ 01 февраля 2019

У меня есть общий вопрос по кодированию для загрузки Spring.Представьте, что у вас есть контроллер, когда пользователь заходит на определенную страницу, мы читаем некоторые данные из БД, мы делаем некоторую бизнес-логику с этими данными и в зависимости от бизнес-логики мы переходим на другую страницу.Есть 3 способа, которыми я могу запрограммировать это.Вопрос в том, какой метод лучше и почему.Таким образом, я пытаюсь понять различные варианты.Возможно, есть и другие варианты, поэтому, если у вас есть лучшее предложение, пожалуйста, дайте мне знать.Другой вопрос, вы всегда создаете bean / компоненты в Spring или иногда программируете класс Java способом?

Вариант 1: Статический метод Я читаю данные из БД в классе контроллера, в другом классе я делаю некоторую бизнес-логику в статическом методе и возвращаю новую строку.Это выглядит следующим образом:

Класс контроллера:

@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;
    }
}

Класс бизнес-логики:

public class Test {

    public static String testMethod(List<Route> route) {
        // do some business logic
        return "index";
    }
}

Вариант 2: Я читаю данные в классе @Service, вВ том же классе я занимаюсь бизнес-логикой.В моем классе контроллера я автоматически подключаю класс обслуживания и вызываю метод в классе @Service:

Класс контроллера:

@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;
    }
}

Класс бизнес-логики:

@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";
    }
}

Option3: или я делаю то же, что и option1, но с @ Bean

Класс контроллера:

@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;
    }
}

Бизнес-логика:

@Service
public class Test {
    public String testMethod(List<Route> routes) {
        // do some business logic
        return "index";
    }
} 

Класс конфигурации:

@Configuration
public class ConfigAll {

    @Bean
    public Test getAddress() {
        return new Test();
    }
}  

Ответы [ 2 ]

0 голосов
/ 01 февраля 2019

Я бы порекомендовал следующий микро-сервис, например, дизайн, поскольку ваши сервисные классы должны обрабатывать бизнес-логику:

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);
    }
}

TestService.java

@Service
public class TestService {
    private final TestDAO testRespository;

    public TestService(TestRespository testRepository) {
        this.testRepository = testRepository;
    }

    public List<Route> findAllRoutes() {
        return testRepository.findAllRoutes();
    }
}

TestDAO.java

public interface TestDAO {
    List<Route> 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
    }
} 

Обратите внимание, что вы будете инициализировать зависимости класса контроллера и класса обслуживания в их конструкторах.Это связано с тем, что вам будет проще смоделировать эти объекты, когда придет время протестировать их с помощью Mockito и т. Д. Теперь, когда речь заходит о следующем вопросе:

Представьте, что у вас естьконтроллер, когда пользователь переходит на определенную страницу, мы читаем некоторые данные из БД, мы делаем некоторую бизнес-логику с этими данными и в зависимости от бизнес-логики мы переходим на другую страницу

Так каквы возвращаете список «маршрутов» из БД, технически вы можете обработать список маршрутов и вернуть только один маршрут в рамках ResponseEntity, чтобы клиент мог использовать его и перенаправить на его конец.

Альтернативой может быть возвращение клиенту списка маршрутов, и позволить бизнес-логике клиента обрабатывать свои собственные перенаправления на основе предоставленных ему маршрутов.

0 голосов
/ 01 февраля 2019

Используйте вариант 2, однако вы не вернете «index», вы скорее вернете сами Routes.

Под капотом @Controller, @Service, @Repositoryвсе бины, одна из причин, почему они отличаются, состоит в том, что Spring Boot может реализовать идею " тестирование слайсов ".Это позволяет вам тестировать отдельные части вашего приложения изолированно.

Например, если у вас есть RouteService, вы можете полностью смоделировать этот сервис, чтобы вернуть Route без подключения к вашей базе данных, и передать его непосредственно на уровень представления, например, шаблон Thymeleaf си протестируйте его с @WebMvcTest.Уровень представления / HTTP должен быть максимально простым и не содержать логику.Логика принадлежит в @Service.

Используя @Service, вы также можете воспользоваться аннотациями, такими как @Transactional, которые позволяют автоматически откатить единицу работы в случае возникновения проблемы.В вашем варианте 1 вы только читаете все свои маршруты из репозитория, однако представьте, что вам также нужно что-то обновить, и ваш статический метод выдал исключение: система не откатит обновление, так как оно уже было зафиксировано..

Как правило, не используйте статические методы, если они не являются частью библиотечной функции, например, кодировщик base64, который можно протестировать в полной изоляции.Использование статических методов затрудняет тестирование вашей системы, поскольку вы не можете легко их смоделировать.

Использование варианта 3 не имеет смысла, так как сканирование компонентов и аннотации не требуют ручной настройки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...