WedX - журнал о программировании и компьютерных науках

Spring @Controller и RequestMapping вызывают разные службы в зависимости от заданного параметра

Предположим, у меня есть этот код:

@Controller
@RequestMapping("/something")
public class SomeController {
    @Autowired
    private SomeService aService;

    @RequestMapping("/doStuff")
    public void doStuff(@RequestParam("type") String type) {
        aService.doStuff();
    }
}

В моем приложении мне нужно вызвать конкретную службу в зависимости от указанного типа. Все сервисы реализуют один и тот же интерфейс. Если я правильно понимаю, SomeService не может быть интерфейсом. Я мог бы использовать фабрику услуг и создавать экземпляр службы в зависимости от типа каждый раз, когда выполняется новый запрос, но это выглядит не очень эффективно.

В качестве альтернативы я мог бы использовать другой контроллер для каждого типа службы (и закодировать тип в REST URI), но это потребовало бы большого количества дублирования кода, поскольку все службы в основном реализуют один и тот же интерфейс.

У меня вопрос: если вызываемая служба зависит от переданного параметра, какой шаблон лучше всего использовать для этого сценария?

01.04.2014

  • Если я правильно понимаю, SomeService не может быть интерфейсом неправильно, это может быть интерфейс, на самом деле он должен быть, и Spring внедрит в него экземпляр реализации класса или просто восстановит нужный экземпляр из BeanFactory . 01.04.2014

Ответы:


1

Как и в ответе RC., вместо использования Map и добавления вами значений просто позвольте Spring BeanFactory сделает это за вас:

@Controller
@RequestMapping("/something")
public class SomeController {
    @Autowired
    private BeanFactory beanFactory;

    @RequestMapping("/doStuff")
    public void login(@RequestParam("type") String type) {
        SomeService aService = (SomeService)beanFactory.getBean(type);
        aService.doStuff();
    }
}
01.04.2014
  • В конце концов я принял этот, который похож на тот, который я пробовал ранее с фабрикой сервисов из RC, но я ничего не выиграл по сравнению с подходом BeanFactory, и я боролся с проблемами создания экземпляров bean-компонентов. Спасибо всем за потрясающие ответы, вы сделали мой день. 02.04.2014

  • 2

    Вы можете использовать карту здесь, что-то вроде этого:

    @Controller
    @RequestMapping("/something")
    public class SomeController {
        @Autowired
        private SomeService someService;
    
        @Autowired
        private SomeOtherService someOtherService;
    
        // ...
    
        private final Map<String, ServiceCommonInterface> serviceMap = new HashMap<>();
    
        @PostConstruct
        private void postConstruct() {
            serviceMap.put(typeForSomeService, someService);
            serviceMap.put(typeForSomeOtherService, someOtherService);
        }
    
        @RequestMapping("/doStuff")
        public void login(@RequestParam("type") String type) {
            // TODO: ensure type is correct (an enum might be handy here)
            serviceMap.get(type).doStuff();
        }
    }
    

    Или лучше, как указано в комментариях, вы можете использовать квалификаторы:

    @Controller
    @RequestMapping("/something")
    public class SomeController {
        @Autowired
        private ApplicationContext applicationContext;
    
        @RequestMapping("/doStuff")
        public void login(@RequestParam("type") String type) {
            // TODO: ensure type is a correct bean name
            applicationContext.getBean(type, ServiceCommonInterface.class).doStuff();
        }
    }
    
    01.04.2014
  • Это то, к чему я стремился. В качестве альтернативы, вместо прямой карты создайте bean-компонент, в который вы внедряете все сервисы и генерируете Map. 01.04.2014
  • да, я читал ваш комментарий и думал, черт возьми, я могу просто использовать квалификатор, карта является контекстом весны 01.04.2014

  • 3

    В зависимости от количества типов, которые вы хотите поддерживать, я вижу два варианта.

    1) Autowire на фабрике, как вы упомянули, и лениво создавайте каждую службу по мере необходимости. Если службы не имеют состояния, вы можете сохранить ссылку на объект после создания, поэтому вам нужно будет создать только один раз для каждого типа.

    2) Autowire в Spring Map, где ключом являются ваши типы, а значением является правильный сервис для использования. Затем, когда вы получите тип, вы можете получить правильный сервис для вашей карты.

    Например, для карты: https://www.mkyong.com/spring/spring-collections-list-set-map-and-properties-example/ или см. Как внедрить Map‹String, List› в java springs?

    Оба они требуют, чтобы вы создали интерфейс для своего сервиса, что, как вы сказали, возможно.

    01.04.2014
    Новые материалы

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..

    ИИ в аэрокосмической отрасли
    Каждый полет – это шаг вперед к великой мечте. Чтобы это происходило в их собственном темпе, необходима команда астронавтов для погони за космосом и команда технического обслуживания..


    Для любых предложений по сайту: [email protected]