【SpringBoot 教程】Spring Boot 返回 Json 数据及数据封装

愿你如阳光,明媚不忧伤。

目録

    • 1. 什么是SpringBoot
      • 1.1 简化编码
      • 1.2 简化配置
      • 1.3 简化部署
      • 1.4 简化监控
    • 2. Spring Boot 对 Json 的处理
      • 2.1 Class、List、Map 的处理
      • 2.2 null 的处理
      • 2.3 使用阿里巴巴FastJson的设置
    • 3. 封装统一的数据结构
      • 3.1 定义统一的 json 结构

 


1. 什么是SpringBoot

SpringBoot 基于 Spring Framework 构建,本质上是一些库的集合,它能够被任意项目的构建系统所使用,它使用 “习惯优于配置” (Convention over Configuration 项目中存在大量的配置,此外还内置一个习惯性的配置)的理念让你的项目快速运行起来。是一个配置工具,整合工具,辅助工具。和 Spring 框架紧密结合用于提升 Spring 开发者的体验。

【SpringBoot 教程】Spring Boot 返回 Json 数据及数据封装_第1张图片
Spring Boot 是伴随着 Spring 4.0 诞生的,从字面理解,Boot是引导的意思,因此 Spring Boot 旨在帮助开发者快速搭建 Spring 框架。Spring Boot 继承了原有 Spring 框架的优秀基因,使 Spring 在使用中更加方便快捷。


1.1 简化编码

举个例子,比如我们要创建一个 web 项目,在使用 Spring 的时候,需要在 pom 文件中添加多个依赖,而 Spring Boot 则会帮助开发者快速启动一个 web 容器,只需要在 pom 文件中添加一个 starter-web 依赖即可。

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-webartifactId>
dependency>

我们点击进入该依赖后可以看到,Spring Boot 这个 starter-web 已经包含了多个依赖,包括之前在 Spring 工程中需要导入的依赖。

 <dependencies>
    <dependency>
      <groupId>org.springframework.bootgroupId>
      <artifactId>spring-boot-starterartifactId>
      <version>2.5.4version>
      <scope>compilescope>
    dependency>
    <dependency>
      <groupId>org.springframework.bootgroupId>
      <artifactId>spring-boot-starter-jsonartifactId>
      <version>2.5.4version>
      <scope>compilescope>
    dependency>
    <dependency>
      <groupId>org.springframework.bootgroupId>
      <artifactId>spring-boot-starter-tomcatartifactId>
      <version>2.5.4version>
      <scope>compilescope>
    dependency>
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-webartifactId>
      <version>5.3.9version>
      <scope>compilescope>
    dependency>
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-webmvcartifactId>
      <version>5.3.9version>
      <scope>compilescope>
    dependency>
  dependencies>

由此可以看出,Spring Boot 大大简化了我们的编码,我们不用一个个导入依赖,直接一个依赖即可。


1.2 简化配置

Spring 虽然使Java EE轻量级框架,但由于其繁琐的配置,一度被人认为是“配置地狱”。各种XML、Annotation配置会让人眼花缭乱,而且配置多的话,如果出错了也很难找出原因。Spring Boot更多的是采用 Java Config 的方式,对 Spring 进行配置。举个例子:
新建一个类,但是我不用 @Service 注解,也就是说,它是个普通的类,那么我们如何使它也成为一个 Bean 让 Spring 去管理呢?只需要 @Configuration 和 @Bean 两个注解即可,如下:

public class TestService {
    public String sayHello() {
        return "Hello Spring Boot!";
    }
}
***************************************************************************
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JavaConfig {
    @Bean
    public TestService getTestService() {
        return new TestService();
    }
}

@Configuration 表示该类是个配置类, @Bean 表示该方法返回一个 Bean。这样就把 TestService 作 为 Bean 让 Spring 去管理了,在其他地方,我们如果需要使用该 Bean,和原来一样,直接使用 @Resource 注解注入进来即可使用,非常方便。

@Resource
private TestService testService;

另外,部署配置方面,原来 Spring 有多个 xml 和 properties配置,在 Spring Boot 中只需要一个 application.yml 即可。


1.3 简化部署

在使用 Spring 时,项目部署时需要我们在服务器上部署 tomcat,然后把项目打成 war 包扔到 tomcat 里,在使用 Spring Boot 后,我们不需要在服务器上去部署 tomcat,因为 Spring Boot 内嵌了 tomcat,我们只需要将项目打成 jar 包,使用 java -jar xxx.jar 一键式启动项目。另外,也降低对运行环境的基本要求,环境变量中有JDK即可。


1.4 简化监控

我们可以引入 spring-boot-start-actuator 依赖,直接使用 REST 方式来获取进程的运行期性能参数,从而达到监控的目的,比较方便。但是 Spring Boot 只是个微框架,没有提供相应的服务发现与注册的配套功能,没有外围监控集成方案,没有外围安全管理方案,所以在微服务架构中,还需要 Spring Cloud 来配合一起使用。

 


2. Spring Boot 对 Json 的处理

