JAX-RS 2.0中的透明PATCH支持

PATCH方法是最不受欢迎的HTTP方法之一,因为直到最近才真正没有一种标准的PATCH格式。 一段时间以来,它已经针对JSON进行了标准化,因此有很多库可以为您完成繁重的工作。 出于本博客的目的,我将使用json-patch,尽管可以很容易地将这种特定的实现方式适应您选择的补丁库。

每个正常值可以让资源和Bean类不受干扰。 在此示例代码中,我们有一个简单的资源,该资源知道如何返回原始对象,并且该资源允许您执行PATCH方法。 请注意,patch方法仅接受bean对象,这是因为我们需要做一些魔术才能对补丁进行预处理。

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;@Path("service")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class Service {@GETpublic Bean get() {return new Bean(true);}@PATCH@Consumes("application/json-patch+json")public Bean patch(Bean input) {System.out.println(input.getMessage() + "  " + input.getTitle());return input;}}import java.util.ArrayList;
import java.util.List;public class Bean {private String title = "title";private String message = "message";private List<String> list = new ArrayList<String>();public Bean() {this(false);}public Bean(boolean init) {if (init) {title = "title";message = "message";list.add("one");list.add("two");}}public void setList(List list) {this.list = list;}public List getList() {return list;}public void setTitle(String title) {this.title = title;}public String getTitle() {return title;}public void setMessage(String message) {this.message = message;}public String getMessage() {return message;}}

因此,对于这个示例,我们必须创建@PATCH批注,幸运的是,JAX-RS为此目的包含了一个扩展元批注。 我们还将使用@NameBinding因为此示例使用的是JAX-RS 2.0,因此我们可以@NameBinding连接过滤器。

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;import javax.ws.rs.HttpMethod;
import javax.ws.rs.NameBinding;@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@HttpMethod("PATCH")
@Documented
@NameBinding
public @interface PATCH {
}

