SpringMVC開(kāi)發(fā)restful API之用戶查詢代碼詳解
一,什么是restful風(fēng)格?
首先,我們來(lái)看幾組例子。
傳統(tǒng)的url:
查詢 /user/query?name=tom GET
詳情 /user/query?id=1 GET
創(chuàng)建 /user/create?name=tom POST
修改 /user/update?id=1&name=jerry POST
刪除 /user/delete?id=1 GET
restful風(fēng)格的url:
查詢 /user?name=tom GET
詳情 /user/1 GET
創(chuàng)建 /user POST
修改 /user/1 PUT
刪除 /user/1 DELETE
經(jīng)過(guò)上面的幾組對(duì)比,我們可以得出結(jié)論:
傳統(tǒng)的URL是通過(guò)鏈接表示行為,而restful風(fēng)格是用URL描述資源
使用HTTP方法描述行為,使用HTTP狀態(tài)碼表示不同的結(jié)果。在傳統(tǒng)的請(qǐng)求方式上,我們一般會(huì)采用POST和GET方法來(lái)發(fā)送請(qǐng)求,而在restful風(fēng)格中它使用GET表示查詢請(qǐng)求,POST表示增加的請(qǐng)求,PUT表示修改的請(qǐng)求,DELETE表示刪除的請(qǐng)求。在傳統(tǒng)的請(qǐng)求中,無(wú)論你請(qǐng)求的成功與否,它都會(huì)給你返回一大串的json格式的數(shù)據(jù)來(lái)描述請(qǐng)求的結(jié)果,但是在restful風(fēng)格中,它對(duì)不同的結(jié)果都有不同的狀態(tài)碼來(lái)描述不同的結(jié)果。
使用json格式的數(shù)據(jù)來(lái)交互。在傳統(tǒng)的URL中,我們常常會(huì)將有些信息通過(guò)鏈接的形式發(fā)送給服務(wù)器,但是在restful風(fēng)格中這些傳遞給服務(wù)器或者傳給前臺(tái)的數(shù)據(jù)都會(huì)使用json格式的數(shù)據(jù)來(lái)傳遞。
最后一點(diǎn),要強(qiáng)調(diào)的是,restful是中風(fēng)格,并不是強(qiáng)制要求的規(guī)范。
二,使用Sring MVC的restful風(fēng)格開(kāi)發(fā)用戶請(qǐng)求的案例
接下來(lái),讓我們用實(shí)例來(lái)體驗(yàn)一下restful風(fēng)格。
首先,我們創(chuàng)建maven項(xiàng)目。
在src/main/java包下創(chuàng)建一個(gè)包,然后在這個(gè)包下床架一個(gè)controller類(lèi)
import java.util.ArrayList; import java.util.List; import org.apache.commons.lang.builder.ReflectionToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; import org.springframework.data.domain.Pageable; import org.springframework.data.web.PageableDefault; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import cn.shinelon.vo.User; import cn.shinelon.vo.UserQueryCondition; /** * @author Shinelon * */ @RestController public class UserController { @RequestMapping(value="/user",method=RequestMethod.GET) //required表示是否是必須要填的,false表示不需要,然后defaultValue表示默認(rèn)值 // public List<User> query(@RequestParam(required=false,defaultValue="jerrty") String username){ //當(dāng)前臺(tái)需要傳來(lái)多個(gè)值的時(shí)候,可以把參數(shù)封裝到一個(gè)對(duì)象中 //pageable表示分頁(yè)的信息,同樣的,如果前臺(tái)沒(méi)有傳來(lái)數(shù)據(jù),也可以給分頁(yè)信息來(lái)設(shè)置默認(rèn)值 public List<User> query(UserQueryCondition condition,@PageableDefault(size=15,page=3,sort="username,asc") Pageable pageable){ System.out.println(pageable.getPageSize()); System.out.println(pageable.getPageNumber()); System.out.println(pageable.getSort()); //使用反射來(lái)輸出查詢的參數(shù) System.out.println(ReflectionToStringBuilder.toString(condition,ToStringStyle.MULTI_LINE_STYLE)); List<User> list=new ArrayList<User>(); list.add(new User()); list.add(new User()); list.add(new User()); return list; } }
先介紹一下上面的代碼的含義,我們使用@RestController注解來(lái)聲明這個(gè)類(lèi)是使用了restful風(fēng)格的controller控制層,@RequestMapping這個(gè)注解相信大家都不陌生吧,它的第一個(gè)屬性表示你的請(qǐng)求路徑,第二個(gè)是你的請(qǐng)求的方法,如果在一個(gè)方法前面加入這個(gè)注解,我們就可以通過(guò)這個(gè)注解上表示的URL來(lái)請(qǐng)求到這個(gè)方法的操作以及返回結(jié)果。
//required表示是否是必須要填的,false表示不需要,然后defaultValue表示默認(rèn)值 // public List<User> query(@RequestParam(required=false,defaultValue="jerrty") String username){
在這段代碼中,我們可以使用@RequestParam注解來(lái)顯示的指明傳遞的參數(shù),required表示是否是必須要填的,false表示不需要,然后defaultValue表示默認(rèn)值,表示如果前臺(tái)沒(méi)有傳遞這個(gè)參數(shù),就使用這個(gè)默認(rèn)值。當(dāng)然,如果你前臺(tái)傳遞的參數(shù)和你的方法參數(shù)一樣的話就不用指明這個(gè)注釋了,它會(huì)自動(dòng)的給這個(gè)方法傳遞參數(shù),這也體現(xiàn)了spring的強(qiáng)大之處。
//當(dāng)前臺(tái)需要傳來(lái)多個(gè)值的時(shí)候,可以把參數(shù)封裝到一個(gè)對(duì)象中 //pageable表示分頁(yè)的信息,同樣的,如果前臺(tái)沒(méi)有傳來(lái)數(shù)據(jù),也可以給分頁(yè)信息來(lái)設(shè)置默認(rèn)值 public List<User> query(UserQueryCondition condition,@PageableDefault(size=15,page=3,sort="username,asc") Pageable pageable){
在看上面這段代碼,如果前臺(tái)傳遞來(lái)幾個(gè)參數(shù),那很好辦,我們只要給這個(gè)方法多幾個(gè)形參就可以,但是如果前臺(tái)傳遞來(lái)大量的信息,我們還會(huì)創(chuàng)建那么多的參數(shù)嗎?那樣恐怕會(huì)使你的代碼特別難看吧。這時(shí),我們可以將多個(gè)參數(shù)封裝到一個(gè)對(duì)象中,而在這個(gè)方法中傳遞這個(gè)對(duì)象的一個(gè)引用,如上面的代碼我們將查詢的請(qǐng)求全部封裝到了一個(gè)UserQueryCondition 的類(lèi)中。這樣就化簡(jiǎn)了代碼,也讓更加有了層次性。
我們?cè)趕rc/main/java路徑下創(chuàng)建一個(gè)VO層,然后創(chuàng)建UserQueryCondition 類(lèi)如下:
public class UserQueryCondition { public String username; public String sex; public int age; public String address; //省略set,get方法 }
在VO層,另一個(gè)Javabean是USER類(lèi),代碼如下:
public class User { public String username; public String password; //省略set,get方法 }
我們接著上面的講解,Pageable這個(gè)類(lèi)可以傳遞分頁(yè)的信息,比如每頁(yè)的信息數(shù)量,頁(yè)數(shù)等等信息,@PageableDefault(size=15,page=3,sort=”username,asc”) 這個(gè)參數(shù)表示分頁(yè)信息的默認(rèn)值,如果我們不傳遞分頁(yè)的信息,那么它將默認(rèn)每頁(yè)的大小size為15,頁(yè)數(shù)page為第三頁(yè),分類(lèi)的方式是使用username,采用asc升序的方式排列。
解釋完上面的代碼我們就可以開(kāi)始測(cè)試,相信大家都知道,后臺(tái)開(kāi)發(fā)就頭疼的就是測(cè)試,你每次測(cè)試都要啟動(dòng)服務(wù)器,這樣很浪費(fèi)時(shí)間,不過(guò)在這里我們可以采用spring提供的測(cè)試的平臺(tái),我們就可以不用每次去啟動(dòng)服務(wù)器了,哈哈哈,體會(huì)到了spring的強(qiáng)大之處了吧。話不多說(shuō),先看代碼。
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.MediaType; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; /** * @author Shinelon * */ @RunWith(SpringRunner.class) @SpringBootTest public class UserControllerTest { @Autowired private WebApplicationContext wac; private MockMvc mockMvc; @Before public void setup() { mockMvc=MockMvcBuilders.webAppContextSetup(wac).build(); } @Test public void whenQuerySuccess() throws Exception { // mockMvc.perform(MockMvcRequestBuilders.get("/user") // .contentType(MediaType.APPLICATION_JSON_UTF8)) // .andExpect(MockMvcResultMatchers.status().isOk()) // .andExpect(MockMvcResultMatchers.jsonPath("$.length()").value(3)); //在STS里的偏好設(shè)置中設(shè)置了這幾個(gè)類(lèi),所以可以自動(dòng)引入其靜態(tài)方法 mockMvc.perform(get("/user") // .param("username", "shinelon") .param("username", "shinelon") .param("sex", "male") .param("age", "18") .param("address", "北京市") .param("size", "15") //分頁(yè)的信息 .param("page", "3") .param("sort", "age,desc") //按照年齡升序排列 .contentType(MediaType.APPLICATION_JSON_UTF8)) .andExpect(status().isOk()) .andExpect(jsonPath("$.length()").value(3)); } }
在這里,我們使用springboot,@SpringBootTest注解聲明下面這個(gè)類(lèi)為springboot的測(cè)試類(lèi),我們可以去src/test/java這個(gè)路徑下去創(chuàng)建這個(gè)類(lèi),@Before這個(gè)注解是前置聲明,表示每次測(cè)試之前都會(huì)先執(zhí)行這段代碼,在這里,我們創(chuàng)建了mockMvc這個(gè)來(lái),這是spring提供的一種測(cè)試類(lèi),讀者可以去查查其API,這里不做詳細(xì)介紹了。
// mockMvc.perform(MockMvcRequestBuilders.get("/user") // .contentType(MediaType.APPLICATION_JSON_UTF8)) // .andExpect(MockMvcResultMatchers.status().isOk()) // .andExpect(MockMvcResultMatchers.jsonPath("$.length()").value(3));
這里,介紹一下這段注釋掉的代碼,和下面的那段代碼作用相同,不過(guò)下面的代碼更加簡(jiǎn)潔,我們可以在eclipse中的偏好設(shè)置favorite中設(shè)置MockMvcRequestBuilders,MockMvcResultMatchers這兩個(gè)類(lèi)型的設(shè)置,這樣就可以化簡(jiǎn)代碼,eclipse將會(huì)自動(dòng)加入其靜態(tài)方法,這里讀者可能看不出來(lái)是什么意思,自己試一下就會(huì)感受到了,不會(huì)的可以留言哈。
mockMvc.perform(get("/user") // .param("username", "shinelon") .param("username", "shinelon") .param("sex", "male") .param("age", "18") .param("address", "北京市") .param("size", "15") //分頁(yè)的信息 .param("page", "3") .param("sort", "age,desc") //按照年齡升序排列 .contentType(MediaType.APPLICATION_JSON_UTF8)) .andExpect(status().isOk()) .andExpect(jsonPath("$.length()").value(3));
最后,上面的代碼時(shí)我們測(cè)試的參數(shù),比如username,age,還有分頁(yè)的信息等等,這類(lèi)似與我們前臺(tái)URL或者表單中提交到后臺(tái)的參數(shù)。這里還有一點(diǎn)要介紹的是.andExpect(jsonPath(“$.length()”).value(3)),這段代碼表示前臺(tái)期望返回的是一個(gè)json格式的數(shù)據(jù)其長(zhǎng)度為3,這種寫(xiě)法讀者可以去github上搜索jsonPath這個(gè)關(guān)鍵字,上面有官方的詳細(xì)介紹文檔。
最后我們啟動(dòng)程序,看控制臺(tái)輸出的結(jié)果,下面是控制臺(tái)打印的主要信息。怎么樣,是不是感受到了restful的風(fēng)格,自己動(dòng)手試試會(huì)更加深有體會(huì)。
15 3 age: DESC cn.shinelon.vo.UserQueryCondition@ee96866[ username=shinelon sex=male age=18 address=北京市 ]
總結(jié)
以上就是本文關(guān)于SpringMVC開(kāi)發(fā)restful API之用戶查詢代碼詳解的全部?jī)?nèi)容,希望對(duì)大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站:springmvc接收jquery提交的數(shù)組數(shù)據(jù)代碼分享、Spring MVC實(shí)現(xiàn)的登錄攔截器代碼分享、SpringMVC使用MultipartFile 實(shí)現(xiàn)異步上傳方法介紹等,有什么問(wèn)題可以隨時(shí)留言,小編會(huì)及時(shí)回復(fù)大家的。感謝朋友們對(duì)本站的支持!
- springmvc使用REST出現(xiàn):Request?method?'PUT'?not?supported問(wèn)題
- 如何利用Spring?MVC實(shí)現(xiàn)RESTful風(fēng)格
- springmvc Rest風(fēng)格介紹及實(shí)現(xiàn)代碼示例
- Spring MVC利用Swagger2如何構(gòu)建動(dòng)態(tài)RESTful API詳解
- SpringMVC Restful api接口實(shí)現(xiàn)的代碼
- SpringMVC數(shù)據(jù)頁(yè)響應(yīng)ModelAndView實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)
- Spring MVC 文件、cookies的接收 與REST響應(yīng)詳解
相關(guān)文章
rabbitmq使用springboot實(shí)現(xiàn)direct模式(最新推薦)
這篇文章主要介紹了rabbitmq使用springboot實(shí)現(xiàn)direct模式,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07Java隨機(jī)生成驗(yàn)證碼的實(shí)現(xiàn)示例
這篇文章主要介紹Java隨機(jī)生成驗(yàn)證碼的實(shí)現(xiàn)方法,文中有相關(guān)的實(shí)現(xiàn)代碼供大家參考,具有一定的參考價(jià)值,需要的朋友可以參考下2023-08-08利用Java多線程技術(shù)導(dǎo)入數(shù)據(jù)到Elasticsearch的方法步驟
這篇文章主要介紹了利用Java多線程技術(shù)導(dǎo)入數(shù)據(jù)到Elasticsearch的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07springboot配置nacos的實(shí)現(xiàn)示例
本文將介紹如何在Spring?Boot中配置Nacos,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-09-09java編程實(shí)現(xiàn)屏幕截圖(截屏)代碼總結(jié)
這篇文章主要介紹了java編程實(shí)現(xiàn)屏幕截圖(截屏)代碼,結(jié)合3個(gè)實(shí)例總結(jié)分析了Java截屏?xí)r頁(yè)面抓取及圖片保存的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11java實(shí)現(xiàn)超市商品庫(kù)存管理平臺(tái)
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)超市商品庫(kù)存管理平臺(tái),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-10-10Java判斷字符串是否是整數(shù)或者浮點(diǎn)數(shù)的方法
今天小編就為大家分享一篇Java判斷字符串是否是整數(shù)或者浮點(diǎn)數(shù)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-07-07Java面向?qū)ο缶幊讨^承和多態(tài)以及包的解析與使用范例
繼承就是可以直接使用前輩的屬性和方法。自然界如果沒(méi)有繼承,那一切都是處于混沌狀態(tài)。多態(tài)是同一個(gè)行為具有多個(gè)不同表現(xiàn)形式或形態(tài)的能力。多態(tài)就是同一個(gè)接口,使用不同的實(shí)例而執(zhí)行不同操作2021-11-11