在Spring框架中,格式化器(Formatter)和注解(Annotation)是处理数据格式化和验证的强大工具。通过将注解与格式化器绑定,我们可以在字段级别灵活地定义数据的格式化规则。本文将通过一个完整的示例,展示如何创建自定义注解、格式化器,并将它们绑定到Spring的AnnotationFormatterFactory中,实现字段级别的数据格式化。
一、背景与需求
在开发Web应用时,我们经常需要对用户输入的数据进行格式化处理。例如,地址信息可能需要根据不同的显示需求进行格式化。Spring 3的Formatter API允许我们通过注解绑定自定义格式化器,从而在字段级别灵活定义数据的格式化规则。
二、创建实体类
首先,我们需要定义一些实体类来存储数据。这里以Customer和Address为例:
java复制
public class Customer {
private Long id;
private String name;
private Address address;
// getters and setters
}
public class Address {
private String street;
private String city;
private String county;
private String zipCode;
// getters and setters
}
三、创建自定义格式化器
接下来,我们创建一个自定义的格式化器AddressFormatter,用于格式化Address对象。格式化器可以根据不同的样式(如全地址或地区)来输出地址信息:
java复制
import org.springframework.format.Formatter;
import java.text.ParseException;
import java.util.Locale;
public class AddressFormatter implements Formatter
{private Style style = Style.FULL;
public void setStyle(Style style) {
this.style = style;
}
@Override
public Address parse(String text, Locale locale) throws ParseException {
// 解析逻辑(省略)
return new Address();
}
@Override
public String print(Address address, Locale locale) {
switch (style) {
case FULL:
return address.getStreet() + ", " + address.getCity() + ", " + address.getCounty() + " " + address.getZipCode();
case REGION:
return address.getCity() + ", " + address.getCounty();
default:
return address.getStreet();
}
}
public enum Style {
FULL, REGION
}
}
四、定义自定义注解
为了在字段级别使用格式化器,我们需要定义一个注解@AddressFormat,并将其绑定到AddressFormatter:
java复制
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface AddressFormat {
AddressFormatter.Style style() default AddressFormatter.Style.FULL;
}
五、绑定注解与格式化器
通过实现AnnotationFormatterFactory接口,我们可以将注解与格式化器绑定起来:
java复制
import org.springframework.format.AnnotationFormatterFactory;
import org.springframework.format.Parser;
import org.springframework.format.Printer;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class AddressFormatAnnotationFormatterFactory implements AnnotationFormatterFactory {
@Override
public Set<Class<?>> getFieldTypes() {
return new HashSet<>(Arrays.asList(Address.class));
}
@Override
public Printer<?> getPrinter(AddressFormat annotation, Class<?> fieldType) {
return getAddressFormatter(annotation, fieldType);
}
@Override
public Parser<?> getParser(AddressFormat annotation, Class<?> fieldType) {
return getAddressFormatter(annotation, fieldType);
}
private AddressFormatter getAddressFormatter(AddressFormat annotation, Class<?> fieldType) {
AddressFormatter formatter = new AddressFormatter();
formatter.setStyle(annotation.style());
return formatter;
}
}
六、注册AnnotationFormatterFactory
在Spring配置中,我们需要将AnnotationFormatterFactory注册到FormatterRegistry中:
java复制
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@EnableWebMvc
@Configuration
public class MyWebConfig extends WebMvcConfigurerAdapter {
@Override
public void addFormatters(FormatterRegistry registry) {
AddressFormatAnnotationFormatterFactory factory = new AddressFormatAnnotationFormatterFactory();
registry.addFormatterForFieldAnnotation(factory);
}
}
七、使用注解
在Customer类中,我们可以通过@AddressFormat注解指定地址的格式化方式:
java复制
public class Customer {
private Long id;
private String name;
@AddressFormat(style = AddressFormatter.Style.FULL)
private Address address;
// getters and setters
}
八、创建控制器与视图
最后,我们创建一个简单的控制器和JSP页面来展示格式化后的数据:
控制器
java复制
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
@RequestMapping(“/customers”)
public class CustomerController {
@RequestMapping(method = RequestMethod.GET)
public String handleRequest(Model model) {
// 假设从服务层获取客户数据
model.addAttribute(“customerList”, getCustomerData());
return “customers”;
}
private List<Customer> getCustomerData() {
// 模拟数据
Customer customer = new Customer();
customer.setId(1L);
customer.setName("John Doe");
Address address = new Address();
address.setStreet("123 Main St");
address.setCity("Springfield");
address.setCounty("Spring County");
address.setZipCode("12345");
customer.setAddress(address);
return Collections.singletonList(customer);
}
}
JSP页面(customers.jsp)
jsp复制
<%@ page language=“java” contentType=“text/html; charset=ISO-8859-1” pageEncoding=“ISO-8859-1”%>
<%@ taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core”%>
<%@taglib uri=“http://www.springframework.org/tags” prefix=“spring” %>