首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

SpringMVC 類型轉換、格式化與資料驗證完整指南

     編輯:Java 綜合教學

SpringMVC 類型轉換、格式化與資料驗證完整指南

本文從 <mvc:annotation-driven /> 切入,系統講解 SpringMVC 的類型轉換體系、格式化支援、JSR-303 驗證與 Spring Validator 兩種驗證方式,以及錯誤訊息前端顯示機制。

一、<mvc:annotation-driven /> 核心作用

  • 自動註冊 RequestMappingHandlerMapping、RequestMappingHandlerAdapter、ExceptionHandlerExceptionResolver
  • 啟用 ConversionService 支援表單參數類型轉換
  • 啟用 @Valid 支援 JSR-303 驗證
  • 啟用 @RequestBody/@ResponseBody 支援 REST/JSON

二、類型轉換與格式化

核心介面:ConversionService

位於 org.springframework.core.convert,透過 ConversionServiceFactoryBean 在 Spring 容器中配置實例。<mvc:annotation-driven /> 預設註冊 FormattingConversionServiceFactoryBean,支援日期/數字格式化。

自訂類型轉換器

實作 Converter<S, T> 介面:

public class PersonConverter implements Converter<String, Person> {
    @Override
    public Person convert(String source) {
        // 解析 "name:lily|age:23" → Person 物件
        String[] parts = source.split("\\|");
        Person p = new Person();
        for (String part : parts) {
            String[] kv = part.split(":");
            Field field = Person.class.getDeclaredField(kv[0]);
            field.setAccessible(true);
            if (field.getType().equals(Integer.class)) {
                field.set(p, Integer.parseInt(kv[1]));
            } else {
                field.set(p, kv[1]);
            }
        }
        return p;
    }
}

配置自訂 ConversionService

<bean id="formattingConversionService" 
      class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="com.example.converter.PersonConverter"/>
            <bean class="com.example.converter.String2MapConverter"/>
        </set>
    </property>
</bean>

<mvc:annotation-driven conversion-service="formattingConversionService"/>

關鍵點:使用 FormattingConversionServiceFactoryBean 而非 ConversionServiceFactoryBean,避免覆蓋預設日期/數字格式化器。

格式化註解:@DateTimeFormat、@NumberFormat

public class Employee {
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    @Past
    private Date birth;
    
    @NumberFormat(pattern = "#,###,###.##")
    private Double salary;
    // getter/setter...
}

請求 birth=1992-12-23&salary=1,234,567.89 自動綁定為 Date 與 Double。

三、資料驗證

方式一:Spring Validator 介面

public class PersonValidator implements Validator {
    @Override
    public boolean supports(Class<?> clazz) {
        return Person.class.equals(clazz);
    }
    @Override
    public void validate(Object target, Errors errors) {
        ValidationUtils.rejectIfEmpty(errors, "name", "name.empty", "姓名不能為空");
        Person p = (Person) target;
        if (p.getAge() < 0) errors.rejectValue("age", "negative", "年齡不能為負");
        else if (p.getAge() > 110) errors.rejectValue("age", "too.old", "年齡不可超過110");
    }
}
Controller 中使用
@InitBinder
public void initBinder(DataBinder binder) {
    binder.setValidator(new PersonValidator());
}

@RequestMapping("/test")
public String test(@Valid Person person, BindingResult result) {
    if (result.hasErrors()) {
        for (ObjectError e : result.getAllErrors()) {
            System.out.println(e.getDefaultMessage());
        }
    }
    return "success";
}

注意:@InitBinder("person") 可限定僅對特定模型屬性生效;同一 @InitBinder 方法只能設定一個 Validator,多個會覆蓋。

方式二:JSR-303 (Bean Validation) - 推薦

需引入 Hibernate Validator 實作:

validation-api-1.1.0.Final.jar
hibernate-validator-5.x.jar
jboss-logging-3.x.jar
classmate-1.x.jar
實體類加註解
public class Person {
    @NotBlank(message = "姓名不能為空")
    private String name;
    
    @Min(value = 10, message = "最小10歲", groups = First.class)
    @Max(value = 110, message = "最大110歲", groups = Second.class)
    private int age;
    // getter/setter...
}
Controller 直接使用
@RequestMapping("/test")
public String test(@Validated({First.class}) Person person, BindingResult result) {
    // 無需 @InitBinder,支援同一 Controller 多種 Bean 同時驗證
    ...
}
分組驗證
  • 定義標記介面:public interface First {}
  • 註解加 groups = First.class
  • Controller 用 @Validated({First.class, Second.class}) 指定分組,按順序驗證

自訂驗證註解

@Target({FIELD, METHOD})
@Retention(RUNTIME)
@Constraint(validatedBy = NumberValidator.class)
public @interface Number {
    String message() default "必須為數字";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

public class NumberValidator implements ConstraintValidator<Number, String> {
    @Override public void initialize(Number ann) {}
    @Override public boolean isValid(String value, ConstraintValidatorContext ctx) {
        try { Integer.parseInt(value); return true; }
        catch (NumberFormatException e) { return false; }
    }
}

四、前端錯誤訊息顯示

Spring MVC 標籤庫:<form:errors path="fieldName"/>

  • 錯誤代碼生成規則(以 @Pattern 驗證 password 為例):
    Pattern.user.password → Pattern.password → Pattern.java.lang.String → Pattern
  • 類型轉換錯誤前綴:typeMismatch
  • 缺少必填參數:required
  • 方法呼叫異常:methodInvocation

國際化訊息配置

<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basename" value="i18n"/>
</bean>

建立 i18n.properties / i18n_zh_TW.properties 等檔案,鍵對應上述錯誤代碼。

五、@InitBinder 進階

@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.setDisallowedFields("name"); // 禁止綁定 name 欄位
    binder.setAllowedFields("age", "email"); // 僅允許綁定指定欄位
    binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
}

工具推薦:中文 ↔ Unicode 在線轉換 atool.org

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved