Spring Boot構(gòu)建RESTful API與單元測試

Spring

首先榄棵,回顧并詳細(xì)說明一下在快速入門中使用的@Controller肴楷、@RestController辕棚、@RequestMapping注解逆粹。如果您對Spring MVC不熟悉并且還沒有嘗試過快速入門案例,建議先看一下快速入門的內(nèi)容芍锚。

  • @Controller:修飾class昔园,用來創(chuàng)建處理http請求的對象
  • @RestController:Spring4之后加入的注解,原來在@Controller中返回json需要@ResponseBody來配合闹炉,如果直接用@RestController替代@Controller就不需要再配置@ResponseBody蒿赢,默認(rèn)返回json格式。
  • @RequestMapping:配置url映射

下面我們嘗試使用Spring MVC來實現(xiàn)一組對User對象操作的RESTful API渣触,配合注釋詳細(xì)說明在Spring MVC中如何映射HTTP請求羡棵、如何傳參、如何編寫單元測試嗅钻。

** RESTful API具體設(shè)計如下:**

請求類型 URL 功能說明
GET /users 查詢用戶列表
POST /users 創(chuàng)建一個用戶
GET /users/id 根據(jù)id查詢一個用戶
PUT /users/id 根據(jù)id更新一個用戶
DELETE /users/id 根據(jù)id刪除一個用戶

User實體定義:

public class User { 
 
    private Long id; 
    private String name; 
    private Integer age; 
 
    // 省略setter和getter 
     
} 

實現(xiàn)對User對象的操作接口

 
@RestController 
@RequestMapping(value="/users")     // 通過這里配置使下面的映射都在/users下 
public class UserController { 
 
    // 創(chuàng)建線程安全的Map 
    static Map<Long, User> users = Collections.synchronizedMap(new HashMap<Long, User>()); 
 
    @RequestMapping(value="/", method=RequestMethod.GET) 
    public List<User> getUserList() { 
        // 處理"/users/"的GET請求皂冰,用來獲取用戶列表 
        // 還可以通過@RequestParam從頁面中傳遞參數(shù)來進(jìn)行查詢條件或者翻頁信息的傳遞 
        List<User> r = new ArrayList<User>(users.values()); 
        return r; 
    } 
 
    @RequestMapping(value="/", method=RequestMethod.POST) 
    public String postUser(@ModelAttribute User user) { 
        // 處理"/users/"的POST請求,用來創(chuàng)建User 
        // 除了@ModelAttribute綁定參數(shù)之外养篓,還可以通過@RequestParam從頁面中傳遞參數(shù) 
        users.put(user.getId(), user); 
        return "success"; 
    } 
 
    @RequestMapping(value="/{id}", method=RequestMethod.GET) 
    public User getUser(@PathVariable Long id) { 
        // 處理"/users/{id}"的GET請求秃流,用來獲取url中id值的User信息 
        // url中的id可通過@PathVariable綁定到函數(shù)的參數(shù)中 
        return users.get(id); 
    } 
 
    @RequestMapping(value="/{id}", method=RequestMethod.PUT) 
    public String putUser(@PathVariable Long id, @ModelAttribute User user) { 
        // 處理"/users/{id}"的PUT請求,用來更新User信息 
        User u = users.get(id); 
        u.setName(user.getName()); 
        u.setAge(user.getAge()); 
        users.put(id, u); 
        return "success"; 
    } 
 
    @RequestMapping(value="/{id}", method=RequestMethod.DELETE) 
    public String deleteUser(@PathVariable Long id) { 
        // 處理"/users/{id}"的DELETE請求柳弄,用來刪除User 
        users.remove(id); 
        return "success"; 
    } 
 
} 
 

下面針對該Controller編寫測試用例驗證正確性舶胀,具體如下。當(dāng)然也可以通過瀏覽器插件等進(jìn)行請求提交驗證碧注。

 
@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = MockServletContext.class) 
@WebAppConfiguration 
public class ApplicationTests { 
 
    private MockMvc mvc; 
 
