diff --git a/code_generator/pom.xml b/code_generator/pom.xml
new file mode 100644
index 0000000..3af2ffc
--- /dev/null
+++ b/code_generator/pom.xml
@@ -0,0 +1,45 @@
+
+
+
+ demo_mall
+ com.sanbangzi
+ 0.0.1-SNAPSHOT
+
+ 4.0.0
+
+ code_generator
+
+
+
+
+ org.mybatis.generator
+ mybatis-generator-maven-plugin
+ 1.3.6
+
+ ${basedir}/src/main/resources/generatorConfig.xml
+ true
+ true
+
+
+
+ mysql
+ mysql-connector-java
+ 5.1.45
+
+
+ tk.mybatis
+ mapper
+ 4.0.3
+
+
+ org.freemarker
+ freemarker
+ 2.3.23
+
+
+
+
+
+
\ No newline at end of file
diff --git a/code_generator/src/main/resources/generator/mapper.ftl b/code_generator/src/main/resources/generator/mapper.ftl
new file mode 100644
index 0000000..6fb8046
--- /dev/null
+++ b/code_generator/src/main/resources/generator/mapper.ftl
@@ -0,0 +1,12 @@
+package ${package};
+
+import ${tableClass.fullClassName};
+
+/**
+* 通用 Mapper 代码生成器
+*
+* @author mapper-generator
+*/
+public interface ${tableClass.shortClassName}${mapperSuffix} extends ${baseMapper!"com.sanbangzi.common.utils.MyMapper"}<${tableClass.shortClassName}> {
+
+}
diff --git a/code_generator/src/main/resources/generatorConfig.xml b/code_generator/src/main/resources/generatorConfig.xml
new file mode 100644
index 0000000..b16800f
--- /dev/null
+++ b/code_generator/src/main/resources/generatorConfig.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/common/pom.xml b/common/pom.xml
new file mode 100644
index 0000000..a80201a
--- /dev/null
+++ b/common/pom.xml
@@ -0,0 +1,62 @@
+
+
+ 4.0.0
+
+ com.sanbangzi
+ demo_mall
+ 0.0.1-SNAPSHOT
+
+
+
+ common
+
+
+
+ org.apache.commons
+ commons-lang3
+
+
+
+ commons-codec
+ commons-codec
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ com.github.pagehelper
+ pagehelper-spring-boot-starter
+
+
+
+ com.google.guava
+ guava
+
+
+
+ tk.mybatis
+ mapper
+
+
+
+ com.squareup.okhttp3
+ okhttp
+
+
+
+ com.squareup.okio
+ okio
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+
diff --git a/common/src/main/java/com/sanbangzi/common/utils/BeanUtil.java b/common/src/main/java/com/sanbangzi/common/utils/BeanUtil.java
new file mode 100644
index 0000000..ae464d7
--- /dev/null
+++ b/common/src/main/java/com/sanbangzi/common/utils/BeanUtil.java
@@ -0,0 +1,60 @@
+package com.sanbangzi.common.utils;
+
+import com.google.common.collect.Lists;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeanUtils;
+
+import java.util.List;
+
+public class BeanUtil extends BeanUtils {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(BeanUtil.class);
+
+ /**
+ * 对象拷贝 (数据源为空返回空)
+ * @param from 数据源
+ * @param to 目标对象
+ * @param 范型
+ * @return 数据源为空返回空
+ * @throws Exception
+ */
+ public static T copyObject(Object from, Class to) {
+ Object dest = null;
+ try {
+ if (null == from) {
+ return null;
+ }
+ dest = to.newInstance();
+ copyProperties(from, dest);
+ } catch (Exception e) {
+ LOGGER.error("拷贝对象错误:" + e);
+ }
+ return (T) dest;
+ }
+
+ /**
+ * 拷贝集合
+ * @param from 数据源
+ * @param to 目标
+ * @param 范型
+ * @return 数据源为空不返回空
+ */
+ public static List copyList(List from, Class to) {
+ if (null == from || from.isEmpty()) {
+ return Lists.newArrayList();
+ }
+ List dest = Lists.newArrayList();
+ from.forEach((Object e) -> {
+ try {
+ T toObject = (T) to.newInstance();
+ copyProperties(e, toObject);
+ dest.add(toObject);
+ } catch (Exception e1) {
+ LOGGER.error("拷贝集合错误:" + e1);
+ }
+ });
+ return dest;
+ }
+
+}
diff --git a/common/src/main/java/com/sanbangzi/common/utils/CollectionUtil.java b/common/src/main/java/com/sanbangzi/common/utils/CollectionUtil.java
new file mode 100644
index 0000000..62f81be
--- /dev/null
+++ b/common/src/main/java/com/sanbangzi/common/utils/CollectionUtil.java
@@ -0,0 +1,14 @@
+package com.sanbangzi.common.utils;
+
+import java.util.Collection;
+
+public class CollectionUtil {
+
+ public static boolean isBlank(Collection c) {
+ return null == c || c.isEmpty();
+ }
+
+ public static boolean isNotBlank(Collection c) {
+ return !isBlank(c);
+ }
+}
diff --git a/common/src/main/java/com/sanbangzi/common/utils/DigestUtil.java b/common/src/main/java/com/sanbangzi/common/utils/DigestUtil.java
new file mode 100644
index 0000000..0cf13da
--- /dev/null
+++ b/common/src/main/java/com/sanbangzi/common/utils/DigestUtil.java
@@ -0,0 +1,6 @@
+package com.sanbangzi.common.utils;
+
+import org.apache.commons.codec.digest.DigestUtils;
+
+public class DigestUtil extends DigestUtils {
+}
diff --git a/common/src/main/java/com/sanbangzi/common/utils/MyMapper.java b/common/src/main/java/com/sanbangzi/common/utils/MyMapper.java
new file mode 100644
index 0000000..e8fa2fa
--- /dev/null
+++ b/common/src/main/java/com/sanbangzi/common/utils/MyMapper.java
@@ -0,0 +1,7 @@
+package com.sanbangzi.common.utils;
+
+import tk.mybatis.mapper.common.Mapper;
+import tk.mybatis.mapper.common.MySqlMapper;
+
+public interface MyMapper extends Mapper, MySqlMapper {
+}
diff --git a/common/src/main/java/com/sanbangzi/common/utils/MyPage.java b/common/src/main/java/com/sanbangzi/common/utils/MyPage.java
new file mode 100644
index 0000000..a3e90d2
--- /dev/null
+++ b/common/src/main/java/com/sanbangzi/common/utils/MyPage.java
@@ -0,0 +1,34 @@
+package com.sanbangzi.common.utils;
+
+
+import com.github.pagehelper.PageInfo;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class MyPage {
+
+ // 页数
+ private Integer pageNum;
+
+ // 每页大小
+ private Integer pageSize;
+
+ // 总页数
+ private Integer pages;
+
+ // 总记录数
+ private Long total;
+
+ // 数据
+ private List data;
+
+ public static MyPage newInstance(PageInfo pageInfo) {
+ return new MyPage(pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getPages(), pageInfo.getTotal(), pageInfo.getList());
+ }
+}
diff --git a/common/src/main/java/com/sanbangzi/common/utils/RandomUtil.java b/common/src/main/java/com/sanbangzi/common/utils/RandomUtil.java
new file mode 100644
index 0000000..316c691
--- /dev/null
+++ b/common/src/main/java/com/sanbangzi/common/utils/RandomUtil.java
@@ -0,0 +1,14 @@
+package com.sanbangzi.common.utils;
+
+import java.util.UUID;
+
+public class RandomUtil {
+
+ /**
+ * 32位uuid
+ * @return
+ */
+ public static String uuid() {
+ return UUID.randomUUID().toString().replaceAll("-", "").toString();
+ }
+}
diff --git a/common/src/main/java/com/sanbangzi/common/utils/StringUtil.java b/common/src/main/java/com/sanbangzi/common/utils/StringUtil.java
new file mode 100644
index 0000000..3d26594
--- /dev/null
+++ b/common/src/main/java/com/sanbangzi/common/utils/StringUtil.java
@@ -0,0 +1,7 @@
+package com.sanbangzi.common.utils;
+
+import org.apache.commons.lang3.StringUtils;
+
+public class StringUtil extends StringUtils {
+
+}
diff --git a/common/src/main/java/com/sanbangzi/common/utils/WebResponse.java b/common/src/main/java/com/sanbangzi/common/utils/WebResponse.java
new file mode 100644
index 0000000..41bc950
--- /dev/null
+++ b/common/src/main/java/com/sanbangzi/common/utils/WebResponse.java
@@ -0,0 +1,17 @@
+package com.sanbangzi.common.utils;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class WebResponse {
+
+ private Integer code;
+
+ private String msg;
+
+ private Object data;
+}
diff --git a/common/src/main/java/com/sanbangzi/common/utils/okhttp/CallBackUtil.java b/common/src/main/java/com/sanbangzi/common/utils/okhttp/CallBackUtil.java
new file mode 100644
index 0000000..41c0b8c
--- /dev/null
+++ b/common/src/main/java/com/sanbangzi/common/utils/okhttp/CallBackUtil.java
@@ -0,0 +1,114 @@
+package com.sanbangzi.common.utils.okhttp;
+
+import okhttp3.Call;
+import okhttp3.Response;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+public abstract class CallBackUtil {
+
+ public void onError(final Call call, final Exception e) {
+ onFailure(call, e);
+ }
+
+ public void onSuccess(Call call, Response response) {
+ final T obj = onParseResponse(call, response);
+ onResponse(obj);
+
+ }
+
+
+ public abstract T onParseResponse(Call call, Response response);
+
+
+ public abstract void onFailure(Call call, Exception e);
+
+
+ public abstract void onResponse(T response);
+
+
+ public static abstract class CallBackDefault extends CallBackUtil {
+ @Override
+ public Response onParseResponse(Call call, Response response) {
+ return response;
+ }
+ }
+
+ public static abstract class CallBackString extends CallBackUtil {
+ @Override
+ public String onParseResponse(Call call, Response response) {
+ try {
+ return response.body().string();
+ } catch (IOException e) {
+ new RuntimeException("failure");
+ return "";
+ }
+ }
+ }
+
+
+ /**
+ * 下载文件时的回调类
+ */
+ public static abstract class CallBackFile extends CallBackUtil {
+
+ private final String mDestFileDir;
+ private final String mdestFileName;
+
+ /**
+ * @param destFileDir:文件目录
+ * @param destFileName:文件名
+ */
+ public CallBackFile(String destFileDir, String destFileName) {
+ mDestFileDir = destFileDir;
+ mdestFileName = destFileName;
+ }
+
+ @Override
+ public File onParseResponse(Call call, Response response) {
+
+ InputStream is = null;
+ byte[] buf = new byte[1024 * 8];
+ int len = 0;
+ FileOutputStream fos = null;
+ try {
+ is = response.body().byteStream();
+ final long total = response.body().contentLength();
+
+ long sum = 0;
+
+ File dir = new File(mDestFileDir);
+ if (!dir.exists()) {
+ dir.mkdirs();
+ }
+ File file = new File(dir, mdestFileName);
+ fos = new FileOutputStream(file);
+ while ((len = is.read(buf)) != -1) {
+ sum += len;
+ fos.write(buf, 0, len);
+ }
+ fos.flush();
+
+ return file;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ response.body().close();
+ if (is != null) is.close();
+ } catch (IOException e) {
+ }
+ try {
+ if (fos != null) fos.close();
+ } catch (IOException e) {
+ }
+
+ }
+ return null;
+ }
+ }
+}
diff --git a/common/src/main/java/com/sanbangzi/common/utils/okhttp/OkHttpUtil.java b/common/src/main/java/com/sanbangzi/common/utils/okhttp/OkHttpUtil.java
new file mode 100644
index 0000000..8eec72a
--- /dev/null
+++ b/common/src/main/java/com/sanbangzi/common/utils/okhttp/OkHttpUtil.java
@@ -0,0 +1,556 @@
+package com.sanbangzi.common.utils.okhttp;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+
+public class OkHttpUtil {
+ public static final String METHOD_GET = "GET";
+ public static final String METHOD_POST = "POST";
+ public static final String METHOD_PUT = "PUT";
+ public static final String METHOD_DELETE = "DELETE";
+
+
+ /**
+ * get请求
+ *
+ * @param url:url
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用。
+ */
+ public static void okHttpGet(String url, CallBackUtil callBack) {
+ okHttpGet(url, null, null, callBack);
+ }
+
+
+ /**
+ * get同步请求
+ *
+ * @param url:url
+ */
+ public static String okHttpSynGet(String url) {
+ return okHttpSynGet(url, null);
+ }
+
+ /**
+ * get请求,可以传递参数
+ *
+ * @param url:url
+ * @param paramsMap:map集合,封装键值对参数
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用。
+ */
+ public static void okHttpGet(String url, Map paramsMap, CallBackUtil callBack) {
+ okHttpGet(url, paramsMap, null, callBack);
+ }
+
+ /**
+ * get同步请求,可以传递参数
+ *
+ * @param url:url
+ * @param paramsMap:map集合,封装键值对参数
+ */
+ public static String okHttpSynGet(String url, Map paramsMap) {
+ return okHttpSynGet(url, paramsMap, null);
+ }
+
+ /**
+ * get请求,可以传递参数
+ *
+ * @param url:url
+ * @param paramsMap:map集合,封装键值对参数
+ * @param headerMap:map集合,封装请求头键值对
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用。
+ */
+ public static void okHttpGet(String url, Map paramsMap, Map headerMap, CallBackUtil callBack) {
+ new RequestUtil(METHOD_GET, url, paramsMap, headerMap, callBack).execute();
+ }
+
+ /**
+ * get同步请求,可以传递参数
+ *
+ * @param url:url
+ * @param paramsMap:map集合,封装键值对参数
+ * @param headerMap:map集合,封装请求头键值对
+ */
+ public static String okHttpSynGet(String url, Map paramsMap, Map headerMap) {
+ return new RequestUtil(METHOD_GET, url, paramsMap, headerMap, null).newCall();
+ }
+
+ /**
+ * post请求
+ *
+ * @param url:url
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用。
+ */
+ public static void okHttpPost(String url, CallBackUtil callBack) {
+ okHttpPost(url, null, callBack);
+ }
+
+
+ /**
+ * post同步请求
+ *
+ * @param url:url
+ */
+ public static String okHttpSynPost(String url) {
+ return okHttpSynPost(url, null);
+ }
+
+ /**
+ * post请求,可以传递参数
+ *
+ * @param url:url
+ * @param paramsMap:map集合,封装键值对参数
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用。
+ */
+ public static void okHttpPost(String url, Map paramsMap, CallBackUtil callBack) {
+ okHttpPost(url, paramsMap, null, callBack);
+ }
+
+ /**
+ * post请求,可以传递参数
+ *
+ * @param url:url
+ * @param paramsMap:map集合,封装键值对参数
+ */
+ public static String okHttpSynPost(String url, Map paramsMap) {
+ return okHttpSynPost(url, paramsMap, null);
+ }
+
+
+ /**
+ * post请求,可以传递参数
+ *
+ * @param url:url
+ * @param paramsMap:map集合,封装键值对参数
+ * @param headerMap:map集合,封装请求头键值对
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用。
+ */
+ public static void okHttpPost(String url, Map paramsMap, Map headerMap, CallBackUtil callBack) {
+ new RequestUtil(METHOD_POST, url, paramsMap, headerMap, callBack).execute();
+ }
+
+ /**
+ * post 同步请求,可以传递参数
+ *
+ * @param url:url
+ * @param paramsMap:map集合,封装键值对参数
+ * @param headerMap:map集合,封装请求头键值对
+ */
+ public static String okHttpSynPost(String url, Map paramsMap, Map headerMap) {
+ return new RequestUtil(METHOD_POST, url, paramsMap, headerMap, null).newCall();
+ }
+
+ /**
+ * put请求
+ *
+ * @param url:url
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用。
+ */
+ public static void okHttpPut(String url, CallBackUtil callBack) {
+ okHttpPut(url, null, callBack);
+ }
+
+
+ /**
+ * put同步请求
+ *
+ * @param url:url
+ */
+ public static String okHttpSynPut(String url) {
+ return okHttpSynPut(url, null);
+ }
+
+ /**
+ * put请求,可以传递参数
+ *
+ * @param url:url
+ * @param paramsMap:map集合,封装键值对参数
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用。
+ */
+ public static void okHttpPut(String url, Map paramsMap, CallBackUtil callBack) {
+ okHttpPut(url, paramsMap, null, callBack);
+ }
+
+ /**
+ * put同步请求,可以传递参数
+ *
+ * @param url:url
+ * @param paramsMap:map集合,封装键值对参数
+ */
+ public static String okHttpSynPut(String url, Map paramsMap) {
+ return okHttpSynPut(url, paramsMap, null);
+ }
+
+ /**
+ * put请求,可以传递参数
+ *
+ * @param url:url
+ * @param paramsMap:map集合,封装键值对参数
+ * @param headerMap:map集合,封装请求头键值对
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用。
+ */
+ public static void okHttpPut(String url, Map paramsMap, Map headerMap, CallBackUtil callBack) {
+ new RequestUtil(METHOD_PUT, url, paramsMap, headerMap, callBack).execute();
+ }
+
+ /**
+ * put同步请求,可以传递参数
+ *
+ * @param url:url
+ * @param paramsMap:map集合,封装键值对参数
+ * @param headerMap:map集合,封装请求头键值对
+ */
+ public static String okHttpSynPut(String url, Map paramsMap, Map headerMap) {
+ return new RequestUtil(METHOD_PUT, url, paramsMap, headerMap, null).newCall();
+ }
+
+ /**
+ * delete请求
+ *
+ * @param url:url
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用。
+ */
+ public static void okHttpDelete(String url, CallBackUtil callBack) {
+ okHttpDelete(url, null, callBack);
+ }
+
+
+ /**
+ * delete请求
+ *
+ * @param url:url
+ */
+ public static String okHttpSynDelete(String url) {
+ return okHttpSynDelete(url, null);
+ }
+
+ /**
+ * delete请求,可以传递参数
+ *
+ * @param url:url
+ * @param paramsMap:map集合,封装键值对参数
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用。
+ */
+ public static void okHttpDelete(String url, Map paramsMap, CallBackUtil callBack) {
+ okHttpDelete(url, paramsMap, null, callBack);
+ }
+
+ /**
+ * delete请求,可以传递参数
+ *
+ * @param url:url
+ * @param paramsMap:map集合,封装键值对参数
+ */
+ public static String okHttpSynDelete(String url, Map paramsMap) {
+ return okHttpSynDelete(url, paramsMap, null);
+ }
+
+ /**
+ * delete请求,可以传递参数
+ *
+ * @param url:url
+ * @param paramsMap:map集合,封装键值对参数
+ * @param headerMap:map集合,封装请求头键值对
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用。
+ */
+ public static void okHttpDelete(String url, Map paramsMap, Map headerMap, CallBackUtil callBack) {
+ new RequestUtil(METHOD_DELETE, url, paramsMap, headerMap, callBack).execute();
+ }
+
+ /**
+ * delete请求,可以传递参数
+ *
+ * @param url:url
+ * @param paramsMap:map集合,封装键值对参数
+ * @param headerMap:map集合,封装请求头键值对
+ */
+ public static String okHttpSynDelete(String url, Map paramsMap, Map headerMap) {
+ return new RequestUtil(METHOD_DELETE, url, paramsMap, headerMap, null).newCall();
+ }
+
+ /**
+ * post请求,可以传递参数
+ *
+ * @param url:url
+ * @param jsonStr:json格式的参数
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用。
+ */
+ public static void okHttpPostJson(String url, String jsonStr, CallBackUtil callBack) {
+ okHttpPostJson(url, jsonStr, null, callBack);
+ }
+
+ /**
+ * post请求,可以传递参数
+ *
+ * @param url:url
+ * @param jsonStr:json格式的参数
+ * @param headerMap:map集合,封装请求头键值对
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用。
+ */
+ public static void okHttpPostJson(String url, String jsonStr, Map headerMap, CallBackUtil callBack) {
+ new RequestUtil(METHOD_POST, url, jsonStr, headerMap, callBack).execute();
+ }
+
+
+ /**
+ * post请求,可以传递参数
+ *
+ * @param url:url
+ * @param jsonStr:json格式的参数
+ */
+ public static String okHttpSynPostJson(String url, String jsonStr) {
+ return okHttpSynPostJson(url, jsonStr, null);
+ }
+
+ /**
+ * post请求,可以传递参数
+ *
+ * @param url:url
+ * @param jsonStr:json格式的参数
+ * @param headerMap:map集合,封装请求头键值对
+ */
+ public static String okHttpSynPostJson(String url, String jsonStr, Map headerMap) {
+ return new RequestUtil(METHOD_POST, url, jsonStr, headerMap, null).newCall();
+ }
+
+ /**
+ * post请求,可以传递参数,获取返回流
+ *
+ * @param url:url
+ * @param jsonStr:json格式的参数
+ * @param headerMap:map集合,封装请求头键值对
+ */
+ public static byte[] okHttpSynPostByte(String url, String jsonStr, Map headerMap) {
+ return new RequestUtil(METHOD_POST, url, jsonStr, headerMap, null).newByteImg();
+ }
+
+
+ /**
+ * put请求,可以传递参数
+ *
+ * @param url:url
+ * @param jsonStr:json格式的参数
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用。
+ */
+ public static void okHttpPutJson(String url, String jsonStr, CallBackUtil callBack) {
+ okHttpPutJson(url, jsonStr, null, callBack);
+ }
+
+ /**
+ * put请求,可以传递参数
+ *
+ * @param url:url
+ * @param jsonStr:json格式的参数
+ * @param headerMap:map集合,封装请求头键值对
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用。
+ */
+ public static void okHttpPutJson(String url, String jsonStr, Map headerMap, CallBackUtil callBack) {
+ new RequestUtil(METHOD_PUT, url, jsonStr, headerMap, callBack).execute();
+ }
+
+
+ /**
+ * put请求,可以传递参数
+ *
+ * @param url:url
+ * @param jsonStr:json格式的参数
+ */
+ public static String okHttpSynPutJson(String url, String jsonStr) {
+ return okHttpSynPutJson(url, jsonStr, null);
+ }
+
+ /**
+ * put请求,可以传递参数
+ *
+ * @param url:url
+ * @param jsonStr:json格式的参数
+ * @param headerMap:map集合,封装请求头键值对
+ */
+ public static String okHttpSynPutJson(String url, String jsonStr, Map headerMap) {
+ return new RequestUtil(METHOD_PUT, url, jsonStr, headerMap, null).newCall();
+ }
+
+ /**
+ * delete请求,可以传递参数
+ *
+ * @param url:url
+ * @param jsonStr:json格式的键参数
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用。
+ */
+ public static void okHttpDeleteJson(String url, String jsonStr, CallBackUtil callBack) {
+ okHttpDeleteJson(url, jsonStr, null, callBack);
+ }
+
+ /**
+ * delete请求,可以传递参数
+ *
+ * @param url:url
+ * @param jsonStr:json格式的参数
+ * @param headerMap:map集合,封装请求头键值对
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用。
+ */
+ public static void okHttpDeleteJson(String url, String jsonStr, Map headerMap, CallBackUtil callBack) {
+ new RequestUtil(METHOD_DELETE, url, jsonStr, headerMap, callBack).execute();
+ }
+
+ /**
+ * delete请求,可以传递参数
+ *
+ * @param url:url
+ * @param jsonStr:json格式的键参数
+ */
+ public static String okHttpSynDeleteJson(String url, String jsonStr) {
+ return okHttpSynDeleteJson(url, jsonStr, null);
+ }
+
+ /**
+ * delete请求,可以传递参数
+ *
+ * @param url:url
+ * @param jsonStr:json格式的参数
+ * @param headerMap:map集合,封装请求头键值对
+ */
+ public static String okHttpSynDeleteJson(String url, String jsonStr, Map headerMap) {
+ return new RequestUtil(METHOD_DELETE, url, jsonStr, headerMap, null).newCall();
+ }
+
+
+ /**
+ * post请求,上传单个文件
+ *
+ * @param url:url
+ * @param file:File对象
+ * @param fileKey:上传参数时file对应的键
+ * @param fileType:File类型,是image,video,audio,file
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用
+ */
+ public static void okHttpUploadFile(String url, File file, String fileKey, String fileType, CallBackUtil callBack) {
+ okHttpUploadFile(url, file, fileKey, fileType, null, callBack);
+ }
+
+ /**
+ * post请求,上传单个文件
+ *
+ * @param url:url
+ * @param file:File对象
+ * @param fileKey:上传参数时file对应的键
+ * @param fileType:File类型,是image,video,audio,file
+ * @param paramsMap:map集合,封装键值对参数
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用
+ */
+ public static void okHttpUploadFile(String url, File file, String fileKey, String fileType, Map paramsMap, CallBackUtil callBack) {
+ okHttpUploadFile(url, file, fileKey, fileType, paramsMap, null, callBack);
+ }
+
+ /**
+ * post请求,上传单个文件
+ *
+ * @param url:url
+ * @param file:File对象
+ * @param fileKey:上传参数时file对应的键
+ * @param fileType:File类型,是image,video,audio,file
+ * @param paramsMap:map集合,封装键值对参数
+ * @param headerMap:map集合,封装请求头键值对
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用
+ */
+ public static void okHttpUploadFile(String url, File file, String fileKey, String fileType, Map paramsMap, Map headerMap, CallBackUtil callBack) {
+ new RequestUtil(METHOD_POST, url, paramsMap, file, fileKey, fileType, headerMap, callBack).execute();
+ }
+
+ /**
+ * post请求,上传多个文件,以list集合的形式
+ *
+ * @param url:url
+ * @param fileList:集合元素是File对象
+ * @param fileKey:上传参数时fileList对应的键
+ * @param fileType:File类型,是image,video,audio,file
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用。
+ */
+ public static void okHttpUploadListFile(String url, List fileList, String fileKey, String fileType, CallBackUtil callBack) {
+ okHttpUploadListFile(url, null, fileList, fileKey, fileType, callBack);
+ }
+
+ /**
+ * post请求,上传多个文件,以list集合的形式
+ *
+ * @param url:url
+ * @param fileList:集合元素是File对象
+ * @param fileKey:上传参数时fileList对应的键
+ * @param fileType:File类型,是image,video,audio,file
+ * @param paramsMap:map集合,封装键值对参数
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用。
+ */
+ public static void okHttpUploadListFile(String url, Map paramsMap, List fileList, String fileKey, String fileType, CallBackUtil callBack) {
+ okHttpUploadListFile(url, paramsMap, fileList, fileKey, fileType, null, callBack);
+ }
+
+ /**
+ * post请求,上传多个文件,以list集合的形式
+ *
+ * @param url:url
+ * @param fileList:集合元素是File对象
+ * @param fileKey:上传参数时fileList对应的键
+ * @param fileType:File类型,是image,video,audio,file
+ * @param paramsMap:map集合,封装键值对参数
+ * @param headerMap:map集合,封装请求头键值对
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用。
+ */
+ public static void okHttpUploadListFile(String url, Map paramsMap, List fileList, String fileKey, String fileType, Map headerMap, CallBackUtil callBack) {
+ new RequestUtil(METHOD_POST, url, paramsMap, fileList, fileKey, fileType, headerMap, callBack).execute();
+ }
+
+ /**
+ * post请求,上传多个文件,以map集合的形式
+ *
+ * @param url:url
+ * @param fileMap:集合key是File对象对应的键,集合value是File对象
+ * @param fileType:File类型,是image,video,audio,file
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用。
+ */
+ public static void okHttpUploadMapFile(String url, Map fileMap, String fileType, CallBackUtil callBack) {
+ okHttpUploadMapFile(url, fileMap, fileType, null, callBack);
+ }
+
+ /**
+ * post请求,上传多个文件,以map集合的形式
+ *
+ * @param url:url
+ * @param fileMap:集合key是File对象对应的键,集合value是File对象
+ * @param fileType:File类型,是image,video,audio,file
+ * @param paramsMap:map集合,封装键值对参数
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用。
+ */
+ public static void okHttpUploadMapFile(String url, Map fileMap, String fileType, Map paramsMap, CallBackUtil callBack) {
+ okHttpUploadMapFile(url, fileMap, fileType, paramsMap, null, callBack);
+ }
+
+ /**
+ * post请求,上传多个文件,以map集合的形式
+ *
+ * @param url:url
+ * @param fileMap:集合key是File对象对应的键,集合value是File对象
+ * @param fileType:File类型,是image,video,audio,file
+ * @param paramsMap:map集合,封装键值对参数
+ * @param headerMap:map集合,封装请求头键值对
+ * @param callBack:回调接口,onFailure方法在请求失败时调用,onResponse方法在请求成功后调用。
+ */
+ public static void okHttpUploadMapFile(String url, Map fileMap, String fileType, Map paramsMap, Map headerMap, CallBackUtil callBack) {
+ new RequestUtil(METHOD_POST, url, paramsMap, fileMap, fileType, headerMap, callBack).execute();
+ }
+
+ /**
+ * 下载文件,不带参数
+ */
+ public static void okHttpDownloadFile(String url, CallBackUtil.CallBackFile callBack) {
+ okHttpDownloadFile(url, null, callBack);
+ }
+
+ /**
+ * 下载文件,带参数
+ */
+ public static void okHttpDownloadFile(String url, Map paramsMap, CallBackUtil.CallBackFile callBack) {
+ okHttpGet(url, paramsMap, null, callBack);
+ }
+
+
+}
diff --git a/common/src/main/java/com/sanbangzi/common/utils/okhttp/RequestUtil.java b/common/src/main/java/com/sanbangzi/common/utils/okhttp/RequestUtil.java
new file mode 100644
index 0000000..c0103c1
--- /dev/null
+++ b/common/src/main/java/com/sanbangzi/common/utils/okhttp/RequestUtil.java
@@ -0,0 +1,361 @@
+package com.sanbangzi.common.utils.okhttp;
+
+import com.sanbangzi.common.utils.okhttp.CallBackUtil;
+import com.sanbangzi.common.utils.okhttp.OkHttpUtil;
+import okhttp3.*;
+import okio.*;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+public class RequestUtil {
+ private String mMetyodType;//请求方式,目前只支持get和post
+ private String mUrl;//接口
+ private Map mParamsMap;//键值对类型的参数,只有这一种情况下区分post和get。
+ private String mJsonStr;//json类型的参数,post方式
+ private File mFile;//文件的参数,post方式,只有一个文件
+ private List mfileList;//文件集合,这个集合对应一个key,即mfileKey
+ private String mfileKey;//上传服务器的文件对应的key
+ private Map mfileMap;//文件集合,每个文件对应一个key
+ private String mFileType;//文件类型的参数,与file同时存在
+ private Map mHeaderMap;//头参数
+ private CallBackUtil mCallBack;//回调接口
+ private OkHttpClient mOkHttpClient;//OKhttpClient对象
+ private Request mOkHttpRequest;//请求对象
+ private Request.Builder mRequestBuilder;//请求对象的构建者
+
+
+ RequestUtil(String methodType, String url, Map paramsMap, Map headerMap, CallBackUtil callBack) {
+ this(methodType, url, null, null, null, null, null, null, paramsMap, headerMap, callBack);
+ }
+
+ RequestUtil(String methodType, String url, String jsonStr, Map headerMap, CallBackUtil callBack) {
+ this(methodType, url, jsonStr, null, null, null, null, null, null, headerMap, callBack);
+ }
+
+ RequestUtil(String methodType, String url, Map paramsMap, File file, String fileKey, String fileType, Map headerMap, CallBackUtil callBack) {
+ this(methodType, url, null, file, null, fileKey, null, fileType, paramsMap, headerMap, callBack);
+ }
+
+ RequestUtil(String methodType, String url, Map paramsMap, List fileList, String fileKey, String fileType, Map headerMap, CallBackUtil callBack) {
+ this(methodType, url, null, null, fileList, fileKey, null, fileType, paramsMap, headerMap, callBack);
+ }
+
+ RequestUtil(String methodType, String url, Map paramsMap, Map fileMap, String fileType, Map headerMap, CallBackUtil callBack) {
+ this(methodType, url, null, null, null, null, fileMap, fileType, paramsMap, headerMap, callBack);
+ }
+
+ private RequestUtil(String methodType, String url, String jsonStr, File file, List fileList, String fileKey, Map fileMap, String fileType, Map paramsMap, Map headerMap, CallBackUtil callBack) {
+ mMetyodType = methodType;
+ mUrl = url;
+ mJsonStr = jsonStr;
+ mFile = file;
+ mfileList = fileList;
+ mfileKey = fileKey;
+ mfileMap = fileMap;
+ mFileType = fileType;
+ mParamsMap = paramsMap;
+ mHeaderMap = headerMap;
+ mCallBack = callBack;
+ getInstance();
+ }
+
+
+ /**
+ * 创建OKhttpClient实例。
+ */
+ private void getInstance() {
+ mOkHttpClient = new OkHttpClient();
+ mRequestBuilder = new Request.Builder();
+ if (mFile != null || mfileList != null || mfileMap != null) {//先判断是否有文件,
+ setFile();
+ } else {
+ //设置参数
+ switch (mMetyodType) {
+ case OkHttpUtil.METHOD_GET:
+ setGetParams();
+ break;
+ case OkHttpUtil.METHOD_POST:
+ mRequestBuilder.post(getRequestBody());
+ break;
+ case OkHttpUtil.METHOD_PUT:
+ mRequestBuilder.put(getRequestBody());
+ break;
+ case OkHttpUtil.METHOD_DELETE:
+ mRequestBuilder.delete(getRequestBody());
+ break;
+ }
+ }
+ mRequestBuilder.url(mUrl);
+ if (mHeaderMap != null) {
+ setHeader();
+ }
+ //mRequestBuilder.addHeader("Authorization","Bearer "+"token");可以把token添加到这儿
+ mOkHttpRequest = mRequestBuilder.build();
+ }
+
+ /**
+ * 得到body对象
+ */
+ private RequestBody getRequestBody() {
+ /**
+ * 首先判断mJsonStr是否为空,由于mJsonStr与mParamsMap不可能同时存在,所以先判断mJsonStr
+ */
+ if (!StringUtils.isEmpty(mJsonStr)) {
+ MediaType JSON = MediaType.parse("application/json; charset=utf-8");//数据类型为json格式,
+ return RequestBody.create(JSON, mJsonStr);//json数据,
+ }
+
+ /**
+ * post,put,delete都需要body,但也都有body等于空的情况,此时也应该有body对象,但body中的内容为空
+ */
+ FormBody.Builder formBody = new FormBody.Builder();
+ if (mParamsMap != null) {
+ for (String key : mParamsMap.keySet()) {
+ formBody.add(key, mParamsMap.get(key));
+ }
+ }
+ return formBody.build();
+ }
+
+
+ /**
+ * get请求,只有键值对参数
+ */
+ private void setGetParams() {
+ if (mParamsMap != null) {
+ mUrl = mUrl + "?";
+ for (String key : mParamsMap.keySet()) {
+ mUrl = mUrl + key + "=" + mParamsMap.get(key) + "&";
+ }
+ mUrl = mUrl.substring(0, mUrl.length() - 1);
+ }
+ }
+
+
+ /**
+ * 设置上传文件
+ */
+ private void setFile() {
+ if (mFile != null) {//只有一个文件,且没有文件名
+ if (mParamsMap == null) {
+ setPostFile();
+ } else {
+ setPostParameAndFile();
+ }
+ } else if (mfileList != null) {//文件集合,只有一个文件名。所以这个也支持单个有文件名的文件
+ setPostParameAndListFile();
+ } else if (mfileMap != null) {//多个文件,每个文件对应一个文件名
+ setPostParameAndMapFile();
+ }
+
+ }
+
+ /**
+ * 只有一个文件,且提交服务器时不用指定键,没有参数
+ */
+ private void setPostFile() {
+ if (mFile != null && mFile.exists()) {
+ MediaType fileType = MediaType.parse(mFileType);
+ RequestBody body = RequestBody.create(fileType, mFile);//json数据,
+ mRequestBuilder.post(new ProgressRequestBody(body, mCallBack));
+ }
+ }
+
+ /**
+ * 只有一个文件,且提交服务器时不用指定键,带键值对参数
+ */
+ private void setPostParameAndFile() {
+ if (mParamsMap != null && mFile != null) {
+ MultipartBody.Builder builder = new MultipartBody.Builder();
+ builder.setType(MultipartBody.FORM);
+ for (String key : mParamsMap.keySet()) {
+ builder.addFormDataPart(key, mParamsMap.get(key));
+ }
+ builder.addFormDataPart(mfileKey, mFile.getName(), RequestBody.create(MediaType.parse(mFileType), mFile));
+ mRequestBuilder.post(new ProgressRequestBody(builder.build(), mCallBack));
+ }
+ }
+
+ /**
+ * 文件集合,可能带有键值对参数
+ */
+ private void setPostParameAndListFile() {
+ if (mfileList != null) {
+ MultipartBody.Builder builder = new MultipartBody.Builder();
+ builder.setType(MultipartBody.FORM);
+ if (mParamsMap != null) {
+ for (String key : mParamsMap.keySet()) {
+ builder.addFormDataPart(key, mParamsMap.get(key));
+ }
+ }
+ for (File f : mfileList) {
+ builder.addFormDataPart(mfileKey, f.getName(), RequestBody.create(MediaType.parse(mFileType), f));
+ }
+ mRequestBuilder.post(builder.build());
+ }
+ }
+
+ /**
+ * 文件Map,可能带有键值对参数
+ */
+ private void setPostParameAndMapFile() {
+ if (mfileMap != null) {
+ MultipartBody.Builder builder = new MultipartBody.Builder();
+ builder.setType(MultipartBody.FORM);
+ if (mParamsMap != null) {
+ for (String key : mParamsMap.keySet()) {
+ builder.addFormDataPart(key, mParamsMap.get(key));
+ }
+ }
+
+ for (String key : mfileMap.keySet()) {
+ builder.addFormDataPart(key, mfileMap.get(key).getName(), RequestBody.create(MediaType.parse(mFileType), mfileMap.get(key)));
+ }
+ mRequestBuilder.post(builder.build());
+ }
+ }
+
+
+ /**
+ * 设置头参数
+ */
+ private void setHeader() {
+ if (mHeaderMap != null) {
+ for (String key : mHeaderMap.keySet()) {
+ mRequestBuilder.addHeader(key, mHeaderMap.get(key));
+ }
+ }
+ }
+
+
+ void execute() {
+ mOkHttpClient.newCall(mOkHttpRequest).enqueue(new Callback() {
+ @Override
+ public void onFailure(final Call call, final IOException e) {
+ if (mCallBack != null) {
+ mCallBack.onError(call, e);
+ }
+ }
+
+ @Override
+ public void onResponse(final Call call, final Response response) throws IOException {
+ if (mCallBack != null) {
+ mCallBack.onSuccess(call, response);
+ }
+ }
+
+ });
+ }
+
+ public String newCall() {
+ try {
+ Response response = mOkHttpClient.newCall(mOkHttpRequest).execute();
+ return response.body().string();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+
+ public byte[] newByteCall() {
+ try {
+ Response response = mOkHttpClient.newCall(mOkHttpRequest).execute();
+ return response.body().bytes();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * 用于解析用户二维码生成情况
+ * @return
+ */
+ public byte[] newByteImg() {
+ try {
+ Response response = mOkHttpClient.newCall(mOkHttpRequest).execute();
+ if ("application/json; charset=UTF-8".equals(response.body().contentType().toString())){
+ //获取流格式错误
+ return null;
+ }
+ return response.body().bytes();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * 自定义RequestBody类,得到文件上传的进度
+ */
+ private static class ProgressRequestBody extends RequestBody {
+ //实际的待包装请求体
+ private final RequestBody requestBody;
+ //包装完成的BufferedSink
+ private BufferedSink bufferedSink;
+ private CallBackUtil callBack;
+
+ ProgressRequestBody(RequestBody requestBody, CallBackUtil callBack) {
+ this.requestBody = requestBody;
+ this.callBack = callBack;
+ }
+
+ /**
+ * 重写调用实际的响应体的contentType
+ */
+ @Override
+ public MediaType contentType() {
+ return requestBody.contentType();
+ }
+
+ /**
+ * 重写调用实际的响应体的contentLength ,这个是文件的总字节数
+ */
+ @Override
+ public long contentLength() throws IOException {
+ return requestBody.contentLength();
+ }
+
+ /**
+ * 重写进行写入
+ */
+ @Override
+ public void writeTo(BufferedSink sink) throws IOException {
+ if (bufferedSink == null) {
+ bufferedSink = Okio.buffer(sink(sink));
+ }
+ requestBody.writeTo(bufferedSink);
+ //必须调用flush,否则最后一部分数据可能不会被写入
+ bufferedSink.flush();
+ }
+
+ /**
+ * 写入,回调进度接口
+ */
+ private Sink sink(BufferedSink sink) {
+ return new ForwardingSink(sink) {
+ //当前写入字节数
+ long bytesWritten = 0L;
+ //总字节长度,避免多次调用contentLength()方法
+ long contentLength = 0L;
+
+ @Override
+ public void write(Buffer source, long byteCount) throws IOException {
+ super.write(source, byteCount);//这个方法会循环调用,byteCount是每次调用上传的字节数。
+ if (contentLength == 0) {
+ //获得总字节长度
+ contentLength = contentLength();
+ }
+ //增加当前写入的字节数
+ bytesWritten += byteCount;
+ }
+ };
+ }
+ }
+
+}
diff --git a/company_service/pom.xml b/company_service/pom.xml
new file mode 100644
index 0000000..7bd99ca
--- /dev/null
+++ b/company_service/pom.xml
@@ -0,0 +1,38 @@
+
+
+ 4.0.0
+
+ com.sanbangzi
+ demo_mall
+ 0.0.1-SNAPSHOT
+
+
+
+ company_service
+
+
+
+
+ com.sanbangzi
+ common
+
+
+
+ com.sanbangzi
+ domain
+
+
+
+ com.sanbangzi
+ company_service_api
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+
+
diff --git a/company_service/src/main/java/com/sanbangzi/company_service/dao/CompanyBannerDao.java b/company_service/src/main/java/com/sanbangzi/company_service/dao/CompanyBannerDao.java
new file mode 100644
index 0000000..6672de1
--- /dev/null
+++ b/company_service/src/main/java/com/sanbangzi/company_service/dao/CompanyBannerDao.java
@@ -0,0 +1,7 @@
+package com.sanbangzi.company_service.dao;
+
+import com.sanbangzi.common.utils.MyMapper;
+import com.sanbangzi.domain.entity.CompanyBannerEntity;
+
+public interface CompanyBannerDao extends MyMapper {
+}
diff --git a/company_service/src/main/java/com/sanbangzi/company_service/dao/CompanyProductTypeDao.java b/company_service/src/main/java/com/sanbangzi/company_service/dao/CompanyProductTypeDao.java
new file mode 100644
index 0000000..54e201f
--- /dev/null
+++ b/company_service/src/main/java/com/sanbangzi/company_service/dao/CompanyProductTypeDao.java
@@ -0,0 +1,7 @@
+package com.sanbangzi.company_service.dao;
+
+import com.sanbangzi.common.utils.MyMapper;
+import com.sanbangzi.domain.entity.CompanyProductTypeEntity;
+
+public interface CompanyProductTypeDao extends MyMapper {
+}
diff --git a/company_service/src/main/java/com/sanbangzi/company_service/impl/CompanyBannerServiceImpl.java b/company_service/src/main/java/com/sanbangzi/company_service/impl/CompanyBannerServiceImpl.java
new file mode 100644
index 0000000..4b6e38a
--- /dev/null
+++ b/company_service/src/main/java/com/sanbangzi/company_service/impl/CompanyBannerServiceImpl.java
@@ -0,0 +1,32 @@
+package com.sanbangzi.company_service.impl;
+
+import com.sanbangzi.common.utils.BeanUtil;
+import com.sanbangzi.company_service.dao.CompanyBannerDao;
+import com.sanbangzi.company_service_api.api.CompanyBannerService;
+import com.sanbangzi.company_service_api.exception.CompanyException;
+import com.sanbangzi.domain.dto.res.CompanyBannerResDTO;
+import com.sanbangzi.domain.entity.CompanyBannerEntity;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import tk.mybatis.mapper.entity.Example;
+import tk.mybatis.mapper.weekend.WeekendSqls;
+
+import java.util.List;
+
+@Service
+public class CompanyBannerServiceImpl implements CompanyBannerService {
+
+ @Autowired
+ private CompanyBannerDao companyBannerMapper;
+
+ @Override
+ public List listByCompanyId(Long companyId) throws CompanyException {
+ Example example = Example.builder(CompanyBannerEntity.class)
+ .where(WeekendSqls.custom().andEqualTo(CompanyBannerEntity::getCompanyId, companyId))
+ .orderByAsc("sort").build();
+ List companyBannerEntities = companyBannerMapper.selectByExample(example);
+
+ return BeanUtil.copyList(companyBannerEntities, CompanyBannerResDTO.class);
+ }
+
+}
diff --git a/company_service/src/main/java/com/sanbangzi/company_service/impl/CompanyProductTypeServiceImpl.java b/company_service/src/main/java/com/sanbangzi/company_service/impl/CompanyProductTypeServiceImpl.java
new file mode 100644
index 0000000..ebe3b54
--- /dev/null
+++ b/company_service/src/main/java/com/sanbangzi/company_service/impl/CompanyProductTypeServiceImpl.java
@@ -0,0 +1,30 @@
+package com.sanbangzi.company_service.impl;
+
+import com.sanbangzi.common.utils.BeanUtil;
+import com.sanbangzi.company_service.dao.CompanyProductTypeDao;
+import com.sanbangzi.company_service_api.api.CompanyProductTypeService;
+import com.sanbangzi.company_service_api.exception.CompanyException;
+import com.sanbangzi.domain.dto.res.CompanyProductTypeResDTO;
+import com.sanbangzi.domain.entity.CompanyProductTypeEntity;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import tk.mybatis.mapper.entity.Example;
+import tk.mybatis.mapper.weekend.WeekendSqls;
+
+import java.util.List;
+
+@Service
+public class CompanyProductTypeServiceImpl implements CompanyProductTypeService {
+
+ @Autowired
+ private CompanyProductTypeDao companyProductTypeDao;
+
+ @Override
+ public List listByCompanyId(Long companyId) throws CompanyException {
+ Example example = Example.builder(CompanyProductTypeEntity.class)
+ .where(WeekendSqls.custom().andEqualTo(CompanyProductTypeEntity::getCompanyId, companyId))
+ .orderByAsc("sort").build();
+ return BeanUtil.copyList(companyProductTypeDao.selectByExample(example), CompanyProductTypeResDTO.class);
+ }
+
+}
diff --git a/company_service_api/pom.xml b/company_service_api/pom.xml
new file mode 100644
index 0000000..f6d4952
--- /dev/null
+++ b/company_service_api/pom.xml
@@ -0,0 +1,28 @@
+
+
+ 4.0.0
+
+ com.sanbangzi
+ demo_mall
+ 0.0.1-SNAPSHOT
+
+
+
+ company_service_api
+
+
+
+ com.sanbangzi
+ domain
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+
+
diff --git a/company_service_api/src/main/java/com/sanbangzi/company_service_api/api/CompanyBannerService.java b/company_service_api/src/main/java/com/sanbangzi/company_service_api/api/CompanyBannerService.java
new file mode 100644
index 0000000..ff3e6ff
--- /dev/null
+++ b/company_service_api/src/main/java/com/sanbangzi/company_service_api/api/CompanyBannerService.java
@@ -0,0 +1,11 @@
+package com.sanbangzi.company_service_api.api;
+
+import com.sanbangzi.company_service_api.exception.CompanyException;
+import com.sanbangzi.domain.dto.res.CompanyBannerResDTO;
+
+import java.util.List;
+
+public interface CompanyBannerService {
+
+ List listByCompanyId(Long companyId) throws CompanyException;
+}
diff --git a/company_service_api/src/main/java/com/sanbangzi/company_service_api/api/CompanyProductTypeService.java b/company_service_api/src/main/java/com/sanbangzi/company_service_api/api/CompanyProductTypeService.java
new file mode 100644
index 0000000..8457cd8
--- /dev/null
+++ b/company_service_api/src/main/java/com/sanbangzi/company_service_api/api/CompanyProductTypeService.java
@@ -0,0 +1,12 @@
+package com.sanbangzi.company_service_api.api;
+
+import com.sanbangzi.company_service_api.exception.CompanyException;
+import com.sanbangzi.domain.dto.res.CompanyProductTypeResDTO;
+
+import java.util.List;
+
+public interface CompanyProductTypeService {
+
+ List listByCompanyId(Long companyId) throws CompanyException;
+
+}
diff --git a/company_service_api/src/main/java/com/sanbangzi/company_service_api/consts/CompanyCacheKeyConst.java b/company_service_api/src/main/java/com/sanbangzi/company_service_api/consts/CompanyCacheKeyConst.java
new file mode 100644
index 0000000..229cc0e
--- /dev/null
+++ b/company_service_api/src/main/java/com/sanbangzi/company_service_api/consts/CompanyCacheKeyConst.java
@@ -0,0 +1,4 @@
+package com.sanbangzi.company_service_api.consts;
+
+public class CompanyCacheKeyConst {
+}
diff --git a/company_service_api/src/main/java/com/sanbangzi/company_service_api/consts/CompanyConst.java b/company_service_api/src/main/java/com/sanbangzi/company_service_api/consts/CompanyConst.java
new file mode 100644
index 0000000..48939ec
--- /dev/null
+++ b/company_service_api/src/main/java/com/sanbangzi/company_service_api/consts/CompanyConst.java
@@ -0,0 +1,4 @@
+package com.sanbangzi.company_service_api.consts;
+
+public class CompanyConst {
+}
diff --git a/company_service_api/src/main/java/com/sanbangzi/company_service_api/exception/CompanyErrorCode.java b/company_service_api/src/main/java/com/sanbangzi/company_service_api/exception/CompanyErrorCode.java
new file mode 100644
index 0000000..b6cf819
--- /dev/null
+++ b/company_service_api/src/main/java/com/sanbangzi/company_service_api/exception/CompanyErrorCode.java
@@ -0,0 +1,22 @@
+package com.sanbangzi.company_service_api.exception;
+
+import lombok.Getter;
+import lombok.Setter;
+
+public enum CompanyErrorCode {
+
+ BUSINESS_ERROR(40001, "");
+
+ @Getter
+ private Integer code;
+
+ @Getter
+ @Setter
+ private String msg;
+
+ private CompanyErrorCode(Integer code, String msg) {
+ this.code = code;
+ this.msg = msg;
+ }
+
+}
diff --git a/company_service_api/src/main/java/com/sanbangzi/company_service_api/exception/CompanyException.java b/company_service_api/src/main/java/com/sanbangzi/company_service_api/exception/CompanyException.java
new file mode 100644
index 0000000..885c9c3
--- /dev/null
+++ b/company_service_api/src/main/java/com/sanbangzi/company_service_api/exception/CompanyException.java
@@ -0,0 +1,16 @@
+package com.sanbangzi.company_service_api.exception;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@AllArgsConstructor
+public class CompanyException extends RuntimeException {
+
+ @Getter
+ private CompanyErrorCode companyErrorCode;
+
+ public static CompanyException throwBusiError(String msg) {
+ CompanyErrorCode.BUSINESS_ERROR.setMsg(msg);
+ return new CompanyException(CompanyErrorCode.BUSINESS_ERROR);
+ }
+}
diff --git a/crm_web/pom.xml b/crm_web/pom.xml
new file mode 100644
index 0000000..138dd7c
--- /dev/null
+++ b/crm_web/pom.xml
@@ -0,0 +1,30 @@
+
+
+ 4.0.0
+
+ com.sanbangzi
+ demo_mall
+ 0.0.1-SNAPSHOT
+
+
+
+ crm_web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/crm_web/src/main/java/com/sanbangzi/crm_web/CrmWebApplication.java b/crm_web/src/main/java/com/sanbangzi/crm_web/CrmWebApplication.java
new file mode 100644
index 0000000..ef95900
--- /dev/null
+++ b/crm_web/src/main/java/com/sanbangzi/crm_web/CrmWebApplication.java
@@ -0,0 +1,14 @@
+package com.sanbangzi.crm_web;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class CrmWebApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(CrmWebApplication.class, args);
+ }
+
+}
+
diff --git a/crm_web/src/main/resources/application.properties b/crm_web/src/main/resources/application.properties
new file mode 100644
index 0000000..e69de29
diff --git a/domain/pom.xml b/domain/pom.xml
new file mode 100644
index 0000000..295040f
--- /dev/null
+++ b/domain/pom.xml
@@ -0,0 +1,27 @@
+
+
+ 4.0.0
+
+ com.sanbangzi
+ demo_mall
+ 0.0.1-SNAPSHOT
+
+
+
+ domain
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ tk.mybatis
+ mapper
+
+
+
+
diff --git a/domain/src/main/java/com/sanbangzi/domain/dto/req/ProductReqDTO.java b/domain/src/main/java/com/sanbangzi/domain/dto/req/ProductReqDTO.java
new file mode 100644
index 0000000..1d86982
--- /dev/null
+++ b/domain/src/main/java/com/sanbangzi/domain/dto/req/ProductReqDTO.java
@@ -0,0 +1,17 @@
+package com.sanbangzi.domain.dto.req;
+
+import lombok.Data;
+
+@Data
+public class ProductReqDTO {
+
+ private Long companyId;
+
+ private Long typeId;
+
+ private String title;
+
+ private Integer pageNum;
+
+ private Integer pageSize;
+}
diff --git a/domain/src/main/java/com/sanbangzi/domain/dto/req/UserReqDTO.java b/domain/src/main/java/com/sanbangzi/domain/dto/req/UserReqDTO.java
new file mode 100644
index 0000000..ac3b786
--- /dev/null
+++ b/domain/src/main/java/com/sanbangzi/domain/dto/req/UserReqDTO.java
@@ -0,0 +1,16 @@
+package com.sanbangzi.domain.dto.req;
+
+import lombok.Data;
+
+@Data
+public class UserReqDTO {
+
+ /** 小程序opendId */
+ private String openId;
+
+ /** 昵称 */
+ private String nickName;
+
+ /** 头像 */
+ private String headPhoto;
+}
diff --git a/domain/src/main/java/com/sanbangzi/domain/dto/res/CompanyBannerResDTO.java b/domain/src/main/java/com/sanbangzi/domain/dto/res/CompanyBannerResDTO.java
new file mode 100644
index 0000000..135cadc
--- /dev/null
+++ b/domain/src/main/java/com/sanbangzi/domain/dto/res/CompanyBannerResDTO.java
@@ -0,0 +1,16 @@
+package com.sanbangzi.domain.dto.res;
+
+import lombok.Data;
+
+@Data
+public class CompanyBannerResDTO {
+
+ /** 图片 */
+ private String picture;
+
+ /** 链接 */
+ private String link;
+
+ /** 类型(1:无链接,2:产品) */
+ private Byte type;
+}
diff --git a/domain/src/main/java/com/sanbangzi/domain/dto/res/CompanyProductTypeResDTO.java b/domain/src/main/java/com/sanbangzi/domain/dto/res/CompanyProductTypeResDTO.java
new file mode 100644
index 0000000..b54cd57
--- /dev/null
+++ b/domain/src/main/java/com/sanbangzi/domain/dto/res/CompanyProductTypeResDTO.java
@@ -0,0 +1,13 @@
+package com.sanbangzi.domain.dto.res;
+
+import lombok.Data;
+
+@Data
+public class CompanyProductTypeResDTO {
+
+ /** 主键 */
+ private Long id;
+
+ /** 名称 */
+ private String name;
+}
diff --git a/domain/src/main/java/com/sanbangzi/domain/dto/res/ProductDetailResDTO.java b/domain/src/main/java/com/sanbangzi/domain/dto/res/ProductDetailResDTO.java
new file mode 100644
index 0000000..0292112
--- /dev/null
+++ b/domain/src/main/java/com/sanbangzi/domain/dto/res/ProductDetailResDTO.java
@@ -0,0 +1,22 @@
+package com.sanbangzi.domain.dto.res;
+
+import lombok.Data;
+
+@Data
+public class ProductDetailResDTO {
+
+ /** 主键 */
+ private Long id;
+
+ /** 标题 */
+ private String title;
+
+ /** 产品价格(分) */
+ private Integer price;
+
+ /** 轮播数据 */
+ private String carousel;
+
+ /** 产品详情 */
+ private String detail;
+}
diff --git a/domain/src/main/java/com/sanbangzi/domain/dto/res/ProductResDTO.java b/domain/src/main/java/com/sanbangzi/domain/dto/res/ProductResDTO.java
new file mode 100644
index 0000000..d64cda4
--- /dev/null
+++ b/domain/src/main/java/com/sanbangzi/domain/dto/res/ProductResDTO.java
@@ -0,0 +1,19 @@
+package com.sanbangzi.domain.dto.res;
+
+import lombok.Data;
+
+@Data
+public class ProductResDTO {
+
+ /** 主键 */
+ private Long id;
+
+ /** 主图 */
+ private String photo;
+
+ /** 标题 */
+ private String title;
+
+ /** 产品价格(分) */
+ private Integer price;
+}
diff --git a/domain/src/main/java/com/sanbangzi/domain/dto/res/UserResDTO.java b/domain/src/main/java/com/sanbangzi/domain/dto/res/UserResDTO.java
new file mode 100644
index 0000000..2bcbd9b
--- /dev/null
+++ b/domain/src/main/java/com/sanbangzi/domain/dto/res/UserResDTO.java
@@ -0,0 +1,22 @@
+package com.sanbangzi.domain.dto.res;
+
+import lombok.Data;
+
+@Data
+public class UserResDTO {
+
+ /** 用户id */
+ private Long id;
+
+ /** 用户唯一码 */
+ private String code;
+
+ /** 小程序opendId */
+ private String openId;
+
+ /** 昵称 */
+ private String nickName;
+
+ /** 头像 */
+ private String headPhoto;
+}
diff --git a/domain/src/main/java/com/sanbangzi/domain/dto/res/XcxLoginResDTO.java b/domain/src/main/java/com/sanbangzi/domain/dto/res/XcxLoginResDTO.java
new file mode 100644
index 0000000..2e892a4
--- /dev/null
+++ b/domain/src/main/java/com/sanbangzi/domain/dto/res/XcxLoginResDTO.java
@@ -0,0 +1,19 @@
+package com.sanbangzi.domain.dto.res;
+
+import lombok.Data;
+
+@Data
+public class XcxLoginResDTO {
+
+ /** 用户token */
+ private String accessToken;
+
+ /** 用户id */
+ private Long userId;
+
+ /** 用户昵称 */
+ private String nickName;
+
+ /** 用户头像 */
+ private String headPhoto;
+}
diff --git a/domain/src/main/java/com/sanbangzi/domain/entity/CompanyAccountEntity.java b/domain/src/main/java/com/sanbangzi/domain/entity/CompanyAccountEntity.java
new file mode 100644
index 0000000..657efc3
--- /dev/null
+++ b/domain/src/main/java/com/sanbangzi/domain/entity/CompanyAccountEntity.java
@@ -0,0 +1,39 @@
+package com.sanbangzi.domain.entity;
+
+import lombok.Data;
+
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.util.Date;
+
+/** 公司账号表 */
+@Data
+@Table(name = "company_account")
+public class CompanyAccountEntity {
+
+ /** 主键 */
+ @Id
+ private Long id;
+
+ /** 账号 */
+ private String account;
+
+ /** 密码 */
+ private String password;
+
+ /** 头像 */
+ private String headPhoto;
+
+ /** 昵称 */
+ private String nickName;
+
+ /** 状态(1:正常) */
+ private Byte status;
+
+ /** 创建时间 */
+ private Date createTime;
+
+ /** 公司id(关联company.id) */
+ private Long companyId;
+
+}
diff --git a/domain/src/main/java/com/sanbangzi/domain/entity/CompanyBannerEntity.java b/domain/src/main/java/com/sanbangzi/domain/entity/CompanyBannerEntity.java
new file mode 100644
index 0000000..4c438ff
--- /dev/null
+++ b/domain/src/main/java/com/sanbangzi/domain/entity/CompanyBannerEntity.java
@@ -0,0 +1,32 @@
+package com.sanbangzi.domain.entity;
+
+import lombok.Data;
+
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+/** 公司banner表 */
+@Data
+@Table(name = "company_banner")
+public class CompanyBannerEntity {
+
+ /** 主键 */
+ @Id
+ private Long id;
+
+ /** 图片 */
+ private String picture;
+
+ /** 链接 */
+ private String link;
+
+ /** 类型(1:无链接,2:产品) */
+ private Byte type;
+
+ /** 排序 */
+ private Byte sort;
+
+ /** 公司id(关联company.id) */
+ private Long companyId;
+
+}
diff --git a/domain/src/main/java/com/sanbangzi/domain/entity/CompanyEntity.java b/domain/src/main/java/com/sanbangzi/domain/entity/CompanyEntity.java
new file mode 100644
index 0000000..6c3df77
--- /dev/null
+++ b/domain/src/main/java/com/sanbangzi/domain/entity/CompanyEntity.java
@@ -0,0 +1,39 @@
+package com.sanbangzi.domain.entity;
+
+import lombok.Data;
+
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.util.Date;
+
+/** 公司表 */
+@Data
+@Table(name = "company")
+public class CompanyEntity {
+
+ /** 主键 */
+ @Id
+ private Long id;
+
+ /** 公司唯一码 */
+ private String code;
+
+ /** 名称 */
+ private String name;
+
+ /** 联系人 */
+ private String linkMan;
+
+ /** 联系电话 */
+ private String linkPhone;
+
+ /** 状态(1:正常) */
+ private Byte status;
+
+ /** 创建时间 */
+ private Date createTime;
+
+ /** 修改时间 */
+ private Date updateTime;
+
+}
diff --git a/domain/src/main/java/com/sanbangzi/domain/entity/CompanyProductTypeEntity.java b/domain/src/main/java/com/sanbangzi/domain/entity/CompanyProductTypeEntity.java
new file mode 100644
index 0000000..6e9cf7e
--- /dev/null
+++ b/domain/src/main/java/com/sanbangzi/domain/entity/CompanyProductTypeEntity.java
@@ -0,0 +1,26 @@
+package com.sanbangzi.domain.entity;
+
+import lombok.Data;
+
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+/** 公司产品分类 */
+@Data
+@Table(name = "company_product_type")
+public class CompanyProductTypeEntity {
+
+ /** 主键 */
+ @Id
+ private Long id;
+
+ /** 名称 */
+ private String name;
+
+ /** 排序 */
+ private Byte sort;
+
+ /** 公司id(关联company.id) */
+ private Long companyId;
+
+}
diff --git a/domain/src/main/java/com/sanbangzi/domain/entity/ProductEntity.java b/domain/src/main/java/com/sanbangzi/domain/entity/ProductEntity.java
new file mode 100644
index 0000000..dbcf34b
--- /dev/null
+++ b/domain/src/main/java/com/sanbangzi/domain/entity/ProductEntity.java
@@ -0,0 +1,42 @@
+package com.sanbangzi.domain.entity;
+
+import lombok.Data;
+
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.util.Date;
+
+/** 产品表 */
+@Data
+@Table(name = "product")
+public class ProductEntity {
+
+ /** 主键 */
+ @Id
+ private Long id;
+
+ /** 产品唯一码 */
+ private String code;
+
+ /** 主图 */
+ private String photo;
+
+ /** 标题 */
+ private String title;
+
+ /** 产品价格(分) */
+ private Integer price;
+
+ /** 状态(1:正常) */
+ private Byte status;
+
+ /** 创建时间 */
+ private Date createTime;
+
+ /** 修改时间 */
+ private Date updateTime;
+
+ /** 公司id(关联company.id) */
+ private Long companyId;
+
+}
diff --git a/domain/src/main/java/com/sanbangzi/domain/entity/ProductTypeAssociateEntity.java b/domain/src/main/java/com/sanbangzi/domain/entity/ProductTypeAssociateEntity.java
new file mode 100644
index 0000000..3c5da39
--- /dev/null
+++ b/domain/src/main/java/com/sanbangzi/domain/entity/ProductTypeAssociateEntity.java
@@ -0,0 +1,15 @@
+package com.sanbangzi.domain.entity;
+
+import lombok.Data;
+
+/** 产品分类关系表 */
+@Data
+public class ProductTypeAssociateEntity {
+
+ /** 产品id(关联product.id) */
+ private Long productId;
+
+ /** 公司产品分类id(关联company_product_type.id) */
+ private Long companyProductTypeId;
+
+}
diff --git a/domain/src/main/java/com/sanbangzi/domain/entity/ProudctResourceEntity.java b/domain/src/main/java/com/sanbangzi/domain/entity/ProudctResourceEntity.java
new file mode 100644
index 0000000..6c3f0ce
--- /dev/null
+++ b/domain/src/main/java/com/sanbangzi/domain/entity/ProudctResourceEntity.java
@@ -0,0 +1,29 @@
+package com.sanbangzi.domain.entity;
+
+import lombok.Data;
+
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+/** 产品资源表 */
+@Data
+@Table(name = "proudct_resource")
+public class ProudctResourceEntity {
+
+ /** 主键 */
+ @Id
+ private Long id;
+
+ /** 资源 */
+ private String resource;
+
+ /** 资源类型(1:轮播图,2:产品详情) */
+ private Byte type;
+
+ /** 排序 */
+ private Byte sort;
+
+ /** 产品id(关联product.id) */
+ private Long productId;
+
+}
diff --git a/domain/src/main/java/com/sanbangzi/domain/entity/UserEntity.java b/domain/src/main/java/com/sanbangzi/domain/entity/UserEntity.java
new file mode 100644
index 0000000..24e2592
--- /dev/null
+++ b/domain/src/main/java/com/sanbangzi/domain/entity/UserEntity.java
@@ -0,0 +1,39 @@
+package com.sanbangzi.domain.entity;
+
+import lombok.Data;
+
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.util.Date;
+
+/** 用户表 */
+@Data
+@Table(name = "user")
+public class UserEntity {
+
+ /** 主键 */
+ @Id
+ private Long id;
+
+ /** 用户唯一码 */
+ private String code;
+
+ /** 小程序opendId */
+ private String openId;
+
+ /** 昵称 */
+ private String nickName;
+
+ /** 头像 */
+ private String headPhoto;
+
+ /** 状态(1:正常) */
+ private Byte status;
+
+ /** 创建时间 */
+ private Date createTime;
+
+ /** 修改时间 */
+ private Date updateTime;
+
+}
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..eb3ce7f
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,281 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.1.1.RELEASE
+
+
+
+ com.sanbangzi
+ demo_mall
+ 0.0.1-SNAPSHOT
+ pom
+ demo_mall
+ 样板小程序商城
+
+
+ common
+ domain
+ thriparty
+ user_service
+ user_service_api
+ product_service
+ product_service_api
+ crm_web
+ xcx_web
+ code_generator
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ 2.1.1.RELEASE
+ 2.1.1.RELEASE
+ 2.1.1.RELEASE
+ 1.1.10
+ 1.2.47
+ 5.1.45
+ 1.3.2
+ 1.2.5
+ 4.0.3
+ 25.0-jre
+ 3.4
+ 1.11
+ 2.6
+ 1.18.4
+ 2.9.0
+ 2.5.0
+ 3.10.0
+ 1.14.1
+ 2.8.3
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+ ${spring-boot-starter.version}
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ ${spring-boot-starter-web.version}
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+ redis.clients
+ jedis
+
+
+ io.lettuce
+ lettuce-core
+
+
+ ${spring-boot-starter-data-redis.version}
+
+
+
+
+ redis.clients
+ jedis
+ ${jedis.version}
+
+
+
+
+ org.apache.commons
+ commons-pool2
+ ${commons-pool2.version}
+
+
+
+
+ com.alibaba
+ druid
+ ${alibaba.druid.version}
+
+
+
+
+ mysql
+ mysql-connector-java
+ ${mysql-connector-java.version}
+
+
+
+
+ org.apache.commons
+ commons-lang3
+ ${common.lang.version}
+
+
+
+
+ commons-codec
+ commons-codec
+ ${commons-codec.version}
+
+
+
+
+ commons-io
+ commons-io
+ ${commons-io.version}
+
+
+
+
+ com.google.guava
+ guava
+ ${guava.version}
+
+
+
+
+ org.mybatis.spring.boot
+ mybatis-spring-boot-starter
+ ${mybatis.version}
+
+
+
+
+ com.github.pagehelper
+ pagehelper-spring-boot-starter
+ ${pagehelper.starter.version}
+
+
+ org.mybatis.spring.boot
+ mybatis-spring-boot-starter
+
+
+
+
+
+
+ tk.mybatis
+ mapper
+ ${mapper.version}
+
+
+
+
+ com.alibaba
+ fastjson
+ ${alibaba.fastjson.version}
+
+
+
+
+ com.squareup.okhttp3
+ okhttp
+ ${okhttp.version}
+
+
+
+
+ com.squareup.okio
+ okio
+ ${okio.version}
+
+
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+ provided
+
+
+
+
+ com.aliyun.oss
+ aliyun-sdk-oss
+ ${aliyun-sdk-oss.version}
+
+
+
+
+ ${project.groupId}
+ common
+ ${project.version}
+
+
+
+ ${project.groupId}
+ domain
+ ${project.version}
+
+
+
+ ${project.groupId}
+ thriparty
+ ${project.version}
+
+
+
+ ${project.groupId}
+ user_service
+ ${project.version}
+
+
+
+ ${project.groupId}
+ user_service_api
+ ${project.version}
+
+
+
+ ${project.groupId}
+ product_service
+ ${project.version}
+
+
+
+ ${project.groupId}
+ product_service_api
+ ${project.version}
+
+
+
+ ${project.groupId}
+ company_service_api
+ ${project.version}
+
+
+
+ ${project.groupId}
+ company_service
+ ${project.version}
+
+
+
+ ${project.groupId}
+ xcx_web
+ ${project.version}
+
+
+
+ ${project.groupId}
+ code_generator
+ ${project.version}
+
+
+
+
+
+
diff --git a/product_service/pom.xml b/product_service/pom.xml
new file mode 100644
index 0000000..1ae2443
--- /dev/null
+++ b/product_service/pom.xml
@@ -0,0 +1,41 @@
+
+
+ 4.0.0
+
+ com.sanbangzi
+ demo_mall
+ 0.0.1-SNAPSHOT
+
+
+
+ product_service
+
+
+
+ com.sanbangzi
+ common
+
+
+
+ com.sanbangzi
+ domain
+
+
+
+ com.sanbangzi
+ product_service_api
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.mybatis.spring.boot
+ mybatis-spring-boot-starter
+
+
+
+
diff --git a/product_service/src/main/java/com/sanbangzi/product_service/dao/ProductDao.java b/product_service/src/main/java/com/sanbangzi/product_service/dao/ProductDao.java
new file mode 100644
index 0000000..8dacd86
--- /dev/null
+++ b/product_service/src/main/java/com/sanbangzi/product_service/dao/ProductDao.java
@@ -0,0 +1,14 @@
+package com.sanbangzi.product_service.dao;
+
+import com.sanbangzi.common.utils.MyMapper;
+import com.sanbangzi.domain.dto.res.ProductResDTO;
+import com.sanbangzi.domain.entity.ProductEntity;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface ProductDao extends MyMapper {
+
+ List pageByType(@Param("typeId") Long typeId);
+
+}
diff --git a/product_service/src/main/java/com/sanbangzi/product_service/dao/ProudctResourceDao.java b/product_service/src/main/java/com/sanbangzi/product_service/dao/ProudctResourceDao.java
new file mode 100644
index 0000000..68ddfb0
--- /dev/null
+++ b/product_service/src/main/java/com/sanbangzi/product_service/dao/ProudctResourceDao.java
@@ -0,0 +1,7 @@
+package com.sanbangzi.product_service.dao;
+
+import com.sanbangzi.common.utils.MyMapper;
+import com.sanbangzi.domain.entity.ProudctResourceEntity;
+
+public interface ProudctResourceDao extends MyMapper {
+}
diff --git a/product_service/src/main/java/com/sanbangzi/product_service/impl/ProductServiceImpl.java b/product_service/src/main/java/com/sanbangzi/product_service/impl/ProductServiceImpl.java
new file mode 100644
index 0000000..336df36
--- /dev/null
+++ b/product_service/src/main/java/com/sanbangzi/product_service/impl/ProductServiceImpl.java
@@ -0,0 +1,105 @@
+package com.sanbangzi.product_service.impl;
+
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import com.google.common.base.Joiner;
+import com.google.common.collect.Lists;
+import com.sanbangzi.common.utils.BeanUtil;
+import com.sanbangzi.common.utils.CollectionUtil;
+import com.sanbangzi.common.utils.MyPage;
+import com.sanbangzi.domain.dto.req.ProductReqDTO;
+import com.sanbangzi.domain.dto.res.ProductDetailResDTO;
+import com.sanbangzi.domain.dto.res.ProductResDTO;
+import com.sanbangzi.domain.entity.ProductEntity;
+import com.sanbangzi.domain.entity.ProudctResourceEntity;
+import com.sanbangzi.product_service.dao.ProductDao;
+import com.sanbangzi.product_service.dao.ProudctResourceDao;
+import com.sanbangzi.product_service_api.api.ProductService;
+import com.sanbangzi.product_service_api.consts.ProductConst;
+import com.sanbangzi.product_service_api.exception.ProductException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import tk.mybatis.mapper.entity.Example;
+import tk.mybatis.mapper.weekend.WeekendSqls;
+
+import java.util.List;
+
+@Service
+public class ProductServiceImpl implements ProductService {
+
+ @Autowired
+ private ProductDao productDao;
+
+ @Autowired
+ private ProudctResourceDao proudctResourceDao;
+
+ @Override
+ public List getNew(Long companyId) throws ProductException {
+ PageHelper.startPage(1, ProductConst.NEW_PRODUCT_NUMBER);
+ Example example = Example.builder(ProductEntity.class)
+ .where(WeekendSqls.custom().andEqualTo(ProductEntity::getCompanyId, companyId))
+ .orderByDesc("createTime").build();
+ return BeanUtil.copyList(productDao.selectByExample(example), ProductResDTO.class);
+ }
+
+ @Override
+ public MyPage pageRecommend(ProductReqDTO productReqDTO) throws ProductException {
+ Example example = Example.builder(ProductEntity.class)
+ .where(WeekendSqls.custom().andEqualTo(ProductEntity::getCompanyId, productReqDTO.getCompanyId()))
+ .orderByDesc("updateTime").build();
+ PageHelper.startPage(productReqDTO.getPageNum(), productReqDTO.getPageSize());
+ return MyPage.newInstance(PageInfo.of(BeanUtil.copyList(productDao.selectByExample(example), ProductResDTO.class)));
+ }
+
+ @Override
+ public MyPage searchByTitle(ProductReqDTO productReqDTO) throws ProductException {
+ Example example = Example.builder(ProductEntity.class)
+ .where(WeekendSqls.custom().andLike(ProductEntity::getTitle, "%" + productReqDTO.getTitle() + "%"))
+ .orderByDesc("updateTime").build();
+ PageHelper.startPage(productReqDTO.getPageNum(), productReqDTO.getPageSize());
+ return MyPage.newInstance(PageInfo.of(BeanUtil.copyList(productDao.selectByExample(example), ProductResDTO.class)));
+ }
+
+ @Override
+ public MyPage pageByType(ProductReqDTO productReqDTO) throws ProductException {
+ PageHelper.startPage(productReqDTO.getPageNum(), productReqDTO.getPageSize());
+ List res = productDao.pageByType(productReqDTO.getTypeId());
+ return null == res ? null : MyPage.newInstance(PageInfo.of(res));
+ }
+
+ @Override
+ public ProductDetailResDTO getDetailById(Long productId) throws Exception {
+ ProductEntity entity = productDao.selectByPrimaryKey(productId);
+ if (null == entity) {
+ throw ProductException.throwBusiError("产品已下线");
+ }
+ ProductDetailResDTO res = BeanUtil.copyObject(entity, ProductDetailResDTO.class);
+
+ // 获取产品资源数据
+ Example example = Example.builder(ProudctResourceEntity.class)
+ .where(WeekendSqls.custom().andEqualTo(ProudctResourceEntity::getProductId, productId))
+ .orderByDesc("sort").build();
+ List resourceEntities = proudctResourceDao.selectByExample(example);
+ if (CollectionUtil.isBlank(resourceEntities)) {
+ throw ProductException.throwBusiError("产品已下线");
+ }
+ List carouselList = Lists.newArrayList();
+ String detail = null;
+ for (ProudctResourceEntity resourceEntity : resourceEntities) {
+ String resource = resourceEntity.getResource();
+ Byte type = resourceEntity.getType();
+ switch (type) {
+ case ProductConst.PRODUCT_RESOURCE_TYPE_CAROUSEL:
+ carouselList.add(resource);
+ break;
+ case ProductConst.PRODUCT_RESOURCE_TYPE_DETAIL:
+ detail = resource;
+ break;
+ default:
+ }
+ }
+ res.setCarousel(Joiner.on(",").join(carouselList));
+ res.setDetail(detail);
+ return res;
+ }
+}
diff --git a/product_service/src/main/resources/mapper/ProductMapper.xml b/product_service/src/main/resources/mapper/ProductMapper.xml
new file mode 100644
index 0000000..a0319cf
--- /dev/null
+++ b/product_service/src/main/resources/mapper/ProductMapper.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/product_service_api/pom.xml b/product_service_api/pom.xml
new file mode 100644
index 0000000..8e7ee58
--- /dev/null
+++ b/product_service_api/pom.xml
@@ -0,0 +1,32 @@
+
+
+ 4.0.0
+
+ com.sanbangzi
+ demo_mall
+ 0.0.1-SNAPSHOT
+
+
+
+ product_service_api
+
+
+
+ com.sanbangzi
+ domain
+
+
+
+ com.sanbangzi
+ common
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+
diff --git a/product_service_api/src/main/java/com/sanbangzi/product_service_api/api/ProductService.java b/product_service_api/src/main/java/com/sanbangzi/product_service_api/api/ProductService.java
new file mode 100644
index 0000000..5a692a6
--- /dev/null
+++ b/product_service_api/src/main/java/com/sanbangzi/product_service_api/api/ProductService.java
@@ -0,0 +1,22 @@
+package com.sanbangzi.product_service_api.api;
+
+import com.sanbangzi.common.utils.MyPage;
+import com.sanbangzi.domain.dto.req.ProductReqDTO;
+import com.sanbangzi.domain.dto.res.ProductDetailResDTO;
+import com.sanbangzi.domain.dto.res.ProductResDTO;
+import com.sanbangzi.product_service_api.exception.ProductException;
+
+import java.util.List;
+
+public interface ProductService {
+
+ List getNew(Long companyId) throws ProductException;
+
+ MyPage pageRecommend(ProductReqDTO productReqDTO) throws ProductException;
+
+ MyPage searchByTitle(ProductReqDTO productReqDTO) throws ProductException;
+
+ MyPage pageByType(ProductReqDTO productReqDTO) throws ProductException;
+
+ ProductDetailResDTO getDetailById(Long productId) throws Exception;
+}
diff --git a/product_service_api/src/main/java/com/sanbangzi/product_service_api/consts/ProductCacheKeyConst.java b/product_service_api/src/main/java/com/sanbangzi/product_service_api/consts/ProductCacheKeyConst.java
new file mode 100644
index 0000000..eb95ef2
--- /dev/null
+++ b/product_service_api/src/main/java/com/sanbangzi/product_service_api/consts/ProductCacheKeyConst.java
@@ -0,0 +1,4 @@
+package com.sanbangzi.product_service_api.consts;
+
+public class ProductCacheKeyConst {
+}
diff --git a/product_service_api/src/main/java/com/sanbangzi/product_service_api/consts/ProductConst.java b/product_service_api/src/main/java/com/sanbangzi/product_service_api/consts/ProductConst.java
new file mode 100644
index 0000000..b7294a4
--- /dev/null
+++ b/product_service_api/src/main/java/com/sanbangzi/product_service_api/consts/ProductConst.java
@@ -0,0 +1,11 @@
+package com.sanbangzi.product_service_api.consts;
+
+public class ProductConst {
+
+ /** 新品展示数量 */
+ public static final Integer NEW_PRODUCT_NUMBER = 6;
+
+ /** 产品资源类型 */
+ public static final byte PRODUCT_RESOURCE_TYPE_CAROUSEL = 1; // 轮播图
+ public static final byte PRODUCT_RESOURCE_TYPE_DETAIL = 2; // 产品详情
+}
diff --git a/product_service_api/src/main/java/com/sanbangzi/product_service_api/exception/ProductErrorCode.java b/product_service_api/src/main/java/com/sanbangzi/product_service_api/exception/ProductErrorCode.java
new file mode 100644
index 0000000..125dae6
--- /dev/null
+++ b/product_service_api/src/main/java/com/sanbangzi/product_service_api/exception/ProductErrorCode.java
@@ -0,0 +1,21 @@
+package com.sanbangzi.product_service_api.exception;
+
+import lombok.Getter;
+import lombok.Setter;
+
+public enum ProductErrorCode {
+
+ BUSINESS_ERROR(30001, "");
+
+ @Getter
+ private Integer code;
+
+ @Getter
+ @Setter
+ private String msg;
+
+ private ProductErrorCode(Integer code, String msg) {
+ this.code = code;
+ this.msg = msg;
+ }
+}
diff --git a/product_service_api/src/main/java/com/sanbangzi/product_service_api/exception/ProductException.java b/product_service_api/src/main/java/com/sanbangzi/product_service_api/exception/ProductException.java
new file mode 100644
index 0000000..34d37d2
--- /dev/null
+++ b/product_service_api/src/main/java/com/sanbangzi/product_service_api/exception/ProductException.java
@@ -0,0 +1,16 @@
+package com.sanbangzi.product_service_api.exception;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@AllArgsConstructor
+public class ProductException extends RuntimeException {
+
+ @Getter
+ private ProductErrorCode productErrorCode;
+
+ public static ProductException throwBusiError(String msg) {
+ ProductErrorCode.BUSINESS_ERROR.setMsg(msg);
+ return new ProductException(ProductErrorCode.BUSINESS_ERROR);
+ }
+}
diff --git a/thriparty/pom.xml b/thriparty/pom.xml
new file mode 100644
index 0000000..02ce316
--- /dev/null
+++ b/thriparty/pom.xml
@@ -0,0 +1,36 @@
+
+
+ 4.0.0
+
+ com.sanbangzi
+ demo_mall
+ 0.0.1-SNAPSHOT
+
+
+
+ thriparty
+
+
+
+ com.sanbangzi
+ common
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ com.alibaba
+ fastjson
+
+
+
+ com.aliyun.oss
+ aliyun-sdk-oss
+
+
+
+
diff --git a/thriparty/src/main/java/com/sanbangzi/thriparty/ali/oss/OssConst.java b/thriparty/src/main/java/com/sanbangzi/thriparty/ali/oss/OssConst.java
new file mode 100644
index 0000000..469f3f8
--- /dev/null
+++ b/thriparty/src/main/java/com/sanbangzi/thriparty/ali/oss/OssConst.java
@@ -0,0 +1,16 @@
+package com.sanbangzi.thriparty.ali.oss;
+
+public class OssConst {
+
+ public static final String ENDPOINT = "http://oss-cn-hangzhou.aliyuncs.com";
+
+ public static final String ACCESS_KEY_ID = "";
+
+ public static final String ACCESS_KEY_SECRET = "";
+
+ public static final String BUCKET = "sanbangzi20181225";
+
+ public static final String FILE_NAME_PREFIX = "https://"+ BUCKET +".oss-cn-hangzhou.aliyuncs.com/";
+
+ public static final String USER_HEAD_PHOTO_DIR = "img/user/headPhoto/";
+}
diff --git a/thriparty/src/main/java/com/sanbangzi/thriparty/ali/oss/OssUtil.java b/thriparty/src/main/java/com/sanbangzi/thriparty/ali/oss/OssUtil.java
new file mode 100644
index 0000000..898f559
--- /dev/null
+++ b/thriparty/src/main/java/com/sanbangzi/thriparty/ali/oss/OssUtil.java
@@ -0,0 +1,40 @@
+package com.sanbangzi.thriparty.ali.oss;
+
+import com.aliyun.oss.OSSClient;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.rmi.ServerException;
+
+public class OssUtil {
+
+ /**
+ * 字节数组上传
+ */
+ public static String uploadByteArr(String key, byte[] bytes) throws ServerException {
+ OSSClient ossClient = new OSSClient(OssConst.ENDPOINT, OssConst.ACCESS_KEY_ID, OssConst.ACCESS_KEY_SECRET);
+ ossClient.putObject(OssConst.BUCKET, key, new ByteArrayInputStream(bytes));
+ ossClient.shutdown();
+ return OssConst.FILE_NAME_PREFIX + key;
+ }
+
+ /**
+ * 图片地址上传
+ */
+ public static String uploadUrlImg(String key, String imgUrl) throws ServerException {
+ OSSClient ossClient = new OSSClient(OssConst.ENDPOINT, OssConst.ACCESS_KEY_ID, OssConst.ACCESS_KEY_SECRET);
+ InputStream inputStream = null;
+ try {
+ inputStream = new URL(imgUrl).openStream();
+ ossClient.putObject(OssConst.BUCKET, key, inputStream);
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ ossClient.shutdown();
+ }
+ return OssConst.FILE_NAME_PREFIX + key;
+ }
+
+}
diff --git a/thriparty/src/main/java/com/sanbangzi/thriparty/wx/xcx/XcxManage.java b/thriparty/src/main/java/com/sanbangzi/thriparty/wx/xcx/XcxManage.java
new file mode 100644
index 0000000..e0d9e71
--- /dev/null
+++ b/thriparty/src/main/java/com/sanbangzi/thriparty/wx/xcx/XcxManage.java
@@ -0,0 +1,13 @@
+package com.sanbangzi.thriparty.wx.xcx;
+
+import java.util.Map;
+
+public interface XcxManage {
+
+ /**
+ * 根据code兑换openId
+ * @param code
+ * @return
+ */
+ Map getOpenIdByCode(String code);
+}
diff --git a/thriparty/src/main/java/com/sanbangzi/thriparty/wx/xcx/XcxUtil.java b/thriparty/src/main/java/com/sanbangzi/thriparty/wx/xcx/XcxUtil.java
new file mode 100644
index 0000000..6b04626
--- /dev/null
+++ b/thriparty/src/main/java/com/sanbangzi/thriparty/wx/xcx/XcxUtil.java
@@ -0,0 +1,67 @@
+package com.sanbangzi.thriparty.wx.xcx;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.google.common.collect.Maps;
+import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.security.AlgorithmParameters;
+import java.util.Arrays;
+import java.util.Map;
+
+public class XcxUtil {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(XcxUtil.class);
+
+ /**
+ * 解密微信用户信息
+ */
+ public static Map decodeUserInfo(String userInfo, String sessionKey) {
+ JSONObject jsonObject = JSON.parseObject(userInfo);
+
+ // 被加密的数据
+ String encryptedData = jsonObject.getString("encryptedData");
+ byte[] dataByte = Base64.decode(encryptedData);
+ // 加密秘钥
+ byte[] keyByte = Base64.decode(sessionKey);
+ // 偏移量
+ String iv = jsonObject.getString("iv");
+ byte[] ivByte = Base64.decode(iv);
+
+ //如果密钥不足16位,那么就补足。备注:这个if中的内容很重要
+ try {
+ int base = 16;
+ if (keyByte.length % base != 0) {
+ int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
+ byte[] temp = new byte[groups * base];
+ Arrays.fill(temp, (byte) 0);
+ System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
+ keyByte = temp;
+ }
+ //获取解密公钥KEY
+ SecretKeySpec specKey = new SecretKeySpec(keyByte, "AES");
+
+ AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
+ parameters.init(new IvParameterSpec(ivByte));
+
+ Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
+ cipher.init(Cipher.DECRYPT_MODE, specKey, parameters);
+ byte[] resultByte = cipher.doFinal(dataByte);
+
+ //返回结果
+ if (null != resultByte && resultByte.length > 0) {
+ String result = new String(resultByte, "UTF-8");
+ LOGGER.info("小程序解密用户信息为:[{}]", result);
+ return JSON.parseObject(result, Map.class);
+ }
+ } catch (Exception ex) {
+ LOGGER.error("小程序解密用户信息失败:[{}]", ex);
+ }
+ return null;
+ }
+}
diff --git a/thriparty/src/main/java/com/sanbangzi/thriparty/wx/xcx/impl/XcxManageImpl.java b/thriparty/src/main/java/com/sanbangzi/thriparty/wx/xcx/impl/XcxManageImpl.java
new file mode 100644
index 0000000..f68e49f
--- /dev/null
+++ b/thriparty/src/main/java/com/sanbangzi/thriparty/wx/xcx/impl/XcxManageImpl.java
@@ -0,0 +1,36 @@
+package com.sanbangzi.thriparty.wx.xcx.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.google.common.collect.Maps;
+import com.sanbangzi.common.utils.okhttp.OkHttpUtil;
+import com.sanbangzi.thriparty.wx.xcx.XcxManage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+@Component
+public class XcxManageImpl implements XcxManage {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(XcxManageImpl.class);
+
+ private static final String APP_ID = "";
+
+ private static final String APP_SECRET = "";
+
+ private static final String XCX_EXCHANGE_OPEN_ID_URL = "https://api.weixin.qq.com/sns/jscode2session";
+
+ public Map getOpenIdByCode(String code) {
+ Map params = Maps.newHashMap();
+ params.put("grant_type", "authorization_code");
+ params.put("appid", APP_ID);
+ params.put("secret", APP_SECRET);
+ params.put("js_code", code);
+ LOGGER.info("请求微信用code兑换openId,参数[{}]", params);
+ String response = OkHttpUtil.okHttpSynGet(XCX_EXCHANGE_OPEN_ID_URL, params);
+ LOGGER.info("请求微信用code兑换openId,返回结果[{}]", response);
+ return JSONObject.parseObject(response, Map.class);
+ }
+
+}
diff --git a/user_service/pom.xml b/user_service/pom.xml
new file mode 100644
index 0000000..e89f4bd
--- /dev/null
+++ b/user_service/pom.xml
@@ -0,0 +1,46 @@
+
+
+ 4.0.0
+
+ com.sanbangzi
+ demo_mall
+ 0.0.1-SNAPSHOT
+
+
+
+ user_service
+
+
+
+ com.sanbangzi
+ domain
+
+
+
+ com.sanbangzi
+ common
+
+
+
+ com.sanbangzi
+ thriparty
+
+
+
+ com.sanbangzi
+ user_service_api
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+
diff --git a/user_service/src/main/java/com/sanbangzi/user_service/dao/UserDao.java b/user_service/src/main/java/com/sanbangzi/user_service/dao/UserDao.java
new file mode 100644
index 0000000..2f5e773
--- /dev/null
+++ b/user_service/src/main/java/com/sanbangzi/user_service/dao/UserDao.java
@@ -0,0 +1,7 @@
+package com.sanbangzi.user_service.dao;
+
+import com.sanbangzi.common.utils.MyMapper;
+import com.sanbangzi.domain.entity.UserEntity;
+
+public interface UserDao extends MyMapper {
+}
diff --git a/user_service/src/main/java/com/sanbangzi/user_service/impl/UserServiceImpl.java b/user_service/src/main/java/com/sanbangzi/user_service/impl/UserServiceImpl.java
new file mode 100644
index 0000000..7059891
--- /dev/null
+++ b/user_service/src/main/java/com/sanbangzi/user_service/impl/UserServiceImpl.java
@@ -0,0 +1,53 @@
+package com.sanbangzi.user_service.impl;
+
+import com.sanbangzi.common.utils.BeanUtil;
+import com.sanbangzi.common.utils.RandomUtil;
+import com.sanbangzi.domain.dto.req.UserReqDTO;
+import com.sanbangzi.domain.dto.res.UserResDTO;
+import com.sanbangzi.domain.entity.UserEntity;
+import com.sanbangzi.user_service.dao.UserDao;
+import com.sanbangzi.user_service_api.api.UserService;
+import com.sanbangzi.user_service_api.consts.UserConst;
+import com.sanbangzi.user_service_api.exception.UserException;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import tk.mybatis.mapper.entity.Example;
+import tk.mybatis.mapper.weekend.WeekendSqls;
+
+import java.util.Date;
+import java.util.Optional;
+
+@Service
+public class UserServiceImpl implements UserService {
+
+ @Autowired
+ private UserDao userDao;
+
+ @Override
+ public UserResDTO getById(Long userId) throws UserException {
+ return BeanUtil.copyObject(userDao.selectByPrimaryKey(userId), UserResDTO.class);
+ }
+
+ @Override
+ public UserResDTO getByOpenId(String openId) throws UserException {
+ Example example = Example.builder(UserEntity.class)
+ .where(WeekendSqls.custom().andEqualTo(UserEntity::getOpenId, openId))
+ .build();
+ return BeanUtil.copyObject(userDao.selectOneByExample(example), UserResDTO.class);
+ }
+
+ @Override
+ public Long save(UserReqDTO user) throws Exception {
+ UserEntity entity = new UserEntity();
+ BeanUtils.copyProperties(user, entity);
+ String code = RandomUtil.uuid();
+ Date now = new Date();
+ entity.setCode(code);
+ entity.setStatus(UserConst.USER_STATUS_NORMAL);
+ entity.setCreateTime(now);
+ entity.setUpdateTime(now);
+ userDao.insertSelective(entity);
+ return entity.getId();
+ }
+}
diff --git a/user_service/src/main/java/com/sanbangzi/user_service/impl/XcxLoginServiceImpl.java b/user_service/src/main/java/com/sanbangzi/user_service/impl/XcxLoginServiceImpl.java
new file mode 100644
index 0000000..6fa4d1d
--- /dev/null
+++ b/user_service/src/main/java/com/sanbangzi/user_service/impl/XcxLoginServiceImpl.java
@@ -0,0 +1,97 @@
+package com.sanbangzi.user_service.impl;
+
+import com.sanbangzi.common.utils.RandomUtil;
+import com.sanbangzi.common.utils.StringUtil;
+import com.sanbangzi.domain.dto.req.UserReqDTO;
+import com.sanbangzi.domain.dto.res.UserResDTO;
+import com.sanbangzi.domain.dto.res.XcxLoginResDTO;
+import com.sanbangzi.thriparty.ali.oss.OssConst;
+import com.sanbangzi.thriparty.ali.oss.OssUtil;
+import com.sanbangzi.thriparty.wx.xcx.XcxManage;
+import com.sanbangzi.thriparty.wx.xcx.XcxUtil;
+import com.sanbangzi.user_service_api.api.UserService;
+import com.sanbangzi.user_service_api.api.XcxLoginService;
+import com.sanbangzi.user_service_api.consts.UserCacheKeyConst;
+import com.sanbangzi.user_service_api.exception.UserErrorCode;
+import com.sanbangzi.user_service_api.exception.UserException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Service;
+
+import java.util.Map;
+
+@Service
+public class XcxLoginServiceImpl implements XcxLoginService {
+
+ @Autowired
+ private XcxManage xcxManage;
+
+ @Autowired
+ private UserService userService;
+
+ @Autowired
+ private StringRedisTemplate stringRedisTemplate;
+
+ @Override
+ public XcxLoginResDTO login(String code) throws UserException {
+ Map xcxResMap = xcxManage.getOpenIdByCode(code);
+ String openId = xcxResMap.get("openid");
+ if (StringUtil.isBlank(openId)) {
+ throw UserException.throwErrorCode(UserErrorCode.LOGIN_ERROR);
+ }
+ UserResDTO userResDTO = userService.getByOpenId(openId);
+ if (null == userResDTO) {
+ throw UserException.throwErrorCode(UserErrorCode.LOGIN_ERROR);
+ }
+ Long userId = userResDTO.getId();
+ String accessToken = RandomUtil.uuid();
+ stringRedisTemplate.opsForValue().set(UserCacheKeyConst.XCX_ACCESS_TOKEN + accessToken, String.valueOf(userId), UserCacheKeyConst.XCX_ACCESS_TOKEN_EXPIRE_TIME);
+
+ XcxLoginResDTO xcxLoginResDTO = new XcxLoginResDTO();
+ xcxLoginResDTO.setUserId(userId);
+ xcxLoginResDTO.setAccessToken(accessToken);
+ xcxLoginResDTO.setHeadPhoto(userResDTO.getHeadPhoto());
+ xcxLoginResDTO.setNickName(userResDTO.getNickName());
+ return xcxLoginResDTO;
+ }
+
+ @Override
+ public XcxLoginResDTO register(String code, String userInfo) throws Exception {
+ Map xcxResMap = xcxManage.getOpenIdByCode(code);
+ String openId = xcxResMap.get("openid");
+ String sessionKey = xcxResMap.get("session_key");
+ if (StringUtil.isBlank(openId)) {
+ throw UserException.throwErrorCode(UserErrorCode.REGISTER_ERROR);
+ }
+ if (null != userService.getByOpenId(openId)) {
+ throw UserException.throwErrorCode(UserErrorCode.REGISTER_ERROR);
+ }
+ Map decodeUserInfo = XcxUtil.decodeUserInfo(userInfo, sessionKey);
+ if (null == decodeUserInfo) {
+ throw UserException.throwErrorCode(UserErrorCode.REGISTER_ERROR);
+ }
+
+ // 注册用户
+ UserReqDTO userReq = new UserReqDTO();
+ userReq.setOpenId(openId);
+ String nickName = decodeUserInfo.get("nickName").toString();
+ userReq.setNickName(nickName);
+ String avatarUrl = decodeUserInfo.get("avatarUrl").toString();
+ // 上传头像
+ String key = String.format("%s%s%s", OssConst.USER_HEAD_PHOTO_DIR, RandomUtil.uuid(), ".jpeg");
+ String headPhoto = OssUtil.uploadUrlImg(key, avatarUrl);
+ userReq.setHeadPhoto(headPhoto);
+ Long userId = userService.save(userReq);
+
+ // 登录
+ String accessToken = RandomUtil.uuid();
+ stringRedisTemplate.opsForValue().set(UserCacheKeyConst.XCX_ACCESS_TOKEN + accessToken, String.valueOf(userId), UserCacheKeyConst.XCX_ACCESS_TOKEN_EXPIRE_TIME);
+
+ XcxLoginResDTO xcxLoginResDTO = new XcxLoginResDTO();
+ xcxLoginResDTO.setUserId(userId);
+ xcxLoginResDTO.setAccessToken(accessToken);
+ xcxLoginResDTO.setNickName(nickName);
+ xcxLoginResDTO.setHeadPhoto(headPhoto);
+ return xcxLoginResDTO;
+ }
+}
diff --git a/user_service_api/pom.xml b/user_service_api/pom.xml
new file mode 100644
index 0000000..79cf3d6
--- /dev/null
+++ b/user_service_api/pom.xml
@@ -0,0 +1,27 @@
+
+
+ 4.0.0
+
+ com.sanbangzi
+ demo_mall
+ 0.0.1-SNAPSHOT
+
+
+
+ user_service_api
+
+
+
+ com.sanbangzi
+ domain
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+
diff --git a/user_service_api/src/main/java/com/sanbangzi/user_service_api/api/UserService.java b/user_service_api/src/main/java/com/sanbangzi/user_service_api/api/UserService.java
new file mode 100644
index 0000000..66b93e3
--- /dev/null
+++ b/user_service_api/src/main/java/com/sanbangzi/user_service_api/api/UserService.java
@@ -0,0 +1,16 @@
+package com.sanbangzi.user_service_api.api;
+
+import com.sanbangzi.domain.dto.req.UserReqDTO;
+import com.sanbangzi.domain.dto.res.UserResDTO;
+import com.sanbangzi.user_service_api.exception.UserException;
+
+import java.util.Optional;
+
+public interface UserService {
+
+ UserResDTO getById(Long userId) throws UserException;
+
+ UserResDTO getByOpenId(String openId) throws UserException;
+
+ Long save(UserReqDTO user) throws Exception;
+}
diff --git a/user_service_api/src/main/java/com/sanbangzi/user_service_api/api/XcxLoginService.java b/user_service_api/src/main/java/com/sanbangzi/user_service_api/api/XcxLoginService.java
new file mode 100644
index 0000000..bc34fd4
--- /dev/null
+++ b/user_service_api/src/main/java/com/sanbangzi/user_service_api/api/XcxLoginService.java
@@ -0,0 +1,11 @@
+package com.sanbangzi.user_service_api.api;
+
+import com.sanbangzi.domain.dto.res.XcxLoginResDTO;
+import com.sanbangzi.user_service_api.exception.UserException;
+
+public interface XcxLoginService {
+
+ XcxLoginResDTO login(String code) throws UserException;
+
+ XcxLoginResDTO register(String code, String userInfo) throws Exception;
+}
diff --git a/user_service_api/src/main/java/com/sanbangzi/user_service_api/consts/UserCacheKeyConst.java b/user_service_api/src/main/java/com/sanbangzi/user_service_api/consts/UserCacheKeyConst.java
new file mode 100644
index 0000000..a8f64ce
--- /dev/null
+++ b/user_service_api/src/main/java/com/sanbangzi/user_service_api/consts/UserCacheKeyConst.java
@@ -0,0 +1,7 @@
+package com.sanbangzi.user_service_api.consts;
+
+public class UserCacheKeyConst {
+
+ public static final String XCX_ACCESS_TOKEN = "xcx_access_token:";
+ public static final Long XCX_ACCESS_TOKEN_EXPIRE_TIME = 24 * 60 * 60L;
+}
diff --git a/user_service_api/src/main/java/com/sanbangzi/user_service_api/consts/UserConst.java b/user_service_api/src/main/java/com/sanbangzi/user_service_api/consts/UserConst.java
new file mode 100644
index 0000000..18d908f
--- /dev/null
+++ b/user_service_api/src/main/java/com/sanbangzi/user_service_api/consts/UserConst.java
@@ -0,0 +1,6 @@
+package com.sanbangzi.user_service_api.consts;
+
+public class UserConst {
+
+ public static final Byte USER_STATUS_NORMAL = 1;
+}
diff --git a/user_service_api/src/main/java/com/sanbangzi/user_service_api/exception/UserErrorCode.java b/user_service_api/src/main/java/com/sanbangzi/user_service_api/exception/UserErrorCode.java
new file mode 100644
index 0000000..c24f985
--- /dev/null
+++ b/user_service_api/src/main/java/com/sanbangzi/user_service_api/exception/UserErrorCode.java
@@ -0,0 +1,23 @@
+package com.sanbangzi.user_service_api.exception;
+
+import lombok.Getter;
+import lombok.Setter;
+
+public enum UserErrorCode {
+
+ BUSINESS_ERROR(20001, ""),
+ LOGIN_ERROR(20002, "登录失败"),
+ REGISTER_ERROR(20003, "注册失败");
+
+ @Getter
+ private Integer code;
+
+ @Getter
+ @Setter
+ private String msg;
+
+ private UserErrorCode(Integer code, String msg) {
+ this.code = code;
+ this.msg = msg;
+ }
+}
diff --git a/user_service_api/src/main/java/com/sanbangzi/user_service_api/exception/UserException.java b/user_service_api/src/main/java/com/sanbangzi/user_service_api/exception/UserException.java
new file mode 100644
index 0000000..44f9a93
--- /dev/null
+++ b/user_service_api/src/main/java/com/sanbangzi/user_service_api/exception/UserException.java
@@ -0,0 +1,20 @@
+package com.sanbangzi.user_service_api.exception;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@AllArgsConstructor
+public class UserException extends RuntimeException {
+
+ @Getter
+ private UserErrorCode userErrorCode;
+
+ public static UserException throwErrorCode(UserErrorCode userErrorCode) {
+ return new UserException(userErrorCode);
+ }
+
+ public static UserException throwBusiError(String msg) {
+ UserErrorCode.BUSINESS_ERROR.setMsg(msg);
+ return new UserException(UserErrorCode.BUSINESS_ERROR);
+ }
+}
diff --git a/xcx_web/pom.xml b/xcx_web/pom.xml
new file mode 100644
index 0000000..0129891
--- /dev/null
+++ b/xcx_web/pom.xml
@@ -0,0 +1,121 @@
+
+
+ 4.0.0
+
+ com.sanbangzi
+ demo_mall
+ 0.0.1-SNAPSHOT
+
+
+
+ xcx_web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+ redis.clients
+ jedis
+
+
+
+ org.apache.commons
+ commons-pool2
+
+
+
+ com.alibaba
+ fastjson
+
+
+
+ com.alibaba
+ druid
+
+
+
+ mysql
+ mysql-connector-java
+
+
+
+ org.mybatis.spring.boot
+ mybatis-spring-boot-starter
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ commons-io
+ commons-io
+
+
+
+ com.sanbangzi
+ common
+
+
+
+ com.sanbangzi
+ user_service_api
+
+
+
+ com.sanbangzi
+ user_service
+
+
+
+ com.sanbangzi
+ domain
+
+
+
+ com.sanbangzi
+ common
+
+
+
+ com.sanbangzi
+ company_service_api
+
+
+
+ com.sanbangzi
+ company_service
+
+
+
+ com.sanbangzi
+ product_service_api
+
+
+
+ com.sanbangzi
+ product_service
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/xcx_web/src/main/java/com/sanbangzi/xcx_web/XcxWebApplication.java b/xcx_web/src/main/java/com/sanbangzi/xcx_web/XcxWebApplication.java
new file mode 100644
index 0000000..49e76e2
--- /dev/null
+++ b/xcx_web/src/main/java/com/sanbangzi/xcx_web/XcxWebApplication.java
@@ -0,0 +1,18 @@
+package com.sanbangzi.xcx_web;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.ComponentScan;
+import tk.mybatis.spring.annotation.MapperScan;
+
+@ComponentScan(basePackages = {"com.sanbangzi"})
+@MapperScan(basePackages = "com.sanbangzi.*.dao")
+@SpringBootApplication
+public class XcxWebApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(XcxWebApplication.class, args);
+ }
+
+}
+
diff --git a/xcx_web/src/main/java/com/sanbangzi/xcx_web/annotation/CurrentUser.java b/xcx_web/src/main/java/com/sanbangzi/xcx_web/annotation/CurrentUser.java
new file mode 100644
index 0000000..59d6278
--- /dev/null
+++ b/xcx_web/src/main/java/com/sanbangzi/xcx_web/annotation/CurrentUser.java
@@ -0,0 +1,11 @@
+package com.sanbangzi.xcx_web.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.PARAMETER)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface CurrentUser {
+}
diff --git a/xcx_web/src/main/java/com/sanbangzi/xcx_web/annotation/IgnoreLogin.java b/xcx_web/src/main/java/com/sanbangzi/xcx_web/annotation/IgnoreLogin.java
new file mode 100644
index 0000000..a567414
--- /dev/null
+++ b/xcx_web/src/main/java/com/sanbangzi/xcx_web/annotation/IgnoreLogin.java
@@ -0,0 +1,11 @@
+package com.sanbangzi.xcx_web.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface IgnoreLogin {
+}
diff --git a/xcx_web/src/main/java/com/sanbangzi/xcx_web/annotation/IgnoreSignature.java b/xcx_web/src/main/java/com/sanbangzi/xcx_web/annotation/IgnoreSignature.java
new file mode 100644
index 0000000..00bd1c2
--- /dev/null
+++ b/xcx_web/src/main/java/com/sanbangzi/xcx_web/annotation/IgnoreSignature.java
@@ -0,0 +1,11 @@
+package com.sanbangzi.xcx_web.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface IgnoreSignature {
+}
diff --git a/xcx_web/src/main/java/com/sanbangzi/xcx_web/annotation/RequestParamsNotEmpty.java b/xcx_web/src/main/java/com/sanbangzi/xcx_web/annotation/RequestParamsNotEmpty.java
new file mode 100644
index 0000000..9bd3865
--- /dev/null
+++ b/xcx_web/src/main/java/com/sanbangzi/xcx_web/annotation/RequestParamsNotEmpty.java
@@ -0,0 +1,14 @@
+package com.sanbangzi.xcx_web.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface RequestParamsNotEmpty {
+
+ String[] names() default {};
+
+}
diff --git a/xcx_web/src/main/java/com/sanbangzi/xcx_web/api/BaseController.java b/xcx_web/src/main/java/com/sanbangzi/xcx_web/api/BaseController.java
new file mode 100644
index 0000000..3e475df
--- /dev/null
+++ b/xcx_web/src/main/java/com/sanbangzi/xcx_web/api/BaseController.java
@@ -0,0 +1,24 @@
+package com.sanbangzi.xcx_web.api;
+
+import com.sanbangzi.common.utils.WebResponse;
+
+public abstract class BaseController {
+
+ /**
+ * 成功返回不带数据
+ */
+ protected WebResponse xcxSuccess() {
+ WebResponse response = new WebResponse();
+ response.setCode(200);
+ response.setMsg("成功");
+ return response;
+ }
+
+ /**
+ * 成功返回带数据
+ */
+ protected WebResponse xcxSuccess(Object data) {
+ return new WebResponse(200, "成功", data);
+ }
+
+}
diff --git a/xcx_web/src/main/java/com/sanbangzi/xcx_web/api/CompanyController.java b/xcx_web/src/main/java/com/sanbangzi/xcx_web/api/CompanyController.java
new file mode 100644
index 0000000..605783e
--- /dev/null
+++ b/xcx_web/src/main/java/com/sanbangzi/xcx_web/api/CompanyController.java
@@ -0,0 +1,39 @@
+package com.sanbangzi.xcx_web.api;
+
+import com.sanbangzi.common.utils.WebResponse;
+import com.sanbangzi.company_service_api.api.CompanyBannerService;
+import com.sanbangzi.company_service_api.api.CompanyProductTypeService;
+import com.sanbangzi.domain.dto.res.CompanyBannerResDTO;
+import com.sanbangzi.xcx_web.annotation.IgnoreLogin;
+import com.sanbangzi.xcx_web.annotation.RequestParamsNotEmpty;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/company")
+public class CompanyController extends BaseController {
+
+ @Autowired
+ private CompanyBannerService companyBannerService;
+
+ @Autowired
+ private CompanyProductTypeService companyProductTypeService;
+
+ @IgnoreLogin
+ @GetMapping("/banner")
+ @RequestParamsNotEmpty(names = {"companyId"})
+ public WebResponse banner(Long companyId) throws Exception {
+ List companyBannerResDTOS = companyBannerService.listByCompanyId(companyId);
+ return xcxSuccess(companyBannerResDTOS);
+ }
+
+ @IgnoreLogin
+ @GetMapping("/productType")
+ @RequestParamsNotEmpty(names = {"companyId"})
+ public WebResponse productType(Long companyId) throws Exception {
+ return xcxSuccess(companyProductTypeService.listByCompanyId(companyId));
+ }
+
+}
diff --git a/xcx_web/src/main/java/com/sanbangzi/xcx_web/api/LoginController.java b/xcx_web/src/main/java/com/sanbangzi/xcx_web/api/LoginController.java
new file mode 100644
index 0000000..d83dadc
--- /dev/null
+++ b/xcx_web/src/main/java/com/sanbangzi/xcx_web/api/LoginController.java
@@ -0,0 +1,30 @@
+package com.sanbangzi.xcx_web.api;
+
+import com.sanbangzi.common.utils.WebResponse;
+import com.sanbangzi.user_service_api.api.XcxLoginService;
+import com.sanbangzi.xcx_web.annotation.IgnoreLogin;
+import com.sanbangzi.xcx_web.annotation.RequestParamsNotEmpty;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class LoginController extends BaseController {
+
+ @Autowired
+ private XcxLoginService xcxLoginService;
+
+ @IgnoreLogin
+ @RequestParamsNotEmpty(names = {"code"})
+ @GetMapping("/login")
+ public WebResponse login(String code) throws Exception {
+ return xcxSuccess(xcxLoginService.login(code));
+ }
+
+ @IgnoreLogin
+ @RequestParamsNotEmpty(names = {"code", "userInfo"})
+ @GetMapping("/register")
+ public WebResponse register(String code, String userInfo) throws Exception {
+ return xcxSuccess(xcxLoginService.register(code, userInfo));
+ }
+}
diff --git a/xcx_web/src/main/java/com/sanbangzi/xcx_web/api/ProductController.java b/xcx_web/src/main/java/com/sanbangzi/xcx_web/api/ProductController.java
new file mode 100644
index 0000000..25277f8
--- /dev/null
+++ b/xcx_web/src/main/java/com/sanbangzi/xcx_web/api/ProductController.java
@@ -0,0 +1,53 @@
+package com.sanbangzi.xcx_web.api;
+
+import com.sanbangzi.common.utils.WebResponse;
+import com.sanbangzi.domain.dto.req.ProductReqDTO;
+import com.sanbangzi.product_service_api.api.ProductService;
+import com.sanbangzi.xcx_web.annotation.IgnoreLogin;
+import com.sanbangzi.xcx_web.annotation.RequestParamsNotEmpty;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/product")
+public class ProductController extends BaseController {
+
+ @Autowired
+ private ProductService productService;
+
+ @IgnoreLogin
+ @GetMapping("/getNew")
+ @RequestParamsNotEmpty(names = {"companyId"})
+ public WebResponse getNew(Long companyId) throws Exception {
+ return xcxSuccess(productService.getNew(companyId));
+ }
+
+ @IgnoreLogin
+ @PostMapping("/pageRecommend")
+ @RequestParamsNotEmpty(names = {"companyId", "pageNum", "pageSize"})
+ public WebResponse pageRecommend(@RequestBody ProductReqDTO productReqDTO) throws Exception {
+ return xcxSuccess(productService.pageRecommend(productReqDTO));
+ }
+
+ @IgnoreLogin
+ @PostMapping("/search")
+ @RequestParamsNotEmpty(names = {"companyId", "pageNum", "pageSize"})
+ public WebResponse search(@RequestBody ProductReqDTO productReqDTO) throws Exception {
+ return xcxSuccess(productService.searchByTitle(productReqDTO));
+ }
+
+ @IgnoreLogin
+ @PostMapping("/pageByType")
+ @RequestParamsNotEmpty(names = {"companyId", "pageNum", "pageSize"})
+ public WebResponse pageByType(@RequestBody ProductReqDTO productReqDTO) throws Exception {
+ return xcxSuccess(productService.pageByType(productReqDTO));
+ }
+
+ @IgnoreLogin
+ @GetMapping("/detail")
+ @RequestParamsNotEmpty(names = {"productId"})
+ public WebResponse getById(Long productId) throws Exception {
+ return xcxSuccess(productService.getDetailById(productId));
+ }
+
+}
diff --git a/xcx_web/src/main/java/com/sanbangzi/xcx_web/api/UserController.java b/xcx_web/src/main/java/com/sanbangzi/xcx_web/api/UserController.java
new file mode 100644
index 0000000..34dd5c8
--- /dev/null
+++ b/xcx_web/src/main/java/com/sanbangzi/xcx_web/api/UserController.java
@@ -0,0 +1,9 @@
+package com.sanbangzi.xcx_web.api;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/user")
+public class UserController extends BaseController {
+}
diff --git a/xcx_web/src/main/java/com/sanbangzi/xcx_web/config/CorsConfig.java b/xcx_web/src/main/java/com/sanbangzi/xcx_web/config/CorsConfig.java
new file mode 100644
index 0000000..f91a315
--- /dev/null
+++ b/xcx_web/src/main/java/com/sanbangzi/xcx_web/config/CorsConfig.java
@@ -0,0 +1,32 @@
+package com.sanbangzi.xcx_web.config;
+
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpHeaders;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+@Configuration
+public class CorsConfig {
+
+ @Bean
+ public FilterRegistrationBean preHandle() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ CorsConfiguration config = new CorsConfiguration();
+ config.setAllowCredentials(true);
+ // 设置你要允许的网站域名,如果全允许则设为 *
+ config.addAllowedOrigin("*");
+ // 如果要限制 HEADER 或 METHOD 请自行更改
+ config.addAllowedHeader("*");
+ // 暴露头信息
+ config.addExposedHeader(HttpHeaders.SET_COOKIE);
+ config.addAllowedMethod("*");
+ source.registerCorsConfiguration("/**", config);
+ FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
+ // 这个顺序很重要哦,为避免麻烦请设置在最前
+ bean.setOrder(0);
+ return bean;
+ }
+}
diff --git a/xcx_web/src/main/java/com/sanbangzi/xcx_web/config/RedisConfig.java b/xcx_web/src/main/java/com/sanbangzi/xcx_web/config/RedisConfig.java
new file mode 100644
index 0000000..ba89116
--- /dev/null
+++ b/xcx_web/src/main/java/com/sanbangzi/xcx_web/config/RedisConfig.java
@@ -0,0 +1,158 @@
+package com.sanbangzi.xcx_web.config;
+
+import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer;
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.cache.Cache;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.annotation.CachingConfigurerSupport;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.cache.interceptor.CacheErrorHandler;
+import org.springframework.cache.interceptor.KeyGenerator;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.cache.RedisCacheManager;
+import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+import redis.clients.jedis.JedisPool;
+import redis.clients.jedis.JedisPoolConfig;
+
+@Configuration
+@EnableCaching
+public class RedisConfig extends CachingConfigurerSupport {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(RedisConfig.class);
+
+ @Autowired
+ private JedisConnectionFactory jedisConnectionFactory;
+
+ @Bean
+ @Override
+ public KeyGenerator keyGenerator() {
+ return (target, method, params) -> {
+ StringBuilder sb = new StringBuilder();
+ sb.append(target.getClass().getName());
+ sb.append(":");
+ sb.append(method.getName());
+ for (Object obj : params) {
+ sb.append(":" + String.valueOf(obj));
+ }
+ String rsToUse = String.valueOf(sb);
+ LOGGER.info("自动生成Redis Key -> [{}]", rsToUse);
+ return rsToUse;
+ };
+ }
+
+ @Bean
+ @Override
+ public CacheManager cacheManager() {
+ LOGGER.info("初始化 -> [{}]", "CacheManager RedisCacheManager Start");
+ RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager
+ .RedisCacheManagerBuilder
+ .fromConnectionFactory(jedisConnectionFactory);
+ return builder.build();
+ }
+
+ @Bean
+ public RedisTemplate redisTemplate(JedisConnectionFactory jedisConnectionFactory ) {
+ //设置序列化
+// Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
+// ObjectMapper om = new ObjectMapper();
+// om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+// om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
+// jackson2JsonRedisSerializer.setObjectMapper(om);
+ GenericFastJsonRedisSerializer fastJsonRedisSerializer = new GenericFastJsonRedisSerializer();
+
+ //配置redisTemplate
+ RedisTemplate redisTemplate = new RedisTemplate();
+ redisTemplate.setConnectionFactory(jedisConnectionFactory);
+
+ redisTemplate.setDefaultSerializer(fastJsonRedisSerializer);
+ redisTemplate.setKeySerializer(fastJsonRedisSerializer);
+ redisTemplate.setValueSerializer(fastJsonRedisSerializer);
+ redisTemplate.setHashKeySerializer(fastJsonRedisSerializer);
+ redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
+// RedisSerializer stringSerializer = new StringRedisSerializer();
+// redisTemplate.setKeySerializer(stringSerializer);//key序列化
+// redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);//value序列化
+// redisTemplate.setHashKeySerializer(stringSerializer);//Hash key序列化
+// redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);//Hash value序列化
+ redisTemplate.afterPropertiesSet();
+ return redisTemplate;
+ }
+
+ @Override
+ @Bean
+ public CacheErrorHandler errorHandler() {
+ LOGGER.info("初始化 -> [{}]", "Redis CacheErrorHandler");
+ CacheErrorHandler cacheErrorHandler = new CacheErrorHandler() {
+ @Override
+ public void handleCacheGetError(RuntimeException e, Cache cache, Object key) {
+ LOGGER.error("Redis occur handleCacheGetError:key -> [{}]", key, e);
+ }
+
+ @Override
+ public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) {
+ LOGGER.error("Redis occur handleCachePutError:key -> [{}];value -> [{}]", key, value, e);
+ }
+
+ @Override
+ public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) {
+ LOGGER.error("Redis occur handleCacheEvictError:key -> [{}]", key, e);
+ }
+
+ @Override
+ public void handleCacheClearError(RuntimeException e, Cache cache) {
+ LOGGER.error("Redis occur handleCacheClearError:", e);
+ }
+ };
+ return cacheErrorHandler;
+ }
+
+ @ConfigurationProperties
+ class DataJedisProperties {
+ @Value("${spring.redis.host}")
+ private String host;
+ @Value("${spring.redis.password}")
+ private String password;
+ @Value("${spring.redis.port}")
+ private int port;
+ @Value("${spring.redis.timeout}")
+ private int timeout;
+ @Value("${spring.redis.jedis.pool.max-idle}")
+ private int maxIdle;
+ @Value("${spring.redis.jedis.pool.max-wait}")
+ private long maxWaitMillis;
+
+ @Bean
+ JedisConnectionFactory jedisConnectionFactory() {
+ LOGGER.info("Create JedisConnectionFactory successful");
+ JedisConnectionFactory factory = new JedisConnectionFactory();
+ factory.setHostName(host);
+ factory.setPort(port);
+ factory.setTimeout(timeout);
+ factory.setPassword(password);
+ factory.setUsePool(true);
+ return factory;
+ }
+ @Bean
+ public JedisPool redisPoolFactory() {
+ LOGGER.info("JedisPool init successful,host -> [{}];port -> [{}]", host, port);
+ JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
+ jedisPoolConfig.setMaxIdle(maxIdle);
+ jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
+
+ JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout, password);
+ return jedisPool;
+ }
+ }
+}
diff --git a/xcx_web/src/main/java/com/sanbangzi/xcx_web/config/WebMvcConfig.java b/xcx_web/src/main/java/com/sanbangzi/xcx_web/config/WebMvcConfig.java
new file mode 100644
index 0000000..c39d858
--- /dev/null
+++ b/xcx_web/src/main/java/com/sanbangzi/xcx_web/config/WebMvcConfig.java
@@ -0,0 +1,41 @@
+package com.sanbangzi.xcx_web.config;
+
+import com.sanbangzi.xcx_web.interceptor.LoginInterceptor;
+import com.sanbangzi.xcx_web.interceptor.RequestParamsNotEmptyMethodArgumentInterceptor;
+import com.sanbangzi.xcx_web.interceptor.SignatureInterceptor;
+import com.sanbangzi.xcx_web.resolver.CurrentUserResolver;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.method.support.HandlerMethodArgumentResolver;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import java.util.List;
+
+@Configuration
+public class WebMvcConfig implements WebMvcConfigurer {
+
+ @Autowired
+ private LoginInterceptor loginInterceptor;
+
+ @Autowired
+ private RequestParamsNotEmptyMethodArgumentInterceptor requestParamsNotEmptyMethodArgumentInterceptor;
+
+ @Autowired
+ private SignatureInterceptor signatureInterceptor;
+
+ @Autowired
+ private CurrentUserResolver currentUserResolver;
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(signatureInterceptor).order(2).addPathPatterns("/**");
+ registry.addInterceptor(loginInterceptor).order(3).addPathPatterns("/**");
+ registry.addInterceptor(requestParamsNotEmptyMethodArgumentInterceptor).order(4).addPathPatterns("/**");
+ }
+
+ @Override
+ public void addArgumentResolvers(List resolvers) {
+ resolvers.add(currentUserResolver);
+ }
+}
diff --git a/xcx_web/src/main/java/com/sanbangzi/xcx_web/consts/XcxCacheKeyConst.java b/xcx_web/src/main/java/com/sanbangzi/xcx_web/consts/XcxCacheKeyConst.java
new file mode 100644
index 0000000..0354412
--- /dev/null
+++ b/xcx_web/src/main/java/com/sanbangzi/xcx_web/consts/XcxCacheKeyConst.java
@@ -0,0 +1,5 @@
+package com.sanbangzi.xcx_web.consts;
+
+public class XcxCacheKeyConst {
+
+}
diff --git a/xcx_web/src/main/java/com/sanbangzi/xcx_web/consts/XcxConst.java b/xcx_web/src/main/java/com/sanbangzi/xcx_web/consts/XcxConst.java
new file mode 100644
index 0000000..ad17ebf
--- /dev/null
+++ b/xcx_web/src/main/java/com/sanbangzi/xcx_web/consts/XcxConst.java
@@ -0,0 +1,7 @@
+package com.sanbangzi.xcx_web.consts;
+
+public class XcxConst {
+
+ /** 登录token */
+ public static final String ACCESS_TOKEN_KEY = "access-token";
+}
diff --git a/xcx_web/src/main/java/com/sanbangzi/xcx_web/exception/XcxErrorCode.java b/xcx_web/src/main/java/com/sanbangzi/xcx_web/exception/XcxErrorCode.java
new file mode 100644
index 0000000..189c55b
--- /dev/null
+++ b/xcx_web/src/main/java/com/sanbangzi/xcx_web/exception/XcxErrorCode.java
@@ -0,0 +1,26 @@
+package com.sanbangzi.xcx_web.exception;
+
+import lombok.Getter;
+import lombok.Setter;
+
+public enum XcxErrorCode {
+
+ SIGN_ERROR(10001, "签名错误"),
+ ACCESS_TOKEN_ERROR(10002, "登录token错误"),
+ PARAM_NULL_ERROR(10003, ""),
+ DATA_CHECK_ERROR(10004, "暂不支持该种传输校验");
+
+ @Getter
+ private Integer code;
+
+ @Setter
+ @Getter
+ private String msg;
+
+ private XcxErrorCode(Integer code, String msg) {
+ this.code = code;
+ this.msg = msg;
+ }
+
+
+}
diff --git a/xcx_web/src/main/java/com/sanbangzi/xcx_web/exception/XcxException.java b/xcx_web/src/main/java/com/sanbangzi/xcx_web/exception/XcxException.java
new file mode 100644
index 0000000..2394336
--- /dev/null
+++ b/xcx_web/src/main/java/com/sanbangzi/xcx_web/exception/XcxException.java
@@ -0,0 +1,20 @@
+package com.sanbangzi.xcx_web.exception;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@AllArgsConstructor
+public class XcxException extends RuntimeException {
+
+ @Getter
+ private XcxErrorCode xcxErrorCode;
+
+ public static XcxException throwErrorCode(XcxErrorCode xcxErrorCode) {
+ return new XcxException(xcxErrorCode);
+ }
+
+ public static XcxException throwParamNull(String paramName) {
+ XcxErrorCode.PARAM_NULL_ERROR.setMsg("参数[" + paramName + "] 为空");
+ return new XcxException(XcxErrorCode.PARAM_NULL_ERROR);
+ }
+}
diff --git a/xcx_web/src/main/java/com/sanbangzi/xcx_web/filter/StreamFilter.java b/xcx_web/src/main/java/com/sanbangzi/xcx_web/filter/StreamFilter.java
new file mode 100644
index 0000000..145253c
--- /dev/null
+++ b/xcx_web/src/main/java/com/sanbangzi/xcx_web/filter/StreamFilter.java
@@ -0,0 +1,31 @@
+package com.sanbangzi.xcx_web.filter;
+
+import com.sanbangzi.xcx_web.wapper.RequestWrapper;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.Order;
+
+import javax.servlet.*;
+import javax.servlet.annotation.WebFilter;
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+
+@Order(1)
+@Configuration
+@WebFilter(filterName = "streamFilter", urlPatterns = "/*")
+public class StreamFilter implements Filter {
+
+ @Override
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
+ // 防止流读取一次后就没有了, 所以需要将流继续写出去
+ HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
+ filterChain.doFilter(new RequestWrapper(httpServletRequest), servletResponse);
+ }
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {}
+
+
+
+ @Override
+ public void destroy() {}
+}
diff --git a/xcx_web/src/main/java/com/sanbangzi/xcx_web/handler/GlobalExceptionHandler.java b/xcx_web/src/main/java/com/sanbangzi/xcx_web/handler/GlobalExceptionHandler.java
new file mode 100644
index 0000000..cd1f2f9
--- /dev/null
+++ b/xcx_web/src/main/java/com/sanbangzi/xcx_web/handler/GlobalExceptionHandler.java
@@ -0,0 +1,65 @@
+package com.sanbangzi.xcx_web.handler;
+
+import com.sanbangzi.common.utils.WebResponse;
+import com.sanbangzi.company_service_api.exception.CompanyErrorCode;
+import com.sanbangzi.company_service_api.exception.CompanyException;
+import com.sanbangzi.product_service_api.exception.ProductErrorCode;
+import com.sanbangzi.product_service_api.exception.ProductException;
+import com.sanbangzi.user_service_api.exception.UserErrorCode;
+import com.sanbangzi.user_service_api.exception.UserException;
+import com.sanbangzi.xcx_web.exception.XcxErrorCode;
+import com.sanbangzi.xcx_web.exception.XcxException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+@RestControllerAdvice
+public class GlobalExceptionHandler {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionHandler.class);
+
+ @ExceptionHandler(XcxException.class)
+ public WebResponse xcxExceptionHandle(XcxException e) {
+ XcxErrorCode xcxErrorCode = e.getXcxErrorCode();
+ Integer code = xcxErrorCode.getCode();
+ String msg = xcxErrorCode.getMsg();
+ LOGGER.error("模板模块, 错误信息 => code:{}, msg:{}",code, msg);
+ return new WebResponse(code, msg, null);
+ }
+
+ @ExceptionHandler(UserException.class)
+ public WebResponse userExceptionHandle(UserException e) {
+ UserErrorCode userErrorCode = e.getUserErrorCode();
+ Integer code = userErrorCode.getCode();
+ String msg = userErrorCode.getMsg();
+ LOGGER.error("模板模块, 错误信息 => code:{}, msg:{}",code, msg);
+ return new WebResponse(code, msg, null);
+ }
+
+ @ExceptionHandler(ProductException.class)
+ public WebResponse productExceptionHandle(ProductException e) {
+ ProductErrorCode productErrorCode = e.getProductErrorCode();
+ Integer code = productErrorCode.getCode();
+ String msg = productErrorCode.getMsg();
+ LOGGER.error("模板模块, 错误信息 => code:{}, msg:{}",code, msg);
+ return new WebResponse(code, msg, null);
+ }
+
+ @ExceptionHandler(CompanyException.class)
+ public WebResponse companyExceptionHandle(CompanyException e) {
+ CompanyErrorCode companyErrorCode = e.getCompanyErrorCode();
+ Integer code = companyErrorCode.getCode();
+ String msg = companyErrorCode.getMsg();
+ LOGGER.error("模板模块, 错误信息 => code:{}, msg:{}",code, msg);
+ return new WebResponse(code, msg, null);
+ }
+
+ @ExceptionHandler(Exception.class)
+ @ResponseBody
+ public WebResponse ExceptionHandler(Exception e) throws Exception {
+ LOGGER.error("系统内部错误, 错误信息:", e);
+ return new WebResponse(500, "程序员小哥哥出差", null);
+ }
+}
diff --git a/xcx_web/src/main/java/com/sanbangzi/xcx_web/interceptor/LoginInterceptor.java b/xcx_web/src/main/java/com/sanbangzi/xcx_web/interceptor/LoginInterceptor.java
new file mode 100644
index 0000000..c7e268a
--- /dev/null
+++ b/xcx_web/src/main/java/com/sanbangzi/xcx_web/interceptor/LoginInterceptor.java
@@ -0,0 +1,66 @@
+package com.sanbangzi.xcx_web.interceptor;
+
+import com.sanbangzi.common.utils.StringUtil;
+import com.sanbangzi.user_service_api.consts.UserCacheKeyConst;
+import com.sanbangzi.xcx_web.annotation.IgnoreLogin;
+import com.sanbangzi.xcx_web.consts.XcxConst;
+import com.sanbangzi.xcx_web.exception.XcxErrorCode;
+import com.sanbangzi.xcx_web.exception.XcxException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Component;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Arrays;
+
+@Component
+public class LoginInterceptor extends HandlerInterceptorAdapter {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(LoginInterceptor.class);
+
+ @Value("${spring.profiles.active}")
+ private String profiles;
+
+ @Autowired
+ private StringRedisTemplate stringRedisTemplate;
+
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+ if (isRelease(handler)) {
+ return true;
+ }
+ String remoteAccessToken = request.getHeader(XcxConst.ACCESS_TOKEN_KEY);
+ if (StringUtil.isBlank(remoteAccessToken)) {
+ throw XcxException.throwErrorCode(XcxErrorCode.ACCESS_TOKEN_ERROR);
+ }
+ String cacheKey = UserCacheKeyConst.XCX_ACCESS_TOKEN + remoteAccessToken;
+ String localAccessToken = stringRedisTemplate.opsForValue().get(cacheKey);
+ if (!StringUtil.equals(remoteAccessToken, localAccessToken)) {
+ throw XcxException.throwErrorCode(XcxErrorCode.ACCESS_TOKEN_ERROR);
+ }
+ return true;
+ }
+
+ /**
+ * 是否放行
+ * @param handler
+ * @return
+ */
+ private boolean isRelease(Object handler) {
+ if (Arrays.asList("dev", "test").contains(profiles)) {
+ return true;
+ }
+ if (!(handler instanceof HandlerMethod)) {
+ return true;
+ }
+ IgnoreLogin annotation = AnnotationUtils.findAnnotation(((HandlerMethod) handler).getMethod(), IgnoreLogin.class);
+ return null != annotation;
+ }
+}
diff --git a/xcx_web/src/main/java/com/sanbangzi/xcx_web/interceptor/RequestParamsNotEmptyMethodArgumentInterceptor.java b/xcx_web/src/main/java/com/sanbangzi/xcx_web/interceptor/RequestParamsNotEmptyMethodArgumentInterceptor.java
new file mode 100644
index 0000000..bc8a633
--- /dev/null
+++ b/xcx_web/src/main/java/com/sanbangzi/xcx_web/interceptor/RequestParamsNotEmptyMethodArgumentInterceptor.java
@@ -0,0 +1,88 @@
+package com.sanbangzi.xcx_web.interceptor;
+
+import com.alibaba.fastjson.JSON;
+import com.google.common.base.Splitter;
+import com.sanbangzi.common.utils.StringUtil;
+import com.sanbangzi.xcx_web.annotation.RequestParamsNotEmpty;
+import com.sanbangzi.xcx_web.exception.XcxErrorCode;
+import com.sanbangzi.xcx_web.exception.XcxException;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.ArrayUtils;
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.stereotype.Component;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.lang.reflect.Method;
+import java.util.Map;
+
+@Component
+public class RequestParamsNotEmptyMethodArgumentInterceptor extends HandlerInterceptorAdapter {
+
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+
+ if (!(handler instanceof HandlerMethod)) {
+ return true;
+ }
+
+ HandlerMethod handlerMethod = (HandlerMethod) handler;
+ Method method = handlerMethod.getMethod();
+ RequestParamsNotEmpty annotation = AnnotationUtils.findAnnotation(method, RequestParamsNotEmpty.class);
+ if (null == annotation) {
+ return true;
+ }
+ String[] params = annotation.names();
+ if (ArrayUtils.isEmpty(params)) {
+ return true;
+ }
+
+ String requestMethod = request.getMethod();
+ String contentType = request.getContentType();
+
+ if ("GET".equalsIgnoreCase(requestMethod)) {
+ checkGet(request, params);
+ } else if ("POST".equalsIgnoreCase(requestMethod) && StringUtil.isNotBlank(contentType) && "application/json".equalsIgnoreCase(contentType)) {
+ checkPost(request, params);
+ } else {
+ throw XcxException.throwErrorCode(XcxErrorCode.DATA_CHECK_ERROR);
+ }
+ return true;
+ }
+
+ /**
+ * 校验get请求
+ * @param request
+ * @param params
+ * @throws Exception
+ */
+ private void checkGet(HttpServletRequest request, String[] params) throws Exception {
+ String value = null;
+ for (String paramName : params) {
+ value = request.getParameter(paramName);
+ if (StringUtil.isAnyEmpty(paramName, value)) {
+ throw XcxException.throwParamNull(paramName);
+ }
+ }
+ }
+
+ /**
+ * 校验post请求json体
+ * @param request
+ * @param checkParams
+ * @throws Exception
+ */
+ private void checkPost(HttpServletRequest request, String[] checkParams) throws Exception {
+ String requestParam = IOUtils.toString(request.getInputStream(), "UTF-8");
+ Map requestParamMap = JSON.parseObject(requestParam, Map.class);
+ String value = null;
+ for (String paramName : checkParams) {
+ value = String.valueOf(requestParamMap.get(paramName));
+ if (StringUtil.isAnyEmpty(paramName, value)) {
+ throw XcxException.throwParamNull(paramName);
+ }
+ }
+ }
+}
diff --git a/xcx_web/src/main/java/com/sanbangzi/xcx_web/interceptor/SignatureInterceptor.java b/xcx_web/src/main/java/com/sanbangzi/xcx_web/interceptor/SignatureInterceptor.java
new file mode 100644
index 0000000..723a880
--- /dev/null
+++ b/xcx_web/src/main/java/com/sanbangzi/xcx_web/interceptor/SignatureInterceptor.java
@@ -0,0 +1,85 @@
+package com.sanbangzi.xcx_web.interceptor;
+
+import com.alibaba.fastjson.JSON;
+import com.google.common.base.Joiner;
+import com.google.common.collect.Maps;
+import com.sanbangzi.common.utils.DigestUtil;
+import com.sanbangzi.common.utils.StringUtil;
+import com.sanbangzi.xcx_web.annotation.IgnoreSignature;
+import com.sanbangzi.xcx_web.exception.XcxErrorCode;
+import com.sanbangzi.xcx_web.exception.XcxException;
+import org.apache.commons.io.IOUtils;
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.stereotype.Component;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.lang.reflect.Method;
+import java.util.Map;
+import java.util.TreeMap;
+
+@Component
+public class SignatureInterceptor extends HandlerInterceptorAdapter {
+
+ private static final String SIGN_KEY = "signKey";
+
+ private static final String SIGN_SALT = "";
+
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+
+ if (!(handler instanceof HandlerMethod)) {
+ return true;
+ }
+
+ HandlerMethod handlerMethod = (HandlerMethod) handler;
+ Method method = handlerMethod.getMethod();
+ IgnoreSignature ignoreSignature = AnnotationUtils.findAnnotation(method, IgnoreSignature.class);
+ if (null != ignoreSignature) {
+ return true;
+ }
+
+ String requestMethod = request.getMethod();
+ String contentType = request.getContentType();
+
+ // 获取参数
+ String remoteSign = "";
+ Map signMap = Maps.newTreeMap();
+ if ("GET".equalsIgnoreCase(requestMethod)) {
+ remoteSign = request.getParameter(SIGN_KEY);
+ Map parameterMap = request.getParameterMap();
+ for (Map.Entry entry : parameterMap.entrySet()) {
+ String key = entry.getKey();
+ if (!SIGN_KEY.equals(key)) {
+ signMap.put(key, entry.getValue()[0]);
+ }
+ }
+ } else if ("POST".equalsIgnoreCase(requestMethod) && StringUtil.isNotBlank(contentType) && "application/json".equalsIgnoreCase(contentType)) {
+ String paramsStr = IOUtils.toString(request.getInputStream(), "UTF-8");
+ signMap = JSON.parseObject(paramsStr, TreeMap.class);
+ remoteSign = signMap.get(SIGN_KEY);
+ signMap.remove(SIGN_KEY);
+ } else {
+ throw XcxException.throwErrorCode(XcxErrorCode.DATA_CHECK_ERROR);
+ }
+ return sign(remoteSign, signMap);
+ }
+
+ private static boolean sign(String remoteSign, Map signMap) {
+ if (StringUtil.isBlank(remoteSign)) {
+ throw XcxException.throwErrorCode(XcxErrorCode.SIGN_ERROR);
+ }
+ String sign = Joiner.on("&").withKeyValueSeparator("=").join(signMap);
+ sign = new StringBuilder(SIGN_SALT).append(sign).append(SIGN_SALT).toString();
+ String localSign = DigestUtil.md5Hex(sign);
+ boolean equals = StringUtil.equals(remoteSign, localSign);
+ if (!equals) {
+ throw XcxException.throwErrorCode(XcxErrorCode.SIGN_ERROR);
+ }
+ return true;
+ }
+
+
+}
diff --git a/xcx_web/src/main/java/com/sanbangzi/xcx_web/resolver/CurrentUserResolver.java b/xcx_web/src/main/java/com/sanbangzi/xcx_web/resolver/CurrentUserResolver.java
new file mode 100644
index 0000000..020eb89
--- /dev/null
+++ b/xcx_web/src/main/java/com/sanbangzi/xcx_web/resolver/CurrentUserResolver.java
@@ -0,0 +1,49 @@
+package com.sanbangzi.xcx_web.resolver;
+
+import com.sanbangzi.common.utils.StringUtil;
+import com.sanbangzi.domain.dto.res.UserResDTO;
+import com.sanbangzi.user_service_api.api.UserService;
+import com.sanbangzi.user_service_api.consts.UserCacheKeyConst;
+import com.sanbangzi.xcx_web.annotation.CurrentUser;
+import com.sanbangzi.xcx_web.consts.XcxConst;
+import com.sanbangzi.xcx_web.exception.XcxErrorCode;
+import com.sanbangzi.xcx_web.exception.XcxException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.MethodParameter;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+import org.springframework.web.bind.support.WebDataBinderFactory;
+import org.springframework.web.context.request.NativeWebRequest;
+import org.springframework.web.method.support.HandlerMethodArgumentResolver;
+import org.springframework.web.method.support.ModelAndViewContainer;
+
+@Component
+public class CurrentUserResolver implements HandlerMethodArgumentResolver {
+
+ @Autowired
+ private UserService userService;
+
+ @Autowired
+ private RedisTemplate redisTemplate;
+
+ @Override
+ public boolean supportsParameter(MethodParameter parameter) {
+ if (parameter.getParameterType().isAssignableFrom(UserResDTO.class) &&
+ parameter.hasParameterAnnotation(CurrentUser.class)) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest webRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
+ // 取出的登录用户token
+ String token = webRequest.getHeader(XcxConst.ACCESS_TOKEN_KEY);
+ String key = UserCacheKeyConst.XCX_ACCESS_TOKEN + token;
+ String userIdStr = redisTemplate.opsForValue().get(key).toString();
+ if (StringUtil.isBlank(userIdStr)) {
+ throw XcxException.throwErrorCode(XcxErrorCode.ACCESS_TOKEN_ERROR);
+ }
+ return userService.getById(Long.parseLong(userIdStr));
+ }
+}
diff --git a/xcx_web/src/main/java/com/sanbangzi/xcx_web/wapper/RequestWrapper.java b/xcx_web/src/main/java/com/sanbangzi/xcx_web/wapper/RequestWrapper.java
new file mode 100644
index 0000000..aa5ff62
--- /dev/null
+++ b/xcx_web/src/main/java/com/sanbangzi/xcx_web/wapper/RequestWrapper.java
@@ -0,0 +1,65 @@
+package com.sanbangzi.xcx_web.wapper;
+
+import lombok.Getter;
+import org.apache.commons.io.IOUtils;
+
+import javax.servlet.ReadListener;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+public class RequestWrapper extends HttpServletRequestWrapper {
+
+ @Getter
+ private final String body;
+
+ public RequestWrapper(HttpServletRequest request) throws IOException {
+ super(request);
+ body = IOUtils.toString(request.getInputStream(), "UTF-8");
+ }
+
+ @Override
+ public ServletInputStream getInputStream() throws IOException {
+ byte[] by = body.getBytes();
+ ServletInputStream inStream = new CustomServletInputStream(by);
+ return inStream;
+ }
+
+ @Override
+ public BufferedReader getReader() throws IOException {
+ InputStreamReader inStream = new InputStreamReader(this.getInputStream());
+ return new BufferedReader(inStream);
+ }
+
+ private static class CustomServletInputStream extends ServletInputStream {
+ private ByteArrayInputStream buffer;
+
+ public CustomServletInputStream(byte[] contents) {
+ this.buffer = new ByteArrayInputStream(contents);
+ }
+
+ @Override
+ public int read() throws IOException {
+ return buffer.read();
+ }
+
+ @Override
+ public boolean isFinished() {
+ return buffer.available() == 0;
+ }
+
+ @Override
+ public boolean isReady() {
+ return true;
+ }
+
+ @Override
+ public void setReadListener(ReadListener listener) {
+ throw new RuntimeException("not implemented");
+ }
+ }
+}
diff --git a/xcx_web/src/main/resources/application-dev.yml b/xcx_web/src/main/resources/application-dev.yml
new file mode 100644
index 0000000..1dbf2ac
--- /dev/null
+++ b/xcx_web/src/main/resources/application-dev.yml
@@ -0,0 +1,17 @@
+spring:
+ profiles:
+ include: dev
+ datasource:
+ url: jdbc:mysql://127.0.0.1:3306/demo_mall?useUnicode=true&characterEncoding=utf-8&useSSL=false
+ username: root
+ password: flame
+ redis:
+ ###Redis数据库索引(默认为0)
+ database: 0
+ host: 127.0.0.1
+ port: 6379
+ password:
+
+logging:
+ level:
+ root: debug
\ No newline at end of file
diff --git a/xcx_web/src/main/resources/application-prod.yml b/xcx_web/src/main/resources/application-prod.yml
new file mode 100644
index 0000000..8632441
--- /dev/null
+++ b/xcx_web/src/main/resources/application-prod.yml
@@ -0,0 +1,18 @@
+spring:
+ profiles:
+ include: prod
+ datasource:
+ url: jdbc:mysql://127.0.0.1:3306/demo_mall?useUnicode=true&characterEncoding=utf-8&useSSL=false
+ username: root
+ password: flame
+ redis:
+ ###Redis数据库索引(默认为0)
+ database: 0
+ host: 127.0.0.1
+ port: 6379
+ password:
+
+logging:
+ level:
+ root: error
+ file: /data/log/xcx_web.log
\ No newline at end of file
diff --git a/xcx_web/src/main/resources/application-test.yml b/xcx_web/src/main/resources/application-test.yml
new file mode 100644
index 0000000..62b2794
--- /dev/null
+++ b/xcx_web/src/main/resources/application-test.yml
@@ -0,0 +1,18 @@
+spring:
+ profiles:
+ include: prod
+ datasource:
+ url: jdbc:mysql://127.0.0.1:3306/demo_mall?useUnicode=true&characterEncoding=utf-8&useSSL=false
+ username: root
+ password: flame
+ redis:
+ ###Redis数据库索引(默认为0)
+ database: 0
+ host: 127.0.0.1
+ port: 6379
+ password:
+
+logging:
+ level:
+ root: info
+ file: /data/log/xcx_web.log
\ No newline at end of file
diff --git a/xcx_web/src/main/resources/application.yml b/xcx_web/src/main/resources/application.yml
new file mode 100644
index 0000000..1f144e5
--- /dev/null
+++ b/xcx_web/src/main/resources/application.yml
@@ -0,0 +1,48 @@
+spring:
+ profiles:
+ active: dev
+ application:
+ name: demo_mall
+ datasource:
+ type: com.alibaba.druid.pool.DruidDataSource
+ driver-class-name: com.mysql.jdbc.Driver
+ redis:
+ ###连接超时时间(毫秒)
+ timeout: 10000
+ jedis:
+ pool:
+ ###连接池最大连接数(使用负值表示没有限制)
+ max-active: 8
+ ###连接池最大阻塞等待时间(使用负值表示没有限制)
+ max-wait: -1
+ ###连接池中的最大空闲连接
+ max-idle: 5
+ ###连接池中的最小空闲连接
+ min-idle: 0
+
+# session配置
+server:
+ servlet:
+ session:
+ persistent: true
+ timeout: 5000
+ cookie:
+ http-only: false
+ context-path: /xcx
+ port: 8080
+
+mybatis:
+ type-aliases-package: com.sanbangzi.domain.entity
+ mapper-locations: classpath*:mapper/*.xml
+
+mapper:
+ mappers:
+ - com.sanbangzi.common.utils.MyMapper
+ not-empty: false
+ identity: MYSQL
+
+pagehelper:
+ helperDialect: mysql
+ reasonable: true
+ supportMethodsArguments: true
+ params: count=countSql
\ No newline at end of file
diff --git a/xcx_web/src/main/resources/sql/demo_mall.sql b/xcx_web/src/main/resources/sql/demo_mall.sql
new file mode 100644
index 0000000..df0841c
--- /dev/null
+++ b/xcx_web/src/main/resources/sql/demo_mall.sql
@@ -0,0 +1,96 @@
+create table user (
+ id bigint(16) unsigned not null auto_increment comment '主键',
+ code varchar(32) not null default '' comment '用户唯一码',
+ open_id varchar(32) not null default '' comment '小程序opendId',
+ nick_name varchar(32) character set utf8mb4 not null default '' comment '昵称',
+ head_photo varchar(128) not null default '' comment '头像',
+ status tinyint(1) unsigned not null comment '状态(1:正常)',
+ create_time datetime not null comment '创建时间',
+ update_time datetime not null comment '修改时间',
+ primary key (id),
+ key idx_code (code),
+ key idx_open_id (open_id)
+) engine = InnoDB auto_increment=10001 default charset=utf8 comment '用户表';
+
+create table company (
+ id bigint(16) unsigned not null auto_increment comment '主键',
+ code varchar(32) not null default '' comment '公司唯一码',
+ name varchar(64) not null default '' comment '名称',
+ link_man varchar(32) not null default '' comment '联系人',
+ link_phone varchar(16) not null default '' comment '联系电话',
+ status tinyint(1) unsigned not null comment '状态(1:正常)',
+ create_time datetime not null comment '创建时间',
+ update_time datetime not null comment '修改时间',
+ primary key (id),
+ key idx_code(code)
+) engine = InnoDB auto_increment=10001 default charset=utf8 comment '公司表';
+
+create table company_account(
+ id bigint(16) unsigned not null auto_increment comment '主键',
+ account varchar(32) not null default '' comment '账号',
+ password varchar(32) not null default '' comment '密码',
+ head_photo varchar(128) not null default '' comment '头像',
+ nick_name varchar(64) not null default '' comment '昵称',
+ status tinyint(1) unsigned not null comment '状态(1:正常)',
+ create_time datetime not null comment '创建时间',
+ company_id bigint(16) unsigned not null comment '公司id(关联company.id)',
+ primary key (id),
+ key idx_account (account),
+ key idx_company_id (company_id)
+) engine = InnoDB auto_increment=10001 default charset=utf8 comment '公司账号表';
+
+create table company_banner (
+ id bigint(16) unsigned not null auto_increment comment '主键',
+ picture varchar(128) not null default '' comment '图片',
+ link varchar(128) not null default '链接',
+ type tinyint(1) unsigned not null comment '类型(1:无链接,2:产品)',
+ sort tinyint(1) unsigned not null comment '排序',
+ company_id bigint(16) unsigned not null comment '公司id(关联company.id)',
+ primary key (id),
+ key idx_company_id (company_id)
+) engine=InnoDB auto_increment=10001 default charset=utf8 comment '公司banner表';
+
+create table company_product_type (
+ id bigint(16) unsigned not null auto_increment comment '主键',
+ name varchar(32) not null default '' comment '名称',
+ sort tinyint(1) unsigned not null comment '排序',
+ company_id bigint(16) unsigned not null comment '公司id(关联company.id)',
+ primary key (id),
+ key idx_company_id (company_id)
+)engine=InnoDB auto_increment=10001 default charset=utf8 comment '公司产品分类表';
+
+create table product_type_associate (
+ product_id bigint(16) unsigned not null comment '产品id(关联product.id)',
+ company_product_type_id bigint(16) unsigned not null comment '公司产品分类id(关联company_product_type.id)',
+ key idx_product_id(product_id),
+ key idx_company_product_type_id (company_product_type_id)
+) engine=InnoDB auto_increment=10001 default charset=utf8 comment '产品分类关系表';
+
+
+create table product (
+ id bigint(16) unsigned not null auto_increment comment '主键',
+ code varchar(32) not null default '' comment '产品唯一码',
+ photo varchar(128) not null default '' comment '主图',
+ title varchar(256) not null default '' comment '标题',
+ price int(12) unsigned not null comment '产品价格(分)',
+ status tinyint(1) unsigned not null comment "状态(1:正常)",
+ create_time datetime not null comment '创建时间',
+ update_time datetime not null comment '修改时间',
+ company_id bigint(16) unsigned not null comment '公司id(关联company.id)',
+ primary key (id),
+ key idx_code (code),
+ key idx_company_id(company_id)
+) engine=InnoDB auto_increment=10001 default charset=utf8 comment '产品表';
+
+create table proudct_resource (
+ id bigint(16) unsigned not null auto_increment comment '主键',
+ resource text character set utf8mb4 not null comment '资源',
+ type tinyint(1) unsigned not null comment '资源类型(1:轮播图,2:产品详情)',
+ sort tinyint(1) unsigned not null comment '排序',
+ product_id bigint(16) unsigned not null comment '产品id(关联product.id)',
+ primary key (id),
+ key idx_product_id (product_id)
+) engine=InnoDB auto_increment=10001 default charset=utf8 comment '产品资源表';
+
+
+