在Spring Boot中整合Katharsis,来快速开发JSON API的Web应用

news2024/9/21 0:31:29

1 简介

我们进行Web API开发的时候,经常会使用Json格式的消息体,而Json格式非常灵活,不同的人会有不同的设计风格和实现,而JSON API提供了一套标准。但它并不提供直接实现。

Katharsis是JSON API的Java实现,使用它可以快速开发出Json based的Web接口,还能快速的整合到Spring中。今天我们就来试试如何在Spring Boot中使用Katharsis。

2 整合过程

2.1 添加依赖

我们在Spring Boot中添加依赖如下,包括常规的starter、jpa和h2,而整合Katharsis只需要katharsis-spring即可。

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
  </dependency>
  <dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
  </dependency>
  <dependency>
    <groupId>io.katharsis</groupId>
    <artifactId>katharsis-spring</artifactId>
    <version>3.0.2</version>
  </dependency>
</dependencies>

2.2 Entity类

我们定义两个Entity,一个是学生,一个是教室,而教室对象会包含多个学生。

学生:

@JsonApiResource(type = "students")
@Entity
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Student {
    @JsonApiId
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;
}

教室:

@JsonApiResource(type = "classrooms")
@Entity
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Classroom {
    @JsonApiId
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "classrooms_students", joinColumns = @JoinColumn(name = "classroom_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "student_id", referencedColumnName = "id"))
    @JsonApiRelation(serialize= SerializeType.EAGER)
    private Set<Student> students;
}

注解JsonApiResource这个会指定资源名称,这个会影响api的URL,注解JsonApiId则指定资源的id。

2.3 资源操作类

Katharsis使用ResourceRepository来对资源进行增删改查操作,这个跟数据库的增删改查类似,但属于更高一层。抽象到资源RESTful的资源层面,然后再调用数据库的Repository来操作,这里统一实现ResourceRepositoryV2接口。

@Component
public class StudentResourceRepository implements ResourceRepositoryV2<Student, Long> {

    private final StudentRepository studentRepository;

    public StudentResourceRepository(StudentRepository studentRepository) {
        this.studentRepository = studentRepository;
    }

    @Override
    public Student findOne(Long id, QuerySpec querySpec) {
        Optional<Student> student = studentRepository.findById(id);
        return student.orElse(null);
    }

    @Override
    public ResourceList<Student> findAll(QuerySpec querySpec) {
        return querySpec.apply(studentRepository.findAll());
    }

    @Override
    public ResourceList<Student> findAll(Iterable<Long> ids, QuerySpec querySpec) {
        return querySpec.apply(studentRepository.findAllById(ids));
    }

    @Override
    public <S extends Student> S save(S entity) {
        return studentRepository.save(entity);
    }

    @Override
    public void delete(Long id) {
        studentRepository.deleteById(id);
    }

    @Override
    public Class<Student> getResourceClass() {
        return Student.class;
    }

    @Override
    public <S extends Student> S create(S entity) {
        return save(entity);
    }

}

而数据库方面我们使用JPA实现即可:

public interface StudentRepository extends JpaRepository<Student, Long> {
}

上面的代码是针对Student资源类型的,对Classroom类似,就不把代码列出来了。

2.4 配置

为了使用Katharsis,我们需要在配置中引入KatharsisConfigV3,我们直接在Spring Boot启动类中引入即可:

@SpringBootApplication
@Import(KatharsisConfigV3.class)
public class KatharsisExample {
    public static void main(String[] args) {
        SpringApplication.run(KatharsisExample.class, args);
    }
}

Spring Boot的配置文件如下:

server.port=8080
server.servlet.context-path=/

katharsis.domainName=https://www.pkslow.com
katharsis.pathPrefix=/api/katharsis

spring.datasource.url = jdbc:h2:mem:springKatharsis;DB_CLOSE_DELAY=-1
spring.datasource.username = sa
spring.datasource.password =

spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto = create-drop
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.H2Dialect
spring.jpa.properties.hibernate.globally_quoted_identifiers=true

katharsis.pathPrefix是URL前缀,而katharsis.domainName会影响Self Link等返回。

2.5 初始化数据

为了方便测试,初始化一些数据进行查询:

@Component
public class InitData {

    private final ClassroomRepository classroomRepository;

    private final StudentRepository studentRepository;

    public InitData(ClassroomRepository classroomRepository, StudentRepository studentRepository) {
        this.classroomRepository = classroomRepository;
        this.studentRepository = studentRepository;
    }

    @PostConstruct
    private void setupData() {
        Set<Student> students = new HashSet<>();
        Student student = Student.builder().name("Larry Deng").build();
        students.add(student);
        studentRepository.save(student);
        student = Student.builder().name("Eason").build();
        students.add(student);
        studentRepository.save(student);
        student = Student.builder().name("JJ Lin").build();
        students.add(student);
        studentRepository.save(student);

        Classroom classroom = Classroom.builder().name("Classroom No.1").students(students)
                .build();
        classroomRepository.save(classroom);
    }
}

至此则整合完毕了。

3 测试

整合完后启动,就可以用curl或Postman开始测试了:

查询一个student:

$ curl http://localhost:8080/api/katharsis/students/1 | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   139    0   139    0     0   9828      0 --:--:-- --:--:-- --:--:-- 23166
{
  "data": {
    "id": "1",
    "type": "students",
    "attributes": {
      "name": "Larry Deng"
    },
    "links": {
      "self": "https://www.pkslow.com/api/katharsis/students/1"
    }
  }
}

查询多个student:

$ curl http://localhost:8080/api/katharsis/students | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   429    0   429    0     0   3633      0 --:--:-- --:--:-- --:--:--  3830
{
  "data": [
    {
      "id": "1",
      "type": "students",
      "attributes": {
        "name": "Larry Deng"
      },
      "links": {
        "self": "https://www.pkslow.com/api/katharsis/students/1"
      }
    },
    {
      "id": "2",
      "type": "students",
      "attributes": {
        "name": "Eason"
      },
      "links": {
        "self": "https://www.pkslow.com/api/katharsis/students/2"
      }
    },
    {
      "id": "3",
      "type": "students",
      "attributes": {
        "name": "JJ Lin"
      },
      "links": {
        "self": "https://www.pkslow.com/api/katharsis/students/3"
      }
    }
  ],
  "meta": {
    "totalResourceCount": null
  }
}

查询一个教室:

$ curl http://localhost:8080/api/katharsis/classrooms/4 | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   834    0   834    0     0  62462      0 --:--:-- --:--:-- --:--:--  116k
{
  "data": {
    "id": "4",
    "type": "classrooms",
    "attributes": {
      "name": "Classroom No.1"
    },
    "relationships": {
      "students": {
        "data": [
          {
            "id": "3",
            "type": "students"
          },
          {
            "id": "2",
            "type": "students"
          },
          {
            "id": "1",
            "type": "students"
          }
        ],
        "links": {
          "self": "https://www.pkslow.com/api/katharsis/classrooms/4/relationships/students",
          "related": "https://www.pkslow.com/api/katharsis/classrooms/4/students"
        }
      }
    },
    "links": {
      "self": "https://www.pkslow.com/api/katharsis/classrooms/4"
    }
  },
  "included": [
    {
      "id": "1",
      "type": "students",
      "attributes": {
        "name": "Larry Deng"
      },
      "links": {
        "self": "https://www.pkslow.com/api/katharsis/students/1"
      }
    },
    {
      "id": "2",
      "type": "students",
      "attributes": {
        "name": "Eason"
      },
      "links": {
        "self": "https://www.pkslow.com/api/katharsis/students/2"
      }
    },
    {
      "id": "3",
      "type": "students",
      "attributes": {
        "name": "JJ Lin"
      },
      "links": {
        "self": "https://www.pkslow.com/api/katharsis/students/3"
      }
    }
  ]
}

新增一个学生:

$ curl --header "Content-Type: application/json"   --request POST   --data '{
    "data": {
        "type": "students",
        "attributes": {
            "name": "Justin"
        }
    }
}'   http://localhost:8080/api/katharsis/students | jq .

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   249    0   135  100   114  11202   9459 --:--:-- --:--:-- --:--:-- 41500
{
  "data": {
    "id": "6",
    "type": "students",
    "attributes": {
      "name": "Justin"
    },
    "links": {
      "self": "https://www.pkslow.com/api/katharsis/students/6"
    }
  }
}

