SpringBoot学习之Json数据交互的方法

时间:2021-10-15 23:16:01

json知识讲解

json的定义

json(javascript object notation, js 对象简谱) 是一种轻量级的数据交换格式。它基于 ecmascript (欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 json 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。

解释来自于百度百科,说简单点。json就是一串字符串 只不过元素会使用特定的符号标注。

json的几种常见格式

对象

?
1
2
3
4
{
"username": "清风一阵吹我心",
"password": "123456"
}

数组

?
1
2
3
4
5
[
"one",
"two",
"three"
]

对象数组

?
1
2
3
4
5
6
7
8
9
10
11
12
{
"student": [
"张三",
"李四",
"王五"
],
"teacher": [
"语文",
"数学",
"英语"
]
}

数组对象

?
1
2
3
4
5
6
7
8
9
10
[
{
"username": "张三",
"age": 18
},
{
"username": "李四",
"age": 20
}
]

复杂的格式

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
{
 "msg": "查询成功",
 "code": 200,
 "data": {
  "provinces": [
   {
    "name": "重庆",
    "cities": [
     {
      "name": "重庆市",
      "district": [
       "江北区",
       "渝北区",
       "万州区",
       "合川区"
      ]
     }
    ]
   },
   {
    "name": "北京",
    "cities": [
     {
      "name": "北京市",
      "district": [
       "海淀区",
       "昌平区",
       "朝阳区",
       "丰台区"
      ]
     }
    ]
   }
  ]
 }
}

使用json的好处

  • 与xml相比,数据格式比较简单, 易于读写
  • 格式都是压缩的, 占用带宽小
  • 便于服务器端的解析,支持多种语言。包括c,c#,java,javascript, perl,php,python,ruby等。

json的知识,就讲到这里。

最近在弄监控主机项目,对javaweb又再努力学习。实际的项目场景中,前后分离几乎是所以项目的标配,全栈的时代的逐渐远去,后端负责业务逻辑处理,前端负责数据展示成了一种固定的开发模式。像thymeleaf这种东西没法实现前后端分离模板难学也只有写java的才用吧,还是用js模板引擎接受json好。

1. json报文

springboot 默认会使用 json 作为响应报文格式。首先,我们创建一个 usercontroller 用于处理前端的 web 请求。

定义一个简单的控制器,与通常返回 url 的 controller 不一样的是,login() 使用了 @responsebody 注解,它表示此接口响应为纯数据,不带任何界面展示,可以获得标准json。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@controller
@requestmapping("/user")
public class usercontroller {
 
 @requestmapping("/login")
 @responsebody
 public respentity login(@requestbody requser requser) { //使用requser模型来接受,而不用user
 
  user user = new user();
  if(requser != null) {
   user.setname(requser.getname());
   user.setpassword(requser.getpassword());
  }
 
  return new respentity(respcode.success, user); //返回的响应实体具体看下节
 }
}

对于上面的代码来说,还可以做进一步的优化,由于所有的 restful 接口都只是返回数据,所以我们可以直接在类级别上添加 @responsebody 注解。而大多数情况下,@controller 与 @responsebody 又会一起使用,所以我们使用 @restcontroller 注解来替换掉它们,从而更加简洁地实现功能。

2. 接口规范

对于每一家公司来说,都会定义自己的数据规范,一个统一且标准的数据规范对于系统维护来说是非常重要的,也在很在程度上提升了开发效率。

2.1 响应报文规范

接口响应至少需要告诉使用方三项信息:状态码、描述、数据。其中,数据不是每个接口必须的,如果只是一个简单修改的动作,可能就没有必须返回数据了。下面我们定义一个 respentity类来封装我们的响应报文model:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class respentity {
 private int code;
 private string msg;
 private object data;
 
 public respentity(respcode respcode) {
  this.code = respcode.getcode();
  this.msg = respcode.getmsg();
 }
 
 public respentity(respcode respcode, object data) {
  this(respcode);
  this.data = data;
 }
 
 ...
}

同时,定义一个枚举类来维护我们的状态码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public enum respcode {
 
 success(0, "请求成功"),
 warn(-1, "网络异常,请稍后重试");
 
 private int code;
 private string msg;
 
 respcode(int code, string msg) {
  this.msg = msg;
 }
 
 public int getcode() {
  return code;
 }
 public string getmsg() {
  return msg;
 }
}

这样,我们的响应数据规范已基本建立。

2.2 请求数据规范

响应报文格式我们已经定义好了,那么请求数据我们如何接收呢?

一般来说,请求与响应会使用相同的报文形式。如果响应为json,那么请求也建议使用json。

为登录请求添加输入参数,首先,需要我们定义好用户实体user类,直接在映射方法login() 使用该实体进行参数接收,并将接收到的参数直接返回,1.节代码已实现。

调出postman,填写正确的url,选择post方式发送请求,选择body,将 content-type 设置成 application/json,填入 json 格式的请求数据,点击 send 即可得到如下结果。

SpringBoot学习之Json数据交互的方法

数据接收非常成功,但在上面的响应报文中,存在着了一个非常严重的问题,那就是用户的密码也随同用户信息一起返回给了客户端,显然这并不是一种正确的做法。

我们需要对其进行一次过滤,由于 springboot 默认使用 jackson 作为 json 序列化工具,如果想要过滤掉响应中的某些字段,只需在过滤字段对应的 get 方法上加上 @jsonignore 注解即可。

但这样又会引发另外一个问题,那就是请求中的字段也被过滤掉了,对于这种问题,可以采用抽离请求参数模型的方式进行处理,即自定义一套参数接收的 model,比如,接收用户登录的会使用 requser 来进行参数接收,这样使得请求参数模型与数据库映射实体完全分离,在一定程度上提升了系统的安全性。替换成 model 对象后(1.节的代码已经替换好了),我们就可以在数据库映射实体 user 上增加 @jsonignore 注解忽略该字段的序列化,而不影响请求参数的输入。

SpringBoot学习之Json数据交互的方法

3. 参数校验

出于系统健壮性的考虑,我们需要对所有的参数进行必要性校验,如:登录请求时,如果没有用户名,程序应该立即驳回该请求。上面请求参数模型(model)的抽象也使得我们对数据校验更加方便,当然主要还是依赖于 springboot 的 validate 功能的强大支持。

3.1. 简单参数校验

对于登录接口来说,用户名与密码都是必输的,那么我们现在为其添加上对应的参数校验,无需 if-else 判断,简单的几个注解就可以帮助我们完成所有的工作。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class logincontroller {
 
 @requestmapping("/login")
 @responsebody
 public respentity login(@requestbody @valid requser requser) {
 
 }
}
----
public class requser {
 @notblank(message = "用户名不能为空")
 public string getname() {
  return name;
 }
 
 @notblank(message = "密码不能为空")
 public string getpassword() {
  return password;
 }
 ...
}

我们为请求参数的 model 对象requser 加上了 @valid 注解,并在 model 类中对需要校验字段的 get 方法上添加相应的校验注解。效果如下:

SpringBoot学习之Json数据交互的方法

3.2. 复杂参数校验

正则表达式校验

如果用户的登录名为手机号,那么就需要对登录名的格式做进一步的校验,下面使用正则表达式来校验手机号的合法性。

?
1
2
3
4
5
6
7
8
@notblank(message = "用户名不能为空")
@pattern(
  regexp = "1(([38]\\d)|(5[^4&&\\d])|(4[579])|(7[0135678]))\\d{8}",
  message = "手机号格式不合法"
)
public string getusername() {
 return username;
}

自定义校验注解

在系统使用过程中,有很多地方需要对手机号的格式进行校验,如:注册、验证码发送等。

但校验手机号的正则表达式又过于复杂,如果多处编写,一旦运营商增加某个号段,对程序的维护人员来说就是一个噩耗。这时,可以使用自定义校验注解来代替这些常用的校验。

手机号校验注解 phone:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
@constraint(validatedby = phonevalidator.class)
@target({elementtype.method, elementtype.field})
@retention(retentionpolicy.runtime)
@documented
public @interface phone {
 
 string message() default "手机号格式不合法";
 
 class<?>[] groups() default {};
 
 class<? extends payload>[] payload() default {};
 
}

手机号校验实现类 phonevalidator:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
public class phonevalidator implements constraintvalidator<phone, string> {
 
 private pattern pattern = pattern.compile("1(([38]\\d)|(5[^4&&\\d])|(4[579])|(7[0135678]))\\d{8}");
 
 @override
 public void initialize(phone phone) {
 }
 
 @override
 public boolean isvalid(string value, constraintvalidatorcontext constraintvalidatorcontext) {
  return pattern.matcher(value).matches();
 }
}

model 上的使用:

?
1
2
3
4
@phone
public string getusername() {
 return username;
}

这样的话,如果因为某些不可抗拒因素导致校验规则的变动,只需要修改一处理即可,维护成本大大降低。

SpringBoot学习之Json数据交互的方法

4. xml 报文

大多数情况下,使用 json 就可以满足我们的需求了,但仍然存在某些特定的场景需要使用到 xml 形式的报文,如:微信公众号开发。不过不用担心,切换成 xml 报文也只需要做轻微的改动,添加相关依赖如下:"com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.8.8"

然后就可以开始进行测试了,此处借助一个模拟 http 请求工具(postman)来协助我们测试该接口:

SpringBoot学习之Json数据交互的方法

在上面的测试范例里,我们指定了 accept 为 text/xml,这样 springboot 就会返回 xml 形式的数据。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://www.cnblogs.com/stillcoolme/p/7678883.html