• 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[\r\n]");  
            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) + "[\r\n]");  
            }  
            System.out.println("[\r\n]");  
            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() + "[\r\n]");  
            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) + "[\r\n]");  
            }  
            System.out.println("[\r\n]");  
            System.out.println(response.getEntity(String.class) + "[\r\n]");  
        }  
    }  

    服务端日志如下:

    二月 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[
    ]  
    accept:[text/plain][
    ]  
    content-type:[text/plain][
    ]  
    user-agent:[Java/1.7.0_65][
    ]  
    host:[127.0.0.1:10000][
    ]  
    connection:[keep-alive][
    ]  
    [
    ]  
    1814260800  
    ****** HTTP request ******  
    GET http://127.0.0.1:10000/service/sean?desc=description HTTP/1.1[
    ]  
    auth:[123456][
    ]  
    accept:[text/plain][
    ]  
    content-type:[text/plain][
    ]  
    user-agent:[Java/1.7.0_65][
    ]  
    host:[127.0.0.1:10000][
    ]  
    connection:[keep-alive][
    ]  
    [
    ]  

    客户端日志如下:

    String:sean[description]  
    ****** HTTP response ******  
    HTTP/1.1 200 OK[
    ]  
    Transfer-Encoding:[chunked][
    ]  
    Date:[Fri, 06 Feb 2015 08:33:38 GMT][
    ]  
    Content-Type:[text/plain][
    ]  
    [
    ]  
    sean[description][
    ]  
  • 相关阅读:
    mysql 数据库引擎
    dubbo 微服务
    spring 属性文件加载接口---PropertySourceLoader
    Shiro架构
    HTTP状态码
    Shiro 修改权限,刷新权限
    Consul 架构(译)
    Java EE平台介绍(译)
    Java SPI机制
    Otb_000_ElementUI 的 Drawer组件无法上下滚动没有滚动条
  • 原文地址:https://www.cnblogs.com/chen-lhx/p/6138495.html
Copyright © 2020-2023  润新知