Jersey框架一:Jersey RESTful WebService框架简介[通俗易懂]

📝 ✏️ 📌
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配置如下:

代码语言:javascript复制

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">

4.0.0

JERSEY_SERVER

JERSEY_SERVER

1.0

com.sun.jersey

jersey-server

1.18

com.sun.jersey

jersey-grizzly2

1.18

首先介绍几个注解:

@Path

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

代码语言:javascript复制@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

代码语言:javascript复制@Path("{sub_path:[A-Z]*}")@GET

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

@Consumes

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

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

@Produces

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

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

@QueryParam

代码语言:javascript复制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注解,这样在应用范围内,只会创建资源类的一个实例

服务端程序如下:

代码语言:javascript复制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 headers = httpHeader.getRequestHeaders();

Iterator 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配置如下:

代码语言:javascript复制

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">

4.0.0

JERSEY_CLIENT

JERSEY_CLIENT

1.0

com.sun.jersey

jersey-client

1.18

com.sun.jersey

jersey-grizzly2

1.18

客户端程序如下:

代码语言:javascript复制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 headers = response.getHeaders();

Iterator 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]");

}

}服务端日志如下:

代码语言:javascript复制二月 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[\r\n]

accept:[text/plain][\r\n]

content-type:[text/plain][\r\n]

user-agent:[Java/1.7.0_65][\r\n]

host:[127.0.0.1:10000][\r\n]

connection:[keep-alive][\r\n]

[\r\n]

1814260800

****** HTTP request ******

GET http://127.0.0.1:10000/service/sean?desc=description HTTP/1.1[\r\n]

auth:[123456][\r\n]

accept:[text/plain][\r\n]

content-type:[text/plain][\r\n]

user-agent:[Java/1.7.0_65][\r\n]

host:[127.0.0.1:10000][\r\n]

connection:[keep-alive][\r\n]

[\r\n]客户端日志如下:

代码语言:javascript复制String:sean[description]

****** HTTP response ******

HTTP/1.1 200 OK[\r\n]

Transfer-Encoding:[chunked][\r\n]

Date:[Fri, 06 Feb 2015 08:33:38 GMT][\r\n]

Content-Type:[text/plain][\r\n]

[\r\n]

sean[description][\r\n]版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/193313.html原文链接:https://javaforall.cn

🔗 相关推荐

✨ 💡 🎯
给你四个方块,你会想到什么?
beat365官方

给你四个方块,你会想到什么?

📅 09-02 👀 7862
Excel批量转换日期格式技巧
365买球怎么玩

Excel批量转换日期格式技巧

📅 09-24 👀 8392
2018世界杯冠军之夜奇门遁甲预测世界杯冠军法国vs克罗地亚