Как вызвать контроллер Spring MVC в рамках Framework?

В моем проекте Spring у меня есть прослушиватель сообщений JMS, которым управляет spring:

<bean id="jmsFactory" class="org.apache.activemq.ActiveMQConnectionFactory" p:brokerURL="tcp://localhost:61616"/>

<bean id="simpleExampleListener" class="my.package.ExampleListener" />

<jms:listener-container container-type="default" connection-factory="jmsFactory" acknowledge="auto" concurrency="1-3">
    <jms:listener destination="TEST.FOO" ref="simpleExampleListener" method="onMessage"/>
</jms:listener-container>

В одном конкретном сообщении мне нужно вызвать контроллер Spring MVC, который находится в области запроса (на самом деле цель состоит в том, чтобы вызвать службу, которая также находится в области запроса и вызывается контроллером). Поэтому я не могу сделать это напрямую из слушателя, так как Spring управляет ими по мере необходимости, и они не привязаны к области запроса (из-за этого я не могу получить доступ к контроллеру через @Autowire или ApplicationContext). Одним из решений может быть HTTP-вызов с Rest Template для URL-адреса, сопоставленного моим контроллером. Но, я думаю, это своего рода накладные расходы, так что, может быть, есть какой-то другой способ избежать накладных расходов протокола HTTP и сделать вызов Controller в рамках Spring MVC?


person Laimoncijus    schedule 11.05.2012    source источник
comment
Не могли бы вы использовать область прототипа, а не область запроса?   -  person skaffman    schedule 11.05.2012
comment
если бы вы сделали вызов Http, по крайней мере, это было бы слабо связано с кодом веб-приложения. вызов контроллера напрямую намного уродливее.   -  person Nathan Hughes    schedule 11.05.2012
comment
Можете ли вы объяснить, почему вы хотите вызывать контроллер из прослушивателя сообщений? Я не могу придумать ни одного варианта использования...   -  person Tomasz Nurkiewicz    schedule 11.05.2012
comment
@Nathan Hughes: ну, на самом деле, цель состоит в том, чтобы вызвать службу (также в области запроса), которая вызывается контроллером, поэтому контроллер можно пропустить, а службу вызвать напрямую, что больше не сделает ее уродливой ...   -  person Laimoncijus    schedule 11.05.2012
comment
согласованный. позвоните в сервис, проблема решена ^_^   -  person Nathan Hughes    schedule 11.05.2012
comment
@Tomasz Nurkiewicz: мой плохой, как я уже ответил Натану Хьюзу, моя цель - вызвать службу в области запроса, которую можно вызвать двумя способами: через контроллер - как обычный запрос или когда есть сообщение в очереди сообщений ( 2-я часть, которую я пытаюсь достичь сейчас).   -  person Laimoncijus    schedule 11.05.2012
comment
@Nathan Hughes: проблема была бы решена, если бы я назвал это, но теперь у него есть @Scope("request"), поэтому я не могу получить к нему доступ из моего Listener... :)   -  person Laimoncijus    schedule 11.05.2012
comment
ик. я предполагал, что служба будет иметь одноэлементную область действия.   -  person Nathan Hughes    schedule 11.05.2012


Ответы (1)


Вам нужно задаться вопросом, почему класс обслуживания определяется как область запроса - в идеале уровень обслуживания не должен иметь какой-либо неявной/явной зависимости от веб-уровня. Если это не в вашей власти, вы можете использовать следующий обходной путь. Вам нужно будет добавить spring-test.jar в качестве зависимости.

    class Listener {

    @Autowired
    RequestScopedService requestScopedService;


    void handle() {
        MockHttpServletRequest request = new MockHttpServletRequest();
        RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
        try {
             requestScopedService.callSomeMethod();
        } finally {
             ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).requestCompleted();
             RequestContextHolder.resetRequestAttributes();
        }

Если сервисный компонент сконфигурирован с тегом <aop:scoped-proxy/>, его можно подключить автоматически. В противном случае вам нужно получить контекст приложения (путем реализации ApplicationContextAware) и выполнить поиск.

person gkamal    schedule 11.05.2012