Spring MVC Formatear fechas y números

Cuando usemos la anotación @EnableWebMvc sobre nuestra clase de configuración o la etiqueta <mvc:annotation-driven/> en su correspondiente archivo de configuración XML automáticamente habilitaremos la capacidad de formatear fechas con @DateTimeFormat, también podremos darle formato a los campos números con  @NumberFormat

La configuración del Servlet 3.1+ la haremos mediante código Java, es simple, solo añadiremos el ViewResolver para las vistas JSP.

@EnableWebMvc
@Configuration
@ComponentScan(basePackages = {"carmelo.spring.controller"})
public class WebAppConfig extends WebMvcConfigurerAdapter {

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.jsp("/WEB-INF/views/", ".jsp");
    }   
}

Nuestra clase modelo la llamaremos Empleado la misma se define de la siguiente manera:

public class Empleado {
    
    private String nombre;
    private LocalDate fecha;
    private BigDecimal salario;

    public Empleado() {
        this.nombre = "Empleado Uno";
        this.fecha = LocalDate.now();
        this.salario = BigDecimal.valueOf(12000.6789);
    }

   // getter, setter, ...
    
}

El controlador será la clase HomeController la misma ingresa un atributo de tipo Empleado al modelo y devuelve el nombre de la vista .jsp que utilizaremos.

@Controller
public class HomeController {

    @RequestMapping("/")
    public String home(Model model) {
        model.addAttribute("empleado", new Empleado());
        return "home";
    }
}

El archivo /WEB-INF/views/home.jsp define la vista, veamos su código:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="mvc" %>
<%@taglib uri="http://www.springframework.org/tags" prefix="spring" %>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Spring MVC Formatter</title>
        <style>
            body {font-family: Segoe UI Light;}
            input {width: 100%;}       
            .row-divider {margin: 10px; border-bottom: 1px solid gray;}
        </style>
    </head>
    <body>
        <h1>Spring MVC Formatter</h1>

        <mvc:form modelAttribute="empleado" action="create">
            <fieldset>
                <legend>Datos del Empleado</legend>
                
                <mvc:label path="nombre" >Nombre completo: </mvc:label> <br />
                <mvc:input path="nombre" />
                
                <div class="row-divider" ></div>
                
                <mvc:label path="fecha" >Fecha de inicio: </mvc:label> <br />
                <mvc:input path="fecha" />
                
                <div class="row-divider" ></div>
                
                <mvc:label path="salario" >Salario bruto: </mvc:label> <br />
                <mvc:input path="salario" />
            </fieldset>
        </mvc:form>
    </body>
</html>

Si corremos y abrimos el navegador veremos lo siguiente:

image

Lo que tenemos hasta aquí lo hemos visto en tutoriales anteriores, lo que nos interesa mostrar es como podemos darle formato a la fecha y el salario, para ello usaremos las anotaciones @DateTimeFormat y @NumberFormat que nos servirán para formatear fechas y números.

public class Empleado {
    
    private String nombre;
    
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate fecha;
    
    //@NumberFormat(pattern = "##,###.##")
    @NumberFormat(style = NumberFormat.Style.CURRENCY)
    private BigDecimal salario;

}

Formato para números y fechas en Spring MVC

La enumeración NumberFormat.Style nos provee de varios patrones de formato que podemos utilizar, prueba cada uno de ellos para apreciar la salida, además también es posible crear nuestro propio patrón, por ejemplo: @NumberFormat(pattern = "##,###.##"), de igual forma la anotación para las fechas @DateTimeFormat(pattern = "yyyy-MM-dd") define un patrón para formato.

Crear un Formatter personalizado

Es posible crear un Formatter personalizado para cualquier clase, para ver un ejemplo sencillo veremos como podemos definir uno para la clase LocalDate, para crearlo debemos implementar la interface Formatter<T> donde T es el tipo de clase para la cual crearemos el Formatter.

Es necesario implementar los métodos print(...) y parse(...), el primero convierte el objeto T en su cadena de texto correspondiente y el segundo hace el proceso inverso, toma una cadena de texto y la convierte en el objeto T.

public class LocalDateFormatter implements Formatter<LocalDate> {

    private static final String PATTERN = "(dd) (MM) (yyyy)";

    @Override
    public String print(LocalDate fecha, Locale locale) {
        return fecha.format(DateTimeFormatter.ofPattern(PATTERN, locale));
    }

    @Override
    public LocalDate parse(String string, Locale locale) throws ParseException {
        return LocalDate.parse(string, DateTimeFormatter.ofPattern(PATTERN, locale));
    }

}

El objeto LocalDate es fácil transformarlo a texto usando el método format(...) solo debemos indicar el patrón a usar, para obtener el objeto a partir de una cadena usamos LocalDate.parse(...) indicando la cadena y el patrón usado por la misma.

Para poder usar el LocalDateFormatteraddFormatters(FormatterRegistry registry) y usamos el método del objeto registry addFormatterForFieldType(...) para registrar el formatter, al usar este método todos los campos del tipo indicado, LocalDate, se formatearán usando la clase LocalDateFormatter.

@EnableWebMvc
@Configuration
@ComponentScan(basePackages = {"carmelo.spring.controller"})
public class WebAppConfig extends WebMvcConfigurerAdapter {

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.jsp("/WEB-INF/views/", ".jsp");
    }

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addFormatterForFieldType(LocalDate.class, new LocalDateFormatter());
    }
    
}

Formatear fechas en Spring MVC

Con esto ya no es necesario usar la anotación @DateTimeFormat para formatear los campos de fecha, siempre que estos sean de tipo LocalDate.

Descargar: springmvc-formatter.zip

Comentarios

Entradas populares de este blog

Conectar SQL Server con Java

Entrenar OpenCV en Detección de Objetos

Procesamiento de imágenes en OpenCV

Acceso a la webcam con OpenCV

Conociendo la clase cv::Mat de OpenCV