选择通过更改内容类型返回的详细程度,第二部分

在上一篇文章中 ,我们研究了使用MOXy的功能来控制特定实体的数据输出级别。 这篇文章着眼于Jersey 2.x提供的抽象,它允许您定义一组自定义的批注以具有相同的效果。

与之前一样,我们几乎没有什么琐碎的资源可以返回Jersey将为我们转换为JSON的对象,请注意,目前此代码中没有任何内容可以进行过滤-我不会将注释传递给
Response对象,如Jersey示例中所示:

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;@Path("hello")
public class SelectableHello {@GET@Produces({ "application/json; level=detailed", "application/json; level=summary", "application/json; level=normal" })public Message hello() {return new Message();}
}

在我的设计中,我将定义四个注释: NoViewSummaryViewNormalViewDetailedView 。 所有根对象都必须实现NoView注释,以防止暴露未注释的字段-您可能觉得在设计中没有必要。 所有这些类看起来都一样,所以我只显示一个。 请注意,创建AnnotationLiteral的工厂方法必须优先于创建动态代理以具有相同效果的工厂使用。 2.5中有代码,将忽略由java.lang.reflect.Proxy对象实现的任何注释,其中包括您可能从类中检索到的所有注释。 我正在为此提交修复程序。

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.enterprise.util.AnnotationLiteral;import org.glassfish.jersey.message.filtering.EntityFiltering;@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@EntityFiltering
public @interface NoView {/*** Factory class for creating instances of the annotation.*/public static class Factory extends AnnotationLiteral<NoView> implements NoView {private Factory() {}public static NoView get() {return new Factory();}}}

现在我们可以快速浏览一下Message Bean,这比我以前的示例稍微复杂一点,以非常简单的形式显示子图的过滤。 正如我之前说过的那样,在类的根部使用NoView注释进行注释–这应该意味着privateData不会返回给客户端,因为它没有特别地注释。

import javax.xml.bind.annotation.XmlRootElement;@XmlRootElement
@NoView
public class Message {private String privateData;@SummaryViewprivate String summary;@NormalViewprivate String message;@DetailedViewprivate String subtext;@DetailedViewprivate SubMessage submessage;public Message() {summary = "Some simple summary";message = "This is indeed the message";subtext = "This is the deep and meaningful subtext";submessage = new SubMessage();privateData = "The fox is flying tonight";}// Getters and setters not shown
}public class SubMessage {private String message;public SubMessage() {message = "Some sub messages";}// Getters and setters not shown
}

如前所述,资源类中没有代码可以处理过滤–我认为这是一个横切关注点,因此我将其抽象为WriterInterceptor。 请注意,如果使用的实体上没有NoView批注,则会抛出该异常。

