SpringBoot入门系列(二)如何返回统一的数据格式
前面介绍了Spring Boot的优点,然后介绍了如何快速创建Spring Boot 项目。不清楚的朋友可以看看之前的文章:https://www.cnblogs.com/zhangweizhong/category/1657780.html。
今天来说一说Spring的@Controller和@RestController控制器, 他们是如何响应客户端请求,如何返回json数据。
这个系列课程的完整源码,也会提供给大家。大家关注我的微信公众号(架构师精进),回复:springboot源码 获取这个系列课程的完整源码。或者点此链接直接下载完整源码
一、@Controller和@RestController 两种控制器
Spring中有Controller,RestController的两种控制器,都是用来表示Spring某个类的是否可以接收HTTP请求。
但是不同的是:
1、Controller:标识一个Spring类是Spring MVC controller处理器。
2、RestController: 主要用于Restfull接口,返回客户端数据请求。
所以RestController是@Controller和@ResponseBody的结合体,两个标注合并起来的作用。
二、@Controller的用法
1、创建pojo 包,并创建User 对象
package com.weiz.pojo; import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude; import java.util.Date; public class User {
private String name; @JsonIgnore
private String password; private Integer age; @JsonFormat(pattern = "yyyy-MM-dd hh:mm:ss",locale = "zh",timezone = "GMT+8")
private Date birthday; @JsonInclude(JsonInclude.Include.NON_NULL)
private String desc; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} public Integer getAge() {
return age;
} public void setAge(Integer age) {
this.age = age;
} public String getDesc() {
return desc;
} public void setDesc(String desc) {
this.desc = desc;
} public Date getBirthday() {
return birthday;
} public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
2、创建UserController 控制器
package com.weiz.controller; import com.weiz.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; import java.util.Date; @Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/getUser")
@ResponseBody
public User getUser(){
User u = new User();
u.setName("weiz");
u.setAge(18);
u.setBirthday(new Date());
u.setPassword("weiz"); return u;
}
}
3、运行查看数据返回,在浏览器中输入:http://localhost:8080/user/getUser,返回数据可以看到控制器自动将user对象转换为json数据格式。

三、@RestController的用法
其实 RestController是Controller和ResponseBody的结合体,两个标注合并起来的作用。
所以,将上面的UserController 修改如下即可:
package com.weiz.controller; import com.weiz.pojo.JSONResult;
import com.weiz.pojo.User;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import java.util.Date; //@Controller
@RestController // RestController = Controller + ResponseBody
@RequestMapping("/user")
public class UserController {
@RequestMapping("/getUser")
//@ResponseBody
public JSONResult getUser(){
User u = new User();
u.setName("weiz222");
u.setAge(20);
u.setBirthday(new Date());
u.setPassword("weiz222"); return u;
}
}
四、统一返回
其实 RestController 给客户端返回数据时,一般会用jackson序列化返回。而不是直接返回整个pojo类对象。下面就简单介绍下如何统一返回json数据格式:
1、pojo类相关增加序列化格式配置,如上面的User对象的定义

