Java 如何控制Thymeleaf模板中的有效数字(仅在必要时)?

Java 如何控制Thymeleaf模板中的有效数字(仅在必要时)?,java,spring,spring-mvc,thymeleaf,Java,Spring,Spring Mvc,Thymeleaf,使用th:text属性计算和呈现数字字段时,Thymeleaf会显示可用的完整位数。例如,这: <span th:text="${user.averageScore}"/> 我想显示这个数字,四舍五入到小数点后两位以内。从Thymeleaf文档中可以看出: <span th:text="${#numbers.formatDecimal(user.averageScore, 0, 2)}"/> 然而,有没有办法让这更灵活。。。如果该值的小数位数少于两位?我只想去掉小数点

使用
th:text
属性计算和呈现数字字段时,Thymeleaf会显示可用的完整位数。例如,这:

<span th:text="${user.averageScore}"/>
我想显示这个数字,四舍五入到小数点后两位以内。从Thymeleaf文档中可以看出:

<span th:text="${#numbers.formatDecimal(user.averageScore, 0, 2)}"/>
然而,有没有办法让这更灵活。。。如果该值的小数位数少于两位?我只想去掉小数点,减少到两位。我从来不想加小数点,最多两位。如果上述字段的值为107,则它将呈现为:

107.00

我如何制作两位或更少小数的Thymeleaf格式的数字。。。而不是仅仅两位小数,不管怎样?

嗨,你可以试试这样的东西

<span th:text="${user.averageScore} % 1 == 0? ${user.averageScore} :${#numbers.formatDecimal(user.averageScore, 0, 2)}"/>

在Thymeleaf 2.1中没有简单的方法可以做到这一点,但有两种困难的方法

艰难之路#1:Fork Thymeleaf并向org.Thymeleaf.expression.Numbers类添加一个格式方法,该方法满足您的需要(添加一个采用十进制格式模式的方法看起来像是一个逻辑扩展)

困难之路#2:向Thymeleaf添加一个方言,该方言提供了一个新的表达式类,可以执行您想要的格式设置。我下面的示例基于使用Spring和Thymeleaf注册一种方言来格式化表示小时的数字

步骤1:注册方言:

@Component
public class ThymeLeafSetup implements InitializingBean {

@Autowired
private SpringTemplateEngine templateEngine;

@Override
public void afterPropertiesSet() throws Exception {
    templateEngine.addDialect(new HoursDialect());
}
}
步骤2:创建方言类(委托给TimeUtils静态方法的格式化逻辑)-基于Java8TimeDialante:

public class HoursDialect extends AbstractDialect implements IExpressionEnhancingDialect {
public static class Hours {
    public String format(BigDecimal hours) {
        return TimeUtils.formatHours(hours);
    }
}

@Override
public String getPrefix() {
    // No attribute or tag processors, so we don't need a prefix at all and
    // we can return whichever value.
    return "hours";
}

@Override
public boolean isLenient() {
    return false;
}

@Override
public Map<String, Object> getAdditionalExpressionObjects(IProcessingContext processingContext) {
    return Collections.singletonMap("hours", new Hours());
}
}
步骤4:格式化逻辑测试

@Test
public void formatDecimalWilLFormatAsExpected() {
    verifyHourNumberFormatsAsExpected("1.5", "1.5");
    verifyHourNumberFormatsAsExpected("1.25", "1.25");
    verifyHourNumberFormatsAsExpected("123.0", "123");
    verifyHourNumberFormatsAsExpected("1230", "1,230");
}

void verifyHourNumberFormatsAsExpected(String number, String expected) {
    assertThat(TimeUtils.formatHours(new BigDecimal(number))).isEqualTo(expected);
}

第二个和第三个参数是什么?
public class HoursDialect extends AbstractDialect implements IExpressionEnhancingDialect {
public static class Hours {
    public String format(BigDecimal hours) {
        return TimeUtils.formatHours(hours);
    }
}

@Override
public String getPrefix() {
    // No attribute or tag processors, so we don't need a prefix at all and
    // we can return whichever value.
    return "hours";
}

@Override
public boolean isLenient() {
    return false;
}

@Override
public Map<String, Object> getAdditionalExpressionObjects(IProcessingContext processingContext) {
    return Collections.singletonMap("hours", new Hours());
}
}
public class TimeUtils {

public static String formatHours(BigDecimal hours) {
    DecimalFormat format = new DecimalFormat("#0.##");
    format.setGroupingUsed(true);
    format.setGroupingSize(3);
    return format.format(hours);
}
}
@Test
public void formatDecimalWilLFormatAsExpected() {
    verifyHourNumberFormatsAsExpected("1.5", "1.5");
    verifyHourNumberFormatsAsExpected("1.25", "1.25");
    verifyHourNumberFormatsAsExpected("123.0", "123");
    verifyHourNumberFormatsAsExpected("1230", "1,230");
}

void verifyHourNumberFormatsAsExpected(String number, String expected) {
    assertThat(TimeUtils.formatHours(new BigDecimal(number))).isEqualTo(expected);
}