SpringCloud day01

在这里插入图片描述

Spring cloud介绍

spring cloud 是一系列框架的集合。它利用 spring boot 的开发便利性巧妙地简化了分布式系统基础设施的开发如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用 spring boot 的开发风格做到一键启动和部署。spring cloud 并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过 spring boot 风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包

spring cloud 对于中小型互联网公司来说是一种福音,因为这类公司往往没有实力或者没有足够的资金投入去开发自己的分布式系统基础设施,使用 spring cloud 一站式解决方案能在从容应对业务发展的同时大大减少开发成本。同时,随着近几年微服务架构和 docker 容器概念的火爆,也会让 spring cloud 在未来越来越“云”化的软件开发风格中立有一席之地,尤其是在目前五花八门的分布式解决方案中提供了标准化的、一站式的技术方案,意义可能会堪比当年 servlet 规范的诞生,有效推进服务端软件系统技术水平的进步。

spring cloud 技术组成

在这里插入图片描述
eureka
微服务治理,服务注册和发现

ribbon
负载均衡、请求重试

hystrix
断路器,服务降级、熔断

feign
ribbon + hystrix 集成,并提供声明式客户端

hystrix dashboard 和 turbine
hystrix 数据监控

zuul
API 网关,提供微服务的统一入口,并提供统一的权限验证

config
配置中心

bus
消息总线, 配置刷新

sleuth+zipkin
链路跟踪

Spring Cloud 对比 Dubbo

在这里插入图片描述
Dubbo

Dubbo只是一个远程调用(RPC)框架
默认基于长连接,支持多种序列化格式
Spring Cloud

框架集
提供了一整套微服务解决方案(全家桶)
基于http调用, Rest API

SpringCloud入门案例

项目结构

在这里插入图片描述
商品服务 item service,端口 8001
用户服务 user service,端口 8101
订单服务 order service,端口 8201
在这里插入图片描述
在这里插入图片描述
新建empty project
在这里插入图片描述
在这里插入图片描述

创建sp01-common模块

在这里插入图片描述
在这里插入图片描述
添加依赖

<dependencies>
		<dependency>
			<groupId>com.fasterxml.jackson.module</groupId>
			<artifactId>jackson-module-parameter-names</artifactId>
			<version>2.9.8</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.datatype</groupId>
			<artifactId>jackson-datatype-jdk8</artifactId>
			<version>2.9.8</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.datatype</groupId>
			<artifactId>jackson-datatype-jsr310</artifactId>
			<version>2.9.8</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.datatype</groupId>
			<artifactId>jackson-datatype-guava</artifactId>
			<version>2.9.8</version>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.6</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>3.1.0</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>1.7.26</version>
		</dependency>
		<dependency>
		    <groupId>org.apache.commons</groupId>
		    <artifactId>commons-lang3</artifactId>
		    <version>3.9</version>
		</dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.0</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>
	</build>

修改maven配置
在这里插入图片描述
统一jdk版本
在这里插入图片描述
在这里插入图片描述
创建项目结构:
在这里插入图片描述
修改编码集
在这里插入图片描述

pojo

package cn.tedu.sp01.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Item {
    private Integer id;
    private String name;
    private Integer number;
}
package cn.tedu.sp01.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Order {
    private String id;
    private User user;
    private List<Item> items;
}
package cn.tedu.sp01.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private Integer id;
    private String username;
    private String password;
}

service

package cn.tedu.sp01.service;

import cn.tedu.sp01.pojo.Item;

import java.util.List;

public interface ItemService {
    //获取订单的商品列表
    List<Item> getItems(String orderId);
    //减少商品的库存
    void decreaseNumbers(List<Item> list);
}

package cn.tedu.sp01.service;

import cn.tedu.sp01.pojo.Order;

public interface OrderService {
    //获取订单
    Order getOrder(String orderId);
    //添加定单实例
    void addOrder(Order order);
}


package cn.tedu.sp01.service;

import cn.tedu.sp01.pojo.User;

