JAX-RS入门 一 :基础

来源:互联网 发布:联通软件研究院怎么样 编辑:程序博客网 时间:2024/04/30 06:15
博客分类:

 

简介

JAX-RS是一套用java实现REST服务的规范,提供了一些标注将一个资源类,一个POJOJava类,封装为Web资源。标注包括:

  • @Path,标注资源类或方法的相对路径
  • @GET,@PUT,@POST,@DELETE,标注方法是用的HTTP请求的类型
  • @Produces,标注返回的MIME媒体类型
  • @Consumes,标注可接受请求的MIME媒体类型
  • @PathParam,@QueryParam,@HeaderParam,@CookieParam,@MatrixParam,@FormParam,分别标注方法的参数来自于HTTP请求的不同位置,例如@PathParam来自于URL的路径,@QueryParam来自于URL的查询参数,@HeaderParam来自于HTTP请求的头信息,@CookieParam来自于HTTP请求的Cookie。

目前JAX-RS的实现包括:

  • Apache CXF,开源的Web服务框架。
  • Jersey, 由Sun提供的JAX-RS的参考实现。
  • RESTEasy,JBoss的实现。
  • Restlet,由Jerome Louvel和Dave Pawson开发,是最早的REST框架,先于JAX-RS出现。
  • Apache Wink,一个Apache软件基金会孵化器中的项目,其服务模块实现JAX-RS规范

