Spring Boot优雅封装校验参数(Kotlin版本)

1,228 阅读2分钟

这是我参与更文挑战的第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中获取传值过来并返回相应的错误内容。

image.png

遇到的难点

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

@ControllerAdvice @valid实现拦截错误信息响应json给前端 参数效验