LiferayのJSPをオーバーライドするAPIベースのアプローチ(つまり、動的インクルードとポートレットフィルター)は、アプリおよびコアのJSPをオーバーライドする最良の方法です。カスタムJSPバッグを使用して、コアJSPをオーバーライドすることもできます。しかし、このアプローチはAPIベースのアプローチほど安定していません。カスタムJSPバッグのJSPにバグがある場合(コードやLiferayの変更のせいで)、ほとんどの場合は実行時に、機能が壊れたり、厄介なログエラーが表示されたりすることで気付くはずです。カスタムJSPバッグを使用してJSPをオーバーライドすることはバッドプラクティスであり、Extプラグインを使用してLiferay DXPをカスタマイズするのと同じです。ただし、既存のカスタムJSPバッグを維持している場合は、このチュートリアルでその動作について説明します。
重要:Liferayは、カスタムJSPバッグを使用してオーバーライドされたJSPのアップグレードを保証できません。
カスタムJSPバッグモジュールは、次の基準を満たす必要があります。
-
拡張するJSPのカスタムJSPを提供および指定している。
-
カスタムJSPを提供するための
CustomJspBag
実装が含まれている。
モジュールは、このコードをLiferayのOSGiランタイムに転送します。 新しいモジュールを作成したら、カスタムJSPを指定します。
カスタムJSPの指定
Liferay DXPのコアJSPをオーバーライドするJSPを作成します。Mavenの標準ディレクトリレイアウトを使用している場合は、src/main/resources/META-INF/jsps
の下にJSPを配置します。以下をオーバーライドする場合:
portal-web/docroot/html/common/themes/bottom-ext.jsp
カスタムJSPを次のように配置します。
[your module]/src/main/resources/META-INF/jsps/html/common/themes/bottom-ext.jsp
注:モジュール内src/main/resources/META-INF/jsps
以外の場所にカスタムJSPを配置する場合は、その場所をモジュールのbnd.bnd
ファイル内の-includeresource: META-INF/jsps=
ディレクティブに割り当てます。
たとえばモジュール内のフォルダsrc/META-INF/custom_jsps
にカスタムJSPを配置する場合は、bnd.bnd
内で次のように指定します。
-includeresource: META-INF/jsps=src/META-INF/custom_jsps
カスタムJSPバッグを実装する
Liferay DXP(特にCustomJspBagRegistryUtil
クラス)は、CustomJspBag
サービスからJSPを読み込みます。次の手順では、カスタムJSPバッグを実装します。
-
モジュールで、
CustomJspBag
を実装するクラスを作成します。 -
次のように、
@Component
アノテーションを追加して、クラスをOSGiサービスとして登録します。@Component( immediate = true, property = { "context.id=BladeCustomJspBag", "context.name=Test Custom JSP Bag", "service.ranking:Integer=100" } )
immediate = true
:モジュールのアクティベーションでサービスを利用できるようにします。context.id
:カスタムJSPバッグのクラス名。BladeCustomJspBag
をクラス名に置き換えます。context.name
:人間が読み取れるサービス名。独自の名前に置き換えます。service.ranking:Integer
:実装の優先順位。コンテナは、優先度が最も高い実装を選択します。
-
getCustomJspDir
メソッドを実装して、JSPが存在するモジュールのJAR内のフォルダパスを返します(例:META-INF/jsps
)。@Override public String getCustomJspDir() { return "META-INF/jsps/"; }
-
activate
メソッドと次のフィールドを作成します。このメソッドは、モジュールがアクティブ化されると、すべてのカスタムJSPのURLパスをリストに追加します。@Activate protected void activate(BundleContext bundleContext) { _bundle = bundleContext.getBundle(); _customJsps = new ArrayList<>(); Enumeration<URL> entries = _bundle.findEntries( getCustomJspDir(), "*.jsp", true); while (entries.hasMoreElements()) { URL url = entries.nextElement(); _customJsps.add(url.getPath()); } } private Bundle _bundle; private List<String> _customJsps;
-
このモジュールのカスタムJSP URLパスのリストを返す
getCustomJsps
メソッドを実装します。@Override public List<String> getCustomJsps() { return _customJsps; }
-
新しい
com.liferay.portal.kernel.url.URLContainer
を返すgetURLContainer
メソッドを実装します。URLコンテナをインスタンス化し、getResources
およびgetResource
メソッドをオーバーライドします。getResources
メソッドは、指定されたパスで、コンテナ内のリソースへのすべてのパスを検索します。一致するカスタムJSPパスのStrings
のHashSet
が返されます。getResource
メソッドは、その名前ごとに1つの特定のリソースを返します(パスを含む)。サンプルのBladeCustomJspBag
クラスは、次のようにgetURLContainer
を実装します。@Override public URLContainer getURLContainer() { return _urlContainer; } private final URLContainer _urlContainer = new URLContainer() { @Override public URL getResource(String name) { return _bundle.getEntry(name); } @Override public Set<String> getResources(String path) { Set<String> paths = new HashSet<>(); for (String entry : _customJsps) { if (entry.startsWith(path)) { paths.add(entry); } } return paths; } };
-
true
を返すisCustomJspGlobal
メソッドを実装します。@Override public boolean isCustomJspGlobal() { return true; }
これで、モジュールはカスタムJSPとカスタムJSPバッグの実装を提供します。デプロイすると、Liferay DXPは、オーバーライドするコアJSPの代わりにカスタムJSPを使用します。
JSPを拡張する
コアJSPに何かを追加する場合は、空の-ext.jsp
があるかを確認し、JSP全体ではなくそれをオーバーライドします。JSP全体が大幅に変更されると、その過程でカスタマイズが崩れる可能性があるため、こうすることでよりシンプルかつ安定した状態を維持できます。-ext.jsp
をオーバーライドすると、-ext.jsp
を含む元のJSPのみに依存します。たとえば、portal-web/docroot/html/common/themes/bottom.jsp
を開き、最後までスクロールしてください。
以下が表示されます。
<liferay-util:include page="/html/common/themes/bottom-ext.jsp" />
bottom.jsp
に何かを追加する必要がある場合は、bottom-ext.jsp
をオーバーライドします。
Liferay DXP 7.0以降、以前はhtml/common/themes
に含まれていた以下のJSPファイルのコンテンツがインライン化され、パフォーマンスが向上しました。
body_bottom-ext.jsp
body_top-ext.jsp
bottom-ext.jsp
bottom-test.jsp
これらはコードベースの明示的なファイルではなくなりました。ただし、モジュールでそれらを作成して、機能とコンテンツを追加することは引き続き可能です。
このタイプのカスタマイズは最後の手段であることに留意してください。この実装の性質によりオーバーライドが壊れる可能性があり、Liferayのコア機能がそれとともに機能しなくなる可能性があります。オーバーライドするJSPが別のモジュールにある場合は、JSPをオーバーライドするためのLiferay APIベースのアプローチに関するセクションを参照してください。
サイトスコープのJSPカスタマイズ
Liferay Portal 6.2では、アプリケーションアダプタを使用して、コアJSPのカスタマイズの対象を特定のサイトに絞り込むことができました。Liferay DXP 7.0ではJSPの大部分がモジュールに移行されたため、このユースケースは大幅に縮小しました。コアJSPのカスタマイズの対象を特定のサイトに絞り込む必要がある場合は、Liferay Portal 6.2の場合と同様にアプリケーションアダプタを準備して、 Liferay DXP 7.1にデプロイします。これで引き続き機能します。ただし、このアプローチはLiferay DXP 7.1では非推奨であり、Liferay 8.0ではまったくサポートされていないことに注意してください。