public interface UserService {
    //获取用户
    User getUser(Integer id);
    //增加用户积分
    void addScore(Integer id, Integer score);
}

web.util

package cn.tedu.web.util;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CookieUtil {

    /**
     * @param response
     * @param name
     * @param value
     * @param maxAge
     */
    public static void setCookie(HttpServletResponse response,
                                 String name, String value, String domain, String path, int maxAge) {
        Cookie cookie = new Cookie(name, value);
        if(domain != null) {
            cookie.setDomain(domain);
        }
        cookie.setPath(path);
        cookie.setMaxAge(maxAge);
        response.addCookie(cookie);
    }
    public static void setCookie(HttpServletResponse response, String name, String value, int maxAge) {
        setCookie(response, name, value, null, "/", maxAge);
    }
    public static void setCookie(HttpServletResponse response, String name, String value) {
        setCookie(response, name, value, null, "/", 3600);
    }
    public static void setCookie(HttpServletResponse response, String name) {
        setCookie(response, name, "", null, "/", 3600);
    }

    /**
     * @param request
     * @param name
     * @return
     */
    public static String getCookie(HttpServletRequest request, String name) {
        String value = null;
        Cookie[] cookies = request.getCookies();
        if (null != cookies) {
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals(name)) {
                    value = cookie.getValue();
                }
            }
        }
        return value;
    }

    /**
     * @param response
     * @param name
     * @return
     */
    public static void removeCookie(HttpServletResponse response, String name, String domain, String path) {
        setCookie(response, name, "", domain, path, 0);
    }

}
package cn.tedu.web.util;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class JsonResult<T> {
    /** 成功 */
    public static final int SUCCESS = 200;

    /** 没有登录 */
    public static final int NOT_LOGIN = 400;

    /** 发生异常 */
    public static final int EXCEPTION = 401;

    /** 系统错误 */
    public static final int SYS_ERROR = 402;

    /** 参数错误 */
    public static final int PARAMS_ERROR = 403;

    /** 不支持或已经废弃 */
    public static final int NOT_SUPPORTED = 410;

    /** AuthCode错误 */
    public static final int INVALID_AUTHCODE = 444;

    /** 太频繁的调用 */
    public static final int TOO_FREQUENT = 445;

    /** 未知的错误 */
    public static final int UNKNOWN_ERROR = 499;

    private int code;
    private String msg;
    private T data;



    public static JsonResult build() {
        return new JsonResult();
    }
    public static JsonResult build(int code) {
        return new JsonResult().code(code);
    }
    public static JsonResult build(int code, String msg) {
        return new JsonResult<String>().code(code).msg(msg);
    }
    public static <T> JsonResult<T> build(int code, T data) {
        return new JsonResult<T>().code(code).data(data);
    }
    public static <T> JsonResult<T> build(int code, String msg, T data) {
        return new JsonResult<T>().code(code).msg(msg).data(data);
    }

    public JsonResult<T> code(int code) {
        this.code = code;
        return this;
    }
    public JsonResult<T> msg(String msg) {
        this.msg = msg;
        return this;
    }
    public JsonResult<T> data(T data) {
        this.data = data;
        return this;
    }


    public static JsonResult ok() {
        return build(SUCCESS);
    }
    public static JsonResult ok(String msg) {
        return build(SUCCESS, msg);
    }
    public static <T> JsonResult<T> ok(T data) {
        return build(SUCCESS, data);
    }
    public static JsonResult err() {
        return build(EXCEPTION);
    }
    public static JsonResult err(String msg) {
        return build(EXCEPTION, msg);
    }

    @Override
    public String toString() {
        return JsonUtil.to(this);
    }
}
package cn.tedu.web.util;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Writer;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.datatype.guava.GuavaModule;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class JsonUtil {
    private static ObjectMapper mapper;
    private static JsonInclude.Include DEFAULT_PROPERTY_INCLUSION = JsonInclude.Include.NON_DEFAULT;
    private static boolean IS_ENABLE_INDENT_OUTPUT = false;
    private static String CSV_DEFAULT_COLUMN_SEPARATOR = ",";
    static {
        try {
            initMapper();
            configPropertyInclusion();
            configIndentOutput();
            configCommon();
        } catch (Exception e) {
            log.error("jackson config error", e);
        }
    }

    private static void initMapper() {
        mapper = new ObjectMapper();
    }

    private static void configCommon() {
        config(mapper);
    }

    private static void configPropertyInclusion() {
        mapper.setSerializationInclusion(DEFAULT_PROPERTY_INCLUSION);
    }

    private static void configIndentOutput() {
        mapper.configure(SerializationFeature.INDENT_OUTPUT, IS_ENABLE_INDENT_OUTPUT);
    }

    private static void config(ObjectMapper objectMapper) {
        objectMapper.enable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN);
        objectMapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
        objectMapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
        objectMapper.enable(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY);
        objectMapper.enable(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS);
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        objectMapper.disable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES);
        objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        objectMapper.enable(JsonParser.Feature.ALLOW_COMMENTS);
        objectMapper.disable(JsonGenerator.Feature.ESCAPE_NON_ASCII);
        objectMapper.enable(JsonGenerator.Feature.IGNORE_UNKNOWN);
        objectMapper.enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES);
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        objectMapper.enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES);
        objectMapper.registerModule(new ParameterNamesModule());
        objectMapper.registerModule(new Jdk8Module());
        objectMapper.registerModule(new JavaTimeModule());
        objectMapper.registerModule(new GuavaModule());
    }
    public static void setSerializationInclusion(JsonInclude.Include inclusion) {
        DEFAULT_PROPERTY_INCLUSION = inclusion;
        configPropertyInclusion();
    }

    public static void setIndentOutput(boolean isEnable) {
        IS_ENABLE_INDENT_OUTPUT = isEnable;
        configIndentOutput();
    }

    public static <V> V from(URL url, Class<V> c) {
        try {
            return mapper.readValue(url, c);
        } catch (IOException e) {
            log.error("jackson from error, url: {}, type: {}", url.getPath(), c, e);
            return null;
        }
    }

    public static <V> V from(InputStream inputStream, Class<V> c) {
        try {
            return mapper.readValue(inputStream, c);
        } catch (IOException e) {
            log.error("jackson from error, type: {}", c, e);
            return null;
        }
    }

    public static <V> V from(File file, Class<V> c) {
        try {
            return mapper.readValue(file, c);
        } catch (IOException e) {
            log.error("jackson from error, file path: {}, type: {}", file.getPath(), c, e);
            return null;
        }
    }

    public static <V> V from(Object jsonObj, Class<V> c) {
        try {
            return mapper.readValue(jsonObj.toString(), c);
        } catch (IOException e) {
            log.error("jackson from error, json: {}, type: {}", jsonObj.toString(), c, e);
            return null;
        }
    }

    public static <V> V from(String json, Class<V> c) {
        try {
            return mapper.readValue(json, c);
        } catch (IOException e) {
            log.error("jackson from error, json: {}, type: {}", json, c, e);
            return null;
        }
    }

    public static <V> V from(URL url, TypeReference<V> type) {
        try {
            return mapper.readValue(url, type);
        } catch (IOException e) {
            log.error("jackson from error, url: {}, type: {}", url.getPath(), type, e);
            return null;
        }
    }

    public static <V> V from(InputStream inputStream, TypeReference<V> type) {
        try {
            return mapper.readValue(inputStream, type);
        } catch (IOException e) {
            log.error("jackson from error, type: {}", type, e);
            return null;
        }
    }

    public static <V> V from(File file, TypeReference<V> type) {
        try {
            return mapper.readValue(file, type);
        } catch (IOException e) {
            log.error("jackson from error, file path: {}, type: {}", file.getPath(), type, e);
            return null;
        }
    }

    public static <V> V from(Object jsonObj, TypeReference<V> type) {
        try {
            return mapper.readValue(jsonObj.toString(), type);
        } catch (IOException e) {
            log.error("jackson from error, json: {}, type: {}", jsonObj.toString(), type, e);
            return null;
        }
    }

    public static <V> V from(String json, TypeReference<V> type) {
        try {
            return mapper.readValue(json, type);
        } catch (IOException e) {
            log.error("jackson from error, json: {}, type: {}", json, type, e);
            return null;
        }
    }

    public static <V> String to(List<V> list) {
        try {
            return mapper.writeValueAsString(list);
        } catch (JsonProcessingException e) {
            log.error("jackson to error, obj: {}", list, e);
            return null;
        }
    }

    public static <V> String to(V v) {
        try {
            return mapper.writeValueAsString(v);
        } catch (JsonProcessingException e) {
            log.error("jackson to error, obj: {}", v, e);
            return null;
        }
    }

    public static <V> void toFile(String path, List<V> list) {
        try (Writer writer = new FileWriter(new File(path), true)) {
            mapper.writer().writeValues(writer).writeAll(list);
            writer.flush();
        } catch (Exception e) {
            log.error("jackson to file error, path: {}, list: {}", path, list, e);
        }
    }

    public static <V> void toFile(String path, V v) {
        try (Writer writer = new FileWriter(new File(path), true)) {
            mapper.writer().writeValues(writer).write(v);
            writer.flush();
        } catch (Exception e) {
            log.error("jackson to file error, path: {}, obj: {}", path, v, e);
        }
    }

    public static String getString(String json, String key) {
        if (StringUtils.isEmpty(json)) {
            return null;
        }
        try {
            JsonNode node = mapper.readTree(json);
            if (null != node) {
                return node.get(key).toString();
            } else {
                return null;
            }
        } catch (IOException e) {
            log.error("jackson get string error, json: {}, key: {}", json, key, e);
            return null;
        }
    }

    public static Integer getInt(String json, String key) {
        if (StringUtils.isEmpty(json)) {
            return null;
        }
        try {
            JsonNode node = mapper.readTree(json);
            if (null != node) {
                return node.get(key).intValue();
            } else {
                return null;
            }
        } catch (IOException e) {
            log.error("jackson get int error, json: {}, key: {}", json, key, e);
            return null;
        }
    }

    public static Long getLong(String json, String key) {
        if (StringUtils.isEmpty(json)) {
            return null;
        }
        try {
            JsonNode node = mapper.readTree(json);
            if (null != node) {
                return node.get(key).longValue();
            } else {
                return null;
            }
        } catch (IOException e) {
            log.error("jackson get long error, json: {}, key: {}", json, key, e);
            return null;
        }
    }

    public static Double getDouble(String json, String key) {
        if (StringUtils.isEmpty(json)) {
            return null;
        }
        try {
            JsonNode node = mapper.readTree(json);
            if (null != node) {
                return node.get(key).doubleValue();
            } else {
                return null;
            }
        } catch (IOException e) {
            log.error("jackson get double error, json: {}, key: {}", json, key, e);
            return null;
        }
    }

    public static BigInteger getBigInteger(String json, String key) {
        if (StringUtils.isEmpty(json)) {
            return new BigInteger(String.valueOf(0.00));
        }
        try {
            JsonNode node = mapper.readTree(json);
            if (null != node) {
                return node.get(key).bigIntegerValue();
            } else {
                return null;
            }
        } catch (IOException e) {
            log.error("jackson get biginteger error, json: {}, key: {}", json, key, e);
            return null;
        }
    }

    public static BigDecimal getBigDecimal(String json, String key) {
        if (StringUtils.isEmpty(json)) {
            return null;
        }
        try {
            JsonNode node = mapper.readTree(json);
            if (null != node) {
                return node.get(key).decimalValue();
            } else {
                return null;
            }
        } catch (IOException e) {
            log.error("jackson get bigdecimal error, json: {}, key: {}", json, key, e);
            return null;
        }
    }

    public static boolean getBoolean(String json, String key) {
        if (StringUtils.isEmpty(json)) {
            return false;
        }
        try {
            JsonNode node = mapper.readTree(json);
            if (null != node) {
                return node.get(key).booleanValue();
            } else {
                return false;
            }
        } catch (IOException e) {
            log.error("jackson get boolean error, json: {}, key: {}", json, key, e);
            return false;
        }
    }

    public static byte[] getByte(String json, String key) {
        if (StringUtils.isEmpty(json)) {
            return null;
        }
        try {
            JsonNode node = mapper.readTree(json);
            if (null != node) {
                return node.get(key).binaryValue();
            } else {
                return null;
            }
        } catch (IOException e) {
            log.error("jackson get byte error, json: {}, key: {}", json, key, e);
            return null;
        }
    }

    public static <T> ArrayList<T> getList(String json, String key) {
        if (StringUtils.isEmpty(json)) {
            return null;
        }
        String string = getString(json, key);
        return from(string, new TypeReference<ArrayList<T>>() {});
    }

    public static <T> String add(String json, String key, T value) {
        try {
            JsonNode node = mapper.readTree(json);
            add(node, key, value);
            return node.toString();
        } catch (IOException e) {
            log.error("jackson add error, json: {}, key: {}, value: {}", json, key, value, e);
            return json;
        }
    }

    private static <T> void add(JsonNode jsonNode, String key, T value) {
        if (value instanceof String) {
            ((ObjectNode) jsonNode).put(key, (String) value);
        } else if (value instanceof Short) {
            ((ObjectNode) jsonNode).put(key, (Short) value);
        } else if (value instanceof Integer) {
            ((ObjectNode) jsonNode).put(key, (Integer) value);
        } else if (value instanceof Long) {
            ((ObjectNode) jsonNode).put(key, (Long) value);
        } else if (value instanceof Float) {
            ((ObjectNode) jsonNode).put(key, (Float) value);
        } else if (value instanceof Double) {
            ((ObjectNode) jsonNode).put(key, (Double) value);
        } else if (value instanceof BigDecimal) {
            ((ObjectNode) jsonNode).put(key, (BigDecimal) value);
        } else if (value instanceof BigInteger) {
            ((ObjectNode) jsonNode).put(key, (BigInteger) value);
        } else if (value instanceof Boolean) {
            ((ObjectNode) jsonNode).put(key, (Boolean) value);
        } else if (value instanceof byte[]) {
            ((ObjectNode) jsonNode).put(key, (byte[]) value);
        } else {
            ((ObjectNode) jsonNode).put(key, to(value));
        }
    }

    public static String remove(String json, String key) {
        try {
            JsonNode node = mapper.readTree(json);
            ((ObjectNode) node).remove(key);
            return node.toString();
        } catch (IOException e) {
            log.error("jackson remove error, json: {}, key: {}", json, key, e);
            return json;
        }
    }

    public static <T> String update(String json, String key, T value) {
        try {
            JsonNode node = mapper.readTree(json);
            ((ObjectNode) node).remove(key);
            add(node, key, value);
            return node.toString();
        } catch (IOException e) {
            log.error("jackson update error, json: {}, key: {}, value: {}", json, key, value, e);
            return json;
        }
    }

    public static String format(String json) {
        try {
            JsonNode node = mapper.readTree(json);
            return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(node);
        } catch (IOException e) {
            log.error("jackson format json error, json: {}", json, e);
            return json;
        }
    }

    public static boolean isJson(String json) {
        try {
            mapper.readTree(json);
            return true;
        } catch (Exception e) {
            log.error("jackson check json error, json: {}", json, e);
            return false;
        }
    }

    private static InputStream getResourceStream(String name) {
        return JsonUtil.class.getClassLoader().getResourceAsStream(name);
    }

    private static InputStreamReader getResourceReader(InputStream inputStream) {
        if (null == inputStream) {
            return null;
        }
        return new InputStreamReader(inputStream, StandardCharsets.UTF_8);
    }
}

