Jersey采用模板Freemarker输出
来源:互联网 发布:网络维护实训周报 编辑:程序博客网 时间:2024/05/20 01:38
简介
首先来说一下什么是jersey,他是实现了restful风格的其中一个框架,当然除了jersey还有其他的,例如
- apache axis2
- apache CXF
- spring mvc 也算上一个,但不是标准的
不过在平时在开发web下,目前流行的还是以spring mvc为主,但现在也有一些后起之秀,就例如
- JFinal
- Spring boot
以笔者了解呢目前jersey用得还是蛮多的,最主要是体现在对外接口上面。
不说那么多了,送上看看怎么在jersey用freemarker
配置
maven
<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的
web.xml
<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
的配置
java 配置
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等等
Control
@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
的
源码分析
FreemarkerMvcFeature.java
直接看源码config方法
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
是干嘛的
FreemarkerViewProcessor.java
@Overrideprotected Template resolve(final String templateReference, final Reader reader) throws Exception { return factory.getConfiguration().getTemplate(templateReference); }@Overridepublic 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
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);//把你添加的信息告诉jerseyaddProperties(pro);
那么最后完成我们的工作,其中包括怎么配置出jersey怎么输出freemarker模板,并且简单的分析了一下他的源码,以及怎么自定义配置freemarker
如有说得不好多多指教
- Jersey采用模板Freemarker输出
- Jersey采用模板Freemarker输出
- 输出Freemarker模板
- springboot采用FreeMarker模板集成应用
- 采用freemarker模板引擎作为Java邮件模板
- 对freemarker输出的模板进行加工
- 在FreeMarker模板中输出rfc 822标准格式时间
- freemarker用模板输出指定格式word文档
- freemarker 模板
- FreeMarker模板
- freemarker-模板
- Jersey 配合 Jackson 输出 json
- freemarker模板技术
- freemarker模板中迭代Map
- FreeMarker解析字符串模板
- FreeMarker模板学习
- FreeMarker模板宏
- 什么是freemarker模板生成器
- Linux 磁盘管理
- 【u004】数列
- [React Native混合开发]React Native for iOS之UI组件
- Partition List
- [React Native混合开发]React Native for iOS之应用
- Jersey采用模板Freemarker输出
- [React Native混合开发]React Native for iOS之动手写组件
- 每日总结0825-Git的安装与使用(一)
- Android逆向之旅---静态方式破解微信获取聊天记录和通讯录信息
- Express 项目中使用 Mongoose
- 【phalcon】完美路由配置 apache nginx
- Mac 配置经常遇到的问题 No Module named xxx
- 无监督学习(图像处理应用中)的前世今生
- 值传递