修改:

$ curl --header "Content-Type: application/json"   --request PATCH   --data '{
    "data": {
        "id":"6",
        "type": "students",
        "attributes": {
            "name": "Justin Wu"
        }
    }
}'   http://localhost:8080/api/katharsis/students/6 | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   273    0   138  100   135   4425   4329 --:--:-- --:--:-- --:--:-- 10920
{
  "data": {
    "id": "6",
    "type": "students",
    "attributes": {
      "name": "Justin Wu"
    },
    "links": {
      "self": "https://www.pkslow.com/api/katharsis/students/6"
    }
  }
}

删除:

$ curl --header "Content-Type: application/json"   --request DELETE   --data '{
    "data": {
        "id":"6",
        "type": "students",
        "attributes": {
            "name": "Justin Wu"
        }
    }
}'   http://localhost:8080/api/katharsis/students/6 | jq .

至此,我们已经覆盖了增删改查操作了。而我们在代码中并没有去写我们之前常写的Controller,却可以访问对应接口。因为Katharsis默认已经帮我们实现了,可以查看类:io.katharsis.core.internal.dispatcher.ControllerRegistry

4 代码

代码请看GitHub: https://github.com/LarryDpk/pkslow-samples

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

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

相关文章

canal env create (mysql -> kafka)