    @Before 
    public void setUp() throws Exception { 
        mvc = MockMvcBuilders.standaloneSetup(new UserController()).build(); 
    } 
 
    @Test 
    public void testUserController() throws Exception { 
        // 測試UserController 
        RequestBuilder request = null; 
 
        // 1嚣伐、get查一下user列表,應(yīng)該為空 
        request = get("/users/"); 
        mvc.perform(request) 
                .andExpect(status().isOk()) 
                .andExpect(content().string(equalTo("[]"))); 
 
        // 2萍丐、post提交一個user 
        request = post("/users/") 
                .param("id", "1") 
                .param("name", "測試大師") 
                .param("age", "20"); 
        mvc.perform(request) 
                .andExpect(content().string(equalTo("success"))); 
 
        // 3惑芭、get獲取user列表遗座,應(yīng)該有剛才插入的數(shù)據(jù) 
        request = get("/users/"); 
        mvc.perform(request) 
                .andExpect(status().isOk()) 
                .andExpect(content().string(equalTo("[{\"id\":1,\"name\":\"測試大師\",\"age\":20}]"))); 
 
        // 4、put修改id為1的user 
        request = put("/users/1") 
                .param("name", "測試終極大師") 
                .param("age", "30"); 
        mvc.perform(request) 
                .andExpect(content().string(equalTo("success"))); 
 
        // 5、get一個id為1的user 
        request = get("/users/1"); 
        mvc.perform(request) 
                .andExpect(content().string(equalTo("{\"id\":1,\"name\":\"測試終極大師\",\"age\":30}"))); 
 
        // 6假消、del刪除id為1的user 
        request = delete("/users/1"); 
        mvc.perform(request) 
                .andExpect(content().string(equalTo("success"))); 
 
        // 7、get查一下user列表,應(yīng)該為空 
        request = get("/users/"); 
        mvc.perform(request) 
                .andExpect(status().isOk()) 
                .andExpect(content().string(equalTo("[]"))); 
 
    } 
 
} 
 

至此,我們通過引入web模塊(沒有做其他的任何配置)弥臼,就可以輕松利用Spring MVC的功能,以非常簡潔的代碼完成了對User對象的RESTful API的創(chuàng)建以及單元測試的編寫舱呻。其中同時介紹了Spring MVC中最為常用的幾個核心注解:@Controller,@RestController,RequestMapping以及一些參數(shù)綁定的注解:@PathVariable,@ModelAttribute,@RequestParam等醋火。

完整案例

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末悠汽,一起剝皮案震驚了整個濱河市箱吕,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌柿冲,老刑警劉巖茬高,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異假抄,居然都是意外死亡怎栽,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進(jìn)店門宿饱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來熏瞄,“玉大人,你說我怎么就攤上這事谬以∏恳” “怎么了?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵为黎,是天一觀的道長邮丰。 經(jīng)常有香客問我,道長铭乾,這世上最難降的妖魔是什么剪廉? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮炕檩,結(jié)果婚禮上斗蒋,老公的妹妹穿的比我還像新娘。我一直安慰自己笛质,他們只是感情好泉沾,可當(dāng)我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著经瓷,像睡著了一般爆哑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上舆吮,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天揭朝,我揣著相機與錄音队贱,去河邊找鬼。 笑死潭袱,一個胖子當(dāng)著我的面吹牛柱嫌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播屯换,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼编丘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了彤悔?” 一聲冷哼從身側(cè)響起嘉抓,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎晕窑,沒想到半個月后抑片,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡杨赤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年敞斋,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片疾牲。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡植捎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出阳柔,到底是詐尸還是另有隱情焰枢,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布盔沫,位于F島的核電站医咨,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏架诞。R本人自食惡果不足惜拟淮,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望谴忧。 院中可真熱鬧很泊,春花似錦、人聲如沸沾谓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽均驶。三九已至昏兆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間妇穴,已是汗流浹背爬虱。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工隶债, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人跑筝。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓死讹,卻偏偏與公主長得像,于是被迫代替她去往敵國和親曲梗。 傳聞我的和親對象是個殘疾皇子赞警,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容