Spring Boot学习笔记(一)Json数据封装与统一数据返回格式

SpringBoot 专栏收录该内容
1 篇文章 0 订阅

前言

在我们日常开发过程中,接口与接口之间,前后端之间数据的传输都使用 JSON 格式。本文介绍Sping Boot中

一、JSON简介

文章开始之前,我们先简单回顾一下JSON的概念
参考自官方JSON中文说明以及JSON维基百科

(1)名称:

JSON(JavaScript Object Notation,JavaScript对象表示法,读作/ˈdʒeɪsən/)

(2)与XML对比:

JSON是一种轻量级的资料交换语言,而XML是一个完整的标记语言,这使得XML在程序判读上需要比较多的功夫。XML利用标记语言的特性提供了绝佳的延展性(如XPath),在数据存储,扩展及高级检索方面相较JSON更具优势,而JSON则由于比XML更加小巧,以及浏览器的内建快速解析支持,使得其更适用于网络数据传输领域。

(3)语法:

  1. 数据在名称/值对中:json数据是由键值对构成的, 键用引号(单双都行)引起来,也可以不使用引号
  2. 数据由逗号分隔:多个键值对由逗号分隔
  3. 花括号保存对象:使用{}定义json 格式
  4. 方括号保存数组:[ ]
  5. 值的取值类型:
    1. 数字(整数或浮点数)
    2. 字符串(在双引号中)
    3. 逻辑值(true 或 false)
    4. 数组(在方括号中) {“persons”:[{},{}]}
    5. 对象(在花括号中) {“address”:{“province”:“广东”…}}
    6. null

(4)JSON解析器:

常见的解析器:Gson(Google的JSON处理框架),fastjson(阿里巴巴的JSON处理框架),jackson(Spring Boot默认JSON处理框架)

二、Spring Boot默认对JSON的处理

(1)创建Spring Boot工程并在pom.xml加入依赖如下

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
 </dependencies>

这里我们只需关注spring-boot-starter-web 依赖
在IDEA中,对着spring-boot-starter-web依赖按住CTRL+鼠标左键
在这里插入图片描述
可以看到spring-boot-starter-web封装了一个spring-boot-starter-json依赖
在这里插入图片描述
我们再点进去,可以看到jackson的各项依赖已经被封装好
在这里插入图片描述

(2)创建实体类命名为Person.java

public class Person {
    private String name;
    private Integer age;
    private Integer phoneNumber;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(Integer phoneNumber) {
        this.phoneNumber = phoneNumber;
    }
    public Person(String name,Integer age,Integer phoneNumber){
        this.name = name;
        this.age = age;
        this.phoneNumber = phoneNumber;
    }
}

(3)创建Controller类命名为PersonController.java

import com.rex.springbootjson.entity.Person;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController

public class PersonController {
    @RequestMapping("/person")
    public Person getPerson(){
        return new Person("张三",18,123);
    }
    @RequestMapping("/list")
    public List<Person> getPersonList() {
        List<Person> personList = new ArrayList<>();
        Person user1 = new Person("李四",18,123);
        Person user2 = new Person("王五",15,321);
        personList.add(user1);
        personList.add(user2);
        return personList;
    }
    @RequestMapping("/map")
    public Map<String, Object> getPersonMap() {
        Map<String, Object> map = new HashMap<>(3);
        Person person = new Person("王五",24,321);
        map.put("成员信息", person);
        map.put("住址", null);
        map.put("学历", "本科");
        return map;
    }
}

这里我们重点关注@RestController注解
CTRL+鼠标左键点开@RestController注解,可见其封装了@Controller注解。而@RestController与@Controller的主要区别是:
1. @RestController是将json/xml返回到前端页面
2. @Controller是将HTML页面返回到前端页面

而另一个注解@ResponseBody的作用简而言之就是将对象转化为JSON格式
具体详解可以参考@ResponseBody详解
在这里插入图片描述

(4)启动Spring Boot项目

  1. 访问http://localhost:8080/person
    在这里插入图片描述
  2. 访问http://localhost:8080/list,返回List类型的JSON
    在这里插入图片描述

3.访问http://localhost:8080/map ,返回map类型的JSON
在这里插入图片描述

三、 jackson 中对null的处理

由上图,地址一栏出现了null值,实际项目开发中难免会遇到一些 null 值出现,我们转 json 时,是不希望有这些 null 出现的,比如我们期望所有的 null 在转 json 时都变成 “” 这种空字符串,此时我们需要新建一个JSON配置类

  1. 创建JsonConfig.java文件,加入如下代码
import com.fasterxml.jackson.core.JsonGenerator;
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;

@Configuration
public class JsonConfig {
    @Bean
    @Primary
    @ConditionalOnMissingBean(ObjectMapper.class)
    public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
        ObjectMapper objectMapper = builder.createXmlMapper(false).build();
        objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
            @Override
            public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
                jsonGenerator.writeString("");
            }
        });
        return objectMapper;
    }
}

  1. 重启Spring Boot项目,重新访问http://localhost:8080/map
    在这里插入图片描述
    可以看到null值已经被处理

四、统一数据返回格式

1.为什么要做统一数据返回格式

在以前后端分离为主流的开发环境下,前后端开发人员需要通过API交互,但为了前端人员能够快速做逻辑展示与页面交互处理,每一次RESTful请求都应该包含以下几个信息:

