SpringBoot學(xué)習(xí)之Json數(shù)據(jù)交互的方法
JSON知識(shí)講解
JSON的定義
JSON(JavaScript Object Notation, JS 對(duì)象簡(jiǎn)譜) 是一種輕量級(jí)的數(shù)據(jù)交換格式。它基于 ECMAScript (歐洲計(jì)算機(jī)協(xié)會(huì)制定的js規(guī)范)的一個(gè)子集,采用完全獨(dú)立于編程語(yǔ)言的文本格式來(lái)存儲(chǔ)和表示數(shù)據(jù)。簡(jiǎn)潔和清晰的層次結(jié)構(gòu)使得 JSON 成為理想的數(shù)據(jù)交換語(yǔ)言。 易于人閱讀和編寫,同時(shí)也易于機(jī)器解析和生成,并有效地提升網(wǎng)絡(luò)傳輸效率。
解釋來(lái)自于百度百科,說(shuō)簡(jiǎn)單點(diǎn)。JSON就是一串字符串 只不過(guò)元素會(huì)使用特定的符號(hào)標(biāo)注。
JSON的幾種常見(jiàn)格式
對(duì)象
{ "username": "清風(fēng)一陣吹我心", "password": "123456" }
數(shù)組
[ "one", "two", "three" ]
對(duì)象數(shù)組
{ "student": [ "張三", "李四", "王五" ], "teacher": [ "語(yǔ)文", "數(shù)學(xué)", "英語(yǔ)" ] }
數(shù)組對(duì)象
[ { "username": "張三", "age": 18 }, { "username": "李四", "age": 20 } ]
復(fù)雜的格式
{ "msg": "查詢成功", "code": 200, "data": { "provinces": [ { "name": "重慶", "cities": [ { "name": "重慶市", "district": [ "江北區(qū)", "渝北區(qū)", "萬(wàn)州區(qū)", "合川區(qū)" ] } ] }, { "name": "北京", "cities": [ { "name": "北京市", "district": [ "海淀區(qū)", "昌平區(qū)", "朝陽(yáng)區(qū)", "豐臺(tái)區(qū)" ] } ] } ] } }
使用JSON的好處
- 與XML相比,數(shù)據(jù)格式比較簡(jiǎn)單, 易于讀寫
- 格式都是壓縮的, 占用帶寬小
- 便于服務(wù)器端的解析,支持多種語(yǔ)言。包括C,C#,Java,JavaScript, Perl,php,Python,Ruby等。
JSON的知識(shí),就講到這里。
最近在弄監(jiān)控主機(jī)項(xiàng)目,對(duì)javaweb又再努力學(xué)習(xí)。實(shí)際的項(xiàng)目場(chǎng)景中,前后分離幾乎是所以項(xiàng)目的標(biāo)配,全棧的時(shí)代的逐漸遠(yuǎn)去,后端負(fù)責(zé)業(yè)務(wù)邏輯處理,前端負(fù)責(zé)數(shù)據(jù)展示成了一種固定的開(kāi)發(fā)模式。像thymeleaf這種東西沒(méi)法實(shí)現(xiàn)前后端分離模板難學(xué)也只有寫java的才用吧,還是用js模板引擎接受json好。
1. Json報(bào)文
SpringBoot 默認(rèn)會(huì)使用 Json 作為響應(yīng)報(bào)文格式。首先,我們創(chuàng)建一個(gè) UserController 用于處理前端的 Web 請(qǐng)求。
定義一個(gè)簡(jiǎn)單的控制器,與通常返回 Url 的 Controller 不一樣的是,login() 使用了 @ResponseBody 注解,它表示此接口響應(yīng)為純數(shù)據(jù),不帶任何界面展示,可以獲得標(biāo)準(zhǔn)Json。
@Controller @RequestMapping("/user") public class UserController { @RequestMapping("/login") @ResponseBody public RespEntity login(@RequestBody ReqUser reqUser) { //使用reqUser模型來(lái)接受,而不用User User user = new User(); if(reqUser != null) { user.setName(reqUser.getName()); user.setPassword(reqUser.getPassword()); } return new RespEntity(RespCode.SUCCESS, user); //返回的響應(yīng)實(shí)體具體看下節(jié) } }
對(duì)于上面的代碼來(lái)說(shuō),還可以做進(jìn)一步的優(yōu)化,由于所有的 Restful 接口都只是返回?cái)?shù)據(jù),所以我們可以直接在類級(jí)別上添加 @ResponseBody 注解。而大多數(shù)情況下,@Controller 與 @ResponseBody 又會(huì)一起使用,所以我們使用 @RestController 注解來(lái)替換掉它們,從而更加簡(jiǎn)潔地實(shí)現(xiàn)功能。
2. 接口規(guī)范
對(duì)于每一家公司來(lái)說(shuō),都會(huì)定義自己的數(shù)據(jù)規(guī)范,一個(gè)統(tǒng)一且標(biāo)準(zhǔn)的數(shù)據(jù)規(guī)范對(duì)于系統(tǒng)維護(hù)來(lái)說(shuō)是非常重要的,也在很在程度上提升了開(kāi)發(fā)效率。
2.1 響應(yīng)報(bào)文規(guī)范
接口響應(yīng)至少需要告訴使用方三項(xiàng)信息:狀態(tài)碼、描述、數(shù)據(jù)。其中,數(shù)據(jù)不是每個(gè)接口必須的,如果只是一個(gè)簡(jiǎn)單修改的動(dòng)作,可能就沒(méi)有必須返回?cái)?shù)據(jù)了。下面我們定義一個(gè) RespEntity類來(lái)封裝我們的響應(yīng)報(bào)文model:
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; } ... }
同時(shí),定義一個(gè)枚舉類來(lái)維護(hù)我們的狀態(tài)碼:
public enum RespCode { SUCCESS(0, "請(qǐng)求成功"), WARN(-1, "網(wǎng)絡(luò)異常,請(qǐng)稍后重試"); private int code; private String msg; RespCode(int code, String msg) { this.msg = msg; } public int getCode() { return code; } public String getMsg() { return msg; } }
這樣,我們的響應(yīng)數(shù)據(jù)規(guī)范已基本建立。
2.2 請(qǐng)求數(shù)據(jù)規(guī)范
響應(yīng)報(bào)文格式我們已經(jīng)定義好了,那么請(qǐng)求數(shù)據(jù)我們?nèi)绾谓邮漳兀?br />
一般來(lái)說(shuō),請(qǐng)求與響應(yīng)會(huì)使用相同的報(bào)文形式。如果響應(yīng)為Json,那么請(qǐng)求也建議使用Json。
為登錄請(qǐng)求添加輸入?yún)?shù),首先,需要我們定義好用戶實(shí)體User類,直接在映射方法login() 使用該實(shí)體進(jìn)行參數(shù)接收,并將接收到的參數(shù)直接返回,1.節(jié)代碼已實(shí)現(xiàn)。
調(diào)出Postman,填寫正確的Url,選擇POST方式發(fā)送請(qǐng)求,選擇Body,將 Content-Type 設(shè)置成 application/json,填入 Json 格式的請(qǐng)求數(shù)據(jù),點(diǎn)擊 Send 即可得到如下結(jié)果。
數(shù)據(jù)接收非常成功,但在上面的響應(yīng)報(bào)文中,存在著了一個(gè)非常嚴(yán)重的問(wèn)題,那就是用戶的密碼也隨同用戶信息一起返回給了客戶端,顯然這并不是一種正確的做法。
我們需要對(duì)其進(jìn)行一次過(guò)濾,由于 SpringBoot 默認(rèn)使用 Jackson 作為 Json 序列化工具,如果想要過(guò)濾掉響應(yīng)中的某些字段,只需在過(guò)濾字段對(duì)應(yīng)的 get 方法上加上 @JsonIgnore 注解即可。
但這樣又會(huì)引發(fā)另外一個(gè)問(wèn)題,那就是請(qǐng)求中的字段也被過(guò)濾掉了,對(duì)于這種問(wèn)題,可以采用抽離請(qǐng)求參數(shù)模型的方式進(jìn)行處理,即自定義一套參數(shù)接收的 Model,比如,接收用戶登錄的會(huì)使用 ReqUser 來(lái)進(jìn)行參數(shù)接收,這樣使得請(qǐng)求參數(shù)模型與數(shù)據(jù)庫(kù)映射實(shí)體完全分離,在一定程度上提升了系統(tǒng)的安全性。替換成 Model 對(duì)象后(1.節(jié)的代碼已經(jīng)替換好了),我們就可以在數(shù)據(jù)庫(kù)映射實(shí)體 User 上增加 @JsonIgnore 注解忽略該字段的序列化,而不影響請(qǐng)求參數(shù)的輸入。
3. 參數(shù)校驗(yàn)
出于系統(tǒng)健壯性的考慮,我們需要對(duì)所有的參數(shù)進(jìn)行必要性校驗(yàn),如:登錄請(qǐng)求時(shí),如果沒(méi)有用戶名,程序應(yīng)該立即駁回該請(qǐng)求。上面請(qǐng)求參數(shù)模型(Model)的抽象也使得我們對(duì)數(shù)據(jù)校驗(yàn)更加方便,當(dāng)然主要還是依賴于 SpringBoot 的 Validate 功能的強(qiáng)大支持。
3.1. 簡(jiǎn)單參數(shù)校驗(yàn)
對(duì)于登錄接口來(lái)說(shuō),用戶名與密碼都是必輸?shù)?,那么我們現(xiàn)在為其添加上對(duì)應(yīng)的參數(shù)校驗(yàn),無(wú)需 if-else 判斷,簡(jiǎn)單的幾個(gè)注解就可以幫助我們完成所有的工作。
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; } ... }
我們?yōu)檎?qǐng)求參數(shù)的 Model 對(duì)象ReqUser 加上了 @Valid 注解,并在 Model 類中對(duì)需要校驗(yàn)字段的 get 方法上添加相應(yīng)的校驗(yàn)注解。效果如下:
3.2. 復(fù)雜參數(shù)校驗(yàn)
正則表達(dá)式校驗(yàn)
如果用戶的登錄名為手機(jī)號(hào),那么就需要對(duì)登錄名的格式做進(jìn)一步的校驗(yàn),下面使用正則表達(dá)式來(lái)校驗(yàn)手機(jī)號(hào)的合法性。
@NotBlank(message = "用戶名不能為空") @Pattern( regexp = "1(([38]\\d)|(5[^4&&\\d])|(4[579])|(7[0135678]))\\d{8}", message = "手機(jī)號(hào)格式不合法" ) public String getUsername() { return username; }
自定義校驗(yàn)注解
在系統(tǒng)使用過(guò)程中,有很多地方需要對(duì)手機(jī)號(hào)的格式進(jìn)行校驗(yàn),如:注冊(cè)、驗(yàn)證碼發(fā)送等。
但校驗(yàn)手機(jī)號(hào)的正則表達(dá)式又過(guò)于復(fù)雜,如果多處編寫,一旦運(yùn)營(yíng)商增加某個(gè)號(hào)段,對(duì)程序的維護(hù)人員來(lái)說(shuō)就是一個(gè)噩耗。這時(shí),可以使用自定義校驗(yàn)注解來(lái)代替這些常用的校驗(yàn)。
手機(jī)號(hào)校驗(yàn)注解 Phone:
@Constraint(validatedBy = PhoneValidator.class) @Target({ElementType.METHOD, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Phone { String message() default "手機(jī)號(hào)格式不合法"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
手機(jī)號(hào)校驗(yàn)實(shí)現(xiàn)類 PhoneValidator:
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 上的使用:
@Phone public String getUsername() { return username; }
這樣的話,如果因?yàn)槟承┎豢煽咕芤蛩貙?dǎo)致校驗(yàn)規(guī)則的變動(dòng),只需要修改一處理即可,維護(hù)成本大大降低。
4. Xml 報(bào)文
大多數(shù)情況下,使用 Json 就可以滿足我們的需求了,但仍然存在某些特定的場(chǎng)景需要使用到 XML 形式的報(bào)文,如:微信公眾號(hào)開(kāi)發(fā)。不過(guò)不用擔(dān)心,切換成 XML 報(bào)文也只需要做輕微的改動(dòng),添加相關(guān)依賴如下:"com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.8.8"
然后就可以開(kāi)始進(jìn)行測(cè)試了,此處借助一個(gè)模擬 HTTP 請(qǐng)求工具(Postman)來(lái)協(xié)助我們測(cè)試該接口:
在上面的測(cè)試范例里,我們指定了 Accept 為 text/xml,這樣 SpringBoot 就會(huì)返回 XML 形式的數(shù)據(jù)。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- SpringBoot整合Web開(kāi)發(fā)之Json數(shù)據(jù)返回的實(shí)現(xiàn)
- SpringBoot前后端json數(shù)據(jù)交互的全過(guò)程記錄
- SpringBoot實(shí)現(xiàn)前后端、json數(shù)據(jù)交互以及Controller接收參數(shù)的幾種常用方式
- SpringBoot響應(yīng)Json數(shù)據(jù)亂碼通過(guò)配置的解決
- springboot 返回json格式數(shù)據(jù)時(shí)間格式配置方式
- SpringBoot之返回json數(shù)據(jù)的實(shí)現(xiàn)方法
- SpringBoot響應(yīng)處理之以Json數(shù)據(jù)返回的實(shí)現(xiàn)方法
相關(guān)文章
Java中將接口返回的字節(jié)串轉(zhuǎn)為文件詳解
這篇文章主要給大家介紹了關(guān)于Java中將接口返回的字節(jié)串轉(zhuǎn)為文件的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2021-11-11Java實(shí)現(xiàn)堆排序(Heapsort)實(shí)例代碼
這篇文章主要介紹了Java實(shí)現(xiàn)堆排序(Heapsort)實(shí)例代碼,有需要的朋友可以參考一下2013-12-12Java使用RedisTemplate操作Redis遇到的坑
這篇文章主要介紹了Java使用RedisTemplate操作Redis遇到的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12SpringBoot+layui實(shí)現(xiàn)文件上傳功能
Spring Boot是由Pivotal團(tuán)隊(duì)提供的全新框架,其設(shè)計(jì)目的是用來(lái)簡(jiǎn)化新Spring應(yīng)用的初始搭建以及開(kāi)發(fā)過(guò)程。這篇文章主要介紹了SpringBoot+layui實(shí)現(xiàn)文件上傳,需要的朋友可以參考下2018-09-09詳解如何在Spring Boot中實(shí)現(xiàn)容錯(cuò)機(jī)制
容錯(cuò)機(jī)制是構(gòu)建健壯和可靠的應(yīng)用程序的重要組成部分,它可以幫助應(yīng)用程序在面對(duì)異?;蚬收蠒r(shí)保持穩(wěn)定運(yùn)行,Spring Boot提供了多種機(jī)制來(lái)實(shí)現(xiàn)容錯(cuò),包括異常處理、斷路器、重試和降級(jí)等,本文將介紹如何在Spring Boot中實(shí)現(xiàn)這些容錯(cuò)機(jī)制,需要的朋友可以參考下2023-10-10Spring?Feign超時(shí)設(shè)置深入了解
Spring?Cloud中Feign客戶端是默認(rèn)開(kāi)啟支持Ribbon的,最重要的兩個(gè)超時(shí)就是連接超時(shí)ConnectTimeout和讀超時(shí)ReadTimeout,在默認(rèn)情況下,也就是沒(méi)有任何配置下,F(xiàn)eign的超時(shí)時(shí)間會(huì)被Ribbon覆蓋,兩個(gè)超時(shí)時(shí)間都是1秒2023-03-03Java在長(zhǎng)字符串中查找短字符串的實(shí)現(xiàn)多種方法
這篇文章主要介紹了Java在長(zhǎng)字符串中查找短字符串的實(shí)現(xiàn)多種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12springboot斷點(diǎn)上傳、續(xù)傳、秒傳實(shí)現(xiàn)方式
這篇文章主要介紹了springboot斷點(diǎn)上傳、續(xù)傳、秒傳實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07