2、增加Json通用的封装类JsonUtils ,下面这个就是比较常用的json数据封装类。
package com.weiz.utils; import java.util.List; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; /**
*
* @Title: JSONResult.java
* @Package com.weiz.utils
* @Description: 自定义响应数据结构
* 这个类是提供给门户,ios,安卓,微信商城用的
* 门户接受此类数据后需要使用本类的方法转换成对于的数据类型格式(类,或者list)
* 其他自行处理
* 200:表示成功
* 500:表示错误,错误信息在msg字段中
* 501:bean验证错误,不管多少个错误都以map形式返回
* 502:拦截器拦截到用户token出错
* 555:异常抛出信息
* Copyright: Copyright (c) 2016
*
* @author weiz
* @date 2016年4月22日 下午8:33:36
* @version V1.0
*/
public class JSONResult { // 定义jackson对象
private static final ObjectMapper MAPPER = new ObjectMapper(); // 响应业务状态
private Integer status; // 响应消息
private String msg; // 响应中的数据
private Object data; private String ok; // 不使用 public static JSONResult build(Integer status, String msg, Object data) {
return new JSONResult(status, msg, data);
} public static JSONResult ok(Object data) {
return new JSONResult(data);
} public static JSONResult ok() {
return new JSONResult(null);
} public static JSONResult errorMsg(String msg) {
return new JSONResult(500, msg, null);
} public static JSONResult errorMap(Object data) {
return new JSONResult(501, "error", data);
} public static JSONResult errorTokenMsg(String msg) {
return new JSONResult(502, msg, null);
} public static JSONResult errorException(String msg) {
return new JSONResult(555, msg, null);
} public JSONResult() { } public JSONResult(Integer status, String msg, Object data) {
this.status = status;
this.msg = msg;
this.data = data;
} public JSONResult(Object data) {
this.status = 200;
this.msg = "OK";
this.data = data;
} public Boolean isOK() {
return this.status == 200;
} public Integer getStatus() {
return status;
} public void setStatus(Integer status) {
this.status = status;
} public String getMsg() {
return msg;
} public void setMsg(String msg) {
this.msg = msg;
} public Object getData() {
return data;
} public void setData(Object data) {
this.data = data;
} /**
*
* @Description: 将json结果集转化为LeeJSONResult对象
* 需要转换的对象是一个类
* @param jsonData
* @param clazz
* @return
*
* @author weiz
* @date 2016年4月22日 下午8:34:58
*/
public static JSONResult formatToPojo(String jsonData, Class<?> clazz) {
try {
if (clazz == null) {
return MAPPER.readValue(jsonData, JSONResult.class);
}
JsonNode jsonNode = MAPPER.readTree(jsonData);
JsonNode data = jsonNode.get("data");
Object obj = null;
if (clazz != null) {
if (data.isObject()) {
obj = MAPPER.readValue(data.traverse(), clazz);
} else if (data.isTextual()) {
obj = MAPPER.readValue(data.asText(), clazz);
}
}
return build(jsonNode.get("status").intValue(), jsonNode.get("msg").asText(), obj);
} catch (Exception e) {
return null;
}
} /**
*
* @Description: 没有object对象的转化
* @param json
* @return
*
* @author weiz
* @date 2016年4月22日 下午8:35:21
*/
public static JSONResult format(String json) {
try {
return MAPPER.readValue(json, JSONResult.class);
} catch (Exception e) {
e.printStackTrace();
}
return null;
} /**
*
* @Description: Object是集合转化
* 需要转换的对象是一个list
* @param jsonData
* @param clazz
* @return
*
* @author weiz
* @date 2016年4月22日 下午8:35:31
*/
public static JSONResult formatToList(String jsonData, Class<?> clazz) {
try {
JsonNode jsonNode = MAPPER.readTree(jsonData);
JsonNode data = jsonNode.get("data");
Object obj = null;
if (data.isArray() && data.size() > 0) {
obj = MAPPER.readValue(data.traverse(),
MAPPER.getTypeFactory().constructCollectionType(List.class, clazz));
}
return build(jsonNode.get("status").intValue(), jsonNode.get("msg").asText(), obj);
} catch (Exception e) {
return null;
}
} public String getOk() {
return ok;
} public void setOk(String ok) {
this.ok = ok;
} }
3、如何调用

最后
以上,就把Spring Boot中的Controller及如何返回json数据介绍完了。
这个系列课程的完整源码,也会提供给大家。大家关注我的微信公众号(架构师精进),回复:springboot源码 获取这个系列课程的完整源码。

