关斯涵
cx 12 months ago
parent afa48d0491
commit 57aa7484fb

25
.gitignore vendored

@ -0,0 +1,25 @@
/target/
!.mvn/wrapper/maven-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/build/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 545 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 812 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 747 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

@ -0,0 +1,244 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.njupt.swg</groupId>
<artifactId>spring-cloud-for-snailmall</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-cloud-for-snailmall</name>
<description>聚合工程的父工程</description>
<packaging>pom</packaging>
<modules>
<module>snailmall-eureka-server</module>
<module>snailmall-config-server</module>
<module>snailmall-category-service</module>
<module>snailmall-api-gateway</module>
<module>snailmall-product-service</module>
<module>snailmall-cart-service</module>
<module>snailmall-user-service</module>
<module>snailmall-shipping-service</module>
<module>snailmall-keygen-service</module>
<module>snailmall-order-service</module>
</modules>
<properties>
<project.build.sourceencoding>UTF-8</project.build.sourceencoding>
<project.reporting.outputencoding>UTF-8</project.reporting.outputencoding>
<java.version>1.8</java.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--MYSQL-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.2.0</version>
</dependency>
<!--json序列化和反序列-->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-avro</artifactId>
<version>2.9.0</version>
</dependency>
<!--druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.18</version>
</dependency>
<!--工具包,各种数据结构-->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
<!--时间处理-->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.3</version>
</dependency>
<!-- ftpclient -->
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.1</version>
</dependency>
<!-- file upload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.0.1</version>
</dependency>
<!-- mybatis 分页-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>com.github.miemiedev</groupId>
<artifactId>mybatis-paginator</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>0.9.4</version>
</dependency>
<!-- alipay 与支付宝demo中依赖的包的版本是一致的-->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>1.10</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>1.3</version>
</dependency>
<!--redis-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.6</version>
</dependency>
<!--logback-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.1.6</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.6</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
<version>1.1.2</version>
</dependency>
<!--curator-->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.12.0</version>
</dependency>
<!--alipay-->
<dependency>
<groupId>com.alipay</groupId>
<artifactId>sdk-java</artifactId>
<version>20161213</version>
</dependency>
<dependency>
<groupId>com.alipay</groupId>
<artifactId>trade-sdk</artifactId>
<version>20161215</version>
</dependency>
<!-- 自动生成API文档 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.5.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,25 @@
/target/
!.mvn/wrapper/maven-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/build/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.njupt.swg</groupId>
<artifactId>spring-cloud-for-snailmall</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>snailmall-api-gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>snailmall-api-gateway</name>
<description>网关服务</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--util-->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,27 @@
package com.njupt.swg;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
@SpringBootApplication
@EnableDiscoveryClient
@EnableZuulProxy
@PropertySource(value="classpath:parameter.properties")
public class SnailmallApiGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(SnailmallApiGatewayApplication.class, args);
}
@Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
return new PropertySourcesPlaceholderConfigurer();
}
}

@ -0,0 +1,104 @@
package com.njupt.swg.cache;
import com.njupt.swg.exception.SnailmallException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
/**
* @Author swg.
* @Date 2019/1/1 15:03
* @CONTACT 317758022@qq.com
* @DESC
*/
@Component
@Slf4j
public class CommonCacheUtil {
@Autowired
private JedisPoolWrapper jedisPoolWrapper;
/**
* key
*/
public void cache(String key, String value) {
try {
JedisPool pool = jedisPoolWrapper.getJedisPool();
if (pool != null) {
try (Jedis Jedis = pool.getResource()) {
Jedis.select(0);
Jedis.set(key, value);
}
}
} catch (Exception e) {
log.error("redis存值失败", e);
throw new SnailmallException("redis报错");
}
}
/**
* key
*/
public String getCacheValue(String key) {
String value = null;
try {
JedisPool pool = jedisPoolWrapper.getJedisPool();
if (pool != null) {
try (Jedis Jedis = pool.getResource()) {
Jedis.select(0);
value = Jedis.get(key);
}
}
} catch (Exception e) {
log.error("redis获取指失败", e);
throw new SnailmallException("redis报错");
}
return value;
}
/**
* key
*/
public long cacheNxExpire(String key, String value, int expire) {
long result = 0;
try {
JedisPool pool = jedisPoolWrapper.getJedisPool();
if (pool != null) {
try (Jedis jedis = pool.getResource()) {
jedis.select(0);
result = jedis.setnx(key, value);
jedis.expire(key, expire);
}
}
} catch (Exception e) {
log.error("redis塞值和设置缓存时间失败", e);
throw new SnailmallException("redis报错");
}
return result;
}
/**
* key
*/
public void delKey(String key) {
JedisPool pool = jedisPoolWrapper.getJedisPool();
if (pool != null) {
try (Jedis jedis = pool.getResource()) {
jedis.select(0);
try {
jedis.del(key);
} catch (Exception e) {
log.error("从redis中删除失败", e);
throw new SnailmallException("redis报错");
}
}
}
}
}

@ -0,0 +1,43 @@
package com.njupt.swg.cache;
import com.njupt.swg.common.Parameters;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import javax.annotation.PostConstruct;
/**
* @Author swg.
* @Date 2019/1/1 15:00
* @CONTACT 317758022@qq.com
* @DESC redisredishash
*/
@Component
@Slf4j
public class JedisPoolWrapper {
@Autowired
private Parameters parameters;
private JedisPool jedisPool = null;
@PostConstruct
public void init(){
try {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(parameters.getRedisMaxTotal());
config.setMaxIdle(parameters.getRedisMaxIdle());
config.setMaxWaitMillis(parameters.getRedisMaxWaitMillis());
jedisPool = new JedisPool(config,parameters.getRedisHost(),parameters.getRedisPort(),2000,"xxx");
log.info("【初始化redis连接池成功】");
}catch (Exception e){
log.error("【初始化redis连接池失败】",e);
}
}
public JedisPool getJedisPool() {
return jedisPool;
}
}

@ -0,0 +1,33 @@
package com.njupt.swg.common;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @Author swg.
* @Date 2019/1/1 14:27
* @CONTACT 317758022@qq.com
* @DESC
*/
@Component
@Data
public class Parameters {
/*****redis config start*******/
@Value("${redis.host}")
private String redisHost;
@Value("${redis.port}")
private int redisPort;
@Value("${redis.max-idle}")
private int redisMaxTotal;
@Value("${redis.max-total}")
private int redisMaxIdle;
@Value("${redis.max-wait-millis}")
private int redisMaxWaitMillis;
/*****redis config end*******/
@Value("#{'${security.noneSecurityAdminPaths}'.split(',')}")
private List<String> noneSecurityAdminPaths;
}

@ -0,0 +1,32 @@
package com.njupt.swg.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import java.util.Arrays;
/**
*
* C - Cross O - Origin R - Resource S - Sharing
*/
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.setAllowedOrigins(Arrays.asList("*")); //http:www.a.com
config.setAllowedHeaders(Arrays.asList("*"));
config.setAllowedMethods(Arrays.asList("*"));
config.setMaxAge(300l);
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}

@ -0,0 +1,46 @@
package com.njupt.swg.constants;
/**
* @Author swg.
* @Date 2019/1/1 13:19
* @CONTACT 317758022@qq.com
* @DESC
*/
public class Constants {
/**自定义状态码 start**/
public static final int RESP_STATUS_OK = 200;
public static final int RESP_STATUS_NOAUTH = 401;
public static final int RESP_STATUS_INTERNAL_ERROR = 500;
public static final int RESP_STATUS_BADREQUEST = 400;
/**自定义状态码 end**/
/***redis user相关的key以这个打头**/
public static final String TOKEN_PREFIX = "user_";
/**
* redis
*/
public interface RedisCacheExtime{
int REDIS_SESSION_EXTIME = 60* 30;//30分钟
}
/** 用户注册判断重复的参数类型 start **/
public static final String EMAIL = "email";
public static final String USERNAME = "username";
/** 用户注册判断重复的参数类型 end **/
/** 用户角色 **/
public interface Role{
int ROLE_CUSTOME = 0;//普通用户
int ROLE_ADMIN = 1;//管理员用户
}
/**用户注册分布式锁路径***/
public static final String USER_REGISTER_DISTRIBUTE_LOCK_PATH = "/user_reg";
}

@ -0,0 +1,27 @@
package com.njupt.swg.controller;
import com.njupt.swg.resp.ResponseEnum;
import com.njupt.swg.resp.ServerResponse;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author swg.
* @Date 2019/1/2 21:21
* @CONTACT 317758022@qq.com
* @DESC
*/
@RestController
public class ErrorHandleController implements ErrorController {
@Override
public String getErrorPath() {
return "/error";
}
@RequestMapping("/error")
public ServerResponse error() {
return ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(),"用户未登陆或者权限不足");
}
}

@ -0,0 +1,43 @@
package com.njupt.swg.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.io.Serializable;
import java.util.Date;
/**
* @Author swg.
* @Date 2018/12/31 21:01
* @CONTACT 317758022@qq.com
* @DESC
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class User implements Serializable {
private Integer id;
private String username;
private String password;
private String email;
private String phone;
private String question;
private String answer;
//角色0-管理员,1-普通用户
private Integer role;
private Date createTime;
private Date updateTime;
}

@ -0,0 +1,25 @@
package com.njupt.swg.exception;
import com.njupt.swg.resp.ResponseEnum;
import lombok.Getter;
/**
* @Author swg.
* @Date 2019/1/1 13:18
* @CONTACT 317758022@qq.com
* @DESC
*/
@Getter
public class SnailmallException extends RuntimeException{
private int exceptionStatus = ResponseEnum.ERROR.getCode();
public SnailmallException(String msg){
super(msg);
}
public SnailmallException(int code,String msg){
super(msg);
exceptionStatus = code;
}
}

@ -0,0 +1,136 @@
package com.njupt.swg.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.njupt.swg.cache.CommonCacheUtil;
import com.njupt.swg.common.Parameters;
import com.njupt.swg.constants.Constants;
import com.njupt.swg.entity.User;
import com.njupt.swg.exception.SnailmallException;
import com.njupt.swg.resp.ResponseEnum;
import com.njupt.swg.resp.ServerResponse;
import com.njupt.swg.utils.CookieUtil;
import com.njupt.swg.utils.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_DECORATION_FILTER_ORDER;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
/**
* @Author swg.
* @Date 2019/1/3 10:21
* @CONTACT 317758022@qq.com
* @DESC controller
* userID,controller
*/
@Slf4j
@Component
public class AdminUserFilter extends ZuulFilter {
@Autowired
private CommonCacheUtil commonCacheUtil;
@Autowired
private Parameters parameters;
@Override
public String filterType() {
return PRE_TYPE;
}
@Override
public int filterOrder() {
return PRE_DECORATION_FILTER_ORDER-1;
}
@Override
public boolean shouldFilter() {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
//获取当前请求的url
String url = request.getRequestURI();
//前端的路径不在这里校验,直接放过
if (!url.contains("manage")){
log.info("【{}不需要进行权限校验】",url);
return false;
}
if(url.contains("upload")){
log.info("【{}不需要进行权限校验】",url);
return false;
}
//从配置文件获取所有门户需要校验的路径
// String[] passUrls = parameters.getNoneSecurityAdminPaths().toArray(new String[parameters.getNoneSecurityAdminPaths().size()]);
// for(String str:passUrls){
// //指定的路径比较特殊,也不在这里校验
// if(url.contains("manage") && url.contains(str)){
// log.info("【{}不需要进行权限校验】",url);
// return false;
// }
// }
log.info("【{}----需要进行权限校验,必须是管理员身份才可以进入】",url);
return true;
}
@Override
public ServerResponse run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
//校验是否为管理员身份
String loginToken = CookieUtil.readLoginToken(request);
log.info("【获取cookie----{}】",loginToken);
if(StringUtils.isEmpty(loginToken)){
// // 过滤该请求,不对其进行路由
// requestContext.setSendZuulResponse(false);
// //返回错误代码
// requestContext.setResponseStatusCode(Constants.RESP_STATUS_NOAUTH);
// return ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(),"用户未登录,无法获取当前用户信息");
this.returnMsg(requestContext);
return ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(),"用户未登录,无法获取当前用户信息");
//throw new SnailmallException("用户未登录,无法获取当前用户信息");
}
//2.从redis中获取用户信息
String userStr = commonCacheUtil.getCacheValue(loginToken);
log.info("【从redis中获取用户信息:{}】",userStr);
if(userStr == null){
// // 过滤该请求,不对其进行路由
// requestContext.setSendZuulResponse(false);
// //返回错误代码
// requestContext.setResponseStatusCode(Constants.RESP_STATUS_NOAUTH);
// return ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(),"用户未登录,无法获取当前用户信息"); //SnailmallException(ResponseEnum.NEED_LOGIN.getCode(),"用户未登录,无法获取当前用户信息");
this.returnMsg(requestContext);
return ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(),"用户未登录,无法获取当前用户信息");
}
String url = request.getRequestURI();
log.info("【获取当前url:{}】",url);
if(url.contains("manage")){
log.info("【来到了管理后台,需要校验权限】");
User currentUser = JsonUtil.Str2Obj(userStr,User.class);
log.info("【当前登陆的用户为:{}】",currentUser);
if(!currentUser.getRole().equals(Constants.Role.ROLE_ADMIN)){
//不是管理员报错
log.error("【当前登陆用户不是管理员身份】");
// 过滤该请求,不对其进行路由
// requestContext.setSendZuulResponse(false);
// //返回错误代码
// requestContext.setResponseStatusCode(Constants.RESP_STATUS_NOAUTH);
// return ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(),"用户未登录,无法获取当前用户信息");
this.returnMsg(requestContext);
return ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(),"用户未登录,无法获取当前用户信息");
//throw new SnailmallException("用户权限不够");
}
}
return null;
}
//返回没权限消息
private void returnMsg(RequestContext ctx){
ctx.getResponse().setContentType("application/json; charset=utf-8");
ctx.setSendZuulResponse(false); //令zuul过滤该请求不对其进行路由
ctx.setResponseStatusCode(Constants.RESP_STATUS_OK);
ctx.setResponseBody(JsonUtil.obj2String(ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(),"用户未登录,无法获取当前用户信息")));
}
}

