简体   繁体   English

Spring REST API 用于pojo的注册日期转换器

[英]Spring REST API register date converter for pojo

Spring rest provides building pojo functionality by default from path variables and url parameters. Spring rest 默认从路径变量和 url 参数提供构建 pojo 功能。

In my case I have pojo:就我而言,我有 pojo:

public class MyCriteria {
  private String from;
  private String till;
  private Long communityNumber;
  private String communityName;
}

that is used in my controller.在我的 controller 中使用。 Url is http://localhost:8080/community/{communityNumber}/app . Url 是http://localhost:8080/community/{communityNumber}/app Request result of请求结果

curl "http://localhost:8080/community/1/app?from=2018-11-14&till=2019-05-13&communityName=myCOm"

is:是:

{
  'from':'2018-11-14';
  'till':'2019-05-12';
  'communityNumber':'1';
  'communityName':'myCOm'
}

It seems works fine.它似乎工作正常。 Much more better to have in pojo data with required types by purposes.在 pojo 数据中拥有按目的所需的类型要好得多。 So I'd like to have fields from and till of LocalDate type.所以我想from till类型的LocalDate Using spring I'd like to have this solution almost out the box .使用 spring 我希望这个解决方案几乎是开箱即用的 But any spring or jackson date converters can't resolve my issue because of life cycle.但是由于生命周期,任何 spring 或 jackson 日期转换器都无法解决我的问题。

Spring validates types of pojo fields before injecting dates and I'm get type mismatch exception. Spring 在注入日期之前验证 pojo 字段的类型,我得到类型不匹配异常。 I think the general reason is using special builder by spring that tries to find required parameters by name and it ignores annotations to be applied inside of pojo for the fields.我认为一般原因是使用 spring 的特殊构建器,它试图按名称查找所需的参数,它忽略了要在 pojo 内部应用的字段的注释。

Question is:问题是:

Is there any elegant solutions for building pojo by spring where some fields will be converted from String to LocalDate format by default?通过 spring 构建 pojo 是否有任何优雅的解决方案,默认情况下某些字段将从String转换为LocalDate格式?

PS附言

Mandatory conditions are:强制性条件是:

  • request method is GET ;请求方法是GET
  • required pojo is:所需的 pojo 是:
public class MyCriteria {
  private LocalDate from;
  private LocalDate till;
  private Long communityNumber;
  private String communityName;
}
  • lets skip ideas with custom AOP implementations or with getter s where injected convert logic;让我们跳过自定义 AOP 实现或注入转换逻辑的getter的想法;
  • there are neither body (request body is empty) nor json (all required data are path variables or path params).既没有正文(请求正文为空)也没有 json(所有必需的数据都是路径变量或路径参数)。

PS2. PS2。

  • Controller example that can be used for experiments is:可用于实验的 Controller 示例为:
import lombok.extern.slf4j.Slf4j;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;
import org.vl.example.rest.dtofromoaramsandpath.web.dto.MyCriteria;

import java.time.LocalDate;

@RestController
@RequestMapping("verify/criteria/mapping")
@Slf4j
public class MyController {

    @GetMapping("community/{communityNumber}/dto")
    public MyCriteria loadDataByDto(MyCriteria criteria) {
        log.info("received criteria: {}", criteria);
        return criteria;
    }

    @GetMapping("community/{communityNumber}/default/params")
    public String loadDataByDefaultParameters(@PathVariable("communityNumber") String communityNumber,
                                            @RequestParam(value = "from", required = false) String from,
                                            @RequestParam(value = "till", required = false) String till,
                                            @RequestParam(value = "communityName", required = false) String communityName) {
        log.info("received data without converting:\n\tcommunityNumber => {}\n\tfrom => {}\n\ttill => {}\n\tcommunityName => {}",
                communityNumber, from, till, communityName);
        return new StringBuilder("{")
                .append("\n\tfrom:").append(from).append(";")
                .append("\n\tfrom:").append(from).append(";")
                .append("\n\ttill:").append(till).append(";")
                .append("\n\tcommunityName:").append(communityName)
                .append("\n}\n").toString();
    }

