<?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.tedu</groupId> <artifactId>sp01-commons</artifactId> <version>1.0-SNAPSHOT</version> <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.12</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> </project>
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; }
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 cn.tedu.web.util.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); } }
package cn.tedu.sp01.service; import cn.tedu.sp01.pojo.Item; import java.util.List; public interface ItemService { List<Item> getItems(String orderId); void decreaseNumber(List<Item> items); }
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 userId); void addScore(Integer userId, Integer score); }
<?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.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>cn.tedu</groupId> <artifactId>sp02-itemservice</artifactId> <version>0.0.1-SNAPSHOT</version> <name>sp02-itemservice</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <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> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>cn.tedu</groupId> <artifactId>sp01-commons</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!-- 安装 editstarters alt+insert 选择 edit starters --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR8</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> </project>
# html xml # yaml yet another markup language 腋毛 # 向注册中心注册的服务名 spring: application: name: item-service server: port: 8001 # eureka连接地址 # defaultZone 默认地点 # 其他地点配置,需要由云服务来提供 eureka: client: service-url: defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka
package cn.tedu.sp02; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Sp02ItemserviceApplication { public static void main(String[] args) { SpringApplication.run(Sp02ItemserviceApplication.class, args); } }
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.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; @Service @Slf4j public class ItemServiceImpl implements ItemService { // 根据订单id获取订单的商品列表 @Override public List<Item> getItems(String orderId) { ArrayList<Item> items = new ArrayList<>(); items.add(new Item(1,"商品1",1)); items.add(new Item(2,"商品2",3)); items.add(new Item(3,"商品3",5)); items.add(new Item(4,"商品4",2)); items.add(new Item(5,"商品5",1)); return items; } // 减少商品库存 @Override public void decreaseNumber(List<Item> items) { for (Item item:items) { log.info("减少商品库存: "+item); } } }
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 javax.annotation.PostConstruct; import java.util.List; import java.util.Random; @RestController @Slf4j public class ItemController { /* 测试负载均衡时,在浏览器显示端口号 */ @Value("${server.port}") private int port; @Autowired private ItemService itemService; @GetMapping("/{orderId}") //和下面一行等价 //@RequestMapping(path="/{orderId}",method = RequestMethod.GET) // GET //@RequestMapping("/{orderId}") // GET、POST public JsonResult<List<Item>> getItems(@PathVariable String orderId) throws InterruptedException { log.info("获取订单的商品列表, orderId="+orderId); //随机的延迟 if (Math.random() < 0.9) { //延迟 long t = new Random().nextInt(5000); log.info("延迟: "+t); Thread.sleep(t); } List<Item> items = itemService.getItems(orderId); //订单的商品列表 return JsonResult.ok().msg("port="+port).data(items); } /* @RequestBody 完整接收请求协议体的内容,转成商品集合 */ @PostMapping("/decreaseNumber") public JsonResult<?> decreaseNumber(@RequestBody List<Item> items) { itemService.decreaseNumber(items); //减少商品库存 return JsonResult.ok().msg("减少商品库存成功"); } }
package cn.tedu.sp02; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class Sp02ItemserviceApplicationTests { @Test void contextLoads() { } }
<?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.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>cn.tedu</groupId> <artifactId>sp03-userservice</artifactId> <version>0.0.1-SNAPSHOT</version> <name>sp03-userservice</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <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> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>cn.tedu</groupId> <artifactId>sp01-commons</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR8</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> </project>
spring: application: name: user-service server: port: 8101 # 自定义属性 # 测试用的用户数据 sp: user-service: users: "[{\"id\":7, \"username\":\"abc\",\"password\":\"123\"},{\"id\":8, \"username\":\"def\",\"password\":\"456\"},{\"id\":9, \"username\":\"ghi\",\"password\":\"789\"}]" eureka: client: service-url: defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka
package cn.tedu.sp03; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Sp03UserserviceApplication { public static void main(String[] args) { SpringApplication.run(Sp03UserserviceApplication.class, args); } }
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; //yml配置中的测试用用户数据 //根据用户id获取用户 @Override public User getUser(Integer userId) { log.info("获取用户,userId="+userId+", userJson="+userJson); //从测试用的用户数据中寻找 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 userId, Integer score) { log.info("增加用户积分,userId="+userId+", 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.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 user = userService.getUser(userId); //获取用户 return JsonResult.ok().data(user); } // http://localhsot:8101/8/score?score=1000 @GetMapping("/{userId}/score") public JsonResult<?> addScore(@PathVariable Integer userId, Integer score) { userService.addScore(userId, score); //增加用户积分 return JsonResult.ok().msg("增加用户积分成功"); // "{code:200, msg:'xxxxxxx', data:null}" } }
package cn.tedu.sp03; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class Sp03UserserviceApplicationTests { @Test void contextLoads() { } }
<?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.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>cn.tedu</groupId> <artifactId>sp04-orderservice</artifactId> <version>0.0.1-SNAPSHOT</version> <name>sp04-orderservice</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <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> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>cn.tedu</groupId> <artifactId>sp01-commons</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR8</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> </project>
package cn.tedu.sp04; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Sp04OrderserviceApplication { public static void main(String[] args) { SpringApplication.run(Sp04OrderserviceApplication.class, args); } }
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) { /* 获取订单 调用用户获取用户数据,调用商品获取商品列表 */ //TODO: 远程调用商品服务,获取商品 //TODO: 远程调用用户,获取用户数据 Order order = new Order(); order.setId(orderId); //order.setItems(商品列表); //order.setUser(用户); return order; } @Override public void addOrder(Order order) { 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; //根据订单id获取订单 @GetMapping("/{orderId}") public JsonResult<Order> getOrder(@PathVariable String orderId) { log.info("获取订单: orderId"+orderId); Order order = orderService.getOrder(orderId); return JsonResult.ok().data(order); } //添加订单,demo演示,不接收任何参数,数据在方法中写死 @GetMapping("/") public JsonResult<?> addOrder() { //订单对象中包含: 订单id,用户,购买的商品 Order order = new Order( "6u5u645y34", new User(8,"用户8", "密码8"), Arrays.asList(new Item[]{ new Item(1, "商品1", 2), new Item(2, "商品2", 1), new Item(3, "商品3", 1), new Item(4, "商品4", 4), new Item(5, "商品5", 3) })); orderService.addOrder(order); return JsonResult.ok().msg("添加订单成功"); } }
package cn.tedu.sp04; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class Sp04OrderserviceApplicationTests { @Test void contextLoads() { } }
<?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.4.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.SR8</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 eureka: server: enable-self-preservation: false #关闭保护模式 instance: hostname: eureka1 #集群服务器间用主机名区分 client: #单台服务器,不向自己注册,不从自己拉取 register-with-eureka: false fetch-registry: false
# application-eureka1.yml # 激活当前profile: --spring.profiles.active=eureka1 eureka: instance: hostname: eureka1 client: register-with-eureka: true fetch-registry: true service-url: defaultZone: http://eureka2:2002/eureka
# application-eureka2.yml # 激活当前profile: --spring.profiles.active=eureka2 eureka: instance: hostname: eureka2 client: register-with-eureka: true fetch-registry: true service-url: defaultZone: http://eureka1:2001/eureka
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); } }
package cn.tedu.sp05; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class Sp05EurekaApplicationTests { @Test void contextLoads() { } }
<?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.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>cn.tedu</groupId> <artifactId>sp06-ribbon</artifactId> <version>0.0.1-SNAPSHOT</version> <name>sp06-ribbon</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Hoxton.SR8</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</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> <dependency> <groupId>cn.tedu</groupId> <artifactId>sp01-commons</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </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: ribbon server: port: 3001 eureka: client: service-url: defaultZone: http://eureka1:2001/eureka,http://eureka2:2002/eureka ribbon: # 单台服务器重试次数 MaxAutoRetries: 1 # 更换服务器的次数 MaxAutoRetriesNextServer: 2 #hystrix: # command: # default: # execution: # isolation: # thread: # timeoutInMilliseconds: 500 #默认1000 management: endpoints: web: exposure: include: hystrix.stream #"*" #- beans #- env
package cn.tedu.sp06; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; @EnableCircuitBreaker @SpringBootApplication public class Sp06RibbonApplication { public static void main(String[] args) { SpringApplication.run(Sp06RibbonApplication.class, args); } /* 可以放在启动类中, 或者也可以放在自定义的自动配置类 */ @Bean @LoadBalanced //ribbon的注解,对RestTemplate进行增强 public RestTemplate restTemplate() { SimpleClientHttpRequestFactory f = new SimpleClientHttpRequestFactory(); f.setConnectTimeout(1000); //连接超时 f.setReadTimeout(1000); //等待响应超时 return new RestTemplate(f); } }
package cn.tedu.sp06.controller; import cn.tedu.sp01.pojo.Item; import cn.tedu.sp01.pojo.Order; import cn.tedu.sp01.pojo.User; import cn.tedu.web.util.JsonResult; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import org.springframework.web.client.RestTemplate; import java.util.List; @RestController @Slf4j public class RibbonController { @Autowired private RestTemplate rt; // 调用远程的商品服务 // 如果远程调用失败,跳转到另一段代码去执行 @HystrixCommand(fallbackMethod = "getItemsFB") @GetMapping("/item-service/{orderId}") public JsonResult<List<Item>> getItems(@PathVariable String orderId) { //调用远程服务 // {1} 是 RestTemplate 定义的一种占位符格式,后面第三个参数 orderId 会对占位符进行填充 return rt.getForObject("http://item-service/{1}",JsonResult.class,orderId); } @HystrixCommand(fallbackMethod = "decreaseNumberFB") @PostMapping("/item-service/decreaseNumber") public JsonResult<?> decreaseNumber(@RequestBody List<Item> items) { // 调用商品服务,减少商品库存 //items post请求协议体数据 return rt.postForObject("http://item-service/decreaseNumber",items, JsonResult.class); } @HystrixCommand(fallbackMethod = "getUserFB") @GetMapping("/user-service/{userId}") public JsonResult<User> getUser(@PathVariable Integer userId) { return rt.getForObject("http://user-service/{1}", JsonResult.class, userId); } @HystrixCommand(fallbackMethod = "addScoreFB") @GetMapping("/user-service/{userId}/score") public JsonResult<?> addScore(@PathVariable Integer userId, Integer score) { return rt.getForObject("http://user-service/{1}/score?score={2}", JsonResult.class, userId, score); } @HystrixCommand(fallbackMethod = "getOrderFB") @GetMapping("/order-service/{orderId}") public JsonResult<Order> getOrder(@PathVariable String orderId) { return rt.getForObject("http://order-service/{1}", JsonResult.class, orderId); } @HystrixCommand(fallbackMethod = "addOrderFB") @GetMapping("/order-service/") public JsonResult<?> addOrder() { return rt.getForObject("http://order-service/", JsonResult.class); } // public JsonResult<List<Item>> getItemsFB(String orderId) { return JsonResult.err().msg("获取订单的商品列表失败"); } public JsonResult<?> decreaseNumberFB(List<Item> items) { return JsonResult.err().msg("减少商品库存失败"); } public JsonResult<User> getUserFB(Integer userId) { return JsonResult.err().msg("获取用户失败"); } public JsonResult<?> addScoreFB(Integer userId, Integer score) { return JsonResult.err().msg("增加用户积分失败"); } public JsonResult<Order> getOrderFB(String orderId) { return JsonResult.err().msg("获取订单失败"); } public JsonResult<?> addOrderFB() { return JsonResult.err().msg("保存订单失败"); } }
package cn.tedu.sp06; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class Sp06RibbonApplicationTests { @Test void contextLoads() { } }
<?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.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>cn.tedu</groupId> <artifactId>sp08-hystrix-dashboard</artifactId> <version>0.0.1-SNAPSHOT</version> <name>sp08-hystrix-dashboard</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Hoxton.SR8</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</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: hystrix-dashboard server: port: 4001 # 配置允许监控的主机地址 hystrix: dashboard: proxy-stream-allow-list: localhost
package cn.tedu.sp08; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard; @EnableHystrixDashboard @SpringBootApplication public class Sp08HystrixDashboardApplication { public static void main(String[] args) { SpringApplication.run(Sp08HystrixDashboardApplication.class, args); } }
package cn.tedu.sp08; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class Sp08HystrixDashboardApplicationTests { @Test void contextLoads() { } }