Spring Boot常用数据处理方式

统一结果响应

为了与前端进行数据交互时,能有一个统一的数据结构,一般我们都需要一个统一响应结果类

以下直接上代码,粘贴可用

typescript 复制代码
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;
    }
}

接下来我们就可以用统一结果响应类进行数据交互

java 复制代码
@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查看数据信息就很清晰

json 复制代码
{
    "message": "成功!",
    "data": {
        "id": 1000,
        "account": "moyun",
        "password": null,
        "userName": "墨云",
        "tel": null,
        "status": null,
        "createUser": null,
        "createType": null,
        "createTime": null,
        "updateTime": null
    },
    "state": true,
    "code": 200
}

一般在实际项目中,见得最多的就是BaseResponse和JsonResult这两个统一响应结果类,命名看个人习惯,内部结构都大同小异

成功结果,常用以下四个静态方法

ini 复制代码
BaseResponse.renderSuccess();
BaseResponse.renderSuccess(String msg);
BaseResponse.renderSuccess(Object obj);
BaseResponse.renderSuccess(String msg, Object obj);

业务级错误结果,常用以下五个静态方法

vbnet 复制代码
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);

系统级错误结果,可用以下三个静态方法(不常用,只是与业务级错误进行区分)

scss 复制代码
BaseResponse.renderError();
BaseResponse renderError(String msg);
BaseResponse renderError(String msg, Integer code);

全局异常处理

全局异常处理类主要用于,当服务器出现异常时,将捕获到的异常信息以json数据返给前端。

先自定义一个异常类,继承RuntimeException

java 复制代码
package com.kjyfx.exception;

/**
 * 微信公众号:云说Java、Java栈记
 * @author moyun
 * @date 2020/12/01
 */
public class MsgException extends RuntimeException{
    public MsgException() {
    }

    public MsgException(String message) {
        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);
    }
}

再定义一个全局异常处理器,可以自行添加其他异常处理

kotlin 复制代码
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 BaseResponse.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

java 复制代码
@RequestMapping("/getUser")
public SysUser getUser(){
    SysUser sysUser = null;
    if(null == sysUser){
        throw new MsgException("服务器报了一个错");
    }
    return new SysUser();
}

此时我们访问接口:http://localhost:9000/base/sysUser/getUser

就会得到以下数据,便是全局异常处理器为我们处理的

json 复制代码
{
    "message": "服务器报了一个错",
    "data": null,
    "state": false,
    "code": 500
}

全局异常处理器最主要的两个注解,

@RestControllerAdvice:作用于类上,相当于Controller的切面,对异常统一处理,定制,之后再以json格式返给前端

@ExceptionHandler:统一处理某一类异常,作用于方法上,捕捉到相应异常后,会执行其修饰的方法

例如:执行到第四行的时候肯定会报空指针异常

java 复制代码
@RequestMapping("/getUser")
public SysUser getUser(){
    SysUser sysUser = null;
    sysUser.setId(1000L);
    return new SysUser();
}

访问接口后,将会得到全局异常处理器返回的数据

json 复制代码
{
    "message": "出现了空指针!",
    "data": null,
    "state": false,
    "code": 500
}

JSON数据处理

对于以上得到的json数据,如果对象属性没有赋值,则会显示为null值,对前端来说这是很不友好的,一不小心整个页面就会瘫痪,接下来我们用SpringBoot自带的Jackson对数据进行转换,将null处理为""空串

创建JacksonConfig配置类:

java 复制代码
package com.kjyfx.config;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.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被注册之后,如果而注册相同类型的bean,就不会成功,

它会保证你的bean只有一个,即你的实例只有一个

之后我们重启项目,再访问接口,会得到以下数据,null成功被转成了""空串

json 复制代码
{
    "message": "成功!",
    "data": {
        "id": 1000,
        "account": "moyun",
        "password": "",
        "userName": "墨云",
        "tel": "",
        "status": "",
        "createUser": "",
        "createType": "",
        "createTime": "",
        "updateTime": ""
    },
    "state": true,
    "code": 200
}
相关推荐
wkj00136 分钟前
vue中 js-cookie 用法
前端·javascript·vue.js
熟悉的新风景5 小时前
springboot项目或其他项目使用@Test测试项目接口配置-spring-boot-starter-test
java·spring boot·后端
漠月瑾-西安6 小时前
如何在 React + TypeScript 中实现 JSON 格式化功能
javascript·jst实现json格式化
晴空月明6 小时前
分布式系统高可用性设计 - 监控与日志系统
后端
止观止7 小时前
React响应式组件范式:从类组件到Hooks
javascript·react.js·ecmascript
@大迁世界7 小时前
React 及其生态新闻 — 2025年6月
前端·javascript·react.js·前端框架·ecmascript
songroom7 小时前
【转】Rust: PhantomData,#may_dangle和Drop Check 真真假假
开发语言·后端·rust
LJianK17 小时前
Java和JavaScript的&&和||
java·javascript·python
红尘散仙7 小时前
Rust 终端 UI 开发新玩法:用 Ratatui Kit 轻松打造高颜值 CLI
前端·后端·rust
mldong7 小时前
mldong-goframe:基于 GoFrame + Vben5 的全栈快速开发框架正式开源!
vue.js·后端·go