(codeMsg);
+ }
+
+ private Result(T data) {
+ this.data = data;
+ }
+
+ private Result(int code, String msg) {
+ this.code = code;
+ this.msg = msg;
+ }
+
+ private Result(CodeMsg codeMsg) {
+ if(codeMsg != null) {
+ this.code = codeMsg.getCode();
+ this.msg = codeMsg.getMsg();
+ }
+ }
+
+
+ public int getCode() {
+ return code;
+ }
+ public void setCode(int code) {
+ this.code = code;
+ }
+ public String getMsg() {
+ return msg;
+ }
+ public void setMsg(String msg) {
+ this.msg = msg;
+ }
+ public T getData() {
+ return data;
+ }
+ public void setData(T data) {
+ this.data = data;
+ }
+}
diff --git a/src/demo/manage/leyou-common/src/main/java/com/leyou/utils/CodecUtils.java b/src/demo/manage/leyou-common/src/main/java/com/leyou/utils/CodecUtils.java
new file mode 100644
index 00000000..0748d710
--- /dev/null
+++ b/src/demo/manage/leyou-common/src/main/java/com/leyou/utils/CodecUtils.java
@@ -0,0 +1,20 @@
+package com.leyou.utils;
+
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+
+/**
+ * @Author: 98050
+ * @Time: 2018-10-23 10:49
+ * @Feature: 密码加密
+ */
+public class CodecUtils {
+
+ public static String passwordBcryptEncode(String username,String password){
+
+ return new BCryptPasswordEncoder().encode(username + password);
+ }
+
+ public static Boolean passwordConfirm(String rawPassword,String encodePassword){
+ return new BCryptPasswordEncoder().matches(rawPassword,encodePassword);
+ }
+}
diff --git a/src/demo/manage/leyou-common/src/main/java/com/leyou/utils/CookieUtils.java b/src/demo/manage/leyou-common/src/main/java/com/leyou/utils/CookieUtils.java
new file mode 100644
index 00000000..79096d82
--- /dev/null
+++ b/src/demo/manage/leyou-common/src/main/java/com/leyou/utils/CookieUtils.java
@@ -0,0 +1,222 @@
+package com.leyou.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+
+/**
+ *
+ * Cookie 工具类
+ * @author li
+ * @time 2018/8/5
+ */
+public final class CookieUtils {
+
+ protected static final Logger logger = LoggerFactory.getLogger(CookieUtils.class);
+
+ /**
+ * 得到Cookie的值, 不编码
+ *
+ * @param request
+ * @param cookieName
+ * @return
+ */
+ public static String getCookieValue(HttpServletRequest request, String cookieName) {
+ return getCookieValue(request, cookieName, false);
+ }
+
+ /**
+ * 得到Cookie的值
+ *
+ * @param request
+ * @param cookieName
+ * @return
+ */
+ public static String getCookieValue(HttpServletRequest request, String cookieName, boolean isDecoder) {
+ Cookie[] cookieList = request.getCookies();
+ if (cookieList == null || cookieName == null){
+ return null;
+ }
+ String retValue = null;
+ try {
+ for (int i = 0; i < cookieList.length; i++) {
+ if (cookieList[i].getName().equals(cookieName)) {
+ if (isDecoder) {
+ retValue = URLDecoder.decode(cookieList[i].getValue(), "UTF-8");
+ } else {
+ retValue = cookieList[i].getValue();
+ }
+ break;
+ }
+ }
+ } catch (UnsupportedEncodingException e) {
+ logger.error("Cookie Decode Error.", e);
+ }
+ return retValue;
+ }
+
+ /**
+ * 得到Cookie的值,
+ *
+ * @param request
+ * @param cookieName
+ * @return
+ */
+ public static String getCookieValue(HttpServletRequest request, String cookieName, String encodeString) {
+ Cookie[] cookieList = request.getCookies();
+ if (cookieList == null || cookieName == null){
+ return null;
+ }
+ String retValue = null;
+ try {
+ for (int i = 0; i < cookieList.length; i++) {
+ if (cookieList[i].getName().equals(cookieName)) {
+ retValue = URLDecoder.decode(cookieList[i].getValue(), encodeString);
+ break;
+ }
+ }
+ } catch (UnsupportedEncodingException e) {
+ logger.error("Cookie Decode Error.", e);
+ }
+ return retValue;
+ }
+
+ /**
+ * 设置Cookie的值 不设置生效时间默认浏览器关闭即失效,也不编码
+ */
+ public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue) {
+ setCookie(request, response, cookieName, cookieValue, -1);
+ }
+
+ /**
+ * 设置Cookie的值 在指定时间内生效,但不编码
+ */
+ public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage) {
+ setCookie(request, response, cookieName, cookieValue, cookieMaxage, false);
+ }
+
+ /**
+ * 设置Cookie的值 不设置生效时间,但编码
+ */
+ public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, boolean isEncode) {
+ setCookie(request, response, cookieName, cookieValue, -1, isEncode);
+ }
+
+ /**
+ * 设置Cookie的值 在指定时间内生效, 编码参数
+ */
+ public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage, boolean isEncode) {
+ doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, isEncode);
+ }
+
+ /**
+ * 设置Cookie的值 在指定时间内生效, 编码参数(指定编码)
+ */
+ public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage, String encodeString) {
+ doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, encodeString);
+ }
+
+ /**
+ * 删除Cookie带cookie域名
+ */
+ public static void deleteCookie(HttpServletRequest request, HttpServletResponse response, String cookieName) {
+ doSetCookie(request, response, cookieName, "", -1, false);
+ }
+
+ /**
+ * 设置Cookie的值,并使其在指定时间内生效
+ *
+ * @param cookieMaxage
+ * cookie生效的最大秒数
+ */
+ private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage, boolean isEncode) {
+ try {
+ if (cookieValue == null) {
+ cookieValue = "";
+ } else if (isEncode) {
+ cookieValue = URLEncoder.encode(cookieValue, "utf-8");
+ }
+ Cookie cookie = new Cookie(cookieName, cookieValue);
+ if (cookieMaxage > 0) {
+ cookie.setMaxAge(cookieMaxage);
+ }
+ if (null != request) {
+ // 设置域名的cookie
+ cookie.setDomain(getDomainName(request));
+ }
+ cookie.setPath("/");
+ response.addCookie(cookie);
+ } catch (Exception e) {
+ logger.error("Cookie Encode Error.", e);
+ }
+ }
+
+ /**
+ * 设置Cookie的值,并使其在指定时间内生效
+ *
+ * @param cookieMaxage
+ * cookie生效的最大秒数
+ */
+ private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage, String encodeString) {
+ try {
+ if (cookieValue == null) {
+ cookieValue = "";
+ } else {
+ cookieValue = URLEncoder.encode(cookieValue, encodeString);
+ }
+ Cookie cookie = new Cookie(cookieName, cookieValue);
+ if (cookieMaxage > 0) {
+ cookie.setMaxAge(cookieMaxage);
+ }
+ if (null != request){
+ // 设置域名的cookie
+ cookie.setDomain(getDomainName(request));
+ }
+ cookie.setPath("/");
+ response.addCookie(cookie);
+ } catch (Exception e) {
+ logger.error("Cookie Encode Error.", e);
+ }
+ }
+
+ /**
+ * 得到cookie的域名
+ */
+ private static final String getDomainName(HttpServletRequest request) {
+ String domainName = null;
+
+ String serverName = request.getRequestURL().toString();
+ if (serverName == null || serverName.equals("")) {
+ domainName = "";
+ } else {
+ serverName = serverName.toLowerCase();
+ serverName = serverName.substring(7);
+ final int end = serverName.indexOf("/");
+ serverName = serverName.substring(0, end);
+ final String[] domains = serverName.split("\\.");
+ int len = domains.length;
+ if (len > 3) {
+ // www.xxx.com.cn
+ domainName = domains[len - 3] + "." + domains[len - 2] + "." + domains[len - 1];
+ } else if (len <= 3 && len > 1) {
+ // xxx.com or xxx.cn
+ domainName = domains[len - 2] + "." + domains[len - 1];
+ } else {
+ domainName = serverName;
+ }
+ }
+
+ if (domainName != null && domainName.indexOf(":") > 0) {
+ String[] ary = domainName.split("\\:");
+ domainName = ary[0];
+ }
+ return domainName;
+ }
+
+}
diff --git a/src/demo/manage/leyou-common/src/main/java/com/leyou/utils/IdWorker.java b/src/demo/manage/leyou-common/src/main/java/com/leyou/utils/IdWorker.java
new file mode 100644
index 00000000..d3e7947e
--- /dev/null
+++ b/src/demo/manage/leyou-common/src/main/java/com/leyou/utils/IdWorker.java
@@ -0,0 +1,187 @@
+package com.leyou.utils;
+
+import java.lang.management.ManagementFactory;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+
+/**
+ * 名称:IdWorker.java
+ * 描述:分布式自增长ID
+ *
+ * Twitter的 Snowflake JAVA实现方案
+ *
+ * 核心代码为其IdWorker这个类实现,其原理结构如下,我分别用一个0表示一位,用—分割开部分的作用:
+ * 1||0---0000000000 0000000000 0000000000 0000000000 0 --- 00000 ---00000 ---000000000000
+ * 在上面的字符串中,第一位为未使用(实际上也可作为long的符号位),接下来的41位为毫秒级时间,
+ * 然后5位datacenter标识位,5位机器ID(并不算标识符,实际是为线程标识),
+ * 然后12位该毫秒内的当前毫秒内的计数,加起来刚好64位,为一个Long型。
+ * 这样的好处是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由datacenter和机器ID作区分),
+ * 并且效率较高,经测试,snowflake每秒能够产生26万ID左右,完全满足需要。
+ *
+ * 64位ID (42(毫秒)+5(机器ID)+5(业务编码)+12(重复累加))
+ *
+ * @author Polim
+ */
+public class IdWorker {
+ /**
+ * 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动)
+ */
+ private final static long twepoch = 1288834974657L;
+ /**
+ * 机器标识位数
+ */
+ private final static long workerIdBits = 5L;
+ /**
+ * 数据中心标识位数
+ */
+ private final static long datacenterIdBits = 5L;
+ /**
+ * 机器ID最大值
+ */
+ private final static long maxWorkerId = -1L ^ (-1L << workerIdBits);
+ /**
+ * 数据中心ID最大值
+ */
+ private final static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
+ /**
+ * 毫秒内自增位
+ */
+ private final static long sequenceBits = 12L;
+ /**
+ * 机器ID偏左移12位
+ */
+ private final static long workerIdShift = sequenceBits;
+ /**
+ * 数据中心ID左移17位
+ */
+ private final static long datacenterIdShift = sequenceBits + workerIdBits;
+ /**
+ * 时间毫秒左移22位
+ */
+ private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
+
+ private final static long sequenceMask = -1L ^ (-1L << sequenceBits);
+ /**
+ * 上次生产id时间戳
+ */
+ private static long lastTimestamp = -1L;
+ /**
+ * 并发控制
+ */
+ private long sequence = 0L;
+
+ private final long workerId;
+ /**
+ * 数据标识id部分
+ */
+ private final long datacenterId;
+
+ public IdWorker(){
+ this.datacenterId = getDatacenterId(maxDatacenterId);
+ this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);
+ }
+ /**
+ * @param workerId
+ * 工作机器ID
+ * @param datacenterId
+ * 序列号
+ */
+ public IdWorker(long workerId, long datacenterId) {
+ if (workerId > maxWorkerId || workerId < 0) {
+ throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
+ }
+ if (datacenterId > maxDatacenterId || datacenterId < 0) {
+ throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
+ }
+ this.workerId = workerId;
+ this.datacenterId = datacenterId;
+ }
+ /**
+ * 获取下一个ID
+ *
+ * @return
+ */
+ public synchronized long nextId() {
+ long timestamp = timeGen();
+ if (timestamp < lastTimestamp) {
+ throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
+ }
+
+ if (lastTimestamp == timestamp) {
+ // 当前毫秒内,则+1
+ sequence = (sequence + 1) & sequenceMask;
+ if (sequence == 0) {
+ // 当前毫秒内计数满了,则等待下一秒
+ timestamp = tilNextMillis(lastTimestamp);
+ }
+ } else {
+ sequence = 0L;
+ }
+ lastTimestamp = timestamp;
+ // ID偏移组合生成最终的ID,并返回ID
+ long nextId = ((timestamp - twepoch) << timestampLeftShift)
+ | (datacenterId << datacenterIdShift)
+ | (workerId << workerIdShift) | sequence;
+
+ return nextId;
+ }
+
+ private long tilNextMillis(final long lastTimestamp) {
+ long timestamp = this.timeGen();
+ while (timestamp <= lastTimestamp) {
+ timestamp = this.timeGen();
+ }
+ return timestamp;
+ }
+
+ private long timeGen() {
+ return System.currentTimeMillis();
+ }
+
+ /**
+ *
+ * 获取 maxWorkerId
+ *
+ */
+ protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {
+ StringBuffer mpid = new StringBuffer();
+ mpid.append(datacenterId);
+ String name = ManagementFactory.getRuntimeMXBean().getName();
+ if (!name.isEmpty()) {
+ /*
+ * GET jvmPid
+ */
+ mpid.append(name.split("@")[0]);
+ }
+ /*
+ * MAC + PID 的 hashcode 获取16个低位
+ */
+ return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
+ }
+
+ /**
+ *
+ * 数据标识id部分
+ *
+ */
+ protected static long getDatacenterId(long maxDatacenterId) {
+ long id = 0L;
+ try {
+ InetAddress ip = InetAddress.getLocalHost();
+ NetworkInterface network = NetworkInterface.getByInetAddress(ip);
+ if (network == null) {
+ id = 1L;
+ } else {
+ byte[] mac = network.getHardwareAddress();
+ id = ((0x000000FF & (long) mac[mac.length - 1])
+ | (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;
+ id = id % (maxDatacenterId + 1);
+ }
+ } catch (Exception e) {
+ System.out.println(" getDatacenterId: " + e.getMessage());
+ }
+ return id;
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/demo/manage/leyou-common/src/main/java/com/leyou/utils/JsonUtils.java b/src/demo/manage/leyou-common/src/main/java/com/leyou/utils/JsonUtils.java
new file mode 100644
index 00000000..2850137a
--- /dev/null
+++ b/src/demo/manage/leyou-common/src/main/java/com/leyou/utils/JsonUtils.java
@@ -0,0 +1,79 @@
+package com.leyou.utils;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.sun.istack.internal.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author: li
+ * @create: 2018-04-24 17:20
+ **/
+public class JsonUtils {
+
+ public static final ObjectMapper mapper = new ObjectMapper();
+
+ private static final Logger logger = LoggerFactory.getLogger(JsonUtils.class);
+
+ @Nullable
+ public static String serialize(Object obj) {
+ if (obj == null) {
+ return null;
+ }
+ if (obj.getClass() == String.class) {
+ return (String) obj;
+ }
+ try {
+ return mapper.writeValueAsString(obj);
+ } catch (JsonProcessingException e) {
+ logger.error("json序列化出错:" + obj, e);
+ return null;
+ }
+ }
+
+ @Nullable
+ public static T parse(String json, Class tClass) {
+ try {
+ return mapper.readValue(json, tClass);
+ } catch (IOException e) {
+ logger.error("json解析出错:" + json, e);
+ return null;
+ }
+ }
+
+ @Nullable
+ public static List parseList(String json, Class eClass) {
+ try {
+ return mapper.readValue(json, mapper.getTypeFactory().constructCollectionType(List.class, eClass));
+ } catch (IOException e) {
+ logger.error("json解析出错:" + json, e);
+ return null;
+ }
+ }
+
+ @Nullable
+ public static Map parseMap(String json, Class kClass, Class vClass) {
+ try {
+ return mapper.readValue(json, mapper.getTypeFactory().constructMapType(Map.class, kClass, vClass));
+ } catch (IOException e) {
+ logger.error("json解析出错:" + json, e);
+ return null;
+ }
+ }
+
+ @Nullable
+ public static T nativeRead(String json, TypeReference type) {
+ try {
+ return mapper.readValue(json, type);
+ } catch (IOException e) {
+ logger.error("json解析出错:" + json, e);
+ return null;
+ }
+ }
+}
diff --git a/src/demo/manage/leyou-common/src/main/java/com/leyou/utils/NumberUtils.java b/src/demo/manage/leyou-common/src/main/java/com/leyou/utils/NumberUtils.java
new file mode 100644
index 00000000..ac32ad5c
--- /dev/null
+++ b/src/demo/manage/leyou-common/src/main/java/com/leyou/utils/NumberUtils.java
@@ -0,0 +1,75 @@
+package com.leyou.utils;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.regex.MatchResult;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author: 98050
+ * @create: 2018-04-25 09:13
+ **/
+public class NumberUtils {
+
+ public static boolean isInt(Double num) {
+ return num.intValue() == num;
+ }
+
+ /**
+ * 判断字符串是否是数值格式
+ * @param str
+ * @return
+ */
+ public static boolean isDigit(String str){
+ if(str == null || str.trim().equals("")){
+ return false;
+ }
+ return str.matches("^\\d+$");
+ }
+
+ /**
+ * 将一个小数精确到指定位数
+ * @param num
+ * @param scale
+ * @return
+ */
+ public static double scale(double num, int scale) {
+ BigDecimal bd = new BigDecimal(num);
+ return bd.setScale(scale, RoundingMode.HALF_UP).doubleValue();
+ }
+
+ /**
+ * 从字符串中根据正则表达式寻找,返回找到的数字数组
+ * @param value
+ * @param regex
+ * @return
+ */
+ public static Double[] searchNumber(String value, String regex){
+ List doubles = new ArrayList<>();
+ Pattern pattern = Pattern.compile(regex);
+ Matcher matcher = pattern.matcher(value);
+ if(matcher.find()) {
+ MatchResult result = matcher.toMatchResult();
+ for (int i = 1; i <= result.groupCount(); i++) {
+ doubles.add(Double.valueOf(result.group(i)));
+ }
+ }
+ return doubles.toArray(new Double[doubles.size()]);
+ }
+
+ /**
+ * 生成指定位数的随机数字
+ * @param len
+ * @return
+ */
+ public static String generateCode(int len){
+ len = Math.min(len, 8);
+ int min = Double.valueOf(Math.pow(10, len - 1)).intValue();
+ int num = new Random().nextInt(Double.valueOf(Math.pow(10, len + 1)).intValue() - 1) + min;
+ return String.valueOf(num).substring(0,len);
+ }
+}
diff --git a/src/demo/manage/leyou-common/src/main/java/com/leyou/utils/Test.java b/src/demo/manage/leyou-common/src/main/java/com/leyou/utils/Test.java
new file mode 100644
index 00000000..d639099b
--- /dev/null
+++ b/src/demo/manage/leyou-common/src/main/java/com/leyou/utils/Test.java
@@ -0,0 +1,16 @@
+package com.leyou.utils;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Author: 98050
+ * Time: 2018-08-05 15:58
+ * Feature:
+ */
+public class Test {
+ public static void main(String[] args) {
+ List lis = Arrays.asList(1, 2, 3);
+ lis.forEach(num -> System.out.println(num));
+ }
+}
diff --git a/src/demo/manage/leyou-config/pom.xml b/src/demo/manage/leyou-config/pom.xml
new file mode 100644
index 00000000..afc4627e
--- /dev/null
+++ b/src/demo/manage/leyou-config/pom.xml
@@ -0,0 +1,65 @@
+
+
+
+ leyou
+ com.leyou.parent
+ 1.0.0-SNAPSHOT
+
+ 4.0.0
+
+ com.leyou.config
+ leyou-config
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.cloud
+ spring-cloud-config-server
+
+
+
+ org.springframework.cloud
+ spring-cloud-bus
+
+
+
+ org.springframework.cloud
+ spring-cloud-stream-binder-rabbit
+
+
+
+
+ app
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ com.spotify
+ docker-maven-plugin
+ 0.4.13
+
+ 47.104.175.20:5000/${project.artifactId}:${project.version}
+ jdk1.8
+ ["java", "-jar","/${project.build.finalName}.jar"]
+
+
+ /
+ ${project.build.directory}
+ ${project.build.finalName}.jar
+
+
+ http://47.104.175.20:2375
+
+
+
+
+
\ No newline at end of file
diff --git a/src/demo/manage/leyou-config/src/main/java/com/leyou/config/LyConfigApplication.java b/src/demo/manage/leyou-config/src/main/java/com/leyou/config/LyConfigApplication.java
new file mode 100644
index 00000000..c0446488
--- /dev/null
+++ b/src/demo/manage/leyou-config/src/main/java/com/leyou/config/LyConfigApplication.java
@@ -0,0 +1,19 @@
+package com.leyou.config;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.config.server.EnableConfigServer;
+
+/**
+ * @Author: 98050
+ * @Time: 2018-11-28 16:39
+ * @Feature: 配置中心
+ */
+@EnableConfigServer
+@SpringBootApplication
+public class LyConfigApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(LyConfigApplication.class,args);
+ }
+}
diff --git a/src/demo/manage/leyou-config/src/main/java/com/leyou/config/myconfig/MvcConfig.java b/src/demo/manage/leyou-config/src/main/java/com/leyou/config/myconfig/MvcConfig.java
new file mode 100644
index 00000000..41575a65
--- /dev/null
+++ b/src/demo/manage/leyou-config/src/main/java/com/leyou/config/myconfig/MvcConfig.java
@@ -0,0 +1,27 @@
+package com.leyou.config.myconfig;
+
+import come.leyou.config.filter.MyFilter;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * @Author: 98050
+ * @Time: 2018-11-30 20:56
+ * @Feature:
+ */
+@Configuration
+public class MvcConfig implements WebMvcConfigurer {
+
+ @Bean
+ public FilterRegistrationBean someFilterRegistration1() {
+ //新建过滤器注册类
+ FilterRegistrationBean registration = new FilterRegistrationBean();
+ // 添加我们写好的过滤器
+ registration.setFilter( new MyFilter());
+ // 设置过滤器的URL模式
+ registration.addUrlPatterns("/*");
+ return registration;
+ }
+}
diff --git a/src/demo/manage/leyou-config/src/main/java/come/leyou/config/filter/CustometRequestWrapper.java b/src/demo/manage/leyou-config/src/main/java/come/leyou/config/filter/CustometRequestWrapper.java
new file mode 100644
index 00000000..ce044dc1
--- /dev/null
+++ b/src/demo/manage/leyou-config/src/main/java/come/leyou/config/filter/CustometRequestWrapper.java
@@ -0,0 +1,44 @@
+package come.leyou.config.filter;
+
+import javax.servlet.ReadListener;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+/**
+ * @author 98050
+ */
+public class CustometRequestWrapper extends HttpServletRequestWrapper {
+ public CustometRequestWrapper(HttpServletRequest request) {
+ super(request);
+ }
+
+ @Override
+ public ServletInputStream getInputStream() throws IOException {
+ byte[] bytes = new byte[0];
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
+
+ return new ServletInputStream() {
+ @Override
+ public boolean isFinished() {
+ return byteArrayInputStream.read() == -1 ? true:false;
+ }
+
+ @Override
+ public boolean isReady() {
+ return false;
+ }
+
+ @Override
+ public void setReadListener(ReadListener readListener) {
+
+ }
+
+ @Override
+ public int read() throws IOException {
+ return byteArrayInputStream.read();
+ }
+ };
+ }
+ }
\ No newline at end of file
diff --git a/src/demo/manage/leyou-config/src/main/java/come/leyou/config/filter/MyFilter.java b/src/demo/manage/leyou-config/src/main/java/come/leyou/config/filter/MyFilter.java
new file mode 100644
index 00000000..d5b55592
--- /dev/null
+++ b/src/demo/manage/leyou-config/src/main/java/come/leyou/config/filter/MyFilter.java
@@ -0,0 +1,47 @@
+package come.leyou.config.filter;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * @Author: 98050
+ * @Time: 2018-11-30 20:59
+ * @Feature:
+ */
+public class MyFilter implements Filter {
+
+ private Logger logger = LoggerFactory.getLogger(MyFilter.class);
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ logger.info("过滤器启动");
+ }
+
+ @Override
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
+ HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
+ HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
+ String url = httpServletRequest.getRequestURI();
+
+ //过滤/actuator/bus-refresh请求
+ String suffix = "/bus-refresh";
+ if (!url.endsWith(suffix)){
+ filterChain.doFilter(servletRequest,servletResponse);
+ return;
+ }
+
+ CustometRequestWrapper requestWrapper = new CustometRequestWrapper(httpServletRequest);
+ filterChain.doFilter(requestWrapper,servletResponse);
+
+ }
+
+ @Override
+ public void destroy() {
+ logger.info("过滤器销毁");
+ }
+}
diff --git a/src/demo/manage/leyou-config/src/main/resources/application.yml b/src/demo/manage/leyou-config/src/main/resources/application.yml
new file mode 100644
index 00000000..56ca3174
--- /dev/null
+++ b/src/demo/manage/leyou-config/src/main/resources/application.yml
@@ -0,0 +1,22 @@
+server:
+ port: 10011
+spring:
+ application:
+ name: leyou-config
+ cloud:
+ config:
+ server:
+ git:
+ uri: https://github.com/lyj8330328/leyou-config.git
+ rabbitmq:
+ host: 192.168.19.121
+ username: /leyou
+ password: leyou
+ virtual-host: /leyou
+
+
+management: #暴露触发消息总线的地址
+ endpoints:
+ web:
+ exposure:
+ include: bus-refresh
diff --git a/src/demo/manage/leyou-goods-web/pom.xml b/src/demo/manage/leyou-goods-web/pom.xml
new file mode 100644
index 00000000..d0af25f7
--- /dev/null
+++ b/src/demo/manage/leyou-goods-web/pom.xml
@@ -0,0 +1,108 @@
+
+
+
+ leyou
+ com.leyou.parent
+ 1.0.0-SNAPSHOT
+
+ 4.0.0
+
+ com.leyou.goods
+ leyou-goods-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-netflix-eureka-client
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+
+ org.springframework.boot
+ spring-boot-starter-amqp
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+
+
+
+ com.leyou.item.interface
+ leyou-item-interface
+ 1.0.0-SNAPSHOT
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+
+
+
+ org.springframework.cloud
+ spring-cloud-bus
+
+
+
+ org.springframework.cloud
+ spring-cloud-stream-binder-rabbit
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+
+ app
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ com.spotify
+ docker-maven-plugin
+ 0.4.13
+
+ 47.104.175.20:5000/${project.artifactId}:${project.version}
+ jdk1.8
+ ["java", "-jar","/${project.build.finalName}.jar"]
+
+
+ /
+ ${project.build.directory}
+ ${project.build.finalName}.jar
+
+
+ http://47.104.175.20:2375
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/LyGoodsWebApplication.java b/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/LyGoodsWebApplication.java
new file mode 100644
index 00000000..c3f7c35d
--- /dev/null
+++ b/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/LyGoodsWebApplication.java
@@ -0,0 +1,22 @@
+package com.leyou;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+
+/**
+ * @Author: 98050
+ * Time: 2018-10-17 11:10
+ * Feature: 商品详情微服务启动器,开启fegin功能
+ */
+@SpringBootApplication
+@EnableDiscoveryClient
+@EnableFeignClients
+public class LyGoodsWebApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(LyGoodsWebApplication.class,args);
+ }
+}
diff --git a/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/client/BrandClient.java b/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/client/BrandClient.java
new file mode 100644
index 00000000..05f53936
--- /dev/null
+++ b/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/client/BrandClient.java
@@ -0,0 +1,14 @@
+package com.leyou.client;
+
+/**
+ * @Author: 98050
+ * Time: 2018-10-17 18:59
+ * Feature:品牌FeignClient
+ */
+
+import com.leyou.item.api.BrandApi;
+import org.springframework.cloud.openfeign.FeignClient;
+
+@FeignClient(value = "item-service")
+public interface BrandClient extends BrandApi {
+}
diff --git a/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/client/CategoryClient.java b/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/client/CategoryClient.java
new file mode 100644
index 00000000..19714b68
--- /dev/null
+++ b/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/client/CategoryClient.java
@@ -0,0 +1,13 @@
+package com.leyou.client;
+
+import com.leyou.item.api.CategoryApi;
+import org.springframework.cloud.openfeign.FeignClient;
+
+/**
+ * @Author: 98050
+ * Time: 2018-10-17 19:01
+ * Feature:商品分类FeignClient
+ */
+@FeignClient(value = "item-service")
+public interface CategoryClient extends CategoryApi {
+}
diff --git a/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/client/GoodsClient.java b/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/client/GoodsClient.java
new file mode 100644
index 00000000..be41c9b7
--- /dev/null
+++ b/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/client/GoodsClient.java
@@ -0,0 +1,13 @@
+package com.leyou.client;
+
+import com.leyou.item.api.GoodsApi;
+import org.springframework.cloud.openfeign.FeignClient;
+
+/**
+ * @Author: 98050
+ * Time: 2018-10-17 18:55
+ * Feature:商品FeignClient
+ */
+@FeignClient(value = "item-service")
+public interface GoodsClient extends GoodsApi {
+}
diff --git a/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/client/SpecClient.java b/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/client/SpecClient.java
new file mode 100644
index 00000000..79bc459b
--- /dev/null
+++ b/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/client/SpecClient.java
@@ -0,0 +1,13 @@
+package com.leyou.client;
+
+import com.leyou.item.api.SpecApi;
+import org.springframework.cloud.openfeign.FeignClient;
+
+/**
+ * @Author: 98050
+ * Time: 2018-10-17 19:01
+ * Feature:spec FeignClient
+ */
+@FeignClient(value = "item-service")
+public interface SpecClient extends SpecApi {
+}
diff --git a/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/client/SpuClient.java b/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/client/SpuClient.java
new file mode 100644
index 00000000..a9b3df3e
--- /dev/null
+++ b/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/client/SpuClient.java
@@ -0,0 +1,13 @@
+package com.leyou.client;
+
+import com.leyou.item.api.SpuApi;
+import org.springframework.cloud.openfeign.FeignClient;
+
+/**
+ * @Author: 98050
+ * Time: 2018-10-17 19:02
+ * Feature:
+ */
+@FeignClient(value = "item-service")
+public interface SpuClient extends SpuApi {
+}
diff --git a/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/controller/GoodsController.java b/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/controller/GoodsController.java
new file mode 100644
index 00000000..df3a84c6
--- /dev/null
+++ b/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/controller/GoodsController.java
@@ -0,0 +1,79 @@
+package com.leyou.controller;
+
+import com.leyou.service.GoodsHtmlService;
+import com.leyou.service.GoodsService;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.BoundHashOperations;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.thymeleaf.context.WebContext;
+import org.thymeleaf.spring5.context.webflux.SpringWebFluxContext;
+import org.thymeleaf.spring5.view.ThymeleafViewResolver;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @Author: 98050
+ * Time: 2018-10-17 16:06
+ * Feature: 商品详情页面跳转
+ */
+@Controller
+@RequestMapping("item")
+public class GoodsController {
+
+ @Autowired
+ private GoodsService goodsService;
+
+ @Autowired
+ private GoodsHtmlService goodsHtmlService;
+
+ @Autowired
+ private StringRedisTemplate stringRedisTemplate;
+
+ @Autowired
+ private ThymeleafViewResolver thymeleafViewResolver;
+
+ private static String KEY_PREFIX = "leyou:goods:detail:";
+
+ @GetMapping(value = "{id}.html",produces = "text/html")
+ @ResponseBody
+ public String toItemPage(HttpServletRequest request, HttpServletResponse response, Model model, @PathVariable("id")String id) throws InterruptedException, ExecutionException {
+ Long idN = Long.parseLong(id);
+ //加载数据
+ Map modelMap = this.goodsService.loadModel(idN);
+ //把数据放入模型中
+ model.addAllAttributes(modelMap);
+ //页面静态化
+// this.goodsHtmlService.asyncExecute(idN);
+// return "item";
+ BoundHashOperations hashOperations = this.stringRedisTemplate.boundHashOps(KEY_PREFIX+id);
+ String html = (String) hashOperations.get(id);
+ /**
+ * 先取缓存
+ */
+ if (StringUtils.isNotEmpty(html)){
+ //不空,则返回
+ return html;
+ }
+ //手动渲染模板
+ WebContext context = new WebContext(request,response,request.getServletContext(),request.getLocale(),model.asMap());
+ html = thymeleafViewResolver.getTemplateEngine().process("item",context);
+ if (StringUtils.isNotEmpty(html)){
+ //不空,放入缓存
+ //设置有效期60秒
+ hashOperations.put(id,html);
+ hashOperations.expire(60, TimeUnit.SECONDS);
+ }
+ return html;
+ }
+}
diff --git a/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/listener/GoodsListener.java b/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/listener/GoodsListener.java
new file mode 100644
index 00000000..86bdd7db
--- /dev/null
+++ b/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/listener/GoodsListener.java
@@ -0,0 +1,64 @@
+package com.leyou.listener;
+
+import com.leyou.service.GoodsHtmlService;
+import org.springframework.amqp.core.ExchangeTypes;
+import org.springframework.amqp.rabbit.annotation.Exchange;
+import org.springframework.amqp.rabbit.annotation.Queue;
+import org.springframework.amqp.rabbit.annotation.QueueBinding;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * @Author: 98050
+ * @Time: 2018-10-21 14:45
+ * @Feature: mq监听器,消费者
+ */
+@Component
+public class GoodsListener {
+
+ @Autowired
+ private GoodsHtmlService goodsHtmlService;
+
+ /**
+ * 处理insert和update的消息
+ * @param id
+ * @throws Exception
+ */
+ @RabbitListener(bindings = @QueueBinding(
+ value = @Queue(value = "leyou.create.web.queue",durable = "true"), //队列持久化
+ exchange = @Exchange(
+ value = "leyou.item.exchange",
+ ignoreDeclarationExceptions = "true",
+ type = ExchangeTypes.TOPIC
+ ),
+ key = {"item.insert","item.update"}
+ ))
+ public void listenCreate(Long id) throws Exception{
+ if (id == null){
+ return;
+ }
+ //创建或更新索引
+ this.goodsHtmlService.createHtml(id);
+ }
+
+ @RabbitListener(bindings = @QueueBinding(
+ value = @Queue(value = "leyou.delete.web.queue",durable = "true"), //队列持久化
+ exchange = @Exchange(
+ value = "leyou.item.exchange",
+ ignoreDeclarationExceptions = "true",
+ type = ExchangeTypes.TOPIC
+ ),
+ key = {"item.delete"}
+ ))
+ public void listenDelete(Long id){
+ if (id == null){
+ return;
+ }
+
+ //删除索引
+ this.goodsHtmlService.deleteHtml(id);
+ }
+
+
+}
diff --git a/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/service/GoodsHtmlService.java b/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/service/GoodsHtmlService.java
new file mode 100644
index 00000000..4be3c933
--- /dev/null
+++ b/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/service/GoodsHtmlService.java
@@ -0,0 +1,29 @@
+package com.leyou.service;
+
+import java.util.concurrent.ExecutionException;
+
+/**
+ * @Author: 98050
+ * @Time: 2018-10-19 09:40
+ * @Feature: 页面详情静态化接口
+ */
+public interface GoodsHtmlService {
+
+ /**
+ * 创建html页面
+ * @param spuId
+ */
+ void createHtml(Long spuId) throws InterruptedException, ExecutionException;
+
+ /**
+ * 新建线程处理页面静态化,Controller调用
+ * @param spuId
+ */
+ void asyncExecute(Long spuId);
+
+ /**
+ * 删除html页面
+ * @param id
+ */
+ void deleteHtml(Long id);
+}
diff --git a/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/service/GoodsService.java b/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/service/GoodsService.java
new file mode 100644
index 00000000..ef1649da
--- /dev/null
+++ b/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/service/GoodsService.java
@@ -0,0 +1,18 @@
+package com.leyou.service;
+
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+
+/**
+ * @Author: 98050
+ * Time: 2018-10-17 19:27
+ * Feature:商品详情页后台
+ */
+public interface GoodsService {
+ /**
+ * 商品详细信息
+ * @param spuId
+ * @return
+ */
+ Map loadModel(Long spuId) throws InterruptedException, ExecutionException;
+}
diff --git a/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/service/impl/GoodsHtmlServiceImpl.java b/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/service/impl/GoodsHtmlServiceImpl.java
new file mode 100644
index 00000000..b8102296
--- /dev/null
+++ b/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/service/impl/GoodsHtmlServiceImpl.java
@@ -0,0 +1,86 @@
+package com.leyou.service.impl;
+
+import com.leyou.service.GoodsHtmlService;
+import com.leyou.service.GoodsService;
+
+
+import com.leyou.utils.ThreadUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.thymeleaf.TemplateEngine;
+import org.thymeleaf.context.Context;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+
+/**
+ * @Author: 98050
+ * @Time: 2018-10-19 09:46
+ * @Feature: 实现页面静态化接口
+ */
+@Service
+public class GoodsHtmlServiceImpl implements GoodsHtmlService {
+
+ @Autowired
+ private GoodsService goodsService;
+
+ @Autowired
+ private TemplateEngine templateEngine;
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(GoodsHtmlService.class);
+
+
+ @Override
+ public void createHtml(Long spuId) throws InterruptedException, ExecutionException {
+ PrintWriter writer = null;
+
+ //获取页面数据
+ Map spuMap = this.goodsService.loadModel(spuId);
+ //创建Thymeleaf上下文对象
+ Context context = new Context();
+ //把数据放入上下文对象
+ context.setVariables(spuMap);
+
+ //创建输出流
+ File file = new File("D:\\nginx-1.12.2\\html\\item\\"+spuId+".html");
+ try {
+ writer = new PrintWriter(file);
+ //执行页面静态化方法
+ templateEngine.process("item",context,writer);
+ } catch (FileNotFoundException e) {
+ LOGGER.error("页面静态化出错:{}"+e,spuId);
+ }finally {
+ if (writer != null){
+ writer.close();
+ }
+ }
+ }
+
+ /**
+ * 新建线程处理页面静态化
+ * @param spuId
+ */
+ @Override
+ public void asyncExecute(Long spuId) {
+ ThreadUtils.execute(() -> {
+ try {
+ createHtml(spuId);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } catch (ExecutionException e) {
+ e.printStackTrace();
+ }
+ });
+ }
+
+ @Override
+ public void deleteHtml(Long id) {
+ File file = new File("D:\\nginx-1.12.2\\html\\item\\"+id+".html");
+ file.deleteOnExit();
+ }
+}
diff --git a/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/service/impl/GoodsServiceImpl.java b/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/service/impl/GoodsServiceImpl.java
new file mode 100644
index 00000000..6293b491
--- /dev/null
+++ b/src/demo/manage/leyou-goods-web/src/main/java/com/leyou/service/impl/GoodsServiceImpl.java
@@ -0,0 +1,199 @@
+package com.leyou.service.impl;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.leyou.service.GoodsService;
+import com.leyou.client.BrandClient;
+import com.leyou.client.CategoryClient;
+import com.leyou.client.GoodsClient;
+import com.leyou.item.bo.SpuBo;
+import com.leyou.item.pojo.Sku;
+import com.leyou.item.pojo.SpuDetail;
+import com.leyou.item.pojo.Brand;
+import com.leyou.item.pojo.Category;
+import com.leyou.utils.JsonUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * @Author: 98050
+ * Time: 2018-10-17 19:40
+ * Feature:商品详情页信息
+ */
+@Service
+public class GoodsServiceImpl implements GoodsService {
+
+ @Autowired
+ private GoodsClient goodsClient;
+
+ @Autowired
+ private BrandClient brandClient;
+
+ @Autowired
+ private CategoryClient categoryClient;
+
+ @Override
+ public Map loadModel(Long spuId) throws InterruptedException, ExecutionException {
+
+ final CountDownLatch countDownLatch = new CountDownLatch(2);
+ ExecutorService executorService = Executors.newFixedThreadPool(3);
+
+ SpuBo spuBo = executorService.submit(() -> {
+ countDownLatch.countDown();
+ return this.goodsClient.queryGoodsById(spuId);
+ }).get();
+
+ Brand brand = executorService.submit(() -> {
+ countDownLatch.countDown();
+ return this.brandClient.queryBrandByIds(Collections.singletonList(spuBo.getBrandId())).get(0);
+ }).get();
+
+ countDownLatch.await();
+
+ SpuDetail spuDetail = spuBo.getSpuDetail();
+ List skuList = spuBo.getSkus();
+ List ids = new ArrayList<>();
+ ids.add(spuBo.getCid1());
+ ids.add(spuBo.getCid2());
+ ids.add(spuBo.getCid3());
+
+ List categoryList = executorService.submit(() -> this.categoryClient.queryCategoryByIds(ids).getBody()).get();
+ /**
+ * 对于规格属性的处理需要注意以下几点:
+ * 1. 所有规格都保存为id和name形式
+ * 2. 规格对应的值保存为id和value形式
+ * 3. 都是map形式
+ * 4. 将特有规格参数单独抽取
+ */
+
+ //获取所有规格参数,然后封装成为id和name形式的数据
+ String allSpecJson = spuDetail.getSpecifications();
+ List