Spring MVC格式化器(Java学习笔记)

在实际的项目开发中,经常会涉及到一些需要进行格式化的数据,例如金额、日期等。以金额为例,当金额为 10 万元时,在比较正式的场合往往要写成 ¥100000;而日期也可以被写作多种格式,例如 yyyy-MM-dd、yyyy-MM-dd hh:ss:mm 等。这些数据都要经过一定的格式化处理才能够正常使用。

Formatter接口

Spring 提供了一个 Formatter 接口, T 表示目标数据类型,它被称为格式化转换器。

Formatter 的作用与 Converter(类型转换器)相似,都是可以将一种数据类型转换成另一种数据类型。但不同的是,Formatter 的源类型必须是 String 类型,而 Converter 的源类型可以是任意数据类型。

package org.springframework.format;

public interface Formatter<T> extends Printer<T>, Parser<T> {
}

Formatter 接口继承了 Printer 和 Parser 接口,其泛型 T 表示字符串需要转换的目标类型。 在 Printer 和 Parser 接口中,分别包含一个 print() 方法和一个 parse() 方法。Spring MVC 中所有的格式化转换器实现类都必须重写(覆盖)这两个方法。

方法接口说明
T parse(String text, Locale locale) throws ParseException; Printer该方法能够将数据按照一定的格式输出成字符串。该方法中包含一个 Locale 类型的参数,即该方法可根据地区来做出相应的定制。
String print(T object, Locale locale); Parser该方法能够将满足一定格式的字符串转换为对象。其包含一个 Locale 类型的参数,即该方法可根据国家和地区做出相应的定制。

内置格式化转换器

Spring MVC 默认提供了多个内置的格式化器,通过它们,我们可以轻松地实现对日期(Date)类型和数值(Number)类型数据的格式化工作,具体如下。

内置格式化器说明
NumberFormatter实现 Number 与 String 之间的解析与格式化。
CurrencyFormatter实现 Number 与 String 之间的解析与格式化(带货币符号)。
PercentFormatter实现 Number 与 String 之间的解析与格式化(带百分数符号)。
DateFormatter实现 Date 与 String 之间的解析与格式化。

虽然 Formatter 与 Converter 存在一定的差异,但格式化转换本质上还是属于“类型转换”的范畴,因此在 Spring MVC 中 Formatter(格式化转换器)实际上是委托给 Converter 机制实现的。

Spring 的格式化模块中定义了一个 FormattingConversionService 类,它是 ConversionService 接口(类型转换器的服务接口)的实现类。它与其他的类型转换器实现类不同,它不仅具有类型转换功能,还具有格式化转换功能。

Spring MVC 还专门为 FormattingConversionService 提供了一个名为 FormattingConversionServiceFactroyBean 的工厂类,它主要作用就是在 Spring 上下文中构造 FormattingConversionService 的实例。

除此之外,FormattingConversionServiceFactroyBean 还为以下 2 个格式化注解提供了支持,使得我们可以更加方便地使用 Spring MVC 内置的格式化器,对数据进行格式化转换。

格式化注解说明
@DateTimeFormat 注解使用该注解,能够实现对日期类型数据的格式化
@NumberFormat 注解使用该注解,能够实现对数值类型数据的格式化

我们知道,只要 Spring MVC 的配置文件中配置一个 mvc:annotation-driven 标签,Spring MVC 在启动时就会自动初始化一个 FormattingConversionServiceFactoryBean 类型的实例:ConversionService。

也就是说,我们只要在 Spring MVC 配置文件中配置了 mvc:annotation-driven 标签,就可以直接在 Spring MVC 项目中使用 @NumberFormat 注解和 @DateTimeFormat 注解,对 Number 类型和 Date 类型数据进行格式化转换。

日期格式化

@DateTimeFormat 注解可对 java.util.Date、java.util.Calendar、java.long.Long 等时间类型的数据进行标注,以实现对日期类型的数据进行格式化处理。

@DateTimeFormat 注解主要包含以下 3 个属性。

属性类型说明
patternString用于指定解析或格式化日期时间的模式,其常用取值包括 yyyy-MM-dd、yyyy-MM-dd hh:mm:ss 等。
isoDateTimeFormat.ISO用于指定解析或格式化日期时间的 ISO 模式,其取值有 4 种:DATE:yyyy-MM-dd。TIME:hh:mm:ss:SSSZ。DATE_TIME:yyyy-MM-dd hh:mm:ss:SSSZ。NONE:无
styleString用于指定日期时间的格式。该属性由两个字符组成,第一个字符表示日期的格式,第二个字符表示时间的格式。S:短日期/时间格式。M:中日期/时间格式。L:长日期/时间格式。F:完整日期/时间格式。其默认值为“SS”,即日期和时间都采用短格式。

数值格式化@NumberFormat 注解可以用来格式化任何数字基本类型(如 int、long 等)或 java.lang.Number 类型的实例(如 BigDecimal、Integer 等)。

@NumberFormat 注解拥有两个互斥的属性,如下表。

属性类型说明
styleNumberFormat.Style该属性用于指定数值的样式类型,其取值有以下 4 种:DEFAULT:默认类型/NUMBER:正常数值类型/PERCENT:百分数类型/CURRENCY:货币数值类型
patternString该属性用于自定义数值的样式星星,例如 #,###

