1、消息處理功能html
Spring提供MessageSource接口用於提供消息處理功能:java
public interface MessageSource { String getMessage(String code, Object[] args, String defaultMessage, Locale locale); String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException; String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException; }
Spring提供了兩個默認實現:git
StaticMessageSource // 測試用 ResourceBundleMessageSource // 用於生產環境
ApplicationContext
接口擴展了MessageSource
接口,當ApplicationContext
被加載時,它會自動在context中查找已定義爲MessageSource
類型的bean。此bean的名稱須爲messageSource
。若是找到,那麼全部對上述方法的調用將被委託給該bean。不然ApplicationContext
會在其父類中查找是否含有同名的bean。若是有,就把它做爲MessageSource
。若是它最終沒有找到任何的消息源,一個空的StaticMessageSource
將會被實例化,使它可以接受上述方法的調用。正則表達式
示例以下:spring
屬性文件api
# exception.properties message.arg=the {0} {1} is requred. # format.properties message=這是一條測試消息 # format_en_GB.properties message=this is a test
spring 配置(spring-validation.xml)mvc
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd "> <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <property name="basenames"> <list> <value>classpath:format</value> <value>classpath:exception</value> </list> </property> <property name="fileEncodings"> <props> <prop key="classpath:format">utf-8</prop> </props> </property> </bean> </beans>
測試app
public class MessageTest { public static void main(String[] args) { MessageSource ms = new ClassPathXmlApplicationContext("spring-validation.xml"); String msg1 = ms.getMessage("message", null, "yeah", null); String msg2 = ms.getMessage("message.arg", new Object[] { "aa", "bb" }, "yeah", null); // 參數定製 String msg3 = ms.getMessage("message", null, "yeah", Locale.UK); // 支持國際化 System.out.println(msg1); System.out.println(msg2); System.out.println(msg3); } }
運行結果ide
這是一條測試消息 the aa bb is requred. this is a test
補充:spring提供了MessageSourceAware接口,用於在bean建立時自動注入MessageSource。post
2、數據驗證
JSR-303 (Bean Validation 1.0)定義了基於註解JavaBean數據驗證規範,註解以下:
@Null 被註釋的元素必須爲null @NotNull 被註釋的元素必須不爲null @AssertTrue 被註釋的元素必須爲true @AssertFalse 被註釋的元素必須爲false @Min(value) 被註釋的元素必須爲一個數字,其值必須大於等於指定值 @Max(value) 被註釋的元素必須爲一個數字,其值必須小於等於指定值 @DecimalMin(value) 被註釋的元素必須爲一個數字,其值必須大於等於指定值 @DecimalMax(value) 被註釋的元素必須爲一個數字,其值必須小於等於指定值 @Size(max, min) 被註釋的元素必須在指定範圍內 @Digits(integer, fraction) 被註釋的元素必須爲一個數字,其值必須在可接受的範圍內 @Past 被註釋的元素必須是一個過去的日期 @Future 被註釋的元素必須是一個未來的日期 @Pattern(value) 被註釋的元素必須符合指定的正則表達式 @Valid 被註釋的元素必須爲對象,表示遞歸驗證對象屬性
hibernate validator 在JSR303的基礎上對校驗註解進行了擴展,擴展註解以下:
@Emai 被註釋的元素必須是電子郵件格式 @Length 被註釋的字符串大小必須在指定範圍內 @NotEmpty 被註釋的字符串必須非空 @Range 被註釋的元素必須在合適的範圍內
全部被支持的註解列表參見:hibernate-validator -> /org/hibernate/validator/ValidationMessages.properties
spring在hibernate validator基礎上對JavaBean的數據校驗方式進行了封裝,配置與使用方式以下:
一、添加依賴
<dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.1.Final</version> </dependency> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.16.Final</version> </dependency>
二、添加配置
<!-- validator bean --> <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"> <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/> <property name="validationMessageSource" ref="messageSource"/> </bean> <!-- 註冊(註冊方式與Converter相同,參見Spring MVC 使用介紹(八)—— 類型轉換) --> <mvc:annotation-driven validator="validator" />
注:messageSource的配置與上例相同
# format.properties msg.age=性別須大於{value}歲
三、使用
Java Bean
public class Person { @NotNull private String name; @Min(value = 12, message = "{msg.age2}") private int age; ... }
controller
@ControllerAdvice public class MyControllerAdvice { @ResponseBody @ExceptionHandler public Map<String, String> errorhandler(Exception ex) { BindException e = (BindException) ex; Map<String, String> map = new HashMap<>(); map.put("error", e.getBindingResult().getFieldError().getDefaultMessage()); return map; } }
@RestController public class ValidController { @RequestMapping("/test1") public Person test1(@Valid Person person) { return person; } }
四、測試
訪問:http://localhost:8080/shiro-test/test1?name=12&age=6,輸出
{"error":"性別須大於12歲"}
訪問:http://localhost:8080/shiro-test/test1?age=20,輸出
{"error":"must not be null"}
3、錯誤消息
數據驗證錯誤消息的指定有多種方式:
一、默認錯誤消息
默認的錯誤消息文件是/org/hibernate/validator/ValidationMessages.properties,以下圖所示:
消息鍵默認爲:驗證約束註解的全限定類名.message
當不指定驗證註解的message屬性時,則使用默認消息
二、覆蓋默認錯誤消息
方法很簡單:在MessageSource的屬性文件中依據默認消息鍵從新定義鍵值:
# format.properties javax.validation.constraints.NotNull.message = 不能爲空
三、自定義錯誤消息
在屬性文件中定義錯誤消息,使用註解的message屬性引用:
# format.properties
msg.notnull=不能爲空
public class Person { @NotNull(message = "{msg.notnull}") private String name; ... }
3.1 消息佔位符
可在錯誤消息中使用佔位符獲取約束值,規則爲:{驗證註解屬性名},如@Length有min和max屬性,可在消息文件中使用{min}和{max}獲取;@Max有value屬性,可以使用{value}獲取
msg.age=性別須大於{value}歲
3.2 EL表達式
可在錯誤消息中使用EL表達式,規則爲:${表達式},如可以使用${validatedValue}獲取驗證值,使用${min > 1 ? '大於1' : '小於等於1'}添加邏輯判斷:
javax.validation.constraints.Size.message = [${validatedValue}]須大於等於{min}字符 javax.validation.constraints.Min.message = 數量${min > 1 ? '大於1' : '小於等於1'}
在EL表達式中,可以使用java.util.Formatter類型的formatter變量進行格式化:
${formatter.format("%04d", min)}
參考:
spring中ResourceBundleMessageSource的配置使用方法
SpringMVC數據驗證——第七章 註解式控制器的數據驗證、類型轉換及格式化——跟着開濤學SpringMVC