自定义注释驱动格式化Spring MVC [英] Custom Annotation-driven Formatting Spring MVC

查看:138
本文介绍了自定义注释驱动格式化Spring MVC的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将一个java EE应用程序迁移到spring boot并且我遇到了转换问题。
现在,无论我的货币是否良好,我将我的货币存储为Long(其德国欧元)。
我写了一个自定义的jsf转换器,它做了类似的事情:

I am migrating a java EE application to spring boot and i got stuck at a converting problem. Now whether its good or not i stored my currencies as Long (its german euro). I wrote a custom jsf converter that does something like that:

长 - >字符串

22 - > 00,22

22 -> 00,22

3310 - > 33,10

3310 -> 33,10

字符串 - >长

3 - > 3

22,11 - > 2211

22,11 -> 2211

现在,Spring MVC是摆脱JSF的一个原因。
我想使用303 Beanvalidation,使用Spring MVC(@Valid @ModelAttribute,BindingResult适用于@Pattern例如)

Now Spring MVC was one reason to move away from JSF. I would like to make use of 303 Beanvalidation, with Spring MVC (@Valid @ModelAttribute, BindingResult which works fine for @Pattern e.g)

现在我不能使用@NumberFormat(style = Style.Currency),这可以做我想要的,如果我没有存储我的货币那么久。

Now i cant use @NumberFormat(style=Style.Currency), which would do what I want, if I have not stored my currency as long.

我写了一个自定义格式化程序并注册它到FormatterRegistry

I wrote a custom Formatter and registered it to 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正在运行,但现在每个long都被转换。我认为是对的。
因此经过一些研究后我研究了6.6.2注释驱动的格式化
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html

to this point everthing is working, but now every long is converted. What I think is right. So after some research I looked into 6.6.2 Annotation-driven Formatting http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html

我在文档中创建AnnotationFormatterFactory

I created as in the documentation an 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:对于输入字符串:22,00

sadly it is not working : Failed to convert property value of type java.lang.String to required type long for property value; nested exception is java.lang.NumberFormatException: For input string: "22,00"

对于长篇帖子感到抱歉,不知道我做错了什么?或者更好的解决方案将格式化程序绑定到一个控制器?数据库模拟应该是最不可能的选择。

Sorry for the long post, any idea what i did wrong ? Or any better Solution to bind a formatter to only one controller? A Databasemirgration should be the very least option.

谢谢!

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

Thanks to M. Deinum

推荐答案

对于初学者来说,你的注释不再存在了。您需要确保它在运行时保留,默认情况下会删除注释。为此,在注释上添加 @Retention 元注释。您可能还想添加 @Target 注释来指定可以设置的类型。

For starters your annotation isn't there anymore. You need to make sure it is retained at runtime, by default annotations are removed. For this add the @Retention meta annotation on your annotation. You probably also want to add the @Target annotation to specify on which types it can be set.

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface LongCurrency {}

接下来请确保您已注册 LongCurrencyFormatAnnotationFormatterFactory 正常。如果您没有注册它将不会被使用。

Next make sure that you have registered your LongCurrencyFormatAnnotationFormatterFactory properly. If you don't register it it will not be used.

@Override 
public void addFormatters(FormatterRegistry registry) {
    registry.addFormatterForFieldAnnotation(new LongCurrencyFormatAnnotationFormatterFactory()); 
}

这两项更改都应该使您的格式化程序被调用/使用。

Both changes should make that your formatter is going to be called/used.

这篇关于自定义注释驱动格式化Spring MVC的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