首页 > 解决方案 > 如何从角度接收日期(弹簧)类型的requestParam

问题描述

我是angularspring的新手, 我正在尝试发送带有一些日期参数的 get 请求,但我一直收到错误消息。

<div class="form-row">
              <div class="form-group col-md-3">
                <label for="beforeAdmission">Avant l'Admission</label>
                <input type="text"
                   placeholder="Datepicker"
                   class="form-control"
                   id="beforeAdmission"
                   name="beforeAdmission" 
                   bsDatepicker
                   [bsConfig]="{ dateInputFormat: 'dd/mm/yyyy' }"
                   [(bsValue)]="search.beforeAdmission"
                   >
              </div>
              <div class="form-group col-md-3">
                <label for="afterAdmission">Après l'Admission</label>
                <input type="text"
                   placeholder="Datepicker"
                   class="form-control"
                   id="afterAdmission"
                   name="afterAdmission" 
                   bsDatepicker
                   [bsConfig]="{ dateInputFormat: 'dd/mm/yyyy' }"
                   [(bsValue)]="search.afterAdmission"
                   >
              </div>
              <div class="form-group col-md-3">
                <label for="beforePay">Avant Paiement</label>
                <input type="text"
                   placeholder="Datepicker"
                   class="form-control"
                   id="beforePay"
                   name="beforePay" 
                   bsDatepicker
                   [bsConfig]="{ dateInputFormat: 'dd/mm/yyyy' }"
                   [(bsValue)]="search.beforePay"
                   >
              </div>
              <div class="form-group col-md-3">
                <label for="afterPay">Après Paiement</label>
                <input type="text"
                   placeholder="Datepicker"
                   class="form-control"
                   id="afterPay"
                   name="afterPay" 
                   bsDatepicker
                   [bsConfig]="{ dateInputFormat: 'dd/mm/yyyy' }"
                   [(bsValue)]="search.afterPay"
                   >
              </div>
             </div>

export interface Search {
    beforeAdmission:Date,
    afterAdmission : Date,
    beforePay : Date,
    afterPay : Date
}
search : Search = {
        beforeAdmission:new Date(this.d.getFullYear() + 5, this.d.getMonth(), this.d.getDate()),
        afterAdmission : new Date(this.d.getFullYear() - 20 , this.d.getMonth(), this.d.getDate()),
        beforePay : new Date(this.d.getFullYear() + 5 , this.d.getMonth(), this.d.getDate()),
        afterPay :  new Date(this.d.getFullYear() - 20 , this.d.getMonth(), this.d.getDate())
}

onSearch(){

        this.service.search(this.search).subscribe(res =>{
            this.cheques = res;
        },err =>{
        
        });
    }
public search(search){
    return this.http.get(this.url+"?beforeAdmission="+search.beforeAdmission+"&afterAdmission="+search.afterAdmission
                            +"&beforePay="+search.beforePay+"&afterPay="+search.afterPay,{headers:this.headers});
    }```

@GetMapping("/cheques")
    public Page<ChequeOrEffet> getAll(@RequestParam(name="beforeAdmission",defaultValue = "01/01/1950")@DateTimeFormat(pattern = "dd/mm/yyyy",iso=ISO.DATE)Date beforeAdmission
                                    ,@RequestParam(name="afterAdmission",defaultValue = "01/01/2050") @DateTimeFormat(pattern = "dd/mm/yyyy",iso=ISO.DATE) Date  afterAdmission
                                    ,@RequestParam(name="beforePay",defaultValue = "01/01/1950") @DateTimeFormat(pattern = "dd/mm/yyyy",iso=ISO.DATE) Date beforePay
                                    ,@RequestParam(name="afterPay",defaultValue = "01/01/2050") @DateTimeFormat(pattern = "dd/mm/yyyy",iso=ISO.DATE) Date afterPay) {
        
        System.out.println("xx");
        return service.seach((Date)beforeAdmission, (Date)afterAdmission, (Date)beforePay, (Date)afterPay);
    }
                                    
2020-08-31 01:50:45.158  WARN 35616 --- [nio-8080-exec-7] .m.m.a.ExceptionHandlerExceptionResolver : Resolved [org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.util.Date'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@org.springframework.web.bind.annotation.RequestParam @org.springframework.format.annotation.DateTimeFormat java.util.Date] for value 'Sun Aug 31 2025 00:00:00 GMT 0000 (Coordinated Universal Time)'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [Sun Aug 31 2025 00:00:00 GMT 0000 (Coordinated Universal Time)]]

ps:我已经尝试过stackoverflow的一些解决方案,但对我没有任何帮助,

标签: javaangularspringspring-bootspring-mvc

解决方案


In your Angular service, you are sending the dates of your Search as their toString() representation. But in your Spring controller, you are expecting them to be in "dd/mm/yyyy" format. Spring cannot parse your those date strings into a Date, hence the IllegalArgumentException.

You can format the JS dates into "dd/mm/yyyy" in your Angular service. For example using a simple method like:

formatDate(date: Date): string {
  const day = date.getDate() < 10 ? `0${date.getDate()}` : date.getDate() + '';
  const month = date.getMonth() + 1 < 10 ? `0${date.getMonth() + 1}` : (date.getMonth() + 1) + '';
  const year = date.getFullYear() + '';
  return `${day}/${month}/${year}`;
}

Or use a date library like https://date-fns.org/ for more robust formatting.

Then use the formatDate method in your service:

public search(search) {
  const params = new HttpParams()
    .set('beforeAdmission', formatDate(search.beforeAdmission))
    .set('afterAdmission', formatDate(search.afterAdmission))
    .set('beforePay', formatDate(search.beforePay))
    .set('afterPay', formatDate(search.afterPay));

  const options = {
    params,
    headers: this.headers
  };
  return this.http.get(this.url, options);
}

Finally, you need to set the pattern of @DateTimeFormat to be correct (mm is minute of hour).

@GetMapping("/cheques")
public ResponseEntity<String> getAll(
            @RequestParam(name = "beforeAdmission", defaultValue = "01/01/1950") @DateTimeFormat(pattern = "dd/MM/yyyy") Date beforeAdmission,
            @RequestParam(name = "afterAdmission", defaultValue = "01/01/2050") @DateTimeFormat(pattern = "dd/MM/yyyy") Date afterAdmission,
            @RequestParam(name = "beforePay", defaultValue = "01/01/1950") @DateTimeFormat(pattern = "dd/MM/yyyy") Date beforePay,
            @RequestParam(name = "afterPay", defaultValue = "01/01/2050") @DateTimeFormat(pattern = "dd/MM/yyyy") Date afterPay) {
        
        System.out.println("xx");
        return service.seach((Date) beforeAdmission, (Date) afterAdmission, (Date) beforePay, (Date) afterPay);
    }

I would also suggest using java.time.LocalDate over java.util.Date.


推荐阅读