Custom Binding Annotation - Tuong-Nguyen/Spring GitHub Wiki
Define a custom formatter to binds fields value using annotation.
Implement Formatter<Date> interface with <Date> is data type that is expected to bind.
public class VNDateFormatter implements Formatter<Date> {
private String pattern;
public VNDateFormatter(String pattern){
this.pattern = pattern;
}
@Override
public Date parse(String s, Locale locale) throws ParseException {
String date = "";
if (s.length() == 0){
return null;
}
int dayIndex = s.indexOf("ngay");
int monthIndex = s.indexOf("thang");
int yearIndex = s.indexOf("nam");
if (s.startsWith("ngay")){
String day = s.substring(dayIndex + 4, monthIndex).trim();
String month = s.substring(monthIndex + 5, yearIndex).trim();
String year = s.substring(yearIndex + 3).trim();
date = day + "/" + month + "/" + year;
}
return getDateFormat(locale).parse(date);
}
@Override
public String print(Date date, Locale locale) {
if (date == null) {
return "";
}
String[] dateArray = getDateFormat(locale).format(date).split("/");
String printDate = "ngay " + dateArray[0] + " thang " + dateArray[1] + " nam " + dateArray[2];
return printDate;
}
protected DateFormat getDateFormat(Locale locale) {
DateFormat dateFormat = new SimpleDateFormat(this.pattern, locale);
dateFormat.setLenient(false);
return dateFormat;
}
}Declare parameters for Formatter as pattern field and override two methods parse and print to custom for binding.
parse method: parse an instance of Date data type from the formatted representation from the client.
print method: print an instance of Date data type for display in the client.
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface VNDateFormat {
public static final String PATTERN_DEFAULT = "dd/MM/yyyy";
String pattern() default PATTERN_DEFAULT;
}The name of interface is name of annotation.
In the body of interface, initialize default value for parameters of Formatter i.e VNDateFormatter as shown above.
Create a class implements AnnotationFormatterFactory<VNDateFormat> interface with data type is annotation that have been created above.
public class VNDateFormatAnnotationFormatterFactory implements AnnotationFormatterFactory<VNDateFormat> {
@Override
public Set<Class<?>> getFieldTypes() {
return new HashSet<>(Arrays.asList(Date.class));
}
@Override
public Printer<?> getPrinter(VNDateFormat vnDateFormat, Class<?> aClass) {
return getVNDateFormatter(vnDateFormat, aClass);
}
@Override
public Parser<?> getParser(VNDateFormat vnDateFormat, Class<?> aClass) {
return getVNDateFormatter(vnDateFormat, aClass);
}
private Formatter<Date> getVNDateFormatter(VNDateFormat annotation, Class<?> fieldType){
VNDateFormatter vnDateFormatter = new VNDateFormatter(annotation.pattern());
return vnDateFormatter;
}
}Override:
getFieldTypes method to return the types of fields the annotation may be used on.
getPrinter and getParser method by getting arguments (i.e pattern value) from annotation to pass into Formatter.
In the WebConfig file, override addFormatters method to register AnnotationFormatterFactory above (i.e VNDateFormatAnnotationFormatterFactory)
@Override
public void addFormatters(FormatterRegistry registry) {
VNDateFormatAnnotationFormatterFactory factory = new
VNDateFormatAnnotationFormatterFactory();
registry.addFormatterForFieldAnnotation(factory);
}Annotate fields with a new annotation as @VNDateFormat
public class Course {
private int id;
private String title;
private String description;
@VNDateFormat(pattern = "dd/MM/yyyy")
private Date startDate;
@VNDateFormat(pattern = "dd/MM/yyyy")
private Date endDate;