sp02-itemservice模块

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
添加依赖:


		<dependency>
			<groupId>cn.tedu</groupId>
			<artifactId>sp01-commons</artifactId>
			<version>1.0-SNAPSHOT</version>
		</dependency>

修改yml文件
yml 也叫yaml:Yet another markup language
在这里插入图片描述
创建包结构:
在这里插入图片描述

#应用名作为服务ID注册到注册中心
spring:
  application:
    name: item-service
    
server:
  port: 8001
package cn.tedu.sp02.item.service;

import cn.tedu.sp01.pojo.Item;
import cn.tedu.sp01.service.ItemService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
@Service
@Slf4j
public class ItemServiceImpl implements ItemService {
    @Override
    public List<Item> getItems(String orderId) {
        ArrayList<Item> list = new ArrayList<Item>();
        list.add(new Item(1, "商品 1",1));
        list.add(new Item(2, "商品 2",2));
        list.add(new Item(3, "商品 3",3));
        list.add(new Item(4, "商品 4",4));
        list.add(new Item(5, "商品 5",5));
        return list;
    }

    @Override
    public void decreaseNumbers(List<Item> list) {
        for(Item item : list) {
            log.info("减少库存 - "+item); //记录日志
        }
    }
}

在这里插入图片描述
@RequestBody 注解,完整接收请求协议体数据,只有post请求有协议体,get请求只有协议头
接收完后自动json转换,转换为java对象

