006 SpringCloud 學習筆記2-----SpringCloud基礎入門

1.SpringCloud概述html

微服務是一種架構方式,最終確定須要技術架構去實施。前端

微服務的實現方式不少,可是最火的莫過於Spring Cloud了。
SpringCloud優勢:java

  - 後臺硬:做爲Spring家族的一員,有整個Spring全家桶靠山,背景十分強大。
  - 技術強:Spring做爲Java領域的前輩,能夠說是功力深厚。有強力的技術團隊支撐,通常人還真比不了
  - 羣衆基礎好:能夠說大多數程序員的成長都伴隨着Spring框架,試問:如今有幾家公司開發不用Spring?SpringCloud與Spring的各個框架無縫整合,對你們來講一切都是熟悉的配方,熟悉的味道。
  - 使用方便:相信你們都體會到了SpringBoot給咱們開發帶來的便利,而SpringCloud徹底支持SpringBoot的開發,用不多的配置就能完成微服務框架的搭建mysql

(1)簡介程序員

Spring最擅長的就是集成,把世界上最好的框架拿過來,集成到本身的項目中。
SpringCloud也是同樣,它將如今很是流行的一些技術整合到一塊兒,實現了諸如:配置管理,服務發現,智能路由,負載均衡,熔斷器,控制總線,集羣狀態等等功能。其主要涉及的組件包括:
- Eureka:服務治理組件,包含服務註冊中心,服務註冊與發現機制的實現。(服務治理,服務註冊/發現)
- Zuul:網關組件,提供智能路由,訪問過濾功能
- Ribbon:客戶端負載均衡的服務調用組件(客戶端負載)
- Feign:服務調用,給予Ribbon和Hystrix的聲明式服務調用組件 (聲明式服務調用)
- Hystrix:容錯管理組件,實現斷路器模式,幫助服務依賴中出現的延遲和爲故障提供強大的容錯能力。(熔斷、斷路器,容錯)web

架構圖:spring

 

2.微服務場景模擬案例sql

首先,咱們須要模擬一個服務調用的場景,搭建兩個工程:lucky-service-provider(服務提供方)和lucky-service-consumer(服務調用方)。方便後面學習微服務架構
服務提供方:使用mybatis操做數據庫,實現對數據的增刪改查;並對外提供rest接口服務。
服務消費方:使用restTemplate遠程調用服務提供方的rest接口服務,獲取數據。數據庫

(1)服務提供者springboot

咱們新建一個項目:lucky-service-provider,對外提供根據id查詢用戶的服務。

<1>Spring腳手架(Spring Initializr)建立工程

最終生成的項目結構:

(2)代碼編寫

<1>配置

屬性文件,這裏咱們採用了yaml語法,而不是properties:

server:
  port: 8081
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/springboot
    username: root
    password: plj824
mybatis:
  type-aliases-package: lucky.service.domain

<2>實體類

package lucky.service.domain;

import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * 數據庫表users對應的實體類
 * 注意:Users這個類中添加了@Table、@Id、@GeneratedValue等註解
 * 這些註解的使用須要在pom文件中添加mapper的依賴
 */
@Table(name="users")
public class Users {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id; // 主 鍵
    private String username; // 用戶名
    private String password; // 密 碼
    private String name; // 姓 名

    public Integer getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}

<3>UsersMapper

package lucky.service.mapper;

import lucky.service.domain.Users;

public interface UsersMapper extends tk.mybatis.mapper.common.Mapper<Users>{

}

注意:mapper接口類須要在springboot引導類----LuckyServiceProviderApplication.java類中添加註解@MapperScan

package lucky.service;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import tk.mybatis.spring.annotation.MapperScan;

//聲明該類是一個springboot引導類:springboot應用的入口
@SpringBootApplication
@MapperScan("lucky.service.mapper")  //mapper接口的包掃描
public class LuckyServiceProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(LuckyServiceProviderApplication.class, args);
    }

}

<4>UsersService.java

package lucky.service;

import lucky.domain.Users;
import lucky.mapper.UsersMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class UsersService {

    @Autowired
    private UsersMapper usersMapper;

    public Users queryUsersById(Integer id){
        return this.usersMapper.selectByPrimaryKey(id);
    }

    @Transactional
    public void deleteUserById(Long id){
        this.usersMapper.deleteByPrimaryKey(id);
    }

    public List<Users> queryAllUsers() {
        return this.usersMapper.selectAll();
    }
}

<5>UsersController.java

package lucky.controller;

import lucky.domain.Users;
import lucky.service.UsersService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

@Controller
@RequestMapping(path = "/users")
public class UsersController {

    @Autowired
    private UsersService usersService;

    @RequestMapping(path = "/query")
    @ResponseBody
    public String queryUsers(){
        return "hello users";
    }

    @RequestMapping(path = "/queryUsersById")
    @ResponseBody
    public Users queryUsersById(@RequestParam("id") Integer id){
        return this.usersService.queryUsersById(id);
    }

    /**
     * 查詢全部用戶,並在前端顯示
     * @param model model對象用來向前端傳遞數據
     * @return 返回視圖名稱
     */
    @RequestMapping(path = "/queryAllUsers")
    public String queryAllUsers(Model model){
        //1.查詢全部用戶
        List<Users> users = this.usersService.queryAllUsers();
        //2.放入模型
        model.addAttribute("users",users);
        //3.返回模板名稱(就是classpath:/templates/目錄下的html文件名)
        return "users";
    }

}

<6>測試效果

(3)服務調用者

搭建lucky-service-consumer服務消費方工程。

<1>Spring腳手架(Spring Initializr)建立工程(在同一個工程project下建立不一樣的模塊)

(4)代碼編寫

<1>首先在引導類中註冊RestTemplate

package lucky.service.luckyserviceconsumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class LuckyServiceConsumerApplication {

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
    
    public static void main(String[] args) {
        SpringApplication.run(LuckyServiceConsumerApplication.class, args);
    }

}

<2>編寫配置(application.yml):

server:
  port: 8080

<3>編寫UserController:

package lucky.service.controller;

import lucky.service.domain.Users;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;

@Controller
@RequestMapping(path = "/consumer/user")
public class UserController {
    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping(path = "/queryUsersById")
    @ResponseBody
    public Users queryUserById(@RequestParam("id") Integer id){
        return this.restTemplate.getForObject("http://localhost:8081/users/queryUsersById?id="+id,Users.class);
    }


}

<4>實體類

package lucky.service.domain;

import java.io.Serializable;

/**
 * 數據庫表users對應的實體類
 */

public class Users  implements Serializable {

    private Integer id; // 主 鍵
    private String username; // 用戶名
    private String password; // 密 碼
    private String name; // 姓 名

    public Integer getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}

<5>測試效果

 3.微服務場景模擬案例存在的問題

 

- 在consumer中,咱們把url地址硬編碼到了代碼中,不方便後期維護
- consumer須要記憶provider的地址,若是出現變動,可能得不到通知,地址將失效
- consumer不清楚provider的狀態,服務宕機也不知道
- provider只有1臺服務,不具有高可用性
- 即使provider造成集羣,consumer還需本身實現負載均衡

相關文章
相關標籤/搜索