SpringBoot入门系列(二)如何返回统一的数据格式的更多相关文章
- SpringBoot入门系列(十一)统一异常处理的实现
前面介绍了Spring Boot 如何整合定时任务已经Spring Boot 如何创建异步任务和定时任务.不清楚的朋友可以看看之前的文章:<Spring Boot 入门系列文章> 接下来主 ...
- SpringBoot入门系列(十二)统一日志收集
前面介绍了Spring Boot 异常处理,不清楚的朋友可以看看之前的文章:https://www.cnblogs.com/zhangweizhong/category/1657780.html. 今 ...
- mybatis入门系列二之输入与输出参数
mybatis入门系列二之详解输入与输出参数 基础知识 mybatis规定mapp.xml中每一个SQL语句形式上只能有一个@parameterType和一个@resultType 1. 返回 ...
- C# 互操作性入门系列(二):使用平台调用调用Win32 函数
好文章搬用工模式启动ing ..... { 文章中已经包含了原文链接 就不再次粘贴了 言明 改文章是一个系列,但只收录了2篇,原因是 够用了 } --------------------------- ...
- [转]C# 互操作性入门系列(二):使用平台调用调用Win32 函数
传送门 C#互操作系列文章: C# 互操作性入门系列(一):C#中互操作性介绍 C# 互操作性入门系列(二):使用平台调用调用Win32 函数 C# 互操作性入门系列(三):平台调用中的数据封送处理 ...
- Maven入门系列(二)--设置中央仓库的方法
原文地址:http://www.codeweblog.com/maven入门系列-二-设置中央仓库的方法/ Maven仓库放在我的文档里好吗?当然不好,重装一次电脑,意味着一切jar都要重新下载和发布 ...
- SpringBoot入门教程(二)CentOS部署SpringBoot项目从0到1
在之前的博文<详解intellij idea搭建SpringBoot>介绍了idea搭建SpringBoot的详细过程, 并在<CentOS安装Tomcat>中介绍了Tomca ...
- C语言高速入门系列(二)
C语言高速入门系列(二) -----转载请注明出处coder-pig 本节引言: 在前面一节中我们对C语言进行了初步的了解,学会了使用IDE进行代码的编写,编译执行! 在这一节中我们会对C语言的基本的 ...
- SpringBoot入门(二)——起步依赖
本文来自网易云社区 在前一篇我们通过简单几步操作就生成了一个可以直接运行的Web程序,这是因为SpringBoot代替我们做了许多工作,概括来讲可以分为起步依赖和自动配置.这一篇先来看看起步依赖. 项 ...
- SpringBoot入门系列(转)
SpringBoot入门系列:第一篇 Hello World http://blog.csdn.net/lxhjh/article/details/51711148
随机推荐
- 使用java获取手机号归属地等信息httpClient实现
java获取手机号归属地 一般想获取手机号归属地等信息个人是无法获取的,但是可以通过调用第三方接口获取,具体百度搜索很多这里例子提供一个淘宝的接口 ,该功能已经发布到网站作为一个在线小工具,拿走不谢: ...
- 吴裕雄--天生自然python学习笔记:python 用pygame模块处理音频文件
除了对图片. Word 等普通格式的文件进行处理外, Python 还有强大的多媒体文件操作能力,如对音频.视频 文件的操作 . 如果要播放音乐,我们可以用 pygame 包中的 mixer 对 象. ...
- C# 关闭登录窗体,显示主窗体
首先在programm.cs里设置登录窗体显示 static class Program { /// <summary> /// The main ent ...
- RHEL7在线安装rvm(ruby管理包)
ttp://blog.csdn.net/lixwjava/article/details/50408070 安装curl sudo yum install curl 然后在在终端中输入命令 curl ...
- day19-3个双下item方法
#使用双下item方法来实现属性的增删改查: # 查:__getitem__ 增改:__setitem__ 删除: __delitem__ class Goods: def __init__(self ...
- linux 上安装 java
一.源码安装 1.本地下载 java, 并上传到 linux 上 2.解压文件 tar -zxvf jdk-7u72-linux-i586.gz 3.配置环境变量 vi /etc/profile ...
- 第一届“信安杯”部分WriteUp
第一届"信安杯"部分WriteUp------OooooohLeeGay队! 小队成员(按姓氏):郭泽坤.李江川.赵乐祺 以下这部分是做出来的 2019.11.23-24 ++Re ...
- JAVA单例模式的几种写法
/** * 单例模式懒汉式(双重检锁线程安全.JDK1.5之后) */ public class Singleton { private static volatile Singleton singl ...
- 源码中TODO、FIXME和XXX的含义
前言: 今天在阅读Qt Creator的源代码时,发现一些注释中有FIXME英文单词,用英文词典居然查不到其意义! 实际上,在阅读一些开源代码时,我们常会碰到诸如:TODO.FIXME和XXX的单词 ...
- 新特DEV1光速发布背后:原来“开公司”也能风驰电掣
去年12月16日,总融资额达到200亿元的蔚来汽车正式推出电动SUV车型ES8:去年12月22日,威马汽车宣布最新一轮融资,累计获得120亿元的融资额:今年1月29日,小鹏汽车宣布启动总额为22亿元人 ...