JerseyMVCで静的ファイルをリソースクラスの対象から除外する
【概要】
JerseyMVCで静的ファイルをJAX-RSのリソースから除外する方法についてです。
ApplicationPathアノテーションにパスを設定すると
そのパスより下のサブディレクトリが
すべてJAX-RSのリソースとして扱われます。
今回は静的ファイルを除外する方法について調べてみました。
【パスでなんとかする】
簡単に思い浮かぶ方法としては
ApplicationPathアノテーションに指定するパスで工夫するというのがあります。
ApplicationPathに「/service」などの値を設定して、
静的ファイルは別のパスを設定する方法です。
この方法だと画面を表示するためのURLに
全て「/service」をつけることになるので、
URLが長くなってしまいます。
【静的リソースのパスを指定する】
今回のメインとなる内容です。
JerseyMVCでは特定のURLを静的ファイルとして扱い、
JAX-RSのリソースから除外する設定があります。
設定はweb.xmlで行います。
【web.xml】
web.xmlにfilterの設定を行います。
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <filter> <filter-name>JerseySettingFilter</filter-name> <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class> <init-param> <param-name>javax.ws.rs.Application</param-name> <param-value>jp.ne.glory.web.ApplicationSetting</param-value> </init-param> <init-param> <param-name>jersey.config.servlet.filter.staticContentRegex</param-name> <param-value>/(css|js)/.*</param-value> </init-param> </filter> <filter-mapping> <filter-name>JerseySettingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
ServletContainerをフィルターとして登録します。
javax.ws.rs.Applicationはプロパティの名前と同じクラスを継承したクラスを指定します。
JerseyMVCを動かす場合はorg.glassfish.jersey.server.ResourceConfigを
継承して作成していると思うので、そのクラスを設定します。
jersey.config.servlet.filter.staticContentRegexに
静的ファイルとして取り扱いたいURLを指定します。
URLの指定はその名のとおり正規表現で指定します。
【ResourceConfig】
package jp.ne.glory.web; import javax.ws.rs.ApplicationPath; import jp.ne.glory.web.framework.ThymeleafViewProcessor; import org.glassfish.jersey.filter.LoggingFilter; import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.server.mvc.MvcFeature; @ApplicationPath("/") public class ApplicationSetting extends ResourceConfig { public ApplicationSetting() { packages(this.getClass().getPackage().getName()); register(ThymeleafViewProcessor.class); register(MvcFeature.class); register(LoggingFilter.class); } }
ApplicationSettingではApplicationPathに「/」を指定し、
全てのURLをJAX-RSのリソースクラスとして扱うようにします。
【そのほかのファイル】
基本的に前回と同じです。
[テンプレートプロセッサ]
@Provider public class ThymeleafViewProcessor implements TemplateProcessor<String> { @Context private HttpServletRequest request; @Context private HttpServletResponse response; @Context private ServletContext servletContext; private final TemplateEngine templateEngine; public ThymeleafViewProcessor() { TemplateResolver resolver = new ServletContextTemplateResolver(); resolver.setPrefix("/WEB-INF/view/"); resolver.setSuffix(".html"); resolver.setTemplateMode("HTML5"); resolver.setCacheTTLMs(3600000L); templateEngine = new TemplateEngine(); templateEngine.setTemplateResolver(resolver); } @Override public String resolve(String name, MediaType mediaType) { return name; } @Override public void writeTo(String templateReference, Viewable viewable, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream out) throws IOException { WebContext context = new WebContext(request, response, servletContext); context.setVariable("it", viewable.getModel()); Writer writer = new OutputStreamWriter(out); templateEngine.process(templateReference, context, writer); writer.flush(); } }
[リソースクラス]
@Path("top") public class Top { /** * 画面を表示する. * * @return ビューオブジェクト */ @GET @Produces(MediaType.TEXT_HTML) public Viewable view() { final TopInfo topInfo = new TopInfo(LocalDateTime.now(), "Taro", "Yamada"); return new Viewable("/top/top", topInfo); } }
[Bean(TopInfo)]
public class TopInfo { public final LocalDateTime now; public final String lastName; public final String firstName; public TopInfo(final LocalDateTime now, final String lastName, final String firstName) { this.now = now; this.lastName = lastName; this.firstName = firstName; } }
[HTML]
<!DOCTYPE html> <html> <head> <title>Top Page</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <link rel="stylesheet" href="../../../css/base.css" th:href="@{/css/base.css}" /> </head> <body> <div th:text="${it.now}"></div> <div th:text="${it.lastName}"></div> <div th:text="${it.firstName}"></div> </body> </html>
[CSS]
body { margin : 0px; padding : 0px; background-color : lightsteelblue; text-align: center; }
【動かして見る】
warを作ってhttp://localhost:8080/hoge/topにアクセスします。
hogeにはコンテキストパスを指定します。
↓のような画面が表示されます。
作成したCSSが適用されていることがわかります。
【まとめ】
個人的にはResourceConfigのプロパティ設定で
除外できれば良かったなと思うのですが、できないようです。
もしかしたら、自分の設定が悪くてできていない可能性もありますが・・・
それでもweb.xmlに設定書くだけなので、簡単に設定できるのが良いですね。