实例

创建Spring MVC项目添加相关依赖:
pom.xml文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>formatter</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>formatter</name>
    <packaging>war</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
        <junit.version>5.8.2</junit.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <!--    Spring Web MVC 开发必备依赖-->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.2.15.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.2.15.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.15.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.2.15.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>5.2.15.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.2.15.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.15.RELEASE</version>
        </dependency>

        <!--    Thymeleaf的依赖-->
        <dependency>
            <groupId>org.attoparser</groupId>
            <artifactId>attoparser</artifactId>
            <version>2.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring5</artifactId>
            <version>3.0.15.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.unbescape</groupId>
            <artifactId>unbescape</artifactId>
            <version>1.1.6.RELEASE</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.3.2</version>
            </plugin>
        </plugins>
    </build>
</project>

web.xml文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <!--请求和响应的字符串过滤器-->
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--来处理 PUT 和 DELETE 请求的过滤器-->
    <filter>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- 配置SpringMVC的前端控制器,对浏览器发送的请求统一进行处理 -->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--配置 DispatcherServlet 的一个初始化参数:spring mvc 配置文件按的位置和名称-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springMVC.xml</param-value>
        </init-param>

        <!--作为框架的核心组件,在启动过程中有大量的初始化操作要做
            而这些操作放在第一次请求时才执行会严重影响访问速度
            因此需要通过此标签将启动控制DispatcherServlet的初始化时间提前到服务器启动时-->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <!--设置springMVC的核心控制器所能处理的请求的请求路径
        /所匹配的请求可以是/login或.html或.js或.css方式的请求路径
        但是/不能匹配.jsp请求路径的请求-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

在rersource文件夹下创建springMVC.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--开启组件扫描-->
    <context:component-scan base-package="com.example.formatter"/>

    <!-- 配置 Thymeleaf 视图解析器 -->
    <bean id="viewResolver"
          class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
        <property name="order" value="1"/>
        <property name="characterEncoding" value="UTF-8"/>
        <property name="templateEngine">
            <bean class="org.thymeleaf.spring5.SpringTemplateEngine">
                <property name="templateResolver">
                    <bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
                        <!-- 视图前缀 -->
                        <property name="prefix" value="/WEB-INF/templates/"/>
                        <!-- 视图后缀 -->
                        <property name="suffix" value=".html"/>
                        <property name="templateMode" value="HTML5"/>
                        <property name="characterEncoding" value="UTF-8"/>
                    </bean>
                </property>
            </bean>
        </property>
    </bean>
    <!--view-name:设置请求地址所对应的视图名称-->
    <mvc:view-controller path="/" view-name="supermarket"/>
    <!--注解驱动-->
    <mvc:annotation-driven/>
</beans>

bean.Supermarket类:

package com.example.formatter.bean;

import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.NumberFormat;

import java.math.BigDecimal;
import java.util.Date;


public class Supermarket {
    private String name;
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date date;
    /**
     * 使用 @NumberFormat 注解格式化数值
     */
    @NumberFormat(style = NumberFormat.Style.CURRENCY)
    private BigDecimal money;


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public BigDecimal getMoney() {
        return money;
    }

    public void setMoney(BigDecimal money) {
        this.money = money;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    @Override
    public String toString() {
        return "Supermarket{" +
                "name='" + name + '\'' +
                ", date=" + date +
                ", money=" + money +
                '}';
    }
}

controller.MarketController

package com.example.formatter.controller;

import com.example.formatter.bean.Supermarket;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class MarketController {

    @RequestMapping(value = "/market", method = RequestMethod.POST)
    public String login(Supermarket market, Model model) {
        model.addAttribute("market", market);
        System.out.println(market);
        return "success";
    }
}

在WEB-INF/templates下:
supermarket.html:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="UTF-8">
  <title>测试</title>
</head>
<body>
<form th:action="@{/market}" method="post">
  <table>
    <tr>
      <td>名称:</td>
      <td><input type="text" name="name" required><br></td>
    </tr>
    <tr>
      <td>收入:</td>
      <td><input type="text" name="money" required><br></td>
    </tr>
    <tr>
      <td>日期:</td>
      <td><input type="date" name="date" required><br></td>
    </tr>

    <tr>
      <td colspan="2" align="center">
        <input type="submit" value="提交">
        <input type="reset" value="重置">
      </td>
    </tr>
  </table>
</form>
</body>
</html>

success.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="UTF-8">
  <title>测试</title>
</head>
<body>
<table>
  <tr>
    <td>名称:</td>
    <td th:text="${market.getName()}"></td>
  </tr>
  <tr>
    <td>收入:</td>
    <td th:text="${market.getMoney()}"></td>
  </tr>
  <tr>
    <td>日期:</td>
    <td th:text="${#dates.format(market.getDate(),'yyyy-MM-dd')}"></td>
  </tr>
</table>
</body>
</html>

修改应用配置:
在这里插入图片描述
启动应用:
在这里插入图片描述
运行结果:
在这里插入图片描述

#学习原文

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值