使用Spring Boot+JPA+MySQL光速构建RESTful风格API并使用Httpie进行测试

笔者是个懒人,但是真没想到写一个RESTful风格的API接口可以这么快。官方文档地址:https://spring.io/guides/gs/accessing-data-rest/

0. 使用Spring Initializ初始化一个Spring Boot项目

用Idea的话点击New Project选择Spring Initializ, 一路next填上项目名包名等。然后可以先选上依赖,也可以就选一个core,后面在pom文件里写。

不用Idea的话直接去https://start.spring.io,选择maven,java(你也可以试试gradle+kotlin),然后选上依赖,当然我们这里先不选,生成好后下载下来。然后再用自己的IDE或者编辑器打开。

1. 在pom文件里添加依赖

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.45</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

添加如上依赖,然后用maven sync一下把依赖包都下下来。

简单说下,spring-boot-starter-web和spring-boot-starter-test是构建web应用必须要有的;mysql-connector-java是mysql的驱动;spring-boot-starter-data-jpa是一个ORM(Object Relational Mapping)对象映射框架,简单来说就是把应用内存中的对象和数据库中的数据建立映射关系,熟悉Android的朋友们知道的GreenDao和它做的就是同一类事;spring-boot-starter-data-rest是今天的重头戏,它真的可以帮助我们以光速写一个RESTful的API接口。

2.配置数据库

开启自己的Mysql服务,create一个数据库,我这里叫cloud_mall,然后在application.properties中写上连接数据库相关的参数:

spring.jpa.hibernate.ddl-auto=create
spring.datasource.url=jdbc:mysql://localhost:3306/cloud_mall?useSSL=false
spring.datasource.username=root
spring.datasource.password=xxxx

这其中注意第一个参数,主要有以下这几种常见选择:

  • ddl-auto:create----没有表的Entity会在数据库中建表,已经有的会清空数据。

  • ddl-auto:create-drop----每次程序结束的时候会清空表。

  • ddl-auto:update----会根据Entity更新表的结构。

  • ddl-auto:validate----运行程序会校验数据与数据库的字段类型是否相同,不同会报错。

因此第一次需要创建表的时候我们用create,后面再次运行我们用update比较好。

ddl-auto:validate----运行程序会校验数据与数据库的字段类型是否相同,不同会报错

作者:万里飞鹏
来源:CSDN
原文:https://blog.csdn.net/zhangtongpeng/article/details/79609942
版权声明:本文为博主原创文章,转载请附上博文链接!

3.建一个叫Commodity的商品java bean类

@Entity
public class  Commodity {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private int category;

    private String name;

    private String subTitle;

    private String picUrl;

    private long price;

    private int stock;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSubTitle() {
        return subTitle;
    }

    public void setSubTitle(String subTitle) {
        this.subTitle = subTitle;
    }

    public int getCategory() {
        return category;
    }

    public void setCategory(int category) {
        this.category = category;
    }

    public String getPicUrl() {
        return picUrl;
    }

    public void setPicUrl(String picUrl) {
        this.picUrl = picUrl;
    }

    public long getPrice() {
        return price;
    }

    public void setPrice(long price) {
        this.price = price;
    }

    public int getStock() {
        return stock;
    }

    public void setStock(int stock) {
        this.stock = stock;
    }
}

4. 写一个继承PagingAndSortingRepository的Repository接口

@RepositoryRestResource(collectionResourceRel = "commodity", path = "commodity")
public interface CommodityRepository extends PagingAndSortingRepository<Commodity, Long>{
    List<Commodity> findByName(@Param("name") String name);
}

是的,你没看错就这么简单,写完了。先看下自己的MySql数据库commodity表有没有建好,数据结构是不是和我们写的Commodity类一样。

其中findByName是自己写的,你可以按照提示写其他的查找方法,至于剩下的CURD,统统都让spring-boot-starter-data-rest框架自己实现好了。

5.下载Httpie准备测试

这里为啥给大家推荐这个命令行软件呢?Postman和Restlet Client这些Chrome插件已经够好用了啊?确实如此,但是笔者最近迷恋上了命令行- -。命令行软件的好处就是快,不用点来点去,适合写完一个接口立马测试用,系统性的测试API肯定还是Postman这些好使。另外就是命令行可以在没有GUI服务器上直接使用。当然curl也可以,一开始我也是用curl,但是参数太多,用起来还是有点不太方便。

下载方式就不写了,见官方网站:https://httpie.org/

6. 使用POST添加数据

现在我们直接在终端输入http localhost:8080可以试一下,没用报错,但是没数据。因此我们先用POST请求加几个数据。直接输入http POST url json参数,注意string类型的直接key=value就好,整形和浮点型用key:=value。

judy:~$ http POST localhost:8080/commodity name=IPhone7 subTitle=IPhone7 price:=2588.88 stock:=12
HTTP/1.1 201 
Content-Type: application/json;charset=UTF-8
Date: Wed, 17 Oct 2018 11:39:50 GMT
Location: http://localhost:8080/commodity/3
Transfer-Encoding: chunked

{
    "_links": {
        "commodity": {
            "href": "http://localhost:8080/commodity/3"
        }, 
        "self": {
            "href": "http://localhost:8080/commodity/3"
        }
    }, 
    "category": 0, 
    "name": "IPhone7", 
    "picUrl": null, 
    "price": 2588, 
    "stock": 12, 
    "subTitle": "IPhone7"
}