&#xff08;1&#xff09;获取资源及解压 选定安装路径 cd /home下载canal.admin wget https://github.com/alibaba/canal/releases/download/canal-1.1.5/canal.admin-1.1.5.tar.gz解压canal-admin mkdir canal-admin tar -zxvf canal.admin-1.1.5.tar.gz -C canal-adm…

Nginx服务器上安装SSL证书

Nginx服务器上安装SSL证书1、前提条件2、nginx安装http_ssl_module模块2.1 查看是否安装过http_ssl_module2.2 进入nginx源文件目录2.3 重新编译nginx2.4 用新的nginx覆盖旧的3、https配置(SSL证书安装)3.1 下载证书文件和密钥文件3.2 服务器上创建cert文件夹3.3 配置nginx.con…

2023年中级计算机软考怎么报考呢?软考证书有用吗?

计算机软考简称软考&#xff0c;全称计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试&#xff0c;是由人力资源和社会保障部&#xff08;原人事部&#xff09;、工业和信息化部&#xff08;原信息产业部&#xff09;领导的国家级考试&#xff0c;其目的是&#…

C++——stack和queue的介绍和使用

文章目录1. stack的介绍和使用1.1 stack的介绍1.2 stack的使用1.3 几个比较经典的oj题2. queue的介绍和使用2.1 queue的介绍2.2 queue的使用3. 容器适配器3.1 什么是适配器3.2 STL标准库中stack和queue的底层结构3.3 deque的简单介绍(简单介绍)3.3.1 deque的原理介绍3.3.2 dequ…

王道操作系统笔记(四)——— 进程同步与互斥

文章目录一、同步与互斥的概念1.1 同步与互斥的基本概念1.2 临界资源与共享资源1.3 独占设备与共享设备二、实现临界区互斥的基本方法2.1 软件实现方法2.1.1 单标志法2.1.2 双标志先检查法2.1.3 双标志后检查法2.1.4 Peterson 算法2.1.5 软件实现方法总结2.2 硬件实现方法2.2.1…

OpenMMLab 计算机视觉 # day2: 图像分类与基础视觉模型

相关资源: github 第二课 图像分类与基础视觉模型 图像分类 图像分类任务&#xff1a;给定一张图片&#xff0c;识别图像中的物体是什么 X∈RH∗W∗3→{1,2..,K}X\in R^{H*W*3} \rightarrow \{1,2..,K\}X∈RH∗W∗3→{1,2..,K}&#xff1b; 从图片中学习&#xff1a; …

Linux--Version Branch

参考链接1. Linux Version BranchLinux的发行版本大体分可为两类。一类是商业公司维护的发行版本&#xff0c;以Redhat&#xff08;RHEL&#xff09;为代表一类是社区组织维护的发行版本&#xff0c;以Debian为代表。2.Debian branchDebian系列主要包含Debian和Ubuntu等。Debia…

操作系统权限提升(十二)之绕过UAC提权-Windows UAC概述

系列文章 操作系统权限提升(一)之操作系统权限介绍 操作系统权限提升(二)之常见提权的环境介绍 操作系统权限提升(三)之Windows系统内核溢出漏洞提权 操作系统权限提升(四)之系统错误配置-Tusted Service Paths提权 操作系统权限提升(五)之系统错误配置-PATH环境变量提权 操作…

已解决TypeError: eval() arg 1 must be a string, bytes or code object

已解决TypeError: eval() arg 1 must be a string, bytes or code object 文章目录报错问题报错翻译报错原因解决方法联系博主免费帮忙解决报错报错问题 粉丝群里面的一个小伙伴&#xff0c;想用Python爬虫然后解析数据&#xff0c;但是发生了报错&#xff08;当时他心里瞬间…

YOLOv8 Ultralytics:最先进的 YOLO 模型——简介+实战教程