package cn.tedu.sp02.item.controller;

import cn.tedu.sp01.pojo.Item;
import cn.tedu.sp01.service.ItemService;
import cn.tedu.web.util.JsonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@Slf4j
public class ItemController {
    @Autowired
    private ItemService itemService;
    //为了后面测试集群多台服务器,这里注入端口号
    @Value("${server.port}")
    private int port;

    @GetMapping("/{orderId}")
    public JsonResult<List<Item>> getItems(@PathVariable String orderId){
      log.info("orderId="+orderId+",port="+port);
      List<Item> items=itemService.getItems(orderId);
      return JsonResult.ok().msg("port="+port).data(items);
    }

        //只处理post请求
    //@RequestBody  注解,完整接收请求协议体数据,只有post请求有协议体,get请求只有协议头
    //接收完后自动json转换,转换为java对象
        @PostMapping("/{dechreaseNumber}")
        public JsonResult decreaseNumber(@RequestBody List<Item> items){
           itemService.decreaseNumbers(items);
           return JsonResult.ok().msg("减少商品库存成功");

        }
}

在这里插入图片描述
访问测试:

在这里插入图片描述

postman

PostMan安装
网页调试工具不仅可以调试简单的css、html、脚本等简单的网页基本信息,它还可以发送几乎所有类型的HTTP请求!Postman在发送网络HTTP请求方面可以说是Chrome插件类产品中的代表产品之一
在这里插入图片描述
GET请求
GET请求:点击Params,输入参数及value,可输入多个,即显示在url链接上,所以,get请求的请求头与请求参数如在接口文档中无特别声明时,可以不填
POST请求—表单提交
在这里插入图片描述
post请求—json提交
post请求—xml提交
post请求—自行设置Content-Type
HTTP的POST请求的参数,都是放在请求正文中的,只是根据Content-Type来判断请求正文的格式,那么我们同样可以在表单提交时,选择raw,然后自行设置Content-Type为application/x-www-form-urlencoded
在这里插入图片描述
post请求—二进制文件提交
postman的断言
浏览器提交方式get提交