@ -0,0 +1,52 @@
package com.njupt.swg.filter;
import com.google.common.util.concurrent.RateLimiter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.SERVLET_DETECTION_FILTER_ORDER;
/**
* @Author swg.
* @Date 2019/1/3 11:21
* @CONTACT 317758022@qq.com
* @DESC
*/
@Component
public class RateLimitFilter extends ZuulFilter {
//放100个令牌
private static final RateLimiter RATE_LIMITER = RateLimiter.create(100);
@Override
public String filterType() {
return PRE_TYPE;
}
@Override
public int filterOrder() {
return SERVLET_DETECTION_FILTER_ORDER - 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();
if(!RATE_LIMITER.tryAcquire()){
//没有取到一个令牌的话,可以这样返回信息给前端
context.set("状态码",401);
context.set("error.message","用户没有获取到令牌");
}
return null;
}
}

@ -0,0 +1,25 @@
package com.njupt.swg.resp;
import lombok.Getter;
/**
* @Author swg.
* @Date 2018/12/31 20:15
* @CONTACT 317758022@qq.com
* @DESC
*/
@Getter
public enum ResponseEnum {
SUCCESS(0,"SUCCESS"),
ERROR(1,"ERROR"),
ILLEGAL_ARGUMENTS(2,"ILLEGAL_ARGUMENTS"),
NEED_LOGIN(10,"NEED_LOGIN");
private int code;
private String desc;
ResponseEnum(int code,String desc){
this.code = code;
this.desc = desc;
}
}

@ -0,0 +1,75 @@
package com.njupt.swg.resp;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Getter;
import java.io.Serializable;
/**
* @Author swg.
* @Date 2018/12/31 20:11
* @CONTACT 317758022@qq.com
* @DESC
*/
@Getter
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
public class ServerResponse<T> implements Serializable {
private int status;
private String msg;
private T data;
private ServerResponse(int status){
this.status = status;
}
private ServerResponse(int status,String msg){
this.status = status;
this.msg = msg;
}
private ServerResponse(int status,T data){
this.status = status;
this.data = data;
}
private ServerResponse(int status,String msg,T data){
this.status = status;
this.msg = msg;
this.data = data;
}
@JsonIgnore
public boolean isSuccess(){
return this.status == ResponseEnum.SUCCESS.getCode();
}
/**
*
*/
public static <T>ServerResponse<T> createBySuccess(){
return new ServerResponse<>(ResponseEnum.SUCCESS.getCode(),ResponseEnum.SUCCESS.getDesc());
}
public static <T>ServerResponse<T> createBySuccessMessage(String message){
return new ServerResponse<>(ResponseEnum.SUCCESS.getCode(),message);
}
public static <T>ServerResponse<T> createBySuccess(T data){
return new ServerResponse<>(ResponseEnum.SUCCESS.getCode(),data);
}
public static <T>ServerResponse<T> createBySuccess(String message,T data){
return new ServerResponse<>(ResponseEnum.SUCCESS.getCode(),message,data);
}
/**
*
*/
public static <T>ServerResponse<T> createByError(){
return new ServerResponse<>(ResponseEnum.ERROR.getCode(),ResponseEnum.ERROR.getDesc());
}
public static <T>ServerResponse<T> createByErrorMessage(String msg){
return new ServerResponse<>(ResponseEnum.ERROR.getCode(),msg);
}
public static <T>ServerResponse<T> createByErrorCodeMessage(int code,String msg){
return new ServerResponse<>(code,msg);
}
}

@ -0,0 +1,74 @@
package com.njupt.swg.utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* cookie
*/
@Slf4j
public class CookieUtil {
private final static String COOKIE_DOMAIN = "oursnail.cn";
private final static String COOKIE_NAME = "snailmall_login_token";
/**
* cookie
* @param response
* @param token
*/
public static void writeLoginToken(HttpServletResponse response,String token){
Cookie ck = new Cookie(COOKIE_NAME,token);
ck.setDomain(COOKIE_DOMAIN);
ck.setPath("/");//设值在根目录
ck.setHttpOnly(true);//不允许通过脚本访问cookie,避免脚本攻击
ck.setMaxAge(60*60*24*365);//一年,-1表示永久,单位是秒maxage不设置的话cookie就不会写入硬盘只会写在内存只在当前页面有效
log.info("write cookieName:{},cookieValue:{}",ck.getName(),ck.getValue());
response.addCookie(ck);
}
/**
* cookie
* @param request
* @return
*/
public static String readLoginToken(HttpServletRequest request){
Cookie[] cks = request.getCookies();
if(cks != null){
for(Cookie ck:cks){
log.info("cookieName:{},cookieBValue:{}",ck.getName(),ck.getValue());
if(StringUtils.equals(ck.getName(),COOKIE_NAME)){
log.info("return cookieName:{},cookieBValue:{}",ck.getName(),ck.getValue());
return ck.getValue();
}
}
}
return null;
}
/**
*
* @param request
* @param response
*/
public static void delLoginToken(HttpServletRequest request,HttpServletResponse response){
Cookie[] cks = request.getCookies();
if(cks != null){
for(Cookie ck:cks) {
if(StringUtils.equals(ck.getName(),COOKIE_NAME)){
ck.setDomain(COOKIE_DOMAIN);
ck.setPath("/");
ck.setMaxAge(0);//0表示消除此cookie
log.info("del cookieName:{},cookieBValue:{}",ck.getName(),ck.getValue());
response.addCookie(ck);
return;
}
}
}
}
}

@ -0,0 +1,68 @@
package com.njupt.swg.utils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @DESC
*/
public class DateTimeUtil {
//joda-time
//str->Date
//Date->str
public static final String STANDARD_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static Date strToDate(String dateTimeStr, String formatStr){
DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(formatStr);
DateTime dateTime = dateTimeFormatter.parseDateTime(dateTimeStr);
return dateTime.toDate();
}
public static String dateToStr(Date date,String formatStr){
if(date == null){
return StringUtils.EMPTY;
}
DateTime dateTime = new DateTime(date);
return dateTime.toString(formatStr);
}
//固定好格式
public static Date strToDate(String dateTimeStr){
DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(STANDARD_FORMAT);
DateTime dateTime = dateTimeFormatter.parseDateTime(dateTimeStr);
return dateTime.toDate();
}
public static String dateToStr(Date date){
if(date == null){
return StringUtils.EMPTY;
}
DateTime dateTime = new DateTime(date);
return dateTime.toString(STANDARD_FORMAT);
}
//Date -> 时间戳
public static Long dateToChuo(Date date) throws ParseException {
if(date == null){
return null;
}
SimpleDateFormat format = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );
return format.parse(String.valueOf(date)).getTime();
}
public static void main(String[] args) throws ParseException {
SimpleDateFormat format = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );
String time="1970-01-06 11:45:55";
Date date = format.parse(time);
System.out.print("Format To times:"+date.getTime());
}
}

@ -0,0 +1,126 @@
package com.njupt.swg.utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.codehaus.jackson.type.JavaType;
import org.codehaus.jackson.type.TypeReference;
import java.io.IOException;
import java.text.SimpleDateFormat;
/**
* jackson
*/
@Slf4j
public class JsonUtil {
private static ObjectMapper objectMapper = new ObjectMapper();
static {
//所有字段都列入进行转换
objectMapper.setSerializationInclusion(JsonSerialize.Inclusion.ALWAYS);
//取消默认转换timestamp形式
objectMapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS,false);
//忽略空bean转json的错误
objectMapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS,false);
//统一时间的格式
objectMapper.setDateFormat(new SimpleDateFormat(DateTimeUtil.STANDARD_FORMAT));
//忽略json存在属性但是java对象不存在属性的错误
objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES,false);
}
/**
*
* @param obj
* @param <T>
* @return
*/
public static <T> String obj2String(T obj){
if(obj == null){
return null;
}
try {
return obj instanceof String ? (String) obj : objectMapper.writeValueAsString(obj);
} catch (IOException e) {
log.warn("parse object to string error",e);
return null;
}
}
/**
* 便
* @param obj
* @param <T>
* @return
*/
public static <T> String obj2StringPretty(T obj){
if(obj == null){
return null;
}
try {
return obj instanceof String ? (String) obj : objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
} catch (IOException e) {
log.warn("parse object to string error",e);
return null;
}
}
/**
*
* @param str
* @param clazz
* @param <T>
* @return
*/
public static <T> T String2Obj(String str,Class<T> clazz){
if(StringUtils.isEmpty(str) || clazz == null){
return null;
}
try {
return clazz.equals(String.class)?(T)str:objectMapper.readValue(str,clazz);
} catch (IOException e) {
log.warn("parse string to obj error",e);
return null;
}
}
/**
*
* @param str
* @param typeReference
* @param <T>
* @return
*/
public static <T> T Str2Obj(String str, TypeReference typeReference){
if(StringUtils.isEmpty(str) || typeReference == null){
return null;
}
try {
return (T) (typeReference.getType().equals(String.class)?str:objectMapper.readValue(str,typeReference));
} catch (IOException e) {
log.warn("parse string to obj error",e);
return null;
}
}
/**
*
* @param str
* @param collectionClass
* @param elementClasses
* @param <T>
* @return
*/
public static <T> T Str2Obj(String str,Class<?> collectionClass,Class<?>... elementClasses){
JavaType javaType = objectMapper.getTypeFactory().constructParametricType(collectionClass,elementClasses);
try {
return objectMapper.readValue(str,javaType);
} catch (IOException e) {
log.warn("parse string to obj error",e);
return null;
}
}
}

@ -0,0 +1,67 @@
eureka:
client:
service-url:
defaultZone: http://111.231.119.253:8761/eureka
spring:
application:
name: api-gateway
zipkin:
base-url: http://106.14.163.235:9411
sender:
type: web
sleuth:
sampler:
probability: 1
cloud:
config:
discovery:
enabled: true
service-id: SNAILMALL-CONFIG-SERVER
profile: dev
bus:
trace:
enabled: true
enabled: true
server:
port: 8080
ribbon:
ReadTimeout: 60000
ConnectTimeout: 60000
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 60000
zuul:
host:
socket-timeout-millis: 10000
connect-timeout-millis: 10000
max-total-connections: 20000
routes:
category:
path: /category/**/
serviceId: category-service
sensitiveHeaders:
user:
path: /user/**/
serviceId: user-service
sensitiveHeaders:
prodcut:
path: /product/**/
serviceId: product-service
sensitiveHeaders:
shipping:
path: /shipping/**/
serviceId: shipping-service
sensitiveHeaders:
cart:
path: /cart/**/
serviceId: cart-service
sensitiveHeaders:
order:
path: /order/**/
serviceId: order-service
sensitiveHeaders:

