这是我参与更文挑战的第1天,活动详情查看: 更文挑战
由于之前的使用的Django没有规范化。返回给前端校验信息比较乱,而现在有机会重构,故想重新统一规范化错误信息。
我们先定一个数据类
// Response.kt
// 封装接口的统一返回实体类
data class Response<T>(
val code: Int = 200,
val data: T? = null,
val msg: String? = "请求成功",
val err: HashMap<String, String>? = null
)
封装一个校验的异常类
接着我们使用@ControllerAdvice注解和@ValidException注解
// ValidParamException.kt
package com.demo.utils
import org.springframework.stereotype.Controller
import org.springframework.validation.BindingResult
import org.springframework.validation.FieldError
import org.springframework.web.bind.MethodArgumentNotValidException
import org.springframework.web.bind.annotation.ControllerAdvice
import org.springframework.web.bind.annotation.ExceptionHandler
import org.springframework.web.bind.annotation.ResponseBody
import java.util.HashMap
/**
* @author watson haw
* @date 2021/6/1 8:28 下午
*/
@Controller
@ControllerAdvice
class ValidParamException {
@ExceptionHandler(value = [(MethodArgumentNotValidException::class)])
@ResponseBody
fun handleMethodArgumentNotValidException(ex: MethodArgumentNotValidException): Response<HashMap<String, String>> {
val bindingResult: BindingResult = ex.bindingResult
val errors: List<FieldError> = bindingResult.fieldErrors
val errorMessage = HashMap<String, String>(errors.size)
for (error: FieldError in errors) {
// 这里需要判空,因为defaultMessage不一定有返回值
// 只有当有返回值的时候才执行后面的迭代操作
error.defaultMessage?.let { errorMessage.put(error.field, it) };
}
// 这里将会使用上面定义好的数据了Result
// 但是需要注意这里的code 400并不会改变返回给前端的status,只是用于状态判断
return Response(400, err = errorMessage)
}
}
返回的结果如下图,这样前端就可以当code为400时候在err中获取传值过来并返回相应的错误内容。
遇到的难点
1.ExceptionHandler用法 Java中直接反射即可
@ExceptionHandler(MethodArgumentNotValidException.class)
但是Kotlin中我们需要把具体反射的类作为一个value放在集合中
@ExceptionHandler(value = [(MethodArgumentNotValidException::class)])
2.HashMap的用法 Java中可以直接使用HashMap<String, String>
但是Kotlin中是需要调用原生的Java集合才行,并不是很Kotlin 这里应该可以换为mapOf或者hashMapOf,后期想办法再处理一下。
参考文章
Kotlin - Spring REST - ControllerAdvice with ExceptionHandler won't get invoked