[{"id":1, "name":"abc", "number":23},{"id":2, "name":"def", "number":11}]

在这里插入图片描述
点击SEND提交成功界面
在这里插入图片描述
在这里插入图片描述

SP03-userservice

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
依赖

<dependency>
			<groupId>cn.tedu</groupId>
			<artifactId>sp01-commons</artifactId>
			<version>1.0-SNAPSHOT</version>
		</dependency>

yaml

#添加一个自定义属性
#配置三个测试用的用户数据
sp:
  user-service:
    users: "[{\"id\":7, \"username\":\"abc\",\"password\":\"123\"},{\"id\":8, \"username\":\"def\",\"password\":\"456\"},{\"id\":9, \"username\":\"ghi\",\"password\":\"789\"}]"
#向注册中心注册时
#应用名作为服务ID注册到注册中心
spring:
  application:
    name: user-service

server:
  port: 8101

项目结构:
在这里插入图片描述
在这里插入图片描述
jackson包

import com.fasterxml.jackson.core.type.TypeReference;

匿名内部类,转化成list集合

package cn.tedu.sp03.user.service;

import cn.tedu.sp01.pojo.User;
import cn.tedu.sp01.service.UserService;
import cn.tedu.web.util.JsonUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@Slf4j
public class UserServiceImpl implements UserService {
   @Value("${sp.user-service.users}")
   private String userJson;