@ -0,0 +1,2 @@
# 配置后台不需要校验的url后缀
security.noneSecurityAdminPaths=upload.do,richtext_img_upload.do

@ -0,0 +1,25 @@
/target/
!.mvn/wrapper/maven-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/build/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/

@ -0,0 +1,118 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.njupt.swg</groupId>
<artifactId>spring-cloud-for-snailmall</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>snailmall-cart-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>snailmall-cart-service</name>
<description>购物车服务</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--spring cloud相关-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--jackson-->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
</dependency>
<!--druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<!--util-->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
</dependency>
<!--MYSQL-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!--jedis-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!--joda time-->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
</dependencies>
<build>
<!--编译xml文件-->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,18 @@
package com.njupt.swg;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class SnailmallCartServiceApplication {
public static void main(String[] args) {
SpringApplication.run(SnailmallCartServiceApplication.class, args);
}
}

@ -0,0 +1,104 @@
package com.njupt.swg.cache;
import com.njupt.swg.common.exception.SnailmallException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
/**
* @Author swg.
* @Date 2019/1/1 15:03
* @CONTACT 317758022@qq.com
* @DESC
*/
@Component
@Slf4j
public class CommonCacheUtil {
@Autowired
private JedisPoolWrapper jedisPoolWrapper;
/**
* key
*/
public void cache(String key, String value) {
try {
JedisPool pool = jedisPoolWrapper.getJedisPool();
if (pool != null) {
try (Jedis Jedis = pool.getResource()) {
Jedis.select(0);
Jedis.set(key, value);
}
}
} catch (Exception e) {
log.error("redis存值失败", e);
throw new SnailmallException("redis报错");
}
}
/**
* key
*/
public String getCacheValue(String key) {
String value = null;
try {
JedisPool pool = jedisPoolWrapper.getJedisPool();
if (pool != null) {
try (Jedis Jedis = pool.getResource()) {
Jedis.select(0);
value = Jedis.get(key);
}
}
} catch (Exception e) {
log.error("redis获取指失败", e);
throw new SnailmallException("redis报错");
}
return value;
}
/**
* key
*/
public long cacheNxExpire(String key, String value, int expire) {
long result = 0;
try {
JedisPool pool = jedisPoolWrapper.getJedisPool();
if (pool != null) {
try (Jedis jedis = pool.getResource()) {
jedis.select(0);
result = jedis.setnx(key, value);
jedis.expire(key, expire);
}
}
} catch (Exception e) {
log.error("redis塞值和设置缓存时间失败", e);
throw new SnailmallException("redis报错");
}
return result;
}
/**
* key
*/
public void delKey(String key) {
JedisPool pool = jedisPoolWrapper.getJedisPool();
if (pool != null) {
try (Jedis jedis = pool.getResource()) {
jedis.select(0);
try {
jedis.del(key);
} catch (Exception e) {
log.error("从redis中删除失败", e);
throw new SnailmallException("redis报错");
}
}
}
}
}

@ -0,0 +1,42 @@
package com.njupt.swg.cache;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import javax.annotation.PostConstruct;
/**
* @Author swg.
* @Date 2019/1/1 15:00
* @CONTACT 317758022@qq.com
* @DESC redisredishash
*/
@Component
@Slf4j
public class JedisPoolWrapper {
@Autowired
private Parameters parameters;
private JedisPool jedisPool = null;
@PostConstruct
public void init(){
try {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(parameters.getRedisMaxTotal());
config.setMaxIdle(parameters.getRedisMaxIdle());
config.setMaxWaitMillis(parameters.getRedisMaxWaitMillis());
jedisPool = new JedisPool(config,parameters.getRedisHost(),parameters.getRedisPort(),2000,"xxx");
log.info("【初始化redis连接池成功】");
}catch (Exception e){
log.error("【初始化redis连接池失败】",e);
}
}
public JedisPool getJedisPool() {
return jedisPool;
}
}

@ -0,0 +1,33 @@
package com.njupt.swg.cache;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @Author swg.
* @Date 2019/1/1 14:27
* @CONTACT 317758022@qq.com
* @DESC
*/
@Component
@Data
public class Parameters {
/*****redis config start*******/
@Value("${redis.host}")
private String redisHost;
@Value("${redis.port}")
private int redisPort;
@Value("${redis.max-idle}")
private int redisMaxTotal;
@Value("${redis.max-total}")
private int redisMaxIdle;
@Value("${redis.max-wait-millis}")
private int redisMaxWaitMillis;
/*****redis config end*******/
/*****curator config start*******/
@Value("${zk.host}")
private String zkHost;
/*****curator config end*******/
}

@ -0,0 +1,23 @@
package com.njupt.swg.clients;
import com.njupt.swg.common.resp.ServerResponse;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* @Author swg.
* @Date 2019/1/5 14:57
* @CONTACT 317758022@qq.com
* @DESC
*/
@FeignClient("product-service")
public interface ProductClient {
@RequestMapping("/product/detail.do")
ServerResponse getProductDetail(@RequestParam("productId") Integer productId);
@RequestMapping("/product/queryProduct.do")
ServerResponse queryProduct(@RequestParam("productId") Integer productId);
}

@ -0,0 +1,42 @@
package com.njupt.swg.common.constants;
/**
* @Author swg.
* @Date 2019/1/1 13:19
* @CONTACT 317758022@qq.com
* @DESC
*/
public class Constants {
/**自定义状态码 start**/
public static final int RESP_STATUS_OK = 200;
public static final int RESP_STATUS_NOAUTH = 401;
public static final int RESP_STATUS_INTERNAL_ERROR = 500;
public static final int RESP_STATUS_BADREQUEST = 400;
/**自定义状态码 end**/
public interface Cart{
int CHECKED = 1;//即购物车选中状态
int UN_CHECKED = 0;//购物车中未选中状态
String LIMIT_NUM_FAIL = "LIMIT_NUM_FAIL";
String LIMIT_NUM_SUCCESS = "LIMIT_NUM_SUCCESS";
}
/** 产品的状态 **/
public interface Product{
int PRODUCT_ON = 1;
int PRODUCT_OFF = 2;
int PRODUCT_DELETED = 3;
}
/***redis product stock**/
public static final String PRODUCT_TOKEN_STOCK_PREFIX = "product__stock_";
public static final String PRODUCT_TOKEN_PREFIX = "product__";
}

@ -0,0 +1,33 @@
package com.njupt.swg.common.exception;
import com.njupt.swg.common.constants.Constants;
import com.njupt.swg.common.resp.ServerResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @Author swg.
* @Date 2019/1/1 13:21
* @CONTACT 317758022@qq.com
* @DESC
*/
@ControllerAdvice
@ResponseBody
@Slf4j
public class ExceptionHandlerAdvice {
@ExceptionHandler(Exception.class)
public ServerResponse handleException(Exception e){
log.error(e.getMessage(),e);
return ServerResponse.createByErrorCodeMessage(Constants.RESP_STATUS_INTERNAL_ERROR,"系统异常,请稍后再试");
}
@ExceptionHandler(SnailmallException.class)
public ServerResponse handleException(SnailmallException e){
log.error(e.getMessage(),e);
return ServerResponse.createByErrorCodeMessage(e.getExceptionStatus(),e.getMessage());
}
}

@ -0,0 +1,25 @@
package com.njupt.swg.common.exception;
import com.njupt.swg.common.resp.ResponseEnum;
import lombok.Getter;
/**
* @Author swg.
* @Date 2019/1/1 13:18
* @CONTACT 317758022@qq.com
* @DESC
*/
@Getter
public class SnailmallException extends RuntimeException{
private int exceptionStatus = ResponseEnum.ERROR.getCode();
public SnailmallException(String msg){
super(msg);
}
public SnailmallException(int code,String msg){
super(msg);
exceptionStatus = code;
}
}

@ -0,0 +1,25 @@
package com.njupt.swg.common.resp;
import lombok.Getter;
/**
* @Author swg.
* @Date 2018/12/31 20:15
* @CONTACT 317758022@qq.com
* @DESC
*/
@Getter
public enum ResponseEnum {
SUCCESS(0,"SUCCESS"),
ERROR(1,"ERROR"),
ILLEGAL_ARGUMENTS(2,"ILLEGAL_ARGUMENTS"),
NEED_LOGIN(10,"NEED_LOGIN");
private int code;
private String desc;
ResponseEnum(int code,String desc){
this.code = code;
this.desc = desc;
}
}

@ -0,0 +1,77 @@
package com.njupt.swg.common.resp;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Getter;
import java.io.Serializable;
/**
* @Author swg.
* @Date 2018/12/31 20:11
* @CONTACT 317758022@qq.com
* @DESC
*/
@Getter
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
public class ServerResponse<T> implements Serializable {
private int status;
private String msg;
private T data;
public ServerResponse(){}
private ServerResponse(int status){
this.status = status;
}
private ServerResponse(int status,String msg){
this.status = status;
this.msg = msg;
}
private ServerResponse(int status,T data){
this.status = status;
this.data = data;
}
private ServerResponse(int status,String msg,T data){
this.status = status;
this.msg = msg;
this.data = data;
}
@JsonIgnore
public boolean isSuccess(){
return this.status == ResponseEnum.SUCCESS.getCode();
}
/**
*
*/
public static <T>ServerResponse<T> createBySuccess(){
return new ServerResponse<>(ResponseEnum.SUCCESS.getCode(),ResponseEnum.SUCCESS.getDesc());
}
public static <T>ServerResponse<T> createBySuccessMessage(String message){
return new ServerResponse<>(ResponseEnum.SUCCESS.getCode(),message);
}
public static <T>ServerResponse<T> createBySuccess(T data){
return new ServerResponse<>(ResponseEnum.SUCCESS.getCode(),data);
}
public static <T>ServerResponse<T> createBySuccess(String message,T data){
return new ServerResponse<>(ResponseEnum.SUCCESS.getCode(),message,data);
}
/**
*
*/
public static <T>ServerResponse<T> createByError(){
return new ServerResponse<>(ResponseEnum.ERROR.getCode(),ResponseEnum.ERROR.getDesc());
}
public static <T>ServerResponse<T> createByErrorMessage(String msg){
return new ServerResponse<>(ResponseEnum.ERROR.getCode(),msg);
}
public static <T>ServerResponse<T> createByErrorCodeMessage(int code,String msg){
return new ServerResponse<>(code,msg);
}
}

@ -0,0 +1,42 @@
package com.njupt.swg.common.utils;
import java.math.BigDecimal;
/**
* @Author swg.
* @Date 2019/1/5 15:20
* @CONTACT 317758022@qq.com
* @DESC BigDecimal
*/
public class BigDecimalUtil {
private BigDecimalUtil(){
}
public static BigDecimal add(double v1, double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2);
}
public static BigDecimal sub(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2);
}
public static BigDecimal mul(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2);
}
public static BigDecimal div(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.divide(b2,2,BigDecimal.ROUND_HALF_UP);//四舍五入,保留2位小数
//除不尽的情况
}
}

@ -0,0 +1,74 @@
package com.njupt.swg.common.utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* cookie
*/
@Slf4j
public class CookieUtil {
private final static String COOKIE_DOMAIN = "oursnail.cn";
private final static String COOKIE_NAME = "snailmall_login_token";
/**
* cookie
* @param response
* @param token
*/
public static void writeLoginToken(HttpServletResponse response,String token){
Cookie ck = new Cookie(COOKIE_NAME,token);
ck.setDomain(COOKIE_DOMAIN);
ck.setPath("/");//设值在根目录
ck.setHttpOnly(true);//不允许通过脚本访问cookie,避免脚本攻击
ck.setMaxAge(60*60*24*365);//一年,-1表示永久,单位是秒maxage不设置的话cookie就不会写入硬盘只会写在内存只在当前页面有效
log.info("write cookieName:{},cookieValue:{}",ck.getName(),ck.getValue());
response.addCookie(ck);
}
/**
* cookie
* @param request
* @return
*/
public static String readLoginToken(HttpServletRequest request){
Cookie[] cks = request.getCookies();
if(cks != null){
for(Cookie ck:cks){
log.info("cookieName:{},cookieBValue:{}",ck.getName(),ck.getValue());
if(StringUtils.equals(ck.getName(),COOKIE_NAME)){
log.info("return cookieName:{},cookieBValue:{}",ck.getName(),ck.getValue());
return ck.getValue();
}
}
}
return null;
}
/**
*
* @param request
* @param response
*/
public static void delLoginToken(HttpServletRequest request,HttpServletResponse response){
Cookie[] cks = request.getCookies();
if(cks != null){
for(Cookie ck:cks) {
if(StringUtils.equals(ck.getName(),COOKIE_NAME)){
ck.setDomain(COOKIE_DOMAIN);
ck.setPath("/");
ck.setMaxAge(0);//0表示消除此cookie
log.info("del cookieName:{},cookieBValue:{}",ck.getName(),ck.getValue());
response.addCookie(ck);
return;
}
}
}
}
}

