资源定位之注解相关简介

@QueryParam注解

JAX-RS2定义了@QueryParam注解来定义查询参数,如下表所示

接口描述 资源地址
分页查询列表数据 /query-resource/test?start=24&size=10
排序并分页查询列表收 /query-resource/test?limit=5&sort=program
查询单项数据 /query-resource/test?id=9
1、分页查询
   /**** @param start  起始条目  参数都使用了final进行限制*               符合Checkstyle风格 即输入参数只作为逻辑算法的依据使用*               其本身并不会再找个过程中被修改* @param size 查询的条目* @return*/@Path("/page")  //page?start=0&size=10  访问@GET@Consumes(MediaType.APPLICATION_JSON)  //指定请求返回的响应体为JSON@Produces(MediaType.APPLICATION_JSON)public User getByPaging(@QueryParam("start") final int start,@QueryParam("size") final int size){return null;}
2、排序查询
/*** @param limit  分页查询条目* @param sortName 排序规则* @return*/@Path("/order")    //order?limit=10&sort=web 访问@GET@Consumes(MediaType.APPLICATION_JSON)  //指定请求返回的响应体为JSON@Produces(MediaType.APPLICATION_JSON)public User getByOrder(@QueryParam("limit") final int limit,@QueryParam("sort") final int sortName){return null;}
3、单项查询
    /*** @param segId  * @return*/@Path("/query")    //order?id=10 访问@GET@Consumes(MediaType.APPLICATION_JSON)  //指定请求返回的响应体为JSON@Produces(MediaType.APPLICATION_JSON)public User getByQuery(@QueryParam("id") final int segId){return null;}

@PathParam注解

JAX-RS2定义@PathParam注解来定义路径参数—-每个参数对应一个子资源,示例列表如下:

接口描述 资源地址
基本路径参数 /path-resource/Eric
J结合查询参数 /path-resource/Eric?hometown=Luoma
带有标点符号的资源路径 /path-resource/199-1999
/path-resource/01,2012-12,2014
子资源变长的资源路径 /path-resource/Asia/china/northeast/liaoning/shenyang/huanggu
//path-resource/q/restful;program=java;type=web
/path-resource/q2/restful;program=java;type=web
1、@Path注解

JAX-RS2定义@Path注解来定义资源路径,@Path接收一个value参数来解析资源路径地址,可以使用静态定义的方式外,也可以使用动态变量的方式,格式:{参数名称:正则表达式},例如资源地址:/path-resource、199-1999.参考示例如下

 @Path("{from:\\d+}-{to:\\d+}")    //order?id=10 访问@GET@Consumes(MediaType.APPLICATION_JSON)  //指定请求返回的响应体为JSON@Produces(MediaType.APPLICATION_JSON)public User getByCondition(@QueryParam("from") final Integer from, @PathParam("to") final Integer to) {return null;}

在来一个复杂的例子:/path-resource、01,2012-12,2014(引入了逗号(,))

@Path("{beginMonth:\\d+},{beginYear:\\d+}-{endMonth:\\d+},{endYear:\\d+}")
2、正则表达式
3、路径配查询

查询参数和路径参数在一个接口中配合使用,可以更便捷的完成资源定位。

    /*** /path-resource/Eric?hometown=Luoma ** @param user   Eric* @param hometown  Luoma* @return*/@Path("{user:[a-zA-Z][a-zA-Z_0-9]*}")    //order?id=10 访问@GET@Consumes(MediaType.APPLICATION_JSON)  //指定请求返回的响应体为JSON@Produces(MediaType.APPLICATION_JSON)public User getUserInfo(@QueryParam("user") final String user,@DefaultValue("Shen Yang") @QueryParam("hometown") final String hometown) {return null;}
4、路径区间

路径区间(PathSegment)是对资源地址更加灵活的支持,使资源类的一个方法可以支持更加广泛的资源地址的请求,例如下面的例子

/path-resource/Asia/china/northeast/liaoning/shenyang/huanggu
/path-resource/Asia/china/northeast/liaoning/shenyang/tiexi
/path-resource/china/liaoning/shenyang