名称描述
状态码标识请求成功与否,如[1:成功; -1:失败]
错误码定义明确错误码,更好的应对业务异常;请求成功该值可为空
错误消息与错误码相对应,更具体的描述异常信息
resultBody通常是Bean对象对应的JSON数据,通常为了应对不同返回值类型,将其声明为泛型类型

这里总结下我们常用的状态码以及表示的含义:

code区间类型含义
1**100-199信息 服务器接收到请求,需要请求者继续执行操作
2**200-299成功 请求被成功接收并处理
3**300-399重定向 需要进一步的操作以完成请求
4**400-499客户端错误 请求包含语法错误或无法完成请求
5**500-599服务器错误 服务器在处理的时候发生错误

2.统一的JSON结构的配置

在config文件夹下创建UnifiedReturnConfig文件

package com.rex.springbootjson.config;

import com.rex.springbootjson.entity.CommonResult;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.MethodParameter;
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.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

@EnableWebMvc
@Configuration
public class UnifiedReturnConfig {

    @RestControllerAdvice("com.rex.springbootjson.Controller")
    static class CommonResultResponseAdvice implements ResponseBodyAdvice<Object> {
        @Override
        public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
            return true;
        }

        @Override
        public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
            if (body instanceof CommonResult){
                return body;
            }

            return new CommonResult<Object>(body);
        }
    }
}

在entity文件下创建实体类CommmonResult,添加如下代码

package com.rex.springbootjson.entity;



public final class CommonResult<T> {

    private int status = 1;

    private String errorCode = "";

    private String errorMsg = "";

    private T resultBody;

    public CommonResult() {
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public String getErrorCode() {
        return errorCode;
    }

    public void setErrorCode(String errorCode) {
        this.errorCode = errorCode;
    }

    public String getErrorMsg() {
        return errorMsg;
    }

    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
    }

    public T getResultBody() {
        return resultBody;
    }

    public void setResultBody(T resultBody) {
        this.resultBody = resultBody;
    }

    public CommonResult(T resultBody) {
        this.resultBody = resultBody;
    }
}

3.在controller类下PersonController添加如下代码

 @RequestMapping("/CommonResult")
    public CommonResult<Object> getUserList() {
        List<Person> personList2 = new ArrayList<>();
        Person user1 = new Person("李四",18,123);
        Person user2 = new Person("王五",15,321);
        personList2.add(user1);
        personList2.add(user2);
        return new CommonResult<Object>(personList2);
    }

好的,我们的统一返回格式已经大功告成,接下来测试。

3.测试接口

访问http://localhost:8080/CommonResult
返回结果如下

{"status":1,
"errorCode":"",
"errorMsg":"",
"resultBody":[{"name":"李四","age":18,"phoneNumber":123},{"name":"王五","age":15,"phoneNumber":321}]}

下面我们随便访问一个不存在的接口,如http://localhost:8080/aaa,(这里用浏览器可能直接Whitelabel Error Page)用接口测试工具可以返回如下结果

{"timestamp":1603540190184,
"status":404,"error":
"Not Found",
"message":"","path":"/aaa"}

总结

本文仅是对Spring Boot的json处理及统一返回做一个实例,是本人在学习过程中的总结与实践。

展开阅读全文
  • 16
    点赞
  • 17
    评论
  • 7
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

<div style="color:#444444;"> 适用人群 <p style="color:#666666;"> 所有的IT从业者,尤其适合快速掌握新技术,快速增长工作经验人群,对教育公平,教育公益,教育爱心公益人士 </p> </div> <p> </p> 课程概述 <p> 该互联网实战项目是基于 Spring Boot 2+ SpringSecurity5+Element UI+Vue Admin Template+蚂蚁可视化AntV 等技术栈开发的项目,采用分布式,多模块,前后端分离开发。包括图形展示、权限管理、用户管理等功能。<br /> 【后端技术】<br /> 技术 说明<br /> Spring Boot2 MVC框架 开发的站式解决方案<br /> Spring Security5  认证和授权框架<br /> MyBatisPlus3.3.1  基于 MyBatis 框架的快速研发框架<br /> MyBatisCode工具 生成 MyBatis 相关代码<br /> Jackson 提供了处理 JSON 数据的工具<br /> Lombok 简化对象封装工具 <br /> Druid   数据库连接池 <br /> 【前端技术】<br /> Vue        互联网最火的前端框架<br /> Vue Router 路由框架<br /> Vuex 全局状态管理框架<br /> Axios 前端 HTTP 框架<br /> Element UI 前端 UI 框架<br /> Vue Element Admin 前端模板<br /> Antv  蚂蚁金服可视化技术,阿里巴巴可视化技术,天猫,淘宝,支付宝,花呗均使用AntV<br /> 【开发工具】<br /> IntelliJ IDEA 开发 IDE<br /> SQLyog 数据库连接客户端<br /> Postman HTTP 请求工具<br /> 【开发环境】<br /> 工具 版本<br /> JDK 1.8 </p> <p> MySQL 5.7 </p> <p> <img src="https://img-bss.csdn.net/202004100922276928.png" alt="" /><img src="https://img-bss.csdn.net/202004100922434479.png" alt="" /><img src="https://img-bss.csdn.net/202004100922566924.png" alt="" /><img src="https://img-bss.csdn.net/202004100923062693.png" alt="" /></p> <p> <br /></p> <p> <br /></p>
相关推荐
©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值