@ -0,0 +1,68 @@
package com.njupt.swg.common.utils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @DESC
*/
public class DateTimeUtil {
//joda-time
//str->Date
//Date->str
public static final String STANDARD_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static Date strToDate(String dateTimeStr, String formatStr){
DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(formatStr);
DateTime dateTime = dateTimeFormatter.parseDateTime(dateTimeStr);
return dateTime.toDate();
}
public static String dateToStr(Date date,String formatStr){
if(date == null){
return StringUtils.EMPTY;
}
DateTime dateTime = new DateTime(date);
return dateTime.toString(formatStr);
}
//固定好格式
public static Date strToDate(String dateTimeStr){
DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(STANDARD_FORMAT);
DateTime dateTime = dateTimeFormatter.parseDateTime(dateTimeStr);
return dateTime.toDate();
}
public static String dateToStr(Date date){
if(date == null){
return StringUtils.EMPTY;
}
DateTime dateTime = new DateTime(date);
return dateTime.toString(STANDARD_FORMAT);
}
//Date -> 时间戳
public static Long dateToChuo(Date date) throws ParseException {
if(date == null){
return null;
}
SimpleDateFormat format = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );
return format.parse(String.valueOf(date)).getTime();
}
public static void main(String[] args) throws ParseException {
SimpleDateFormat format = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );
String time="1970-01-06 11:45:55";
Date date = format.parse(time);
System.out.print("Format To times:"+date.getTime());
}
}

@ -0,0 +1,126 @@
package com.njupt.swg.common.utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.codehaus.jackson.type.JavaType;
import org.codehaus.jackson.type.TypeReference;
import java.io.IOException;
import java.text.SimpleDateFormat;
/**
* jackson
*/
@Slf4j
public class JsonUtil {
private static ObjectMapper objectMapper = new ObjectMapper();
static {
//所有字段都列入进行转换
objectMapper.setSerializationInclusion(JsonSerialize.Inclusion.ALWAYS);
//取消默认转换timestamp形式
objectMapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS,false);
//忽略空bean转json的错误
objectMapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS,false);
//统一时间的格式
objectMapper.setDateFormat(new SimpleDateFormat(DateTimeUtil.STANDARD_FORMAT));
//忽略json存在属性但是java对象不存在属性的错误
objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES,false);
}
/**
*
* @param obj
* @param <T>
* @return
*/
public static <T> String obj2String(T obj){
if(obj == null){
return null;
}
try {
return obj instanceof String ? (String) obj : objectMapper.writeValueAsString(obj);
} catch (IOException e) {
log.warn("parse object to string error",e);
return null;
}
}
/**
* 便
* @param obj
* @param <T>
* @return
*/
public static <T> String obj2StringPretty(T obj){
if(obj == null){
return null;
}
try {
return obj instanceof String ? (String) obj : objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
} catch (IOException e) {
log.warn("parse object to string error",e);
return null;
}
}
/**
*
* @param str
* @param clazz
* @param <T>
* @return
*/
public static <T> T String2Obj(String str,Class<T> clazz){
if(StringUtils.isEmpty(str) || clazz == null){
return null;
}
try {
return clazz.equals(String.class)?(T)str:objectMapper.readValue(str,clazz);
} catch (IOException e) {
log.warn("parse string to obj error",e);
return null;
}
}
/**
*
* @param str
* @param typeReference
* @param <T>
* @return
*/
public static <T> T Str2Obj(String str, TypeReference typeReference){
if(StringUtils.isEmpty(str) || typeReference == null){
return null;
}
try {
return (T) (typeReference.getType().equals(String.class)?str:objectMapper.readValue(str,typeReference));
} catch (IOException e) {
log.warn("parse string to obj error",e);
return null;
}
}
/**
*
* @param str
* @param collectionClass
* @param elementClasses
* @param <T>
* @return
*/
public static <T> T Str2Obj(String str,Class<?> collectionClass,Class<?>... elementClasses){
JavaType javaType = objectMapper.getTypeFactory().constructParametricType(collectionClass,elementClasses);
try {
return objectMapper.readValue(str,javaType);
} catch (IOException e) {
log.warn("parse string to obj error",e);
return null;
}
}
}

@ -0,0 +1,59 @@
package com.njupt.swg.common.utils;
import java.security.MessageDigest;
/**
* MD5
*/
public class MD5Util {
private static String byteArrayToHexString(byte b[]) {
StringBuffer resultSb = new StringBuffer();
for (int i = 0; i < b.length; i++)
resultSb.append(byteToHexString(b[i]));
return resultSb.toString();
}
private static String byteToHexString(byte b) {
int n = b;
if (n < 0)
n += 256;
int d1 = n / 16;
int d2 = n % 16;
return hexDigits[d1] + hexDigits[d2];
}
/**
* MD5
*
* @param origin
* @param charsetname
* @return
*/
private static String MD5Encode(String origin, String charsetname) {
String resultString = null;
try {
resultString = new String(origin);
MessageDigest md = MessageDigest.getInstance("MD5");
if (charsetname == null || "".equals(charsetname))
resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
else
resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
} catch (Exception exception) {
}
return resultString.toUpperCase();
}
public static String MD5EncodeUtf8(String origin) {
//这里可以加盐
return MD5Encode(origin, "utf-8");
}
public static void main(String[] args) {
System.out.println(MD5EncodeUtf8("123456"));
}
private static final String hexDigits[] = {"0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
}

@ -0,0 +1,46 @@
package com.njupt.swg.common.utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Properties;
/**
* @Author swg.
* @Date 2018/1/10 14:56
* @DESC
* @CONTACT 317758022@qq.com
*/
@Slf4j
public class PropertiesUtil {
private static Properties props;
static {
String fileName = "parameter.properties";
props = new Properties();
try {
props.load(new InputStreamReader(PropertiesUtil.class.getClassLoader().getResourceAsStream(fileName),"UTF-8"));
} catch (IOException e) {
log.error("配置文件读取异常",e);
}
}
public static String getProperty(String key){
String value = props.getProperty(key.trim());
if(StringUtils.isBlank(value)){
return null;
}
return value.trim();
}
public static String getProperty(String key,String defaultValue){
String value = props.getProperty(key.trim());
if(StringUtils.isBlank(value)){
value = defaultValue;
}
return value.trim();
}
}

@ -0,0 +1,40 @@
package com.njupt.swg.controller;
import com.njupt.swg.cache.CommonCacheUtil;
import com.njupt.swg.common.exception.SnailmallException;
import com.njupt.swg.common.resp.ResponseEnum;
import com.njupt.swg.common.resp.ServerResponse;
import com.njupt.swg.common.utils.CookieUtil;
import com.njupt.swg.common.utils.JsonUtil;
import com.njupt.swg.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.http.HttpServletRequest;
/**
* @Author swg.
* @Date 2019/1/5 16:19
* @CONTACT 317758022@qq.com
* @DESC
*/
@Slf4j
public class BaseController {
@Autowired
private CommonCacheUtil commonCacheUtil;
User getCurrentUser(HttpServletRequest httpServletRequest){
String loginToken = CookieUtil.readLoginToken(httpServletRequest);
if(StringUtils.isEmpty(loginToken)){
throw new SnailmallException("用户未登陆,无法获取当前用户信息");
}
String userJsonStr = commonCacheUtil.getCacheValue(loginToken);
if(userJsonStr == null){
throw new SnailmallException(ResponseEnum.NEED_LOGIN.getCode(),ResponseEnum.NEED_LOGIN.getDesc());
}
User user = JsonUtil.Str2Obj(userJsonStr,User.class);
return user;
}
}

@ -0,0 +1,190 @@
package com.njupt.swg.controller;
import com.njupt.swg.cache.CommonCacheUtil;
import com.njupt.swg.common.constants.Constants;
import com.njupt.swg.common.resp.ResponseEnum;
import com.njupt.swg.common.resp.ServerResponse;
import com.njupt.swg.common.utils.JsonUtil;
import com.njupt.swg.entity.User;
import com.njupt.swg.service.ICartService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
/**
* @Author swg.
* @Date 2019/1/3 21:36
* @CONTACT 317758022@qq.com
* @DESC
*/
@RestController
@RequestMapping("/cart")
public class CartController extends BaseController{
@Autowired
private ICartService cartService;
@Autowired
private CommonCacheUtil commonCacheUtil;
/**
* 1.
* "limitQuantity"
* LIMIT_NUM_FAIL LIMIT_NUM_SUCCESS
*/
@RequestMapping("add.do")
public ServerResponse add(HttpServletRequest httpServletRequest, Integer productId, Integer count){
User user = getCurrentUser(httpServletRequest);
return cartService.add(user.getId(),productId,count);
}
/**
* 2.
* "limitQuantity"
* LIMIT_NUM_FAIL LIMIT_NUM_SUCCESS
*/
@RequestMapping("update.do")
public ServerResponse update(HttpServletRequest httpServletRequest,Integer productId,Integer count){
User user = getCurrentUser(httpServletRequest);
return cartService.update(user.getId(),productId,count);
}
/**
* 3.
*/
@RequestMapping("delete_product.do")
public ServerResponse delete_product(HttpServletRequest httpServletRequest,String productIds){
User user = getCurrentUser(httpServletRequest);
return cartService.delete(user.getId(),productIds);
}
/**
* 4.List
* ,2
*/
@RequestMapping("list.do")
public ServerResponse list(HttpServletRequest httpServletRequest){
User user = getCurrentUser(httpServletRequest);
return cartService.list(user.getId());
}
/**
* 5.
*/
@RequestMapping("select_all.do")
public ServerResponse select_all(HttpServletRequest httpServletRequest){
User user = getCurrentUser(httpServletRequest);
return cartService.selectOrUnSelect(user.getId(), Constants.Cart.CHECKED,null);
}
/**
* 6.
*/
@RequestMapping("un_select_all.do")
public ServerResponse un_select_all(HttpServletRequest httpServletRequest){
User user = getCurrentUser(httpServletRequest);
return cartService.selectOrUnSelect(user.getId(),Constants.Cart.UN_CHECKED,null);
}
/**
* 7.
*/
@RequestMapping("select.do")
public ServerResponse select(HttpServletRequest httpServletRequest,Integer productId){
User user = getCurrentUser(httpServletRequest);
return cartService.selectOrUnSelect(user.getId(),Constants.Cart.CHECKED,productId);
}
/**
* 8.
*/
@RequestMapping("un_select.do")
public ServerResponse un_select(HttpServletRequest httpServletRequest,Integer productId){
User user = getCurrentUser(httpServletRequest);
return cartService.selectOrUnSelect(user.getId(),Constants.Cart.UN_CHECKED,productId);
}
/**
* 9.
*/
@RequestMapping("get_cart_product_count.do")
public ServerResponse<Integer> get_cart_product_count(HttpServletRequest httpServletRequest){
User user = getCurrentUser(httpServletRequest);
return cartService.get_cart_product_count(user.getId());
}
/**
* feignuserId
*/
@RequestMapping("getCartList.do")
public ServerResponse getCartList(HttpServletRequest httpServletRequest){
User user = null;
Enumeration<String> headerNames = httpServletRequest.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
if(name.equalsIgnoreCase("snailmall_login_token")){
String value = httpServletRequest.getHeader(name);
if(StringUtils.isBlank(value)){
return ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(),"用户未登陆,无法获取当前用户信息");
}
String userJsonStr = commonCacheUtil.getCacheValue(value);
if(userJsonStr == null){
return ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(),"用户未登陆,无法获取当前用户信息");
}
user = JsonUtil.Str2Obj(userJsonStr,User.class);
}
}
}
if (user == null){
return ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(),"用户未登陆,无法获取当前用户信息");
}
return cartService.list(user.getId());
}
/**
* feign
*/
@RequestMapping("removeCart.do")
public ServerResponse removeCart(HttpServletRequest httpServletRequest){
User user = null;
Enumeration<String> headerNames = httpServletRequest.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
if(name.equalsIgnoreCase("snailmall_login_token")){
String value = httpServletRequest.getHeader(name);
if(StringUtils.isBlank(value)){
return ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(),"用户未登陆,无法获取当前用户信息");
}
String userJsonStr = commonCacheUtil.getCacheValue(value);
if(userJsonStr == null){
return ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(),"用户未登陆,无法获取当前用户信息");
}
user = JsonUtil.Str2Obj(userJsonStr,User.class);
}
}
}
if (user == null){
return ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(),"用户未登陆,无法获取当前用户信息");
}
return cartService.removeCart(user.getId());
}
}

