5 將 i18n 用于錯(cuò)誤消息
如果你的應(yīng)用程序支持多種語言,則必須使用國際化 (i18n) 以用戶首選語言顯示錯(cuò)誤消息。
以下是在 Spring Boot 應(yīng)用程序中使用 i18n 處理錯(cuò)誤消息的示例
- 首先,在資源目錄下創(chuàng)建一個(gè)包含默認(rèn)錯(cuò)誤消息的
messages.properties
文件
# messages.properties
user.name.required=Name is required.
user.email.invalid=Invalid email format.
user.age.invalid=Age must be a number between 18 and 99.
- 接下來,為每種支持的語言創(chuàng)建一個(gè)
messages_xx.properties
文件,例如,中文的messages_zh_CN.properties
。
user.name.required=名稱不能為空.
user.email.invalid=無效的email格式.
user.age.invalid=年齡必須在18到99歲之間.
- 然后,更新您的驗(yàn)證注釋以使用本地化的錯(cuò)誤消息
public class User {
@NotNull(message = "{user.id.required}")
private Long id;
@NotBlank(message = "{user.name.required}")
private String name;
@Email(message = "{user.email.invalid}")
private String email;
@NotNull(message = "{user.age.required}")
@Min(value = 18, message = "{user.age.invalid}")
@Max(value = 99, message = "{user.age.invalid}")
private Integer age;
}
- 最后,在 Spring 配置文件中配置
MessageSource bean
以加載i18n
消息文件
@Configuration
public class AppConfig {
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
@Bean
public LocalValidatorFactoryBean validator() {
LocalValidatorFactoryBean validatorFactoryBean = new LocalValidatorFactoryBean();
validatorFactoryBean.setValidationMessageSource(messageSource());
return validatorFactoryBean;
}
}
- 現(xiàn)在,當(dāng)發(fā)生驗(yàn)證錯(cuò)誤時(shí),錯(cuò)誤消息將根據(jù)隨請(qǐng)求發(fā)送的“Accept-Language”標(biāo)頭以用戶的首選語言顯示。
6 使用分組驗(yàn)證
驗(yàn)證組是 Spring Boot 驗(yàn)證框架的一個(gè)強(qiáng)大功能,允許您根據(jù)其他輸入值或應(yīng)用程序狀態(tài)應(yīng)用條件驗(yàn)證規(guī)則。
現(xiàn)在有一個(gè)包含三個(gè)字段的User
類的情況下:firstName
、lastName
和email
。我們要確保如果 email
字段為空,則 firstName
或 lastName
字段必須非空。否則,所有三個(gè)字段都應(yīng)該正常驗(yàn)證。
為此,我們將定義兩個(gè)驗(yàn)證組:EmailNotEmpty
和 Default
。EmailNotEmpty
組將包含當(dāng) email
字段不為空時(shí)的驗(yàn)證規(guī)則,而 Default
組將包含所有三個(gè)字段的正常驗(yàn)證規(guī)則。
- 創(chuàng)建帶有驗(yàn)證組的
User
類
public class User {
@NotBlank(groups = Default.class)
private String firstName;
@NotBlank(groups = Default.class)
private String lastName;
@Email(groups = EmailNotEmpty.class)
private String email;
// getters and setters omitted for brevity
public interface EmailNotEmpty {}
public interface Default {}
}
- 請(qǐng)注意,我們?cè)?code>User類中定義了兩個(gè)接口,
EmailNotEmpty
和Default
。這些將作為我們的驗(yàn)證組。
- 接下來,我們更新
Controller
使用這些驗(yàn)證組
@RestController
@RequestMapping("/users")
@Validated
public class UserController {
public ResponseEntity<String> createUser(
@Validated({org.example.model.ex6.User.EmailNotEmpty.class}) @RequestBody User userWithEmail,
@Validated({User.Default.class}) @RequestBody User userWithoutEmail)
{
// Create the user and return a success response
}
}
- 我們已將
@Validated
注釋添加到我們的控制器,表明我們想要使用驗(yàn)證組。我們還更新了createUser
方法,將兩個(gè)User
對(duì)象作為輸入,一個(gè)在email
字段不為空時(shí)使用,另一個(gè)在它為空時(shí)使用。 @Validated
注釋用于指定將哪個(gè)驗(yàn)證組應(yīng)用于每個(gè)User
對(duì)象。對(duì)于userWithEmail
參數(shù),我們指定了EmailNotEmpty
組,而對(duì)于userWithoutEmail
參數(shù),我們指定了Default
組。
- 進(jìn)行這些更改后,現(xiàn)在將根據(jù)“電子郵件”字段是否為空對(duì)“用戶”類進(jìn)行不同的驗(yàn)證。如果為空,則
firstName
或lastName
字段必須非空。否則,所有三個(gè)字段都將正常驗(yàn)證。
7 對(duì)復(fù)雜邏輯使用跨域驗(yàn)證
如果需要驗(yàn)證跨多個(gè)字段的復(fù)雜輸入規(guī)則,可以使用跨字段驗(yàn)證來保持驗(yàn)證邏輯的組織性和可維護(hù)性。跨字段驗(yàn)證可確保所有輸入值均有效且彼此一致,從而防止出現(xiàn)意外行為。
假設(shè)我們有一個(gè)表單,用戶可以在其中輸入任務(wù)的開始日期和結(jié)束日期,并且我們希望確保結(jié)束日期不早于開始日期。我們可以使用跨域驗(yàn)證來實(shí)現(xiàn)這一點(diǎn)。
- 首先,我們定義一個(gè)自定義驗(yàn)證注解
EndDateAfterStartDate
:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = EndDateAfterStartDateValidator.class)
public @interface EndDateAfterStartDate {
String message() default "End date must be after start date";
Class?[] groups() default {};
Class? extends Payload[] payload() default {};
}
- 然后,我們創(chuàng)建驗(yàn)證器
EndDateAfterStartDateValidator
:
public class EndDateAfterStartDateValidator implements ConstraintValidator<EndDateAfterStartDate, TaskForm> {
@Override
public boolean isValid(TaskForm taskForm, ConstraintValidatorContext context) {
if (taskForm.getStartDate() == null || taskForm.getEndDate() == null) {
return true;
}
return taskForm.getEndDate().isAfter(taskForm.getStartDate());
}
}
- 最后,我們將
EndDateAfterStartDate
注釋應(yīng)用于我們的表單對(duì)象TaskForm
:
@EndDateAfterStartDate
public class TaskForm {
@NotNull
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate startDate;
@NotNull
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate endDate;
}
現(xiàn)在,當(dāng)用戶提交表單時(shí),驗(yàn)證框架將自動(dòng)檢查結(jié)束日期是否晚于開始日期,如果不是,則提供有意義的錯(cuò)誤消息。
8 對(duì)驗(yàn)證錯(cuò)誤使用異常處理
可以使用異常處理ExceptionHandler
來統(tǒng)一捕獲和處理驗(yàn)證錯(cuò)誤。
以下是如何在 Spring Boot 中使用異常處理來處理驗(yàn)證錯(cuò)誤的示例:
@RestControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
HttpHeaders headers, HttpStatus status,
WebRequest request) {
Map<String, Object> body = new LinkedHashMap<>();
body.put("timestamp", LocalDateTime.now());
body.put("status", status.value());
// Get all errors
List<String> errors = ex.getBindingResult()
.getFieldErrors()
.stream()
.map(x -> x.getDefaultMessage())
.collect(Collectors.toList());
body.put("errors", errors);
return new ResponseEntity<>(body, headers, status);
}
}
在這里,我們創(chuàng)建了一個(gè)用 @RestControllerAdvice
注解的 RestExceptionHandler
類來處理我們的 REST API 拋出的異常。然后我們創(chuàng)建一個(gè)用@ExceptionHandler
注解的方法來處理在驗(yàn)證失敗時(shí)拋出的 MethodArgumentNotValidException
。
在處理程序方法中,我們創(chuàng)建了一個(gè) Map
對(duì)象來保存錯(cuò)誤響應(yīng)的詳細(xì)信息,包括時(shí)間戳、HTTP 狀態(tài)代碼和錯(cuò)誤消息列表。我們使用 MethodArgumentNotValidException
對(duì)象的 getBindingResult()
方法獲取所有驗(yàn)證錯(cuò)誤并將它們添加到錯(cuò)誤消息列表中。
最后,我們返回一個(gè)包含錯(cuò)誤響應(yīng)詳細(xì)信息的ResponseEntity
對(duì)象,包括作為響應(yīng)主體的錯(cuò)誤消息列表、HTTP 標(biāo)頭和 HTTP 狀態(tài)代碼。
有了這個(gè)異常處理代碼,我們的 REST API 拋出的任何驗(yàn)證錯(cuò)誤都將被捕獲并以結(jié)構(gòu)化和有意義的格式返回給用戶,從而更容易理解和解決問題。
9 測(cè)試你的驗(yàn)證邏輯
需要為你的驗(yàn)證邏輯編寫單元測(cè)試,以幫助確保它正常工作。
@DataJpaTest
public class UserValidationTest {
@Autowired
private TestEntityManager entityManager;
@Autowired
private Validator validator;
@Test
public void testValidation() {
User user = new User();
user.setFirstName("John");
user.setLastName("Doe");
user.setEmail("invalid email");
Set
我們使用 JUnit 5 編寫一個(gè)測(cè)試來驗(yàn)證具有無效電子郵件地址的“用戶”對(duì)象。然后我們使用 Validator
接口來驗(yàn)證 User
對(duì)象并檢查是否返回了預(yù)期的驗(yàn)證錯(cuò)誤。
10 考慮客戶端驗(yàn)證
客戶端驗(yàn)證可以通過向用戶提供即時(shí)反饋并減少對(duì)服務(wù)器的請(qǐng)求數(shù)量來改善用戶體驗(yàn)。但是,不應(yīng)依賴它作為驗(yàn)證輸入的唯一方法。客戶端驗(yàn)證很容易被繞過或操縱,因此必須在服務(wù)器端驗(yàn)證輸入,以確保安全性和數(shù)據(jù)完整性。
總結(jié)
有效的驗(yàn)證對(duì)于任何 Web 應(yīng)用程序的穩(wěn)定性和安全性都是必不可少的。Spring Boot 提供了一套工具和庫來簡(jiǎn)化驗(yàn)證邏輯并使其更易于維護(hù)。通過遵循本文中討論的最佳實(shí)踐,您可以確保您的驗(yàn)證組件有效并提供出色的用戶體驗(yàn)。
-
應(yīng)用程序
+關(guān)注
關(guān)注
38文章
3292瀏覽量
57920 -
spring
+關(guān)注
關(guān)注
0文章
340瀏覽量
14391 -
Boot
+關(guān)注
關(guān)注
0文章
150瀏覽量
35946 -
SpringBoot
+關(guān)注
關(guān)注
0文章
174瀏覽量
201
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
springboot集成mqtt
SpringBoot應(yīng)用啟動(dòng)運(yùn)行run方法
怎樣去設(shè)計(jì)一個(gè)基于springboot+freemark+jpa+MySQL的在線電影訂票系統(tǒng)
如何使用springboot+vue搭建個(gè)人網(wǎng)站2
![如何使用<b class='flag-5'>springboot</b>+vue搭建個(gè)人網(wǎng)站<b class='flag-5'>2</b>](https://file.elecfans.com/web2/M00/91/33/pYYBAGPrPgSAFKSQAAO6rCRIWIY046.jpg)
什么是 SpringBoot?
![什么是 <b class='flag-5'>SpringBoot</b>?](https://file1.elecfans.com/web2/M00/81/FF/wKgZomQvjQKARND_AADW0ILCMHE105.jpg)
SpringBoot常用注解及使用方法2
SpringBoot的核心注解2
![<b class='flag-5'>SpringBoot</b>的核心注解<b class='flag-5'>2</b>](https://file1.elecfans.com/web2/M00/81/FF/wKgaomQvuKaAJR8sAACgyrexpKI904.jpg)
評(píng)論