java-ee
जावा रेस्टफुल वेब सर्विसेज (JAX-RS)
खोज…
टिप्पणियों
SOAP और WS- स्टैक के विपरीत, जो W3C मानकों के रूप में निर्दिष्ट हैं, REST वास्तव में वेब-आधारित इंटरफ़ेस को डिज़ाइन करने और उपयोग करने के लिए सिद्धांतों का एक सेट है। REST / RESTful एप्लिकेशन अन्य मानकों पर बहुत अधिक निर्भर करते हैं:
HTTP
URI, URL
XML, JSON, HTML, GIF, JPEG, and so forth (resource representations)
JAX-RS (RESTful Web Services के लिए जावा एपीआई) की भूमिका RESTful सेवाओं के निर्माण में सहायता करने वाले API प्रदान करना है। हालाँकि, JAX-RS ऐसा करने का सिर्फ एक तरीका है । Restful सेवाओं को जावा में अन्य तरीकों से लागू किया जा सकता है, और (वास्तव में) कई अन्य प्रोग्रामिंग भाषाओं में।
सरल संसाधन
JAX-RS एप्लिकेशन के लिए सबसे पहले एक आधार URI निर्धारित किया जाना चाहिए, जहां से सभी संसाधन उपलब्ध होंगे। उस प्रयोजन के लिए javax.ws.rs.core.Application
class को javax.ws.rs.ApplicationPath
एनोटेशन के साथ विस्तारित और एनोटेट करना होगा। एनोटेशन एक स्ट्रिंग तर्क को स्वीकार करता है जो आधार URI को परिभाषित करता है।
@ApplicationPath(JaxRsActivator.ROOT_PATH)
public class JaxRsActivator extends Application {
/**
* JAX-RS root path.
*/
public static final String ROOT_PATH = "/api";
}
संसाधन सरल POJO वर्ग हैं जो @Path
एनोटेशन के साथ एनोटेट किए जाते हैं।
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
@Path("/hello")
public class HelloWorldResource {
public static final String MESSAGE = "Hello StackOverflow!";
@GET
@Produces("text/plain")
public String getHello() {
return MESSAGE;
}
}
जब एक HTTP GET
अनुरोध /hello
भेजा जाता है, तो संसाधन एक Hello StackOverflow!
साथ प्रतिक्रिया करता है Hello StackOverflow!
संदेश।
GET विधि प्रकार
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
@Path("/hello")
public class HelloWorldResource {
public static final String MESSAGE = "Hello World!";
@GET
@Produces("text/plain")
public String getHello() {
return MESSAGE;
}
@GET
@Path("/{letter}")
@Produces("text/plain")
public String getHelloLetter(@PathParam("letter") int letter){
if (letter >= 0 && letter < MESSAGE.length()) {
return MESSAGE.substring(letter, letter + 1);
} else {
return "";
}
}
}
बिना पैरामीटर के GET
सभी सामग्री ("हैलो वर्ल्ड!") देता है और पथ पैरामीटर के साथ GET
उस स्ट्रिंग में से विशिष्ट अक्षर देता है।
कुछ उदाहरण:
$ curl http://localhost/hello Hello World!
$ curl http://localhost/hello/0 H
$ curl http://localhost/hello/4 o
नोट: यदि आप विधि-प्रकार एनोटेशन (जैसे @GET
ऊपर) @GET
हैं, तो GET अनुरोध हैंडलर होने के लिए एक अनुरोध विधि चूक जाती है।
DELETE विधि
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
@Path("hello")
public class HelloWorldResource {
private String message = "Hello StackOverflow!";
@GET
@Produces("text/plain")
public String getHello() {
return message;
}
@DELETE
public Response deleteMessage() {
message = null;
return Response.noContent().build();
}
}
इसे कर्ल के साथ सेवन करें:
$ curl http://localhost/hello
Hello StackOverflow!
$ curl -X "DELETE" http://localhost/hello
$ curl http://localhost/hello
null
पोस्ट विधि
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
@Path("hello")
public class HelloWorldResource {
@POST
@Path("/receiveParams")
public Response receiveHello(@FormParam("name") String name, @FormParam("message") String message) {
//process parameters
return Response.status(200).build();
}
@POST
@Path("/saveObject")
@Consumes("application/json")
public Response saveMessage(Message message) {
//process message json
return Response.status(200).entity("OK").build();
}
}
पहले तरीके को कैप्चर किए गए इनपुट मापदंडों को भेजकर HTML फॉर्म जमा के माध्यम से लागू किया जा सकता है। फॉर्म जमा करने की कार्रवाई को इंगित करना चाहिए -
/hello/receiveParams
दूसरी विधि के लिए संदेश POJO को गेटर्स / सेटर की आवश्यकता होती है। कोई भी ग्राहक JSON इनपुट के साथ इस विधि को कॉल कर सकता है -
{"sender":"someone","message":"Hello SO!"}
POJO के पास वैसी ही संपत्ति होनी चाहिए जैसे कि क्रमिक कार्य करने के लिए JSON की है।
public class Message {
String sender;
String message;
public String getSender() {
return sender;
}
public void setSender(String sender) {
this.sender = sender;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
अपवाद मैपर
@Provider
public class IllegalArgumentExceptionMapper implements ExceptionMapper<IllegalArgumentException> {
@Override
public Response toResponse(IllegalArgumentException exception) {
return Response.serverError().entity("Invalid input: " + exception.getMessage()).build();
}
}
यह अपवाद मैपर एप्लिकेशन में फेंके गए सभी IllegalArgumentException को पकड़ लेगा, और उपयोगकर्ता को स्टैट्रेस के बजाय एक स्पष्ट संदेश दिखाएगा।
UriInfo
ताकि आपके संसाधन का उपयोग करने के लिए इस्तेमाल उपयोगकर्ता एजेंट यूआरआई के बारे में जानकारी पाने के लिए, आप उपयोग कर सकते @Context
एक साथ पैरामीटर एनोटेशन UriInfo
पैरामीटर। UriInfo
ऑब्जेक्ट में कुछ विधियाँ हैं जिनका उपयोग URI के विभिन्न भागों को प्राप्त करने के लिए किया जा सकता है।
//server is running on https://localhost:8080,
// webapp is at /webapp, servlet at /webapp/servlet
@Path("class")
class Foo {
@GET
@Path("resource")
@Produces(MediaType.TEXT_PLAIN)
public Response getResource(@Context UriInfo uriInfo) {
StringBuilder sb = new StringBuilder();
sb.append("Path: " + uriInfo.getPath() + "\n");
sb.append("Absolute Path: " + uriInfo.getAbsolutePath() + "\n");
sb.append("Base URI: " + uriInfo.getBaseUri() + "\n");
sb.append("Request URI: " + uriInfo.getRequestUri() + "\n");
return Response.ok(sb.toString()).build();
}
}
https://localhost:8080/webapp/servlet/class/resource
:
Path: class/resource
Absolute Path: https://localhost:8080/webapp/servlet/class/resource#
Base URI: https://localhost:8080/webapp/servlet/
Request URI: https://localhost:8080/webapp/servlet/class/resource
SubResources
कभी-कभी संगठनात्मक या अन्य कारणों से यह समझ में आता है कि आपके शीर्ष स्तर का संसाधन एक उप-संसाधन लौटाता है जो इस तरह दिखेगा। (आपके उप-संसाधन को आंतरिक वर्ग होने की आवश्यकता नहीं है)
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
@Path("items")
public class ItemsResource {
@Path("{id}")
public String item(@PathParam("id") String id) {
return new ItemSubResource(id);
}
public static class ItemSubResource {
private final String id;
public ItemSubResource(String id) {
this.id = id;
}
@GET
@Produces("text/plain")
public Item item() {
return "The item " + id;
}
}
}
कस्टम पैरामीटर कन्वर्टर्स
यह एक उदाहरण है कि JAX-RS समापन बिंदु के लिए कस्टम पैरामीटर कन्वर्टर्स को कैसे लागू किया जाए। उदाहरण जावा 8 के java.time
लाइब्रेरी से दो कक्षाएं java.time
है।
@Provider
public class ParamConverters implements ParamConverterProvider {
@Override
public <T> ParamConverter<T> getConverter(Class<T> rawType,
Type genericType,
Annotation[] annotations)
{
if (rawType == LocalDate.class)
return (ParamConverter<T>) new ParamConverter<LocalDate>() {
@Override
public LocalDate fromString(String value) {
return LocalDate.parse(value);
}
@Override
public String toString(LocalDate value) {
return null;
}
};
else if (rawType == MonthDay.class)
return (ParamConverter<T>) new ParamConverter<MonthDay>() {
@Override
public MonthDay fromString(String value) {
int[] ddmm = Arrays.stream(value.split("/"))
.mapToInt(Integer::parseInt)
.toArray();
return MonthDay.of(ddmm[1], ddmm[0]);
}
@Override
public String toString(MonthDay value) {
return null;
}
};
return null;
}
}
नाम बंधन
नाम बाइंडिंग एक अवधारणा है जो JAX-RS रनटाइम से यह कहने की अनुमति देता है कि एक विशिष्ट फ़िल्टर या इंटरसेप्टर को केवल एक विशिष्ट संसाधन विधि के लिए निष्पादित किया जाएगा। जब कोई फ़िल्टर या इंटरसेप्टर केवल एक विशिष्ट संसाधन विधि तक सीमित होता है, तो हम कहते हैं कि यह नाम-बाध्य है । फिल्टर और इंटरसेप्टर जिनके पास ऐसी कोई सीमा नहीं है, उन्हें वैश्विक कहा जाता है।
एक नाम बंधन एनोटेशन को परिभाषित करना
फिल्टर या इंटरसेप्टर को @NameBinding
एनोटेशन का उपयोग करके संसाधन विधि को सौंपा जा सकता है। इस एनोटेशन का उपयोग किसी अन्य उपयोगकर्ता द्वारा लागू एनोटेशन के लिए मेटा एनोटेशन के रूप में किया जाता है जो प्रदाताओं और संसाधन विधियों पर लागू होते हैं। निम्नलिखित उदाहरण देखें:
@NameBinding
@Retention(RetentionPolicy.RUNTIME)
public @interface Compress {}
ऊपर दिया गया उदाहरण एक नया @Compress
एनोटेशन को परिभाषित करता है जो एक नाम बाइंडिंग एनोटेशन है क्योंकि यह @NameBinding
साथ एनोटेट किया @NameBinding
। @Compress
एनोटेशन का उपयोग फिल्टर और इंटरसेप्टर को एंडपॉइंट्स को बांधने के लिए किया जा सकता है।
एक समापन बिंदु के लिए एक फिल्टर या इंटरसेप्टर बांधना
विचार करें कि आपके पास एक इंटरसेप्टर है जो GZIP संपीड़न करता है और आप इस तरह के इंटरसेप्टर को एक संसाधन विधि से बांधना चाहते हैं। इसे करने के लिए, संसाधन विधि और इंटरसेप्टर दोनों को एनोटेट करें, निम्नानुसार:
@Compress
public class GZIPWriterInterceptor implements WriterInterceptor {
@Override
public void aroundWriteTo(WriterInterceptorContext context)
throws IOException, WebApplicationException {
final OutputStream outputStream = context.getOutputStream();
context.setOutputStream(new GZIPOutputStream(outputStream));
context.proceed();
}
}
@Path("helloworld")
public class HelloWorldResource {
@GET
@Produces("text/plain")
public String getHello() {
return "Hello World!";
}
@GET
@Path("too-much-data")
@Compress
public String getVeryLongString() {
String str = ... // very long string
return str;
}
}
@Compress
संसाधन विधि getVeryLongString()
और इंटरसेप्टर GZIPWriterInterceptor
पर लागू किया जाता है। इंटरसेप्टर को केवल तभी निष्पादित किया जाएगा जब इस तरह के एनोटेशन के साथ कोई संसाधन विधि निष्पादित की जाएगी।
उपरोक्त उदाहरण में, इंटरसेप्टर को केवल getVeryLongString()
पद्धति के लिए निष्पादित किया जाएगा। विधि getHello()
लिए इंटरसेप्टर को निष्पादित नहीं किया जाएगा। इस उदाहरण में कारण शायद स्पष्ट है। हम केवल लंबे डेटा को संपीड़ित करना चाहते हैं और हमें "Hello World!"
की संक्षिप्त प्रतिक्रिया को संपीड़ित करने की आवश्यकता नहीं है "Hello World!"
।
नाम बंधन संसाधन वर्ग पर लागू किया जा सकता है। उदाहरण में HelloWorldResource
को @Compress
साथ एनोटेट किया @Compress
। इसका मतलब यह होगा कि सभी संसाधन विधियां इस मामले में संपीड़न का उपयोग करेंगी।
ध्यान दें कि वैश्विक फ़िल्टर हमेशा निष्पादित होते हैं, यहां तक कि संसाधन विधियों के लिए जिनके पास कोई भी नाम बाध्यकारी एनोटेशन हैं।