@ -0,0 +1,36 @@
package com.njupt.swg.dao;
import com.njupt.swg.entity.Cart;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface CartMapper {
int deleteByPrimaryKey(Integer id);
int insert(Cart record);
int insertSelective(Cart record);
Cart selectByPrimaryKey(Integer id);
int updateByPrimaryKeySelective(Cart record);
int updateByPrimaryKey(Cart record);
Cart selectByUserIdProductId(@Param("userId") Integer userId, @Param("productId") Integer productId);
List<Cart> selectCartByUserId(Integer userId);
int selectCartCheckedStatusByUserId(Integer userId);
int deleteByProductIds(@Param("userId") Integer userId, @Param("productIdList") List<String> productIdList);
void selectOrUnSelectProduct(@Param("userId") Integer userId, @Param("checked") int checked, @Param("productId") Integer productId);
int selectCartProductCount(Integer userId);
List<Cart> selectCheckedCartByUserId(Integer userId);
}

@ -0,0 +1,163 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.njupt.swg.dao.CartMapper" >
<resultMap id="BaseResultMap" type="com.njupt.swg.entity.Cart" >
<constructor >
<idArg column="id" jdbcType="INTEGER" javaType="java.lang.Integer" />
<arg column="user_id" jdbcType="INTEGER" javaType="java.lang.Integer" />
<arg column="product_id" jdbcType="INTEGER" javaType="java.lang.Integer" />
<arg column="quantity" jdbcType="INTEGER" javaType="java.lang.Integer" />
<arg column="checked" jdbcType="INTEGER" javaType="java.lang.Integer" />
<arg column="create_time" jdbcType="TIMESTAMP" javaType="java.util.Date" />
<arg column="update_time" jdbcType="TIMESTAMP" javaType="java.util.Date" />
</constructor>
</resultMap>
<sql id="Base_Column_List" >
id, user_id, product_id, quantity, checked, create_time, update_time
</sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
<include refid="Base_Column_List" />
from mmall_cart
where id = #{id,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
delete from mmall_cart
where id = #{id,jdbcType=INTEGER}
</delete>
<insert id="insert" parameterType="com.njupt.swg.entity.Cart" >
insert into mmall_cart (id, user_id, product_id,
quantity, checked, create_time,
update_time)
values (#{id,jdbcType=INTEGER}, #{userId,jdbcType=INTEGER}, #{productId,jdbcType=INTEGER},
#{quantity,jdbcType=INTEGER}, #{checked,jdbcType=INTEGER}, now(),
now())
</insert>
<insert id="insertSelective" parameterType="com.njupt.swg.entity.Cart" >
insert into mmall_cart
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="id != null" >
id,
</if>
<if test="userId != null" >
user_id,
</if>
<if test="productId != null" >
product_id,
</if>
<if test="quantity != null" >
quantity,
</if>
<if test="checked != null" >
checked,
</if>
<if test="createTime != null" >
create_time,
</if>
<if test="updateTime != null" >
update_time,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="id != null" >
#{id,jdbcType=INTEGER},
</if>
<if test="userId != null" >
#{userId,jdbcType=INTEGER},
</if>
<if test="productId != null" >
#{productId,jdbcType=INTEGER},
</if>
<if test="quantity != null" >
#{quantity,jdbcType=INTEGER},
</if>
<if test="checked != null" >
#{checked,jdbcType=INTEGER},
</if>
<if test="createTime != null" >
now(),
</if>
<if test="updateTime != null" >
now(),
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="com.njupt.swg.entity.Cart" >
update mmall_cart
<set >
<if test="userId != null" >
user_id = #{userId,jdbcType=INTEGER},
</if>
<if test="productId != null" >
product_id = #{productId,jdbcType=INTEGER},
</if>
<if test="quantity != null" >
quantity = #{quantity,jdbcType=INTEGER},
</if>
<if test="checked != null" >
checked = #{checked,jdbcType=INTEGER},
</if>
<if test="createTime != null" >
create_time = #{createTime,jdbcType=TIMESTAMP},
</if>
<if test="updateTime != null" >
update_time = now(),
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey" parameterType="com.njupt.swg.entity.Cart" >
update mmall_cart
set user_id = #{userId,jdbcType=INTEGER},
product_id = #{productId,jdbcType=INTEGER},
quantity = #{quantity,jdbcType=INTEGER},
checked = #{checked,jdbcType=INTEGER},
create_time = #{createTime,jdbcType=TIMESTAMP},
update_time = now()
where id = #{id,jdbcType=INTEGER}
</update>
<select id="selectByUserIdProductId" parameterType="map" resultMap="BaseResultMap">
SELECT <include refid="Base_Column_List"/> from mmall_cart
WHERE user_id = #{userId}
and product_id = #{productId}
</select>
<select id="selectCartByUserId" parameterType="int" resultMap="BaseResultMap">
SELECT <include refid="Base_Column_List"/>
from mmall_cart
where user_id = #{userId}
</select>
<select id="selectCartCheckedStatusByUserId" resultType="int" parameterType="int">
SELECT count(1) from mmall_cart WHERE checked = 0 and user_id = #{userId}
</select>
<delete id="deleteByProductIds" parameterType="map">
DELETE from mmall_cart where user_id = #{userId}
<if test="productIdList != null">
and product_id in
<foreach collection="productIdList" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</if>
</delete>
<update id="selectOrUnSelectProduct" parameterType="map">
UPDATE mmall_cart
set update_time = now(),checked = #{checked}
where user_id = #{userId}
<if test="productId != null">
and product_id = #{productId}
</if>
</update>
<select id="selectCartProductCount" resultType="int" parameterType="int">
SELECT IFNULL(sum(quantity),0) as count from mmall_cart where user_id = #{userId}
</select>
<select id="selectCheckedCartByUserId" parameterType="int" resultMap="BaseResultMap">
SELECT <include refid="Base_Column_List"/> from mmall_cart where user_id = #{userId} and checked = 1
</select>
</mapper>

@ -0,0 +1,29 @@
package com.njupt.swg.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Cart {
private Integer id;
private Integer userId;
private Integer productId;
private Integer quantity;
private Integer checked;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss.SSS")
private Date createTime;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss.SSS")
private Date updateTime;
}

@ -0,0 +1,37 @@
package com.njupt.swg.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Product {
private Integer id;
private Integer categoryId;
private String name;
private String subtitle;
private String mainImage;
private String subImages;
private String detail;
private BigDecimal price;
private Integer stock;
private Integer status;
private Date createTime;
private Date updateTime;
}

@ -0,0 +1,43 @@
package com.njupt.swg.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.io.Serializable;
import java.util.Date;
/**
* @Author swg.
* @Date 2018/12/31 21:01
* @CONTACT 317758022@qq.com
* @DESC
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class User implements Serializable {
private Integer id;
private String username;
private String password;
private String email;
private String phone;
private String question;
private String answer;
//角色0-管理员,1-普通用户
private Integer role;
private Date createTime;
private Date updateTime;
}

@ -0,0 +1,39 @@
package com.njupt.swg.message;
import com.njupt.swg.common.utils.JsonUtil;
import com.njupt.swg.service.ICartService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @Author swg.
* @Date 2019/1/7 13:23
* @CONTACT 317758022@qq.com
* @DESC
*/
@Component
@Slf4j
public class MessageReceiver {
@Autowired
private ICartService cartService;
@RabbitListener(bindings = @QueueBinding(
value = @Queue("cart-queue"),
exchange = @Exchange("cart-exchange")
))
public void proess(String message){
log.info("接收到的消息为:{}",message);
Integer userId = Integer.parseInt(message);
log.info("【MQ解析数据,前者为userId,后者为productId{}】",userId);
//清除购物车
cartService.removeCart(userId);
}
}