    @Override
    public User getUser(Integer userId) {
        log.info("获取用户,userId= "+userId);
        List<User> list = JsonUtil.from(userJson, new TypeReference<List<User>>() {});
        for (User u : list) {
            if (u.getId().equals(userId)) {
                return u;
            }
        }
        //找不到用户,也返回一个假的用户数据
        return new User(userId, "用户名:"+userId, "密码:"+userId);
    }

    @Override
    public void addScore(Integer id, Integer score) {
       //增加积分
        log.info("增加用户积分,userId"+id+"-增加积分score="+score);

    }
}

package cn.tedu.sp03.user.controller;

import cn.tedu.sp01.pojo.User;
import cn.tedu.sp01.service.UserService;
import cn.tedu.web.util.JsonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Slf4j
public class UserController {
    @Autowired
    private UserService userService;
    @GetMapping("/{userId}")
    public JsonResult<User> getUser(@PathVariable  Integer userId){
    User u=userService.getUser(userId);
    return JsonResult.ok().data(u);
    }

    //http://localhost:8101/8/score?score=1000
    @GetMapping("/{userId}/score")
    public JsonResult<?> addScore(@PathVariable Integer userId,Integer score){
        userService.addScore(userId, score);
        return JsonResult.ok().msg("增加用户积分成功");
    }



}


