#spring #spring-mvc
#spring #spring-mvc
Вопрос:
У меня есть сервер, который в основном обслуживает JSON API. В настоящее время у нас есть @Controllers, которые прямолинейно делегируют конечные точки REST методам в классах @Service.
Это приводит к большому количеству ненужного шаблонного кода. Могу ли я столкнуться с проблемами, если я просто прокомментирую свои классы @Service аннотациями @Controller и @RequestMapping (например, испорчу вызовы транзакций? Проблемы с зависимостями между службами?)
Ответ №1:
Если вы используете оба @Service
и @Controller
в одном и том же компоненте, есть большая вероятность, что вы создадите два компонента для одного класса, что обычно не то, что вы хотите.
Это происходит потому, что @Controller
обычно загружаются в дочернем контексте (сервлет диспетчера).
Если все ваши компоненты загружены в контексте сервлета диспетчера, все будет в порядке.
РЕДАКТИРОВАТЬ: я ответил на это в своем iPhone, поэтому я не мог вдаваться в подробности.
Я говорю, что велика вероятность, что это будет проблемой, потому что на самом деле это не имеет ничего общего с типом используемых вами аннотаций, а скорее со сканированием компонентов и тем, как это сканирование компонентов назначается контекстам приложения.
Что делает большинство людей, так это сканирует компоненты, которые @Service
должны быть загружены root WebApplicationContext
, которые могут совпадать с контекстом сервлета диспетчера, но часто это не так.
Позвольте мне привести вам пример:
Обычно вы видите applicationContext.xml с помощью следующего:
<context:component-scan base-package="com.blah">
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>
За которым следует XML-файл контекста сервлета отправки со следующим:
<context:component-scan base-package="com.blah" use-default-filters="false">
<context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>
Обратите внимание, как первый исключает @Controller
, а второй явно включает.
При этом, если у вас есть только один WebApplicationContext и он совместно используется с сервлетом диспетчера, тогда вы можете комментировать @Service
с помощью @RequestMapping
, и это должно работать просто отлично, не то чтобы я это рекомендовал.
Комментарии:
1. как я могу узнать, создал ли spring 2 дублирующих компонента? когда я смогу их увидеть?
2. Аннотирование типа с помощью 2
@Component
специализаций само по себе не создает два компонента.3. На самом деле это не имеет ничего общего с типом аннотаций, которые он использует, а скорее с сканированием компонентов и тем, как это сканирование компонентов назначается контекстам приложения.
4. полезное объяснение @AdamGent
Ответ №2:
Шаблон MVC существует по уважительной причине, пусть каждый уровень выполняет свою работу и имеет низкую связь между ними. У каждого стереотипа тоже есть причина для существования.
О каком шаблонном коде вы говорите? @Controller и @RequestMapping просты.
Комментарии:
1. Допустим, у меня есть 10 классов сервисов, каждый из которых содержит 10 методов, которые нужно сделать общедоступными для REST API. Вместо реализации каждого класса сервиса и аннотирования методов для экспорта в качестве REST API, мне нужно создать дополнительные 10 классов контроллеров с 10 методами, каждый из которых имеет тело, которое просто возвращает service.method(param1,param2). Теперь у меня есть два фрагмента кода, которые необходимо синхронизировать — любые изменения в одном требуют изменений в другом (= высокая связь). Если service=controller, зависимости контроллера по-прежнему не связаны с реализацией сервиса и методами, отличными от @RequestMapping.
2. Дело в том, что вы могли бы изменить свой уровень обслуживания, не меняя уровень REST, вы могли бы обработать некоторый случай по умолчанию в вашем уровне обслуживания. То, что вы предлагаете, в основном сводится к отказу от хорошей архитектуры (отделите ядро вашего приложения от внешнего использования) из-за неудобств. Также, когда вам нужно внести изменения в свой уровень обслуживания, это должно быть сложно, поскольку вы меняете суть своего приложения.
Ответ №3:
Могу ли я столкнуться с проблемами, если я просто аннотирую свои
@Service
классы аннотациями@Controller
и@RequestMapping
Вам не нужно аннотировать тип с помощью @Controller
, если он аннотирован с помощью @Service
. Просто убедитесь, что у типа есть @RequestMapping
аннотация. RequestMappingHandlerMapping
Который обрабатывает сопоставление методов обработчика ваших контроллеров, проверяет наличие как @Controller
, так и @RequestMapping
аннотаций на уровне типа. Вам нужно либо.
В остальном это просто вопрос дизайна и разделения задач. На техническом уровне Spring у вас не возникнет никаких других проблем.
(Обратите внимание, что вам придется загрузить компонент через DispatcherServlet
‘s WebApplicationContext
, чтобы RequestMappingHandlerMapping
получить его.)
Ответ №4:
@Controllers предназначены для делегирования входа и конечной точки одному запросу / ответу.
@Service предназначены для предоставления логики этим @Controllers, логики, которая должна быть неизвестна @Controllers.
В @Controllers вы должны @Автоматически подключать свои зависимости @Services. И в ваших @Services ваши другие логические зависимости, такие как DAO и т.д…
Один типичный Rest @ Controller может выглядеть следующим образом:
@Controller
public class UserWSController {
@Autowired
private UserService userService;
@RequestMapping(value = "/{userId}")
@ResponseBody
public User getUserPublicInfo(@PathVariable int userId) {
return this.userService.getUserById(userId);
}
}