我正在将一个java EE应用程序迁移到spring boot并且我遇到了转换问题。 现在无论好坏我将我的货币存储为Long(其德国欧元)。 我写了一个自定义的jsf转换器,它做了类似的事情:
长 - >串
22 - > 00,22
3310 - > 33,10
字符串 - >长
3 - > 3
22,11 - > 2211
现在,Spring MVC是摆脱JSF的一个原因。 我想使用303 Beanvalidation,使用Spring MVC(@Valid @ModelAttribute,BindingResult,它适用于@Pattern,例如)
现在我不能使用@NumberFormat(style = Style.Currency),这可以做我想要的,如果我没有存储我的货币那么久。
我编写了一个自定义Formatter并将其注册到FormatterRegistry
public class LongCurrencyFormatter implements Formatter<Long>{
@Getter
private static final long serialVersionUID = 1L;
@Override
public String print(Long arg0, Locale arg1) {
//logic removed for shorter post
}
@Override
public Long parse(String arg0, Locale arg1) throws ParseException {
//logic removed for shorter post
}
}
到目前为止,everthing正在发挥作用,但现在每一个长期都被转换了。我认为是对的。
因此,经过一些研究,我研究了6.6.2注释驱动格式
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html
我在文档中创建了一个AnnotationFormatterFactory
public class LongCurrencyFormatAnnotationFormatterFactory
implements AnnotationFormatterFactory<LongCurrency> {
@Override
public Set<Class<?>> getFieldTypes() {
Set<Class<?>> setTypes = new HashSet<Class<?>>();
setTypes.add(Long.class);
return setTypes;
}
@Override
public Parser<?> getParser(LongCurrency annotation, Class<?> fieldType) {
return new LongCurrencyFormatter();
}
@Override
public Printer<?> getPrinter(LongCurrency annotation, Class<?> fieldType) {
return new LongCurrencyFormatter();
}
}
我的注释:
public @interface LongCurrency {
}
我的豆子:
public class Costunit {
//other attributes
@LongCurrency
private long value;
}
遗憾的是它不起作用:
无法将类型为java.lang.String的属性值转换为属性值所需的long类型;嵌套异常是java.lang.NumberFormatException:对于输入字符串:&#34; 22,00&#34;
很抱歉这篇长篇文章,不知道我做错了什么?或者更好的解决方案将格式化程序绑定到一个控制器?数据库模拟应该是最不可能的选择。
谢谢!
EDIT1:完整格式化程序代码(当然可以更好用)
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.util.Locale;
import java.util.regex.Pattern;
import lombok.Getter;
import org.springframework.format.Formatter;
public class LongCurrencyFormatter implements Formatter<Long>{
@Getter
private static final long serialVersionUID = 1L;
@Override
public String print(Long arg0, Locale arg1) {
String returnValue = arg0.toString();
boolean minusChar = returnValue.startsWith("-");
returnValue = returnValue.replace("-", "");
if (returnValue.length() > 2) {
String tempStr = returnValue.substring(0, returnValue.length()-2);
Long val = Long.parseLong(tempStr);
DecimalFormat df = new DecimalFormat();
df.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.GERMAN));
String output = df.format(val) + "," +
returnValue.substring(returnValue.length()-2);
returnValue = output;
} else {
if(returnValue.length() == 1) {
returnValue = "0,0"+returnValue;
} else {
returnValue = "0,"+returnValue;
}
}
if(minusChar) {
returnValue = "-" + returnValue;
}
return returnValue;
}
@Override
public Long parse(String arg0, Locale arg1) throws ParseException {
Long returnLong = null;
// 1Test :only one - in front, only digits and "." and one "," , and
// only 2 digits behind ","
// if "," only 2 not 1 digit behind
if (!isValidateLongCurrency(arg0)) {
returnLong = 0L;
} else {
String valueFiltered = arg0.replace(".", "");
// 2: add 2 00 if no ",":
if (!valueFiltered.contains(",")) {
valueFiltered += "00";
}
else {
//E,C or E,CC
String[] splittedValue = valueFiltered.split(",");
if(splittedValue[splittedValue.length-1].length() == 1) {
valueFiltered = valueFiltered + 0;
}
valueFiltered = valueFiltered.replace(",", "");
}
try {
returnLong = new Long(valueFiltered);
} catch (NumberFormatException numEx) {
}
}
return returnLong;
}
private boolean isValidateLongCurrency(String value) {
boolean returnValue = true;
String valueFiltered = value.replace(".", "");
//Euro
String regEx = "^-?[1-9][0-9]*(,[0-9][0-9]?)?$|^-?[0-9](,[0-9][0-9]?)?$|^$";
returnValue = Pattern.matches( regEx, valueFiltered ) ;
return returnValue;
}
}
编辑2,现在正在运作
所做的更改:
import java.lang.annotation.*;
@Target(value={ElementType.METHOD,ElementType.FIELD,ElementType.PARAMETER})
@Retention(value=RetentionPolicy.RUNTIME)
public @interface LongCurrency {
}
@Override
public void addFormatters(FormatterRegistry registry) {
super.addFormatters(registry);
registry.addFormatterForFieldAnnotation(new
LongCurrencyFormatAnnotationFormatterFactory());
}
感谢M. Deinum
答案 0 :(得分:3)
对于初学者来说,你的注释已经不存在了。您需要确保它在运行时保留,默认情况下会删除注释。为此,在注释上添加@Retention
元注释。您可能还想添加@Target
注释以指定可以设置的类型。
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface LongCurrency {}
接下来请确保您已正确注册LongCurrencyFormatAnnotationFormatterFactory
。如果您没有注册,则不会使用它。
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatterForFieldAnnotation(new LongCurrencyFormatAnnotationFormatterFactory());
}
这两个更改都应该使您的格式化程序被调用/使用。