1.Spring Boot返回Json数据及数据封装
1. Controller 中使用@RestController
注解即可返回 Json 格式的数据
首先看看@RestController注解包含了什么东西,
@ResponseBody
注解是将返回的数据结构转换为 Json 格式
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {@AliasFor(annotation = Controller.class)String value() default "";
}
Spring Boot 中默认使用的 json 解析框架是 jackson
1.1 Spring Boot 默认对Json的处理
1.1.1 创建实体类
@Data
public class Student {public int studentId;public String studentName;
}
1.1.2 创建接口类
@RestController
@CrossOrigin
@RequestMapping("/json")
public class JsonTest {@RequestMapping("/getStudent")public Student getStudent() {return new Student(18, "小志");}@RequestMapping("/getStudentList")public List<Student> getStudentList() {List<Student> list = new ArrayList<>();list.add(new Student(18, "小志"));list.add(new Student(19, "小庄"));list.add(new Student(20, "小王"));return list;}@RequestMapping("/getStudentMap")public Map<String,Object> getStudentMap() {Map<String,Object> map = new HashMap();map.put("学生姓名",new Student(25,"小王"));map.put("家庭地址","厦门市惠安县");map.put("出生年月",202000326);return map;}}
1.1.3 结果展示
-- /json/getStudent
{"studentId":18,"studentName":"小志"}-- /json/getStudentList
[{"studentId":18,"studentName":"小志"},{"studentId":19,"studentName":"小庄"},{"studentId":20,"studentName":"小王"}]-- /json/getStudentMap
{"家庭地址":"厦门市惠安县","学生姓名":{"studentId":25,"studentName":"小王"},"出生年月":202000326}
map 中不管是什么数据类型,都可以转成相应的 json 格式
1.1.4 jackson 中对null的处理
把map中的数据更改,测试jackson 中对null的处理
@RequestMapping("/getStudentMap")public Map<String,Object> getStudentMap() {Map<String,Object> map = new HashMap();map.put("学生姓名",new Student(25,"小王"));map.put("家庭地址","厦门市惠安县");map.put("出生年月",null);return map;}--/json/getStudentMap 返回结果
{"家庭地址":"厦门市惠安县","学生姓名":{"studentId":25,"studentName":"小王"},"出生年月":null}
添加 jackson 的配置类
package org.example.springbootdemo.config;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 JacksonConfig {@Bean@Primary@ConditionalOnMissingBean(ObjectMapper.class)public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {ObjectMapper objectMapper = builder.createXmlMapper(false).build();objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {@Overridepublic void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {jsonGenerator.writeString("");}});return objectMapper;}
}
-----------------------------------------------------结果如下--------------------------------------------------------------
{"家庭地址": "厦门市惠安县","学生姓名": {"studentId": 25,"studentName": "小王"},"出生年月": ""
}
1.2 使用阿里巴巴FastJson的设置
使用 fastJson 时,对 null 的处理和 jackson 有些不同,需要继承 WebMvcConfigurationSupport 类,然后覆盖 configureMessageConverters 方法,在方法中,我们可以选择对要实现 null 转换的场景,配置好即可。
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;@Configuration
public class fastJsonConfig extends WebMvcConfigurationSupport {/*** 使用阿里 FastJson 作为JSON MessageConverter* @param converters*/@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) {FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();FastJsonConfig config = new FastJsonConfig();config.setSerializerFeatures(// 保留map空的字段SerializerFeature.WriteMapNullValue,// 将String类型的null转成""SerializerFeature.WriteNullStringAsEmpty,// 将Number类型的null转成0SerializerFeature.WriteNullNumberAsZero,// 将List类型的null转成[]SerializerFeature.WriteNullListAsEmpty,// 将Boolean类型的null转成falseSerializerFeature.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);}
}
1.3 封装返回的统一数据结构
1.3.1 定义返回统一的json结构
@Data
public class CommomResult<T> {private String code;private String message;private T data;public CommomResult(String code, String message, T data) {this.code = code;this.message = message;this.data = data;}
}
1.3.2 修改接口层的返回操作及测试
@RestController
@CrossOrigin
@RequestMapping("/json")
public class JsonTest {@RequestMapping("/getStudent")public CommomResult getStudent() {//return new Student(18, "小志");return new CommomResult("0","查询成功",new Student(18,"小志"));}@RequestMapping("/getStudentList")public CommomResult getStudentList() {List<Student> list = new ArrayList<>();list.add(new Student(18, "小志"));list.add(new Student(19, "小庄"));list.add(new Student(20, "小王"));//return list;return new CommomResult<>("0","查询成功",list);}@RequestMapping("/getStudentMap")public CommomResult getStudentMap() {Map<String,Object> map = new HashMap();map.put("学生姓名",new Student(25,"小王"));map.put("家庭地址","厦门市惠安县");map.put("出生年月",null);//return map;return new CommomResult<>("0","查询成功",map);}}
1.3.3 测试结果
-- /json/getStudent
{"code": "0","message": "查询成功","data": {"studentId": 18,"studentName": "小志"}
}-- /json/getStudentList
{"code": "0","message": "查询成功","data": [{"studentId": 18,"studentName": "小志"},{"studentId": 19,"studentName": "小庄"},{"studentId": 20,"studentName": "小王"}]
}-- /json/getStudentMap
{"code": "0","message": "查询成功","data": {"家庭地址": "厦门市惠安县","学生姓名": {"studentId": 25,"studentName": "小王"},"出生年月": ""}
}
2.使用slf4j进行日志记录
3.Spring Boot中的项目属性配置
3.1 少量配置信息的情况
通过注解,获取当前配置信息
配置文件信息
server:port: 12888
配置类
@Component
public class ConfigEntity {@Value("${server.port}")private String port;
}
测试接口层
注意(@value注解的包):
import org.springframework.beans.factory.annotation.Value;
@RestController
@CrossOrigin
@RequestMapping("/test")
public class TestController {@Value("${server.port}")private String port;private final static Logger logger = LoggerFactory.getLogger(TestController.class);@RequestMapping("/getConfig")public String getConfig() {logger.info("获取注解的配置:" + port);return "获取配置";}}
结果如下
-- /test/getConfig
2025-07-18 11:03:10.568 INFO 21816 --- [ XNIO-1 task-1] o.e.s.c.TestController : 获取注解的配置:12888
3.2 多个配置信息的情况
application-dev.yml 文件# 配置多个微服务的地址
url:# 订单微服务的地址orderUrl: http://localhost:8002# 用户微服务的地址userUrl: http://localhost:8003# 购物车微服务的地址shoppingUrl: http://localhost:8004
情况一的方式,需要添加多个@value注解,情况二则是封装一个url的配置封装类
注意@ConfigurationProperties需要引入依赖,还需补充prefix参数前缀
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional> </dependency>
@Data
@Component
@ConfigurationProperties(prefix = "url")
public class UrlApplication {private String orderUrl;private String userUrl;private String shoppingUrl;
}
测试接口
@RestController
@CrossOrigin
@RequestMapping("/test")
public class TestController {@Resourceprivate UrlApplication urlApplication;private final static Logger logger = LoggerFactory.getLogger(TestController.class);@RequestMapping("/getConfig")public String getConfig() {logger.info("获取注解的配置:" + urlApplication.getOrderUrl());logger.info("获取注解的配置:" + urlApplication.getShoppingUrl());logger.info("获取注解的配置:" + urlApplication.getUserUrl());return "获取配置";}}
结果
-- /test/getConfig
2025-07-18 11:38:27.261 INFO 11612 --- [ XNIO-1 task-1] o.e.s.c.TestController : 获取注解的配置:http://localhost:8002
2025-07-18 11:38:27.262 INFO 11612 --- [ XNIO-1 task-1] o.e.s.c.TestController : 获取注解的配置:http://localhost:8004
2025-07-18 11:38:27.262 INFO 11612 --- [ XNIO-1 task-1] o.e.s.c.TestController : 获取注解的配置:http://localhost:8003
3.3 指定项目配置文件
通过application.yml中的属性:
spring:profiles:active: XX
4.Springboot中的MVC支持
Spring Boot 的 MVC 支持主要来介绍实际项目中最常用的几个注解,包括 @RestController
、 @RequestMapping
、@PathVariable
、@RequestParam
以及 @RequestBody
。主要介绍这几个注解常用的使用方式和特点。
4.1. @RestController
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {@AliasFor(annotation = Controller.class)String value() default "";
}
@RestController
注解包含了原来的 @Controller
和 @ResponseBody
注解
@ResponseBody
注解是将返回的数据结构转换为 Json 格式
如果接口返回的是类似 /login 登录页面,那就不能使用 @RestController
注解,因为使用这个注解返回就会解析成json字符串,得使用@Controller注解,且导入 thymeleaf 依赖(请求的路径未在控制器中定义,或对应的 Thymeleaf 模板不存在则报错如下)
4.2. @RequestMapping
@RequestMapping
是一个用来处理请求地址映射的注解,它可以用于类上,也可以用于方法上。
该注解有6个属性,一般在项目中比较常用的有三个属性:value、method 和 produces。
value 属性:指定请求的实际地址,value 可以省略不写
method 属性:指定请求的类型,主要有 GET、PUT、POST、DELETE,默认为 GET
produces属性:指定返回内容类型,如 produces = “application/json; charset=UTF-8”
4.3. @PathVariable
@PathVariable
注解主要是用来获取 url 参数
@RestController
@CrossOrigin
@RequestMapping("/test")
public class TestController {@GetMapping("/testRequest/{id}")public String testRequest(String id) {System.out.println("获取到的id为:" + id);return "测试@PathVariable ";}-- /test/testRequest/18
获取到的id为:null@GetMapping("/testRequest/{id}")public String testRequest(@PathVariable String id) {System.out.println("获取到的id为:" + id);return "测试@PathVariable ";}-- /test/testRequest/18
获取到的id为:18}
如果想要 url 中占位符中的 id 值直接赋值到参数 id 中,需要保证 url 中的参数和方法接收参数一致,否则就无法接收。如果不一致的话,其实也可以解决,需要用 @PathVariable
中的 value 属性来指定对应关系。
@GetMapping("/testRequest/{name}")public String testRequest(@PathVariable(value = "name") String studentName) {System.out.println("学生的姓名:" + studentName);return "测试@PathVariable ";}
支持多个参数的接收。同样地,如果 url 中的参数和方法中的参数名称不同的话,也需要使用 value 属性来绑定两个参数
4.4. @RequestParam
@RequestParam
注解顾名思义,也是获取请求参数的
主要区别在于: @PathValiable 是从 url 模板中获取参数值, 即这种风格的 url:http://localhost:8080/user/{id} ;而 @RequestParam 是从 request 里面获取参数值,即这种风格的 url:http://localhost:8080/user?id=1
@GetMapping("/testRequest")public String testRequest(@RequestParam(value = "age") String age) {System.out.println("学生的年龄:" + age);return "测试@PathVariable ";}--/test/testRequest?age=88
学生的年龄:88
除了 value 属性外,还有个两个属性比较常用:
- required 属性:true 表示该参数必须要传,否则就会报 404 错误,false 表示可有可无。
- defaultValue 属性:默认值,表示如果请求中没有同名参数时的默认值。
如果表单数据很多,我们不可能在后台方法中写上很多参数,每个参数还要 @RequestParam
注解。针对这种情况,我们需要封装一个实体类来接收这些参数,实体中的属性名和表单中的参数名一致即可。
@Data
public class User {public String userName;public String passWord;
}
接口测试类
@RestController
@CrossOrigin
@RequestMapping("/test")
public class TestController {@PostMapping("/form")public String form(@RequestParam(value = "userName") String userName ,@RequestParam(value = "passWord") String passWord ) {System.out.println("用户名:" + userName);System.out.println("密码:" + passWord);return "测试@PathVariable ";}@PostMapping("/form2")public String form2(User user) {System.out.println("用户名:" + user.userName);System.out.println("密码:" + user.passWord);return "测试@PathVariable ";}}
---------------------------------------------------------结果-----------------------------------------------------------------
用户名:吕子乔
密码:12138
4.5. @RequestBody
@PostMapping("/form3")public String form3(@RequestBody User user) {System.out.println("用户名:" + user.userName);System.out.println("密码:" + user.passWord);return "测试@RequestBody ";}
---------------------------------------------------------结果-----------------------------------------------------------------
用户名:陈美嘉
密码:1314520
5.Spring Boot集成 Swagger2 展现在线接口文档
步骤一:添加Swagger2 的 maven 依赖
步骤二:添加Swagger2 的配置类,注意应添加 @Configuration
注解,@EnableSwagger2
注解。
5.1 可能会出现的问题!
5.2 问题的解决
网页打开 localhost:8007/swagger-ui.html
出现这种情况(此处8007是我后端配置的启动端口),大概率是由于你没有将swagger的配置类放到启动类的同一个目录下,这样子启动类就不知道加载,虽然你有添加 @Configuration
注解,解决方法可以在启动类中添加扫描注解@ComponentScan("xx")
可能你添加完之后并未解决问题,这可能是残留的缓存导致的,可以删除编译后的target目录重新运行!!!
5.3 注解
实体类注解
@ApiModel
实体类的描述
@ApiModelProperty
实体类属性的描述
接口类注解
@Api
注解用于类上,表示标识这个类是 swagger 的资源。
@ApiOperation
注解用于方法,表示一个 http 请求的操作。
@ApiParam
注解用于参数上,用来标明参数信息。