Spring Boot springboot服务器在使用postman发出post请求后返回错误400

j8yoct9x  于 2022-11-05  发布在  Spring
关注(0)|答案(2)|浏览(248)

每当我想把这封信寄给 Postman

{
    "date": "2021-11-05 12:32:32",
    "start": "start",
    "destination": "destination",
    "provider": "provider",
    "driver":1,
    "vehicule":1
}

我得到了错误400,错误请求,我同时使用了@restController和@requestBody注解,同时还将内容类型设置为json。
我在调试器上得到这个错误:

2021-11-09 16:57:52.086  WARN 11748 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.util.Date` from String "2021-11-06 12:32:32.0": not a valid representation (error: Failed to parse Date value '2021-11-06 12:32:32.0': Cannot parse date "2021-11-06 12:32:32.0": while it seems to fit format 'yyyy-MM-dd'T'HH:mm:ss.SSSX', parsing fails (leniency? null)); nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.util.Date` from String "2021-11-06 12:32:32.0": not a valid representation (error: Failed to parse Date value '2021-11-06 12:32:32.0': Cannot parse date "2021-11-06 12:32:32.0": while it seems to fit format 'yyyy-MM-dd'T'HH:mm:ss.SSSX', parsing fails (leniency? null))
 at [Source: (PushbackInputStream); line: 3, column: 17] (through reference chain: com.siam.HRAssistTool.Entity.Schedule["date"])]

我不明白我应该如何解决这个我假设的日期格式相关的问题
当我从json主体中删除时间而只留下日期时,我得到了这个错误:

2021-11-09 17:34:55.418  WARN 11748 --- [nio-8080-exec-4] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of `com.siam.HRAssistTool.Entity.Vehicule` (although at least one Creator exists): no int/Int-argument constructor/factory method to deserialize from Number value (1); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.siam.HRAssistTool.Entity.Vehicule` (although at least one Creator exists): no int/Int-argument constructor/factory method to deserialize from Number value (1)
 at [Source: (PushbackInputStream); line: 8, column: 20] (through reference chain: com.siam.HRAssistTool.Entity.Schedule["vehicule"])]

我计划实体:

@Entity
public class Schedule implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id ; 
    private Date date ; 
    private String Start; 
    private String destination;
    @OneToOne( fetch = FetchType.LAZY)
    private Staff driver; 
    @OneToOne(fetch = FetchType.LAZY)
    private Vehicule vehicule; 
    private String provider;
    //constructors, getters and setters 
}

我的控制器:

@RestController
public class ScheduleController {

    @Autowired
    ScheduleService scheduleService; 

    @PostMapping(value="/schedule/create")
    public @ResponseBody String createSchedule( @RequestBody Schedule schedule) {
        System.out.println(schedule.toString());

        return scheduleService.addSchedule(schedule);

    }
//other crud operation
}
axzmvihb

axzmvihb1#

首先,将Date替换为LocalDate,它是新的Java Time API的一部分。使用它,您可以配置Jackson以轻松处理这种复杂类型的序列化和反序列化。添加以下依赖项:

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.11.0</version>
</dependency>

然后相应地配置Jackson:

@Configuration
public class JacksonConfiguration {

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        objectMapper.registerModule(javaTimeModule);

    objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

        return objectMapper;
    }
}

然后,请避免在Controller中使用实体,无论是作为响应还是请求类型。请使用DTO,它是核心模型实体的特定表示形式。

public class ScheduleCreationDto {
    private LocalDate date; 
    private String Start; 
    private String destination;
    private Long driverId;      // I am guessing the ID is a Long
    private Long vehiculeId;    // I am guessing the ID is a Long
    private String provider;

    //constructors, getters and setters 
}

现在应将其用作请求正文:

@RestController
public class ScheduleController {

    @Autowired
    ScheduleService scheduleService; 

    @PostMapping(value="/schedule/create")
    public @ResponseBody String createSchedule(@RequestBody ScheduleCreationDto scheduleCreationDto) {
        return scheduleService.addSchedule(schedule);
    }

    //other crud operation
}

您还需要更改ScheduleService,以便它基于ScheduleCreationDto创建Schedule。大多数属性需要简单的Map,但其他属性(driverIdvehiculeId)需要您使用提供的ID从数据库中实际获取这些实体。应在ScheduleService中执行类似以下操作:

@Service
public class ScheduleService {

    @Autowired
    ScheduleRepository scheduleRepository; 

    @Autowired
    DriverRepository driverRepository; 

    @Autowired
    VehiculeRepository vehiculeRepository; 

    public String addSchedule(ScheduleCreationDto scheduleCreationDto) {
        Optional<Driver> driver = driverRepository.findById(scheduleCreationDto.getDriverId());
        Optional<Vehicule> vehicule = vehiculeRepository.findById(scheduleCreationDto.getVehiculeId());

        if (driver.isPresent() && vehicule.isPresent()) {
            Schedule schedule = new Schedule(scheduleCreationDto.getDate(), scheduleCreationDto.getStart(), 
                scheduleCreationDto.getDestination(), driver.get(), vehicule.get(), scheduleCreationDto.getProvider());
            scheduleRepository.save(schedule);    
        }

        return // whatever String you want to return, you should actually return the created Schedule, but that is a different topic
    }

    //other crud operation
}
rjee0c15

rjee0c152#

400错误与 Postman 和Sping Boot API的错误请求,在我的情况下,发生了三个原因:
1.第一个问题是请求的json格式不对,例如发送:

{ key: value }

或者:

{ "key" : "value"

这显然不是你的案子。
2.第二个原因是发送的键与对象预期的键不同。例如:

@PostMapping
    public ResponseEntity<Object> save(@RequestResponse @Valid 
    ClassOfReciveObject reciveObject){

    return ResponseEntity.status(HttpStatus.CREATED).body("OK");
    }

如果ClassOfObjectRecived具有属性:

{
    public String age;
    public String name;
}

而你在 Postman 发送别人的钥匙,你会得到一个坏的请求

{
     "country":"Brazil",
     "Continent":"America"
}

3.第三个错误是因为这个类的属性使用了private访问修饰符,将其改为public,或者找到解决方法。

public class ClassOfObjectRecived {
    public String param1;
    public String param2;
    }

相关问题