java 利用JAX-RS快速开发RESTful 服务

javax.ws.rs-api-2.1.jar javax.ws.rs-api-2.1.jar,javax.ws.rs-api,javax.ws.rs,javax 立即下载

JAX-RS(Java API for RESTful Web Services)同样也是JSR的一部分,详细规范定义见 https://jcp.org/en/jsr/detail?id=311 。从JAVA EE 6开始,已经内置了该技术,跟.NET中的RESTful WCF类似,只要在常规方法上使用一些简单的注解,就可以对外暴露成RESTful 服务.

注:本文运行环境为Jboss EAP 6.x ,其它容器特别是tomcat,并未自带JAX-RS依赖的jar包,如果采用tomcat,需要自己导入这些相关依赖jar包。

一、最基础的HelloWorld (无参数)

复制代码
复制代码
 1 @Path("/")
 2 public class MyService {
 3 
 4     final String XMLNS_NAMESPACE = "http://yjmyzz.cnblogs.com/rest/service";
 5     final String ROOT_NODE = "root";
 6 
 7     @GET
 8     @Path("/json/hello")
 9     @Produces(MediaType.APPLICATION_JSON)
10     public JAXBElement<String> getHelloWorldJSON() {
11         JAXBElement<String> result = new JAXBElement<String>(new QName("",
12                 ROOT_NODE), String.class, sayHelloWorld());
13         return result;
14     }
15 。。。
16 }
复制代码
复制代码
1     private String sayHelloWorld() {
2         return "Hello JAX-RS!";
3     }

解释:
@GET 表示该服务可以直接在浏览器地址栏里访问(对应HTTP请求中的GET方法)

@Path 这里用了二次,第一次是在Class上,相当服务的基地址;第二次是在方法上,表示具体某个服务方法的URL.

此外web.xml中,还需要增加以下内容:

