Проблема шаблона аннотации Spring MVC Controller NumberFormat в BigDecimal

У меня есть контроллер Spring, который принимает несколько BigDecimal RequestParams.

Локаль моего приложения — en_US, но только для этого метода контроллера мне нужно связать и преобразовать эти параметры BigDecimal в локаль de_DE (т.е. #.###,## > DOT для группировки и ЗАПЯТАЯ для десятичного разделителя).

Эти значения BigDecimal поступают из текстовых полей пользовательского интерфейса и уже имеют формат de_DE. Вот мой код контроллера, который не работает со следующей ошибкой:

"Не удалось преобразовать значение типа "java.lang.String" в требуемый тип "java.math.BigDecimal"; вложенным исключением является java.lang.NumberFormatException"

@RequestMapping(value = "/create", method = RequestMethod.POST)
public ModelAndView create(@RequestParam("referenceNumber") String referenceNumber, @RequestParam("startDate") @DateTimeFormat(pattern="dd-MM-yyyy") Date startDate, @RequestParam("amount1") @NumberFormat(pattern = "#.###,##") BigDecimal amount1, @RequestParam("amount2") @NumberFormat(pattern = "#.###,##") BigDecimal amount2) {

    // Do something and return

}

Spring каким-то образом игнорирует мой шаблон числового формата. Обратите внимание, что аннотация DateTimeFormat работает должным образом; разбор параметра startDate в правильной форме.

Любая помощь будет оценена по достоинству.

Спасибо.


person Ahmet    schedule 05.02.2017    source источник
comment
Вы можете отлаживать часть кода javascript. Я думаю, вы отправляете строковое значение. Вы можете привести его к номеру в своем коде javascript   -  person Gurkan İlleez    schedule 05.02.2017
comment
@ user3087839 javascript здесь неуместен; конечно, я отправляю кучу строк со стороны просмотра. Отправка формы — это способ отправки строковых пар «ключ-значение» с одной стороны на другую. Я спрашиваю, как преобразовать эти значения строковых параметров нестандартным способом.   -  person Ahmet    schedule 05.02.2017
comment
Аннотация работает, потому что выдает ошибку типа NumberFormatException. Странно отправлять строку и пытаться отформатировать ее позже.   -  person Gurkan İlleez    schedule 05.02.2017
comment
Пожалуйста, дайте нам реальные примеры ввода.   -  person Sotirios Delimanolis    schedule 05.02.2017
comment
@SotiriosDelimanolis вот один пример: referenceNumber:P17-0227 startDate:03-02-2017 сумма1:1.000,44 сумма2:4.020,31   -  person Ahmet    schedule 05.02.2017


Ответы (2)


Вы можете использовать PropertyEditorSupport для обработки ввода формы. следующим образом:

Создайте класс, расширяющий PropertyEditorSupport, для преобразования строки, полученной от клиента, в BigDecimal< /а>, например:

import java.beans.PropertyEditorSupport;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;

public class BigDecimalEditor extends PropertyEditorSupport {

    public void setAsText(String text) {
        NumberFormat formatter = NumberFormat.getNumberInstance(Locale.GERMAN);
        try {
            Number number = formatter.parse(text);
            BigDecimal bigDecimal = BigDecimal.valueOf(number.doubleValue());
            setValue(bigDecimal);
        } catch (ParseException e) {
            // handle exception here
        }
    }
}

И свяжите его с контроллером, как:

@RestController
@RequestMapping(value = "/employee")
public class EmployeeController {

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(BigDecimal.class, new BigDecimalEditor());
    }

    @RequestMapping(value = "/create", method = RequestMethod.POST)
    public ModelAndView create(
            @RequestParam("amount") @NumberFormat(pattern = "#.###,##") BigDecimal amount) {
        System.out.println(amount);
        return new ModelAndView();
    }
}
person Arpit Aggarwal    schedule 05.02.2017
comment
Спасибо за ответ. Это своего рода обходной путь, потому что с customEditors нам не нужно использовать аннотацию NumberFormat. Я действительно хотел бы знать, можно ли использовать аннотацию NumberFormat с пользовательским шаблоном, как шаблон DateTimeFormat. - person Ahmet; 05.02.2017
comment
+1 Для меня это лучший метод, но вы можете зарегистрировать глобальную привязку инициализации, чтобы вам не приходилось регистрировать ее для каждого контроллера (keenformatics.blogspot.it/2013/08/). И не нужно использовать аннотацию NumberFormat в параметре контроллера, CustomEditor преобразует сумму и без аннотации. - person amicoderozer; 20.10.2017
comment
Поскольку вы все равно используете Spring, вы можете сократить содержимое setAsText с помощью Spring NumberUtils: setValue(NumberUtils.parseNumber(text, BigDecimal.class, NumberFormat.getInstance(java.util.Locale.GERMAN))); - person dev-null; 28.11.2020
comment
Но берегись! Точка в обоих вариантах принята как группирующий символ. Таким образом, 123,45 будет ошибкой, а 12345. - person dev-null; 28.11.2020

Я решил свою проблему с помощью: @RequestParam(value="amount1", required=false) @NumberFormat(pattern="#0,00") BigDecimal amount1

person NikNik    schedule 22.02.2017
comment
Я применил обходной путь с помощью PropertyEditorSupport, но я попробую и дам вам знать. Спасибо - person Ahmet; 22.02.2017
comment
на самом деле то, что вы предложили, также работает. Я попробовал это вчера, и это работает хорошо. - person Ahmet; 20.03.2017