Introduction
JAX-RS is a set of JAVA Implementation of the rest Service Specification, provides some annotation to a resource class, a pojojava class, encapsulated as web resources. Annotations include:
- @ Path: indicates the relative path of the Resource class or method.
- @ Get, @ put, @ post, @ Delete. The annotation method is the type of the HTTP request used.
- @ Produces: indicates the mime media type returned.
- @ Consumes: indicates the mime media type that can accept the request.
- @ Pathparam, @ queryparam, @ headerparam, @ cookieparam, @ matrixparam, @ formparam, respectively indicate that the parameters of the method come from different locations of the HTTP request. For example, @ pathparam comes from the URL path, @ queryparam is the URL query parameter, @ headerparam is the header information of the HTTP request, and @ cookieparam is the cookie of the HTTP request.
The current JAX-RS implementation includes:
- Apache cxf is an open-source Web Service Framework.
- Jersey, a reference implementation of the JAX-RS provided by Sun.
- Resteasy, JBoss implementation.
- Restlet, developed by Jerome louvel and Dave pawson, is the earliest rest framework that appeared prior to JAX-RS.
- Apache wink, an Apache Software Foundation incubator project, its service module implements JAX-RS specifications
(From: http://zh.wikipedia.org/wiki/JAX-RS)
Equipment
The tools used in this article include:
- Eclipse-jee-Helios
- Java-1.6.0_26
- Apache -- tomcat-6.0.30
- SoapUI-3.6
The external jar packages used are available (required and must be added to the Web container)
- Neethi-3.0.2.jar
- Jsr311-api-1.1.1.jar
- Cxf-bundle-2.6.0.jar
The external jar packages used are available (optional, when and only treated as an independent application runtime)
- Jetty-http-7.5.4.v20111024.jar
- Jetty-io-7.5.4.v20111024.jar
- Jetty-server-7.5.4.v20111024.jar
- Jetty-util-7.5.4.v20111024.jar
- Jetty-continuation-7.5.4.v20111024.jar
- Wsdl4j-1.6.2.jar
Preparation
(Example from: oreilly-restful Java with JAX-RS (12-2009) (atticaworkflow)
Create a project
In order to proceed smoothly, create a dynamic web project on Eclipse first. After the project directory that conforms to the war structure is created automatically, the file can be easily exported as a war file, put the following jar package
/Webcontent/WEB-INF/libIn:
- Neethi-3.0.2.jar
- Jsr311-api-1.1.1.jar
- Cxf-bundle-2.6.0.jar
In addition, in the project directory, create a new Lib folder to store the following optional jar packages:
- Jetty-http-7.5.4.v20111024.jar
- Jetty-io-7.5.4.v20111024.jar
- Jetty-server-7.5.4.v20111024.jar
- Jetty-util-7.5.4.v20111024.jar
- Jetty-continuation-7.5.4.v20111024.jar
- Wsdl4j-1.6.2.jar
The last step is to add all the nine jar files to the build path of the project, so that the project is ready.
Define Service
Here we need to implement a simple rest service for customer management, including:
- Create Customer
- View customer
- Update customer
First, provide the corresponding service interfaces for these operations:
Java code
- Import java. Io. inputstream;
- Import javax. ws. Rs. consumes;
- Import javax. ws. Rs. Get;
- Import javax. ws. Rs. post;
- Import javax. ws. Rs. Put;
- Import javax. ws. Rs. path;
- Import javax. ws. Rs. pathparam;
- Import javax. ws. Rs. Produces;
- Import javax. ws. Rs. Core. response;
- Import javax. ws. Rs. Core. streamingoutput;
- @ Path ("/customers ")
- Public interface customerresource {
- @ Post
- @ Consumes ("application/XML ")
- Public Response createcustomer (inputstream is );
- @ Get
- @ Path ("{ID }")
- @ Produces ("application/XML ")
- Public streamingoutput getcustomer (@ pathparam ("ID") int ID );
- @ Put
- @ Path ("{ID }")
- @ Consumes ("application/XML ")
- Public void updatecustomer (@ pathparam ("ID") int ID, inputstream is );
- }
Surprisingly, this interface already contains all the key parts for achieving our stated goals:
- @ Path: Defines the service path. The top-level path of the entire service defined in the interface is"/Mers MERs
", The Service path corresponding to the method is the path value defined by the interface path plus method. If not defined, the interface path is used. For example, the Service path of getcustomer () is :"
/Customers/{ID}". Therefore, the rest external service path isService context path/customers/
Sub-Level directory,
- @ Post, @ get, @ put: Types of HTTP requests supported by the annotation method (refer to the above description)
- @ Produces, @ consumes: The request MIME type supported or returned by the annotation method.
We can see that the conditions for each method to be called are as follows:
- Createconsumer ():The request HTTP method is post, the request MIME type is application/XML, and the Request Path is:
Context path/Mers MERs
- Getcustomer ():The HTTP Method of the request is get. The MIME type of the request is application/XML. The Request Path is:
Context path/customers/{ID}
Note: {ID} is the number of an existing (or nonexistent) customer.
- Updatecustomer ():The HTTP Method of the request is put; the MIME type of the request is application/XML; The Request Path:
Context path/customers/{ID}
Note: {ID} is the number of an existing (or nonexistent) customer.
A good implementation method is to separate the definition and implementation of the rest service. In this way, the code structure is concise and clear, and the implementation and modification of the service definition can be easily carried out in the future.
The following describes how to add an implementation:
Java code
- Public class customerresourceservice implements customerresource {
- Private Map <integer, Customer> customerdb = new concurrenthashmap <integer, Customer> ();
- Private atomicinteger idcounter = new atomicinteger ();
- Public Response createcustomer (inputstream is ){
- Customer customer = readcustomer (is );
- Customer. setid (idcounter. incrementandget ());
- Customerdb. Put (customer. GETID (), customer );
- System. Out. println ("created customer" + customer. GETID ());
- Return response. Created (URI. Create ("/Mers MERs/" + customer. GETID ()))
- . Build ();
- }
- Public streamingoutput getcustomer (int id ){
- Final customer = customerdb. Get (ID );
- If (customer = NULL ){
- Throw new webapplicationexception (response. Status. not_found );
- }
- Return new streamingoutput (){
- Public void write (outputstream) throws ioexception,
- Webapplicationexception {
- Outputcustomer (outputstream, customer );
- }
- };
- }
- Public void updatecustomer (int id, inputstream is ){
- Customer update = readcustomer (is );
- Customer current = customerdb. Get (ID );
- If (current = NULL)
- Throw new webapplicationexception (response. Status. not_found );
- Current. setfirstname (update. getfirstname ());
- Current. setlastname (update. getlastname ());
- Current. setstreet (update. getstreet ());
- Current. setstate (update. getstate ());
- Current. setzip (update. getzip ());
- Current. setcountry (update. getcountry ());
- }
- Protected void outputcustomer (outputstream OS, customer Cust)
- Throws ioexception {
- Printstream writer = new printstream (OS );
- Writer. println ("<customer ID = \" "+ Cust. GETID () +" \ "> ");
- Writer. println ("<first-name>" + Cust. getfirstname () + "</first-name> ");
- Writer. println ("<last-name>" + Cust. getlastname () + "</last-name> ");
- Writer. println ("<Street>" + Cust. getstreet () + "</street> ");
- Writer. println ("<city>" + Cust. getcity () + "</city> ");
- Writer. println ("<State>" + Cust. getstate () + "</State> ");
- Writer. println ("<zip>" + Cust. getzip () + "</zip> ");
- Writer. println ("<country>" + Cust. getcountry () + "</country> ");
- Writer. println ("</customer> ");
- }
- Protected customer readcustomer (inputstream is ){
- Try {
- Documentbuilder builder = documentbuilderfactory. newinstance ()
- . Newdocumentbuilder ();
- Document Doc = builder. parse (is );
- Element root = Doc. getdocumentelement ();
- Customer Cust = new customer ();
- If (root. getattribute ("ID ")! = NULL
- &&! Root. getattribute ("ID"). Trim (). Equals ("")){
- Cust. setid (integer. valueof (root. getattribute ("ID ")));
- }
- Nodelist nodes = root. getchildnodes ();
- For (INT I = 0; I <nodes. getlength (); I ++ ){
- Node item = nodes. item (I );
- If (! (Item instanceof element )){
- Continue;
- }
- Element element = (element) nodes. item (I );
- If (element. gettagname (). Equals ("first-name ")){
- Cust. setfirstname (element. gettextcontent ());
- } Else if (element. gettagname (). Equals ("last-name ")){
- Cust. setlastname (element. gettextcontent ());
- } Else if (element. gettagname (). Equals ("street ")){
- Cust. setstreet (element. gettextcontent ());
- } Else if (element. gettagname (). Equals ("city ")){
- Cust. setcity (element. gettextcontent ());
- } Else if (element. gettagname (). Equals ("state ")){
- Cust. setstate (element. gettextcontent ());
- } Else if (element. gettagname (). Equals ("Zip ")){
- Cust. setzip (element. gettextcontent ());
- } Else if (element. gettagname (). Equals ("country ")){
- Cust. setcountry (element. gettextcontent ());
- }
- }
- Return Cust;
- } Catch (exception e ){
- Throw new webapplicationexception (E, response. Status. bad_request );
- }
- }
- }
The implementation of these methods is very direct and I will not elaborate on it. However, note the following:
It is best not to include the definition of a service in the implementation, such as the @ path label and @ pathparam label. If you want to modify the definition, it is best to modify it in the interface; or, if you want to override an annotation of an interface method, the annotation definitions of all interfaces and methods must be rewritten, rather than modifying the changed ones.