具有链接资源的Spring RestTemplate

Spring Data REST是一个了不起的项目,它提供了一些机制来将基于Spring Data的存储库中的资源公开为REST资源。

使用链接资源公开服务

考虑两个简单的基于JPA的实体,课程和教师:

@Entity
@Table(name = "teachers")
public class Teacher {@Id@GeneratedValue(strategy = GenerationType.AUTO)@Column(name = "id")private Long id;@Size(min = 2, max = 50)@Column(name = "name")private String name;@Column(name = "department")@Size(min = 2, max = 50)private String department;    ...
}@Entity
@Table(name = "courses")
public class Course {@Id@GeneratedValue(strategy = GenerationType.AUTO)@Column(name = "id")private Long id;@Size(min = 1, max = 10)@Column(name = "coursecode")private String courseCode;@Size(min = 1, max = 50)@Column(name = "coursename")private String courseName;@ManyToOne@JoinColumn(name = "teacher_id")private Teacher teacher;....
}

本质上,该关系如下所示:

课程老师

现在,将这些实体作为REST资源公开所需要做的就是以这种方式在基于JPA的Spring Data存储库上添加@RepositoryRestResource批注,首先是“ Teacher”资源:

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import univ.domain.Teacher;@RepositoryRestResource
public interface TeacherRepo extends JpaRepository<Teacher, Long> {
}

并公开课程资源:

@RepositoryRestResource
public interface CourseRepo extends JpaRepository<Course, Long> {
}

完成此操作并假设数据存储区中已经有几名教师和几门课程,关于课程的GET将产生以下类型的响应:

{"_links" : {"self" : {"href" : "http://localhost:8080/api/courses{?page,size,sort}","templated" : true}},"_embedded" : {"courses" : [ {"courseCode" : "Course1","courseName" : "Course Name 1","version" : 0,"_links" : {"self" : {"href" : "http://localhost:8080/api/courses/1"},"teacher" : {"href" : "http://localhost:8080/api/courses/1/teacher"}}}, {"courseCode" : "Course2","courseName" : "Course Name 2","version" : 0,"_links" : {"self" : {"href" : "http://localhost:8080/api/courses/2"},"teacher" : {"href" : "http://localhost:8080/api/courses/2/teacher"}}} ]},"page" : {"size" : 20,"totalElements" : 2,"totalPages" : 1,"number" : 0}
}

特定的课程如下所示:

{"courseCode" : "Course1","courseName" : "Course Name 1","version" : 0,"_links" : {"self" : {"href" : "http://localhost:8080/api/courses/1"},"teacher" : {"href" : "http://localhost:8080/api/courses/1/teacher"}}
}

如果您想知道“ _links”,“ _ embedded”是什么– Spring Data REST使用超文本应用程序语言(或简称HAL)来表示链接,例如说一门课程和一位老师之间的链接。

基于HAL的REST服务–使用

有了基于HAL的REST服务,我想到的问题就是如何为该服务编写客户端。 我相信有更好的方法可以做到这一点,但是接下来的工作对我来说很有效,我欢迎任何更简洁的编写客户方法。

首先,我修改了RestTemplate来注册一个定制的Json转换器,该转换器可以理解基于HAL的链接:

public RestTemplate getRestTemplateWithHalMessageConverter() {RestTemplate restTemplate = new RestTemplate();List<HttpMessageConverter<?>> existingConverters = restTemplate.getMessageConverters();List<HttpMessageConverter<?>> newConverters = new ArrayList<>();newConverters.add(getHalMessageConverter());newConverters.addAll(existingConverters);restTemplate.setMessageConverters(newConverters);return restTemplate;
}private HttpMessageConverter getHalMessageConverter() {ObjectMapper objectMapper = new ObjectMapper();objectMapper.registerModule(new Jackson2HalModule());MappingJackson2HttpMessageConverter halConverter = new TypeConstrainedMappingJackson2HttpMessageConverter(ResourceSupport.class);halConverter.setSupportedMediaTypes(Arrays.asList(HAL_JSON));halConverter.setObjectMapper(objectMapper);return halConverter;
}

Spring HATEOS项目提供了Jackson2HalModule并了解HAL表示形式。

有了这个闪亮的新RestTemplate,首先让我们创建一个Teacher实体

Teacher teacher1 = new Teacher();
teacher1.setName("Teacher 1");
teacher1.setDepartment("Department 1");
URI teacher1Uri =testRestTemplate.postForLocation("http://localhost:8080/api/teachers", teacher1);

请注意,在创建实体时,响应为http状态码201,位置标头指向新创建的资源的uri,Spring RestTemplate提供了一种巧妙的方式来通过API发布和获取此位置标头。 因此,现在我们有一个Teacher1Uri代表新创建的老师。

给定此教师URI,现在让我们检索教师 ,教师资源的原始json如下所示:

{"name" : "Teacher 1","department" : "Department 1","version" : 0,"_links" : {"self" : {"href" : "http://localhost:8080/api/teachers/1"}}
}

并使用RestTemplate来检索它:

ResponseEntity<Resource<Teacher>> teacherResponseEntity= testRestTemplate.exchange("http://localhost:8080/api/teachers/1", HttpMethod.GET, null, new ParameterizedTypeReference<Resource<Teacher>>() {
});Resource<Teacher> teacherResource = teacherResponseEntity.getBody();Link teacherLink = teacherResource.getLink("self");
String teacherUri = teacherLink.getHref();Teacher teacher = teacherResource.getContent();

Jackson2HalModule可以帮助干净地解压缩链接并掌握教师实体本身。 我之前已经在这里解释了ParameterizedTypeReference。

现在,更棘手的部分是创建课程。

创建课程很棘手,因为它与教师有关系,使用HAL表示这种关系并不是那么简单。 创建课程的原始POST如下所示:

{"courseCode" : "Course1","courseName" : "Course Name 1","version" : 0,"teacher" : "http://localhost:8080/api/teachers/1"
}

请注意,对教师的引用是一个URI,这就是HAL如何表示专门针对POST内容的嵌入式引用,因此现在可以通过RestTemplate获得此表单。

首先创建一个课程:

Course course1 = new Course();
course1.setCourseCode("Course1");
course1.setCourseName("Course Name 1");

在这一点上,通过处理json树表示形式并将教师链接添加为教师uri,可以更轻松地提供教师链接:

ObjectMapper objectMapper = getObjectMapperWithHalModule();
ObjectNode jsonNodeCourse1 = (ObjectNode) objectMapper.valueToTree(course1);
jsonNodeCourse1.put("teacher", teacher1Uri.getPath());

并发布此内容,应与链接的老师一起创建课程:

URI course1Uri = testRestTemplate.postForLocation(coursesUri, jsonNodeCourse1);

并检索此新创建的课程:

ResponseEntity<Resource<Course>> courseResponseEntity= testRestTemplate.exchange(course1Uri, HttpMethod.GET, null, new ParameterizedTypeReference<Resource<Course>>() {
});Resource<Course> courseResource = courseResponseEntity.getBody();
Link teacherLinkThroughCourse = courseResource.getLink("teacher");

这总结了如何使用RestTemplate创建和检索链接的资源,欢迎提出其他建议。

  • 如果您有兴趣进一步探索它,可以在github repo上找到整个示例–测试在这里 。

翻译自: https://www.javacodegeeks.com/2014/12/spring-resttemplate-with-a-linked-resource.html

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

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

相关文章

POJ 1521 Entropy

求哈夫曼树的平均码长&#xff0c;用优先队列来写&#xff0c;先记录某个字符在字符串里出现的次数&#xff0c;然后放入 队列。依次取出第一小和第二小的数&#xff0c;将两个数相加&#xff0c;构成新的虚拟结点&#xff0c;放入队列中。 /*Accepted 196K 0MS C …

事件处理详解

前言 本文大概整理下绑定事件的几种方式&#xff0c;兼容IE8- 的方式&#xff08;如果需要的话&#xff09;&#xff0c;事件委托&#xff0c;阻止传播&#xff0c;取消默认行为&#xff0c;event对象等。 之前做的多是手机端页面&#xff0c;监听事件也一直是 addEventListene…

用户会话,数据控件和AM池

最近&#xff0c;有人问我有关应用程序模块池的有趣问题。 众所周知&#xff0c;AM池包含用户会话引用的应用程序模块实例&#xff0c;这允许会话在后续请求时从池中获取完全相同的AM实例。 如果应用程序中有多个根应用程序模块&#xff0c;那么每个模块都将拥有自己的AM池&am…

对Group_concaT函数利用剖析 (转)

作者&#xff1a;晓华 开篇介绍 在FLYH4T大哥的“Mysql5注射技巧总结”一文中介绍了通过使用“information_schema”库实现遍历猜解库名表名以及字段名的技术&#xff0c;解决了一些以前使用工具无法猜解到的库名表名以及字段名的问题&#xff0c;提高了注射的效率。关于此文的…

用 CSS 实现元素垂直居中,有哪些好的方案?

DIV居中的经典方法 1. 实现DIV水平居中 设置DIV的宽高&#xff0c;使用margin设置边距0 auto&#xff0c;CSS自动算出左右边距&#xff0c;使得DIV居中。 1 div{ 2 width: 100px; 3 height: 100px; 4 margin: 0 auto; 5 } 缺点&#xff1a;需要设置div的宽度 2.…

使用wss和HTTPS / TLS保护WebSocket的安全

是这个博客的第50条提示&#xff0c;是的&#xff01; 技术提示&#xff03;49说明了如何使用用户名/密码和Servlet安全机制保护WebSocket的安全。 本技术提示将说明如何在WildFly上使用HTTPS / TLS保护WebSocket。 让我们开始吧&#xff01; 创建一个新的密钥库&#xff1a…

时钟同步及其应用(接上一篇)

在linux下做的时钟同步的工作终于暂时告一段落了。 前面简单的做了客户端和服务器端的同步&#xff0c;在基于时间同步的机制上&#xff0c;将系统的1s的时间划分多个时槽。由于此时间同步应用在分布式系统中&#xff0c;涉及到多个客户端和服务器通信的问题&#xff0c;因此划…