JSON 在项目开发中,接口与接口之间,前后端之间数据的传输都使用 Json 格式,在 Spring Boot 中,接口返回 Json 格式的数据很简单,在 Controller 中使用 @RestController 注解即可返回 Json 格式的数据,@RestController 也是 Spring Boot 新增的一个注解。

不懂 json 先跳转 → 搞懂JSON,深入剖析前后台传值等问题,仅此一篇文章就够了!!!

  • @RestController 源码
    可以看出,@RestController 注解包含了原来的 @Controller 和 @ResponseBody 注解。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
    @AliasFor(
        annotation = Controller.class
    )
    String value() default "";
}
  • spring-boot-starter-json 依赖
    我们点开 pom.xml 中的 spring-boot-starter-web 依赖,可以看到一个 spring-boot-starter-json 依赖。再次点进去 spring-boot-starter-json 依赖。
    @ResponseBody 注解是将返回的数据结构转换为 Json 格式。Spring Boot 中默认使用的 Json 解析技术框架是 jackson。
<dependency>
  <groupId>org.springframework.bootgroupId>
  <artifactId>spring-boot-starter-jsonartifactId>
  <version>2.5.4version>
  <scope>compilescope>
dependency>
***************************************************************************
  <dependencies>
    <dependency>
      <groupId>org.springframework.bootgroupId>
      <artifactId>spring-boot-starterartifactId>
      <version>2.5.4version>
      <scope>compilescope>
    dependency>
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-webartifactId>
      <version>5.3.9version>
      <scope>compilescope>
    dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.coregroupId>
      <artifactId>jackson-databindartifactId>
      <version>2.12.4version>
      <scope>compilescope>
    dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.datatypegroupId>
      <artifactId>jackson-datatype-jdk8artifactId>
      <version>2.12.4version>
      <scope>compilescope>
    dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.datatypegroupId>
      <artifactId>jackson-datatype-jsr310artifactId>
      <version>2.12.4version>
      <scope>compilescope>
    dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.modulegroupId>
      <artifactId>jackson-module-parameter-namesartifactId>
      <version>2.12.4version>
      <scope>compilescope>
    dependency>
  dependencies>

到此为止,我们知道了 Spring Boot 中默认使用的 json 解析框架是 jackson。下面我们看一下默认的 jackson 框架对常用数据类型的转 Json 处理。


2.1 Class、List、Map 的处理

  • User.java 实体类
public class User {
    private Integer userId;
    private String userName;
    private String password;
    // 省略get和set和构造器
}
  • JsonController.java 控制器
@RestController
@RequestMapping("/")
public class JsonController {
    @RequestMapping("user")
    public User userJson() {
        return new User(2021092401, "Ouseki1", "password1");
    }

    @RequestMapping("list")
    public List<User> userListJson() {
        List<User> userList = new ArrayList<>();
        User user1 = new User(2021092402, "Ouseki2", "password2");
        User user2 = new User(2021092403, "Ouseki3", "password3");
        userList.add(user1);
        userList.add(user2);
        return userList;
    }

    @RequestMapping("map")
    public Map<String, Object> userMapJson() {
        Map<String, Object> map = new HashMap<>();
        User user = new User(2021092401, "Ouseki1", "password1");
        map.put("作者信息", user);
        map.put("粉丝数量", 666);
        return map;
    }
}
  • 浏览器中输入:http://localhost:8080/user 返回 json 如下:

【SpringBoot 教程】Spring Boot 返回 Json 数据及数据封装_第2张图片

  • 浏览器中输入:http://localhost:8080/list 返回 json 如下:

【SpringBoot 教程】Spring Boot 返回 Json 数据及数据封装_第3张图片

  • 浏览器中输入:http://localhost:8080/map 返回 json 如下:

【SpringBoot 教程】Spring Boot 返回 Json 数据及数据封装_第4张图片


2.2 null 的处理

在实际项目中,我们难免会遇到一些 null 值出现,我们转 json 时,是不希望有这些 null 出现的,比如我们期望所有的 null 在转 json 时都变成 "" 这种空字符串,那怎么做呢?在 Spring Boot 中,我们做一下配置即可,新建一个 jackson 的配置类。

  • 默认处理

【SpringBoot 教程】Spring Boot 返回 Json 数据及数据封装_第5张图片

  • JacksonConfig.java
    @Primary:意思是在众多相同的bean中,优先使用用@Primary注解的bean。
    @Qualifier:指定某个bean有没有资格进行注入。
    @Bean:用于告诉方法,产生一个Bean对象,然后这个Bean对象交给Spring管理。产生这个Bean对象的方法Spring只会调用一次,随后这个Spring将会将这个Bean对象放在自己的IOC容器中。
    @ConditionalOnMissingBean:对于自定义的配置类,我们应该加上该注解,它会保证你的bean只有一个,即你的实例只有一个,当你注册多个相同的bean时,会出现异常,以避免多个配置同时注入的风险。
@Configuration
public class JacksonConfig {
    @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;
    }
}
  • 自定义配置后的效果

