马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
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
|