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

[复制链接]
发表于 2023-2-4 14:07:57 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
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即可。
  1. <dependencies>
  2.   <dependency>
  3.     <groupId>org.springframework.boot</groupId>
  4.     <artifactId>spring-boot-starter-web</artifactId>
  5.   </dependency>
  6.   <dependency>
  7.     <groupId>org.springframework.boot</groupId>
  8.     <artifactId>spring-boot-starter-data-jpa</artifactId>
  9.   </dependency>
  10.   <dependency>
  11.     <groupId>com.h2database</groupId>
  12.     <artifactId>h2</artifactId>
  13.   </dependency>
  14.   <dependency>
  15.     <groupId>io.katharsis</groupId>
  16.     <artifactId>katharsis-spring</artifactId>
  17.     <version>3.0.2</version>
  18.   </dependency>
  19. </dependencies>
复制代码
2.2 Entity类

我们定义两个Entity,一个是学生,一个是教室,而教室对象会包含多个学生。
学生:
  1. @JsonApiResource(type = "students")
  2. @Entity
  3. @Data
  4. @Builder
  5. @NoArgsConstructor
  6. @AllArgsConstructor
  7. public class Student {
  8.     @JsonApiId
  9.     @Id
  10.     @GeneratedValue(strategy = GenerationType.AUTO)
  11.     private Long id;
  12.     private String name;
  13. }
