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 '产品资源表'; + + +