【SpringBoot 教程】Spring Boot 返回 Json 数据及数据封装_第6张图片


2.3 使用阿里巴巴FastJson的设置

有很多朋友习惯于使用阿里巴巴的 fastJson 来做项目中 json 转换的相关工作,关于 fastJson 和 jackson 的对比,网上有很多资料可以查看,主要是根据自己实际项目情况来选择合适的框架。从扩展上来看,fastJson 没有 jackson 灵活,从速度或者上手难度来看,fastJson 可以考虑。

  • fastJson 导入

<dependency>
    <groupId>com.alibabagroupId>
    <artifactId>fastjsonartifactId>
    <version>1.2.78version>
dependency>
  • ALiFastJsonConfig.java
    使用 fastJson 时,对 null 的处理和 jackson 有些不同,需要继承 WebMvcConfigurationSupport 类,然后覆盖 configureMessageConverters 方法,在方法中,我们可以选择对要实现 null 转换的场景,配置好即可。
@Configuration
public class ALiFastJsonConfig extends WebMvcConfigurationSupport {

    /**
     * 使用阿里 FastJson 作为JSON MessageConverter
     *
     * @param converters
     */
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
        com.alibaba.fastjson.support.config.FastJsonConfig config = new com.alibaba.fastjson.support.config.FastJsonConfig();
        config.setSerializerFeatures(
                // 保留map空的字段
                SerializerFeature.WriteMapNullValue,
                // 将String类型的null转成""
                SerializerFeature.WriteNullStringAsEmpty,
                // 将Number类型的null转成0
                SerializerFeature.WriteNullNumberAsZero,
                // 将List类型的null转成[]
                SerializerFeature.WriteNullListAsEmpty,
                // 将Boolean类型的null转成false
                SerializerFeature.WriteNullBooleanAsFalse,
                // 避免循环引用
                SerializerFeature.DisableCircularReferenceDetect);
        converter.setFastJsonConfig(config);
        converter.setDefaultCharset(Charset.forName("UTF-8"));
        List<MediaType> mediaTypeList = new ArrayList<>();
        // 解决中文乱码问题,相当于在Controller上的@RequestMapping中加了个属性produces = "application/json"
        mediaTypeList.add(MediaType.APPLICATION_JSON);
        converter.setSupportedMediaTypes(mediaTypeList);
        converters.add(converter);
    }
}
  • 自定义配置后的效果

【SpringBoot 教程】Spring Boot 返回 Json 数据及数据封装_第7张图片

 


3. 封装统一的数据结构

JsonResult 在实际项目中,除了要封装数据之外,我们往往需要在返回的 json 中添加一些其他信息,比如返回一些状态码 code ,返回一些 msg 给调用者,这样调用者可以根据 code 或者 msg 做一些逻辑判断。所以在实际项目中,我们需要封装一个统一的 json 返回结构存储返回信息。


3.1 定义统一的 json 结构

由于封装的 json 数据的类型不确定,所以在定义统一的 json 结构时,我们需要用到泛型。统一的 json 结构中属性包括数据、状态码、提示信息即可,构造方法可以根据实际业务需求做相应的添加即可,一般来说,应该有默认的返回结构,也应该有用户指定的返回结构。

  • JsonResult.java
package com.example.itgodroad.config;

/**
 * @author : ISCCF_A
 * @version : ITGodRoad_0.0.1
 * @dateTime: 2021/09/24 17:44
 * @since : 11
 */
public class JsonResult<T> {
    private T data;
    private String code;
    private String msg;

    /**
     * 若没有数据返回,默认状态码为0,提示信息为:操作成功!
     */
    public JsonResult() {
        this.code = "0";
        this.msg = "操作成功!";
    }

    /**
     * 若没有数据返回,可以人为指定状态码和提示信息
     *
     * @param code
     * @param msg
     */
    public JsonResult(String code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    /**
     * 有数据返回时,状态码为0,默认提示信息为:操作成功!
     *
     * @param data
     */
    public JsonResult(T data) {
        this.data = data;
        this.code = "0";
        this.msg = "操作成功!";
    }

    /**
     * 有数据返回,状态码为0,人为指定提示信息
     *
     * @param data
     * @param msg
     */
    public JsonResult(T data, String msg) {
        this.data = data;
        this.code = "0";
        this.msg = msg;
    }
    // 省略get和set方法
}

  • JsonController.java
    @RequestMapping("list")
    public JsonResult<List> userListJson() {
        List<User> userList = new ArrayList<>();
        User user1 = new User(2021092402, "Ouseki2", "password2");
        User user2 = new User(2021092403, "Ouseki3", null);
        userList.add(user1);
        userList.add(user2);
        // return userList;
        return new JsonResult<>(userList, "获取用户列表成功!");
    }
  • 返回信息
    通过封装,我们不但将数据通过 json 传给前端或者其他接口,还带上了状态码和提示信息,这在实际项目场景中应用非常广泛。

    【SpringBoot 教程】Spring Boot 返回 Json 数据及数据封装_第8张图片

你可能感兴趣的:(IT界大神成长之路,spring,json,spring,boot)