在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
添加依赖

<dependency>
			<groupId>cn.tedu</groupId>
			<artifactId>sp01-commons</artifactId>
			<version>1.0-SNAPSHOT</version>
		</dependency>
#向注册中心注册时使用这个名字作为服务ID
spring:
  application:
    name: order-service

server:
  port: 8201

在这里插入图片描述

package cn.tedu.sp04.order.service;

import cn.tedu.sp01.pojo.Order;
import cn.tedu.sp01.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class OrderServiceImpl implements OrderService {
    @Override
    public Order getOrder(String orderId) {
        log.info("获取订单,orderId="+orderId);
        //TODO:远程调用商品,获取商品列表
        //TODO:远程调用,获取订单信息
        //假的订单数据
        Order order=new Order();
        order.setId(orderId);
        //order.setUser(用户数据);
        //order.setItems(商品列表);
        return order;
    }

    @Override
    public void addOrder(Order order) {
        //TODO  远程调用商品,减少商品的库存
        //TODO  远程调用用户,增加用户的积分
      log.info("添加订单:"+order);

    }
}

package cn.tedu.sp04.order.controller;

import cn.tedu.sp01.pojo.Item;
import cn.tedu.sp01.pojo.Order;
import cn.tedu.sp01.pojo.User;
import cn.tedu.sp01.service.OrderService;
import cn.tedu.web.util.JsonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;

@RestController
@Slf4j
public class OrderController {
    @Autowired
    private OrderService orderService;
    @GetMapping("/{orderId}")
    public JsonResult<Order> getOrder(@PathVariable String orderId){
        Order order= orderService.getOrder(orderId);
        return JsonResult.ok().msg("成功").data(order);

    }


    @GetMapping("/")
    public JsonResult<?> addOrder(){
        Order order=new Order();
        order.setId("123abc");
        order.setUser(new User(8,null,null));
        order.setItems(Arrays.asList(new Item[] {
                new Item(1,"商品1",2),
                new Item(2,"商品2",1),
                new Item(3,"商品3",3),
                new Item(4,"商品4",1),
                new Item(5,"商品5",5),
        }));
        orderService.addOrder(order);
        return JsonResult.ok().msg("保存订单成功");

    }
}

