微服務簡單實例--電影購票

目錄


通過上一篇文章理解了微服務後我們通過一個簡單的電影購票場景來實現微服務。
如圖:
電影購票系統
這個場景當中,用戶微服務是一個服務提供者,電影微服務是一個服務消費者,之前我們也說到,每個微服務從開發,測試,構建,部署,都應當獨立運行,即每個微服務是單獨的子項目。下面來實現這個場景。

一、編寫服務提供者

新建一個Spring Boot (版本1.5.9.RELEASE) 項目,不知道如何在IDEA中新建的可以看這篇>>傳送門::Spring Boot 入門知識

添加依賴

項目使用H2作爲數據庫,使用jpa作爲持久層框架。Spring Boot環境中H2數據庫的基本配置可參考這篇>>傳送門:Spring Boot環境下的 H2數據庫基本配置

    <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>com.h2database</groupId>
        <artifactId>h2</artifactId>
    </dependency>
    </dependencies>
    <!--引入SpringCloud 依賴-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Edgware.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

配置

application.yml 文件配置如下 :

server:
  port: 8000
spring:
  jpa:
    generate-ddl: false
    show-sql: true
    hibernate:
      ddl_auto: none
  h2:
    console:
      path: /h2-console               #h2 web控制檯路徑
      enabled: true                   #開啓 Web Console
      settings:
        web-allow-others: true        #允許遠程訪問 Web Console
  datasource:
    platform: h2                      #指定數據源類型
    schema: classpath:schema.sql      #指定數據庫的數據腳本
    data: classpath:data.sql          #指定數據庫的數據腳本

spring.h2.console.path 指定了h2控制檯的路徑,可以通過localhost:8000/h2-console 去訪問H2的控制檯。
spring.datasource.schema 與 datasource.data 會在每次啓動項目時都會被執行

schema.sql

drop table user if exists;
create table user (id bigint generated by default as identity, username varchar(40), name varchar(20), age int(3), balance decimal(10,2), primary key (id));

data.sql

insert into user (id, username, name, age, balance) values (1, 'account1', '張三', 20, 100.00);
insert into user (id, username, name, age, balance) values (2, 'account2', '李四', 28, 180.00);
insert into user (id, username, name, age, balance) values (3, 'account3', '王一', 32, 280.00);

pojo

@Entity
@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler"})
public class User {
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;
  @Column
  private String username;
  @Column
  private String name;
  @Column
  private Integer age;
  @Column
  private BigDecimal balance;

//...get
//...set
}

報錯

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer

如果在運行時報以上錯誤,則需要添加註釋:
@JsonIgnoreProperties(value={“hibernateLazyInitializer”,”handler”})

這是因爲 hibernate會給每個被管理的對象加上hibernateLazyInitializer屬性,jsonplugin通過java的反射機制將pojo轉換成json,會把hibernateLazyInitializer也拿出來操作,但是hibernateLazyInitializer無法由反射得到,就會拋異常了。

Dao

@Repository
public interface UserRepository extends JpaRepository<User,Long>{
}

Controller

@RestController
public class UserController {
    @Autowired
    private UserRepository userRepository;

    @GetMapping("/{id}")
    public User findById(@PathVariable Long id){
        User findOne = this.userRepository.getOne(id);
        return findOne;
    }
}

@GetMapping() 等同於 @RequestMapping(method = {RequestMethod.GET})

測試

運行項目,訪問測試
測試

二、編寫服務消費者

消費者作爲服務調用方,這裏只使用最簡單的方式來實現。

添加依賴

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <!--引入SpringCloud 依賴-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Edgware.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

配置

application.yml

server:
    port: 8011
user:
    userServiceUrl: http://localhost:8000/

user.userServiceUrl :把調用地址寫入配置文件

pojo

這裏與上面的服務提供者相同

RestTemplate

實例化RestTemplate
在啓動類中添加以下方法:

@Bean
public RestTemplate restTemplate(){
    return new RestTemplate();
}

Controller

@RestController
public class UserController {
    @Autowired
    private RestTemplate restTemplate;
    @Value("${user.userServiceUrl}")
    private String userServiceUrl;

    @GetMapping("/user/{id}")
    public User findById(@PathVariable Long id){
        return this.restTemplate.getForObject(this.userServiceUrl + id,User.class);
    }
}

這裏使用 restTemplate 來調用服務
@Value(“${user.userServiceUrl}”) 從配置文件中取user.userServiceUrl值

測試

啓動項目進行測試
消費者測試

三、總結

至此,一個簡單的微服務完成!是不是覺得與我們平時寫接口是差不多的,平時我們是在整個系統內部,各個功能模塊之間進行接口調用,微服務則是把這些模塊單獨出來成爲一個子系統,每個子系統提供接口給其它系統調用。
在整個電影購票系統中
使用單一職責原則:兩個微服務只關注整個系統中單獨,有界限的一部分。
滿足服務自治原則:每個微服務具備獨立的業務能力,依賴與運行環境。
使用了輕量級通信機制:消費者中使用了Rest 進行服務調用
微服務粒度:兩個微服務都有明確的功能劃分。

當然微服務不只是這麼簡單,還應該包括安全性,高可用性等,還需要集成其它的組件,後面會邊學習邊作記錄。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章