Доступ к Spring MVC DI beans из jsp
В некоторых структурах MVC вы можете вызвать действие контроллера из представления, если вы хотите выполнить некоторый код и сделать частичный вид. Я не уверен, что это правильный способ сделать это в Spring MVC
Я хочу иметь набор шаблонов JSP. Некоторые из них будут макетами страниц, некоторые из них будут небольшими компонентами, такими как paginator, поле входа, меню, облако тегов и т.д. И т.д. И т.д. Каждому из этих компонентов требуется некоторое beans или действие контроллера для установки некоторых данных в ViewAndModel, чтобы используйте его.
Проблема заключается в том, что я не хочу устанавливать все эти объекты в каждом вызове. Мой регистратор контролирует только обработку регистрации. Итак, как мне это сделать? Как я могу вызвать DI beans или контроллеры из представления, чтобы подготовить частичные представления? Или мне нужно создать некоторые сопоставления? Или я подхожу к проблеме из совершенно неправильного угла?
Ответы
Ответ 1
Spring -MVC может отображать контекст приложения beans на уровень представления, если это то, что вы хотите сделать.
Например, InternalResourceViewResolver
может быть проинструктирован об открытии каждого bean в контексте или только указанных. Взгляните на exposeContextBeansAsAttributes и exposedContextBeanNames свойства.
Например, скажите, что вы хотели открыть beans beanA
и beanB
для ваших JSP. Таким образом, вы должны объявить разрешающий вид в своем контексте:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="exposedContextBeanNames">
<list>
<value>beanA</value>
<value>beanB</value>
</list>
</property>
</bean>
В качестве альтернативы просто вывести каждый bean:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="exposeContextBeansAsAttributes" value="true"/>
</bean>
Независимо от того, является ли это хорошей идеей, другой вопрос, но Spring дает вам возможность.
Ответ 2
ММО
добавьте использование protectedContextBeanNames в конфигурацию viewResolver bean (есть также возможность использовать глобальный флаг, и это не рекомендуется)
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="exposedContextBeanNames">
<list>
<value>beanName</value>
</list>
используйте в своем JSP
${beanName.property}
Ответ 3
Вы можете использовать тег spring:eval
:
...
<spring:eval expression="@properties.getProperty('myProp')" var="myProp" />
${myProp}
...
Где @properties
является bean именем ваших свойств в Spring Контекст. Обратите внимание, что этот подход не использует exposedContextBeanNames
, поэтому его можно использовать с Tiles Views, например (TilesViewResolver
не имеет такого свойства).
Ответ 4
Критической частью использования InternalResourceViewResolver является то, что Spring необходимо задействовать в потоке кода при обработке страницы jsp.
Если вы обращаетесь непосредственно к странице jsp или иным образом обходите любое действие, основанное на Spring (например, путем внутренней пересылки на страницу jsp из-за конфигурации входа в web.xml), это не сработает.
Тем не менее, можно настроить приложение таким образом, чтобы определенные beans были доступны всем, что может попасть в ServletContext (aka applicationScope) через
использование класса ServletContextAttributeExporter.
В конфигурации Spring добавьте:
<bean id="mybean" .../>
<bean class="org.springframework.web.context.support.ServletContextAttributeExporter">
<property name="attributes">
<map>
<entry key="attrname" value-ref="mybean"/>
</map>
</property>
</bean>
Затем на странице JSP вы можете получить доступ к этому bean с помощью:
${applicationScope.attrname}
или если вы знаете, что у вас нет атрибута "attrname" в более конкретной области, просто:
${attrname}
Очевидно, что это не сможет ссылаться на область запросов или сеанса beans, но если вам нужен доступ к singleton bean, тогда он отлично работает.
Ответ 5
Никогда не обращаться к бизнес-компонентам из представлений jsp; что-то вроде sitemesh можно использовать для объединения нескольких видов в одном. Jsps также не должны напрямую ссылаться на методы контроллера.