第一个微服务应用

(git上的源码:https://gitee.com/rain7564/spring_microservices_study/tree/master/first-microservice)

使用idea创建一个基于Spring Cloud的微服务应用
  1. 点击File -> New -> Project,然后出现如下弹窗:


    image.png
  2. 然后点击Next,输入一些必要信息,如下:


    image.png
  3. 点击Next,如下:


    image.png

注:如果没得选(1.5.8),可以随便选一个,然后生成项目后,将版本号改成1.5.8.RELEASE即可。

  1. 点击Next,最后输入Project name和Project location即可,如下:


    image.png
  2. 等从远程下载项目的.zip文件并解压后,idea会自动将jar包导入,第一次创建Spring Boot项目,加载时间可能会比较久,现在可以先喝杯饮料压压惊~~~
  3. 等项目加载完,第一个微服务应用的雏形就完成了,目录结构如下:


    image.png

    标准的maven项目,我们重点关注以下几个文件:
    ① Application.java:Spring Boot工程的启动类(已被重命名),打开该文件,如下:

//该注解表明该类是项目(微服务)的启动类
@SpringBootApplication
public class Application {
    //运行该方法,会启动整个Spring Boot服务
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

② application.properties: Spring Boot项目的配置文件。该配置文件可以用来配置诸如数据源等的配置信息。该文件是properties文件,不过Spring Boot还支持另一种文件格式——application.yml,该教程所有配置文件都会使用这种文件格式来配置各种配置信息。
以后还会有一个配置文件——bootstrap.yml,后文会详讲。
虽说是配置文件,但当配置文件为空,整个项目也能跑起来。
③ .gitignore: 刚创建的项目并没有该文件,是后来加上去的,若不需要push到git,可以忽略该文件。
④ pom.xml: 写过maven工程的道友肯定对这个文件很熟悉。没错,这个微服务实际上就是一个maven工程,只是该文件中默认加入了Spring Boot的Maven插件(<plugins>标签)、从spring-boot-starter-parent继承的版本号(<parent>标签)和Spring Boot框架的启动依赖(<dependencies>标签)。

  1. 因为我们要创建的是基于Spring Cloud的微服务应用,所以需要对刚刚创建的项目进行改造,让刚刚创建的项目变成一个父项目,并创建一个子项目:
  • 删掉下图选中的文件/文件:


    image.png
  • 修改pom.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.study.microservice</groupId>
    <artifactId>first-microservice</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>

    <name>first-microservice</name>
    <description></description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.8.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
  • 创建一个微服务--licenses-service:
    • 右键项目名,依次选择New->Module:


      image.png
    • 创建license-service微服务,可参考以下步骤(类似步骤1-4):
image.png
image.png
image.png

点击Finish,项目加载完成后,整个工程的目录树如下:

image.png

简单说明图中部分文件/文件夹:
① license-service:刚刚新建的微服务。一个基于Spring Cloud的微服务应用,可以包含多个这样的微服务。
② LicenseServiceApplication:license-service微服务的启动类。
③ 文件夹static、templates:static存放类似.js、.jpg等静态资源,templates存放.html文件等。接下来都不涉及页面的开发,所以这两个文件夹可以删掉。
④ application.properties:配置文件。
⑤ pom.xml:pom文件。打开文件,可以看到跟刚刚创建的父工程first-microservice的pom文件类似,但是<dependencies>标签中的依赖略有不同,多了"spring-boot-starter-web"、"mysql-connector-java",这两个就是刚刚创建时勾选的"Web"、"MySQL"。也就是说需要什么依赖,可以在创建时勾选对应的jar包即可。同样你也可以直接编辑pom文件,比如添加依赖"spring-boot-starter-data-jpa"。不过一般都是直接跳过勾选,需要什么直接编辑pom文件。你可能会问,那pom文件怎么知道引用哪个版本的依赖,答案可以参考spring boot的maven配置依赖
从maven结构来看,first-microservice是license-service的父项目,所以可以对license-service项目的pom文件进行修改,去掉<build>、<properties>标签,修改<parent>标签。如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.study.microservice</groupId>
    <artifactId>license-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>license-service</name>
    <description></description>

    <parent>
        <groupId>cn.study.microservice</groupId>
        <artifactId>first-microservice</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

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

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

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

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

</project>

可以看到<parent>引用了父项目first-microservice,license-service的pom文件继承了first-microservice的pom文件。

  • 删除下图选中的文件/文件夹,并重命名启动类和配置文件:
image.png
  • 创建License.java和LicenseController.java:
package cn.study.microservice.license.domain;

public class License{
    private String id;
    private String organizationId;
    private String productName;
    private String licenseType;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getOrganizationId() {
        return organizationId;
    }

    public void setOrganizationId(String organizationId) {
        this.organizationId = organizationId;
    }

    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public String getLicenseType() {
        return licenseType;
    }

    public void setLicenseType(String licenseType) {
        this.licenseType = licenseType;
    }

    public License withId(String id){
        this.setId( id );
        return this;
    }

    public License withOrganizationId(String organizationId){
        this.setOrganizationId(organizationId);
        return this;
    }

    public License withProductName(String productName){
        this.setProductName(productName);
        return this;
    }

    public License withLicenseType(String licenseType){
        this.setLicenseType(licenseType);
        return this;
    }
}
/**
 * 该注解相当于@ResponseBody + @Controller合在一起的作用
 * 会将request/response序列化/反序列化为JSON格式
 */
@RestController
@RequestMapping(value="v1/organizations/{organizationId}/licenses")
public class LicenseServiceController {

    @RequestMapping(value="/{licenseId}",method = RequestMethod.GET)
    public License getLicenses( @PathVariable("organizationId") String organizationId,
                                @PathVariable("licenseId") String licenseId) {
        //@PathVariable能将URL中{organizationId}、{licenseId}映射到方法的变量organizationId、licenseId
        return new License()
                .withId(licenseId)
                .withOrganizationId(organizationId)
                .withProductName("Teleco")
                .withLicenseType("Seat");
    }

    @RequestMapping(value="{licenseId}",method = RequestMethod.PUT)
    public String updateLicenses( @PathVariable("licenseId") String licenseId) {
        return String.format("This is the put");
    }

    @RequestMapping(value="{licenseId}",method = RequestMethod.POST)
    public String saveLicenses( @PathVariable("licenseId") String licenseId) {
        return String.format("This is the post");
    }

    @RequestMapping(value="{licenseId}",method = RequestMethod.DELETE)
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public String deleteLicenses( @PathVariable("licenseId") String licenseId) {
        return String.format("This is the Delete");
    }

}
  • 启动,以下为idea的几种启动方式:
image.png

启动后,可在控制台看到类似下图的打印效果:


image.png

至此,第一个基于Spring Cloud的微服务应用搭建完成,这只是一个最简单的微服务应用,还没涉及到Spring Cloud的五大神兽:

  • 服务发现——Netflix Eureka
  • 客服端负载均衡——Netflix Ribbon
  • 断路器——Netflix Hystrix
  • 服务网关——Netflix Zuul
  • 分布式配置——Spring Cloud Config

下一节,将介绍第一个神兽:Netflix Eureka(服务注册与发现)。

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

推荐阅读更多精彩内容