因此,这里是ReaderInterceptor的实现,该实现将处理传入的流并将其替换为修补版本。 请注意,还使用@PATCH对该类进行了注释,以使@NamedBinding魔术起作用,并且还缺少许多错误处理,因为这是一个简单的POC。

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;import com.github.fge.jsonpatch.JsonPatch;
import com.github.fge.jsonpatch.JsonPatchException;import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;import java.lang.annotation.Annotation;
import java.lang.reflect.Method;import javax.ws.rs.GET;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.ReaderInterceptor;
import javax.ws.rs.ext.ReaderInterceptorContext;import org.glassfish.jersey.message.MessageBodyWorkers;@Provider
@PATCH
public class PatchReader implements ReaderInterceptor {private UriInfo info;private MessageBodyWorkers workers;@Contextpublic void setInfo(UriInfo info) {this.info = info;}@Contextpublic void setWorkers(MessageBodyWorkers workers) {this.workers = workers;}@Overridepublic Object aroundReadFrom(ReaderInterceptorContext readerInterceptorContext) throws IOException,WebApplicationException {// Get the resource we are being called on, // and find the GET methodObject resource = info.getMatchedResources().get(0);Method found = null;for (Method next : resource.getClass().getMethods()) {if (next.getAnnotation(GET.class) != null) {found = next;break;}}if (found != null) {// Invoke the get method to get the state we are trying to patch//Object bean;try {bean = found.invoke(resource);} catch (Exception e) {throw new WebApplicationException(e);}// Convert this object to a an aray of bytes ByteArrayOutputStream baos = new ByteArrayOutputStream();MessageBodyWriter<? super Object> bodyWriter =workers.getMessageBodyWriter(Object.class, bean.getClass(), new Annotation[0], MediaType.APPLICATION_JSON_TYPE);bodyWriter.writeTo(bean, bean.getClass(), bean.getClass(), new Annotation[0], MediaType.APPLICATION_JSON_TYPE,new MultivaluedHashMap<String, Object>(), baos);// Use the Jackson 2.x classes to convert both the incoming patch  // and the current state of the object into a JsonNode / JsonPatchObjectMapper mapper = new ObjectMapper();JsonNode serverState = mapper.readValue(baos.toByteArray(), JsonNode.class);JsonNode patchAsNode = mapper.readValue(readerInterceptorContext.getInputStream(), JsonNode.class);JsonPatch patch = JsonPatch.fromJson(patchAsNode);try {// Apply the patchJsonNode result = patch.apply(serverState);// Stream the result & modify the stream on the readerInterceptorByteArrayOutputStream resultAsByteArray = new ByteArrayOutputStream();mapper.writeValue(resultAsByteArray, result);readerInterceptorContext.setInputStream(new ByteArrayInputStream(resultAsByteArray.toByteArray()));// Pass control back to the Jersey codereturn readerInterceptorContext.proceed();} catch (JsonPatchException e) {throw new WebApplicationException(Response.status(500).type("text/plain").entity(e.getMessage()).build());}} else {throw new IllegalArgumentException("No matching GET method on resource");}}
}

因此,一旦部署完成,就可以开始处理数据,因此原始消息是:

{"list" : ["one","two"],"message" : "message","title" : "title"
}

因此,如果应用以下修补程序,则返回的结果是:

[{"op" : "replace","path" : "/message","value" : "otherMessage"},{"op" : "add","path" : "/list/-","value" : "three"}
]{"list" : ["one","two","three"],"message" : "otherMessage","title" : "title"
}

此示例说明,遵循简单的编码模式并使用简单的注释,将PATCH支持添加到您的类中相对比较简单。 这样,由于实现仅可以委托给您现有的PUT方法,因此PATCH支持变得微不足道。

更新: Jersey团队的Mirsolav Fuksa提醒我,为了使此实现符合PATCH RFC,它应在客户端执行OPTIONS请求时提供Accept-Patch标头。 您可以使用简单的CotnainerResponseFilter来做到这一点:

import java.io.IOException;import java.util.Collections;import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.ext.Provider;@Provider
public class OptionsAcceptHeader implements ContainerResponseFilter {@Overridepublic void filter(ContainerRequestContext requestContext,ContainerResponseContext responseContext) throws IOException {if ("OPTIONS".equals(requestContext.getMethod())) {if (responseContext.getHeaderString("Accept-Patch")==null) {responseContext.getHeaders().put("Accept-Patch", Collections.<Object>singletonList("application/json-patch+json"));  }}}
}

参考:来自Gerard Davison博客博客的JCG合作伙伴 Gerard Davison 对JAX-RS 2.0的透明PATCH支持 。

翻译自: https://www.javacodegeeks.com/2014/02/transparent-patch-support-in-jax-rs-2-0.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/365322.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java开发知识之Java的枚举

Java开发知识之Java的枚举 一丶什么是枚举 枚举可以理解为就是常量,在Java中我们定义常量.都是用 final语句. C中都是用const关键字. 枚举跟C概念都是一样的.就是特定的常量而已. 二丶Java中的枚举 java中的常量.一般都是final定义.但是我们讲过.final定义的常量.初始化的时候可…

linux php7 mongodb,CentOS 7下安装配置PHP7跟LAMP及MongoDB和Redis

CentOS 7下安装配置PHP7跟LAMP及MongoDB和Redis我是想能yum就yum&#xff0c;所有软件的版本一直会升级&#xff0c;注意自己当时的版本是不是已经更新了。首先装CentOS 7装好centos7后默认是不能上网的cd /etc/sysconfig/network-scripts/找到形如ifcfg-enp0s3的文件&#xff…

【汇总目录】C#

[2019年04月29日] C# textbox 自动滚动 [2019年02月07日] C#利用VUDP.cs开发网络通讯应用程序 [2019年02月06日] C#利用VINI.cs操作INI文件 [2018年12月19日] 控件数组批量生成控件 转载于:https://www.cnblogs.com/velscode/p/10535101.html

基于 Bootstrap 的响应式后台管理面板

你想建立一个后台管理面板或者分析仪表板吗&#xff1f;不需从头开始&#xff0c;Keen IO Bootstrap 是一个响应式的仪表盘模板&#xff0c;可以帮助你在几分钟内呈现数据&#xff0c;让你可以创建一个有吸引力的&#xff0c;定制的分析仪表板&#xff0c;随时可以展现给你的团…

Java:AspectJ的异常翻译

在这篇博客文章中&#xff0c;我描述了如何使用AspectJ自动将一种异常类型转换为另一种异常类型。 问题 有时&#xff0c;我们处于必须将异常&#xff08;通常由第三方库引发&#xff09;转换为另一种异常的情况。 假设您使用的是诸如hibernate之类的持久性框架&#xff0c;并…

sparkstreaming监听hdfs目录_大数据系列之Spark Streaming接入Kafka数据

Spark Streaming官方提供Receiver-based和Direct Approach两种方法接入Kafka数据&#xff0c;本文简单介绍两种方式的pyspark实现。1、Spark Streaming接入Kafka方式介绍Spark Streaming 官方提供了两种方式读取Kafka数据&#xff1a;一是Receiver-based Approach。该种读取模式…

php职业认证,如何用 PHP 进行 HTTP 认证

PHP 的 HTTP 认证机制在 PHP 以 Apache 模块方式运行时才有效&#xff0c;因此该功能不适用于 CGI 版本。在 Apache 模块的 PHP 脚本中&#xff0c;可以用 header() 函数来向客户端浏览器发送“Authentication Required”信息&#xff0c;使其弹出一个用户名/密码输入窗口。当用…

时间服务器

时间服务器配置&#xff1a; 1 安装软件包: [rootlocalhost ~]# yum install ntp –y 2 修改配置文件 [rootlocalhost ~]# vim /etc/ntp.conf # 允许内网其他机器同步时间 192.168.1.0该网段 restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap 允许任何ip的客户机都可以…

使用 HTML5 Canvas 绘制出惊艳的水滴效果

HTML5 在不久前正式成为推荐标准&#xff0c;标志着全新的 Web 时代已经来临。在众多 HTML5 特性中&#xff0c;Canvas 元素用于在网页上绘制图形&#xff0c;该元素标签强大之处在于可以直接在 HTML 上进行图形操作&#xff0c;具有极大的应用价值。 这里分享一个惊艳的 Canva…

Java EE 8:社区想要什么?

在进行了之前的两次社区调查之后&#xff0c;第一次调查于2013年12月发布&#xff0c;第二次调查于2014年1月发布&#xff0c;Oracle呼吁企业社区对Java EE 8进行第三次也是最后一次调查 。该调查的截止日期为2014年3月24日&#xff0c;12日。太平洋时间。 值得注意的是&#…

mysql 字符串类型 char varchar

字符类型用在存储名字、邮箱地址、家庭住址等描述性数据 char指的是定长字符&#xff0c;varchar指的是变长字符 #官网&#xff1a;https://dev.mysql.com/doc/refman/5.7/en/char.html #注意&#xff1a;char和varchar括号内的参数指的都是字符的长度#char类型&#xff1a;定长…

二叉树遍历规则

树的遍历顺序大体分为三种&#xff1a;前序遍历&#xff08;先根遍历、先序遍历&#xff09;&#xff0c;中序遍历&#xff08;中根遍历&#xff09;&#xff0c;后序遍历&#xff08;后根遍历&#xff09;。 如图所示二叉树&#xff1a; 前序遍历&#xff1a;前序遍历可以记为…

vue vue的table表格自适应_vue table autoHeight(vue 表格自动高度)

小编主要做的都是后台管理系统&#xff0c;采用布局多为头部、左侧菜单栏&#xff0c;右侧内容&#xff0c;头部和菜单栏固定位置&#xff0c;内容部分如果很长就会出现滚动条(iview和element都提供了布局容器)&#xff0c;后台管理系统多为表格的增删改查&#xff0c;so&#…

php网页的注册界面设计,HTML开发博客之注册页面设计(一)

CSS文件的引入新建文件reg.html文件首先我们来分析网页布局这是我们页面完成后的效果&#xff0c;网页分为三部分头部&#xff0c;主体&#xff0c;和底部我们按照这个顺序开始编写。头部导航栏的编写html>用户注册页面首页科技资讯心情随笔资源收藏图文图片留言板登陆/注册…

Arctext.js - 基于 CSS3 jQuery 的文本弯曲效果

Arctext.js 是基于 Lettering.js 的文本旋转插件&#xff0c;根据设置的旋转半径准确计算每个字母的旋转弧度并均匀分布。虽然 CSS3 也能够实现字符旋转效果&#xff0c;但是要让安排每个字母都沿着弯曲路径排布相当的复杂&#xff0c;结合 Arctext.js 则可以轻松实现这个效果。…

在JDT中使用Java 8 Lambda

旧 Curmudgeon 认识Smalltalk的Dude 在修改Eclipse Java开发工具 &#xff08;JDT&#xff09;项目正在开发的Java 8支持时&#xff0c;我一直在使用这种语言。 我承认我对Java 8中的lambda有点不满意。 当然&#xff0c;这来自于知道Smalltalk &#xff08;和LISP / Schem…

[POJ1463] Strategic game

题目链接&#xff1a; 传送门 题目大意&#xff1a; Bob非常享受玩电脑游戏的过程&#xff0c;尤其是策略游戏&#xff0c;但是在有些时候&#xff0c;他因为不能在第一时间找到最佳的策略而十分伤心。 现在&#xff0c;他遇到了一个问题。他必须保卫一个中世纪的城市&#xff…

zabbix邮件告警

zabbix邮件告警调用第三方邮件服务来发送邮件。 [roottiandong ~]# yum install mailx -y 修改配置文件 [roottiandong ~]# vim /etc/mail.rc 67 set from15600857257163.com smtpsmtp.163.com 68 set smtp-auth-user15600857257163.com 69 set smtp-auth-password密码&#xf…

模糊推理机制 matlab,基于模糊综合评判推理机制的学生素质评价系统设计与实现...

第22卷第2期2002年2月文章编号&#xff1a;(2002)l00l-908l2-008l-03计算机应用ComputerAppIicationsVoI.22,No.2Feb.,2002基于模糊综合评判推理机制的学生素质评价系统设计与实现尹世群(西南师范大学计算机与信息科学学院&#xff0c;重庆4007l5)摘要&#xff1a;根据模糊数学…

SweetAlert – 替代 Alert 的漂亮的提示效果

Sweet Alert 是一个替代传统的 JavaScript Alert 的漂亮提示效果。SweetAlert 自动居中对齐在页面中央&#xff0c;不管您使用的是台式电脑&#xff0c;手机或平板电脑看起来效果都很棒。另外提供了丰富的自定义配置选择&#xff0c;可以灵活控制。 在线演示 插件下载 您可…