Spring Boot实战:Restful API的构建

  上一篇作品讲解了通过Spring
boot与JdbcTemplate、JPA和MyBatis的合并,实现对数据库的走访。前天重要给我们享受一下怎么样通过Spring
boot向前者重回数据。

  在近日的开支流程中,为了最大程度实现上下端的分离,平日后端接口只提供数据接口,由前端通过Ajax请求从后端获取数据并开展渲染再突显给用户。我们用的最多的法子就是后端会回到给前端一个JSON字符串,前端解析JSON字符串生成JavaScript的目的,然后再做拍卖。本文就来演示一下Spring
boot如何兑现这种情势,本文重点会讲课怎么着规划一个Restful的API,并由此Spring
boot来贯彻相关的API。可是,为了我们更好的问询Restful风格的API,我们先规划一个价值观的数据重临接口,这样我们可以对照着来了解。

一、非Restful接口的协理

  我们这里以作品列表为例,实现一个回去作品列表的接口,代码如下:

@Controller
@RequestMapping("/article")
public class ArticleController {

    @Autowired
    private ArticleService articleService;

    @RequestMapping("/list.json")
    @ResponseBody
    public List<Article> listArticles(String title, Integer pageSize, Integer pageNum) {
        if (pageSize == null) {
            pageSize = 10;
        }
        if (pageNum == null) {
            pageNum = 1;
        }
        int offset = (pageNum - 1) * pageSize;
        return articleService.getArticles(title, 1L, offset, pageSize);
    }
}

  那多少个ArticleService(Service)的兑现很简短,就是简单的包装了ArticleMapper的操作,ArticleMapper的始末我们可以参见上一篇的著作,Article瑟维斯(Service)(Service)的实现类如下:

@Service
public class ArticleServiceImpl implements ArticleService {

    @Autowired
    private ArticleMapper articleMapper;

    @Override
    public Long saveArticle(@RequestBody Article article) {
        return articleMapper.insertArticle(article);
    }

    @Override
    public List<Article> getArticles(String title,Long userId,int offset,int pageSize) {
        Article article = new Article();
        article.setTitle(title);
        article.setUserId(userId);
        return articleMapper.queryArticlesByPage(article,offset,pageSize);
    }

    @Override
    public Article getById(Long id) {
        return articleMapper.queryById(id);
    }

    @Override
    public void updateArticle(Article article) {
        article.setUpdateTime(new Date());
        articleMapper.updateArticleById(article);
    }
}

  运行Application.java那一个类,然后访问:http://locahost:8080/article/list.json,就可以看到如下的结果:

图片 1

  Article瑟维斯(Service)(Service)Impl这个类是一个很平凡的类,只有一个Spring的笺注@Service,标识为一个bean以便于通过Spring
IoC容器来保管。大家再来看看ArticleController那些类,其实用过Spring
MVC的人相应都如数家珍这么些讲明,这里大概解释一下:

  @Controller 标识一个类为控制器。

  @RequestMapping URL的映射。

  @ResponseBody 再次回到结果转换为JSON字符串。

  @RequestBody 表示收到JSON格式字符串参数。

  通过这一个两个表明,我们就能轻轻松松的落实通过URL给前端再次来到JSON格式数据的效益。然则我们自然有些纳闷,这不都是Spring
MVC的东西呢?跟Spring boot有怎么样关联?其实Spring
boot的法力就是为我们省去了布置的进程,其他效用实在都是Spring与Spring
MVC来为我们提供的,我们应该记得Spring
boot通过各个starter来为大家提供自动配置的服务,我们的工程里面在此之前引入过这多少个依靠:

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
</dependency>

  这多少个是怀有Spring
boot的web工程都亟需引入的jar包,也就是说只即使Spring
boot的web的工程,都默认补助上述的效应。这里我们更是发现,通过Spring
boot来开发web工程,确实为大家省了好多部署的工作。

 

二、Restful API设计

  好了,我们明日再来看看怎么样兑现Restful
API。实际上Restful本身不是一项什么奥秘的技能,而只是一种编程风格,或者说是一种设计风格。在价值观的http接口设计中,大家一般只行使了get和post六个办法,然后用我们协调定义的词汇来代表不同的操作,比如上边查询著作的接口,我们定义了article/list.json来代表查询著作列表,可以通过get或者post方法来做客。而Restful
API的设计则经过HTTP的措施来表示CRUD相关的操作。因而,除了get和post方法外,还会用到任何的HTTP方法,如PUT、DELETE、HEAD等,通过不同的HTTP方法来表示不同含义的操作。下边是自我设计的一组对著作的增删改查的Restful
API:

接口URL HTTP方法 接口说明
 /article  POST  保存文章
 /article/{id}  GET  查询文章列表
 /article/{id}  DELETE  删除文章
 /article/{id}  PUT  更新文章信息

   这里可以见见,URL仅仅是标识资源的路劲,而具体的一言一行由HTTP方法来指定。

 

三、Restful API实现

  现在大家再来看看怎么着落实地方的接口,其他就不多说,直接看代码:

@RestController
@RequestMapping("/rest")
public class ArticleRestController {

    @Autowired
    private ArticleService articleService;

    @RequestMapping(value = "/article", method = POST, produces = "application/json")
    public WebResponse<Map<String, Object>> saveArticle(@RequestBody Article article) {
        article.setUserId(1L);
        articleService.saveArticle(article);
        Map<String, Object> ret = new HashMap<>();
        ret.put("id", article.getId());
        WebResponse<Map<String, Object>> response = WebResponse.getSuccessResponse(ret);
        return response;
    }

