当前位置: 移动技术网 > IT编程>开发语言>Java > 详解Spring Boot实战之Restful API的构建

详解Spring Boot实战之Restful API的构建

2019年07月19日  | 移动技术网IT编程  | 我要评论

上一篇文章讲解了通过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的实现很简单,就是简单的封装了articlemapper的操作,articlemapper的内容大家可以参考上一篇的文章,articleservice的实现类如下:

@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,就可以看到如下的结果:

articleserviceimpl这个类是一个很普通的类,只有一个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 接口,下篇文章我们会介绍另外一种方式来访问,有兴趣的可以继续关注一下。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网