一、环境
eclipse版本:eclipse-luna 4.4
jre版本:1.8
二、Equinox OSGi应用嵌入Jersey框架搭建REST服务
1.新建插件工程HelloWebOSGI
a.
b.
c.
d.在新建的工程中新建文件夹lib,其中放入附件中的jar包(见文末),全部添加到工程Build Path中。
2.配置运行环境
a.配置引入包、依赖插件
b.选择Run->Run Configuration,new一个环境
保留图中TargetPlatform中的16个Bundle。
c.在Run Configuration中设置参数
友情提示:如果有其他异常请查看提示信息,利用 http://www.aolsearch.com/ 查询提示信息(英文),如果发现http://stackoverflow.com/这个网站有相同提问,基本就知道答案近在咫尺了。
比如笔者遇到的问题:Root exception:java.lang.IllegalStateException: Workbench has not been created yet.
解决方法就是在http://stackoverflow.com/questions/13773582/workbench-has-not-been-created-yet-error-in-eclipse-plugin-programming中找到的。
d.在MANIFEST.MF(META-INF)文件中将lib文件夹中的包都引入如下图中。
3.添加代码
Activator_sample.java
1 package helloworldosgi; 2 3 import java.util.Dictionary; 4 import java.util.HashMap; 5 import java.util.Hashtable; 6 import java.util.logging.Logger; 7 8 import javax.servlet.ServletException; 9 10 import org.glassfish.jersey.servlet.ServletContainer; 11 import org.osgi.framework.BundleActivator; 12 import org.osgi.framework.BundleContext; 13 import org.osgi.framework.ServiceReference; 14 import org.osgi.service.event.Event; 15 import org.osgi.service.event.EventAdmin; 16 import org.osgi.service.http.HttpService; 17 import org.osgi.service.http.NamespaceException; 18 import org.osgi.util.tracker.ServiceTracker; 19 20 /* 21 * BundleActivator:让你能够捕捉到bundle的start和stop事件,并对这两个事件作出自定义的反应。 22 */ 23 public class Activator_sample implements BundleActivator { 24 private BundleContext bc; 25 @SuppressWarnings("rawtypes") 26 private ServiceTracker tracker; 27 private HttpService httpService = null; 28 private static final Logger logger = Logger.getLogger(Activator.class.getName()); 29 30 /** 31 * URL前缀 32 */ 33 public static final String CONTEXT_PATH = "/rest/json"; 34 35 /* 36 * BundleContext:一个bundle在框架中的执行时上下文,这个上下文提供了和框架进行交互的方法。 37 * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) 38 */ 39 @SuppressWarnings({ "unchecked", "rawtypes" }) 40 @Override 41 public synchronized void start(BundleContext bundleContext) throws Exception { 42 this.bc = bundleContext; 43 logger.info("STARTING HTTP SERVICE BUNDLE"); 44 45 this.tracker = new ServiceTracker(this.bc, HttpService.class.getName(), null) { 46 @Override 47 public Object addingService(ServiceReference serviceRef) { 48 httpService = (HttpService) super.addingService(serviceRef); 49 registerServlets(); 50 return httpService; 51 } 52 53 @Override 54 public void removedService(ServiceReference ref, Object service) { 55 if (httpService == service) { 56 unregisterServlets(); 57 httpService = null; 58 } 59 super.removedService(ref, service); 60 } 61 }; 62 63 this.tracker.open(); 64 65 logger.info("HTTP SERVICE BUNDLE STARTED"); 66 } 67 68 /* 69 * BundleContext:一个bundle在框架中的执行时上下文,这个上下文提供了和框架进行交互的方法。 70 * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) 71 */ 72 @Override 73 public synchronized void stop(BundleContext bundleContext) throws Exception { 74 this.tracker.close(); 75 } 76 77 private void registerServlets() { 78 try { 79 rawRegisterServlets(); 80 } catch (InterruptedException | NamespaceException | ServletException ie) { 81 throw new RuntimeException(ie); 82 } 83 } 84 85 private void rawRegisterServlets() throws ServletException, NamespaceException, InterruptedException { 86 logger.info("JERSEY BUNDLE: REGISTERING SERVLETS"); 87 logger.info("JERSEY BUNDLE: HTTP SERVICE = " + httpService.toString()); 88 89 // TODO - temporary workaround 90 // This is a workaround related to issue JERSEY-2093; grizzly (1.9.5) 91 // needs to have the correct context 92 // classloader set 93 ClassLoader myClassLoader = getClass().getClassLoader(); 94 ClassLoader originalContextClassLoader = Thread.currentThread() 95 .getContextClassLoader(); 96 try { 97 Thread.currentThread().setContextClassLoader(myClassLoader); 98 httpService.registerServlet(CONTEXT_PATH, new ServletContainer(), 99 getJerseyServletParams(), null); 100 httpService.registerResources(CONTEXT_PATH + "/hello", "/webroot", null);//前面必须带“/”,后面不一定 101 } finally { 102 Thread.currentThread().setContextClassLoader( 103 originalContextClassLoader); 104 } 105 // END of workaround - after grizzly updated to the recent version, only 106 // the inner call from try block will remain: 107 // httpService.registerServlet("/jersey-http-service", new 108 // ServletContainer(), getJerseyServletParams(), null); 109 110 sendAdminEvent(); 111 logger.info("JERSEY BUNDLE: SERVLETS REGISTERED"); 112 } 113 114 @SuppressWarnings("serial") 115 private void sendAdminEvent() { 116 @SuppressWarnings("rawtypes") 117 ServiceReference eaRef = bc.getServiceReference(EventAdmin.class 118 .getName()); 119 if (eaRef != null) { 120 @SuppressWarnings("unchecked") 121 EventAdmin ea = (EventAdmin) bc.getService(eaRef); 122 ea.sendEvent(new Event("jersey/test/DEPLOYED", 123 new HashMap<String, String>() { 124 { 125 put("context-path", "/"); 126 } 127 })); 128 bc.ungetService(eaRef); 129 } 130 } 131 132 private void unregisterServlets() { 133 if (this.httpService != null) { 134 logger.info("JERSEY BUNDLE: UNREGISTERING SERVLETS"); 135 httpService.unregister(CONTEXT_PATH); 136 logger.info("JERSEY BUNDLE: SERVLETS UNREGISTERED"); 137 } 138 } 139 140 private Dictionary<String, String> getJerseyServletParams() { 141 Dictionary<String, String> jerseyServletParams = new Hashtable<>(); 142 jerseyServletParams.put("javax.ws.rs.Application", 143 RestApplication.class.getName()); 144 logger.info("kira2will" + RestApplication.class.getName()); 145 return jerseyServletParams; 146 } 147 148 149 }
StatusService.java
1 package helloworldosgi; 2 import java.util.ArrayList; 3 import java.util.List; 4 import java.util.logging.Logger; 5 6 import javax.ws.rs.GET; 7 import javax.ws.rs.Path; 8 import javax.ws.rs.PathParam; 9 import javax.ws.rs.Produces; 10 import javax.ws.rs.core.MediaType; 11 12 import data.Node; 13 14 @Path("/status") 15 public class StatusService { 16 17 private static final Logger logger = Logger.getLogger(StatusService.class.getName()); 18 19 @GET 20 @Produces(MediaType.APPLICATION_JSON) 21 public Node getStatus(){ 22 23 List<Node> nodes = new ArrayList<Node>(); 24 Node node = new Node("001", "60800","192.168.1.1","0","92","92","chizhou","50ms","hw"); 25 Node nothingNode = new Node("null","null","null","null","null","null","null","null","null"); 26 //nodes.add(node); 27 nodes.add(node); 28 logger.info(node.getName()); 29 return node; 30 } 31 32 @Path("/{id}") 33 @GET 34 @Produces(MediaType.APPLICATION_JSON) 35 public Node getID(@PathParam("id") int id){ 36 List<Node> nodes = new ArrayList<Node>(); 37 38 nodes.add(new Node("null","null","null","null","null","null","null","null","null")); 39 nodes.add(new Node("001", "60600","192.168.1.1","0","92","92","tonglin","50ms","hw")); 40 nodes.add(new Node("002", "60600","192.168.1.1","0","92","92","tonglin","50ms","hw")); 41 nodes.add(new Node("003", "60600","192.168.1.1","0","92","92","tonglin","50ms","hw")); 42 nodes.add(new Node("004", "60600","192.168.1.1","0","92","92","tonglin","50ms","hw")); 43 nodes.add(new Node("005", "60600","192.168.1.1","0","92","92","tonglin","50ms","hw")); 44 45 int defaultIndex = 0; 46 if ( (id < 1) || (id > nodes.size() - 1) ){ 47 logger.info(nodes.get(defaultIndex).getId()); 48 return nodes.get(defaultIndex); 49 } 50 else{ 51 logger.info(nodes.get(id).getId()); 52 return nodes.get(id); 53 } 54 } 55 }
RestApplication.java
1 package helloworldosgi; 2 3 import java.util.HashSet; 4 import java.util.Set; 5 6 import javax.ws.rs.core.Application; 7 8 import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; 9 10 public class RestApplication extends Application { 11 12 @Override 13 public Set<Class<?>> getClasses() { 14 Set<Class<?>> result = new HashSet<Class<?>>(); 15 16 result.add(JacksonJsonProvider.class); 17 18 result.add(StatusService.class); 19 20 return result; 21 } 22 }
Node.java
1 package data; 2 3 import javax.xml.bind.annotation.XmlRootElement; 4 5 @XmlRootElement 6 public class Node { 7 8 private String id; 9 private String name; 10 private String admin_ip; 11 private String admin_status; 12 private String longitude; 13 private String latitude; 14 private String location; 15 private String latency; 16 private String vendor_name; 17 18 public Node(String id, 19 String name, 20 String admin_ip, 21 String admin_status, 22 String longitude, 23 String latitude, 24 String location, 25 String latency, 26 String vendor_name 27 ){ 28 this.id = id; 29 this.name = name; 30 this.admin_ip = admin_ip; 31 this.admin_status = admin_status; 32 this.longitude = longitude; 33 this.latitude = latitude; 34 this.location = location; 35 this.latency = latency; 36 this.vendor_name = vendor_name; 37 } 38 public String getId() { 39 return id; 40 } 41 42 public void setId(String id) { 43 this.id = id; 44 } 45 46 public String getName() { 47 return name; 48 } 49 50 public void setName(String name) { 51 this.name = name; 52 } 53 54 public String getAdmin_ip() { 55 return admin_ip; 56 } 57 58 public void setAdmin_ip(String admin_ip) { 59 this.admin_ip = admin_ip; 60 } 61 62 public String getAdmin_status() { 63 return admin_status; 64 } 65 66 public void setAdmin_status(String admin_status) { 67 this.admin_status = admin_status; 68 } 69 70 public String getLongitude() { 71 return longitude; 72 } 73 74 public void setLongitude(String longitude) { 75 this.longitude = longitude; 76 } 77 78 public String getLatitude() { 79 return latitude; 80 } 81 82 public void setLatitude(String latitude) { 83 this.latitude = latitude; 84 } 85 86 public String getLocation() { 87 return location; 88 } 89 90 public void setLocation(String location) { 91 this.location = location; 92 } 93 94 public String getLatency() { 95 return latency; 96 } 97 98 public void setLatency(String latency) { 99 this.latency = latency; 100 } 101 102 public String getVendor_name() { 103 return vendor_name; 104 } 105 106 public void setVendor_name(String vendor_name) { 107 this.vendor_name = vendor_name; 108 } 109 }
4.浏览器中输入 http://localhost:8080/rest/json/status 即可访问public Node getStatus() 返回值。
或者输入 http://localhost:8080/rest/json/status/2 即可访问public Node getID(@PathParam("id") int id)返回值。
关于@Path @Get @PathParam 参考 http://www.docin.com/p-317614298.html 第七页。
http://download.csdn.net/detail/kira_will/9729055