Step1: 添加Connector支持
finish->oK完成
Step2:新建Plugin-in Project
源码结构
Blog.Java
package api;
public class Blog { private String title; private String content; private String category; private int readCnt;
public Blog(){}
public Blog(String title, String content, String category, int readCnt) { super(); this.title = title; this.content = content; this.category = category; this.readCnt = readCnt; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getCategory() { return category; } public void setCategory(String category) { this.category = category; } public int getReadCnt() { return readCnt; } public void setReadCnt(int readCnt) { this.readCnt = readCnt; }
} |
IBlogService.java
package api;
import java.util.List;
import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType;
@Path("/blog") public interface IBlogApi { @GET @Produces(MediaType.TEXT_HTML) public String getHtml();
@GET @Path("/blogs") @Produces(MediaType.APPLICATION_JSON) public List<Blog> getBlogs(); } |
BlogApiImpl.java
package api.impl;
import java.util.ArrayList; import java.util.List;
import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType;
import api.Blog; import api.IBlogApi;
@Path("/blog") public class BlogApiImpl implements IBlogApi{
private static List<Blog> blogs = new ArrayList<Blog>();
static{ blogs.add(new Blog("blog1", "....", "hello", 1)); blogs.add(new Blog("blog1", "....", "hello", 1)); blogs.add(new Blog("blog1", "....", "hello", 1)); }
@Override @GET public String getHtml(){ return "<h1>BlogApi</h1>"; }
@Override public List<Blog> getBlogs() { return blogs; } } |
GsonMessageBodyHandler.java
package providers;
import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.lang.annotation.Annotation; import java.lang.reflect.Type;
import javax.ws.rs.Consumes; import javax.ws.rs.Produces; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.ext.MessageBodyReader; import javax.ws.rs.ext.MessageBodyWriter; import javax.ws.rs.ext.Provider;
import com.google.gson.Gson; import com.google.gson.GsonBuilder;
@Provider @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public final class GsonMessageBodyHandler implements MessageBodyWriter<Object>, MessageBodyReader<Object> {
private static final String UTF_8 = "UTF-8";
private Gson gson;
private Gson getGson() { if (gson == null) { final GsonBuilder gsonBuilder = new GsonBuilder(); gson = gsonBuilder.create(); } return gson; }
@Override public boolean isReadable(Class<?> type, Type genericType, java.lang.annotation.Annotation[] annotations, MediaType mediaType) { return true; }
@Override public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException { InputStreamReader streamReader = new InputStreamReader(entityStream, UTF_8); try { Type jsonType; if (type.equals(genericType)) { jsonType = type; } else { jsonType = genericType; } return getGson().fromJson(streamReader, jsonType); } finally { streamReader.close(); } }
@Override public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { return true; }
@Override public long getSize(Object object, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { return -1; }
@Override public void writeTo(Object object, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException { OutputStreamWriter writer = new OutputStreamWriter(entityStream, UTF_8); try { Type jsonType; if (type.equals(genericType)) { jsonType = type; } else { jsonType = genericType; } getGson().toJson(object, jsonType, writer); } finally { writer.close(); } } } |
依赖关系
Step3: 配置DS Component, MANIFEST.MF
component-json-provider.xml
<?xml version="1.0" encoding="UTF-8"?> <scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="Jersey-Test-Json-Provider"> <implementation class="providers.GsonMessageBodyHandler"/> <service> <provide interface="providers.GsonMessageBodyHandler"/> </service> </scr:component> |
component.xml
<?xml version="1.0" encoding="UTF-8"?> <scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="Jersey-Test"> <implementation class="api.impl.BlogApiImpl"/> <service> <provide interface="api.impl.BlogApiImpl"/> </service> </scr:component> |
MANIFEST.MF
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Jersey-Test Bundle-SymbolicName: Jersey-Test Bundle-Version: 1.0.0.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-1.7 Service-Component: component.xml, component-json-provider.xml Import-Package: javax.ws.rs;version="2.0.0", javax.ws.rs.core;version="2.0.0", javax.ws.rs.ext;version="2.0.0" Require-Bundle: com.google.gson |
Step4: Run Configuration
需要添加的bundle有jetty、console、osgi、ds、gson等
Step5: 运行测试
注意路径是services打头
原理简介
通过DS/声明式服务将REST Service接口、GsonMessageBodyHandler注册为service;OSGI-JAXRS-Connector监听被注册的服务,并识别、处理。
另外,这里使用自定义的MessageBodyWriter,其实,OSGi-JAXRS-Connector已经有此功能的Bundle,我们可以直接使用。
将MANIFEST.MF中的component-json-provider.xml移除。
参考资料
http://eclipsesource.com/blogs/2014/02/04/step-by-step-how-to-bring-jax-rs-and-osgi-together/
https://github.com/hstaudacher/osgi-jax-rs-connector
https://github.com/hstaudacher/osgi-jax-rs-connector/tree/master/examples
http://eclipsesource.com/blogs/2012/11/02/integrating-gson-into-a-jax-rs-based-application/