Jersey框架一:Jersey RESTful WebService框架简介
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配置如下: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>JERSEY_SERVER</groupId> <artifactId>JERSEY_SERVER</artifactId> <version>1.0</version> <dependencies> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-server</artifactId> <version>1.18</version> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-grizzly2</artifactId> <version>1.18</version> </dependency> </dependencies> </project> 首先介绍几个注解: @Path 用来为资源类或方法定义URI,当然除了静态URI也支持动态URI @Path("service") public class MyResource { @Path("{sub_path}") @GET public String getResource(@PathParam("sub_path") String resourceName) { ...... 如果此时客户端请求的URI为http://127.0.0.1:10000/service/sean,则sub_path的值为sean @PathParam用来将请求URI的一部分作为方法参数传入方法中 对URI的动态部分,可以自定义校验正则表达式,如果请求参数校验失败,容器返回404 Not Found @Path("{sub_path:[A-Z]*}") @GET 表明被注解的方法响应HTTP GET请求,@POST、@PUT和@DELETE同理 @Consumes 定义请求的媒体类型,如果不指定,则容器默认可接受任意媒体类型,容器负责确认被调用的方法可接受HTTP请求的媒体类型,否则返回415 Unsupported Media Type 方法级注解将覆盖类级注解 @Produces 定义响应媒体类型,如果不指定,则容器默认可接受任意媒体类型,容器负责确认被调用的方法可返回HTTP请求可以接受媒体类型,否则返回406 Not Acceptable 方法级注解将覆盖类级注解 @QueryParam public String getResource( @DefaultValue("Just a test!") @QueryParam("desc") String description) { ...... } 如果请求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注解,这样在应用范围内,只会创建资源类的一个实例 服务端程序如下: package com.sean; import java.io.IOException; import java.net.URI; import java.util.Iterator; import javax.ws.rs.Consumes; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Request; import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriInfo; import org.glassfish.grizzly.http.server.HttpServer; import com.sun.jersey.api.container.grizzly2.GrizzlyServerFactory; import com.sun.jersey.api.core.PackagesResourceConfig; import com.sun.jersey.api.core.ResourceConfig; import com.sun.jersey.spi.resource.Singleton; @Singleton @Path("service") public class MyResource { @Path("{sub_path:[a-zA-Z0-9]*}") @GET @Consumes({MediaType.TEXT_PLAIN,MediaType.APPLICATION_JSON}) @Produces(MediaType.TEXT_PLAIN) public String getResourceName( @PathParam("sub_path") String resourceName,@DefaultValue("Just a test!") @QueryParam("desc") String description,@Context Request request,@Context UriInfo uriInfo,@Context HttpHeaders httpHeader) { System.out.println(this.hashCode()); // 将HTTP请求打印出来 System.out.println("****** HTTP request ******"); StringBuilder strBuilder = new StringBuilder(); strBuilder.append(request.getMethod() + " "); strBuilder.append(uriInfo.getRequestUri().toString() + " "); strBuilder.append("HTTP/1.1[rn]"); System.out.println(strBuilder.toString()); MultivaluedMap<String,String> headers = httpHeader.getRequestHeaders(); Iterator<String> iterator = headers.keySet().iterator(); while(iterator.hasNext()){ String headName = iterator.next(); System.out.println(headName + ":" + headers.get(headName) + "[rn]"); } System.out.println("[rn]"); String responseStr =resourceName + "[" + description + "]"; return responseStr; } public static void main(String[] args) { URI uri = UriBuilder.fromUri("http://127.0.0.1").port(10000).build(); ResourceConfig rc = new PackagesResourceConfig("com.sean"); try { HttpServer server = GrizzlyServerFactory.createHttpServer(uri,rc); server.start(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (NullPointerException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { Thread.sleep(1000*1000); } catch (InterruptedException e) { e.printStackTrace(); } } } ? 二,客户端 Maven配置如下: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>JERSEY_CLIENT</groupId> <artifactId>JERSEY_CLIENT</artifactId> <version>1.0</version> <dependencies> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-client</artifactId> <version>1.18</version> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-grizzly2</artifactId> <version>1.18</version> </dependency> </dependencies> </project> 客户端程序如下: package com.sean; import java.net.URI; import java.util.Iterator; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.UriBuilder; import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.WebResource; import com.sun.jersey.api.client.config.ClientConfig; import com.sun.jersey.api.client.config.DefaultClientConfig; public class JerseyClient { public static void main(String[] args) { // 要使用Jersey Client API,必须首先创建Client的实例 // 有以下两种创建Client实例的方式 // 方式一 ClientConfig cc = new DefaultClientConfig(); cc.getProperties().put(ClientConfig.PROPERTY_CONNECT_TIMEOUT,10*1000); // Client实例很消耗系统资源,需要重用 // 创建web资源,创建请求,接受响应都是线程安全的 // 所以Client实例和WebResource实例可以在多个线程间安全的共享 Client client = Client.create(cc); // 方式二 // Client client = Client.create(); // client.setConnectTimeout(10*1000); // client.getProperties().put(ClientConfig.PROPERTY_CONNECT_TIMEOUT,10*1000); // WebResource将会继承Client中timeout的配置 WebResource resource = client.resource("http://127.0.0.1:10000/service/sean?desc=description"); String str = resource .accept(MediaType.TEXT_PLAIN) .type(MediaType.TEXT_PLAIN) .get(String.class); System.out.println("String:" + str); URI uri = UriBuilder.fromUri("http://127.0.0.1/service/sean").port(10000) .queryParam("desc","description").build(); resource = client.resource(uri); //header方法可用来添加HTTP头 ClientResponse response = resource.header("auth","123456") .accept(MediaType.TEXT_PLAIN) .type(MediaType.TEXT_PLAIN) .get(ClientResponse.class); // 将HTTP响应打印出来 System.out.println("****** HTTP response ******"); StringBuilder strBuilder = new StringBuilder(); strBuilder.append("HTTP/1.1 "); strBuilder.append(response.getStatus() + " "); strBuilder.append(response.getStatusInfo() + "[rn]"); System.out.println(strBuilder.toString()); MultivaluedMap<String,String> headers = response.getHeaders(); Iterator<String> iterator = headers.keySet().iterator(); while(iterator.hasNext()){ String headName = iterator.next(); System.out.println(headName + ":" + headers.get(headName) + "[rn]"); } System.out.println("[rn]"); System.out.println(response.getEntity(String.class) + "[rn]"); } } ? 服务端日志如下: 二月 06,2015 4:33:33 下午 com.sun.jersey.api.core.PackagesResourceConfig init INFO: Scanning for root resource and provider classes in the packages: com.sean 二月 06,2015 4:33:33 下午 com.sun.jersey.api.core.ScanningResourceConfig logClasses INFO: Root resource classes found: class com.sean.Test class com.sean.MyResource 二月 06,2015 4:33:33 下午 com.sun.jersey.api.core.ScanningResourceConfig init INFO: No provider classes found. 二月 06,2015 4:33:33 下午 com.sun.jersey.server.impl.application.WebApplicationImpl _initiate INFO: Initiating Jersey application,version 'Jersey: 1.18 11/22/2013 01:21 AM' 二月 06,2015 4:33:34 下午 org.glassfish.grizzly.http.server.NetworkListener start INFO: Started listener bound to [127.0.0.1:10000] 二月 06,2015 4:33:34 下午 org.glassfish.grizzly.http.server.HttpServer start INFO: [HttpServer] Started. 1814260800 ****** HTTP request ****** GET http://127.0.0.1:10000/service/sean?desc=description HTTP/1.1[rn] accept:[text/plain][rn] content-type:[text/plain][rn] user-agent:[Java/1.7.0_65][rn] host:[127.0.0.1:10000][rn] connection:[keep-alive][rn] [rn] 1814260800 ****** HTTP request ****** GET http://127.0.0.1:10000/service/sean?desc=description HTTP/1.1[rn] auth:[123456][rn] accept:[text/plain][rn] content-type:[text/plain][rn] user-agent:[Java/1.7.0_65][rn] host:[127.0.0.1:10000][rn] connection:[keep-alive][rn] [rn] 客户端日志如下: String:sean[description] ****** HTTP response ****** HTTP/1.1 200 OK[rn] Transfer-Encoding:[chunked][rn] Date:[Fri,06 Feb 2015 08:33:38 GMT][rn] Content-Type:[text/plain][rn] [rn] sean[description][rn] (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |