springCloud入門學習(二):認識springcloud

1、概念java

基於springboot基礎上用於快速構建分佈式系統的通用模式的工具集。web


2、特色spring

一、約定優於配置;springboot

二、隱藏組件複雜性;架構

三、輕量級組件;app

四、組件豐富,功能齊全,例如:服務發現、斷路器、微服務網關等;dom

五、選型中立、豐富;分佈式

六、靈活。ide


3、服務消費者與服務提供者微服務

在微服務架構中有兩種角色:服務消費者與服務提供者,兩者關係以下:

服務提供者:服務的被調用者

服務消費者:服務的調用者


例如,在電影系統中,用戶購買電影票票以前,電影服務須要調用用戶服務的接口獲取用戶信息,此時的電影服務就是調用方,即服務消費者,用戶服務爲被調用方,即服務提供者。


4、微服務實踐

一、服務提供者:用戶服務

項目結構以下:

image.png

這個demo主要是爲了演示服務與服務之間的通訊,所以再也不配置數據源。

User.java

package com.my.user.entity;

import lombok.Data;

/**
 * @author 垃圾美少女
 */
@Data
public class User {


    private Integer id;
    private String name;
    private Integer age;
    private String username;
    private Integer balance;

}

IUserService.java

package com.my.user.service;

import com.my.user.entity.User;

/**
 * @author 垃圾美少女
 */
public interface IUserService {

    User getByUserId(Integer userId);
}

UserServiceImpl.java

package com.my.user.service.impl;

import com.my.user.entity.User;
import com.my.user.service.IUserService;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author 垃圾美少女
 */
@Service
public class UserServiceImpl implements IUserService {

    @Override
    public User getByUserId(Integer userId) {
        List<User> userList = getUserList();
        userList = userList.stream()
                .filter(user -> Objects.equals(user.getId(), userId))
                .collect(Collectors.toList());
        if (userList != null && userList.size() > 0) {
            return userList.get(0);
        }
        return null;
    }

    /**
     * 因爲沒有配置數據源,在此設置虛擬數據
     *
     * @return list
    */
    private List<User> getUserList() {
        List<User> list = new ArrayList<>(5);
        for (int i = 0; i < 5; i++) {
            User user = new User();
            user.setAge(12 + 1);
            user.setId(1 + i);
            user.setName("用戶" + i);
            user.setUsername("用戶名" + i);
            user.setBalance(123 + i);
            list.add(user);
        }
        return list;
    }


}

UserController.java

package com.my.user.controller;

import com.my.user.Util.ReturnUtil;
import com.my.user.entity.User;
import com.my.user.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

/**
 * @author 垃圾美少女
 */
@RestController
@Slf4j
public class UserController {

    @Autowired
    private IUserService userService;


    /**
     * 根據id獲取用戶信息
     *
     * @param userId 用戶id
     * @return map
     */
    @RequestMapping(value = "/user/getUserInfo", method = RequestMethod.GET)
    public Map getUserInfo(Integer userId) {
        try {
            log.info("/user/getUserInfo被訪問,參數:userId=" + userId);
            User user = userService.getByUserId(userId);
            return ReturnUtil.succe***esult(user, "獲取成功");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ReturnUtil.errorResult(null, "獲取失敗");
        }
    }


}

ReturnUtil.java

package com.my.user.Util;

import java.util.HashMap;
import java.util.Map;

/**
 * @author 垃圾美少女
 */
public class ReturnUtil {


    public static Map succe***esult(Object data, String msg) {
        Map<String, Object> map = new HashMap<>(3);
        map.put("code", 1);
        map.put("msg", msg);
        map.put("data", data);
        return map;
    }

    public static Map errorResult(Object data, String msg) {
        Map<String, Object> map = new HashMap<>(3);
        map.put("code", -1);
        map.put("msg", msg);
        map.put("data", data);
        return map;
    }


}

application.yml

server:
  port: 8010 #指定端口爲  8010

啓動項目後訪問:http://localhost:8010/user/getUserInfo?userId=1

獲得相應:

{
    "msg": "獲取成功",
    "data": {
        "id": 1,
        "name": "用戶0",
        "age": 13,
        "username": "用戶名0",
        "balance": 123
    },
    "code": 1
}

表示接口已通。

二、服務消費者:電影服務

項目架構以下:

image.png

User.java和ReturnUtil.java與上例相同在此再也不展現。


MovieApplicaiton.java

package com.my.movie;

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 MovieApplication {

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

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

}

MovieController.java

package com.my.movie.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

/**
 * @author 垃圾美少女
 */
@RestController
@Slf4j
public class MovieController {

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping(value = "/movie/findById", method = RequestMethod.GET)
    public Map findById(Integer userId) {
        log.info("/movie/findById被訪問,參數:userId=" + userId);
        ResponseEntity<HashMap> forEntity =
                this.restTemplate.getForEntity("http://localhost:8010/user/getUserInfo?userId=" + userId, HashMap.class);
        return forEntity.getBody();

    }

}

application.yml

server:
  port: 8020

此時啓動項目,訪問:http://localhost:8020/movie/findById?userId=1

獲得響應:

{
    "msg": "獲取成功",
    "code": 1,
    "data": {
        "id": 1,
        "name": "用戶0",
        "age": 13,
        "username": "用戶名0",
        "balance": 123
    }
}

至此,一個簡單的電影微服務就完成了。

5、上述例子中存在的問題

一、在代碼中寫死訪問路徑

在電影服務中,能夠將user服務的訪問路徑寫到yml配置文件中,使代碼更清爽:

yml:

server:
  port: 8020

userService:
  domain: http://localhost:8010/user/
  getUserByIdUrl: http://localhost:8010/user/getUserInfo?userId=

MovieController.java

package com.my.movie.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

/**
 * @author 垃圾美少女
 */
@RestController
@Slf4j
public class MovieController {

    @Autowired
    private RestTemplate restTemplate;

    @Value("${userService.domain}")
    private String userServiceDomain;

    @Value("${userService.getUserByIdUrl}")
    private String findByUserIdUrl;

    @RequestMapping(value = "/movie/findById", method = RequestMethod.GET)
    public Map findById(Integer userId) {
        log.info("/movie/findById被訪問,參數:userId=" + userId);
        ResponseEntity<HashMap> forEntity =
                this.restTemplate.getForEntity(findByUserIdUrl + userId, HashMap.class);
        return forEntity.getBody();

    }

}

二、適用場景有限:當用戶服務的地址或端口號發生改變時,須要修改電影服務的配置文件而且從新部署,這顯然是不可取的。

相關文章
相關標籤/搜索