(以上来自:http://zh.wikipedia.org/wiki/JAX-RS)

 

装备

本文使用的工具有:

  • Eclipse-jee-helios
  • Java-1.6.0_26
  • apache-tomcat-6.0.30
  • SoapUI-3.6

使用到的外部jar包有(必须的部分,需要加到Web容器中)

  • neethi-3.0.2.jar
  • jsr311-api-1.1.1.jar
  • cxf-bundle-2.6.0.jar

使用到的外部jar包有(可选的部分,当且仅当作为一个独立的application运行时)

  • 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

 准备

 (以下例子来自: Oreilly - RESTful Java with JAX-RS (12-2009) (ATTiCA).pdf)

 

创建工程

为了后续顺利进行,首先在eclipse上先创建一个Dynamic Web Project,完成以后,一个符合war结构的工程目录会自动生成,之后可以很简单的导出为war文件,其中需要把以下jar包放到/WebContent/WEB-INF/lib 里:

  • neethi-3.0.2.jar
  • jsr311-api-1.1.1.jar
  • cxf-bundle-2.6.0.jar 

另外,在工程目录下,新建一个 lib 文件夹用来存放以下可选的jar包:

 

  • 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

最后一步就是把所有这9个jar都加到工程的build path里去,这样工程就准备好了。

 

定义服务

这里要实现一个简单的REST服务用于对客户进行管理,包括:

  • 创建客户
  • 查看客户
  • 更新客户

首先给出对应的于这些操作的服务接口:

Java代码  收藏代码
  1. import java.io.InputStream;  
  2.   
  3. import javax.ws.rs.Consumes;  
  4. import javax.ws.rs.GET;  
  5. import javax.ws.rs.POST;  
  6. import javax.ws.rs.PUT;  
  7. import javax.ws.rs.Path;  
  8. import javax.ws.rs.PathParam;  
  9. import javax.ws.rs.Produces;  
  10. import javax.ws.rs.core.Response;  
  11. import javax.ws.rs.core.StreamingOutput;  
  12.   
  13. @Path("/customers")  
  14. public interface CustomerResource {  
  15.   
  16.     @POST  
  17.     @Consumes("application/xml")  
  18.     public Response createCustomer(InputStream is);  
  19.   
  20.     @GET  
  21.     @Path("{id}")  
  22.     @Produces("application/xml")  
  23.     public StreamingOutput getCustomer(@PathParam("id"int id);  
  24.   
  25.     @PUT  
  26.     @Path("{id}")  
  27.     @Consumes("application/xml")  
  28.     public void updateCustomer(@PathParam("id"int id, InputStream is) ;  
  29. }  

 

 令人惊奇的是,这个接口已经包含了所有实现我们既定目标的关键部分:

  1. @Path: 定义服务路径,接口中定义的整个服务的顶级路径为"/customers",方法对应的服务路径为接口路径加方法定义的Path值,如果未定义,则用接口路径,例如getCustomer()的服务路径为:" /customers/{id} "。所以此REST对外服务路径都是 服务的上下文路径/customers/子级目录,
  2. @POST,@GET,@PUT:标注方法所支持HTTP请求的类型 (参考上面的说明)
  3. @Produces,@Consumes:标注方法支持或返回的请求MIME类型。

由上可以看到,每个方法被调用的条件如下:

  1. createConsumer(): 请求HTTP方法为POST;请求MIME类型为application/xml;请求路径为:上下文路径/customers
  2. getCustomer(): 请求的HTTP方法为GET;请求的MIME类型为application/xml;请求的路径为:上下文路径/customers/{id}
    注: {id}为某个存在(或不存在)customer的编号
  3. updateCustomer(): 请求的HTTP方法为PUT;请求的MIME类型为application/xml;请求的路径:上下文路径/customers/{id}
    注: {id}为某个存在(或不存在)customer的编号

一个好的实现方法是将REST服务的定义和实现分开,这样代码的结构简洁、清晰,在后期也可以很方便的进行实现的替换和服务定义的修改。

 

下面就是添加实现部分:

Java代码  收藏代码
  1. public class CustomerResourceService implements CustomerResource{  
  2.     private Map<Integer, Customer> customerDB = new ConcurrentHashMap<Integer, Customer>();  
  3.     private AtomicInteger idCounter = new AtomicInteger();  
  4.   
  5.     public Response createCustomer(InputStream is) {  
  6.         Customer customer = readCustomer(is);  
  7.         customer.setId(idCounter.incrementAndGet());  
  8.         customerDB.put(customer.getId(), customer);  
  9.         System.out.println("Created customer " + customer.getId());  
  10.         return Response.created(URI.create("/customers/" + customer.getId()))  
  11.                 .build();  
  12.     }  
  13.   
  14.     public StreamingOutput getCustomer(int id) {  
  15.         final Customer customer = customerDB.get(id);  
  16.         if (customer == null) {  
  17.             throw new WebApplicationException(Response.Status.NOT_FOUND);  
  18.         }  
  19.         return new StreamingOutput() {  
  20.             public void write(OutputStream outputStream) throws IOException,  
  21.                     WebApplicationException {  
  22.                 outputCustomer(outputStream, customer);  
  23.             }  
  24.         };  
  25.     }  
  26.   
  27.     public void updateCustomer(int id, InputStream is) {  
  28.         Customer update = readCustomer(is);  
  29.         Customer current = customerDB.get(id);  
  30.         if (current == null)  
  31.             throw new WebApplicationException(Response.Status.NOT_FOUND);  
  32.         current.setFirstName(update.getFirstName());  
  33.         current.setLastName(update.getLastName());  
  34.         current.setStreet(update.getStreet());  
  35.         current.setState(update.getState());  
  36.         current.setZip(update.getZip());  
  37.         current.setCountry(update.getCountry());  
  38.     }  
  39.   
  40.     protected void outputCustomer(OutputStream os, Customer cust)  
  41.             throws IOException {  
  42.         PrintStream writer = new PrintStream(os);  
  43.         writer.println("<customer id=\"" + cust.getId() + "\">");  
  44.         writer.println(" <first-name>" + cust.getFirstName() + "</first-name>");  
  45.         writer.println(" <last-name>" + cust.getLastName() + "</last-name>");  
  46.         writer.println(" <street>" + cust.getStreet() + "</street>");  
  47.         writer.println(" <city>" + cust.getCity() + "</city>");  
  48.         writer.println(" <state>" + cust.getState() + "</state>");  
  49.         writer.println(" <zip>" + cust.getZip() + "</zip>");  
  50.         writer.println(" <country>" + cust.getCountry() + "</country>");  
  51.         writer.println("</customer>");  
  52.     }  
  53.   
  54.     protected Customer readCustomer(InputStream is) {  
  55.         try {  
  56.             DocumentBuilder builder = DocumentBuilderFactory.newInstance()  
  57.                     .newDocumentBuilder();  
  58.             Document doc = builder.parse(is);  
  59.             Element root = doc.getDocumentElement();  
  60.             Customer cust = new Customer();  
  61.             if (root.getAttribute("id") != null  
  62.                     && !root.getAttribute("id").trim().equals("")) {  
  63.                 cust.setId(Integer.valueOf(root.getAttribute("id")));  
  64.             }  
  65.             NodeList nodes = root.getChildNodes();  
  66.             for (int i = 0; i < nodes.getLength(); i++) {  
  67.                 Node item = nodes.item(i);  
  68.                 if(!(item instanceof Element)){  
  69.                     continue;  
  70.                 }  
  71.                 Element element = (Element) nodes.item(i);  
  72.                 if (element.getTagName().equals("first-name")) {  
  73.                     cust.setFirstName(element.getTextContent());  
  74.                 } else if (element.getTagName().equals("last-name")) {  
  75.                     cust.setLastName(element.getTextContent());  
  76.                 } else if (element.getTagName().equals("street")) {  
  77.                     cust.setStreet(element.getTextContent());  
  78.                 } else if (element.getTagName().equals("city")) {  
  79.                     cust.setCity(element.getTextContent());  
  80.                 } else if (element.getTagName().equals("state")) {  
  81.                     cust.setState(element.getTextContent());  
  82.                 } else if (element.getTagName().equals("zip")) {  
  83.                     cust.setZip(element.getTextContent());  
  84.                 } else if (element.getTagName().equals("country")) {  
  85.                     cust.setCountry(element.getTextContent());  
  86.                 }  
  87.             }  
  88.             return cust;  
  89.         } catch (Exception e) {  
  90.             throw new WebApplicationException(e, Response.Status.BAD_REQUEST);  
  91.         }  
  92.     }  
  93. }  

 

这些方法的实现都很直接,不细说,不过有一点需要特别注意的是:

 

最好不要在实现中混杂有服务的定义部分,例如@Path标签,@PathParam标签等等,如果想修改定义,最好是在接口中修改;或者如果想覆盖某个接口方法的某个annotation,则所有该接口方法的annotation定义都需要重写,而不能仅修改变化的
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 裤子摔了一个洞怎么办 顾客反应衣服质量不好怎么办 淘宝买的衣服味道很大怎么办 三国杀账号忘了怎么办 宽带连接被删了 怎么办 手机被偷了qq怎么办 手机丢了微信怎么办啊 手机店把手机修坏了怎么办 在手机店买到山寨机手机怎么办 有人在qq群上骂我怎么办 qq群一直有人骚扰怎么办 苹果手机QQ图标不在桌面上怎么办 苹果手机长按不能删除怎么办 qq发的图片过期怎么办 九黎八卦在仓库怎么办 飞猪f2领了万豪银卡没住怎么办 机械键盘摁键冲突怎么办 玩游戏键盘没反应怎么办 玩枪战游戏头晕恶心怎么办 手机看视频不能横屏怎么办 苹果手机安全码忘记了怎么办 信用卡安全码忘记了怎么办 联想电脑管家阻止我安装软件怎么办 word恢复后打开乱码怎么办 苹果手机局域网也登陆不了怎么办 剑三账号冻结7天怎么办 荒野行动无缘无故被限制时间怎么办 电脑打游戏闪屏怎么办 微信下载出现数据包出错怎么办 安卓平板闪退怎么办 剑侠世界2出了1怎么办 苹果手机有木马病毒删除不了怎么办 苹果手机病毒了怎么办【解决方法】 苹果手机点击病毒链接怎么办 苹果手机有病毒啦怎么办 苹果7p反复重启怎么办 苹果手机屏幕触屏不灵怎么办 苹果手机屏翘起来了怎么办 苹果x手机触屏失灵怎么办 苹果7手机变成黑白屏怎么办 苹果手机屏不动了怎么办