@ -0,0 +1,241 @@
package com.njupt.swg.service;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.njupt.swg.cache.CommonCacheUtil;
import com.njupt.swg.clients.ProductClient;
import com.njupt.swg.common.constants.Constants;
import com.njupt.swg.common.exception.SnailmallException;
import com.njupt.swg.common.resp.ServerResponse;
import com.njupt.swg.common.utils.BigDecimalUtil;
import com.njupt.swg.common.utils.JsonUtil;
import com.njupt.swg.common.utils.PropertiesUtil;
import com.njupt.swg.dao.CartMapper;
import com.njupt.swg.entity.Cart;
import com.njupt.swg.entity.Product;
import com.njupt.swg.vo.CartProductVo;
import com.njupt.swg.vo.CartVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.List;
/**
* @Author swg.
* @Date 2019/1/3 21:36
* @CONTACT 317758022@qq.com
* @DESC
*/
@Service
@Slf4j
public class CartServiceImpl implements ICartService{
@Autowired
private CartMapper cartMapper;
@Autowired
private ProductClient productClient;
@Autowired
private CommonCacheUtil commonCacheUtil;
@Override
public ServerResponse add(Integer userId, Integer productId, Integer count) {
//1.校验参数
if(userId == null){
throw new SnailmallException("用户未登陆");
}
if(productId == null || count == null){
return ServerResponse.createByErrorMessage("参数不正确");
}
//2.校验商品
String productStr = commonCacheUtil.getCacheValue(Constants.PRODUCT_TOKEN_PREFIX+productId);
Product product = null;
if(productStr == null){
ServerResponse response = productClient.queryProduct(productId);
Object object = response.getData();
String objStr = JsonUtil.obj2String(object);
product = (Product) JsonUtil.Str2Obj(objStr,Product.class);
}else {
product = (Product) JsonUtil.Str2Obj(productStr,Product.class);
}
if(product == null){
return ServerResponse.createByErrorMessage("商品不存在");
}
if(!product.getStatus().equals(Constants.Product.PRODUCT_ON)){
return ServerResponse.createByErrorMessage("商品下架或者删除");
}
//3.根据商品或者购物车,购物车存在则增加商品数量即可,不存在则创建新的购物车,一个用户对应一个购物车
Cart cart = cartMapper.selectByUserIdProductId(userId,productId);
if (cart == null){
Cart cartItem = new Cart();
cartItem.setUserId(userId);
cartItem.setProductId(productId);
cartItem.setQuantity(count);
cartItem.setChecked(Constants.Cart.CHECKED);
int resultCount = cartMapper.insert(cartItem);
if(resultCount == 0){
return ServerResponse.createByErrorMessage("添加购物车失败");
}
}else {
cart.setQuantity(cart.getQuantity()+count);
int resultCount = cartMapper.updateByPrimaryKeySelective(cart);
if(resultCount == 0){
return ServerResponse.createByErrorMessage("添加购物车失败");
}
}
//构建购物车信息,返回给前端,并且要检查库存
CartVo cartVo = getCartVoLimit(userId,true);
return ServerResponse.createBySuccess(cartVo);
}
@Override
public ServerResponse update(Integer userId, Integer productId, Integer count) {
if(productId == null || count == null){
return ServerResponse.createByErrorMessage("参数错误");
}
Cart cart = cartMapper.selectByUserIdProductId(userId,productId);
if(cart == null){
return ServerResponse.createByErrorMessage("购物车不存在");
}
cart.setQuantity(count);
int updateCount = cartMapper.updateByPrimaryKeySelective(cart);
if(updateCount == 0){
return ServerResponse.createByErrorMessage("更新购物车失败");
}
CartVo cartVo = this.getCartVoLimit(userId,true);
return ServerResponse.createBySuccess(cartVo);
}
@Override
public ServerResponse delete(Integer userId, String productIds) {
List<String> productIdList = Splitter.on(",").splitToList(productIds);
if(CollectionUtils.isEmpty(productIdList)){
return ServerResponse.createByErrorMessage("参数错误");
}
int rowCount = cartMapper.deleteByProductIds(userId,productIdList);
if(rowCount == 0){
return ServerResponse.createByErrorMessage("此商品已经不存在于购物车中,请勿重复删除");
}
CartVo cartVo = this.getCartVoLimit(userId,false);
return ServerResponse.createBySuccess(cartVo);
}
@Override
public ServerResponse list(Integer userId) {
CartVo cartVo = this.getCartVoLimit(userId,false);
return ServerResponse.createBySuccess(cartVo);
}
@Override
public ServerResponse selectOrUnSelect(Integer userId, int checked, Integer productId) {
cartMapper.selectOrUnSelectProduct(userId,checked,productId);
CartVo cartVo = this.getCartVoLimit(userId,false);
return ServerResponse.createBySuccess(cartVo);
}
@Override
public ServerResponse<Integer> get_cart_product_count(Integer userId) {
if(userId == null){
return ServerResponse.createBySuccess(0);
}
return ServerResponse.createBySuccess(cartMapper.selectCartProductCount(userId));
}
@Override
public ServerResponse removeCart(Integer userId) {
List<Cart> cartList = cartMapper.selectCartByUserId(userId);
for(Cart cart:cartList){
cartMapper.deleteByPrimaryKey(cart.getId());
}
return ServerResponse.createBySuccessMessage("清除购物车成功");
}
/**
*
* @param userId
* @return
*/
private CartVo getCartVoLimit(Integer userId,boolean isJudgeStock) {
CartVo cartVo = new CartVo();
List<CartProductVo> cartProductVoList = Lists.newArrayList();
List<Cart> cartList = cartMapper.selectCartByUserId(userId);
BigDecimal cartTotalPrice = new BigDecimal("0");
if(CollectionUtils.isNotEmpty(cartList)){
//1.遍历购物车一条购物车记录对应一个商品这些购物车共同对应到一个用户userId
for(Cart cart:cartList){
CartProductVo cartProductVo = new CartProductVo();
cartProductVo.setId(cart.getId());
cartProductVo.setUserId(cart.getUserId());
cartProductVo.setProductId(cart.getProductId());
//2.从redis中获取商品获取不到则feign获取并且重置进redis中
String productStr = commonCacheUtil.getCacheValue(Constants.PRODUCT_TOKEN_PREFIX+cart.getProductId());
Product product = null;
if(productStr == null){
ServerResponse response = productClient.queryProduct(cart.getProductId());
Object object = response.getData();
String objStr = JsonUtil.obj2String(object);
product = (Product) JsonUtil.Str2Obj(objStr,Product.class);
}else {
product = (Product) JsonUtil.Str2Obj(productStr,Product.class);
}
if(product != null){
cartProductVo.setProductMainImage(product.getMainImage());
cartProductVo.setProductName(product.getName());
cartProductVo.setProductSubtitle(product.getSubtitle());
cartProductVo.setProductStatus(product.getStatus());
cartProductVo.setProductPrice(product.getPrice());
cartProductVo.setProductStock(product.getStock());
//3.判断这个商品的库存,有些接口不需要再去判断库存了所以根据传进来的isJudgeStock这个boolean参数来决定是否判断库存
int buyLimitCount = 0;
if (isJudgeStock){
if(product.getStock() > cart.getQuantity()){
//4.库存是够的
buyLimitCount = cart.getQuantity();
cartProductVo.setLimitQuantity(Constants.Cart.LIMIT_NUM_SUCCESS);
}else {
//5.库存不够了,则返回当前最大库存
buyLimitCount = product.getStock();
cartProductVo.setLimitQuantity(Constants.Cart.LIMIT_NUM_FAIL);
Cart cartItem = new Cart();
cartItem.setId(cart.getId());
cartItem.setQuantity(buyLimitCount);
cartMapper.updateByPrimaryKeySelective(cartItem);
}
}else {
buyLimitCount = cart.getQuantity();
}
//6.购买的数量已经是确定的了,下面就可以直接计算价格了
cartProductVo.setQuantity(buyLimitCount);
cartProductVo.setProductTotalPrice(BigDecimalUtil.mul(product.getPrice().doubleValue(),buyLimitCount));
cartProductVo.setProductChecked(cart.getChecked());
}
//7.选中的,就加入到总价中
if(cart.getChecked() == Constants.Cart.CHECKED){
cartTotalPrice = BigDecimalUtil.add(cartTotalPrice.doubleValue(),cartProductVo.getProductTotalPrice().doubleValue());
}
cartProductVoList.add(cartProductVo);
}
}
cartVo.setCartTotalPrice(cartTotalPrice);
cartVo.setCartProductVoList(cartProductVoList);
cartVo.setAllChecked(this.getAllCheckedStatus(userId));
cartVo.setImageHost(PropertiesUtil.getProperty("ftp.server.http.prefix","http://img.oursnail.cn/"));
log.info("购物车列表内容为:{}",cartVo);
return cartVo;
}
/**
* 0-1-
*/
private Boolean getAllCheckedStatus(Integer userId) {
if(userId == null){
return false;
}
return cartMapper.selectCartCheckedStatusByUserId(userId) == 0;
}
}

@ -0,0 +1,33 @@
package com.njupt.swg.service;
import com.njupt.swg.common.resp.ServerResponse;
/**
* @Author swg.
* @Date 2019/1/3 21:36
* @CONTACT 317758022@qq.com
* @DESC
*/
public interface ICartService {
/** 购物车添加商品 **/
ServerResponse add(Integer userId, Integer productId, Integer count);
/** 更新购物车某个产品数量 **/
ServerResponse update(Integer userId, Integer productId, Integer count);
/** 移除购物车某个产品 **/
ServerResponse delete(Integer userId, String productIds);
/** 购物车List列表 **/
ServerResponse list(Integer userId);
/** 购物车选中/取消某个商品 **/
ServerResponse selectOrUnSelect(Integer userId, int checked, Integer productId);
/** 查询在购物车里的产品数量 **/
ServerResponse<Integer> get_cart_product_count(Integer userId);
/** 清空购物车 **/
ServerResponse removeCart(Integer userId);
}

@ -0,0 +1,34 @@
package com.njupt.swg.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @Author swg.
* @Date 2019/1/5 15:18
* @CONTACT 317758022@qq.com
* @DESC
*/
@NoArgsConstructor
@AllArgsConstructor
@Data
public class CartProductVo implements Serializable {
private Integer id;
private Integer userId;
private Integer productId;
private Integer quantity;//购物车中此商品的数量
private String productName;
private String productSubtitle;
private String productMainImage;
private BigDecimal productPrice;
private Integer productStatus;
private BigDecimal productTotalPrice;
private Integer productStock;
private Integer productChecked;//此商品是否勾选
private String limitQuantity;//限制数量的一个返回结果
}

@ -0,0 +1,20 @@
package com.njupt.swg.vo;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
/**
* @Author swg.
* @Date 2019/1/5 15:18
* @CONTACT 317758022@qq.com
* @DESC
*/
@Data
public class CartVo {
private List<CartProductVo> cartProductVoList;
private BigDecimal cartTotalPrice;
private Boolean allChecked;//是否已经都勾选
private String imageHost;
}

@ -0,0 +1,44 @@
eureka:
client:
service-url:
defaultZone: http://111.231.119.253:8761/eureka
spring:
zipkin:
sender:
type: web
application:
name: cart-service
cloud:
config:
discovery:
enabled: true
service-id: SNAILMALL-CONFIG-SERVER
profile: dev
bus:
trace:
enabled: true
enabled: true
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
filters: stat
maxActive: 20
initialSize: 1
maxWait: 60000
minIdle: 1
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: select 'x'
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxOpenPreparedStatements: 20
server:
port: 8084
logging:
config: classpath:logback.xml
mybatis:
mapper-locations: classpath:com/njupt/swg/**/**.xml
type-aliases-package: classpath:com.njupt.swg.**.entity

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="LOG_HOME" value="/logs/cart/" />
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{H:mm} %-5level [%logger{16}] %msg%n</pattern>
</encoder>
</appender>
<appender name="normalLog"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${LOG_HOME}/web.normal.%d{yyyy-MM-dd}.log
</FileNamePattern>
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>10MB</maxFileSize>
</triggeringPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{16} - %msg%n
</pattern>
</layout>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>DENY</onMatch>
<onMismatch>ACCEPT</onMismatch>
</filter>
</appender>
<appender name="errorLog"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${LOG_HOME}/web.error.%d{yyyy-MM-dd}.log
</FileNamePattern>
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>10MB</maxFileSize>
</triggeringPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{16} - %msg%n
</pattern>
</layout>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<logger name="com.oursnail" level="debug" >
<appender-ref ref="normalLog" />
<appender-ref ref="errorLog" />
</logger>
<root level="info">
<appender-ref ref="Console" />
</root>
</configuration>

@ -0,0 +1,4 @@
ftp.server.ip=111.231.119.253
ftp.user=ftpuser
ftp.pass=123
ftp.server.http.prefix=http://img.oursnail.cn/

@ -0,0 +1,25 @@
/target/
!.mvn/wrapper/maven-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/build/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/

@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.njupt.swg</groupId>
<artifactId>spring-cloud-for-snailmall</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>snailmall-category-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>snailmall-category-service</name>
<description>Demo project for Spring Boot</description>
<dependencies>
<!--spring cloud相关-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--jackson-->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
</dependency>
<!--druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<!--util-->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
</dependency>
<!--MYSQL-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!--jedis-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
</dependencies>
<build>
<!--编译xml文件-->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,16 @@
package com.njupt.swg;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class SnailmallCategoryServiceApplication {
public static void main(String[] args) {
SpringApplication.run(SnailmallCategoryServiceApplication.class, args);
}
}

@ -0,0 +1,22 @@
package com.njupt.swg.common.constants;
/**
* @Author swg.
* @Date 2019/1/1 13:19
* @CONTACT 317758022@qq.com
* @DESC
*/
public class Constants {
/**自定义状态码 start**/
public static final int RESP_STATUS_OK = 200;
public static final int RESP_STATUS_NOAUTH = 401;
public static final int RESP_STATUS_INTERNAL_ERROR = 500;
public static final int RESP_STATUS_BADREQUEST = 400;
/**自定义状态码 end**/
}

@ -0,0 +1,33 @@
package com.njupt.swg.common.exception;
import com.njupt.swg.common.constants.Constants;
import com.njupt.swg.common.resp.ServerResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @Author swg.
* @Date 2019/1/1 13:21
* @CONTACT 317758022@qq.com
* @DESC
*/
@ControllerAdvice
@ResponseBody
@Slf4j
public class ExceptionHandlerAdvice {
@ExceptionHandler(Exception.class)
public ServerResponse handleException(Exception e){
log.error(e.getMessage(),e);
return ServerResponse.createByErrorCodeMessage(Constants.RESP_STATUS_INTERNAL_ERROR,"系统异常,请稍后再试");
}
@ExceptionHandler(SnailmallException.class)
public ServerResponse handleException(SnailmallException e){
log.error(e.getMessage(),e);
return ServerResponse.createByErrorCodeMessage(e.getExceptionStatus(),e.getMessage());
}
}

@ -0,0 +1,25 @@
package com.njupt.swg.common.exception;
import com.njupt.swg.common.resp.ResponseEnum;
import lombok.Getter;
/**
* @Author swg.
* @Date 2019/1/1 13:18
* @CONTACT 317758022@qq.com
* @DESC
*/
@Getter
public class SnailmallException extends RuntimeException{
private int exceptionStatus = ResponseEnum.ERROR.getCode();
public SnailmallException(String msg){
super(msg);
}
public SnailmallException(int code,String msg){
super(msg);
exceptionStatus = code;
}
}

@ -0,0 +1,25 @@
package com.njupt.swg.common.resp;
import lombok.Getter;
/**
* @Author swg.
* @Date 2018/12/31 20:15
* @CONTACT 317758022@qq.com
* @DESC
*/
@Getter
public enum ResponseEnum {
SUCCESS(0,"SUCCESS"),
ERROR(1,"ERROR"),
ILLEGAL_ARGUMENTS(2,"ILLEGAL_ARGUMENTS"),
NEED_LOGIN(10,"NEED_LOGIN");
private int code;
private String desc;
ResponseEnum(int code,String desc){
this.code = code;
this.desc = desc;
}
}

