本来想加一个Jackson的配置类修改ObjectMapper实现把null转空字符串或空数组,但是加上之后发现没效果,找不到问题在哪里,不知道是不是我使用@RestControllerAdvice全局返回处理类的问题,所以就自己写了一个工具类方法处理,就在全局返回处理类里面调用
找到配置不生效的问题在哪里了,见springboot中添加Jackson配置类不生效
全局返回处理类是用kotlin写的,用来封装统一响应实体和处理全局异常的,用java也是一样的,语法换成java就行。当然,这不是这篇的博文重点,重点是处理null的方法
package com.gt.gxjhpt.configuration import cn.dev33.satoken.exception.NotLoginException import cn.dev33.satoken.exception.NotPermissionException import cn.dev33.satoken.exception.NotRoleException import cn.hutool.json.JSONUtil import com.gt.gxjhpt.entity.RestfulResp import com.gt.gxjhpt.enumeration.RespCodeEnum import com.gt.gxjhpt.exception.MyException import com.gt.gxjhpt.utils.MyUtils import org.springframework.core.MethodParameter import org.springframework.http.HttpStatus import org.springframework.http.MediaType import org.springframework.http.converter.HttpMessageConverter import org.springframework.http.server.ServerHttpRequest import org.springframework.http.server.ServerHttpResponse import org.springframework.http.server.ServletServerHttpResponse import org.springframework.validation.BindException import org.springframework.web.bind.MethodArgumentNotValidException import org.springframework.web.bind.annotation.ExceptionHandler import org.springframework.web.bind.annotation.ResponseStatus import org.springframework.web.bind.annotation.RestControllerAdvice import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice import javax.validation.ConstraintViolationException @RestControllerAdvice class GlobalResponseBodyAdvice : ResponseBodyAdvice<Any> { override fun supports(returnType: MethodParameter, converterType: Class<out HttpMessageConverter<*>>): Boolean { return true } override fun beforeBodyWrite( body: Any?, returnType: MethodParameter, selectedContentType: MediaType, selectedConverterType: Class<out HttpMessageConverter<*>>, request: ServerHttpRequest, response: ServerHttpResponse ): Any? { return when (body) { is RestfulResp<*> -> body is String -> JSONUtil.toJsonStr(RestfulResp<Any>().success(body)) null -> RestfulResp<Any>().success() else -> { val httpResponse = response as ServletServerHttpResponse if (httpResponse.servletResponse.status.equals(200)) { // 设置null值为空字符串或空数组 MyUtils.setNullValue(body) return RestfulResp<Any>().success(body) } else { return body } } } } //其他参数异常 @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(value = [BindException::class]) fun handleBindException(): RestfulResp<*>? { return RestfulResp<Any>().enumResp(RespCodeEnum.PARAM_ERR) } //parameter异常 //为了安全,就不将报错信息返回到前端,只返回粗略信息 @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(value = [ConstraintViolationException::class]) fun handleValidationException(): RestfulResp<*>? { return RestfulResp<Any>().enumResp(RespCodeEnum.PARAM_ERR) } //bean异常 //为了安全,就不将报错信息返回到前端,只返回粗略信息 @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(value = [MethodArgumentNotValidException::class]) fun handleMethodArgumentNotValidException(ex: MethodArgumentNotValidException?): RestfulResp<*>? { return RestfulResp<Any>().enumResp(RespCodeEnum.PARAM_ERR) } //我的自定义异常 @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler( MyException::class ) fun myException(e: MyException): RestfulResp<*>? { e.printStackTrace() return if (e.msg != null) { RestfulResp<Any>().error(e.msg, e.code) } else if (e.respCodeEnum != null) { RestfulResp<Any>().enumResp(e.respCodeEnum) } else { RestfulResp<Any>().unknown() } } //运行时异常 @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ExceptionHandler( RuntimeException::class ) fun runtimeException(e: RuntimeException): RestfulResp<*>? { e.printStackTrace() return RestfulResp<Any>().unknown(e.message) } //空指针异常 @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ExceptionHandler( NullPointerException::class ) fun nullPointerException(e: NullPointerException): RestfulResp<*>? { e.printStackTrace() return RestfulResp<Any>().unknown("空指针-->>" + e.stackTrace[0].toString()) } //未知异常 @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ExceptionHandler( Exception::class ) fun exception(e: Exception): RestfulResp<*>? { e.printStackTrace() return RestfulResp<Any>().unknown(e.message) } // 未提供token @ResponseStatus(HttpStatus.UNAUTHORIZED) @ExceptionHandler(value = [NotLoginException::class]) fun exception(e: NotLoginException): RestfulResp<*>? { e.printStackTrace() return RestfulResp<Any>().unknown(e.message) } // 无角色 @ResponseStatus(HttpStatus.FORBIDDEN) @ExceptionHandler( NotRoleException::class ) fun exception(e: NotRoleException): RestfulResp<*>? { e.printStackTrace() return RestfulResp<Any>().unknown(e.message) } // 无权限 @ResponseStatus(HttpStatus.FORBIDDEN) @ExceptionHandler( NotPermissionException::class ) fun exception(e: NotPermissionException): RestfulResp<*>? { e.printStackTrace() return RestfulResp<Any>().unknown(e.message) } }
处理null的方法,不需要继续递归的类型,要写在第一个else if条件里面,工具类使用hutool
public static void setNullValue(Object body) throws IllegalAccessException, InstantiationException { Class<?> aClass = body.getClass(); if (Collection.class.isAssignableFrom(aClass)) { for (Object it : Convert.toList(body)) { MyUtils.setNullValue(it); } } else if (String.class.isAssignableFrom(aClass) || NumberUtil.isNumber(body.toString()) || BooleanUtil.isBoolean(aClass) || CharUtil.isChar(body) || Date.class.isAssignableFrom(aClass)) { } else if (Map.class.isAssignableFrom(aClass)) { Map<String, Object> objectMap = Convert.toMap(String.class, Object.class, body); objectMap.forEach((k, v) -> { try { if (v == null) { v = ""; } else { MyUtils.setNullValue(v); } } catch (IllegalAccessException | InstantiationException e) { e.printStackTrace(); } objectMap.put(k, v); }); } else { // 自定义响应对象 List<Field> fields = CollUtil.toList(aClass.getDeclaredFields()); // 父类属性 Class<?> superclass = aClass.getSuperclass(); while (superclass != null && superclass != Object.class) { fields.addAll(CollUtil.toList(superclass.getDeclaredFields())); superclass = superclass.getSuperclass(); } for (Field field : fields) { // 取消权限检查 field.setAccessible(true); Object value = field.get(body); if (value == null) { if (Collection.class.isAssignableFrom(field.getType())) { field.set(body, new ArrayList<>()); } else if (String.class.isAssignableFrom(field.getType())) { field.set(body, ""); } } else { MyUtils.setNullValue(value); } } } }