首先來講一下什麼是jersey,他是實現了restful風格的其中一個框架,固然除了jersey還有其餘的,例如html
不過在平時在開發web下,目前流行的仍是以spring mvc爲主,但如今也有一些後起之秀,就例如java
以筆者瞭解呢目前jersey用得仍是蠻多的,最主要是體如今對外接口上面。程序員
不說那麼多了,送上看看怎麼在jersey用freemarkerweb
<dependency> <groupId>javax.ws.rs</groupId> <artifactId>javax.ws.rs-api</artifactId> <version>2.0.1</version> </dependency> <dependency> <groupId>javax.el</groupId> <artifactId>javax.el-api</artifactId> <version>2.2.4</version> </dependency> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet</artifactId> <version>2.23.1</version> </dependency> <dependency> <groupId>org.glassfish.web</groupId> <artifactId>javax.el</artifactId> <version>2.2.4</version> </dependency> <dependency> <groupId>org.glassfish.jersey.ext</groupId> <artifactId>jersey-mvc-mustache</artifactId> <version>2.23.1</version> </dependency> <dependency> <groupId>org.glassfish.jersey.ext</groupId> <artifactId>jersey-mvc-freemarker</artifactId> <version>2.23.1</version> </dependency>
簡單說一下這個配置,最重要的仍是最後那兩個,是jersey作的擴展,固然,他確定有依賴freemarker的spring
<servlet> <servlet-name>restful</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>jersey.config.server.provider.packages</param-name> <param-value> com.example </param-value> </init-param> <init-param> <param-name>javax.ws.rs.Application</param-name> <param-value> com.example.MyApplication </param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>restful</servlet-name> <url-pattern>/restful/*</url-pattern> </servlet-mapping>
最重要的是配置那個掃描包(jersey.config.server.provider.packages
),和spring下的scan package同樣的道理 另外還要讓jersey識別咱們的配置,那麼還要寫一個key爲javax.ws.rs.Application
的配置apache
public class MyApplication extends ResourceConfig { public MyApplication() { /*模板*/ Map<String, Object> pro = new HashMap<String, Object>(1); //模板編碼 pro.put("jersey.config.server.mvc.encoding.freemarker", "UTF-8"); //指定模板基礎路徑 pro.put("jersey.config.server.mvc.templateBasePath.freemarker", "WEB-INF/freemarker"); addProperties(pro). register(FreemarkerMvcFeature.class); } }
這裏主要註冊一個讓他支持freemarker的Feature,固然jersey支持了不少經過註冊能夠作的事情,包括Oauth、Filter、BeanValidata、Security、ContainerRequestFilter等等api
@Path("/views") public class ViewResource { @GET @Path("example") @Produces("text/html") public Viewable exampleView() { Map<String, String> data = new HashMap<String, String>(); data.put("text", "this is the ViewResource test text"); //這裏須要說明一下,前面有"/"和沒有是很大區別的 //沒有的話,jersey會在base路徑下,加上當前類的路徑在加上這個exmaple return new Viewable("/example", data); } }
最後這個java呢,其實就是配置一個控制器,最後經過訪問/restful/views/example
就能夠定位到這個控制器,最後找模板,這個配置的模板是在,/WEB-INF/freemarker/example.ftl
的restful
直接看源碼config方法mvc
public boolean configure(final FeatureContext context) { final Configuration config = context.getConfiguration(); if (!config.isRegistered(FreemarkerViewProcessor.class)) { // Template Processor. context.register(FreemarkerViewProcessor.class); // MvcFeature. if (!config.isRegistered(MvcFeature.class)) { context.register(MvcFeature.class); } return true; } return false; }
咱們平時要jersey支持web服務須要註冊MvcFeature
,那麼,如今看這裏至關於FreemarkerMvcFeature
就依賴這個MvcFeature
,若是沒有註冊,他會幫咱們註冊,jersey這個點作得仍是不錯的 咱們繼續往下看看FreemarkerViewProcessor
是幹嗎的app
@Override protected Template resolve(final String templateReference, final Reader reader) throws Exception { return factory.getConfiguration().getTemplate(templateReference); } @Override public void writeTo(final Template template, final Viewable viewable, final MediaType mediaType, final MultivaluedMap<String, Object> httpHeaders, final OutputStream out) throws IOException { try { Object model = viewable.getModel(); if (!(model instanceof Map)) { model = new HashMap<String, Object>() {{ put("model", viewable.getModel()); }}; } Charset encoding = setContentType(mediaType, httpHeaders); template.process(model, new OutputStreamWriter(out, encoding)); } catch (TemplateException te) { throw new ContainerException(te); } }
從resolve看出,其實這裏算一個入口 ,他從freemarker的configuration中獲取模板,而後直接從wirteTo進行寫出,這裏有個東西須要注意, 他把全部從Viewable中的數據若是是非Map,放到一個以model爲key的Map當中,因此啊,咱們開的時候,若是不是一個Map,須要從model中拿數據
另外,看看這個factory是如何產生的
this.factory = getTemplateObjectFactory(serviceLocator, FreemarkerConfigurationFactory.class, new Value<FreemarkerConfigurationFactory>() { @Override public FreemarkerConfigurationFactory get() { Configuration configuration = getTemplateObjectFactory(serviceLocator, Configuration.class, Values.<Configuration>empty()); if (configuration == null) { return new FreemarkerDefaultConfigurationFactory(servletContext); } else { return new FreemarkerSuppliedConfigurationFactory(configuration); } } });
哎呀,這個很是好啊,從這裏建立這個Configuration,那麼先不說getTemplateObjectFactory這個是幹嗎,先說,下面FreemarkerDefaultConfigurationFactory
,這個就是採用web的加載器,其中包括模板加載器:WebappTemplateLoader
從web上下文加載、ClassTemplateLoader
累加載器加載,FileTemplateLoader
文件根目錄加載 FreemarkerSuppliedConfigurationFactory這個就不說了,他其實就是直接返回上面拿到的configuration好了,咱們下面分析一下getTemplateObjectFactory
先看源碼
protected <F> F getTemplateObjectFactory(final ServiceLocator serviceLocator, final Class<F> type, final Value<F> defaultValue) { //這個值爲 jersey.config.server.mvc.factory.freemarker final Object objectFactoryProperty = config.getProperty(MvcFeature.TEMPLATE_OBJECT_FACTORY + suffix); if (objectFactoryProperty != null) { //若是是Configuration類型,直接轉成對象而且返回 if (type.isAssignableFrom(objectFactoryProperty.getClass())) { return type.cast(objectFactoryProperty); } else { //若是是String類型,直接new 出來而且進行返回 Class<?> factoryClass = null; if (objectFactoryProperty instanceof String) { factoryClass = ReflectionHelper .classForNamePA((String) objectFactoryProperty).run(); } else if (objectFactoryProperty instanceof Class<?>) { factoryClass = (Class<?>) objectFactoryProperty; } if (factoryClass != null) { if (type.isAssignableFrom(factoryClass)) { return type.cast(serviceLocator.create(factoryClass)); } else { LOGGER.log(Level.CONFIG, LocalizationMessages.WRONG_TEMPLATE_OBJECT_FACTORY(factoryClass, type)); } } } } //不然返回空 return defaultValue.get(); }
這下子明白了,jersey的配置工廠均可以自定義,細節的東西仍是考慮的很周全的,那麼若是須要擴展Freemarker
配置,如TemplateLoader
、自定義指令
等等的這些玩意咱們均可以弄了,那麼具體怎麼弄呢,是程序員的,仍是喜歡看代碼比文字的要多點的
//在jersey的Application中能夠配置 //這個obj啊,作的事情能夠是,一個類名,一個Configuration對象,一個Configuration的class //這個就是Freemarker的配置 pro.put("jersey.config.server.mvc.factory.freemarker", obj); //把你添加的信息告訴jersey addProperties(pro);
那麼最後完成咱們的工做,其中包括怎麼配置出jersey怎麼輸出freemarker模板,而且簡單的分析了一下他的源碼,以及怎麼自定義配置freemarker 若有說得很差多多指教