您的位置:首页 > 其它

使用Jersey创建RESTful风格的WebService

2016-03-03 17:51 447 查看

什么是RESTful架构

每一个URI代表一种资源

客户端和服务端之间传递这种资源的某种表现层(“资源”具体呈现出来的形式叫做它的“表现层”。)

对于资源的具体操作,由HTTP动词表示。客户端通过HTTP动词(GET,POST,PUT,DELETE)对服务端资源进行操作,实现表现层状态转换

JAX-RS annotations

AnnotationDescription
@PATH(your_path)Sets the path to base URL + /your_path. The base URL is based on your application name, the servlet and the URL pattern from the web.xml configuration file.
@POSTIndicates that the following method will answer to an HTTP POST request.
@GETIndicates that the following method will answer to an HTTP GET request.
@PUTIndicates that the following method will answer to an HTTP PUT request.
@DELETEIndicates that the following method will answer to an HTTP DELETE request.
@Produces(MediaType.TEXT_PLAIN[, more-types])@Produces defines which MIME type is delivered by a method annotated with @GET. In the example text (“text/plain”) is produced. Other examples would be “application/xml” or “application/json”.
@Consumes(type[, more-types])@Consumes defines which MIME type is consumed by this method.
@PathParamUsed to inject values from the URL into a method parameter. This way you inject, for example, the ID of a resource into the method to get the correct object.
@DefaultValue设置@QueryParam参数的默认值,如: @DefaultValue(“2”) @QueryParam(“step”) int step
@Context解释上下文参数
首先看一个简单例子:

服务端:

//'启动服务器
public class Test {
//服务器路径
public static final String BASE_URI="http://localhost:8080/myapp";
final static ResourceConfig rc = new ResourceConfig().packages("com.chm.test");
public static HttpServer startServer()
{
HttpServer server = GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);//URI.create(BASE_URI), rc
return server;
}

public static void main(String[] args) throws Exception {
//      final HttpServer server = startServer();
//       final HashMap<String, String> initParams = new HashMap<String, String>();
//
//       initParams.put("jersey.config.server.provider.packages", "com.chm.test");//packages定义了Jersey寻找服务类的位置。 它必须指向定义的资源类。

System.out.println("Starting grizzly...");
//       HttpServer server = GrizzlyWebContainerFactory.create(BASE_URI, initParams);

HttpServer server = startServer();

System.out.println(String.format("jersey app started" ));
System.in.read();

server.shutdown();

System.exit(0);
}
}
//资源类
@Path("/user")
public class User {

//  @GET
////    @Path("/{id}")
////    @Produces(MediaType.TEXT_PLAIN)
//  @Produces(MediaType.APPLICATION_JSON)
//  public String sayHello(@Context HttpServletRequest request)
//  {
//      String age = request.getHeader("contentType");
//      System.out.println(age);
//      Map<String, String> map = new HashMap<String, String>();
////        System.out.println("hello");
//      map.put("aa", "zhangsan");
//      map.put("bb", "lisi");
//      String str = "{\"name\":\"zhangsan\",\"age\":24}";
////        System.out.println(id);
//      return str;
//  }
@GET
public String get(@Context UriInfo ui) {
MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
List<String> age = queryParams.get("age");
System.out.println(age);
MultivaluedMap<String, String> pathParams = ui.getPathParameters();
return "success";
}
@PUT
@Path("{chm}")
@Produces(MediaType.TEXT_PLAIN)

public String update(@PathParam("chm") String name, String hello)
{
System.out.println(hello);
System.out.println(name);
return "put invoke";
}

@POST
@Path("f")
public String postFile(final File file)
{
String result = "";
try
{
BufferedReader br = new BufferedReader(new FileReader(file));
return result = br.readLine();

}catch(Exception ex)
{
ex.printStackTrace();
}
return result;
}

}
//客户端
public class ClientTest {

public static void main(String[] args) {
//      HttpServer server  = Test.startServer();
//可以有多个过滤器
final Client client = ClientBuilder.newClient();
//      client.register(Filter.class);
//      WebTarget target = client.target(Test.BASE_URI);
//      Entity<String> entity = Entity.entity("secrety", MediaType.TEXT_PLAIN);
//      Response resp = target.path("/user?age=26;addr=ah").request().get();//
//      System.out.println(resp.getStatus());
//      resp.readEntity(String.class);
//      System.out.println(resp.hasEntity());
//      String str = resp.readEntity(String.class);
//      System.out.println(str);
//      Form form = new Form();
//      form.param("x", "y");

WebTarget target = client.target("http://localhost:8080/jersey/rest/hello");
Entity<String> entity = Entity.entity("<MyBean><anyString>Hello World!</anyString><anyNumber>42</anyNumber></MyBean>", MediaType.TEXT_HTML_TYPE);
Response resp = target.request().post(entity);
resp.close();

//      target.path("/hello/charming").request().put(entity, String.class);

//      String path = System.getProperty("user.dir")+"/src/test.txt";
//      System.out.println(path);
//      File f = new File(path);
//      Entity<File> e = Entity.entity(f, MediaType.TEXT_PLAIN_TYPE);
//      String str1 = target.path("/user/f").request().post(e, String.class);
//      System.out.println(str1);
//
}
}


资源的生命周期

如下所示的例子

import javax.inject.Singleton;

@Path("/item")
public class ItemResource {
@Path("content")
public Class<ItemContentSingletonResource> getItemContentResource() {
return ItemContentSingletonResource.class;
}
}

@Singleton
public class ItemContentSingletonResource {
// this class is managed in the singleton life cycle
}


JAX-RS resources are managed in per-request scope by default which means that new resource is created for each request. In this example the javax.inject.Singleton annotation says that the resource will be managed as singleton and not in request scope. The sub-resource locator method returns a class which means that the runtime will managed the resource instance and its life-cycle. If the method would return instance instead, the Singleton annotation would have no effect and the returned instance would be used.

我们来看看 Resource scopes

scopeAnnotationAnnotation full class nameDescription
Request scope@RequestScoped (or none)org.glassfish.jersey.process.internal.RequestScopedDefault lifecycle (applied when no annotation is present). In this scope the resource instance is created for each new request and used for processing of this request. If the resource is used more than one time in the request processing, always the same instance will be used. This can happen when a resource is a sub resource is returned more times during the matching. In this situation only on instance will server the requests.
Per-lookup scope@PerLookuporg.glassfish.hk2.api.PerLookupIn this scope the resource instance is created every time it is needed for the processing even it handles the same request.
Singleton@Singletonjavax.inject.SingletonIn this scope there is only one instance per jax-rs application. Singleton resource can be either annotated with @Singleton and its class can be registered using the instance of Application. You can also create singletons by registering singleton instances into Application.

典型的设计误区

URI包含动词。“资源”是一种实体,应该是名词。URI不应该有动词,动词放在HTTP协议中。

URI中加入版本号。

例如

http://www.example.com/app/1.0/foo

http://www.example.com/app/1.1/foo

http://www.example.com/app/2.0/foo

不同的版本可以理解为同一种资源的不同表现形式,所以应该用同一个URI,版本号可以在HTTP请求头信息中的Accept字段中区分:

Accept: vnd.example-com.foo+json; version=1.0

Accept: vnd.example-com.foo+json; version=1.1

Accept: vnd.example-com.foo+json; version=2.0
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: