统一结果响应
为了与前端进行数据交互时,能有一个统一的数据结构,一般我们都需要一个统一响应结果类
以下直接上代码,粘贴可用
package com.kjyfx.response; import Java.io.Serializable; /** * 微信公众号:云说Java、Java栈记 * @Created by 墨云 * @Description 统一响应数据 * @Date 2020/8/29 12:33 */ public class BaseResponse<T> implements Serializable { private static final long serialVersionUID = 3997124446365032582L; /** * 返回消息 */ private String message; /** * 返回对象 */ private T data; /** * 是否成功 */ private Boolean state; /** * 自定义错误码 */ private Integer code; /** * 错误,系统异常 * * @return result */ public static BaseResponse renderError() { BaseResponse response = new BaseResponse(); response.setState(Boolean.FALSE); response.setCode(500); return response; } /** * 错误数据(带消息) * * @param msg 需要返回的消息 * @return result */ public static BaseResponse renderError(String msg) { BaseResponse response = BaseResponse.renderError(); response.setMessage(msg); return response; } /** * 错误数据(带消息) * * @param msg 需要返回的消息 * @return result */ public static BaseResponse renderError(String msg, Integer code) { BaseResponse response = BaseResponse.renderError(); response.setMessage(msg); response.setCode(code); return response; } /** * 成功数据 * * @return result */ public static BaseResponse renderSuccess() { BaseResponse response = new BaseResponse(); response.setState(Boolean.TRUE); response.setCode(200); return response; } /** * 成功数据(带信息) * * @param msg 需要返回的信息 * @return result */ public static BaseResponse renderSuccess(String msg) { BaseResponse response = BaseResponse.renderSuccess(); response.setMessage(msg); return response; } /** * 成功数据(带数据) * * @param obj 需要返回的对象 * @return result */ public static BaseResponse renderSuccess(Object obj) { BaseResponse response = BaseResponse.renderSuccess(); response.setData(obj); return response; } /** * 成功数据(带数据,带信息) * * @param msg 需要返回的信息 * @param obj 需要返回的对象 * @return result */ public static BaseResponse renderSuccess(String msg, Object obj) { BaseResponse response = BaseResponse.renderSuccess(); response.setMessage(msg); response.setData(obj); return response; } /** * 失败数据 * * @return result */ public static BaseResponse renderFail() { BaseResponse response = new BaseResponse(); response.setState(Boolean.FALSE); response.setCode(500); return response; } /** * 失败数据(带消息) * * @param msg 需要返回的消息 * @return result */ public static BaseResponse renderFail(String msg) { BaseResponse response = BaseResponse.renderFail(); response.setMessage(msg); return response; } /** * 失败数据(带消息) * * @param msg 需要返回的消息 * @param code 自定义错误码 * @return result */ public static BaseResponse renderFail(String msg, Integer code) { BaseResponse response = BaseResponse.renderFail(); response.setMessage(msg); response.setCode(code); return response; } /** * 失败数据(带数据,带信息) * * @param msg 需要返回的信息 * @param obj 需要返回的对象 * @return result */ public static BaseResponse renderFail(String msg, Object obj) { BaseResponse response = BaseResponse.renderFail(); response.setMessage(msg); response.setData(obj); return response; } /** * 失败数据(带数据,带信息) * * @param msg 需要返回的信息 * @param obj 需要返回的对象 * @param code 自定义错误码 * @return result */ public static BaseResponse renderFail(String msg, Object obj, Integer code) { BaseResponse response = BaseResponse.renderFail(); response.setMessage(msg); response.setData(obj); response.setCode(code); return response; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public T getData() { return data; } public void setData(T data) { this.data = data; } public Boolean getState() { return state; } public void setState(Boolean state) { this.state = state; } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } }
接下来我们就可以用统一结果响应类进行数据交互
@RequestMapping("/getUser") public BaseResponse getUser(){ SysUser sysUser = new SysUser() .setId(1000L) .setAccount("moyun") .setUserName("墨云"); return BaseResponse.renderSuccess("成功!",sysUser); }
访问接口:http://localhost:9000/base/sysUser/getUser,得到如下数据,统一的数据结构,也方便前端请求接口之后的统一响应拦截处理
从code状态码跟state查看数据信息就很清晰
{ "message": "成功!", "data": { "id": 1000, "account": "moyun", "password": null, "userName": "墨云", "pythontel": null, "status": null, "createUser": null, "createType": null, "createTime": null, "updateTime": null }, "state": true, "code": 200 }
一般在实际项目中,见得最多的就是BaseResponse和jsonResult这两个统一响应结果类,命名看个人习惯,内部结构都大同小异
成功结果
,常用以下四个静态方法
BaseResponse.renderSuccess(); BaseResponse.renderSuccess(String msg); BaseResponse.renderSuccess(Object obj); BaseResponse.renderSuccess(String msg, Object obj);
业务级错误结果
,常用以下五个静态方法
BaseResponse.renderFail(); BaseResponse.renderFail(String msg); BaseResponse.renderFail(String msg, Integer code); BaseResponse.renderFail(String msg, Object obj); BaseResponse.renderFail(String msg, Object obj, Integer code);
系统级错误结果
,可用以下三个静态方法(不常用,只是与业务级错误进行区分)
BaseResponse.renderError(); BaseResponse renderError(String msg); BaseResponse renderError(String msg, Integer code);
全局异常处理
全局异常处理类主要用于,当服务器出现异常时,将捕获到的异常信息以json数据返给前端。
先自定义一个异常类,继承RuntimeException
package com.kjyfx.exception; /** * 微信公众号:云说Java、Java栈记 * @author moyun * @date 2020/12/01 */ public class MsgException extends RuntimeException{ public MsgException() { } public MsgException(String message) { SnxxuR super(message); } public MsgException(String message, Throwable cause) { super(message, cause); } public MsgException(Throwable cause) { super(cause); } protected MsgException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); } }
再定义一个全局异常处理器,可以自行添加其他异常处理
package com.kjyfx.exception; import com.kjyfx.response.BaseResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.sql.SQLException; /** * 微信公众号:云说Java、Java栈记 * @author moyun * @date 2020/12/01 */ @RestControllerAdvice public class GlobalExceptionHandler { private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); @ExceptionHandler(value = MsgException.class) public BaseResponse msgExceptionHandler(HttpServletRequest request, HttpServletResponse response, Exception e) { logger.error(e.getMessage()); e.printStackTrace(); return BaseResponse.renderFail(e.getMessage()); } @ExceptionHandler(value = NullPointerException.class) public BaseResponse nullExceptionHandler(HttpServletRequest request, HttpServletResponse response, Exception e) { logger.error(e.getMessage()); e.printStackTrace(); return BaseResponse.renderFail("出现了空指针!"); } @ExceptionHandler(value = org.springframework.web.servlet.NoHandlerFoundException.class) public BaseResponse noHandlerFoundExceptionHandler(HttpServletRequest request, HttpServletResponse response, Exception e) { logger.error(e.getMessage()); return BaseResponse.renderFail("404,未找到请求地址"); } @ExceptionHandler(value = IllegalArgumentException.class) public BaseResponse illegalArgumentExceptionHandler(HttpServletRequest request, HttpServletResponse response, Exception e) { logger.error(e.getMessage()); e.printStackTrace(); return BajsseResponse.renderFail(e.getMessage()); } @ExceptionHandler(value = SQLException.class) public BaseResponse sQLExceptionExceptionHandler(HttpServletRequest request, HttpServletResponse response, Exception e) { logger.error(e.getMessage()); return BaseResponse.renderFail("数据库查询异常"); } }
当我们访问以下接口时,sysUser对象恒为空,此时就会抛出一个MsgException
@RequestMapping("/getUser") public SysUser getUser(){ SysUser sysUser = null; if(null == sysUser){ throw new MsgException("服务器报了一个错"); } return new SysUser(); }
此时我们访问接口:http://localhost:9000/base/sysUser/getUser
就会得到以下数据,便是全局异常处理器为我们处理的
{ "message": "服务器报了一个错", "data": null, "state": false, "code": 500 }
全局异常处理器最主要的两个注解,
@RestControllerAdvice
:作用于类上,相当于Controller的切面,对异常统一处理,定制,之后再以json格式返给前端
@ExceptionHandler
:统一处理某一类异常,作用于方法上,捕捉到相应异常后,会执行其修饰的方法
例如:执行到第四行的时候肯定会报空指针异常
@RequestMapping("/getUser") public SysUser getUser(){ SysUser sysUser = null; sysUser.setId(1000L); return new SysUser(); }
访问接口后,将会得到全局异常处理器返回的数据
{ "message": "出现了空指针!", "data": null, "state": false, "code": 500 }
JSON数据处理
对于以上得到的json数据,如果对象属性没有赋值,则会显示为null值,对前端来说这是很不友好的,一不小心整个页面就会瘫痪,接下来我们用SpringBoot自带的Jackson对数据进行转换,将null处理为""空串
创建JacksonConfig配置类:
package com.kjyfx.config; import com.fasterXML.jackson.core.JsonGenerator; import com.fasterxml.jandroidackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializerProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import java.io.IOException; /** * @Description TODO * 微信公众号:云说Java、Java栈记 * @Date 2020/12/10 22:20 * @Created by moyun */ @Configuration public class JacksonConfig { @Bean @Primary @ConditionalOnMissingBean(ObjectMapper.class) public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) { ObjectMapper objectMapper = builder.createXmlMapper(false).build(); SerializerProvider serializerProvider = objectMapper.getSerializerProvider(); serializerProvider.setNullValueSerializer(new JsonSerializer<Object>() { @Override public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException { jsonGenerator.writeString(""); } }); return objectMapper; } }
@Primary:
当Spring容器扫描到某个接口的多个 bean 时,如果某个bean上加了@Primary 注解 ,则这个bean会被优先选用
@ConditionalOnMissingBean:
它是修饰bean的一个注解,主要实现的是,当你的bean被注册之后,如果而注册相同javascript类型的bean,就不会成功,
它会保证你的bean只有一个,即你的实例只有一个
之后我们重启项目,再访问接口,会得到以下数据,null成功被转成了""空串
{ "message": "成功!", "data": { "id": 1000, "account": "moyun", "password": "", "userName": "墨云", "tel": "", "status": "", "createUser": "", "createType": "", "createTime": "", "updateTime": "" }, "state": true, "code": 200 }
到此这篇关于SpringBoot中常用数据处理方式详解的文章就介绍到这了,更多相关SpringBoot数据处理内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论