使用 Spring Boot 从另一个服务调用 Rest Service 以进行课程注册系统

Posted

技术标签:

【中文标题】使用 Spring Boot 从另一个服务调用 Rest Service 以进行课程注册系统【英文标题】:Calling a Rest Service from another service for course registration system with spring boot 【发布时间】:2020-01-24 20:16:25 【问题描述】:

我试图通过我的 Registration 微服务进行 REST 调用(学生,课程微服务) 插入新注册的服务,但每当我调用这些服务时,Student 微服务都会显示以下错误

> org.springframework.web.client.RestClientException: Error while extracting response for type [class com.homeexam.registrationmanagementserver.model.Student] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of `com.homeexam.registrationmanagementserver.model.Student` out of START_ARRAY token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `com.homeexam.registrationmanagementserver.model.Student` out of START_ARRAY token
 at [Source: (PushbackInputStream); line: 1, column: 1]

我已尽力解决从谷歌搜索的问题,但我找不到任何与该问题相关的解决方案。救命,我出去!

这是我的 RegistrationService 类,我在其中调用这些微服务:

    public Registration create(Registration registration) 

            Student student = restTemplate.getForObject(studentsUrl, Student.class);
            Section section = restTemplate.getForObject(sectionsUrl, Section.class);
            Course course = restTemplate.getForObject(coursesUrl, Course.class);


            /*registration = new Registration(registration.getId(), student.getId(),student.getProgram(),
                    section.getSectionNumber(),course.getCourseCode(),section.getFacultyInitial());*/
            registration.setId(registration.getId());
            registration.setStudentId(student.getId());
            registration.setProgramName(student.getProgram());
            registration.setCourseCode(course.getCourseCode());
            registration.setFacultyInitial(section.getFacultyInitial());
            registration.setSectionNumber(section.getSectionNumber());

            Optional<Registration> optionalReg = registrationRepository.findById(registration.getId());
            Optional<Registration> byCourseCode = registrationRepository.findById(Integer.valueOf(registration.getCourseCode()));
            if (optionalReg.isPresent() ) 
                throw new ResourceAlreadyExistsException();
             else if (byCourseCode.isPresent())
               throw new AlreadyRegisteredException();
            else 
               return registrationRepository.save(registration);
            
        

但是,代码确实可以在不调用微服务相关信息的情况下工作。

注册 JSON


  "courseCode": "string",
  "facultyInitial": "string",
  "id": 0,
  "programName": "string",
  "sectionNumber": 0,
  "studentId": "string"

学生 JSON


    "id": "201600000001",
    "name": "UML Diagram",
    "email": "uml@gmail.com",
    "address": "Texas,USA",
    "dob": "1998-09-11",
    "mobileNumber": "01110000000",
    "dateOfAdmission": "2018-09-10",
    "program": "BSc. in EEE",
    "role": "Student",
    "password": "1555"
  

课程 JSON

[
  
    "courseCode": "CS193",
    "courseTitle": "android Application",
    "courseCredit": 3,
    "sectionList": [
      
        "id": 1,
        "sectionNumber": 1,
        "seatLimit": 25,
        "semesterNumber": 11,
        "facultyInitial": "ATA",
        "course": 
          "courseCode": "CS193",
          "courseTitle": "Android Application",
          "courseCredit": 3,
          "sectionList": null,
          "gradeList": null
        
      ,
      
        "id": 2,
        "sectionNumber": 2,
        "seatLimit": 30,
        "semesterNumber": 11,
        "facultyInitial": "ABA",
        "course": 
          "courseCode": "CS193",
          "courseTitle": "Android Application",
          "courseCredit": 3,
          "sectionList": null,
          "gradeList": null
        
      
    ],
    "gradeList": null
  
]

部分 JSON

[
  
    "id": 1,
    "sectionNumber": 1,
    "seatLimit": 25,
    "semesterNumber": 11,
    "facultyInitial": "ATA",
    "course": 
      "courseCode": "CS193",
      "courseTitle": "Android Application",
      "courseCredit": 3,
      "sectionList": null,
      "gradeList": null
    
  ,
  
    "id": 2,
    "sectionNumber": 2,
    "seatLimit": 30,
    "semesterNumber": 11,
    "facultyInitial": "ABA",
    "course": 
      "courseCode": "CS193",
      "courseTitle": "Android Application",
      "courseCredit": 3,
      "sectionList": null,
      "gradeList": null
    
  
]

Student.java

@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(of = "id","name")
@Document
public class Student 
    @Id
    private String id;
    private String name;
    private String email;
    private String address;
    private LocalDate dob;
    private String mobileNumber;
    private LocalDate dateOfAdmission;
    private String program;
    private Role role;
    private String password;

Registration.java

public class Registration 
    @Id
    private int id;
    private String studentId;
    private String programName;
    private int sectionNumber;
    private String courseCode;
    private String facultyInitial;

【问题讨论】:

错误消息与格式错误的 JSON 有关。能否将 json 内容添加到问题中? @henriqueor 我添加了 JSON 数据 你能不能把Student.java sahre一下 @deshi 以下链接包含 Student.java 类Student.java 始终将代码添加到问题中而不是外部链接上,以保留历史记录以供将来参考。 @JakariaRidoy 【参考方案1】:

错误意味着您向需要单个对象的服务发送了一个数组。

解决方案:为每个请求发送单个 JSON 对象或更改服务以使其接受数组或列表。

【讨论】:

我应该更改哪个服务层 StudentServiceRegistrationService StudentService.java 每当我调用这些服务时 - 它与其他服务有什么关系?首先分析您对 Student 负责的服务。从您的首选客户端(Postman、curlt、...)调用 GET,检查结构。调用 POST 和 PUT,检查它们是否正常工作。 (学生和课程)服务都可以正常工作。他们可以执行所有 CRUD 操作。【参考方案2】:

试试这个:

Student[] students = restTemplate.getForObject(studentsUrl, Student[].class);

【讨论】:

【参考方案3】:

问题可能出在 Student 的角色属性上。在您的 Student 类上,它期望接收 Role 类型,但在您的 JSON 中它是一个 String。

你有这个:


    "id": "201600000001",
    "name": "UML Diagram",
    "email": "uml@gmail.com",
    "address": "Texas,USA",
    "dob": "1998-09-11",
    "mobileNumber": "01110000000",
    "dateOfAdmission": "2018-09-10",
    "program": "BSc. in EEE",
    "role": "Student",
    "password": "1555"

但应该是这样的:


    "id": "201600000001",
    "name": "UML Diagram",
    "email": "uml@gmail.com",
    "address": "Texas,USA",
    "dob": "1998-09-11",
    "mobileNumber": "01110000000",
    "dateOfAdmission": "2018-09-10",
    "program": "BSc. in EEE",
    "role": 
        "type": "Student"
    ,
    "password": "1555"

由于不知道Role类的结构,所以以设置属性“type”为例。

【讨论】:

以上是关于使用 Spring Boot 从另一个服务调用 Rest Service 以进行课程注册系统的主要内容,如果未能解决你的问题,请参考以下文章

如何从另一个新的 Spring Boot 项目调用一个 Spring Boot 项目中存在的 Spring Boot api

Spring MVC - 从另一个休息服务内部调用休息服务

如何使用 Spring Boot feign 客户端进行 Oauth2 身份验证?

从另一个 Magnolia 模块访问 Spring 服务(不使用 Spring Blossom)

如何从另一个 Spring Boot 应用程序访问一个 Spring Boot 应用程序的内存 H2 数据库

Spring-Boot 多模块无法从另一个模块读取属性文件