复制代码
教室:
  1. @JsonApiResource(type = "classrooms")
  2. @Entity
  3. @Data
  4. @Builder
  5. @NoArgsConstructor
  6. @AllArgsConstructor
  7. public class Classroom {
  8.     @JsonApiId
  9.     @Id
  10.     @GeneratedValue(strategy = GenerationType.AUTO)
  11.     private Long id;
  12.     private String name;
  13.     @ManyToMany(fetch = FetchType.EAGER)
  14.     @JoinTable(name = "classrooms_students", joinColumns = @JoinColumn(name = "classroom_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "student_id", referencedColumnName = "id"))
  15.     @JsonApiRelation(serialize= SerializeType.EAGER)
  16.     private Set<Student> students;
  17. }
复制代码
注解JsonApiResource这个会指定资源名称,这个会影响api的URL,注解JsonApiId则指定资源的id。
2.3 资源操作类

Katharsis使用ResourceRepository来对资源进行增删改查操作,这个跟数据库的增删改查类似,但属于更高一层。抽象到资源RESTful的资源层面,然后再调用数据库的Repository来操作,这里统一实现ResourceRepositoryV2接口。
  1. @Component
  2. public class StudentResourceRepository implements ResourceRepositoryV2<Student, Long> {
  3.     private final StudentRepository studentRepository;
  4.     public StudentResourceRepository(StudentRepository studentRepository) {
  5.         this.studentRepository = studentRepository;
  6.     }
  7.     @Override
  8.     public Student findOne(Long id, QuerySpec querySpec) {
  9.         Optional<Student> student = studentRepository.findById(id);
  10.         return student.orElse(null);
  11.     }
  12.     @Override
  13.     public ResourceList<Student> findAll(QuerySpec querySpec) {
  14.         return querySpec.apply(studentRepository.findAll());
  15.     }
  16.     @Override
  17.     public ResourceList<Student> findAll(Iterable<Long> ids, QuerySpec querySpec) {
  18.         return querySpec.apply(studentRepository.findAllById(ids));
  19.     }
  20.     @Override
  21.     public <S extends Student> S save(S entity) {
  22.         return studentRepository.save(entity);
  23.     }
  24.     @Override
  25.     public void delete(Long id) {
  26.         studentRepository.deleteById(id);
  27.     }
  28.     @Override
  29.     public Class<Student> getResourceClass() {
  30.         return Student.class;
  31.     }
  32.     @Override
  33.     public <S extends Student> S create(S entity) {
  34.         return save(entity);
  35.     }
  36. }
复制代码
而数据库方面我们使用JPA实现即可:
  1. public interface StudentRepository extends JpaRepository<Student, Long> {
  2. }
复制代码
上面的代码是针对Student资源类型的,对Classroom类似,就不把代码列出来了。
2.4 配置

为了使用Katharsis,我们需要在配置中引入KatharsisConfigV3,我们直接在Spring Boot启动类中引入即可:
  1. @SpringBootApplication
  2. @Import(KatharsisConfigV3.class)
  3. public class KatharsisExample {
  4.     public static void main(String[] args) {
  5.         SpringApplication.run(KatharsisExample.class, args);
  6.     }
  7. }
复制代码
Spring Boot的配置文件如下:
  1. server.port=8080
  2. server.servlet.context-path=/
  3. katharsis.domainName=https://www.pkslow.com
  4. katharsis.pathPrefix=/api/katharsis
  5. spring.datasource.url = jdbc:h2:mem:springKatharsis;DB_CLOSE_DELAY=-1
  6. spring.datasource.username = sa
  7. spring.datasource.password =
  8. spring.jpa.show-sql = true
  9. spring.jpa.hibernate.ddl-auto = create-drop
  10. spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.H2Dialect
  11. spring.jpa.properties.hibernate.globally_quoted_identifiers=true
复制代码
katharsis.pathPrefix是URL前缀,而katharsis.domainName会影响Self Link等返回。
2.5 初始化数据

为了方便测试,初始化一些数据进行查询:
  1. @Component
  2. public class InitData {
  3.     private final ClassroomRepository classroomRepository;
  4.     private final StudentRepository studentRepository;
  5.     public InitData(ClassroomRepository classroomRepository, StudentRepository studentRepository) {
  6.         this.classroomRepository = classroomRepository;
  7.         this.studentRepository = studentRepository;
  8.     }
  9.     @PostConstruct
  10.     private void setupData() {
  11.         Set<Student> students = new HashSet<>();
  12.         Student student = Student.builder().name("Larry Deng").build();
  13.         students.add(student);
  14.         studentRepository.save(student);
  15.         student = Student.builder().name("Eason").build();
  16.         students.add(student);
  17.         studentRepository.save(student);
  18.         student = Student.builder().name("JJ Lin").build();
  19.         students.add(student);
  20.         studentRepository.save(student);
  21.         Classroom classroom = Classroom.builder().name("Classroom No.1").students(students)
  22.                 .build();
  23.         classroomRepository.save(classroom);
  24.     }
  25. }
复制代码
至此则整合完毕了。
3 测试

整合完后启动,就可以用curl或Postman开始测试了:
查询一个student:
  1. $ curl http://localhost:8080/api/katharsis/students/1 | jq .
  2.   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
  3.                                  Dload  Upload   Total   Spent    Left  Speed
  4. 100   139    0   139    0     0   9828      0 --:--:-- --:--:-- --:--:-- 23166
  5. {
  6.   "data": {
  7.     "id": "1",
  8.     "type": "students",
  9.     "attributes": {
  10.       "name": "Larry Deng"
  11.     },
  12.     "links": {
  13.       "self": "https://www.pkslow.com/api/katharsis/students/1"
  14.     }
  15.   }
  16. }
复制代码
查询多个student:
  1. $ curl http://localhost:8080/api/katharsis/students | jq .
  2.   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
  3.                                  Dload  Upload   Total   Spent    Left  Speed
  4. 100   429    0   429    0     0   3633      0 --:--:-- --:--:-- --:--:--  3830
  5. {
  6.   "data": [
  7.     {
  8.       "id": "1",
  9.       "type": "students",
  10.       "attributes": {
  11.         "name": "Larry Deng"
  12.       },
  13.       "links": {
  14.         "self": "https://www.pkslow.com/api/katharsis/students/1"
  15.       }
  16.     },
  17.     {
  18.       "id": "2",
  19.       "type": "students",
  20.       "attributes": {
  21.         "name": "Eason"
  22.       },
  23.       "links": {
  24.         "self": "https://www.pkslow.com/api/katharsis/students/2"
  25.       }
  26.     },
  27.     {
  28.       "id": "3",
  29.       "type": "students",
  30.       "attributes": {
  31.         "name": "JJ Lin"
  32.       },
  33.       "links": {
  34.         "self": "https://www.pkslow.com/api/katharsis/students/3"
  35.       }
  36.     }
  37.   ],
  38.   "meta": {
  39.     "totalResourceCount": null
  40.   }
  41. }
复制代码
查询一个教室:
  1. $ curl http://localhost:8080/api/katharsis/classrooms/4 | jq .
  2.   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
  3.                                  Dload  Upload   Total   Spent    Left  Speed
  4. 100   834    0   834    0     0  62462      0 --:--:-- --:--:-- --:--:--  116k
  5. {
  6.   "data": {
  7.     "id": "4",
  8.     "type": "classrooms",
  9.     "attributes": {
  10.       "name": "Classroom No.1"
  11.     },
  12.     "relationships": {
  13.       "students": {
  14.         "data": [
  15.           {
  16.             "id": "3",
  17.             "type": "students"
  18.           },
  19.           {
  20.             "id": "2",
  21.             "type": "students"
  22.           },
  23.           {
  24.             "id": "1",
  25.             "type": "students"
  26.           }
  27.         ],
  28.         "links": {
  29.           "self": "https://www.pkslow.com/api/katharsis/classrooms/4/relationships/students",
  30.           "related": "https://www.pkslow.com/api/katharsis/classrooms/4/students"
  31.         }
  32.       }
  33.     },
  34.     "links": {
  35.       "self": "https://www.pkslow.com/api/katharsis/classrooms/4"
  36.     }
  37.   },
  38.   "included": [
  39.     {
  40.       "id": "1",
  41.       "type": "students",
  42.       "attributes": {
  43.         "name": "Larry Deng"
  44.       },
  45.       "links": {
  46.         "self": "https://www.pkslow.com/api/katharsis/students/1"
  47.       }
  48.     },
  49.     {
  50.       "id": "2",
  51.       "type": "students",
  52.       "attributes": {
  53.         "name": "Eason"
  54.       },
  55.       "links": {
  56.         "self": "https://www.pkslow.com/api/katharsis/students/2"
  57.       }
  58.     },
  59.     {
  60.       "id": "3",
  61.       "type": "students",
  62.       "attributes": {
  63.         "name": "JJ Lin"
  64.       },
  65.       "links": {
  66.         "self": "https://www.pkslow.com/api/katharsis/students/3"
  67.       }
  68.     }
  69.   ]
  70. }
复制代码
新增一个学生:
  1. $ curl --header "Content-Type: application/json"   --request POST   --data '{
  2.     "data": {
  3.         "type": "students",
  4.         "attributes": {
  5.             "name": "Justin"
  6.         }
  7.     }
  8. }'   http://localhost:8080/api/katharsis/students | jq .
  9.   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
  10.                                  Dload  Upload   Total   Spent    Left  Speed
  11. 100   249    0   135  100   114  11202   9459 --:--:-- --:--:-- --:--:-- 41500
  12. {
  13.   "data": {
  14.     "id": "6",
  15.     "type": "students",
  16.     "attributes": {
  17.       "name": "Justin"
  18.     },
  19.     "links": {
  20.       "self": "https://www.pkslow.com/api/katharsis/students/6"
  21.     }
  22.   }
  23. }
复制代码
修改:
  1. $ curl --header "Content-Type: application/json"   --request PATCH   --data '{
  2.     "data": {
  3.         "id":"6",
  4.         "type": "students",
  5.         "attributes": {
  6.             "name": "Justin Wu"
  7.         }
  8.     }
  9. }'   http://localhost:8080/api/katharsis/students/6 | jq .
  10.   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
  11.                                  Dload  Upload   Total   Spent    Left  Speed
  12. 100   273    0   138  100   135   4425   4329 --:--:-- --:--:-- --:--:-- 10920
  13. {
  14.   "data": {
  15.     "id": "6",
  16.     "type": "students",
  17.     "attributes": {
  18.       "name": "Justin Wu"
  19.     },
  20.     "links": {
  21.       "self": "https://www.pkslow.com/api/katharsis/students/6"
  22.     }
  23.   }
  24. }
复制代码
删除:
  1. $ curl --header "Content-Type: application/json"   --request DELETE   --data '{
  2.     "data": {
  3.         "id":"6",
  4.         "type": "students",
  5.         "attributes": {
  6.             "name": "Justin Wu"
  7.         }
  8.     }
  9. }'   http://localhost:8080/api/katharsis/students/6 | jq .
复制代码
至此,我们已经覆盖了增删改查操作了。而我们在代码中并没有去写我们之前常写的Controller,却可以访问对应接口。因为Katharsis默认已经帮我们实现了,可以查看类:io.katharsis.core.internal.dispatcher.ControllerRegistry

4 代码

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

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表