YOLOv8 Ultralytics&#xff1a;最先进的 YOLO 模型 什么是 YOLOv8&#xff1f; YOLOv8 是来自 Ultralytics 的最新的基于 YOLO 的对象检测模型系列&#xff0c;提供最先进的性能。 利用以前的 YOLO 版本&#xff0c; YOLOv8 模型更快、更准确 &#xff0c;同时为训练模型提…

unity Vuforia发布移动端,禁止相机权限,出绿屏,强制退出app,如何去掉PERMISSION ERROR

unity Vuforia发布移动端&#xff0c;禁止相机权限&#xff0c;出绿屏&#xff0c;强制退出app&#xff0c;如何去掉PERMISSION ERROR问题描述更改需求解决方案&#xff1a;总结&#x1f4a2;&#x1f4a2;版权声明问题描述 unityvuforia 发布移动端&#xff0c;运行时需要相机…

墨天轮《2022年中国数据库行业年度分析报告》正式发布,精彩抢先看

自2022年4月份起&#xff0c;墨天轮数据社区持续发布月度 《中国数据库行业分析报告》&#xff0c;目前已发布7期&#xff0c;点击超过10万次&#xff0c;下载近万次。 为总结过往&#xff0c;展望未来&#xff0c;墨天轮数据社区正式发布了《2022年中国数据库年度行业分析报告…

MAC(m1)-VsCode上传项目到GitHub仓库

安装Git集成插件&#xff1a; GitHub Pull requests 在Visual Studio Code中查看和管理GitHub拉取请求和问题 Git Graph Git图形化显示和操作 最新最全 VSCODE 插件推荐&#xff08;2023版&#xff09;_白墨石的博客-CSDN博客_vscode插件 在vscode使用git提交推送代码_水…

精选100个Python实战项目案例,送给缺乏实战经验的你

前言&#xff1a;随着 Python 语言的流行&#xff0c;越来越多的人加入到了 Python 的大家庭中。为什么这么多人学 Python &#xff1f;我要喊出那句话了&#xff1a;“人生苦短&#xff0c;我用 Python&#xff01;”&#xff0c;正是因为语法简单、容易学习&#xff0c;所以 …

Jetson 相机编码

Jetson 相机编码 Jetson相机编码是即将发布的“实践”系列的相关代码。有三个存储库: 1. camera-caps JetsonHacks Github存储库camera-caps 通过v4l2-ctl命令行工具提供了一个图形用户界面。您可能会发现&#xff0c;它可以方便地检查连接到Jetson上的V4L2相机的功能。这适…

复试算法练习Day17——从头到尾打印链表

复试算法练习Day17——从头到尾打印链表 题目描述 输入一个链表的头节点&#xff0c;按链表从尾到头的顺序返回每个节点的值&#xff08;用数组返回&#xff09;。 如输入{1,2,3}的链表如下图: 返回一个数组为[3,2,1] 0 < 链表长度 < 10000 示例1 输入&#xff1a;…

SpringMVC之JSON数据传输参数

目录 一&#xff1a;JSON普通数组 二&#xff1a;JSON对象数据 三&#xff1a;JSON对象数组 前面我们说过&#xff0c;现在比较流行的开发方式为异步调用。前后台以异步方式进行交换&#xff0c;传输的数据使用的是JSON,所以前端如果发送的是JSON数据&#xff0c;后端该如何…

C++11中的多线程的支持

C11中的多线程的支持 千禧年以后&#xff0c;主流的芯片厂商都开始生产多核处理器&#xff0c;所以并行编程越来越重要了。在C98中根本没有自己的一套多线程编程库,它采用的是C99中的POSIX标准的pthread库中的互斥锁,来完成多线程编程。 首先来简单一个概念:原子操作,即多线程…

目标检测框架在目标跟踪中的应用

目标检测框架在目标跟踪中的应用 从SiamRPN将跟踪问题定义为one-shot detection任务之后&#xff0c;出现了大量将检测组件由于跟踪的研究。不过Siamese系列一个很大的问题在于其本质仍然是一个模板匹配问题&#xff0c;网络关注的是寻找与target相似的东西&#xff0c;而忽视…

HCIA之数据发送过程

数据发送过程1、同广播域2、跨广播域&#xff08;需要将数据发送给网关&#xff0c;这通过路由器发包&#xff09;&#xff1a;总结1、同广播域 假设PC1要与PC2通讯&#xff1b; PC1不知道PC2的MAC地址&#xff0c;先发送ARP找到PC2的MAC地址&#xff1b; PC1知道了PC2的MAC地…