Java性能调优调查结果(第二部分)

这是系列文章的第二篇&#xff0c;我们将分析2014年10月进行的性能调整调查的结果。如果您尚未阅读第一部分&#xff0c;我们建议从此处开始 。 第二部分将重点监视Java应用程序的性能问题。 特别是&#xff0c;我们尝试回答以下问题&#xff1a; 人们如何发现性能问题&#x…

HDU 2094 产生冠军

判断顶点入度是否唯一即可。如果入度为0的节点只有一个&#xff0c;输出Yes&#xff0c;否则输出No。 代码&#xff1a; 1 #include<iostream>2 #include<cstring>3 4 using namespace std;5 6 int len;7 int map[1001][1001];8 char name[1001][100];9 10 int fu…

简单的css缩放动画,仿腾讯新闻的分享按钮和美团app底部的图标样式

最近看到一些好看的hover的图形缩放效果。然后自己就写了下&#xff0c;发现这2种效果都不错。如果伙伴们更好的实现方式可以在下面留言哦~ 还有美团的效果&#xff0c;我就不展示了&#xff0c;喜欢的可以去app应用上看看。 这两种效果&#xff0c;其实实现的原理是一样的&…

Java性能调优调查结果(第一部分)

我们在2014年10月进行了Java性能调优调查。该调查的主要目的是收集对Java性能世界的见解&#xff0c;以改进Plumbr产品。 但是&#xff0c;我们也很高兴与您分享有趣的结果。 我们收集的数据为进行冗长的分析提供了素材&#xff0c;因此我们决定将结果划分为一系列博客文章。 这…

asp.net ViewState详解

ViewState是一个被误解很深的动物了。我希望通过此文章来澄清人们对ViewState的一些错误认识。为了达到这个目的&#xff0c;我决定从头到尾详细的描述一下整个ViewState的工作机制&#xff0c;其中我会同时用一些例子说明我文章中的观点&#xff0c;结论。比如我会用静态控件(…

OSGi Testsuite:引入类名过滤器

OSGi Testsuite是一个JUnit测试运行程序 &#xff0c;它动态地收集要执行的测试类。 它已经由我的同伴Rdiger大约一年前出版&#xff0c;并且已经在某些项目中证明是有用的。 但是对于gonsole&#xff0c;我们必须使用一个难看的补丁&#xff0c;因为1.0版仅支持.*Test后缀匹配…

javascript数字验证(转)

转自http://www.cnblogs.com/lovelace821/archive/2009/04/27/1444654.html js验证数字 javascript限制输入的只能是数字&#xff0c;判断event.keyCode的值&#xff0c;并将它限定只能为数字&#xff0c;如果不是数字&#xff0c;则返回错误&#xff0c;如果是数字&#xff0c…

需要微缓存吗? 营救记忆

缓存解决了各种各样的性能问题。 有很多方法可以将缓存集成到我们的应用程序中。 例如&#xff0c;当我们使用Spring时&#xff0c;可以轻松使用Cacheable支持。 非常简单&#xff0c;但我们仍然必须配置缓存管理器&#xff0c;缓存区域等。有时&#xff0c;就像用大锤砸破坚果…

es6 对象的扩展

1.属性的简洁表示法function f(x,y) {return {x,y};}// 等同于function f(x,y){return {x:x,y:y};}f(1,2)   // Object {x:1,y:2}例如&#xff1a;let birth 2000/01/01;const Person {name: 张三&#xff0c;// 等同于 birth: birthbirth,// 等同于hello: function()...he…

windows下命令行修改系统时间;修改系统时间的软件

找了很久,都没有找到,还找了关键词 dos下修改系统时间 因为看到linux下修改系统时间是用hwclock 命令写入主板芯片. 而我由于某些原因想自动化修改系统时间,所以找windows下修改系统时间的软件 没有找到. 有一个 意天禁止修改系统时间开发包(系统时间保护组件) 1.0.0.1 ,可以禁…

如何摆脱JavaFX中的重点突出显示

今天&#xff0c;有人问我是否知道摆脱JavaFX控件&#xff08;分别是按钮&#xff09;的焦点突出的方法&#xff1a; 有关此问题的大多数文章和提示建议添加&#xff1a; .button:focused {-fx-focus-color: transparent; }但是使用这种样式&#xff0c;仍然会留下这样的光芒…

extjs 基础部分

创建对象的方法&#xff1a; 使用new 关键字创建对象。 new classname ([config]) 使用Ext.create方法创建。 Ext.create(classname,[config]) new Ext.Viewport({}) 修改为Ext.create(Ext.Viewport,{}) Ext.widget 或Ext.createWidget 创建对象 使用Ext.ns 或者Ext.namespace…

Java时区处理初学者指南

基本时间观念 大多数Web应用程序必须支持不同的时区&#xff0c;而正确处理时区绝非易事。 更糟糕的是&#xff0c;您必须确保各种编程语言&#xff08;例如&#xff0c;前端JavaScript&#xff0c;中间件中的Java和作为数据存储库的MongoDB&#xff09;之间的时间戳是一致的。…