美文网首页Spring Boot&Spring CloudSpring boot
Spring Boot-构建一个复杂的RESTful API及单

Spring Boot-构建一个复杂的RESTful API及单

作者: 蓝色的咖啡 | 来源:发表于2016-09-18 11:58 被阅读4558次

    在前面的快速入门教程中,我们利用5分钟构建了一个非常简单的RESTful Webservice,现在我们来利用Spring Boot来构建一个复杂一点的RestFul API。

    关于RESTful API如何设计,大家可以自行去阮一峰的博客学习一下。话说阮老师真是一个全才,感觉他都懂,程序猿楷模啊!

    我们来设计一个Book的RESTful API,如下所示:

    请求类型 URL 功能说明
    GET /books 查询书籍列表
    POST /books 创建书籍
    GET /books/id 根据ID查询一本书籍
    PUT /books/id 根据ID更新一本书籍
    DELETE /books/id 根据ID删除一本书籍

    Book的实体类定义如下:

    public class Book {
    
        private Long bookId;
        private String title;
        private String author;
    
        //getter/setter方法省略
    }
    

    针对Book资源操作的RESTful接口实现如下:

    @RestController
    @RequestMapping(value="/books")
    public class BookController {
    
        // 创建线程安全的Map
        static Map<Long, Book> books = Collections.synchronizedMap(new HashMap<Long, Book>());
    
        @RequestMapping(value="/", method= RequestMethod.GET)
        public List<Book> getUserList() {
            // 处理"/books/"的GET请求,用来获取图书列表
            // 还可以通过@RequestParam传递参数来进行查询条件或者翻页信息的传递
            List<Book> r = new ArrayList<Book>(books.values());
            return r;
        }
    
        @RequestMapping(value="/", method=RequestMethod.POST,produces = "application/json")
        public String createBook(@RequestBody Book book) {
            // 处理"/books/"的POST请求,用来创建User
            // 除了@ModelAttribute绑定参数之外,还可以通过@RequestParam从页面中传递参数
            books.put(book.getBookId(), book);
            return "success";
        }
    
        @RequestMapping(value="/{bookId}", method=RequestMethod.GET)
        public Book getBook(@PathVariable Long bookId) {
            // 处理"/books/{id}"的GET请求,用来获取url中id值的Book信息
            // url中的id可通过@PathVariable绑定到函数的参数中
            return books.get(bookId);
        }
    
        @RequestMapping(value="/{bookId}", method=RequestMethod.PUT)
        public String putBook(@PathVariable Long bookId, @RequestBody Book book) {
            // 处理"/books/{bookId}"的PUT请求,用来更新Book信息
            Book b = books.get(bookId);
            b.setTitile(book.getTitile());
            b.setAuthor(book.getAuthor());
            books.put(bookId, b);
            return "success";
        }
    
        @RequestMapping(value="/{bookId}", method=RequestMethod.DELETE)
        public String deleteBook(@PathVariable Long bookId) {
            // 处理"/books/{bookId}"的DELETE请求,用来删除Book
            books.remove(bookId);
            return "success";
        }
    }
    

    单元测试

    之前我们在入门教程中使用了Postman来进行测试,现在我们使用Spring自家的MockMvc框架来写单元测试,MockMvc的使用很简单,更详细的用法大家可以自行Google或百度。

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = MockServletContext.class)
    @WebAppConfiguration
    public class TestBookController {
    
        private MockMvc mvc;
    
        private RequestBuilder request = null;
    
    
        @Before
        public void setUp() throws Exception {
            mvc = MockMvcBuilders.standaloneSetup(new BookController()).build();
            request = null;
        }
    
        public void testGet() throws Exception{
            request = get("/books/");
            mvc.perform(request)
                    .andExpect(status().isOk())
                    .andExpect(content().string(equalTo("[]")));
        }
    
        public void testPost() throws Exception{
            Book book = new Book();
            book.setBookId(Long.parseLong("1"));
            book.setTitile("Spring Boot Tutorial");
            book.setAuthor("bluecoffee");
            ObjectMapper objectMapper = new ObjectMapper();
            String jsonBook = objectMapper.writeValueAsString(book);
    
            request = post("/books/")
                    .contentType(MediaType.APPLICATION_JSON)
                    .content(jsonBook.getBytes());
    
            mvc.perform(request)
                    .andExpect(status().isOk())
                    .andExpect(content().string(equalTo("success")));
    
            String respStr = mvc.perform(get("/books/"))
                    .andExpect(status().isOk())
                    .andExpect(content().string(equalTo("[" + jsonBook + "]")))
                    .andReturn().getResponse().getContentAsString();
            System.out.println("testPost.resp:"+respStr);
        }
    
        public void testPut() throws Exception{
            Book book = new Book();
            book.setBookId(Long.parseLong("1"));
            book.setTitile("Spring Boot学习教程");
            book.setAuthor("Alex Qian");
            ObjectMapper objectMapper = new ObjectMapper();
            String jsonBook = objectMapper.writeValueAsString(book);
    
            request = put("/books/" + book.getBookId())
                    .contentType(MediaType.APPLICATION_JSON)
                    .content(jsonBook.getBytes());
    
            mvc.perform(request)
                    .andExpect(status().isOk())
                    .andExpect(content().string(equalTo("success")));
    
            String respStr = mvc.perform(get("/books/"+book.getBookId()))
                    .andExpect(status().isOk())
                    .andExpect(content().string(equalTo(jsonBook)))
                    .andReturn().getResponse().getContentAsString();
            System.out.println("testPut.resp:"+respStr);
        }
    
        public void testDelete() throws Exception{
            request = delete("/books/1");
            mvc.perform(request)
                    .andExpect(status().isOk())
                    .andExpect(content().string(equalTo("success")));
    
            String respStr = mvc.perform(get("/books/"))
                    .andExpect(status().isOk())
                    .andExpect(content().string(equalTo("[]")))
                    .andReturn().getResponse().getContentAsString();
            System.out.println("testDelete.resp:"+respStr);
    
        }
    
        @Test
        public void testSuite() throws Exception{
            this.testGet();//获取一本书籍
            this.testPost();//创建一本书籍
            this.testPut();//更新一本书籍
            this.testDelete();//删除一本书籍
        }
    }
    

    小结

    在这次教程里面,我们仅引入Spring Boot的web模块,并且没有引入任何配置文件,就构建了一个较完整的RESTful API,文中还简要介绍了@PathVariable,@RequestBody,@RequestParam等参数绑定注解的用法,更多的用法大家可以自行去网上查询资料。

    完整代码戳这里: Chapter 3-1-1 - 构建复杂RESTful API及单元测试

    相关文章

      网友评论

      • wdom:要写这么代码,小白哭了,呜呜,其实有很多测试REST API工具比如Wisdom RESTClient
        https://github.com/Wisdom-Projects/rest-client
        蓝色的咖啡:@maspring 谢谢推荐,我去关注看下
      • 417f78ce376d:需要导入哪些包?很多方法都提示说不存在
        417f78ce376d:@蓝色的咖啡 我测试了下,mvc.perform一直抛出空指针异常,但是实际mvc和request都不是空对象,知道啥原因吗
        蓝色的咖啡:@Sun_翁航 你可以去码云下载源代码,所有依赖都在maven里管理

      本文标题:Spring Boot-构建一个复杂的RESTful API及单

      本文链接:https://www.haomeiwen.com/subject/hfawettx.html