    @RequestMapping(value = "/article/{id}", method = DELETE, produces = "application/json")
    public WebResponse<?> deleteArticle(@PathVariable Long id) {
        Article article = articleService.getById(id);
        article.setStatus(-1);
        articleService.updateArticle(article);
        WebResponse<Object> response = WebResponse.getSuccessResponse(null);
        return response;
    }

    @RequestMapping(value = "/article/{id}", method = PUT, produces = "application/json")
    public WebResponse<Object> updateArticle(@PathVariable Long id, @RequestBody Article article) {
        article.setId(id);
        articleService.updateArticle(article);
        WebResponse<Object> response = WebResponse.getSuccessResponse(null);
        return response;
    }

    @RequestMapping(value = "/article/{id}", method = GET, produces = "application/json")
    public WebResponse<Article> getArticle(@PathVariable Long id) {
        Article article = articleService.getById(id);
        WebResponse<Article> response = WebResponse.getSuccessResponse(article);
        return response;
    }
}

  我们再来分析一下那段代码,这段代码和事先代码的界别在于:

  (1)我们运用的是@RestController这一个注明,而不是@Controller,不过这么些声明同样不是Spring
boot提供的,而是Spring MVC4中的提供的诠释,表示一个支撑Restful的控制器。

  (2)这多少个类中有两个URL映射是同等的,即都是/article/{id},这在@Controller标识的类中是不容许出现的。这里的可以通过method来进展区分,produces的功能是象征回去结果的门类是JSON。

  (3)@PathVariable那几个讲明,也是Spring
MVC提供的,其效果是象征该变量的值是从访问路径中取得。

  所以看来看去,这多少个代码仍旧跟Spring boot没太多的涉嫌,Spring
boot也只有是提供自动配置的效益,这也是Spring
boot用起来很舒心的一个很首要的由来,因为它的侵入性非常丰盛小,你基本感觉不到它的留存。

 

四、测试

  代码写完了,怎么测试?除了GET的主意外,都无法平昔通过浏览器来拜会,当然,我们可以直接通过postman来发送各样http请求。然则我要么相比较匡助通过单元测试类来测试各种艺术。这里大家就经过Junit来测试各类艺术:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class)
public class ArticleControllerTest {

    @Autowired
    private ArticleRestController restController;

    private MockMvc mvc;

    @Before
    public void setUp() throws Exception {
        mvc = MockMvcBuilders.standaloneSetup(restController).build();
    }

    @Test
    public void testAddArticle() throws Exception {
        Article article = new Article();
        article.setTitle("测试文章000000");
        article.setType(1);
        article.setStatus(2);
        article.setSummary("这是一篇测试文章");
        Gson gosn = new Gson();
        RequestBuilder builder = MockMvcRequestBuilders
                .post("/rest/article")
                .accept(MediaType.APPLICATION_JSON)
                .contentType(MediaType.APPLICATION_JSON_UTF8)
                .content(gosn.toJson(article));

        MvcResult result = mvc.perform(builder).andReturn();
        System.out.println(result.getResponse().getContentAsString());
    }

    @Test
    public void testUpdateArticle() throws Exception {
        Article article = new Article();
        article.setTitle("更新测试文章");
        article.setType(1);
        article.setStatus(2);
        article.setSummary("这是一篇更新测试文章");
        Gson gosn = new Gson();
        RequestBuilder builder = MockMvcRequestBuilders
                .put("/rest/article/1")
                .accept(MediaType.APPLICATION_JSON)
                .contentType(MediaType.APPLICATION_JSON_UTF8)
                .content(gosn.toJson(article));
        MvcResult result = mvc.perform(builder).andReturn();
    }

    @Test
    public void testQueryArticle() throws Exception {
        RequestBuilder builder = MockMvcRequestBuilders
                .get("/rest/article/1")
                .accept(MediaType.APPLICATION_JSON)
                .contentType(MediaType.APPLICATION_JSON_UTF8);
        MvcResult result = mvc.perform(builder).andReturn();
        System.out.println(result.getResponse().getContentAsString());
    }

    @Test
    public void testDeleteArticle() throws Exception {
        RequestBuilder builder = MockMvcRequestBuilders
                .delete("/rest/article/1")
                .accept(MediaType.APPLICATION_JSON)
                .contentType(MediaType.APPLICATION_JSON_UTF8);
        MvcResult result = mvc.perform(builder).andReturn();
    }
}

  执行结果这里就不给我们贴了,大家有趣味的话可以自己尝试一下。整个类要表明的点依旧很少,首要这几个东西都与Spring
boot没提到,协理这些操作的因由或者上一篇著作中涉嫌的引入对应的starter:

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
</dependency>

  因为要举行HTTP请求,所以这边运用了MockMvc,ArticleRestController通过注入的办法实例化,不可以间接new,否则ArticleRestController就不可以透过Spring
IoC容器来保管,因此其借助的别样类也无法正常注入。通过MockMvc我们就足以轻松的兑现HTTP的DELETE/PUT/POST等办法了。

五、总结

  本文讲解了一旦经过Spring
boot来促成Restful的API,其实多数事物都是Spring和Spring
MVC提供的,Spring
boot只是提供自动配置的功力。可是,正是这种活动配置,为我们缩短了众多的开销和维护工作,使大家能更为简约、高效的贯彻一个web工程,从而让大家能够越来越注意于事情本身的付出,而不需要去关心框架的东西。那篇小说中我们关系了能够透过postman和junit的办法来访问Restful
接口,下篇作品大家会介绍另外一种方法来访问,有趣味的可以连续关注一下。

 

网站地图xml地图