1     <servlet-mapping>
2         <servlet-name>javax.ws.rs.core.Application</servlet-name>
3         <url-pattern>/rest/*</url-pattern>
4     </servlet-mapping>

@Produces 表示返回消息的格式,配合MediaType.APPLICATION_JSON说明,本方法返回Json字符串格式

以上几项综合起来,最终可以用类似 http://localhost:8080/jboss-as-helloworld-rs/rest/json/hello 的地址来访问,返回的结果为:

JAXBElement<T> 类似一个包装器(Wrapper),用于将返回对象做下json/xml格式的包装,比如上图中的{root:}就是它的功劳,感兴趣的朋友,可以把返回类似改成最原始的String对比下差异.

如果需要返回XML格式,只需要把@Produces后面的MediaType.APPLICATION_JSON换成MediaType.APPLICATION_XML就行了,即:

  getHelloWorldXML

效果如下:

 

二、带一个基本类型参数的HelloWorld

复制代码
 1     @GET
 2     @Path("/json/hi/{name}")
 3     @Produces(MediaType.APPLICATION_JSON)
 4     public JAXBElement<String> getHelloToNameJSON(@PathParam("name") String name) {
 5         JAXBElement<String> result = new JAXBElement<String>(new QName("",
 6                 ROOT_NODE), String.class, sayHelloToName(name));
 7         return result;
 8     }
 9 
10     @GET
11     @Path("/xml/hi/{name}")
12     @Produces(MediaType.APPLICATION_XML)
13     public JAXBElement<String> getHelloToNameXML(@PathParam("name") String name) {
14         JAXBElement<String> result = new JAXBElement<String>(new QName(
15                 XMLNS_NAMESPACE, ROOT_NODE), String.class, sayHelloToName(name));
16         return result;
17     }
复制代码
1     private String sayHelloToName(String name) {
2         return "Hello " + name + ",welcome to the world of JAX-RS!";
3     }

对比一下刚才的代码,有二个变化:

2.1 @Path上多了一个{name}的部分,表示url中,将允许以 /json/hi/xxx 的访问URL响应请求

2.2 方法参数前有一个 @PathParam("name") 的注解,表示如果按/json/hi/xxx的方式访问,则url中xxx的部分,会被映射到name这个参数上(说得更通俗点,就是通过解析url最后的xxx部分直接把name传进来)

运行效果如下:

 

三、返回结果为实体Bean

实际应用中,web服务返回的结果,除了基本类型,还有可能是实体Bean,先来定义一个User类

复制代码
 1 package yjmyzz.service.model;
 2 
 3 import javax.xml.bind.annotation.XmlAttribute;
 4 import javax.xml.bind.annotation.XmlElement;
 5 import javax.xml.bind.annotation.XmlRootElement;
 6  
 7 @XmlRootElement(name = "user")
 8 public class User {
 9  
10     String username;
11     String password;
12     int pin;
13  
14     @XmlElement
15     public String getUsername() {
16         return username;
17     }
18  
19     public void setUsername(String username) {
20         this.username = username;
21     }
22  
23     @XmlElement
24     public String getPassword() {
25         return password;
26     }
27  
28     public void setPassword(String password) {
29         this.password = password;
30     }
31  
32     @XmlAttribute
33     public int getPin() {
34         return pin;
35     }
36  
37     public void setPin(int pin) {
38         this.pin = pin;
39     }
40  
41 }
复制代码

代码中加的一堆@XML开头的注解,是为了在传输过程中,如果需要以XML格式传输,这些注解可以帮助完成 XML <-> Obj的转换(详情可参见JAXB相关内容)

复制代码
 1     @GET
 2     @Path("/xml/user")
 3     @Produces(MediaType.APPLICATION_XML)
 4     public User getUserInXML() {
 5         return getUser("unknown");
 6     }
 7 
 8     @GET
 9     @Path("/json/user")
10     @Produces(MediaType.APPLICATION_JSON)
11     public User getUserInJSON() {
12         return getUser("unknown");
13     }
复制代码

注意:这里我们没有使用JAXBElement<T>对结果进行包装,辅助方法getUser()代码如下

复制代码
1     private User getUser(String username) {
2         User user = new User();
3         user.setUsername(username);
4         String pwd = new Long(Math.round(Math.random() * 100000)).toString();
5         user.setPassword(pwd);
6         int pin = (int) (Math.random() * 1000);
7         user.setPin(pin);
8         return user;
9     }
复制代码

运行结果如下:

当然,也可以给方法增加参数,先从最基本类型的String参数耍起:

复制代码
 1     @GET
 2     @Path("/xml/userByName/{name}")
 3     @Produces(MediaType.APPLICATION_XML)
 4     public User getUserInXML(@PathParam("name") String username) {
 5         return getUser(username);
 6     }
 7 
 8     @GET
 9     @Path("/json/userByName/{name}")
10     @Produces(MediaType.APPLICATION_JSON)
11     public User getUserInJSON(@PathParam("name") String username) {
12         return getUser(username);
13     }
复制代码

运行结果如下:

如果加上包装器JAXBElement<User>后,返回结果会变成什么样呢? 我也很好奇,so, 嘿-喂狗!

复制代码
 1     @GET
 2     @Path("/xml/userByName2/{name}")
 3     @Produces(MediaType.APPLICATION_XML)
 4     public JAXBElement<User> getUserInXML2(@PathParam("name") String username) {
 5         JAXBElement<User> result = new JAXBElement<User>(new QName(
 6                 XMLNS_NAMESPACE, ROOT_NODE), User.class, getUser(username));
 7         return result;
 8     }
 9 
10     @GET
11     @Path("/json/userByName2/{name}")
12     @Produces(MediaType.APPLICATION_JSON)
13     public JAXBElement<User> getUserInJSON2(@PathParam("name") String username) {
14         JAXBElement<User> result = new JAXBElement<User>(new QName("",
15                 ROOT_NODE), User.class, getUser(username));
16         return result;
17     }
复制代码

结果如下:

个中差异,请自行体会

 

四、单个String参数的实体Bean注入

web服务中方法的传入参数,不可能都是基础类型,同样也可以是实体Bean

复制代码
 1     @GET
 2     @Path("/xml/product/{name}")
 3     @Produces(MediaType.APPLICATION_XML)
 4     public Product getProductXML(@PathParam("name") Product product) {
 5         return getProductFromServer(product);
 6     }
 7 
 8     @GET
 9     @Path("/xml/product2/{name}")
10     @Produces(MediaType.APPLICATION_XML)
11     public JAXBElement<Product> getProductXML2(
12             @PathParam("name") Product product) {
13         JAXBElement<Product> result = new JAXBElement<Product>(new QName(
14                 XMLNS_NAMESPACE, ROOT_NODE), Product.class,
15                 getProductFromServer(product));
16         return result;
17     }
复制代码

这里我们用到了一个新的Bean :Product类,代码如下:

复制代码
 1 package yjmyzz.service.model;
 2 
 3 import javax.xml.bind.annotation.XmlElement;
 4 import javax.xml.bind.annotation.XmlRootElement;
 5 
 6 @XmlRootElement(name = "product")
 7 public class Product {
 8 
 9     public Product() {
10         System.out.println("construct: Product() is called!");
11     }
12     
13     public Product(String name) {
14         System.out.println("construct: Product(String name) is called!");
15         this.productName = name;
16     }
17 
18     @XmlElement
19     public String getProductName() {
20         return productName;
21     }
22 
23     public void setProductName(String productName) {
24         this.productName = productName;
25     }
26 
27     private String productName;
28 
29 }
复制代码

先提个问题:从@Path上看,我们希望用类似 /xml/product/xxx 来请求该web方法,但是方法中的参数是一个Bean实例,而url中的xxx部分只是一个字符串,一个字符串如何被映射成一个Bean实例呢?

关键在于Product中的构造函数:Product(String name) ,方法getProductXML(@PathParam("name") Product product) 被请求时,url中的xxx部分会先映射成参数name,然后name又会被传入到构造函数Product(String name)中,于是一个崭新的Product对象诞生了!(可以通过eclipse Console的输出来印证Product(String name)是否被调用)

运行结果:

eclipse的控制台里,也可以看到构造器,确实被调用了

除了利用“带参数的构造器”来实现“url参数->Bean实例”的注入,JAX-RS机制还允许使用Bean自身提供的static valueOf()方法来实现注入,再来看一下示例:

从Product派生一个子类Book:

复制代码
 1 package yjmyzz.service.model;
 2 
 3 import java.util.Calendar;
 4 import java.util.Date;
 5 
 6 import javax.xml.bind.annotation.XmlElement;
 7 import javax.xml.bind.annotation.XmlRootElement;
 8 
 9 @XmlRootElement(name = "book")
10 public class Book extends Product {
11 
12     private String isbn;
13 
14     private String author;
15 
16     private Date publishDate;
17 
18     public Book() {
19         System.out.println("construct: Book() is called!");
20     }
21 
22     public static Book valueOf(String isbn) {
23         System.out.println("Book: valueOf(String isbn) is called!");
24 
25         Book book = new Book();
26         book.setISBN(isbn);
27         book.setProductName("Java编程思想(第4版)");
28 
29         book.setAuthor("[美]埃克尔");
30 
31         Calendar calendar = Calendar.getInstance();
32         calendar.set(2007, 6, 1);
33         book.setPublishDate(calendar.getTime());
34         return book;
35     }
36 
37     @XmlElement
38     public String getISBN() {
39         return isbn;
40     }
41 
42     public void setISBN(String isbn) {
43         this.isbn = isbn;
44     }
45 
46     @XmlElement
47     public String getAuthor() {
48         return author;
49     }
50 
51     public void setAuthor(String author) {
52         this.author = author;
53     }
54 
55     @XmlElement
56     public Date getPublishDate() {
57         return publishDate;
58     }
59 
60     public void setPublishDate(Date publishDate) {
61         this.publishDate = publishDate;
62     }
63 
64 }
复制代码

再定义一个新方法:

复制代码
1     @GET
2     @Path("/xml/book/{ISBN}")
3     @Produces(MediaType.APPLICATION_XML)
4     public Book getBookXML(@PathParam("ISBN") Book book) {
5         return getBookFromServer(book);
6     }
复制代码

里面有一个辅助方法,代码如下:

1     private Book getBookFromServer(Book book) {
2         book.setProductName(book.getProductName() + " from server!");
3         return book;
4     }

运行效果如下:

eclipse的控制台信息如下:

 

五、POST方式的Bean实例参数注入

前面提到的都是GET方式的web服务方法,GET方式能传输的数据大小有限,对于较大的参数数据,直接POST的场景更常见,下面是一个示例:

复制代码
 1     @POST
 2     @Path("/json/add-book")
 3     @Produces(MediaType.APPLICATION_JSON)
 4     @Consumes(MediaType.APPLICATION_JSON)
 5     public Book addBookJSON(Book book) {
 6         return getBookFromServer(book);
 7     }
 8     
 9     
10     @POST
11     @Path("/xml/add-book")
12     @Produces(MediaType.APPLICATION_XML)
13     @Consumes(MediaType.APPLICATION_XML)
14     public Book addBookXML(Book book) {
15         return getBookFromServer(book);
16     }
复制代码

解释一下:

又遇到了一个新的注解:@Consumes(MediaType.APPLICATION_JSON) 它表示传入的Book实例是json格式。

我们用jQuery以Ajax方式调用这个服务演示一下:

复制代码
 1         function testJsonAddBook(){
 2             $(document).ready(function(){
 3                 $.ajax({
 4                     type:"POST",
 5                     url:"rest/json/add-book",
 6                     dataType: "json",
 7                     contentType: 'application/json',
 8                     data:JSON.stringify({"productName":"Java编程思想(第4版)","isbn":"9787111213826","author":"[美]埃克尔","publishDate":1183270161125}),
 9                     success: function(data, textStatus, jqXHR){
10                         alert("以下是从服务器返回的Book对象:\n\n" + JSON.stringify(data));
11                     },
12                     error: function(jqXHR, textStatus, errorThrown){
13                         alert('error: ' + textStatus);
14                     }
15                 });
16             })
17         }
18 
19 
20         function testXmlAddBook(){
21             $(document).ready(function(){
22                 $.ajax({
23                     type:"POST",
24                     url:"rest/xml/add-book",
25                     dataType: "xml",
26                     contentType: 'application/xml',
27                     data:"<book><productName>Java编程思想(第4版) from server!</productName><author>[美]埃克尔</author><ISBN>9787111213826</ISBN><publishDate>2007-07-01T13:33:30.782+08:00</publishDate></book>",
28                     success: function(data, textStatus, jqXHR){
29                         alert("以下是从服务器返回的Book对象:\n\n" + data.documentElement.outerHTML);
30                     },
31                     error: function(jqXHR, textStatus, errorThrown){
32                         alert('error: ' + textStatus);
33                     }
34                 });
35             })
36         }
复制代码

运行效果如下:

 

如果断点调试ajax,可以看到传过来的json串已经映射成Bean实例了

示例源代码下载:helloworld-rs.zip

javax.ws.rs-api-2.1.1.jar中文-英文对照文档.zip 1、压缩文件中包含: 中文-英文对照文档、jar包下载地址、Maven依赖、Gradle依赖、源代码下载地址。 2、使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 3、特殊说明: (1)本文档为人性化翻译,精心制作,请放心使用; (2)只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; (3)不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 4、温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件。 5、本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册。 立即下载

相关推荐

zds1104示波器使用指南

(2)将探头连接到探头补偿端,按下auto setup按键,一键捕获。(3)连接需要测量信号,开始查看波形。操作说明书,可以自行查看操作说明书。

m0_61973119的博客 6774

java restful接口开发_Java基于JAX-RS开发Restful接口总结

JAX-RS常用注解:@Path,标注资源类或者方法的相对路径@GET,@PUT,@POST,@DELETE,标注方法是HTTP请求的类型。@Produces,标注返回的MIME媒体类型@Consumes,标注可接受请求的MIME媒体类型@PathParam,@QueryParam,@HeaderParam,@CookieParam,@MatrixParam,@FormParam,分别标注方法的参...

weixin_29006701的博客 819

从婴儿学步到工业级应用:VLA的‘隐式标定‘原理通俗图解

本文深入解析VLA(Vision-Language-Action)模型的'隐式标定'原理,通过类比婴儿学习机制,揭示其如何替代传统手眼标定技术。文章对比了工业机器人传统标定与VLA数据驱动方法的差异,并可视化神经网络注意力机制,展示其在空间关系编码上的突破性进展。最后探讨了VLA在工业应用中的优势与混合架构解决方案。

pz890123456的博客 324

Spring Boot 集成Jersey 创建JAX-RS RESTFul 应用程序。

Spring Boot Jersey 教程展示了如何在 Spring Boot 应用程序中使用 Jersey 设置简单的 RESTFul 应用程序。Jersey 是Spring Boot @RestController.的替代。 Spring是一种流行的 Java 应用程序框架,用于创建企业应用程序。Spring Boot是 Spring 框架演变的下一步。它有助于以最小的努力创建独立的、生产级的基于 Spring 的应用程序。它提倡使用约定优于配置原则而不是 XML 配置。 RESTful 应用.

allway2的博客 1594

从零到一:Zephyr RTOS 在 STM32F4 上的移植与实战(含设备树配置详解)

本文详细介绍了如何从零开始将Zephyr RTOS移植到STM32F4开发板,涵盖开发环境搭建、硬件抽象层分析、设备树配置及系统裁剪等关键步骤。通过实战案例,帮助开发者掌握Zephyr RTOS在嵌入式设备中的应用,提升物联网边缘计算设备的开发效率。

weixin_26976635的博客 591

从芯片选型到光学集成:手持激光测距仪硬件设计全解析

本文全面解析手持激光测距仪的硬件设计,从芯片选型到光学集成,详细介绍了相位法测距技术的核心原理与方案选择。通过模块化设计、信号链路优化及PCB布局技巧,实现毫米级精度。文章还分享了量产化关键控制点,帮助工程师规避常见设计陷阱,提升产品可靠性。

weixin_30425949的博客 445

SpringBoot2.x系列教程38--整合JAX-RS之利用Jersey框架实现RESTful

SpringBoot2.x系列教程38--整合JAX-RS之利用Jersey框架实现RESTful 作者:一一哥 一. JAX-RS与Jersey简介 1. JAX-RS简介 在Java EE 6 中引入了对 JSR-311 的支持。JSR-311(也就是JAX-RS:Java API for RESTful Web Services)旨在定义一个统一的规范,它的核心概念是resource...

一一哥 2373

FFmpeg + OBS 低延迟直播串流实战:从H264裸流到RTP组播的完整配置

本文详细介绍了如何利用FFmpeg将H264裸流转码为RTP协议,并通过组播技术实现与OBS客户端的超低延迟直播串流。文章深入剖析了FFmpeg关键参数调优、SDP文件生成与配置,以及OBS客户端的无缝拉流方法,为需要毫秒级实时交互的场景提供了一套去中心化、高效稳定的完整解决方案。

fanta的博客 830

jax-rs jax-ws_Tomcat服务器上的JAX-WS Web服务部署

jax-rs jax-wsWe learned how to use JAX-WS to create SOAP web services and publish it using javax.xml.ws.Endpoint but most of the times we want to deploy our services on a servlet container. So today w...

从零开始的教程世界 530

嵌入式软件面试常见问题及答案

干了多年的嵌入式,被面试过,也面过不少新人,下面这些是面试中很常见的一些问题及答案,答案可以根据自己的经验自己思考下。--持续补充并更新

weixin_37553721的博客 6024

vue3:html2canvas+jspdf将页面以A4导出为PDF文件,解决内容截断+在分页处截断问题详细排查和解决教程(jsPDF + html2canvas A4分页截断、内容分页时存在截断)

html2canvas + jsPDF 解决内容截断问题,vue3 jspdf-html2canvas生成多页pdf防截断处理(包含代码),vue3解决html2canvas + jsPDF导出pdf分页内容截断问题,jsPDF + html2canvas A4分页截断 完美解决方案(含代码 + 案例),html页面导出pdf截断问题,html2canvas 与 jspdf 相结合生成 pdf 内容被截断的终极解决方案,提供html2canvas+jsPDF将HTML页面以A4纸方式导出为PDF后,内容分页

✅ 精选推荐文章 2245

java restful项目打包_java 利用JAX-RS快速开发RESTful 服务

JAX-RS(Java API for RESTful Web Services)同样也是JSR的一部分,详细规范定义见 https://jcp.org/en/jsr/detail?id=311。从JAVA EE 6开始,已经内置了该技术,跟.NET中的RESTful WCF类似,只要在常规方法上使用一些简单的注解,就可以对外暴露成RESTful 服务.注:本文运行环境为Jboss EAP 6....

weixin_39911066的博客 201

通信算法之283:大疆DJI云哨系统-DJI DroneID物理层协议-解速率匹配及Turbo译码

3. 完整云哨接收机,接收灵敏度。交流: 1279682290 ,2. Turbo译码模块。1. 解速率匹配模块。

leegang12的专栏 868

java 利用JAX-RS快速开发RESTful 服务实例

首先看web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLoc...

新技术革命 1064

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

java_java 利用JAX-RS快速开发RESTful 服务

JAX-RS(Java API for RESTful Web Services)同样也是JSR的一部分,详细规范定义见 https://jcp.org/en/jsr/detail?id=311。从JAVA EE 6开始,已经内置了该技术,跟.NET中的RESTful WCF类似,只要在常规方法上使用一些简单的注解,就可以对外暴露成RESTful 服务. 注:本文运行环境为Jboss EAP ...

weixin_34192732的博客 115

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

上一篇: java JAXB 学习
下一篇: 使用 JAX-RS 简化 REST 应用开发
cq1982
博客等级 码龄21年 107粉丝 36原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值