    @GetMapping("community/{communityNumber}/converted/params")
    public String loadUsingConvertedParameters(@PathVariable("communityNumber") String communityNumber,
                                             @RequestParam(value = "from") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate from,
                                             @RequestParam("till") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate till,
                                             @RequestParam(value = "communityName", required = false) String communityName) {
        log.info("received data with LocalDate converting:\n\tcommunityNumber => {}\n\tfrom => {}\n\ttill => {}\n\tcommunityName => {}",
                communityNumber, from, till, communityName);
        return new StringBuilder("{")
                .append("\n\tfrom:").append(from).append(";")
                .append("\n\tfrom:").append(from).append(";")
                .append("\n\ttill:").append(till).append(";")
                .append("\n\tcommunityName:").append(communityName)
                .append("\n}\n").toString();
    }
}
  • also link on github project that contains module with required controller and criteria to make your understanding and experiments more useful.链接到 github 项目,该项目包含具有所需controllercriteria的模块,以使您的理解和实验更有用。

This might help you.这可能会帮助你。 I have similar situation and I used this approach to convert the data into specific requirement.我有类似的情况,我使用这种方法将数据转换为特定要求。

public class MyCriteria {
  public MyCriteria(LocalDate from, LocalDate till, Long communityNumber, String communityName){
   // assignement of variables
}
  private LocalDate from;
  private LocalDate till;
  private Long communityNumber;
  private String communityName;
}

SO whenever you create a object from JSON, it will create it according to the requirement.因此,每当您从 JSON 创建 object 时,它都会根据要求创建它。

When I implemented this, I used ObjectMapper class of "Jackson" to do this thing.当我实现这个时,我使用了“Jackson”的 ObjectMapper class 来做这件事。 Hope you are uisng the same.希望你也一样。

Use java.sql.Date inside the pojo class.like private Date from.使用 java.sql.Date 里面的 pojo class.like private Date from。 I hope it will work for JSON convertion.我希望它适用于 JSON 转换。 When you are receiving date JSON field from UI then always use Java.sql.Date for Jackson date convert.当您从 UI 接收日期 JSON 字段时,请始终使用 Java.sql.Date for Z7930C25260E609E4A981 convert

For that, you need to add jsr310 dependency.为此,您需要添加jsr310依赖项。

compile("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.8.10")

I hope this works fine for you.我希望这对你有用。

The answer on question is to use init binder to register type mapping inside of specified criteria.问题的答案是使用 init binder 在指定条件内注册类型映射。 It is required to have PropertyEditorSupport implementation for specified purpose.需要为特定目的实现PropertyEditorSupport

Short code example is:短代码示例是:

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(LocalDate.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                setValue(LocalDate.parse(text, DateTimeFormatter.ISO_LOCAL_DATE));
            }
        });
    }

Full code example can be taken from github :完整的代码示例可以从github 获取

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.vl.example.rest.dtofromoaramsandpath.web.dto.MyCriteriaLd;

import java.beans.PropertyEditorSupport;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

@RestController
@RequestMapping("verify/criteria/mapping")
@Slf4j
public class MyControllerLd {
    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(LocalDate.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                setValue(LocalDate.parse(text, DateTimeFormatter.ISO_LOCAL_DATE));
            }
        });
    }

    @GetMapping("community/{communityNumber}/dtold")
    public MyCriteriaLd loadDataByDto(MyCriteriaLd criteria) {
        log.info("received criteria: {}", criteria);
        return criteria;
    }
}

So model for this case can be next:所以这个案例的 model 可以是下一个:

import lombok.Data;

import java.time.LocalDate;

@Data
public class MyCriteriaLd {
    private LocalDate from;
    private LocalDate till;
    private Long communityNumber;
    private String communityName;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM