Jersey框架一:Jersey RESTful WebService框架简介

时间:2022-05-15 19:36:54

Jersey系列文章:

Jersey框架一:Jersey RESTful WebService框架简介

Jersey框架二:Jersey对JSON的支持

Jersey框架三:Jersey对HTTPS的支持

 

开发RESTful WebService意味着支持在多种媒体类型以及抽象底层的客户端-服务器通信细节,如果没有一个好的工具包可用,这将是一个困难的任务

为了简化使用Java开发RESTful WebService及其客户端,一个轻量级的标准被提出:JAX-RS API

Jersey RESTful WebService框架是一个开源的、产品级别的JAVA框架,支持JAX-RS API并且是一个JAX-RS(JSR 311和 JSR 339)的参考实现

Jersey不仅仅是一个JAX-RS的参考实现,Jersey提供自己的API,其API继承自JAX-RS,提供更多的特性和功能以进一步简化RESTful service和客户端的开发

 

Maven版本:3.1.0

Jersey版本:1.18

JDK版本:1.7.0_65

一,服务端

Maven配置如下:

[html] view plain copy
  1. <project xmlns="http://maven.apache.org/POM/4.0.0"   
  2.         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
  3.         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0   
  4.             http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  5.     <modelVersion>4.0.0</modelVersion>  
  6.     <groupId>JERSEY_SERVER</groupId>  
  7.     <artifactId>JERSEY_SERVER</artifactId>  
  8.     <version>1.0</version>  
  9.     <dependencies>  
  10.         <dependency>  
  11.             <groupId>com.sun.jersey</groupId>  
  12.             <artifactId>jersey-server</artifactId>  
  13.             <version>1.18</version>  
  14.         </dependency>  
  15.         <dependency>  
  16.             <groupId>com.sun.jersey</groupId>  
  17.             <artifactId>jersey-grizzly2</artifactId>  
  18.             <version>1.18</version>  
  19.         </dependency>  
  20.     </dependencies>  
  21. </project>  

首先介绍几个注解:

@Path

用来为资源类或方法定义URI,当然除了静态URI也支持动态URI