如上所示的资源地址中含有固定子资源(shenyang),和动态子资源两部分,对于动态匹配变长的子资源地址,PathSegment类型的参数结合正则表达式将大显身手,如下:

    @Path("{region:.+}/shenyang/{district:\\w+}")              //order?id=10 访问@GET@Consumes(MediaType.APPLICATION_JSON)  //指定请求返回的响应体为JSON@Produces(MediaType.APPLICATION_JSON)public User getByAddress(@PathParam("region")final List<PathSegment> region,@PathParam("district") final String district) {final StringBuilder result = new StringBuilder();for (PathSegment pathSegment : region) {result.append(pathSegment.getPath()).append("-");}result.append("shenyang-" + district);return null;}

@MatrixParam注解

通过@MatrixParam注解来逐一的定义参数,即通过声明方式来获取,示例代码如下:

///path-resource/q2/program=java;type=web@Path("q2/{condition}")    //order?id=10 访问@GET@Consumes(MediaType.APPLICATION_JSON)  //指定请求返回的响应体为JSON@Produces(MediaType.APPLICATION_JSON)public User getByCondition(@PathParam("condition") final PathSegment condition,@MatrixParam("program") final String program,@MatrixParam("type") final String type) {return null;}

@FormParam注解

JAX-RS2定义了@FormParam注解来定义表单参数,相应的REST方法用以处理请求实体媒体类型为Content-Type:application/x-www-form-urlencoded的请求,示例代码如下:

