在 Spring 个 RestController 中使用 Field Formatter

Use Field Formatter in Spring RestControllers

我尝试让 RestController 使用我的自定义格式化程序 java.time.Duration,但我不知道为什么没有成功。我有一个简单的 Order 实体、一个 OrderController 和一个 DurationFormatter,它们应该应用于 Order 的 Duration 类型字段与字符串的转换。 Formatter 在 Configuration class 中注册到 FormattingConversionServiceFactoryBean。这是代码:

public class Order {
    @Getter
    @Setter
    private String id;

    @Getter
    @Setter
    @NotNull
    private String customerId;

    @Getter
    @Setter
    private ZonedDateTime validFrom;

    @Getter
    @Setter
    private ZonedDateTime validTo;

    @Getter
    @Setter
    private Duration maxDuration;

    @Getter
    @Setter
    private Duration actDuration;
}

@RestController
@RequestMapping("order")
public class OrderController {

    @RequestMapping(method = RequestMethod.POST)
    public ResponseEntity<?> createOrder(@RequestBody @Valid Order order) {
        HttpHeaders headers = new HttpHeaders();
        headers.setLocation(ServletUriComponentsBuilder.fromCurrentRequest().path("/" + order.getId()).build().toUri());
        return new ResponseEntity<>(null, headers, HttpStatus.CREATED);
    }

    @RequestMapping(method = RequestMethod.GET)
    public Order getExample() {
        Order order = new Order();
        order.setMaxDuration(Duration.ofHours(10));
        return order;
    }
}

public class DurationFormatter implements Formatter<Duration>{

    @Override
    public String print(Duration duration, Locale locale) {
        return new Long(duration.toHours()).toString();
    }

    @Override
    public Duration parse(String text, Locale locale) throws ParseException {
        return Duration.ofHours(Long.parseLong(text));
    }

}

@Configuration
public class AppConfig {
    @Bean
    public FormattingConversionServiceFactoryBean getFormattingConversionServiceFactory() {
        FormattingConversionServiceFactoryBean factory = new FormattingConversionServiceFactoryBean();
        Set<Formatter<?>> formatters = new HashSet<>();
        formatters.add(new DurationFormatter());
        factory.setFormatters(formatters);
        return factory;
    }
}

当我尝试 post 一个订单时,这是我得到的错误:

at [Source: java.io.PushbackInputStream@595e3818; line: 4, column: 30] (through reference chain: com.sap.sptutorial.rest.Order["maxDuration"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class java.time.Duration] from String value ('67'); no single-String constructor/factory method

任何人都可以建议我应用格式化程序的正确方法吗?

格式化程序与 JSON 反序列化无关。在您的案例中,这就是 Jackson 的任务。将以下依赖项添加到您的 pom.xml 以获得对新的 Java 8 种类型的支持就足够了。

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