@ -0,0 +1,78 @@
package com.njupt.swg.common.resp;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @Author swg.
* @Date 2018/12/31 20:11
* @CONTACT 317758022@qq.com
* @DESC
*/
@Getter
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
public class ServerResponse<T> implements Serializable {
private int status;
private String msg;
private T data;
public ServerResponse(){}
public ServerResponse(int status){
this.status = status;
}
public ServerResponse(int status,String msg){
this.status = status;
this.msg = msg;
}
public ServerResponse(int status,T data){
this.status = status;
this.data = data;
}
public ServerResponse(int status,String msg,T data){
this.status = status;
this.msg = msg;
this.data = data;
}
@JsonIgnore
public boolean isSuccess(){
return this.status == ResponseEnum.SUCCESS.getCode();
}
/**
*
*/
public static <T>ServerResponse<T> createBySuccess(){
return new ServerResponse<>(ResponseEnum.SUCCESS.getCode(),ResponseEnum.SUCCESS.getDesc());
}
public static <T>ServerResponse<T> createBySuccessMessage(String message){
return new ServerResponse<>(ResponseEnum.SUCCESS.getCode(),message);
}
public static <T>ServerResponse<T> createBySuccess(T data){
return new ServerResponse<>(ResponseEnum.SUCCESS.getCode(),data);
}
public static <T>ServerResponse<T> createBySuccess(String message,T data){
return new ServerResponse<>(ResponseEnum.SUCCESS.getCode(),message,data);
}
/**
*
*/
public static <T>ServerResponse<T> createByError(){
return new ServerResponse<>(ResponseEnum.ERROR.getCode(),ResponseEnum.ERROR.getDesc());
}
public static <T>ServerResponse<T> createByErrorMessage(String msg){
return new ServerResponse<>(ResponseEnum.ERROR.getCode(),msg);
}
public static <T>ServerResponse<T> createByErrorCodeMessage(int code,String msg){
return new ServerResponse<>(code,msg);
}
}

@ -0,0 +1,72 @@
package com.njupt.swg.controller;
import com.njupt.swg.common.resp.ServerResponse;
import com.njupt.swg.service.ICategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author swg.
* @Date 2019/1/2 12:57
* @CONTACT 317758022@qq.com
* @DESC
*/
//TODO 这里首先实现业务 关于这里重复的鉴权,后面将会移植到网关中统一去做
//TODO 先开放GET请求
@RestController
@RequestMapping("/manage/category/")
public class CategoryController {
@Autowired
private ICategoryService categoryService;
/**
* ()
*/
@RequestMapping("get_category.do")
public ServerResponse getCategory(@RequestParam(value = "categoryId",defaultValue = "0") Integer categoryId){
ServerResponse response = categoryService.getCategory(categoryId);
return response;
}
/**
*
*/
@RequestMapping("add_category.do")
public ServerResponse addCategory(String categoryName, @RequestParam(value = "parentId",defaultValue = "0")int parentId){
ServerResponse response = categoryService.addCategory(categoryName,parentId);
return response;
}
/**
*
*/
@RequestMapping("set_category_name.do")
public ServerResponse<String> set_category_name(String categoryName,Integer categoryId){
return categoryService.updateCategoryName(categoryName,categoryId);
}
/**
*
*/
@RequestMapping("get_deep_category.do")
public ServerResponse get_deep_category(@RequestParam(value = "categoryId",defaultValue = "0") Integer categoryId){
return categoryService.selectCategoryAndDeepChildrenById(categoryId);
}
/**
*
*/
@RequestMapping("get_category_detail.do")
public ServerResponse get_category_detail(Integer categoryId){
return categoryService.getCategoryDetail(categoryId);
}
}

@ -0,0 +1,24 @@
package com.njupt.swg.dao;
import com.njupt.swg.entity.Category;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface CategoryMapper {
int deleteByPrimaryKey(Integer id);
int insert(Category record);
int insertSelective(Category record);
Category selectByPrimaryKey(Integer id);
int updateByPrimaryKeySelective(Category record);
int updateByPrimaryKey(Category record);
List<Category> selectCategoryChildrenByParentId(Integer categoryId);
}

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.njupt.swg.dao.CategoryMapper" >
<resultMap id="BaseResultMap" type="com.njupt.swg.entity.Category" >
<constructor >
<idArg column="id" jdbcType="INTEGER" javaType="java.lang.Integer" />
<arg column="parent_id" jdbcType="INTEGER" javaType="java.lang.Integer" />
<arg column="name" jdbcType="VARCHAR" javaType="java.lang.String" />
<arg column="status" jdbcType="BIT" javaType="java.lang.Boolean" />
<arg column="sort_order" jdbcType="INTEGER" javaType="java.lang.Integer" />
<arg column="create_time" jdbcType="TIMESTAMP" javaType="java.util.Date" />
<arg column="update_time" jdbcType="TIMESTAMP" javaType="java.util.Date" />
</constructor>
</resultMap>
<sql id="Base_Column_List" >
id, parent_id, name, status, sort_order, create_time, update_time
</sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
<include refid="Base_Column_List" />
from mmall_category
where id = #{id,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
delete from mmall_category
where id = #{id,jdbcType=INTEGER}
</delete>
<insert id="insert" parameterType="com.njupt.swg.entity.Category" >
insert into mmall_category (id, parent_id, name,
status, sort_order, create_time,
update_time)
values (#{id,jdbcType=INTEGER}, #{parentId,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR},
#{status,jdbcType=BIT}, #{sortOrder,jdbcType=INTEGER}, now(),
now())
</insert>
<insert id="insertSelective" parameterType="com.njupt.swg.entity.Category" >
insert into mmall_category
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="id != null" >
id,
</if>
<if test="parentId != null" >
parent_id,
</if>
<if test="name != null" >
name,
</if>
<if test="status != null" >
status,
</if>
<if test="sortOrder != null" >
sort_order,
</if>
<if test="createTime != null" >
create_time,
</if>
<if test="updateTime != null" >
update_time,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="id != null" >
#{id,jdbcType=INTEGER},
</if>
<if test="parentId != null" >
#{parentId,jdbcType=INTEGER},
</if>
<if test="name != null" >
#{name,jdbcType=VARCHAR},
</if>
<if test="status != null" >
#{status,jdbcType=BIT},
</if>
<if test="sortOrder != null" >
#{sortOrder,jdbcType=INTEGER},
</if>
<if test="createTime != null" >
now(),
</if>
<if test="updateTime != null" >
now(),
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="com.njupt.swg.entity.Category" >
update mmall_category
<set >
<if test="parentId != null" >
parent_id = #{parentId,jdbcType=INTEGER},
</if>
<if test="name != null" >
name = #{name,jdbcType=VARCHAR},
</if>
<if test="status != null" >
status = #{status,jdbcType=BIT},
</if>
<if test="sortOrder != null" >
sort_order = #{sortOrder,jdbcType=INTEGER},
</if>
<if test="createTime != null" >
create_time = #{createTime,jdbcType=TIMESTAMP},
</if>
<if test="updateTime != null" >
update_time = now(),
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey" parameterType="com.njupt.swg.entity.Category" >
update mmall_category
set parent_id = #{parentId,jdbcType=INTEGER},
name = #{name,jdbcType=VARCHAR},
status = #{status,jdbcType=BIT},
sort_order = #{sortOrder,jdbcType=INTEGER},
create_time = #{createTime,jdbcType=TIMESTAMP},
update_time = now()
where id = #{id,jdbcType=INTEGER}
</update>
<select id="selectCategoryChildrenByParentId" parameterType="int" resultMap="BaseResultMap">
SELECT <include refid="Base_Column_List"/> from mmall_category where parent_id = #{categoryId}
</select>
</mapper>

@ -0,0 +1,26 @@
package com.njupt.swg.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Category {
private Integer id;
private Integer parentId;
private String name;
private Boolean status;
private Integer sortOrder;
private Date createTime;
private Date updateTime;
}

@ -0,0 +1,43 @@
package com.njupt.swg.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.io.Serializable;
import java.util.Date;
/**
* @Author swg.
* @Date 2018/12/31 21:01
* @CONTACT 317758022@qq.com
* @DESC
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class User implements Serializable {
private Integer id;
private String username;
private String password;
private String email;
private String phone;
private String question;
private String answer;
//角色0-管理员,1-普通用户
private Integer role;
private Date createTime;
private Date updateTime;
}

@ -0,0 +1,130 @@
package com.njupt.swg.service;
import com.google.common.collect.Sets;
import com.njupt.swg.common.exception.SnailmallException;
import com.njupt.swg.common.resp.ServerResponse;
import com.njupt.swg.dao.CategoryMapper;
import com.njupt.swg.entity.Category;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* @Author swg.
* @Date 2019/1/2 12:54
* @CONTACT 317758022@qq.com
* @DESC
*/
@Service
@Slf4j
public class CategoryServiceImpl implements ICategoryService{
@Autowired
private CategoryMapper categoryMapper;
@Override
public ServerResponse getCategory(Integer categoryId) {
//1.校验参数
if(categoryId == null){
throw new SnailmallException("未找到该品类");
}
//2.根据父亲id获取这个父亲下一级所有子ID
List<Category> categoryList = categoryMapper.selectCategoryChildrenByParentId(categoryId);
if(CollectionUtils.isEmpty(categoryList)){
log.info("该节点下没有任何子节点");
}
return ServerResponse.createBySuccess(categoryList);
}
@Override
public ServerResponse addCategory(String categoryName, int parentId) {
//1.校验参数
if(StringUtils.isBlank(categoryName)){
throw new SnailmallException("品类名字不能为空");
}
//2.创建类目
Category category = new Category();
category.setName(categoryName);
category.setParentId(parentId);
category.setStatus(true);
int resultCount = categoryMapper.insert(category);
if(resultCount > 0){
return ServerResponse.createBySuccessMessage("添加品类成功");
}
return ServerResponse.createByErrorMessage("添加品类失败");
}
@Override
public ServerResponse<String> updateCategoryName(String categoryName, Integer categoryId) {
//1.校验参数
if(StringUtils.isBlank(categoryName)){
throw new SnailmallException("品类名字不能为空");
}
//2.根据id获取品类
Category tmpCat = categoryMapper.selectByPrimaryKey(categoryId);
if(tmpCat == null){
throw new SnailmallException("品类不存在");
}
//3.更新品类名称
Category category = new Category();
category.setId(categoryId);
category.setName(categoryName);
int resultCount = categoryMapper.updateByPrimaryKeySelective(category);
if(resultCount > 0){
return ServerResponse.createBySuccessMessage("更新品类名称成功");
}
return ServerResponse.createByErrorMessage("更新品类名称失败");
}
@Override
public ServerResponse selectCategoryAndDeepChildrenById(Integer categoryId) {
//1、创建一个空Set用来存放不重复的品类对象--去重
Set<Category> categorySet = Sets.newHashSet();
//2、递归获取所有的子节点儿子、孙子、等等包括自己也添加进去
findChildCategory(categorySet,categoryId);
//3、将递归获取到的品类id取出来放进list中
List<Integer> categoryIdList = new ArrayList<>();
if(categoryId != null){
for(Category category:categorySet){
categoryIdList.add(category.getId());
}
}
return ServerResponse.createBySuccess(categoryIdList);
}
private Set<Category> findChildCategory(Set<Category> categorySet,Integer categoryId){
//4、如果自己不为空的话首先把自己添加进去如果自己为空这个递归分支就结束所以也是一个停止条件
Category category = categoryMapper.selectByPrimaryKey(categoryId);
if(category != null){
categorySet.add(category);
}
//5、根据父亲id获取下一级所有品类即先获取儿子们
List<Category> categoryList = categoryMapper.selectCategoryChildrenByParentId(categoryId);
//6、根据每一个儿子再获取儿子的儿子们递归下去
for(Category categoryItem:categoryList){
findChildCategory(categorySet,categoryItem.getId());
}
return categorySet;
}
@Override
public ServerResponse getCategoryDetail(Integer categoryId) {
if(categoryId == null){
return ServerResponse.createByErrorMessage("参数不能为空");
}
Category category = categoryMapper.selectByPrimaryKey(categoryId);
if(category == null){
return ServerResponse.createByErrorMessage("品类不存在");
}
return ServerResponse.createBySuccess(category);
}
}