[java] view plain copy
  1. @Path("service")   
  2. public class MyResource {  
  3.     @Path("{sub_path}")  
  4.     @GET  
  5.     public String getResource(@PathParam("sub_path") String resourceName) {  
  6. ......  

如果此时客户端请求的URI为http://127.0.0.1:10000/service/sean,则sub_path的值为sean

@PathParam用来将请求URI的一部分作为方法参数传入方法中

对URI的动态部分,可以自定义校验正则表达式,如果请求参数校验失败,容器返回404 Not Found

[java] view plain copy Jersey框架一:Jersey RESTful WebService框架简介Jersey框架一:Jersey RESTful WebService框架简介
  1. @Path("{sub_path:[A-Z]*}")  

@GET

表明被注解的方法响应HTTP GET请求,@POST@PUT@DELETE同理

@Consumes

定义请求的媒体类型,如果不指定,则容器默认可接受任意媒体类型,容器负责确认被调用的方法可接受HTTP请求的媒体类型,否则返回415 Unsupported Media Type

方法级注解将覆盖类级注解

@Produces

定义响应媒体类型,如果不指定,则容器默认可接受任意媒体类型,容器负责确认被调用的方法可返回HTTP请求可以接受媒体类型,否则返回406 Not Acceptable

方法级注解将覆盖类级注解

@QueryParam

[java] view plain copy Jersey框架一:Jersey RESTful WebService框架简介Jersey框架一:Jersey RESTful WebService框架简介
  1. public String getResource(  
  2.         @DefaultValue("Just a test!"@QueryParam("desc") String description) {  
  3.     ......  
  4. }  

如果请求URI中包含desc参数,例如:http://127.0.0.1:10000/service/sean?desc=123456,则desc参数的值将会赋给方法的参数description,否则方法参数description的值将为@DefaultValue注解定义的默认值

@Context

将信息注入请求或响应相关的类,可注入的类有:Application,UriInfo,Request,HttpHeaders和SecurityContext

@Singleton@PerRequest

默认情况下,资源类的生命周期是per-request,也就是系统会为每个匹配资源类URI的请求创建一个实例,这样的效率很低,可以对资源类使用@Singleton注解,这样在应用范围内,只会创建资源类的一个实例

服务端程序如下:

[java] view plain copy
  1. package com.sean;  
  2.    
  3. import java.io.IOException;  
  4. import java.net.URI;  
  5. import java.util.Iterator;  
  6.   
  7. import javax.ws.rs.Consumes;  
  8. import javax.ws.rs.DefaultValue;  
  9. import javax.ws.rs.GET;  
  10. import javax.ws.rs.Path;  
  11. import javax.ws.rs.PathParam;  
  12. import javax.ws.rs.Produces;  
  13. import javax.ws.rs.QueryParam;  
  14. import javax.ws.rs.core.Context;  
  15. import javax.ws.rs.core.HttpHeaders;  
  16. import javax.ws.rs.core.MediaType;  
  17. import javax.ws.rs.core.MultivaluedMap;  
  18. import javax.ws.rs.core.Request;  
  19. import javax.ws.rs.core.UriBuilder;  
  20. import javax.ws.rs.core.UriInfo;  
  21.   
  22. import org.glassfish.grizzly.http.server.HttpServer;  
  23.   
  24. import com.sun.jersey.api.container.grizzly2.GrizzlyServerFactory;  
  25. import com.sun.jersey.api.core.PackagesResourceConfig;  
  26. import com.sun.jersey.api.core.ResourceConfig;  
  27. import com.sun.jersey.spi.resource.Singleton;  
  28.    
  29. @Singleton  
  30. @Path("service")   
  31. public class MyResource {  
  32.       
  33.     @Path("{sub_path:[a-zA-Z0-9]*}")  
  34.     @GET  
  35.     @Consumes({MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON})  
  36.     @Produces(MediaType.TEXT_PLAIN)  
  37.     public String getResourceName(  
  38.             @PathParam("sub_path") String resourceName,  
  39.             @DefaultValue("Just a test!"@QueryParam("desc") String description,  
  40.             @Context Request request,  
  41.             @Context UriInfo uriInfo,  
  42.             @Context HttpHeaders httpHeader) {  
  43.         System.out.println(this.hashCode());  
  44.   
  45. //      将HTTP请求打印出来  
  46.         System.out.println("****** HTTP request ******");  
  47.         StringBuilder strBuilder = new StringBuilder();  
  48.         strBuilder.append(request.getMethod() + " ");  
  49.         strBuilder.append(uriInfo.getRequestUri().toString() + " ");  
  50.         strBuilder.append("HTTP/1.1[\\r\\n]");  
  51.         System.out.println(strBuilder.toString());  
  52.         MultivaluedMap<String, String> headers = httpHeader.getRequestHeaders();  
  53.         Iterator<String> iterator = headers.keySet().iterator();  
  54.         while(iterator.hasNext()){  
  55.             String headName = iterator.next();  
  56.             System.out.println(headName + ":" + headers.get(headName) + "[\\r\\n]");  
  57.         }  
  58.         System.out.println("[\\r\\n]");  
  59.         String responseStr =resourceName + "[" + description + "]";  
  60.         return responseStr;  
  61.     }  
  62.       
  63.     public static void main(String[] args) {  
  64.         URI uri = UriBuilder.fromUri("http://127.0.0.1").port(10000).build();  
  65.         ResourceConfig rc = new PackagesResourceConfig("com.sean");  
  66.         try {  
  67.             HttpServer server = GrizzlyServerFactory.createHttpServer(uri, rc);  
  68.             server.start();  
  69.         } catch (IllegalArgumentException e) {  
  70.             e.printStackTrace();  
  71.         } catch (NullPointerException e) {  
  72.             e.printStackTrace();  
  73.         } catch (IOException e) {  
  74.             e.printStackTrace();  
  75.         }  
  76.         try {  
  77.             Thread.sleep(1000*1000);  
  78.         } catch (InterruptedException e) {  
  79.             e.printStackTrace();  
  80.         }  
  81.     }  
  82. }  

 

二,客户端

Maven配置如下:

[html] view plain copy
  1. <project xmlns="http://maven.apache.org/POM/4.0.0"   
  2.         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
  3.         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0   
  4.                 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  5.     <modelVersion>4.0.0</modelVersion>  
  6.     <groupId>JERSEY_CLIENT</groupId>  
  7.     <artifactId>JERSEY_CLIENT</artifactId>  
  8.     <version>1.0</version>  
  9.     <dependencies>          
  10.         <dependency>  
  11.             <groupId>com.sun.jersey</groupId>  
  12.             <artifactId>jersey-client</artifactId>  
  13.             <version>1.18</version>  
  14.         </dependency>  
  15.         <dependency>  
  16.             <groupId>com.sun.jersey</groupId>  
  17.             <artifactId>jersey-grizzly2</artifactId>  
  18.             <version>1.18</version>  
  19.         </dependency>  
  20.     </dependencies>  
  21. </project>  

客户端程序如下:

[java] view plain copy
  1. package com.sean;  
  2.   
  3. import java.net.URI;  
  4. import java.util.Iterator;  
  5.   
  6. import javax.ws.rs.core.MediaType;  
  7. import javax.ws.rs.core.MultivaluedMap;  
  8. import javax.ws.rs.core.UriBuilder;  
  9.   
  10. import com.sun.jersey.api.client.Client;  
  11. import com.sun.jersey.api.client.ClientResponse;  
  12. import com.sun.jersey.api.client.WebResource;  
  13. import com.sun.jersey.api.client.config.ClientConfig;  
  14. import com.sun.jersey.api.client.config.DefaultClientConfig;  
  15.   
  16. public class JerseyClient {  
  17.   
  18.     public static void main(String[] args) {  
  19. //      要使用Jersey Client API,必须首先创建Client的实例  
  20. //      有以下两种创建Client实例的方式  
  21.           
  22. //     方式一  
  23.         ClientConfig cc = new DefaultClientConfig();  
  24.         cc.getProperties().put(ClientConfig.PROPERTY_CONNECT_TIMEOUT, 10*1000);  
  25. //      Client实例很消耗系统资源,需要重用  
  26. //      创建web资源,创建请求,接受响应都是线程安全的  
  27. //      所以Client实例和WebResource实例可以在多个线程间安全的共享  
  28.         Client client = Client.create(cc);  
  29.           
  30. //      方式二  
  31. //      Client client = Client.create();  
  32. //      client.setConnectTimeout(10*1000);  
  33. //      client.getProperties().put(ClientConfig.PROPERTY_CONNECT_TIMEOUT, 10*1000);  
  34.           
  35. //      WebResource将会继承Client中timeout的配置  
  36.         WebResource resource = client.resource("http://127.0.0.1:10000/service/sean?desc=description");  
  37.           
  38.         String str = resource  
  39.                 .accept(MediaType.TEXT_PLAIN)  
  40.                 .type(MediaType.TEXT_PLAIN)  
  41.                 .get(String.class);  
  42.         System.out.println("String:" + str);  
  43.           
  44.         URI uri = UriBuilder.fromUri("http://127.0.0.1/service/sean").port(10000)  
  45.                 .queryParam("desc""description").build();  
  46.         resource = client.resource(uri);  
  47.           
  48.         //header方法可用来添加HTTP头  
  49.         ClientResponse response = resource.header("auth""123456")  
  50.                 .accept(MediaType.TEXT_PLAIN)  
  51.                 .type(MediaType.TEXT_PLAIN)  
  52.                 .get(ClientResponse.class);  
  53. //      将HTTP响应打印出来  
  54.         System.out.println("****** HTTP response ******");  
  55.         StringBuilder strBuilder = new StringBuilder();  
  56.         strBuilder.append("HTTP/1.1 ");  
  57.         strBuilder.append(response.getStatus() + " ");  
  58.         strBuilder.append(response.getStatusInfo() + "[\\r\\n]");  
  59.         System.out.println(strBuilder.toString());  
  60.         MultivaluedMap<String, String> headers = response.getHeaders();  
  61.         Iterator<String> iterator = headers.keySet().iterator();  
  62.         while(iterator.hasNext()){  
  63.             String headName = iterator.next();  
  64.             System.out.println(headName + ":" + headers.get(headName) + "[\\r\\n]");  
  65.         }  
  66.         System.out.println("[\\r\\n]");  
  67.         System.out.println(response.getEntity(String.class) + "[\\r\\n]");  
  68.     }  
  69. }  

 

服务端日志如下:

[plain] view plain copy
  1. 二月 06, 2015 4:33:33 下午 com.sun.jersey.api.core.PackagesResourceConfig init  
  2. INFO: Scanning for root resource and provider classes in the packages:  
  3.   com.sean  
  4. 二月 06, 2015 4:33:33 下午 com.sun.jersey.api.core.ScanningResourceConfig logClasses  
  5. INFO: Root resource classes found:  
  6.   class com.sean.Test  
  7.   class com.sean.MyResource  
  8. 二月 06, 2015 4:33:33 下午 com.sun.jersey.api.core.ScanningResourceConfig init  
  9. INFO: No provider classes found.  
  10. 二月 06, 2015 4:33:33 下午 com.sun.jersey.server.impl.application.WebApplicationImpl _initiate  
  11. INFO: Initiating Jersey application, version 'Jersey: 1.18 11/22/2013 01:21 AM'  
  12. 二月 06, 2015 4:33:34 下午 org.glassfish.grizzly.http.server.NetworkListener start  
  13. INFO: Started listener bound to [127.0.0.1:10000]  
  14. 二月 06, 2015 4:33:34 下午 org.glassfish.grizzly.http.server.HttpServer start  
  15. INFO: [HttpServer] Started.  
  16. 1814260800  
  17. ****** HTTP request ******  
  18. GET http://127.0.0.1:10000/service/sean?desc=description HTTP/1.1[\r\n]  
  19. accept:[text/plain][\r\n]  
  20. content-type:[text/plain][\r\n]  
  21. user-agent:[Java/1.7.0_65][\r\n]  
  22. host:[127.0.0.1:10000][\r\n]  
  23. connection:[keep-alive][\r\n]  
  24. [\r\n]  
  25. 1814260800  
  26. ****** HTTP request ******  
  27. GET http://127.0.0.1:10000/service/sean?desc=description HTTP/1.1[\r\n]  
  28. auth:[123456][\r\n]  
  29. accept:[text/plain][\r\n]  
  30. content-type:[text/plain][\r\n]  
  31. user-agent:[Java/1.7.0_65][\r\n]  
  32. host:[127.0.0.1:10000][\r\n]  
  33. connection:[keep-alive][\r\n]  
  34. [\r\n]  
Jersey框架一:Jersey RESTful WebService框架简介

客户端日志如下:

[plain] view plain copy
  1. String:sean[description]  
  2. ****** HTTP response ******  
  3. HTTP/1.1 200 OK[\r\n]  
  4. Transfer-Encoding:[chunked][\r\n]  
  5. Date:[Fri, 06 Feb 2015 08:33:38 GMT][\r\n]  
  6. Content-Type:[text/plain][\r\n]  
  7. [\r\n]  
  8. sean[description][\r\n]