Spring で複数の ViewResolver を使用するにはどうすればよいですか?
-
06-07-2019 - |
質問
私は、ほとんどのページが Apache タイル (2.1.2) を使用している Web アプリに取り組んでいますが、そのうちのいくつかは単純な JSP である必要があります。
私は両方とも問題を抱えています InternalResourceViewResolver
そして UrlBasedViewResolver
は何があってもビューを解決しようとするため、どの順序を使用しても、プレーン JSP ページまたはタイル ページで失敗します。
構成は次のとおりです。
<bean id="tilesViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
<property name="order" value="0"/>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
<property name="order" value="1"/>
</bean>
私がやろうとしていることをより明確にするには、次のようなビューステートを設定できる必要があります。
<view-state id="someState" view="/someDir/foo"><!--render foo.jsp -->
<transition on="foo" to="bar"/>
</view-state>
<view-state id="someState" view="something.core"><!--render tile defintion named 'something.core' -->
<transition on="foo" to="bar"/>
</view-state>
タイル定義とプレーンな JSP をレンダリングできるように設定する方法を知っている人はいますか?
解決
おっしゃるように、これらを連結することはできません。両方の状態のjavadocは、両方ともリゾルバチェーンの最後にある必要があることを明確に示しています。
これらのtogatherを本当に使用する必要がある場合は、ViewResolverのシンプルなカスタム実装を作成して、ビュー名を取得し、2つの「本物」のどちらを決定することをお勧めします。委任するリゾルバを表示します。これは、ビュー名に基づいてどのリゾルバーを呼び出すかを指示できることを前提としています。
したがって、次のようにカスタムViewResolverを定義します。
public class MyViewResolver implements ViewResolver {
private ViewResolver tilesResolver;
private ViewResolver jspResolver;
public void setJspResolver(ViewResolver jspResolver) {
this.jspResolver = jspResolver;
}
public void setTilesResolver(ViewResolver tilesResolver) {
this.tilesResolver = tilesResolver;
}
public View resolveViewName(String viewName, Locale locale) throws Exception {
if (isTilesView(viewName)) {
return tilesResolver.resolveViewName(viewName, locale);
} else {
return jspResolver.resolveViewName(viewName, locale);
}
}
private boolean isTilesView(String viewName) {
.....
}
}
isTilesViewメソッドを実装して、委任先のリゾルバを決定する必要があります。
XML構成で、この新しいビューリゾルバーを定義し、他のビューリゾルバーの前に 表示されることを確認します。
<bean class="MyViewResolver">
<property name="tilesResolver" ref="tilesViewResolver"/>
<property name="jspResolver" ref="viewResolver"/>
</bean>
他のヒント
を分割することで同じ問題を解決しました *-servlet.xml
構成ファイルは 2 つに分かれています。私の場合、メインアプリケーションはタイルを使用していますが、QUnit テストを単純な JSP にしたいと考えています。
app-servlet.xml
タイル ビュー リゾルバーのみが含まれています。 tests-servlet.xml
JSP ビュー リゾルバーのみが含まれており、 web.xml
マッピングは、URL に基づいてリクエストを正しいサーブレットにディスパッチします。
<servlet-mapping>
<servlet-name>app</servlet-name> <!-- will reach app-servlet.xml -->
<url-pattern>/foo</url-pattern> <!-- will use "foo" Tile -->
<url-pattern>/bar</url-pattern> <!-- will use "bar" Tile -->
</servlet-mapping>
<servlet-mapping>
<servlet-name>tests</servlet-name> <!-- will reach tests-servlet.xml -->
<url-pattern>/foo-test</url-pattern> <!-- will use foo-test.jsp -->
<url-pattern>/bar-test</url-pattern> <!-- will use bar-test.jsp -->
</servlet-mapping>
あなたは正しい道を進んでいるように見えますが、心に留めておくべきことは、一部のビューリゾルバは常にビューを解決したかのように動作するということです。このようなリゾルバを注文の最後に配置する必要があります。 Tilesビューはそのようなものだと思います。
編集:whoops ...はい、他のポスターは正しいです。これらのリゾルバーは両方とも「常に一致」するので、両方をチェーンで使用することはできません。もう1つの方法は、TilesViewを拡張して、構成済みのタイルビューが見つからない場合に単純なJSPレンダリングを実行することです。
はい、プロジェクトで任意の数のビューリゾルバを使用できます。
したがって、同じプロジェクトで「タイルビューリゾルバー」と「内部ビューリゾルバー」の両方を使用できます。 。
ContentNegotiatingViewResolverを設定する必要があります。 。
ビューリゾルバで順序値を指定します。
<property name="order" value="int Value here" />
タイルビューリゾルバー2とinternalviewresolver 3を指定したように、最初にタイル定義をチェックインし、InternaiViewResolverでチェックされるタイルでビューが見つからない場合
ここに、私に役立ついくつかの構成があります。
<bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1" />
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
<entry key="html" value="text/html" />
</map>
</property>
<property name="parameterName" value="accept"></property>
<property name="favorParameter" value="true"></property>
<property name="defaultContentType" value="text/html"></property>
<property name="viewResolvers">
<list>
<ref bean="tilesViewResolver" />
<ref bean="internalViewResolver" />
</list>
</property>
<property name="defaultViews">
<list>
<bean
class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
</list>
</property>
<property name="ignoreAcceptHeader" value="true" />
</bean>
<!-- Configures the Tiles layout system -->
<bean class="org.springframework.web.servlet.view.tiles2.TilesConfigurer"
id="tilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/layouts/layouts.xml</value>
<!-- Scan views directory for Tiles configurations -->
<value>/WEB-INF/views/**/views.xml</value>
</list>
</property>
</bean>
<bean id="tilesViewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver"
p:viewClass="org.springframework.web.servlet.view.tiles2.TilesView">
<property name="order" value="3" />
</bean>
<bean id="internalViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="order" value="2" />
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
次のように、単純なjspのレイアウトにタイル定義を追加するだけでこの問題を解決しました。
<definition name="plain-jsp.layout" template="/WEB-INF/layouts/plainJsp.jspx" >
<put-attribute name="content" value=""/>
</definition>
このレイアウトは、単純なjspファイルを含めるためのテンプレートとして使用できます。
<definition name="catalog/details" extends="plain-jsp.layout">
<put-attribute name="content" value="/WEB-INF/views/catalog/details.jspx"/>
</definition>
およびレイアウトテンプレートファイル:
<html xmlns:tiles="http://tiles.apache.org/tags-tiles"
xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0">
<jsp:output doctype-root-element="HTML"/>
<jsp:directive.page contentType="text/html;charset=UTF-8" />
<jsp:directive.page pageEncoding="UTF-8" />
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=8" />
</head>
<body>
<div id="content">
<tiles:insertAttribute name="content"/>
</div>
</body>
</html>