@Path("form-resource)
public class FormResource{@Postpublic String newPassword(@DefaultValue("ruolan") @FormParam(FromResource.USER) final String user,@Encoded @FormParam(FormParam.PW) final String password,@Encoded @FormParam(FormParam.NPW) final String newPassword,@FormParam(FormParam.VNPW) final String verification{})
}

上述代码中,newPassword()方法是@FormParam注解定义了user等4个参数,这些参数是容器请求中获取并且匹配的,测试代码示例如下:

    @Testpublic void testPost(){final Form form = new Form();form.param(FormResource.USER,"ruolan");form.param(FormResource.PW,"北京");form.param(FormResource.NPW,"上海");form.param(FormResource.VNPW,"上海");final String result = target.("form-resource").request().post(Entity.entity(form,MediaType.APPLICATION_FORM_URLENCODED_TYPE),String.class);FormTest.LOGGER.debug(result);Assert.assertEquals("encoded should let id to disable decoding","ruolan:%E5%8C%97%E4%BA%AC:%E4%B8%8A%E6%B5%B7:上海",result);}

注意:

  • @Encoded注解用以标识禁用自动解码,示例中的测试结果中%E4%B8%8A%E6%B5%B7是newPassword()方法中的参数值”上海”的编码值,当对newPassword使用@Encoded注解,REST方法得到的参数值就不会被编码
  • @DefaultValue注解,用以为客户端没有为其提供值的参数 提供默认的参数

@BeanParam注解

JAX-RS2定义了@BeanParam注解用于自定义参数组合,使REST方法可以使用简洁的参数形式完成复杂的接口设计

public String getByAddress(@BeanParam Jaxrs2GuideParam param) {
//关注点2:参数组合
public class Jaxrs2GuideParam {@HeaderParam("accept")private String acceptParam;@PathParam("region")private String regionParam;@PathParam("district")private String districtParam;@QueryParam("station")private String stationParam;@QueryParam("vehicle")private String vehicleParam;public void testBeanParam() {
...final WebTarget queryTarget = target(path).path("China").path("northeast").path("shenyang").path("tiexi")
.queryParam("station", "Workers Village").queryParam("vehicle", "bus");result = queryTarget.request().get().readEntity(String.class);//关注点3:查询结果断言 Assert.assertEquals("China/northeast:tiexi:Workers Village:bus", result);
}

//关注点4:复杂的查询请求

http://localhost:9998/ctx-resource/China/shenyang/tiexi?station=Workers+Village&vehicle=bus 

在这段代码中,getByAddress()方法只用了一个使用@BeanParam注解定义的Jaxrs2GuideParam类型的参数,见关注点1;Jaxrs2GuideParam类定义了一系列REST方法会用到的参数类型,包括示例中使用的查询参数”station”和路径参数”region”等,从而使得getByAddress()方法可以匹配更为复杂的资源路径,见关注点2;在变长子资源的例子基础上,增加了查询条件,但测试方法testBeanParam()发起的请求的资源地址见关注点4;可以看出这是一个较为复杂的查询请求。其中路径部分包括China/shenyang/tiexi,查询条件包括station=Workers+Village和vehicle=bus。这些条件均在Jaxrs2GuideParam类中可以匹配,因此从关注点3的测试断言中可以看出,该请求响应的预期结果是

"China/northeast:tiexi:Workers Village:bus"。

@CookieParam注解

JAX-RS2定义了@CookieParam注解用以匹配Cookie中的键值对信息,示例如下。

@GET
public String getHeaderParams(@CookieParam("longitude") final String longitude,@CookieParam("latitude") final String latitude,@CookieParam("population") final double population,@CookieParam("area") final int area) {//关注点1:资源方法入参 return longitude + "," + latitude + " population=" + population + ",area=" + area;
@Test
public void testContexts() {final Builder request = target(path).request();request.cookie("longitude", "123.38");request.cookie("latitude", "41.8");request.cookie("population", "822.8");request.cookie("area", "12948");result = request.get().readEntity(String.class);//关注点2:测试结果断言 Assert.assertEquals("123.38,41.8 population=822.8,area=12948", result);
}

在这段代码中,getHeaderParams()方法包含4个使用@CookieParam注解定义的参数,用于匹配Cookie的字段,见关注点1;在测试方法testContexts中,客户端Builder实例填充了相应的cookie键值对信息,其断言是对cookie字段值的验证,见关注点2。

@Context注解

JAX-RS2定义了@Context注解来解析上下文参数,JAX-RS2中有多种元素可以通过@Context注解作为上下文参数使用,示例代码如下。

 pathMap = uriInfo.getPathParameters();
final MultivaluedMapqueryMap = uriInfo.getQueryParameters();
final ListsegmentList = uriInfo.getPathSegments();
final MultivaluedMapheaderMap = headers.getRequestHeaders();" data-snippet-id="ext.a3f662d96e4890cd0110b0e0facd3b54" data-snippet-saved="false" data-codota-status="done">public String getByAddress(@Context final Application application,@Context final Request request,@Context final javax.ws.rs.ext.Providers provider,@Context final UriInfo uriInfo,@Context final HttpHeaders headers){
在这段代码中,分别定义了Application、Request、Providers、UriInfo和HttpHeaders等5种类型的上下文实例。从这些实例中可以获取请求过程中的重要参数信息,示例代码如下。
final MultivaluedMap<String, String> pathMap = uriInfo.getPathParameters();
final MultivaluedMap<String, String> queryMap = uriInfo.getQueryParameters();
final List<PathSegment> segmentList = uriInfo.getPathSegments();
final MultivaluedMap<String, String> headerMap = headers.getRequestHeaders();

在这段代码中,UriInfo类是路径信息的上下文,从中可以获取路径参数集合getPath-Parameters()和查询参数集合getQueryParameters()。类似地,我们可以从HttpHeaders类中获取头信息集合getRequestHeaders()。这些业务逻辑处理中常用的辅助信息的获取,要通过@Context注解定义方法的参数或者类的字段来实现。


处理响应

REST的响应处理结果应包括响应头中HTTP状态码,响应实体中媒体参数类型和返回值类型,以及异常情况处理。JAX-RS2支持4中返回值类型的响应,分别是无返回值、返回Response类实例、返回GenericEntity类实例和返回自定义类的实例.

VOID(无返回值类型)

在返回值类型中是void的响应,其响应实体为空,HTTP状态码是204。例子代码如下:

    @DELETE@Path("{s}")public void deleteTest(@PathParam("s") final String s){}

因为delete操作不需要返回值关于资源标书的信息,因此该方法没有返回值.(疑问点,如果需要通知客户端是否删除成功了没有呢??????)

RESPONSE(Response返回值类型)

在Response的响应中,响应实体为Response类的entity()方法定义的实体实例。如果该内容为空,则HTTP状态码是204,否则HTTP状态码为200 OK,示例代码如下:

    @POST@Path("c")public Response getResponse(final String s){return Response.ok().entity("char[] : " + s ).build();}

在上述的代码中,Response首先定义了HTTP的状态码为OK,然后填充实体信息,最后调用build()方法构建Response实例

GenericEntity(GenericEntity返回值类型)

通用实体类型作为返回值的情况并不是很常用。其形式是构造一个统一的实体实例并将其返回,实体实例作为第一个参数,该实体类型作为第二个参数,示例代码如下:

    @POST@Path("b")public String getGenericEntity(final  byte[] bytes) {return "byte[] : "  + new String(bytes);}public GenericEntity<String> getGenericTest(final  byte[] bytes){//构建GenericEntity实例return new GenericEntity<>("byte[] : " + new String(bytes),String.class );}
自定义类型

JDK中的类(例如File,String等)都可以作为返回值类型,更常用的是返回自定义的POJO类型。示例代码如下:

    @POST@Path("f")public File getFile(final File f) throws FileNotFoundException, IOException {BufferedReader br = new BufferedReader(new FileReader(f));String s;do {s = br.readLine();} while (s != null);return f;}@POST@Consumes({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})@Produces(MediaType.APPLICATION_XML)public User getEntity(User user){return user;}@POST@Consumes({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})@Produces(MediaType.APPLICATION_XML)public User getEntity(JAXBElement<User> user){User user1 = user.getValue();return user1;}

处理异常

处理状态码
状态码 含义
200 OK 服务器正常响应
201 Created 创建新实体,响应头Location指定访问该实体的URL
202 Accepted 服务器接受请求,处理尚未完成。可用于异步处理机制
204 No Content 服务器正常响应,但是响应实体为空
301 Moved Permanently 请求资源的地址发生永久变动,响应头Location指定新的URL
302 Found 请求资源的额地址发生临时变动
304 Not Modified 客户端缓存资源依然有效
400 Bad Request 请求信息出现语法错误
401 Unauthorized 请求资源无法授权给未验证错误
403 Frobidden 请求资源未授权当前用户
404 Not Found 请求资源不存在
405 Method Not Allowed 请求方法不匹配
406 Not Acceptable 请求资源的媒体类型不匹配
500 Internale Server Error 服务器内部错误,意外终止响应
501 Not Implemented 服务器不支持当前请求

内容协商

@Produces注解

@Produces注解用于定义方法的响应实体的数据类型,可以定义一个或者多个,同事可以为每种类型定义质量因素(qualityfactor)。质量因素是取值范围从0到1的小数值。如果不定义质量因素,那么该类型的质量因素默认为1

    @GET@Path("{id}")@Produces(MediaType.APPLICATION_XML)public User getJaxUser(@PathParam("id") final int userId) {return new User(userId);}@GET@Path("{id}")@Produces(MediaType.APPLICATION_JSON)public User getJsonUser(@PathParam("id") final int userId) {return new User(userId);}/*** 以下的代码中 定义了xml和json两种表述数据类型,xml的质量因素是0.5 json的质量因素是0.9**/@GET@Path("book/{id}")@Produces({"application/json;qs=0.9","application/xml;qs=0.6"})public User getUser(@PathParam("id") final int userId) {return new User(userId);}

如果客户端的请求中,明确接收的数据类型是两者之一,响应实体使用指定类型.如果没有定义或者两者都定义且JSON的质量因素大雨或者等于XML,则返回JSON,还有一种用例就是,两者都定义但是json的质量因素小于XML,内容协商的结果按照客户端的喜好选择相应实体的数据类型(xml格式)

@Consumes注解

@Consumes注解用于定义方法的请求实体的数据类型,和@Produces不同的是,@Consumes注解的数据类型的定义只用于JAX-RS2匹配请求处理的方法,不做内容协商使用,如果匹配不到,服务器会返回HTTP状态码415(Unsupported Meia Type),示例代码如下:

    @POST@Consumes({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})@Produces(MediaType.APPLICATION_XML)public User getEntity(User user){final Builder request = Target(path).request();final User result = request.post(Entity.entity(user,MediaType.APPLICATION_XML), User.class);return user;}

@Consumes媒体类型为XML格式和JSON格式,那么在客户端的请求中,如果请求实体的数据类型定义是两者之一,该方法会被选择为处理请求的方法,否则查找是否有定义为相应数据类型的方法,如果没有抛出javax.ws.rs.NotSupportedException异常,则使用该方法处理请求。

JAVA RESTful WebService实战笔记(二)相关推荐

  1. Java基础--基础语法笔记(二)--Switch的用法

    直接步入主题,接着记录学习java的一些重要笔记.对于一些比较简单的内容,就不会详细的去进行记录. Switch的用法 格式一: switch (表达式) {case 条件1:语句1;break;ca ...

  2. Java并发编程实战笔记2:对象的组合

    设计线程安全的类 在设计现车让安全类的过程之中,需要包含以下三步: 找出构成对象状态的所有变量 找出约束状态变量的不变性条件 建立对象状态的并发访问策略 实例封闭 通过封闭机制与合适的加锁策略结合起来 ...

  3. java并发编程实战(二)

    java并发编程中常常会用到两种容器来存放一些数据,这些数据需要保证能在多线程下正常访问.常见的容器分为两类:同步容器和并发容器.在java并发编程实战一书中的第五章也有讲解. 什么是同步容器以及优劣 ...

  4. java 8实战 异步社区_服!看完阿里大牛手写的Java异步编程实战笔记,我惊呆了...

    这份笔记涵盖了Java中常见的异步编程场景,包括单JVM内的异步编程.跨主机通过网络通信的远程过程调用的异步调用与异步处理,以及Web请求的异步处理等. 在讲解Java中每种异步编程技术时都附有案例, ...

  5. Java 微信小程序笔记 二、 微信支付退款案例

    一.前期准备工作: 上篇博客配置的一些参数和文件Jar包 都要用到 微信支付需要小程序和商户绑定 APP绑定微信商户平台获取商户id(mchID). 证书(商户后台下载). 支付签名密钥(商户后台设置 ...

  6. Jersey构建Java RestFul Webservice基础学习教程

    1.用Jersey构建RESTful服务1–HelloWorld http://www.waylau.com/jersey-restful-helloworld/ 2.用Jersey构建RESTful ...

  7. 神经网络与深度学习——TensorFlow2.0实战(笔记)(二)(Anaconda软件使用)

    Python的运行模式 交互模式 打开命令行窗口 键入 python,激活python交互模式,出现Python提示符 >>> 在提示符 >>> 处, 写入Pyth ...

  8. Java并发编程实战笔记

    如果当多个线程访问同一个可变的状态变量时没有使用合适的同步,那么程序就会出现错误.有三种方式可以修复这个问题: i.不在线程之间共享该状态变量 ii.将状态变量修改为不可变的变量 iii.在访问状态变 ...

  9. Java并发编程实战笔记—— 并发编程1

    1.如何创建并运行java线程 创建一个线程可以继承java的Thread类,或者实现Runnabe接口. public class thread {static class MyThread1 ex ...

最新文章

  1. 什么才是真正的L3自动驾驶?
  2. 后MATLAB时代的七种开源替代,一种堪称完美!
  3. 芯片史上最大收购案!「博通」拟斥资1000亿美元收购「高通」
  4. 郁金香2013网授汇编逆向与外挂 [ 91课,全 ]
  5. struts2重定向
  6. 建立学生选课表 mysql 语句_MySQL常用SQL语句(Python实现学生、课程、选课表增删改查)...
  7. apache mediawiki 安装_如何在CentOS 7上安装MediaWiki
  8. java 二进制 文件比较_Java中对文件的读写操作之比较
  9. magento 问题解答 FQA
  10. Oracle On Linux
  11. 中国电信陆良军:2020年5G手机终端规模达1.7亿
  12. fetch oracle 12c下载,十二、Oracle Fetch子句
  13. 新版傻妞对接QQ完整版(10月24日)
  14. php mysql注入测试工具_PHP+MYSQL 【注入漏洞】攻防测试
  15. 利用OpenGL模拟太阳系
  16. 使用ffmpeg合并多个视频文件
  17. RT_thread空闲线程及两个常用的钩子函数
  18. linux鼠标晃动出现,鼠标指针抖动的原因及其解决方法【详解】
  19. SQLZOOL练习题答案和解析 第2关 SELECT from World
  20. ftp文件缓存服务器,ftp服务器上的缓存在哪

热门文章

  1. 【设计模式02】 抽象工厂模式
  2. 学习记录:Monkey测试
  3. 工作篇 之 解决谷歌地图与 NestedScrollView 滑动冲突
  4. 关于软件测试人员的几个职业规划方向
  5. 一文彻底学会CSS-3
  6. 【百度网盘】 个人资源共享
  7. mysql面试题学校三表查询_mysql经典面试题之学生成绩表
  8. 专业计算机和游戏计算机配置要求,游戏直播电脑配置要求2019|游戏直播电脑配置单推荐(可装win7)...
  9. jmeter性能测试方案
  10. C++初步之核心编程篇五:多态与虚函数类