import java.io.IOException;import java.lang.annotation.Annotation;import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;import javax.ws.rs.ServerErrorException;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.WriterInterceptor;
import javax.ws.rs.ext.WriterInterceptorContext;@Provider
public class ViewWriteInterceptor implements WriterInterceptor {private HttpHeaders httpHeaders;public ViewWriteInterceptor(@Context HttpHeaders httpHeaders) {this.httpHeaders = httpHeaders;}@Overridepublic void aroundWriteTo(WriterInterceptorContext writerInterceptorContext) throws IOException,WebApplicationException {// I assume this case will never happen, just to be sureif (writerInterceptorContext.getEntity() == null) {writerInterceptorContext.proceed();return;}else{Class<?> entityType = writerInterceptorContext.getEntity().getClass();String entityTypeString = entityType.getName();// Ignore any Jersey system classes, for example wadl//if (entityType == String.class  || entityType.isArray() || entityTypeString.startsWith("com.sun") || entityTypeString.startsWith("org.glassfish")) {writerInterceptorContext.proceed();return;}// Fail if the class doesn't have the default NoView annotation // this prevents any unannotated fields from showing up//else if (!entityType.isAnnotationPresent(NoView.class)) {throw new ServerErrorException("Entity type should be tagged with @NoView annotation " + entityType, Response.Status.INTERNAL_SERVER_ERROR);}}// Get hold of the return media type://MediaType mt = writerInterceptorContext.getMediaType();String level = mt.getParameters().get("level");// Get the annotations and modify as required//Set<Annotation> current = new LinkedHashSet<>();current.addAll(Arrays.asList(writerInterceptorContext.getAnnotations()));switch (level != null ? level : "") {default:case "detailed":current.add(com.example.annotation.DetailedView.Factory.get());case "normal":current.add(com.example.annotation.NormalView.Factory.get());case "summary":current.add(com.example.annotation.SummaryView.Factory.get());}writerInterceptorContext.setAnnotations(current.toArray(new Annotation[current.size()]));//writerInterceptorContext.proceed();}
}

最后,您必须手动启用EntityFilterFeature,为此,您可以在Application类中简单地注册它

import java.lang.annotation.Annotation;import javax.ws.rs.ApplicationPath;import org.glassfish.jersey.message.filtering.EntityFilteringFeature;
import org.glassfish.jersey.server.ResourceConfig;@ApplicationPath("/resources/")
public class SelectableApplication extends ResourceConfig {public SelectableApplication() {packages("...");// Set entity-filtering scope via configuration.property(EntityFilteringFeature.ENTITY_FILTERING_SCOPE, new Annotation[] {NormalView.Factory.get(), DetailedView.Factory.get(), NoView.Factory.get(), SummaryView.Factory.get()});register(EntityFilteringFeature.class);}}

一旦一切就绪并运行,应用程序将像以前一样响应:

GET .../hello Accept application/json; level=detailed or application/json
{"message" : "This is indeed the message","submessage" : {"message" : "Some sub messages"},"subtext" : "This is the deep and meaningful subtext","summary" : "Some simple summary"
}GET .../hello Accept application/json; level=normal
{"message" : "This is indeed the message","summary" : "Some simple summary"
}GET .../hello Accept application/json; level=summary
{"summary" : "Some simple summary"
}

这是直接使用MOXy批注的更好选择–使用自定义批注应该更容易将应用程序移植到过度实现中,即使您必须提供自己的过滤器也是如此。 最后,值得探讨的是Jersey扩展,它允许基于角色的筛选 ,我认为这在安全方面很有用。

参考: 通过改变内容类型来选择返回的详细程度,第二部分来自我们的JCG合作伙伴 Gerard Davison,位于Gerard Davison的博客博客中。

翻译自: https://www.javacodegeeks.com/2014/02/selecting-level-of-detail-returned-by-varying-the-content-type-part-ii.html

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

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

相关文章

jQuery.ajax success 与 complete 区别

作者QQ&#xff1a;1095737364 QQ群&#xff1a;123300273 欢迎加入&#xff01; 天天用,不知所以然: $.ajax({type: "post",url: url,dataType:html,success: function(data) { },complete: function(XMLHttpRequest, textStatus) { },error: function(){}}…

vscode如何设置回车自动换行缩进?

要解决这个问题&#xff0c;首先打开设置&#xff0c;查找tabsize&#xff0c;进入settings.json。 把"editor.autoIndent"的属性值改为false&#xff0c;即"editor.autoIndent": "false"&#xff0c;就可以了。

vue 过滤器使用的传参说明

在table中&#xff0c;需要对obj的数据类型进行文字转换&#xff0c;例如后台接口返回的姓别值&#xff1a;1&#xff0c;2。其中需要页面根据字典需要把1》男&#xff0c;2》女进行转换。 以前的习惯是每一个过滤方法都写一个方法进行转换&#xff0c;例如&#xff1a; 页面代…

leetcode 970. 强整数(Powerful Integers)

目录 题目描述&#xff1a;示例 1&#xff1a;示例 2&#xff1a;解法&#xff1a;题目描述&#xff1a; 给定两个正整数 x 和 y&#xff0c;如果某一整数等于 x^i y^j&#xff0c;其中整数 i > 0 且 j > 0&#xff0c;那么我们认为该整数是一个强整数。 返回值小于或等…

ruby sinatra mysql_一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用

前言现代软件工程越来越复杂&#xff0c;而开发效率随着软件复杂度增加呈指数型下降。为在提高开发效率的同时也能保证质量&#xff0c;越来越多团队开始践行敏捷开发方法。持续集成是敏捷开发的重要实践之一。它倡导团队通过自动化构建工具频繁地验证软件可用性&#xff0c;从…

Java 8:在新的Nashorn JS引擎中编译Lambda表达式

在最近的一篇文章中&#xff0c;我了解了Java 8和Scala如何实现Lambda表达式。 众所周知&#xff0c;Java 8不仅引入了对Javac编译器的改进&#xff0c;而且还引入了全新的解决方案-Nashorn。 这个新引擎旨在替代Java现有JavaScript解释器Rhino。 这为我们带来了JVM的前列&…

vue 组件开发

作者QQ&#xff1a;1095737364 QQ群&#xff1a;123300273 欢迎加入&#xff01;1.新建路由:router-->index.js,修改成下面的代码 import Vue from vueimport Router from vue-routerimport index from /components/index/indexVue.use(Router)export default new Ro…

sql中有一些保留字,当你的字段名是它的保留字时,这个时候sql语句的字段不加``就会报错...

sql中有一些保留字&#xff0c;当你的字段名是它的保留字时&#xff0c;这个时候sql语句的字段不加就会报错转载于:https://www.cnblogs.com/w123w/p/10673692.html

C++语言实现-邻接表

图的邻接表实现 邻接表是图的一种链式存储结构。主要是应对于邻接矩阵在顶点多边少的时候&#xff0c;浪费空间的问题。它的方法就是声明两个结构。如下图所示&#xff1a; 先来看看伪代码&#xff1a; typedef char Vertextype; //表结点结构 struct ArcNode { int adjvex; …

为了适应云数据库mySQL产品_为了适应不同的应用场景,云数据库mysql版提供的产品系列包括哪些...

{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],"search_count":[{"count_phone":4,"count":4}]},"card":[{"des":"阿里云数据库专家保驾护航&#xff0c;为用户…

TestNG:在一个测试类中使用@DataProvider依次运行测试

许多Java开发人员和自动化测试工程师在他们的工作中都使用TestNG作为测试框架。 我也不例外。 这是一个显而易见的选择&#xff0c;因为TestNG提供了非常强大的工具集&#xff0c;使处理各种测试变得更加容易。 为了证明这一点&#xff0c;我将在本文中向您展示如何解决一项不平…

mysql 数据库读取_教你如何从 MySQL 数据库读取数据

PHP MySQL 读取数据从 MySQL 数据库读取数据SELECT 语句用于从数据表中读取数据:SELECT column_name(s) FROM table_name我们可以使用 * 号来读取所有数据表中的字段&#xff1a;SELECT * FROM table_name如需学习更多关于 SQL 的知识&#xff0c;请访问我们的 SQL 教程。使用 …

GXC 钱包部署

参考: [ 官方 wiki ] 基于 Ubuntu 的 GXC 部署 基础环境 OS: Ubuntugxc: 官方 [ release 最新版本 ]下载 release 包(ubuntu) cd /usr/src wget https://github.com/gxchain/gxb-core/releases/download/v1.0.181106b/gxb_ubuntu_1.0.1801106.tar.gz 拷贝可执行命令到系统 /usr…

js-js的全局变量和局部变量

*** 全局变量&#xff1a;在script标签里面定义一个变量&#xff0c;这个变量在页面中js部分都可以使用   - 在方法外部使用&#xff0c;在方法内部使用&#xff0c;在另外一个script标签中使用 *** 局部变量&#xff1a;在方法内部定义一个变量&#xff0c;只能在方法内部调…

使用Lucene的新FreeTextSuggester查找长尾建议

Lucene的“ 建议”模块提供了许多有趣的自动建议实现&#xff0c;以便在用户将每个字符输入搜索框时为他们提供实时搜索建议。 例如&#xff0c; WFSTCompletionLookup将所有建议及其权重编译到一个紧凑的有限状态传感器中 &#xff0c;从而可以对基本建议进行快速前缀查找。 …

Java属性中指定Json的属性名称(序列化和反序列化)

序列化对象&#xff0c;只需要使用注解"JsonProperty(value "pwd")" import com.fasterxml.jackson.annotation.JsonProperty;public class User{JsonProperty(value "pwd")private String password; } 比如上面例子&#xff0c;在作为请求接…

网站表单输入框去除浏览器默认样式

网页不可避免的使用到表单&#xff0c;提交一些内容到后端&#xff0c;进行前后端交互。可是由于浏览器总是有各自的默认样式&#xff0c;所以需要对其进行清除。总的来说有以下几种&#xff1a; 1、input输入框获取焦点的时候&#xff0c;默认带蓝色边框&#xff0c;如果设计要…

mysql 查看锁表日志_MYSQL 表锁情况查看

查看锁表情况mysql> show status like ‘Table%’;—————————-——–| Variable_name | Value |—————————-——–| Table_locks_immediate | 795505 || Table_locks_waited | 0 || Table_open_cache_hits | 0 || Table_open_cache_misses | 0 || Table_ope…

js-原始类型和声明变量

** Java的基本数据类型&#xff1a;byte、short、int、long、float、double、char、boolean ** 定义变量 都是用关键字 var(ES6中可以使用const和let来定义变量&#xff0c;后面会有ES6的语法介绍) ** js的原始类型&#xff08;5个&#xff09; - string&#xff1a;字符串  …

Java,Scala,Guava和Trove集合-它们可以容纳多少数据?

关于我们的数据结构&#xff0c;令人着迷的事情之一是&#xff0c;即使我们对它们非常熟悉&#xff0c;我们仍然很难说出像HashMap这样基本的东西在1GB的内存中可以容纳多少个项目。 我们可能会在学校&#xff0c;高级开发人员那里学到这一点&#xff0c;或者由于数据结构选择不…