参数校验与国际化:提高代码稳定性和可维护性的重要方法
在我們日常的工作中,參數校驗是一項非常重要的任務。它能夠幫助我們確保代碼的穩定性和可靠性,避免因為參數錯誤而導致的意外情況發生。參數校驗通常包括對輸入參數的合法性、格式的檢查等。而為了提高代碼的可維護性和可重用性,我們可以使用一些常見的參數校驗方法。
另外,國際化也是一項非常重要的功能,尤其是在跨國項目中。通過國際化的配置,我們可以根據用戶的語言環境,自動切換顯示的語言,提供更好的用戶體驗。在參數校驗中,我們也可以使用國際化配置來返回相應的提示信息,使得提示信息能夠適應不同的語言環境。
- RequestParam參數校驗
- NotEmpty等注解參數校驗
- 實體類增加參數校驗
- CustomException,自定義異常對參數異常進行國際化定制
- NotEmptyField,自定義注解實現對參數異常進行國際化定制
好的,讓我們一步一步來介紹參數校驗的方法。除了上述提到的方法,如果還有一些其他的優秀方法可以用來進行參數校驗,也可以提醒我一下!
RequestParam參數校驗
RequestParam本身就有對參數進行的基礎校驗,比如required表示是否參數必填??梢酝ㄟ^在方法參數上使用@RequestParam注解來實現參數校驗。以下是示例代碼:
@GetMapping("/hello-not-required")
public String sayHelloByNotRequired(@RequestParam(required = false, name = "who") String who) {
if (StrUtil.isBlank(who)) {
who = "World";
}
return StrUtil.format("Hello, {}!", who);
}
如果不傳遞參數,也不會有任何問題,這里不做演示就可以了,非常簡單。
NotEmpty等注解參數校驗
默認message
然而,雖然RequestParam只能指示參數是否被攜帶,但它并不負責檢驗參數值是否為空。因此,我們可以通過與NotEmpty注解結合使用來進行判斷。
@GetMapping("/hello-required")
public String sayHelloByRequired(@RequestParam @NotEmpty String who) {
return StrUtil.format("Hello, {}!", who);
}
當訪問http://localhost:8080/demo/hello-required?who=時,我們的程序是報錯的,因為who字段不能為空
自定義message
如果你仔細閱讀了NotEmpty注解的文檔,你會發現它允許自定義報錯提示信息。因此,我們可以嘗試自定義提示信息,以滿足我們的需求。
@GetMapping("/hello-required-message")
public String sayHelloByRequiredWithMessage(@RequestParam @NotEmpty(message = "who must be not null") String who) {
return StrUtil.format("Hello, {}!", who);
}
我再來為你演示一下,除了NotEmpty注解,還有許多其他已經內置的注解可供使用。我就不一一列舉了,你可以自行探索更多的注解。
實體類增加參數校驗
除了上面提到的簡單校驗方式,我們在實際開發中更常使用的是通過JSON傳遞參數,并使用實體類接收參數。下面是相關代碼示例:
@PostMapping("/hello-required-message-object")
public String sayHelloByRequiredWithMessageForObject(@RequestBody @Valid MyTest test) {
return StrUtil.format("Hello, {}!", test);
}
public class MyTest {
@NotEmpty(message = "NotEmpty.message")
private String test;
public String getTest() {
return test;
}
public void setTest(String test) {
this.test = test;
}
}
加長優化語句:為了方便演示,我特意更換了一些提示信息,以便更清晰地展示給大家。接下來,我們再仔細觀察一下。
自定義異常
其實在工作中,校驗參數是一個常見的任務。我們通常會使用代碼進行各種校驗,因為我們對參數的要求遠遠超出了簡單的非空檢查。除了非空檢查,我們還需要進行其他等值校驗等。因此,如果在代碼中進行校驗,我們可以選擇拋出異常或直接返回錯誤信息。舉個例子,我可以使用自定義異常來說明這一點:
@PostMapping("/hello-required-message-i18n")
public String sayHelloByRequiredWithMessageFori18n() {
throw new CustomException("notBlank.message");
}
代碼經過優化,已經去除了多余的邏輯,直接通過拋出異常來處理。讓我來演示一下。
雖然在出錯時會有報錯信息返回,但是這些錯誤信息并不完全符合業務返回數據的格式。為了解決這個問題,我們需要定義一個全局異常處理類來統一處理異常情況。
@RestControllerAdvice
public class GlobalExceptionHandler {
@Autowired
private MessageSource messageSource;
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ResponseEntity<ErrorResponse> handleCustomException(CustomException ex, Locale locale) {
String errorMessage = messageSource.getMessage(ex.getMessage(), null, locale);
ErrorResponse errorResponse = new ErrorResponse(500, errorMessage);
return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
ErrorResponse是我單獨定義的錯誤描述類,我就不寫了,因為每個項目都會有自己的返回類。
國際化信息
讓我們進一步探討一下關于國際化信息的定制。首先,為了實現這一目標,你需要在應用程序中進行相關的配置,具體來說,就是在application.yaml文件中進行必要的設置。
server:
port: 8080
servlet:
context-path: /demo
spring:
messages:
baseName: i18n/messages
encoding: UTF-8
mvc:
locale: zh_CN
請注意,baseName在這里表示路徑,而最后的messages并不代表包的含義,而是文件的前綴。如果無法找到messages_zh_CN文件,則會嘗試查找messages_zh文件,如果還找不到,則會查找messages文件。因此,請不要再創建一個名為messages的包。
當所有準備工作完成后,我們可以檢查演示結果是否已經改變了字段信息。
自定義注解
現在基本上已經存在了全局異常處理機制,不過我們還需要進一步優化。現在讓我們來討論一下自定義注解的使用。首先,我們注意到錯誤信息無法給出具體的字段值。顯然,我們不能每次都手動寫上每個字段的名稱并提示不能為空。為了解決這個問題,我們需要自定義一個注解來實現自動化的校驗。
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NotEmptyField {
String message() default "";
}
有了注解后,下一步就是通過切面來獲取并處理這個注解。接下來,我們來編寫相應的代碼來實現這個功能:
@Aspect
@Component
public class NotEmptyFieldAspect {
@Autowired
private MessageSource messageSource;
@Around("within(com.xkcoding..*)")
public Object validateNotEmptyField(ProceedingJoinPoint joinPoint) throws Throwable {
// 獲取目標方法的參數列表
Object[] args = joinPoint.getArgs();
// 遍歷參數列表
for (Object arg : args) {
// 獲取參數實體類的屬性
Field[] fields = arg.getClass().getDeclaredFields();
// 遍歷屬性列表
for (Field field : fields) {
// 判斷屬性是否被 @NotEmptyField 注解修飾
if (field.isAnnotationPresent(NotEmptyField.class)) {
// 獲取注解信息
NotEmptyField annotation = field.getAnnotation(NotEmptyField.class);
field.setAccessible(true);
// TODO: 進一步處理邏輯
if (ObjectUtil.isEmpty(field.get(arg))) {
String message = messageSource.getMessage(annotation.message(), null, Locale.getDefault());
throw new CustomException(field.getName() + message);
}
// 輸出屬性和注解信息
System.out.println("屬性:" + field.getName());
System.out.println("注解信息:" + annotation.message());
System.out.println("值:" + field.get(arg));
}
}
}
// 調用目標方法
Object result = joinPoint.proceed();
return result;
}
}
我只是簡單地寫了一下實現邏輯,并沒有進行優化操作,所以以上代碼僅供參考?,F在讓我們來看一下外層代碼:
@PostMapping("/hello-required-message-i18n-object")
public String sayHelloByRequiredWithMessageFori18nObject(@RequestBody @Valid MyTestForAspect myTestForAspect) {
return "";
}
當我們完成所有的準備工作之后,讓我們來觀察一下演示情況:
總結
在我們的工作中,參數校驗是一項不可或缺的重要任務。因此,本文只是初步探討了可以進行優化的方面,而并未詳細闡述如何完美地進行優化。如果我遺漏了一些解決方案,也歡迎大家提供寶貴的建議和提醒。我的目的只是提供一些思路和引發討論,以期能夠共同進步。
總結
以上是生活随笔為你收集整理的参数校验与国际化:提高代码稳定性和可维护性的重要方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一分利息是百分之几,有以下两种情形
- 下一篇: C++ Qt开发:ProgressBar