@ -0,0 +1,29 @@
package com.njupt.swg.service;
import com.njupt.swg.common.resp.ServerResponse;
import com.njupt.swg.entity.Category;
/**
* @Author swg.
* @Date 2019/1/2 12:54
* @CONTACT 317758022@qq.com
* @DESC
*/
public interface ICategoryService {
/** 根据类目id获取其下面所有的一级子类目 **/
ServerResponse getCategory(Integer categoryId);
/** 新建一个商品类目 **/
ServerResponse addCategory(String categoryName, int parentId);
/** 更新品类名称 **/
ServerResponse<String> updateCategoryName(String categoryName, Integer categoryId);
/** 递归查询出所有品类 **/
ServerResponse selectCategoryAndDeepChildrenById(Integer categoryId);
/** 被其他服务调用的接口 **/
ServerResponse getCategoryDetail(Integer categoryId);
}

@ -0,0 +1,43 @@
eureka:
client:
service-url:
defaultZone: http://111.231.119.253:8761/eureka
spring:
zipkin:
sender:
type: web
application:
name: category-service
cloud:
config:
discovery:
enabled: true
service-id: SNAILMALL-CONFIG-SERVER
profile: dev
bus:
trace:
enabled: true
enabled: true
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
filters: stat
maxActive: 20
initialSize: 1
maxWait: 60000
minIdle: 1
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: select 'x'
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxOpenPreparedStatements: 20
server:
port: 8082
logging:
config: classpath:logback.xml
mybatis:
mapper-locations: classpath:com/njupt/swg/**/**.xml
type-aliases-package: classpath:com.njupt.swg.**.entity

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="LOG_HOME" value="/logs/category/" />
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{H:mm} %-5level [%logger{16}] %msg%n</pattern>
</encoder>
</appender>
<appender name="normalLog"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${LOG_HOME}/web.normal.%d{yyyy-MM-dd}.log
</FileNamePattern>
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>10MB</maxFileSize>
</triggeringPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{16} - %msg%n
</pattern>
</layout>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>DENY</onMatch>
<onMismatch>ACCEPT</onMismatch>
</filter>
</appender>
<appender name="errorLog"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${LOG_HOME}/web.error.%d{yyyy-MM-dd}.log
</FileNamePattern>
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>10MB</maxFileSize>
</triggeringPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{16} - %msg%n
</pattern>
</layout>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<logger name="com.oursnail" level="debug" >
<appender-ref ref="normalLog" />
<appender-ref ref="errorLog" />
</logger>
<root level="info">
<appender-ref ref="Console" />
</root>
</configuration>

@ -0,0 +1,25 @@
/target/
!.mvn/wrapper/maven-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/build/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.njupt.swg</groupId>
<artifactId>spring-cloud-for-snailmall</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>snailmall-config-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>snailmall-config-server</name>
<description>配置中心+自动刷新</description>
<packaging>jar</packaging>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-monitor</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,18 @@
package com.njupt.swg;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.config.server.EnableConfigServer;
@SpringBootApplication
@EnableDiscoveryClient
@EnableConfigServer
public class SnailmallConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(SnailmallConfigServerApplication.class, args);
}
}

@ -0,0 +1,34 @@
spring:
application:
name: snailmall-config-server
rabbitmq:
host: 127.0.0.1
port: 5672
username: root
password: root
cloud:
config:
server:
git:
uri: https://github.com/sunweiguo/config-center-for-snailmall
username: sunweiguo
password: xxxxxxxxx
search-paths: user-service-config,category-service-config,product-service-config,order-service-config,keygen-service-config,shipping-service-config,cart-service-config,gateway-service-config
bus:
trace:
enabled: true
enabled: true
server:
port: 8079
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
instance:
ip-address: 111.231.119.253
prefer-ip-address: true
management:
endpoints:
web:
exposure:
include: bus-refresh

@ -0,0 +1,25 @@
/target/
!.mvn/wrapper/maven-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/build/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.njupt.swg</groupId>
<artifactId>spring-cloud-for-snailmall</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>snailmall-eureka-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>snailmall-eureka-server</name>
<description>服务注册中心</description>
<packaging>jar</packaging>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,16 @@
package com.njupt.swg;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class SnailmallEurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(SnailmallEurekaServerApplication.class, args);
}
}

@ -0,0 +1,11 @@
server:
port: 8761
spring:
application:
name: snailmall-eureka-server-2
eureka:
client:
service-url:
defaultZone: http://111.231.119.253:8761/eureka
server:
enable-self-preservation: false

@ -0,0 +1,25 @@
/target/
!.mvn/wrapper/maven-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/build/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.njupt.swg</groupId>
<artifactId>spring-cloud-for-snailmall</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>snailmall-keygen-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>snailmall-keygen-service</name>
<description>全局唯一ID生产服务-雪花算法</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,16 @@
package com.njupt.swg;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class SnailmallKeygenServiceApplication {
public static void main(String[] args) {
SpringApplication.run(SnailmallKeygenServiceApplication.class, args);
}
}

@ -0,0 +1,11 @@
package com.njupt.swg.keygen;
/**
* @Author swg.
* @Date 2019/1/6 21:43
* @CONTACT 317758022@qq.com
* @DESC
*/
public interface KeyGenerator {
Number generateKey();
}

@ -0,0 +1,93 @@
package com.njupt.swg.keygen;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import com.google.common.base.Preconditions;
/**
* @Author swg.
* @Date 2019/1/6 21:44
* @CONTACT 317758022@qq.com
* @DESC
*/
@Slf4j
@Service("snowFlakeKeyGenerator")
public class SnowFlakeKeyGenerator implements KeyGenerator{
@Autowired
private WorkerIDSenquence workerIDSenquence;
public static final long EPOCH;
private static final long SEQUENCE_BITS = 12L;
private static final long WORKER_ID_BITS = 10L;
private static final long SEQUENCE_MASK = 4095L;
private static final long WORKER_ID_LEFT_SHIFT_BITS = 12L;
private static final long TIMESTAMP_LEFT_SHIFT_BITS = 22L;
private static final long WORKER_ID_MAX_VALUE = 1024L;
private static TimeService timeService = new TimeService();
private static long workerId;
private long sequence;
private long lastTime;
public SnowFlakeKeyGenerator() {
}
/**
* workerID ZK
*/
@PostConstruct
public void initWorkerId() throws Exception {
long workerID = workerIDSenquence.getSequence(null);
Preconditions.checkArgument(workerID >= 0L && workerID < 1024L);
workerId = workerID;
}
public synchronized Number generateKey() {
long currentMillis = timeService.getCurrentMillis();
Preconditions.checkState(this.lastTime <= currentMillis, "Clock is moving backwards, last time is %d milliseconds, current time is %d milliseconds", new Object[]{Long.valueOf(this.lastTime), Long.valueOf(currentMillis)});
if(this.lastTime == currentMillis) {
if(0L == (this.sequence = ++this.sequence & 4095L)) {
currentMillis = this.waitUntilNextTime(currentMillis);
}
} else {
this.sequence = 0L;
}
this.lastTime = currentMillis;
if(log.isDebugEnabled()) {
log.debug("{}-{}-{}", new Object[]{(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")).format(new Date(this.lastTime)), Long.valueOf(workerId), Long.valueOf(this.sequence)});
}
return Long.valueOf(currentMillis - EPOCH << 22 | workerId << 12 | this.sequence);
}
private long waitUntilNextTime(long lastTime) {
long time;
for(time = timeService.getCurrentMillis(); time <= lastTime; time = timeService.getCurrentMillis()) {
;
}
return time;
}
public static void setTimeService(TimeService timeService) {
timeService = timeService;
}
static {
Calendar calendar = Calendar.getInstance();
calendar.set(2016, 10, 1);
calendar.set(11, 0);
calendar.set(12, 0);
calendar.set(13, 0);
calendar.set(14, 0);
EPOCH = calendar.getTimeInMillis();
}
}

@ -0,0 +1,16 @@
package com.njupt.swg.keygen;
/**
* @Author swg.
* @Date 2019/1/6 21:45
* @CONTACT 317758022@qq.com
* @DESC
*/
public class TimeService {
public TimeService() {
}
public long getCurrentMillis() {
return System.currentTimeMillis();
}
}

@ -0,0 +1,52 @@
package com.njupt.swg.keygen;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.RetryNTimes;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
* ZK
*/
@Component
@Slf4j
public class WorkerIDSenquence {
@Value("${zk.host}")
private String ZkHost ;
private static final String ZK_PATH = "/snowflake/workID";
private static CuratorFramework client;
@PostConstruct
void initZKNode() throws Exception {
client = CuratorFrameworkFactory.newClient(ZkHost,new RetryNTimes(10, 5000));
client.start();
log.info("zk client start successfully!");
Stat stat = client.checkExists().forPath(ZK_PATH);
if (stat==null){
client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath(ZK_PATH);
}
}
public long getSequence(String hostname) throws Exception {
if(StringUtils.isBlank(hostname)){
hostname = "snowflake_";
}
String path = client.create().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath(ZK_PATH+"/"+hostname);
// snowflake_0000000000
long sequence = Long.valueOf(path.substring(path.length()-4,path.length()));
return sequence;
}
}

@ -0,0 +1,29 @@
package com.njupt.swg.web;
import com.njupt.swg.keygen.KeyGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author swg.
* @Date 2019/1/6 21:47
* @CONTACT 317758022@qq.com
* @DESC ID
*/
@RestController
@RequestMapping
public class KeyGeneratorController {
@Autowired
@Qualifier("snowFlakeKeyGenerator")
private KeyGenerator keyGenerator;
@RequestMapping("/keygen")
public String generateKey() throws Exception {
return String.valueOf(keyGenerator.generateKey().longValue());
}
}

@ -0,0 +1,28 @@
eureka:
client:
service-url:
defaultZone: http://111.231.119.253:8761/eureka
spring:
application:
name: keygen-service
zipkin:
base-url: http://106.14.163.235:9411
sender:
type: web
sleuth:
sampler:
probability: 1
cloud:
config:
discovery:
enabled: true
service-id: SNAILMALL-CONFIG-SERVER
profile: dev
bus:
trace:
enabled: true
enabled: true
server:
port: 8087
zk:
host: 111.231.119.253

@ -0,0 +1,25 @@
/target/
!.mvn/wrapper/maven-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/build/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/

@ -0,0 +1,151 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.njupt.swg</groupId>
<artifactId>spring-cloud-for-snailmall</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>snailmall-order-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>snailmall-order-service</name>
<description>订单服务</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--spring cloud相关-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--jackson-->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
</dependency>
<!--druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<!--util-->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
</dependency>
<!--MYSQL-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!--jedis-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!--joda time-->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
<!--分页-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
</dependency>
<dependency>
<groupId>com.github.miemiedev</groupId>
<artifactId>mybatis-paginator</artifactId>
</dependency>
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
</dependency>
<dependency>
<groupId>com.alipay</groupId>
<artifactId>sdk-java</artifactId>
</dependency>
<dependency>
<groupId>com.alipay</groupId>
<artifactId>trade-sdk</artifactId>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
</dependency>
</dependencies>
<build>
<!--编译xml文件-->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,62 @@
package com.njupt.swg;
import com.njupt.swg.cache.Parameters;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import redis.clients.jedis.JedisPoolConfig;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@EnableTransactionManagement
public class SnailmallOrderServiceApplication {
@Autowired
private Parameters parameters;
public static void main(String[] args) {
SpringApplication.run(SnailmallOrderServiceApplication.class, args);
}
/**
*
* @Description redistemplate
* */
@Bean
public RedisConnectionFactory redisConnectionFactory(){
JedisPoolConfig poolConfig=new JedisPoolConfig();
poolConfig.setTestOnBorrow(true);
poolConfig.setTestOnReturn(true);
poolConfig.setTestWhileIdle(true);
poolConfig.setNumTestsPerEvictionRun(10);
poolConfig.setTimeBetweenEvictionRunsMillis(60000);
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(poolConfig);
jedisConnectionFactory.setHostName(parameters.getRedisHost());
jedisConnectionFactory.setPort(parameters.getRedisPort());
jedisConnectionFactory.setPassword("xxx");
return jedisConnectionFactory;
}
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save