在这里插入图片描述
在这里插入图片描述

注册中心

微服务系统的核心服务
作用:注册和发现
所有的服务启动,都要把自己的地址注册到注册中心
注册中心中维护的就是一张表
在这里插入图片描述
要调用其他服务,从注册中心获得注册表,来发现得到服务

eureka 注册与发现

在这里插入图片描述
注册中心:zookeeper eureka consul nacos etcd…
1 创建eureka项目
2 配置依赖 pom.xml
3 配置 application.yml
4 主程序启用 eureka 服务器
5 启动,访问测试
eureka工作机制

  • 注册
    服务提供者启动时,会一次次反复尝试向eureka注册,直到注册成功为止

  • 拉取
    消费者每30秒拉取一次注册表,来刷新注册表

  • 心跳
    服务提供者,每30S向eureka发送一次心跳数据
    eureka服务器如果连续3次收不到一个服务的心跳,会删除这个服务的注册信息

  • 自我保护模式
    如果因为网络不稳定,15分钟内,85%的服务器出现心跳异常(一次),会自动进入自我保护模式
    所有的服务注册信息不会删除,等网络恢复后可以自动退出保护模式,自动恢复正常
    开发调试期间,可以禁用保护模式(自我保护模式下不删除服务信息,影响测试)

搭建eureka服务器

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
yml

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.7.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>cn.tedu</groupId>
	<artifactId>sp05-eureka</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>sp05-eureka</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
		<spring-cloud.version>Hoxton.SR9</spring-cloud.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</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>

spring:
  application:
    name: eureka-server

server:
  port: 2001   #默认端口8761

eureka:
  server:
    #禁用自我保护模式
    enable-self-preservation: false
  instance:
    #主机名是为了区分集群中不同的服务器
    hostname: eureka1
  client:
    #针对单台服务器,不向自己注册,也不从自己拉取(配置多台服务器,都改为true相互注册相互拉取)
    register-with-eureka: false
    fetch-registry: false


eureka 集群服务器之间,通过 hostname 来区分

eureka.server.enable-self-preservation

eureka 的自我保护状态:心跳失败的比例,在15分钟内是否超过85%,如果出现了超过的情况,Eureka Server会将当前的实例注册信息保护起来,同时提示一个警告,一旦进入保护模式,Eureka Server将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据。也就是不会注销任何微服务

eureka.client.register-with-eureka=false

不向自身注册

eureka.client.fetch-registry=false

不从自身拉取注册信息

eureka.instance.lease-expiration-duration-in-seconds

最后一次心跳后,间隔多久认定微服务不可用,默认90

package cn.tedu.sp05;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@EnableEurekaServer
@SpringBootApplication
public class Sp05EurekaApplication {

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

}

在这里插入图片描述

127.0.0.1       eureka1
127.0.0.1       eureka2

启动,并访问测试

http://eureka1:2001
在这里插入图片描述

service provider 服务提供者

在这里插入图片描述
修改 item-service、user-service、order-service,把微服务注册到 eureka 服务器
1 pom.xml 添加eureka依赖 eureka client依赖
2 application.yml 添加eureka注册配置 http://eureka1:2001/eureka
3 主程序启用eureka客户端
4 启动服务,在eureka中查看注册信息
在这里插入图片描述
安装插件
在这里插入图片描述
在这里插入图片描述
添加client依赖
添加yml配置

在这里插入图片描述
主程序添加:@EnableDiscoveryClient
204表示注册成功
在这里插入图片描述
在这里插入图片描述
依次修改其余两个项目
在这里插入图片描述
复习:
在这里插入图片描述
在这里插入图片描述
对等结构: 每个服务器地位相等,都是一个peer,没有角色区分,即使宕机不会中断服务
在这里插入图片描述
主从服务:主服务器和从服务器
主服务器宕机,选举出新的主服务器,选举期间服务中断
解决方式:双主双从或者多台主服务器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值