<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    gembin

    OSGi, Eclipse Equinox, ECF, Virgo, Gemini, Apache Felix, Karaf, Aires, Camel, Eclipse RCP

    HBase, Hadoop, ZooKeeper, Cassandra

    Flex4, AS3, Swiz framework, GraniteDS, BlazeDS etc.

    There is nothing that software can't fix. Unfortunately, there is also nothing that software can't completely fuck up. That gap is called talent.

    About Me

     

    Putting Java to REST

    from http://java.dzone.com/articles/putting-java-rest

    Last month I gave you an Introduction to REST. It was 100% theory, so now its time to see a little bit of REST in action. Since I am primarily a Java programmer, Part II of this series will focus on writing RESTFul Web services using the Java language. REST does not require a specific client or server-side framework in order to write your Web services. All you need is a client or server that supports the HTTP protocol. In Java land, servlets are a fine instrument for building your distributed apps, but can be a bit cumbersome and require a bunch of glue-code and XML configuration to get things going. So, about a year and a half ago, JSR-311, JAX-RS, was started at the JCP to provide an annotation-based framework to help you be more productive in writing RESTFul Web services. In this article, we'll implement various simple Web services using the JAX-RS specification.   

    A Simple JAX-RS Service

    JAX-RS uses Java annotations to map an incoming HTTP request to a Java method. This is not an RPC mechanism, but rather a way to easily access the parts of the HTTP request you are interested in without a lot of boilerplate code you'd have to write if you were using raw servlets. To use JAX-RS you annotate your class with the @Path annotation to indicate the relative URI path you are interested in, and then annotate one or more of your class's methods with @GET, @POST, @PUT, @DELETE, or @HEAD to indicate which HTTP method you want dispatched to a particular method.

    1.@Path("/orders")
    2.public class OrderEntryService {
    3.   @GET
    4.   public String getOrders() {...}
    5.}

    If we pointed our browser at http://somewhere.com/orders, JAX-RS would dispatch the HTTP request to the getOrders() method and we would get back whatever content the getOrders() method returned.

    JAX-RS has a very simple default component model. When you deploy a JAX-RS annotated class to the JAX-RS runtime, it will allocate OrderEntryService object to service one particular HTTP request, and throw away this object instance at the end of the HTTP response. This per-request model is very similar to stateless EJBs. Most JAX-RS implementations support Spring, EJB, and even JBoss Seam integration. I recommend you use one of those component models rather than the JAX-RS default model as it is very limited and you will quickly find yourself wishing you had used Spring, EJB, or Seam to build your services.

    Accessing Query Parameters

    One problem with the getOrders() method of our OrderEntryService class is that this method could possibly return thousands of orders in our system. It would be nice to be able to limit the size of the result set returned from the system. For this, the client could send a URI query parameter to specify how many results it wanted returned in the HTTP response, i.e. http://somewhere.com/orders?size=50. To extract this information from the HTTP request, JAX-RS has a @QueryParam annotation:

    01.@Path("/orders")
    02.public class OrderEntryService {
    03.   @GET
    04.   public String getOrders(@QueryParam("size")
    05.                           @DefaultValue("50") int size)
    06.   {
    07.     ... method body ...
    08.   }
    09.}

    The @QueryParam will automatically try and pull the "size" query parameter from the incoming URL and convert it to an integer. @QueryParam allows you to inject URL query parameters into any primitive type as well as any class that has a public static valueOf(String) method or a constructor that has one String parameter. The @DefaultValue annotation is an optional piece of metadata. What it does is tell the JAX-RS runtime that if the "size" URI query parameter is not provided by the client, inject the default value of "50".

    Other Parameter Annotations

    There are other parameter annotations like @HeaderParam, @CookieParam, and @FormParam that allow you to extract additional information from the HTTP request to inject into parameters of your Java method. While @HeaderParam and @CookieParam are pretty self explanatory, @FormParam allows you to pull in parameters from an application/x-www-formurlencoded request body (an HTML form). I'm not going to spend much time on them in this article as the behave pretty much in the same way as @QueryParam does.

    Path Parameters and @PathParam

    Our current OrderEntryService has limited usefulness. While getting access to all orders in our system is useful, many times we will have web service client that wants access to one particular order. We could write a new getOrder() method that used @QueryParam to specify which order we were interested in. This is not good RESTFul design as we are putting resource identity within a query parameter when it really belongs as part of the URI path itself. The JAX-RS specification provides the ability to define named path expressions with the @Path annotation and access those matched expressions using the @PathParam annotation. For example, let's implement a getOrder() method using this technique.

    1.@Path("/orders")
    2.public class OrderEntryService {
    3.   @GET
    4.   @Path("/{id}")
    5.   public String getOrder(@PathParam("id") int orderId) {
    6.     ... method body ...
    7.   }
    8.}

    The {id} string represents our path expression. What it initially means to JAX-RS is to match an incoming's request URI to any character other than '/'. For example http://somewhere.com/orders/3333 would dispatch to the getOrder() method, but http://somewhere.com/orders/3333/entries would not. The "id" string names the path expression so that it can be referenced and injected as a method parameter. This is exactly what we are doing in our getOrder() method. The @PathParam annotation will pull in the information from the incoming URI and inject it into the orderId parameter. For example, if our request is http://somewhere.com/orders/111, orderId would get the 111 value injected into it.

    More complex path expressions are also supported. For example, what if we wanted to make sure that id was an integer? We can use Java regular expressions in our path expression as follows:

    1.@Path("{id: \\d+}")

    Notice that a ':' character follows "id". This tells JAX-RS there is a Java regular expression that should be matched as part of the dispatching process.

    Content-Type

    Our getOrder() example, while functional, is incomplete. The String passed back from getOrder() could be any mime type: plain text, HTML, XML, JSON, YAML. Since we're exchanging HTTP messages, JAX-RS will set the response Content-Type to be the preferred mime type asked for by the client (for browsers its usually XML or HTML), and dump the raw bytes of the String to the response output stream.

    You can specify which mime type the method return type provides with the @Produces annotation. For example, let's say our getOrders() method actually returns an XML string.:

    01.@Path("/orders")
    02.public class OrderEntryService {
    03.   @GET
    04.   @Path("{id}")
    05.   @Produces("application/xml")
    06.   public String getOrder(@PathParm("id") int orderId)
    07.   {
    08.      ...
    09.   }
    10.}

    Using the @Produces annotation in this way would cause the Content-Type of the response to be set to "application/xml".

    Content Negotiation

    HTTP clients use the HTTP Accept header to specify a list of mime types they would prefer the server to return to them. For example, my Firefox browser sends this Accept header with every request:

    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

    The server should interpret this string as that the client prefers html or xhtml, but would accept raw XML second, and any other content type third. The mime type parameter "q" in our example identifies that "application/xml" is our 2nd choice and "*/*" (anything) is our third choice (1.0 is the default "q" value if "q" is not specified).

    JAX-RS understands the Accept header and will use it when dispatching to JAX-RS annotated methods. For example, let's add two new getOrder() methods that return HTML and JSON.

    01.@Path("/orders")
    02.public class OrderEntryService {
    03.   @GET
    04.   @Path("{id}")
    05.   @Produces("application/xml")
    06.   public String getOrder(@PathParm("id") int orderId)  {...}
    07. 
    08.   @GET
    09.   @Path("{id}")
    10.   @Produces("text/html")
    11.   public String getOrderHtml(@PathParm("id") int orderId) {...}
    12. 
    13.   @GET
    14.   @Path("{id}")
    15.   @Produces("application/json")
    16.   public String getOrderJson(@PathParm("id") int orderId) {...}
    17.}

    If we pointed our browser at our OrderEntryService, it would dispatch to the getOrderHtml() method as the browser prefers HTML. The Accept header and each method's @Produces annotation is used to determine which Java method to dispatch to.

    Content Marshalling

    Our getOrder() method is still incomplete. It still will have a bit of boilerplate code to convert a list of orders to an XML string that the client can consume. Luckily, JAX-RS allows you to write HTTP message body readers and writers that know how to marshall a specific Java type to and from a specific mime type. The JAX-RS specification has some required built-in marshallers. For instance, vendors are required to provide support for marshalling JAXB annotated classes (JBoss RESTEasy also has providers for JSON, YAML, and other mime types). Let's expand our example:

    01.@XmlRootElement(name="order")
    02.public class Order {
    03.   @XmlElement(name="id")
    04.   int id;
    05. 
    06.   @XmlElement(name="customer-id")
    07.   int customerId;
    08. 
    09.   @XmlElement("order-entries")
    10. 
    11.   List<OrderEntry> entries;
    12....
    13.}
    14. 
    15.@Path("/orders")
    16.public class OrderEntryService {
    17.   @GET
    18.   @Path("{id}")
    19.   @Produces("application/xml"
    20.   public Order getOrder(@PathParm("id") int orderId) {...}
    21.}

    JAX-RS will see that your Content-Type is application/xml and that the Order class has a JAXB annotation and will automatically using JAXB to write the Order object to the HTTP output stream. You can plug in and write your own marshallers using the MessageBodyReader and Writer interfaces, but we will not cover how to do this in this article.

    Response Codes and Custom Responses

    The HTTP specification defines what HTTP response codes should be on a successful request. For example, GET should return 200, OK and PUT should return 201, CREATED. You can expect JAX-RS to return the same default response codes.

    Sometimes, however, you need to specify your own response codes, or simply to add specific headers or cookies to your HTTP response. JAX-RS provides a Response class for this.

    01.@Path("/orders")
    02.public class OrderEntryService {
    03.   @GET
    04.   @Path("{id}")
    05.   public Response getOrder(@PathParm("id") int orderId)
    06.   {
    07.      Order order = ...;
    08.      ResponseBuilder builder = Response.ok(order);
    09.      builder.expires(...some date in the future);
    10.      return builder.build();
    11.   }
    12.}

    In this example, we still want to return a JAXB object with a 200 status code, but we want to add an Expires header to the response. You use the ResponseBuilder class to build up the response, and ResponseBuilder.build() to create the final Response instance.

    Exception Handling

    JAX-RS has a RuntimeException class, WebApplicationException, that allows you to abort your JAX-RS service method. It can take an HTTP status code or even a Response object as one of its constructor parameters. For example

    01.@Path("/orders")
    02.public class OrderEntryService {
    03.   @GET
    04.   @Path("{id}")
    05.   @Produces("application/xml")
    06.   public Order getOrder(@PathParm("id") int orderId) {
    07.      Order order = ...;
    08.      if (order == null) {
    09.         ResponseBuilder builder = Response.status(Status.NOT_FOUND);
    10.         builder.type("text/html");
    11.         builder.entity("<h3>Order Not Found</h3>");
    12.         throw new WebApplicationException(builder.build();
    13.      }
    14.      return order;
    15.   }
    16.}

    In this example, if the order is null, send a HTTP response code of NOT FOUND with a HTML encoded error message.

    Beyond WebApplicationException, you can map non-JAXRS exceptions that might be thrown by your application to a Response object by registering implementations of the ExceptionMapper class:

    1.public interface ExceptionMapper<E extends Throwable>
    2.{
    3.   Response toResponse(E exception);
    4.}

    For example, lets say we were using JPA to locate our Order objects. We could map javax.persistence.EntityNotFoundException to return a NOT FOUND status code.

    01.@Provider
    02.public class EntityNotFoundMapper
    03.    implements ExceptionMapper<EntityNotFoundException>
    04.{
    05.   Response toResponse(EntityNotFoundException exception)
    06.   {
    07.      return Response.status(Status.NOT_FOUND);
    08.   }
    09.}

    You register the ExceptionMapper using the Application deployment method that I'll show you in the next section.

    Deploying a JAX-RS Application

    Although the specification may expand on this before Java EE 6 goes final, it provides only one simple way of deploying your JAX-RS applications into a Java EE environment. First you must implement a javax.ws.rs.core.Application class.

    1.public abstract class Application
    2.{
    3.   public abstract Set<Class<?>> getClasses();
    4.   public Set<Object>getSingletons()
    5.}

    The getClasses() method returns a list of classes you want to deploy into the JAX-RS environment. They can be @Path annotated classes, in which case, you are specifying that you want to use the default per-request component model. These classes could also be a MessageBodyReader or Writer (which I didn't go into a lot of detail), or an ExceptionMapper. The getSingletons() method returns actual instances that you create yourself within the implementation of your Application class. You use this method when you want to have control over instance creation of your resource classes and providers. For example, maybe you are using Spring to instantiate your JAX-RS objects, or you want to register an EJB that uses JAX-RS annotations.

    You tell the JAX-RS runtime to use the class via a <context-param> within your WAR's web.xml file

    1.<context-param>
    2.      <param-name>javax.ws.rs.core.Application</param-name>
    3.      <param-value>com.smoke.MyApplicationConfig</param-value>
    4.</context-param>

    Other JAX-RS Features

    There's a bunch of JAX-RS features I didn't go into detail with or mention. There's a few helper classes for URI building and variant matching as well as classes for encapsulating HTTP specification concepts like Cache-Control. Download the specification and take a look at the Javadocs for more information on this stuff.

    Test Drive JAX-RS

    You can test drive JAX-RS through JBoss's JAX-RS implementation, RESTEasy available at http://jboss.org/resteasy.

    About the Author

    Bill Burke is an engineer and Fellow at JBoss, a division of Red Hat. He is JBoss's representative on JSR-311, JAX-RS and lead on JBoss's RESTEasy implementation.



    posted on 2009-07-10 17:38 gembin 閱讀(1139) 評論(0)  編輯  收藏


    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導航:
     

    導航

    統(tǒng)計

    常用鏈接

    留言簿(6)

    隨筆分類(440)

    隨筆檔案(378)

    文章檔案(6)

    新聞檔案(1)

    相冊

    收藏夾(9)

    Adobe

    Android

    AS3

    Blog-Links

    Build

    Design Pattern

    Eclipse

    Favorite Links

    Flickr

    Game Dev

    HBase

    Identity Management

    IT resources

    JEE

    Language

    OpenID

    OSGi

    SOA

    Version Control

    最新隨筆

    搜索

    積分與排名

    最新評論

    閱讀排行榜

    評論排行榜

    free counters
    主站蜘蛛池模板: 亚洲人成网站在线播放2019| 精品久久8x国产免费观看| 2020国产精品亚洲综合网| 国产亚洲精AA在线观看SEE| 午夜国产大片免费观看| jjizz全部免费看片| 久久精品乱子伦免费| 一区二区三区免费视频观看| MM1313亚洲国产精品| 亚洲国产成+人+综合| 亚洲短视频男人的影院| 亚洲日韩v无码中文字幕| 亚洲国产成人久久综合区| 午夜高清免费在线观看| 免费无码又黄又爽又刺激| 亚洲一区免费视频| 久久99国产乱子伦精品免费| 国产免费无码一区二区| 97在线免费观看视频| 国产免费伦精品一区二区三区| 无套内谢孕妇毛片免费看看| 国产精品亚洲专区无码唯爱网| 亚洲日韩精品无码专区加勒比☆| 亚洲欧洲春色校园另类小说| 亚洲综合精品香蕉久久网97| 亚洲Aⅴ无码专区在线观看q| 亚洲成AV人片在线观看ww| 亚洲狠狠婷婷综合久久久久| 亚洲精品自产拍在线观看| 亚洲av中文无码乱人伦在线播放| 亚洲乱码无码永久不卡在线| 亚洲国产一成人久久精品| 亚洲AV日韩精品久久久久| 久久亚洲精品成人AV| 亚洲精品人成电影网| 亚洲国产91在线| 亚洲字幕AV一区二区三区四区| 国产精品高清视亚洲一区二区| 亚洲国产欧美一区二区三区| 日韩亚洲翔田千里在线| 一级视频在线免费观看|