可以看到返回的数据中给出了我这个IPhone7的url,以及详细属性,为了证明添加成功大家可以去数据库查一下表。

7.使用PUT替换数据

使用http PUT url json参数来替换数据,这里我要修改的是刚才POST上去的IPhone7, 因此url使用刚才POST返回的url。

judy:~$ http PUT localhost:8080/commodity/3 name=IPhone7Plus subTitle=IPhone7Plus price:=2588.88 stock:=12
HTTP/1.1 200 
Content-Type: application/json;charset=UTF-8
Date: Wed, 17 Oct 2018 11:48:31 GMT
Location: http://localhost:8080/commodity/3
Transfer-Encoding: chunked

{
    "_links": {
        "commodity": {
            "href": "http://localhost:8080/commodity/3"
        }, 
        "self": {
            "href": "http://localhost:8080/commodity/3"
        }
    }, 
    "category": 0, 
    "name": "IPhone7Plus", 
    "picUrl": null, 
    "price": 2588, 
    "stock": 12, 
    "subTitle": "IPhone7Plus"
}

可以看到返回结果是没问题的。

8.使用PATCH来修改数据

PUT和PATCH是很容易弄混的两个请求,PUT是整体替换,而PATCH只会改变部分属性。命令格式和PUT一样,只是由于我们只修改部分属性,因此只要把修改的属性放上来就行了,这里我修改了下价格。

judy:~$ http PATCH localhost:8080/commodity/3 price:=3588HTTP/1.1 200 
Content-Type: application/json;charset=UTF-8
Date: Wed, 17 Oct 2018 11:54:57 GMT
Transfer-Encoding: chunked

{
    "_links": {
        "commodity": {
            "href": "http://localhost:8080/commodity/3"
        }, 
        "self": {
            "href": "http://localhost:8080/commodity/3"
        }
    }, 
    "category": 0, 
    "name": "IPhone7Plus", 
    "picUrl": null, 
    "price": 3588, 
    "stock": 12, 
    "subTitle": "IPhone7Plus"
}

修改成功。

9.使用DELETE请求删除数据

都不用猜了,肯定是http DELETE url这样的形式,来试一下:

judy:~$ http DELETE localhost:8080/commodity/3
HTTP/1.1 204 
Date: Wed, 17 Oct 2018 11:58:21 GMT

居然什么提示也没有,别着急,去数据库查一下是不是删除成功了呢?

10.使用GET请求查找数据

GET的话是最常用的,因此可以省略不写。查找之前先用POST添加几条数据。

我们来试一下:

judy:~$ http localhost:8080/commodity
HTTP/1.1 200 
Content-Type: application/hal+json;charset=UTF-8
Date: Wed, 17 Oct 2018 11:58:46 GMT
Transfer-Encoding: chunked

{
    "_embedded": {
        "commodity": [
            {
                "_links": {
                    "commodity": {
                        "href": "http://localhost:8080/commodity/1"
                    }, 
                    "self": {
                        "href": "http://localhost:8080/commodity/1"
                    }
                }, 
                "category": 0, 
                "name": "IPhone5", 
                "picUrl": null, 
                "price": 588, 
                "stock": 10, 
                "subTitle": "IPhone5"
            }, 
            {
                "_links": {
                    "commodity": {
                        "href": "http://localhost:8080/commodity/2"
                    }, 
                    "self": {
                        "href": "http://localhost:8080/commodity/2"
                    }
                }, 
                "category": 0, 
                "name": "IPhone6", 
                "picUrl": null, 
                "price": 988, 
                "stock": 20, 
                "subTitle": "IPhone6"
            }
        ]
    }, 
    "_links": {
        "profile": {
            "href": "http://localhost:8080/profile/commodity"
        }, 
        "search": {
            "href": "http://localhost:8080/commodity/search"
        }, 
        "self": {
            "href": "http://localhost:8080/commodity{?page,size,sort}", 
            "templated": true
        }
    }, 
    "page": {
        "number": 0, 
        "size": 20, 
        "totalElements": 2, 
        "totalPages": 1
    }
}

可以看到我们要的数据都能查到,并且会提示我们可以用page、size、sort这些参数来控制查询范围和排序。还提示了我们可以用http://localhost:8080/commodity/search来查询,查完会提示你用http://localhost:8080/commodity/search/findByName{?name}这个url来查询,这也是我们自己定义的一个抽象查询方法,试一下:

judy:~$ http localhost:8080/commodity/search/findByName?name=IPhone5
HTTP/1.1 200 
Content-Type: application/hal+json;charset=UTF-8
Date: Wed, 17 Oct 2018 12:04:38 GMT
Transfer-Encoding: chunked

{
    "_embedded": {
        "commodity": [
            {
                "_links": {
                    "commodity": {
                        "href": "http://localhost:8080/commodity/1"
                    }, 
                    "self": {
                        "href": "http://localhost:8080/commodity/1"
                    }
                }, 
                "category": 0, 
                "name": "IPhone5", 
                "picUrl": null, 
                "price": 588, 
                "stock": 10, 
                "subTitle": "IPhone5"
            }
        ]
    }, 
    "_links": {
        "self": {
            "href": "http://localhost:8080/commodity/search/findByName?name=IPhone5"
        }
    }
}

果然查到了,是不是很强大呢?当然了,用框架生成的接口灵活性还是不如自己写的接口。不过个人玩的话真的是懒人福利了。有疑问的大家可以互相交流。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容