├── README.md ├── auth-service ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── mycat │ │ └── monoeshop │ │ ├── App.java │ │ ├── config │ │ └── MyAppConfig.java │ │ ├── mapper │ │ └── AccountMapper.java │ │ ├── model │ │ └── Account.java │ │ ├── rest │ │ └── AccountRestService.java │ │ └── service │ │ └── AccountService.java │ └── resources │ ├── application.yml │ ├── create-db.sql │ ├── demo-data.sql │ └── logback.xml ├── cart-service ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── mycat │ │ └── monoeshop │ │ ├── App.java │ │ ├── config │ │ └── MyAppConfig.java │ │ ├── model │ │ ├── Account.java │ │ ├── CartRecord.java │ │ ├── Product.java │ │ ├── Result.java │ │ └── ResultEnum.java │ │ ├── rest │ │ └── CartRestService.java │ │ └── service │ │ └── CartService.java │ └── resources │ ├── application.yml │ └── logback.xml ├── config └── zuul │ └── application.yml ├── eshop-web ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── mycat │ │ └── monoeshop │ │ ├── App.java │ │ ├── JacksonUtil.java │ │ ├── config │ │ ├── SecurityConfig.java │ │ └── SecurityInterceptor.java │ │ ├── controller │ │ ├── AccountController.java │ │ ├── CartController.java │ │ ├── Mainpage.java │ │ └── ProductController.java │ │ ├── model │ │ ├── Account.java │ │ ├── CartRecord.java │ │ ├── Product.java │ │ ├── Result.java │ │ └── ResultEnum.java │ │ └── service │ │ └── rest │ │ ├── AccountService.java │ │ ├── CartService.java │ │ ├── ProductService.java │ │ └── SessionService.java │ └── resources │ ├── application.yml │ ├── logback.xml │ └── static │ ├── cart.html │ ├── css │ ├── bootstrap-table.min.css │ ├── bootstrap-theme.min.css │ ├── bootstrap-theme.min.css.map │ ├── bootstrap.min.css │ ├── bootstrap.min.css.map │ ├── css │ ├── font-awesome.min.css │ ├── fontawesome-webfont.woff2 │ ├── form-elements.css │ ├── product.css │ ├── style-responsive.css │ └── style.css │ ├── detail.html │ ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 │ ├── img │ └── background.jpg │ ├── js │ ├── bootbox.min.js │ ├── bootstrap-table-locale-all.min.js │ ├── bootstrap-table.min.js │ ├── bootstrap.min.js │ ├── cart.js │ ├── detail.js │ ├── index.js │ ├── jquery-3.2.1.min.js │ ├── jquery.backstretch.min.js │ ├── json2.js │ ├── main.js │ ├── npm.js │ ├── product.js │ └── urlparam.js │ ├── login.html │ ├── main.html │ └── product.html ├── eureka-server ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── mycat │ │ └── monoeshop │ │ └── App.java │ └── resources │ ├── application.yml │ └── logback.xml ├── pom.xml ├── product-service ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── mycat │ │ └── monoeshop │ │ ├── App.java │ │ ├── config │ │ └── MyAppConfig.java │ │ ├── mapper │ │ └── ProductMapper.java │ │ ├── model │ │ └── Product.java │ │ ├── rest │ │ └── ProductRestService.java │ │ └── service │ │ └── ProductService.java │ └── resources │ ├── application.yml │ ├── create-db.sql │ ├── demo-data.sql │ └── logback.xml └── zuul-gateway ├── pom.xml └── src └── main ├── java └── com │ └── mycat │ └── monoeshop │ ├── App.java │ ├── config │ ├── FilterConfig.java │ └── MyAppConfig.java │ ├── controller │ └── SessionController.java │ ├── filter │ ├── JacksonUtil.java │ ├── LoginPostFilter.java │ └── SecurityPreFilter.java │ └── model │ ├── Account.java │ ├── Result.java │ └── ResultEnum.java └── resources ├── application.yml └── logback.xml /README.md: -------------------------------------------------------------------------------- 1 | # SpringCloud_eShop 2 | Spring Cloud架构的eshop工程代码 3 | -------------------------------------------------------------------------------- /auth-service/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | Springcloud_eShop 6 | Springcloud_eShop 7 | 0.0.1-SNAPSHOT 8 | 9 | sc_auth-service 10 | sc_auth-service 11 | jar 12 | 13 | 14 | org.mybatis.spring.boot 15 | mybatis-spring-boot-starter 16 | ${mybatis.version} 17 | 18 | 19 | 20 | com.alibaba 21 | druid 22 | ${druid.version} 23 | 24 | 25 | mysql 26 | mysql-connector-java 27 | 28 | 29 | 30 | 31 | eshop_sc_auth_service 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-maven-plugin 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/mycat/monoeshop/App.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 7 | 8 | /** 9 | * Desc: 10 | * 11 | * @date: 27/08/2017 12 | * @author: Leader us 13 | */ 14 | @SpringBootApplication 15 | @EnableDiscoveryClient 16 | @MapperScan("com.mycat.monoeshop.mapper") 17 | public class App { 18 | 19 | public static void main(String[] args) { 20 | SpringApplication.run(App.class, args); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/mycat/monoeshop/config/MyAppConfig.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.config; 2 | 3 | import javax.sql.DataSource; 4 | 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | import org.springframework.cache.annotation.CachingConfigurerSupport; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | import com.alibaba.druid.pool.DruidDataSource; 11 | 12 | /** 13 | * Desc: 14 | * 15 | * @date: 27/08/2017 16 | * @author: Leader us 17 | */ 18 | @Configuration 19 | public class MyAppConfig extends CachingConfigurerSupport { 20 | 21 | @Configuration 22 | public class DruidDataSourceConfig { 23 | @Bean 24 | @ConfigurationProperties(prefix = "spring.datasource") 25 | public DataSource druidDataSource() { 26 | DruidDataSource druidDataSource = new DruidDataSource(); 27 | return druidDataSource; 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/mycat/monoeshop/mapper/AccountMapper.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.mapper; 2 | 3 | 4 | import org.apache.ibatis.annotations.Param; 5 | import org.apache.ibatis.annotations.Select; 6 | 7 | import com.mycat.monoeshop.model.Account; 8 | 9 | /** 10 | * Desc: 11 | * 12 | * @date: 27/08/2017 13 | * @author: Leader us 14 | */ 15 | public interface AccountMapper { 16 | @Select("select * from account where name=#{name,jdbcType=VARCHAR} and password=#{password,jdbcType=VARCHAR}") 17 | Account getAccountByNameAndPwd(@Param("name") String name, @Param("password") String password); 18 | } 19 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/mycat/monoeshop/model/Account.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.model; 2 | 3 | /** 4 | * Desc: 5 | * 6 | * @date: 27/08/2017 7 | * @author: Leader us 8 | */ 9 | public class Account { 10 | private String name; 11 | private String password; 12 | 13 | public String getName() { 14 | return name; 15 | } 16 | 17 | public void setName(String name) { 18 | this.name = name; 19 | } 20 | 21 | public String getPassword() { 22 | return password; 23 | } 24 | 25 | public void setPassword(String password) { 26 | this.password = password; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/mycat/monoeshop/rest/AccountRestService.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.rest; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RequestMethod; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | import com.mycat.monoeshop.model.Account; 11 | import com.mycat.monoeshop.service.AccountService; 12 | 13 | /** 14 | * Desc: 15 | * 16 | * @date: 27/08/2017 17 | * @author: Leader us 18 | */ 19 | @RestController 20 | @RequestMapping("/account") 21 | public class AccountRestService { 22 | @Autowired 23 | private AccountService accountService; 24 | 25 | @RequestMapping(value = "login", method = RequestMethod.POST) 26 | public Account login(HttpServletRequest request, String username, String password) { 27 | Account accont = accountService.login(username, password); 28 | return accont; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/mycat/monoeshop/service/AccountService.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.service; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Service; 7 | 8 | import com.mycat.monoeshop.mapper.AccountMapper; 9 | import com.mycat.monoeshop.model.Account; 10 | 11 | /** 12 | * Desc: 13 | * 14 | * @date: 27/08/2017 15 | * @author: Leader us 16 | */ 17 | @Service 18 | public class AccountService { 19 | private static final Logger LOGGER = LoggerFactory.getLogger(AccountService.class); 20 | 21 | @Autowired 22 | private AccountMapper accountMapper; 23 | 24 | public Account login(String username, String password) { 25 | LOGGER.info("account login, username: {}, password: {}", username, password); 26 | return accountMapper.getAccountByNameAndPwd(username, password); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /auth-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: eshop-auth-service 4 | datasource: 5 | type: com.alibaba.druid.pool.DruidDataSource 6 | url: jdbc:mysql://192.168.18.134:3306/HPE_APP?useSSL=false 7 | username: lession 8 | password: mypass 9 | driver-class-name: com.mysql.jdbc.Driver 10 | initialSize: 2 11 | minIdle: 2 12 | maxActive: 20 13 | maxWait: 60000 14 | timeBetweenEvictionRunsMillis: 60000 15 | minEvictableIdleTimeMillis: 300000 16 | validationQuery: SELECT 1 FROM DUAL 17 | testWhileIdle: true 18 | testOnBorrow: true 19 | testOnReturn: false 20 | poolPreparedStatements: true 21 | maxPoolPreparedStatementPerConnectionSize: 20 22 | schema: classpath:create-db.sql 23 | data: classpath:demo-data.sql 24 | initialize: true 25 | continueOnError: true 26 | info: 27 | app: 28 | name: ${spring.application.name} 29 | version: v1.0.0 30 | server: 31 | port: 8034 32 | context-path: / 33 | tomcat: 34 | uri-encoding: UTF-8 35 | logging: 36 | config: classpath:logback.xml 37 | eureka: 38 | instance: 39 | hostname: 127.0.0.1 40 | prefer-ip-address: true 41 | client: 42 | healthcheck: 43 | enabled: true 44 | registerWithEureka: true 45 | fetchRegistry: true 46 | service-url: 47 | defaultZone: http://127.0.0.1:8030/eureka/ 48 | 49 | -------------------------------------------------------------------------------- /auth-service/src/main/resources/create-db.sql: -------------------------------------------------------------------------------- 1 | --创建account表 2 | CREATE TABLE IF NOT EXISTS `account`( 3 | `name` VARCHAR(20), 4 | `password` VARCHAR(20) NOT NULL, 5 | PRIMARY KEY ( `name` ) 6 | )ENGINE=InnoDB DEFAULT CHARSET=utf8; 7 | -------------------------------------------------------------------------------- /auth-service/src/main/resources/demo-data.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO account VALUES ('guest','111111'); 2 | 3 | -------------------------------------------------------------------------------- /auth-service/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /cart-service/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | Springcloud_eShop 6 | Springcloud_eShop 7 | 0.0.1-SNAPSHOT 8 | 9 | sc_cart-service 10 | sc_cart-service 11 | jar 12 | 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-data-redis 17 | 18 | 19 | com.fasterxml.jackson.core 20 | jackson-core 21 | 22 | 23 | com.fasterxml.jackson.core 24 | jackson-annotations 25 | 26 | 27 | com.fasterxml.jackson.core 28 | jackson-databind 29 | 30 | 31 | 32 | 33 | 34 | eshop_sc_cart-service 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-maven-plugin 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /cart-service/src/main/java/com/mycat/monoeshop/App.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | 7 | /** 8 | * Desc: 9 | * 10 | * @date: 27/08/2017 11 | * @author: Leader us 12 | */ 13 | @SpringBootApplication 14 | @EnableDiscoveryClient 15 | public class App { 16 | 17 | public static void main(String[] args) { 18 | SpringApplication.run(App.class, args); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /cart-service/src/main/java/com/mycat/monoeshop/config/MyAppConfig.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.config; 2 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 3 | import com.fasterxml.jackson.annotation.PropertyAccessor; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | 6 | import javax.sql.DataSource; 7 | 8 | import org.springframework.boot.context.properties.ConfigurationProperties; 9 | import org.springframework.cache.CacheManager; 10 | import org.springframework.cache.annotation.CachingConfigurerSupport; 11 | import org.springframework.context.annotation.Bean; 12 | import org.springframework.context.annotation.Configuration; 13 | import org.springframework.data.redis.cache.RedisCacheManager; 14 | import org.springframework.data.redis.connection.RedisConnectionFactory; 15 | import org.springframework.data.redis.core.RedisTemplate; 16 | import org.springframework.data.redis.core.StringRedisTemplate; 17 | import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; 18 | import org.springframework.data.redis.serializer.RedisSerializer; 19 | import org.springframework.data.redis.serializer.StringRedisSerializer; 20 | 21 | /** 22 | * Desc: 23 | * 24 | * @date: 27/08/2017 25 | * @author: Leader us 26 | */ 27 | @Configuration 28 | public class MyAppConfig extends CachingConfigurerSupport { 29 | 30 | @Bean 31 | public CacheManager cacheManager(RedisTemplate redisTemplate) { 32 | RedisCacheManager rcm = new RedisCacheManager(redisTemplate); 33 | // 设置缓存过期时间 34 | // rcm.setDefaultExpiration(60);//秒 35 | return rcm; 36 | 37 | } 38 | 39 | /** 40 | * RedisTemplate配置 41 | */ 42 | @Bean 43 | public RedisTemplate redisTemplate(RedisConnectionFactory factory) { 44 | StringRedisTemplate template = new StringRedisTemplate(factory); 45 | // 定义key序列化方式 46 | RedisSerializer redisSerializer = new StringRedisSerializer();// Long类型会出现异常信息;需要我们上面的自定义key生成策略,一般没必要 47 | // 定义value的序列化方式 48 | Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); 49 | ObjectMapper om = new ObjectMapper(); 50 | om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); 51 | om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); 52 | jackson2JsonRedisSerializer.setObjectMapper(om); 53 | 54 | template.setKeySerializer(jackson2JsonRedisSerializer); 55 | template.setValueSerializer(jackson2JsonRedisSerializer); 56 | template.setHashKeySerializer(jackson2JsonRedisSerializer); 57 | template.setHashValueSerializer(jackson2JsonRedisSerializer); 58 | template.afterPropertiesSet(); 59 | return template; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /cart-service/src/main/java/com/mycat/monoeshop/model/Account.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.model; 2 | 3 | /** 4 | * Desc: 5 | * 6 | * @date: 27/08/2017 7 | * @author: Leader us 8 | */ 9 | public class Account { 10 | private String name; 11 | private String password; 12 | 13 | public String getName() { 14 | return name; 15 | } 16 | 17 | public void setName(String name) { 18 | this.name = name; 19 | } 20 | 21 | public String getPassword() { 22 | return password; 23 | } 24 | 25 | public void setPassword(String password) { 26 | this.password = password; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /cart-service/src/main/java/com/mycat/monoeshop/model/CartRecord.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.model; 2 | 3 | import java.math.BigDecimal; 4 | import java.util.Date; 5 | 6 | /** 7 | * Desc: 8 | * 9 | * @date: 27/08/2017 10 | * @author: Leader us 11 | */ 12 | public class CartRecord { 13 | private Integer productId; 14 | private String productName; 15 | private BigDecimal productPrice; 16 | private String username; 17 | private Date time; 18 | private Integer count; 19 | 20 | public Integer getProductId() { 21 | return productId; 22 | } 23 | 24 | public void setProductId(Integer productId) { 25 | this.productId = productId; 26 | } 27 | 28 | public String getProductName() { 29 | return productName; 30 | } 31 | 32 | public void setProductName(String productName) { 33 | this.productName = productName; 34 | } 35 | 36 | public BigDecimal getProductPrice() { 37 | return productPrice; 38 | } 39 | 40 | public void setProductPrice(BigDecimal productPrice) { 41 | this.productPrice = productPrice; 42 | } 43 | 44 | public String getUsername() { 45 | return username; 46 | } 47 | 48 | public void setUsername(String username) { 49 | this.username = username; 50 | } 51 | 52 | public Date getTime() { 53 | return time; 54 | } 55 | 56 | public void setTime(Date time) { 57 | this.time = time; 58 | } 59 | 60 | public Integer getCount() { 61 | return count; 62 | } 63 | 64 | public void setCount(Integer count) { 65 | this.count = count; 66 | } 67 | 68 | @Override 69 | public String toString() { 70 | return "CartRecord{" + 71 | "productId='" + productId + '\'' + 72 | ", productName='" + productName + '\'' + 73 | ", productPrice=" + productPrice + 74 | ", username='" + username + '\'' + 75 | ", time=" + time + 76 | ", count=" + count + 77 | '}'; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /cart-service/src/main/java/com/mycat/monoeshop/model/Product.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.model; 2 | 3 | import java.math.BigDecimal; 4 | 5 | /** 6 | * Desc: 7 | * 8 | * @date: 27/08/2017 9 | * @author: Leader us 10 | */ 11 | public class Product { 12 | private Integer id; 13 | private String name; 14 | private BigDecimal price; 15 | private String desc; 16 | 17 | public Integer getId() { 18 | return id; 19 | } 20 | 21 | public void setId(Integer id) { 22 | this.id = id; 23 | } 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | 29 | public void setName(String name) { 30 | this.name = name; 31 | } 32 | 33 | public BigDecimal getPrice() { 34 | return price; 35 | } 36 | 37 | public void setPrice(BigDecimal price) { 38 | this.price = price; 39 | } 40 | 41 | public String getDesc() { 42 | return desc; 43 | } 44 | 45 | public void setDesc(String desc) { 46 | this.desc = desc; 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | return "Product{" + 52 | "id=" + id + 53 | ", name='" + name + '\'' + 54 | ", price=" + price + 55 | ", desc='" + desc + '\'' + 56 | '}'; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /cart-service/src/main/java/com/mycat/monoeshop/model/Result.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.model; 2 | 3 | /** 4 | * Desc: 5 | * 6 | * @date: 27/08/2017 7 | * @author: Leader us 8 | */ 9 | public class Result { 10 | private int code; 11 | private String desc; 12 | private T data; 13 | 14 | public Result() 15 | { 16 | 17 | } 18 | public Result(ResultEnum resultEnum) { 19 | this.code = resultEnum.getCode(); 20 | this.desc = resultEnum.getDesc(); 21 | } 22 | 23 | public Result(ResultEnum resultEnum, T data) { 24 | this.code = resultEnum.getCode(); 25 | this.desc = resultEnum.getDesc(); 26 | this.data = data; 27 | } 28 | 29 | public int getCode() { 30 | return code; 31 | } 32 | 33 | public void setCode(int code) { 34 | this.code = code; 35 | } 36 | 37 | public String getDesc() { 38 | return desc; 39 | } 40 | 41 | public void setDesc(String desc) { 42 | this.desc = desc; 43 | } 44 | 45 | public T getData() { 46 | return data; 47 | } 48 | 49 | public void setData(T data) { 50 | this.data = data; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /cart-service/src/main/java/com/mycat/monoeshop/model/ResultEnum.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.model; 2 | 3 | /** 4 | * Desc: 5 | * 6 | * @date: 27/08/2017 7 | * @author: Leader us 8 | */ 9 | public enum ResultEnum { 10 | SUCCESS(200, "success"), ERROR(502, "error"), NOT_LOGIN(503, "not login"); 11 | 12 | private int code; 13 | private String desc; 14 | 15 | ResultEnum(int code, String desc) { 16 | this.code = code; 17 | this.desc = desc; 18 | } 19 | 20 | public int getCode() { 21 | return code; 22 | } 23 | 24 | public String getDesc() { 25 | return desc; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /cart-service/src/main/java/com/mycat/monoeshop/rest/CartRestService.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.rest; 2 | 3 | import java.util.List; 4 | import java.util.stream.Stream; 5 | 6 | import javax.servlet.http.HttpServletRequest; 7 | 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.web.bind.annotation.RequestBody; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.bind.annotation.RestController; 14 | 15 | import com.mycat.monoeshop.model.CartRecord; 16 | import com.mycat.monoeshop.model.Result; 17 | import com.mycat.monoeshop.service.CartService; 18 | 19 | /** 20 | * Desc: 21 | * 22 | * @date: 27/08/2017 23 | * @author: Leader us 24 | */ 25 | @RestController() 26 | @RequestMapping("/cart") 27 | public class CartRestService { 28 | private static final Logger LOGGER = LoggerFactory.getLogger(CartRestService.class); 29 | @Autowired 30 | private CartService cartService; 31 | 32 | @RequestMapping("records") 33 | public List getProductsByUsername(HttpServletRequest request) { 34 | LOGGER.info("get cart for user " + request.getSession().getId()); 35 | Stream.of(request.getCookies()).forEach(a -> { 36 | System.out.println("yyy cookie " + a.getName() + " " + a.getValue()); 37 | }); 38 | String userName = request.getHeader("accountName"); 39 | LOGGER.info("get cart for user " + userName); 40 | return cartService.getProductsByUsername(userName); 41 | } 42 | 43 | @RequestMapping("add-cart") 44 | public Result addProductToCart(@RequestBody CartRecord cartRecord, HttpServletRequest request) { 45 | cartRecord.setUsername(request.getHeader("accountName")); 46 | LOGGER.info("add goods to cart " + cartRecord); 47 | return cartService.addProductToCart(cartRecord); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /cart-service/src/main/java/com/mycat/monoeshop/service/CartService.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.service; 2 | 3 | import java.util.Collections; 4 | import java.util.List; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.data.redis.core.ListOperations; 10 | import org.springframework.data.redis.core.RedisTemplate; 11 | import org.springframework.stereotype.Service; 12 | 13 | import com.mycat.monoeshop.model.CartRecord; 14 | import com.mycat.monoeshop.model.Result; 15 | import com.mycat.monoeshop.model.ResultEnum; 16 | 17 | /** 18 | * Desc: 19 | * 20 | * @date: 27/08/2017 21 | * @author: Leader us 22 | */ 23 | @Service 24 | public class CartService { 25 | private static final Logger LOGGER = LoggerFactory.getLogger(CartService.class); 26 | private static final String REDIS_KEY_PRE_CART = "cart_"; 27 | 28 | @Autowired 29 | private RedisTemplate redisTemplate; 30 | 31 | public List getProductsByUsername(String username) { 32 | try { 33 | List records = redisTemplate.opsForList().range(REDIS_KEY_PRE_CART + username, 0, -1); 34 | LOGGER.info("get products by username: {}, result: {}", username, records); 35 | return records; 36 | } catch (Exception e) { 37 | LOGGER.warn("redis err ", e); 38 | return Collections.emptyList(); 39 | } 40 | } 41 | 42 | public Result addProductToCart(CartRecord cartRecord) { 43 | try { 44 | LOGGER.info("add product to cart, cartRecord: {}", cartRecord); 45 | String key = REDIS_KEY_PRE_CART + cartRecord.getUsername(); 46 | ListOperations optList = redisTemplate.opsForList(); 47 | List records = optList.range(key, 0, -1); 48 | boolean found = false; 49 | for (int i = 0; i < records.size(); i++) { 50 | CartRecord cur = records.get(i); 51 | if (cur.getProductId().equals(cartRecord.getProductId())) { 52 | cur.setCount(cur.getCount() + 1); 53 | optList.set(key, i, cur); 54 | found = true; 55 | break; 56 | } 57 | } 58 | if (!found) { 59 | redisTemplate.opsForList().leftPush(REDIS_KEY_PRE_CART + cartRecord.getUsername(), cartRecord) 60 | .intValue(); 61 | } 62 | return new Result(ResultEnum.SUCCESS); 63 | } catch (Exception e) { 64 | LOGGER.warn("redis err ", e); 65 | Result rs = new Result<>(ResultEnum.ERROR); 66 | rs.setData(e.toString()); 67 | return rs; 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /cart-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: eshop-cart-service 4 | redis: 5 | host: 192.168.18.134 6 | port: 6379 7 | #password: 8 | info: 9 | app: 10 | name: ${spring.application.name} 11 | version: v1.0.0 12 | server: 13 | port: 8035 14 | context-path: / 15 | tomcat: 16 | uri-encoding: UTF-8 17 | 18 | logging: 19 | config: classpath:logback.xml 20 | eureka: 21 | instance: 22 | hostname: 127.0.0.1 23 | prefer-ip-address: true 24 | client: 25 | healthcheck: 26 | enabled: true 27 | registerWithEureka: true 28 | fetchRegistry: true 29 | service-url: 30 | defaultZone: http://127.0.0.1:8030/eureka/ 31 | -------------------------------------------------------------------------------- /cart-service/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /config/zuul/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: micro-gateway 4 | redis: 5 | host: 192.168.18.134 6 | port: 6379 7 | #password: 8 | info: 9 | app: 10 | name: ${spring.application.name} 11 | version: v1.0.0 12 | server: 13 | port: 8039 14 | context-path: / 15 | tomcat: 16 | uri-encoding: UTF-8 17 | 18 | logging: 19 | config: classpath:logback.xml 20 | eureka: 21 | instance: 22 | hostname: 127.0.0.1 23 | prefer-ip-address: true 24 | client: 25 | healthcheck: 26 | enabled: true 27 | registerWithEureka: true 28 | fetchRegistry: true 29 | service-url: 30 | defaultZone: http://127.0.0.1:8030/eureka/ 31 | 32 | zuul: 33 | ribbon-isolation-strategy: THREAD # SEMAPHORE THREAD 34 | sensitive-headers: 35 | ignored-headers: 36 | ignored-services: '*' 37 | retryable: true 38 | routes: 39 | session: 40 | path: /session/** 41 | url: forward:/session 42 | account: 43 | path: /account/** 44 | serviceId: eshop-auth-service 45 | stripPrefix: false 46 | product: 47 | path: /products/** 48 | serviceId: eshop-product-service 49 | stripPrefix: false 50 | cart: 51 | path: /cart/** 52 | serviceId: eshop-cart-service 53 | stripPrefix: false 54 | 55 | hystrix: 56 | command: 57 | default: 58 | execution: 59 | isolation: 60 | thread: 61 | timeoutInMilliseconds: 10000 62 | 63 | ribbon: 64 | MaxAutoRetries: 2 65 | MaxAutoRetriesNextServer: 3 66 | restclient: 67 | enabled: true -------------------------------------------------------------------------------- /eshop-web/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | 6 | Springcloud_eShop 7 | Springcloud_eShop 8 | 0.0.1-SNAPSHOT 9 | 10 | sc_eshop_web 11 | sc_eshop_web 12 | jar 13 | 14 | 9.5.1 15 | 16 | 17 | 18 | org.springframework.boot 19 | spring-boot-starter-web 20 | 21 | 22 | org.springframework.cloud 23 | spring-cloud-starter-eureka 24 | ${spring.cloud.version} 25 | 26 | 27 | org.springframework.cloud 28 | spring-cloud-starter-feign 29 | ${spring.cloud.version} 30 | 31 | 32 | org.springframework.cloud 33 | spring-cloud-starter-hystrix 34 | ${spring.cloud.version} 35 | 36 | 37 | com.google.guava 38 | guava 39 | 23.0 40 | 41 | 42 | 43 | 44 | eshop_sc_eshop_web 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-maven-plugin 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /eshop-web/src/main/java/com/mycat/monoeshop/App.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.cloud.client.SpringCloudApplication; 5 | import org.springframework.cloud.netflix.feign.EnableFeignClients; 6 | 7 | /** 8 | * Desc: 9 | * 10 | * @date: 27/08/2017 11 | * @author: Leader us 12 | */ 13 | @EnableFeignClients 14 | @SpringCloudApplication 15 | public class App{ 16 | public static final String SESSION_KEY = "SESSION"; 17 | 18 | public static void main(String[] args) { 19 | SpringApplication.run(App.class, args); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /eshop-web/src/main/java/com/mycat/monoeshop/JacksonUtil.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.core.JsonParser; 5 | import com.fasterxml.jackson.core.Version; 6 | import com.fasterxml.jackson.databind.DeserializationFeature; 7 | import com.fasterxml.jackson.databind.JavaType; 8 | import com.fasterxml.jackson.databind.ObjectMapper; 9 | import com.fasterxml.jackson.databind.SerializationFeature; 10 | import com.fasterxml.jackson.databind.module.SimpleModule; 11 | import org.apache.commons.lang.StringUtils; 12 | 13 | import java.util.List; 14 | /** 15 | * Desc: 16 | * 17 | * @date: 27/08/2017 18 | * @author: Leader us 19 | */ 20 | public class JacksonUtil { 21 | private final static ObjectMapper objectMapper = new ObjectMapper(); 22 | 23 | static { 24 | SimpleModule simpleModule = new SimpleModule("SimpleJodaModule", new Version(1, 0, 0, null, null, null)); 25 | objectMapper.registerModule(simpleModule); 26 | objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 27 | objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true); 28 | objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); 29 | objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); 30 | objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true); 31 | objectMapper.configure(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS, true); 32 | objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true); 33 | objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 34 | } 35 | 36 | public static String encode(Object obj) { 37 | try { 38 | return objectMapper.writeValueAsString(obj); 39 | } catch (Exception ignored) { 40 | } 41 | return null; 42 | } 43 | 44 | /** 45 | * 将json string反序列化成对象 46 | * 47 | * @param json 48 | * @param valueType 49 | * @return 50 | */ 51 | public static T decode(String json, Class valueType) { 52 | if (StringUtils.isEmpty(json)) { 53 | return null; 54 | } 55 | try { 56 | return objectMapper.readValue(json, valueType); 57 | } catch (Exception ignored) { 58 | } 59 | return null; 60 | } 61 | 62 | public static List decodeList(String json, Class valueType) { 63 | try { 64 | JavaType javaType = getCollectionType(List.class, valueType); 65 | return (List) objectMapper.readValue(json, javaType); 66 | } catch (Exception ignored) { 67 | } 68 | return null; 69 | } 70 | 71 | private static JavaType getCollectionType(Class collectionClass, Class... elementClasses) { 72 | return objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClasses); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /eshop-web/src/main/java/com/mycat/monoeshop/config/SecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.config; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 6 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 7 | 8 | @Configuration 9 | public class SecurityConfig extends WebMvcConfigurerAdapter { 10 | @Autowired 11 | SecurityInterceptor inteseptor; 12 | @Override 13 | public void addInterceptors(InterceptorRegistry registry) { 14 | registry.addInterceptor(inteseptor).excludePathPatterns("/error","/login.html", "/account/login", 15 | "/session/**", "/detail.html").addPathPatterns("/","/**"); 16 | 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /eshop-web/src/main/java/com/mycat/monoeshop/config/SecurityInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.config; 2 | 3 | import java.io.IOException; 4 | import java.util.Map; 5 | import java.util.Optional; 6 | import java.util.stream.Stream; 7 | 8 | import javax.servlet.ServletException; 9 | import javax.servlet.http.Cookie; 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | 13 | import org.apache.commons.lang.ArrayUtils; 14 | import org.slf4j.Logger; 15 | import org.slf4j.LoggerFactory; 16 | import org.springframework.beans.factory.annotation.Autowired; 17 | import org.springframework.context.ApplicationContext; 18 | import org.springframework.context.event.ContextRefreshedEvent; 19 | import org.springframework.context.event.EventListener; 20 | import org.springframework.stereotype.Component; 21 | import org.springframework.web.servlet.HandlerInterceptor; 22 | import org.springframework.web.servlet.ModelAndView; 23 | 24 | import com.google.common.collect.Maps; 25 | import com.mycat.monoeshop.App; 26 | import com.mycat.monoeshop.model.Result; 27 | import com.mycat.monoeshop.service.rest.SessionService; 28 | 29 | /** 30 | * Desc: 31 | * 32 | * @date: 27/08/2017 33 | * @author: Leader us 34 | */ 35 | @Component 36 | public class SecurityInterceptor implements HandlerInterceptor { 37 | private static final Logger LOGGER = LoggerFactory.getLogger(SecurityInterceptor.class); 38 | private static final String REDIRECT_PAGE = "/login.html"; 39 | ApplicationContext applicationContext; 40 | 41 | @EventListener 42 | public void setApplicationContext(ContextRefreshedEvent event) { 43 | applicationContext = event.getApplicationContext(); 44 | } 45 | 46 | SessionService sessionService; 47 | 48 | @Override 49 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 50 | throws Exception { 51 | Cookie[] cookies = request.getCookies(); 52 | if (ArrayUtils.isEmpty(cookies)) { 53 | LOGGER.warn("no cookie ,to login ," + request.getRequestURL()); 54 | response.sendRedirect(REDIRECT_PAGE); 55 | return false; 56 | } 57 | Optional opt = Stream.of(cookies) 58 | .filter(cookie -> cookie != null && App.SESSION_KEY.equals(cookie.getName())).findFirst(); 59 | 60 | if (opt.isPresent()) { 61 | Cookie cookie = opt.get(); 62 | String token = cookie.getValue(); 63 | LOGGER.info("check SESSION_KEY cookie " + token); 64 | try { 65 | Result sessionResult = getSessionSrv().tokenCheck("SESSION=" + token); 66 | if (sessionResult != null && sessionResult.getCode() == SessionService.RESULT_SUCCESS) { 67 | return true; 68 | } 69 | } catch (Exception e) { 70 | LOGGER.warn("check token error", e); 71 | } 72 | } 73 | LOGGER.warn("no SESSION_KEY cookie ,to login "); 74 | response.sendRedirect(REDIRECT_PAGE); 75 | return false; 76 | } 77 | 78 | private SessionService getSessionSrv() 79 | { 80 | if(sessionService!=null) 81 | { 82 | return sessionService; 83 | }else 84 | { 85 | sessionService=this.applicationContext.getBean(SessionService.class); 86 | return sessionService; 87 | } } 88 | 89 | @Override 90 | public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, 91 | ModelAndView modelAndView) throws Exception { 92 | 93 | } 94 | 95 | @Override 96 | public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) 97 | throws Exception { 98 | 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /eshop-web/src/main/java/com/mycat/monoeshop/controller/AccountController.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.controller; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.servlet.http.Cookie; 6 | import javax.servlet.http.HttpServletResponse; 7 | 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Controller; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.bind.annotation.RequestMethod; 14 | 15 | import com.mycat.monoeshop.App; 16 | import com.mycat.monoeshop.service.rest.AccountService; 17 | 18 | /** 19 | * Desc: 20 | * 21 | * @date: 27/08/2017 22 | * @author: Leader us 23 | */ 24 | @Controller 25 | @RequestMapping("/account") 26 | public class AccountController { 27 | @Autowired 28 | private AccountService accountService; 29 | private static final Logger LOGGER = LoggerFactory.getLogger(AccountService.class); 30 | @RequestMapping(value = "login", method = RequestMethod.POST) 31 | public void login(HttpServletResponse response, String username, String password) throws IOException { 32 | LOGGER.info("login handle "+username); 33 | String token = accountService.login(username, password); 34 | if (token != null) { 35 | Cookie cookie = new Cookie(App.SESSION_KEY, token); 36 | cookie.setMaxAge(24 * 60 * 60); 37 | cookie.setPath("/"); 38 | response.addCookie(cookie); 39 | LOGGER.info("redirect to main.html "); 40 | response.sendRedirect("/main.html"); 41 | //return "redirect:/main.html"; 42 | } else { 43 | response.sendRedirect("/login.html"); 44 | //return "redirect:"; 45 | } 46 | } 47 | 48 | @RequestMapping(value = "/") 49 | public String index() { 50 | return "/main.html"; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /eshop-web/src/main/java/com/mycat/monoeshop/controller/CartController.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.controller; 2 | 3 | import java.util.List; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Controller; 9 | import org.springframework.web.bind.annotation.CookieValue; 10 | import org.springframework.web.bind.annotation.RequestBody; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.ResponseBody; 13 | 14 | import com.mycat.monoeshop.App; 15 | import com.mycat.monoeshop.model.CartRecord; 16 | import com.mycat.monoeshop.model.Result; 17 | import com.mycat.monoeshop.service.rest.CartService; 18 | 19 | /** 20 | * Desc: 21 | * 22 | * @date: 27/08/2017 23 | * @author: Leader us 24 | */ 25 | @Controller 26 | @RequestMapping("/cart") 27 | public class CartController { 28 | private static final Logger LOGGER = LoggerFactory.getLogger(CartController.class); 29 | 30 | @Autowired 31 | private CartService cartService; 32 | 33 | @RequestMapping("records") 34 | @ResponseBody 35 | public List getProductsByUsername(@CookieValue(App.SESSION_KEY) String sessionId) { 36 | LOGGER.info("get cart for user " + sessionId); 37 | return cartService.getProductsByUsername("SESSION="+sessionId); 38 | } 39 | 40 | @RequestMapping("add-cart") 41 | @ResponseBody 42 | public Result addProductToCart(@CookieValue(App.SESSION_KEY) String sessionId, 43 | @RequestBody CartRecord cartRecord) { 44 | cartRecord.setUsername(sessionId); 45 | LOGGER.info("add goods to cart " + cartRecord); 46 | return cartService.addProductToCart("SESSION="+sessionId, cartRecord); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /eshop-web/src/main/java/com/mycat/monoeshop/controller/Mainpage.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.controller; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | 6 | /** 7 | * Desc: 8 | * 9 | * @date: 27/08/2017 10 | * @author: Leader us 11 | */ 12 | @Controller 13 | public class Mainpage { 14 | @RequestMapping("/") 15 | public String index() 16 | { 17 | return "/main.html"; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /eshop-web/src/main/java/com/mycat/monoeshop/controller/ProductController.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.controller; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Controller; 7 | import org.springframework.web.bind.annotation.PathVariable; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.ResponseBody; 10 | 11 | import com.mycat.monoeshop.model.Product; 12 | import com.mycat.monoeshop.service.rest.ProductService; 13 | 14 | /** 15 | * Desc: 16 | * 17 | * @date: 27/08/2017 18 | * @author: Leader us 19 | */ 20 | @Controller 21 | @RequestMapping("/products") 22 | public class ProductController { 23 | @Autowired 24 | private ProductService productService; 25 | 26 | @RequestMapping("") 27 | @ResponseBody 28 | public List getProducts() { 29 | return productService.getProducts(); 30 | } 31 | 32 | @RequestMapping("{id}") 33 | @ResponseBody 34 | public Product getProductById(@PathVariable Integer id) { 35 | return productService.getProductById(id); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /eshop-web/src/main/java/com/mycat/monoeshop/model/Account.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.model; 2 | 3 | /** 4 | * Desc: 5 | * 6 | * @date: 27/08/2017 7 | * @author: Leader us 8 | */ 9 | public class Account { 10 | private String name; 11 | private String password; 12 | 13 | public String getName() { 14 | return name; 15 | } 16 | 17 | public void setName(String name) { 18 | this.name = name; 19 | } 20 | 21 | public String getPassword() { 22 | return password; 23 | } 24 | 25 | public void setPassword(String password) { 26 | this.password = password; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /eshop-web/src/main/java/com/mycat/monoeshop/model/CartRecord.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.model; 2 | 3 | import java.math.BigDecimal; 4 | import java.util.Date; 5 | 6 | /** 7 | * Desc: 8 | * 9 | * @date: 27/08/2017 10 | * @author: Leader us 11 | */ 12 | public class CartRecord { 13 | private Integer productId; 14 | private String productName; 15 | private BigDecimal productPrice; 16 | private String username; 17 | private Date time; 18 | private Integer count; 19 | 20 | public Integer getProductId() { 21 | return productId; 22 | } 23 | 24 | public void setProductId(Integer productId) { 25 | this.productId = productId; 26 | } 27 | 28 | public String getProductName() { 29 | return productName; 30 | } 31 | 32 | public void setProductName(String productName) { 33 | this.productName = productName; 34 | } 35 | 36 | public BigDecimal getProductPrice() { 37 | return productPrice; 38 | } 39 | 40 | public void setProductPrice(BigDecimal productPrice) { 41 | this.productPrice = productPrice; 42 | } 43 | 44 | public String getUsername() { 45 | return username; 46 | } 47 | 48 | public void setUsername(String username) { 49 | this.username = username; 50 | } 51 | 52 | public Date getTime() { 53 | return time; 54 | } 55 | 56 | public void setTime(Date time) { 57 | this.time = time; 58 | } 59 | 60 | public Integer getCount() { 61 | return count; 62 | } 63 | 64 | public void setCount(Integer count) { 65 | this.count = count; 66 | } 67 | 68 | @Override 69 | public String toString() { 70 | return "CartRecord{" + 71 | "productId='" + productId + '\'' + 72 | ", productName='" + productName + '\'' + 73 | ", productPrice=" + productPrice + 74 | ", username='" + username + '\'' + 75 | ", time=" + time + 76 | ", count=" + count + 77 | '}'; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /eshop-web/src/main/java/com/mycat/monoeshop/model/Product.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.model; 2 | 3 | import java.math.BigDecimal; 4 | 5 | /** 6 | * Desc: 7 | * 8 | * @date: 27/08/2017 9 | * @author: Leader us 10 | */ 11 | public class Product { 12 | private Integer id; 13 | private String name; 14 | private BigDecimal price; 15 | private String desc; 16 | 17 | public Integer getId() { 18 | return id; 19 | } 20 | 21 | public void setId(Integer id) { 22 | this.id = id; 23 | } 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | 29 | public void setName(String name) { 30 | this.name = name; 31 | } 32 | 33 | public BigDecimal getPrice() { 34 | return price; 35 | } 36 | 37 | public void setPrice(BigDecimal price) { 38 | this.price = price; 39 | } 40 | 41 | public String getDesc() { 42 | return desc; 43 | } 44 | 45 | public void setDesc(String desc) { 46 | this.desc = desc; 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | return "Product{" + 52 | "id=" + id + 53 | ", name='" + name + '\'' + 54 | ", price=" + price + 55 | ", desc='" + desc + '\'' + 56 | '}'; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /eshop-web/src/main/java/com/mycat/monoeshop/model/Result.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.model; 2 | 3 | /** 4 | * Desc: 5 | * 6 | * @date: 27/08/2017 7 | * @author: Leader us 8 | */ 9 | public class Result { 10 | private int code; 11 | private String desc; 12 | private T data; 13 | 14 | public Result() 15 | { 16 | 17 | } 18 | public Result(ResultEnum resultEnum) { 19 | this.code = resultEnum.getCode(); 20 | this.desc = resultEnum.getDesc(); 21 | } 22 | 23 | public Result(ResultEnum resultEnum, T data) { 24 | this.code = resultEnum.getCode(); 25 | this.desc = resultEnum.getDesc(); 26 | this.data = data; 27 | } 28 | 29 | public int getCode() { 30 | return code; 31 | } 32 | 33 | public void setCode(int code) { 34 | this.code = code; 35 | } 36 | 37 | public String getDesc() { 38 | return desc; 39 | } 40 | 41 | public void setDesc(String desc) { 42 | this.desc = desc; 43 | } 44 | 45 | public T getData() { 46 | return data; 47 | } 48 | 49 | public void setData(T data) { 50 | this.data = data; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /eshop-web/src/main/java/com/mycat/monoeshop/model/ResultEnum.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.model; 2 | 3 | /** 4 | * Desc: 5 | * 6 | * @date: 27/08/2017 7 | * @author: Leader us 8 | */ 9 | public enum ResultEnum { 10 | SUCCESS(200, "success"), ERROR(502, "error"), NOT_LOGIN(503, "not login"); 11 | 12 | private int code; 13 | private String desc; 14 | 15 | ResultEnum(int code, String desc) { 16 | this.code = code; 17 | this.desc = desc; 18 | } 19 | 20 | public int getCode() { 21 | return code; 22 | } 23 | 24 | public String getDesc() { 25 | return desc; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /eshop-web/src/main/java/com/mycat/monoeshop/service/rest/AccountService.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.service.rest; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.cloud.netflix.feign.FeignClient; 6 | import org.springframework.stereotype.Component; 7 | import org.springframework.web.bind.annotation.PostMapping; 8 | import org.springframework.web.bind.annotation.RequestParam; 9 | 10 | /** 11 | * Desc: 12 | * 13 | * @date: 27/08/2017 14 | * @author: Leader us 15 | */ 16 | @FeignClient(name = "micro-gateway", fallback = AccountService.HystrixAccountService.class) 17 | public interface AccountService { 18 | @PostMapping("/account/login") 19 | String login(@RequestParam("username") String username, @RequestParam("password") String password); 20 | 21 | @Component 22 | class HystrixAccountService implements AccountService { 23 | private static final Logger LOGGER = LoggerFactory.getLogger(AccountService.class); 24 | @Override 25 | public String login(String username, String password) { 26 | LOGGER.warn("Hystrix occured: login "); 27 | return null; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /eshop-web/src/main/java/com/mycat/monoeshop/service/rest/CartService.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.service.rest; 2 | 3 | import java.math.BigDecimal; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.cloud.netflix.feign.FeignClient; 10 | import org.springframework.stereotype.Component; 11 | import org.springframework.web.bind.annotation.GetMapping; 12 | import org.springframework.web.bind.annotation.PathVariable; 13 | import org.springframework.web.bind.annotation.RequestBody; 14 | import org.springframework.web.bind.annotation.RequestHeader; 15 | 16 | import com.mycat.monoeshop.model.CartRecord; 17 | import com.mycat.monoeshop.model.Result; 18 | 19 | /** 20 | * Desc: 21 | * 22 | * @date: 27/08/2017 23 | * @author: Leader us 24 | */ 25 | 26 | @FeignClient(name = "micro-gateway", fallback = CartService.HystrixCartService.class) 27 | public interface CartService { 28 | 29 | @GetMapping("/cart/add-cart") 30 | Result addProductToCart(@RequestHeader("Cookie") String sessionId,@RequestBody CartRecord cartRecord); 31 | 32 | @GetMapping("/cart/records") 33 | List getProductsByUsername(@RequestHeader("Cookie") String sessionId); 34 | 35 | @Component 36 | class HystrixCartService implements CartService { 37 | private static final Logger LOGGER = LoggerFactory.getLogger(CartService.class); 38 | @Override 39 | public List getProductsByUsername(@RequestHeader("Cookie") String sessionId) { 40 | LOGGER.warn("Hystrix occured :CartRecord"); 41 | CartRecord prod=new CartRecord(); 42 | prod.setCount(0); 43 | prod.setProductId(0); 44 | prod.setProductName("Error"); 45 | prod.setProductPrice(BigDecimal.ZERO); 46 | ArrayList rest=new ArrayList<>(); 47 | rest.add(prod); 48 | return rest; 49 | } 50 | 51 | @Override 52 | public Result addProductToCart(@RequestHeader("Cookie") String sessionId,CartRecord cartRecord) { 53 | LOGGER.warn("Hystrix occured :addProductToCart"); 54 | return new Result(com.mycat.monoeshop.model.ResultEnum.ERROR); 55 | } 56 | 57 | } 58 | } -------------------------------------------------------------------------------- /eshop-web/src/main/java/com/mycat/monoeshop/service/rest/ProductService.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.service.rest; 2 | 3 | import java.math.BigDecimal; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.cloud.netflix.feign.FeignClient; 10 | import org.springframework.stereotype.Component; 11 | import org.springframework.web.bind.annotation.GetMapping; 12 | import org.springframework.web.bind.annotation.PathVariable; 13 | 14 | import com.mycat.monoeshop.model.Product; 15 | 16 | /** 17 | * Desc: 18 | * 19 | * @date: 27/08/2017 20 | * @author: Leader us 21 | */ 22 | 23 | @FeignClient(name = "micro-gateway", fallback = ProductService.HystrixProductService.class) 24 | public interface ProductService { 25 | 26 | @GetMapping("/products/all") 27 | List getProducts(); 28 | 29 | @GetMapping("/products/{id}") 30 | Product getProductById(@PathVariable("id") Integer id); 31 | 32 | @Component 33 | class HystrixProductService implements ProductService { 34 | Logger LOGGER = LoggerFactory.getLogger(ProductService.class); 35 | 36 | @Override 37 | public List getProducts() { 38 | LOGGER.warn("Hystrix occured: getProducts"); 39 | Product prod = new Product(); 40 | prod.setId(0); 41 | prod.setName("Error"); 42 | prod.setPrice(BigDecimal.ZERO); 43 | prod.setDesc("Erro occured"); 44 | ArrayList rest = new ArrayList<>(); 45 | rest.add(prod); 46 | return rest; 47 | } 48 | 49 | @Override 50 | public Product getProductById(Integer id) { 51 | LOGGER.warn("Hystrix occured: getProductById"); 52 | return null; 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /eshop-web/src/main/java/com/mycat/monoeshop/service/rest/SessionService.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.service.rest; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.cloud.netflix.feign.FeignClient; 6 | import org.springframework.stereotype.Component; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.RequestHeader; 9 | 10 | import com.mycat.monoeshop.model.Result; 11 | import com.mycat.monoeshop.model.ResultEnum; 12 | 13 | /** 14 | * Desc: 15 | * 16 | * @date: 27/08/2017 17 | * @author: Leader us 18 | */ 19 | @FeignClient(name = "micro-gateway", fallback = SessionService.HystrixSessionService.class) 20 | public interface SessionService { 21 | Logger LOGGER = LoggerFactory.getLogger(SessionService.class); 22 | public static final int RESULT_SUCCESS = 200; 23 | @GetMapping(value = "/session/token") 24 | Result tokenCheck(@RequestHeader("Cookie") String sessionId); 25 | 26 | @Component 27 | class HystrixSessionService implements SessionService { 28 | @Override 29 | public Result tokenCheck(String sessionId) { 30 | LOGGER.warn("token check error"); 31 | return new Result(ResultEnum.ERROR); 32 | } 33 | } 34 | 35 | 36 | } 37 | -------------------------------------------------------------------------------- /eshop-web/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: eshop-web 4 | info: 5 | app: 6 | name: ${spring.application.name} 7 | version: v1.0.0 8 | server: 9 | port: 8033 10 | context-path: / 11 | tomcat: 12 | uri-encoding: UTF-8 13 | 14 | logging: 15 | config: classpath:logback.xml 16 | eureka: 17 | instance: 18 | hostname: 127.0.0.1 19 | prefer-ip-address: true 20 | client: 21 | healthcheck: 22 | enabled: true 23 | registerWithEureka: false 24 | fetchRegistry: true 25 | service-url: 26 | defaultZone: http://127.0.0.1:8030/eureka/ 27 | -------------------------------------------------------------------------------- /eshop-web/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/cart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | My Shop Plantform 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/css/bootstrap-table.min.css: -------------------------------------------------------------------------------- 1 | .fixed-table-container .bs-checkbox,.fixed-table-container .no-records-found{text-align:center}.fixed-table-body thead th .th-inner,.table td,.table th{box-sizing:border-box}.bootstrap-table .table{margin-bottom:0!important;border-bottom:1px solid #ddd;border-collapse:collapse!important;border-radius:1px}.bootstrap-table .table:not(.table-condensed),.bootstrap-table .table:not(.table-condensed)>tbody>tr>td,.bootstrap-table .table:not(.table-condensed)>tbody>tr>th,.bootstrap-table .table:not(.table-condensed)>tfoot>tr>td,.bootstrap-table .table:not(.table-condensed)>tfoot>tr>th,.bootstrap-table .table:not(.table-condensed)>thead>tr>td{padding:8px}.bootstrap-table .table.table-no-bordered>tbody>tr>td,.bootstrap-table .table.table-no-bordered>thead>tr>th{border-right:2px solid transparent}.bootstrap-table .table.table-no-bordered>tbody>tr>td:last-child{border-right:none}.fixed-table-container{position:relative;clear:both;border:1px solid #ddd;border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px}.fixed-table-container.table-no-bordered{border:1px solid transparent}.fixed-table-footer,.fixed-table-header{overflow:hidden}.fixed-table-footer{border-top:1px solid #ddd}.fixed-table-body{overflow-x:auto;overflow-y:auto;height:100%}.fixed-table-container table{width:100%}.fixed-table-container thead th{height:0;padding:0;margin:0;border-left:1px solid #ddd}.fixed-table-container thead th:focus{outline:transparent solid 0}.fixed-table-container thead th:first-child{border-left:none;border-top-left-radius:4px;-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px}.fixed-table-container tbody td .th-inner,.fixed-table-container thead th .th-inner{padding:8px;line-height:24px;vertical-align:top;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fixed-table-container thead th .sortable{cursor:pointer;background-position:right;background-repeat:no-repeat;padding-right:30px}.fixed-table-container thead th .both{background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAAAkElEQVQoz7X QMQ5AQBCF4dWQSJxC5wwax1Cq1e7BAdxD5SL+Tq/QCM1oNiJidwox0355mXnG/DrEtIQ6azioNZQxI0ykPhTQIwhCR+BmBYtlK7kLJYwWCcJA9M4qdrZrd8pPjZWPtOqdRQy320YSV17OatFC4euts6z39GYMKRPCTKY9UnPQ6P+GtMRfGtPnBCiqhAeJPmkqAAAAAElFTkSuQmCC')}.fixed-table-container thead th .asc{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZ0lEQVQ4y2NgGLKgquEuFxBPAGI2ahhWCsS/gDibUoO0gPgxEP8H4ttArEyuQYxAPBdqEAxPBImTY5gjEL9DM+wTENuQahAvEO9DMwiGdwAxOymGJQLxTyD+jgWDxCMZRsEoGAVoAADeemwtPcZI2wAAAABJRU5ErkJggg==)}.fixed-table-container thead th .desc{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZUlEQVQ4y2NgGAWjYBSggaqGu5FA/BOIv2PBIPFEUgxjB+IdQPwfC94HxLykus4GiD+hGfQOiB3J8SojEE9EM2wuSJzcsFMG4ttQgx4DsRalkZENxL+AuJQaMcsGxBOAmGvopk8AVz1sLZgg0bsAAAAASUVORK5CYII=)}.fixed-table-container th.detail{width:30px}.fixed-table-container tbody td{border-left:1px solid #ddd}.fixed-table-container tbody tr:first-child td{border-top:none}.fixed-table-container tbody td:first-child{border-left:none}.fixed-table-container tbody .selected td{background-color:#f5f5f5}.fixed-table-container .bs-checkbox .th-inner{padding:8px 0}.fixed-table-container input[type=radio],.fixed-table-container input[type=checkbox]{margin:0 auto!important}.fixed-table-pagination .pagination-detail,.fixed-table-pagination div.pagination{margin-top:10px;margin-bottom:10px}.fixed-table-pagination div.pagination .pagination{margin:0}.fixed-table-pagination .pagination a{padding:6px 12px;line-height:1.428571429}.fixed-table-pagination .pagination-info{line-height:34px;margin-right:5px}.fixed-table-pagination .btn-group{position:relative;display:inline-block;vertical-align:middle}.fixed-table-pagination .dropup .dropdown-menu{margin-bottom:0}.fixed-table-pagination .page-list{display:inline-block}.fixed-table-toolbar .columns-left{margin-right:5px}.fixed-table-toolbar .columns-right{margin-left:5px}.fixed-table-toolbar .columns label{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.428571429}.fixed-table-toolbar .bs-bars,.fixed-table-toolbar .columns,.fixed-table-toolbar .search{position:relative;margin-top:10px;margin-bottom:10px;line-height:34px}.fixed-table-pagination li.disabled a{pointer-events:none;cursor:default}.fixed-table-loading{display:none;position:absolute;top:42px;right:0;bottom:0;left:0;z-index:99;background-color:#fff;text-align:center}.fixed-table-body .card-view .title{font-weight:700;display:inline-block;min-width:30%;text-align:left!important}.table td,.table th{vertical-align:middle}.fixed-table-toolbar .dropdown-menu{text-align:left;max-height:300px;overflow:auto}.fixed-table-toolbar .btn-group>.btn-group{display:inline-block;margin-left:-1px!important}.fixed-table-toolbar .btn-group>.btn-group>.btn{border-radius:0}.fixed-table-toolbar .btn-group>.btn-group:first-child>.btn{border-top-left-radius:4px;border-bottom-left-radius:4px}.fixed-table-toolbar .btn-group>.btn-group:last-child>.btn{border-top-right-radius:4px;border-bottom-right-radius:4px}.bootstrap-table .table>thead>tr>th{vertical-align:bottom;border-bottom:1px solid #ddd}.bootstrap-table .table thead>tr>th{padding:0;margin:0}.bootstrap-table .fixed-table-footer tbody>tr>td{padding:0!important}.bootstrap-table .fixed-table-footer .table{border-bottom:none;border-radius:0;padding:0!important}.pull-right .dropdown-menu{right:0;left:auto}p.fixed-table-scroll-inner{width:100%;height:200px}div.fixed-table-scroll-outer{top:0;left:0;visibility:hidden;width:200px;height:150px;overflow:hidden} -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/css/bootstrap-theme.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.7 (http://getbootstrap.com) 3 | * Copyright 2011-2016 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger.disabled,.btn-danger[disabled],.btn-default.disabled,.btn-default[disabled],.btn-info.disabled,.btn-info[disabled],.btn-primary.disabled,.btn-primary[disabled],.btn-success.disabled,.btn-success[disabled],.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-default,fieldset[disabled] .btn-info,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-warning{-webkit-box-shadow:none;box-shadow:none}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#2e6da4;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} 6 | /*# sourceMappingURL=bootstrap-theme.min.css.map */ -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/css/css: -------------------------------------------------------------------------------- 1 | /* cyrillic-ext */ 2 | @font-face { 3 | font-family: 'Roboto'; 4 | font-style: normal; 5 | font-weight: 100; 6 | src: local('Roboto Thin'), local('Roboto-Thin'), url(http://fonts.gstatic.com/s/roboto/v16/ty9dfvLAziwdqQ2dHoyjphTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); 7 | unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; 8 | } 9 | /* cyrillic */ 10 | @font-face { 11 | font-family: 'Roboto'; 12 | font-style: normal; 13 | font-weight: 100; 14 | src: local('Roboto Thin'), local('Roboto-Thin'), url(http://fonts.gstatic.com/s/roboto/v16/frNV30OaYdlFRtH2VnZZdhTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); 15 | unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; 16 | } 17 | /* greek-ext */ 18 | @font-face { 19 | font-family: 'Roboto'; 20 | font-style: normal; 21 | font-weight: 100; 22 | src: local('Roboto Thin'), local('Roboto-Thin'), url(http://fonts.gstatic.com/s/roboto/v16/gwVJDERN2Amz39wrSoZ7FxTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); 23 | unicode-range: U+1F00-1FFF; 24 | } 25 | /* greek */ 26 | @font-face { 27 | font-family: 'Roboto'; 28 | font-style: normal; 29 | font-weight: 100; 30 | src: local('Roboto Thin'), local('Roboto-Thin'), url(http://fonts.gstatic.com/s/roboto/v16/aZMswpodYeVhtRvuABJWvBTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); 31 | unicode-range: U+0370-03FF; 32 | } 33 | /* vietnamese */ 34 | @font-face { 35 | font-family: 'Roboto'; 36 | font-style: normal; 37 | font-weight: 100; 38 | src: local('Roboto Thin'), local('Roboto-Thin'), url(http://fonts.gstatic.com/s/roboto/v16/VvXUGKZXbHtX_S_VCTLpGhTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); 39 | unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; 40 | } 41 | /* latin-ext */ 42 | @font-face { 43 | font-family: 'Roboto'; 44 | font-style: normal; 45 | font-weight: 100; 46 | src: local('Roboto Thin'), local('Roboto-Thin'), url(http://fonts.gstatic.com/s/roboto/v16/e7MeVAyvogMqFwwl61PKhBTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); 47 | unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; 48 | } 49 | /* latin */ 50 | @font-face { 51 | font-family: 'Roboto'; 52 | font-style: normal; 53 | font-weight: 100; 54 | src: local('Roboto Thin'), local('Roboto-Thin'), url(http://fonts.gstatic.com/s/roboto/v16/2tsd397wLxj96qwHyNIkxPesZW2xOQ-xsNqO47m55DA.woff2) format('woff2'); 55 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215; 56 | } 57 | /* cyrillic-ext */ 58 | @font-face { 59 | font-family: 'Roboto'; 60 | font-style: normal; 61 | font-weight: 300; 62 | src: local('Roboto Light'), local('Roboto-Light'), url(http://fonts.gstatic.com/s/roboto/v16/0eC6fl06luXEYWpBSJvXCBJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); 63 | unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; 64 | } 65 | /* cyrillic */ 66 | @font-face { 67 | font-family: 'Roboto'; 68 | font-style: normal; 69 | font-weight: 300; 70 | src: local('Roboto Light'), local('Roboto-Light'), url(http://fonts.gstatic.com/s/roboto/v16/Fl4y0QdOxyyTHEGMXX8kcRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); 71 | unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; 72 | } 73 | /* greek-ext */ 74 | @font-face { 75 | font-family: 'Roboto'; 76 | font-style: normal; 77 | font-weight: 300; 78 | src: local('Roboto Light'), local('Roboto-Light'), url(http://fonts.gstatic.com/s/roboto/v16/-L14Jk06m6pUHB-5mXQQnRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); 79 | unicode-range: U+1F00-1FFF; 80 | } 81 | /* greek */ 82 | @font-face { 83 | font-family: 'Roboto'; 84 | font-style: normal; 85 | font-weight: 300; 86 | src: local('Roboto Light'), local('Roboto-Light'), url(http://fonts.gstatic.com/s/roboto/v16/I3S1wsgSg9YCurV6PUkTORJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); 87 | unicode-range: U+0370-03FF; 88 | } 89 | /* vietnamese */ 90 | @font-face { 91 | font-family: 'Roboto'; 92 | font-style: normal; 93 | font-weight: 300; 94 | src: local('Roboto Light'), local('Roboto-Light'), url(http://fonts.gstatic.com/s/roboto/v16/NYDWBdD4gIq26G5XYbHsFBJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); 95 | unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; 96 | } 97 | /* latin-ext */ 98 | @font-face { 99 | font-family: 'Roboto'; 100 | font-style: normal; 101 | font-weight: 300; 102 | src: local('Roboto Light'), local('Roboto-Light'), url(http://fonts.gstatic.com/s/roboto/v16/Pru33qjShpZSmG3z6VYwnRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); 103 | unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; 104 | } 105 | /* latin */ 106 | @font-face { 107 | font-family: 'Roboto'; 108 | font-style: normal; 109 | font-weight: 300; 110 | src: local('Roboto Light'), local('Roboto-Light'), url(http://fonts.gstatic.com/s/roboto/v16/Hgo13k-tfSpn0qi1SFdUfVtXRa8TVwTICgirnJhmVJw.woff2) format('woff2'); 111 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215; 112 | } 113 | /* cyrillic-ext */ 114 | @font-face { 115 | font-family: 'Roboto'; 116 | font-style: normal; 117 | font-weight: 400; 118 | src: local('Roboto'), local('Roboto-Regular'), url(http://fonts.gstatic.com/s/roboto/v16/ek4gzZ-GeXAPcSbHtCeQI_esZW2xOQ-xsNqO47m55DA.woff2) format('woff2'); 119 | unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; 120 | } 121 | /* cyrillic */ 122 | @font-face { 123 | font-family: 'Roboto'; 124 | font-style: normal; 125 | font-weight: 400; 126 | src: local('Roboto'), local('Roboto-Regular'), url(http://fonts.gstatic.com/s/roboto/v16/mErvLBYg_cXG3rLvUsKT_fesZW2xOQ-xsNqO47m55DA.woff2) format('woff2'); 127 | unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; 128 | } 129 | /* greek-ext */ 130 | @font-face { 131 | font-family: 'Roboto'; 132 | font-style: normal; 133 | font-weight: 400; 134 | src: local('Roboto'), local('Roboto-Regular'), url(http://fonts.gstatic.com/s/roboto/v16/-2n2p-_Y08sg57CNWQfKNvesZW2xOQ-xsNqO47m55DA.woff2) format('woff2'); 135 | unicode-range: U+1F00-1FFF; 136 | } 137 | /* greek */ 138 | @font-face { 139 | font-family: 'Roboto'; 140 | font-style: normal; 141 | font-weight: 400; 142 | src: local('Roboto'), local('Roboto-Regular'), url(http://fonts.gstatic.com/s/roboto/v16/u0TOpm082MNkS5K0Q4rhqvesZW2xOQ-xsNqO47m55DA.woff2) format('woff2'); 143 | unicode-range: U+0370-03FF; 144 | } 145 | /* vietnamese */ 146 | @font-face { 147 | font-family: 'Roboto'; 148 | font-style: normal; 149 | font-weight: 400; 150 | src: local('Roboto'), local('Roboto-Regular'), url(http://fonts.gstatic.com/s/roboto/v16/NdF9MtnOpLzo-noMoG0miPesZW2xOQ-xsNqO47m55DA.woff2) format('woff2'); 151 | unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; 152 | } 153 | /* latin-ext */ 154 | @font-face { 155 | font-family: 'Roboto'; 156 | font-style: normal; 157 | font-weight: 400; 158 | src: local('Roboto'), local('Roboto-Regular'), url(http://fonts.gstatic.com/s/roboto/v16/Fcx7Wwv8OzT71A3E1XOAjvesZW2xOQ-xsNqO47m55DA.woff2) format('woff2'); 159 | unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; 160 | } 161 | /* latin */ 162 | @font-face { 163 | font-family: 'Roboto'; 164 | font-style: normal; 165 | font-weight: 400; 166 | src: local('Roboto'), local('Roboto-Regular'), url(http://fonts.gstatic.com/s/roboto/v16/CWB0XYA8bzo0kSThX0UTuA.woff2) format('woff2'); 167 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215; 168 | } 169 | /* cyrillic-ext */ 170 | @font-face { 171 | font-family: 'Roboto'; 172 | font-style: normal; 173 | font-weight: 500; 174 | src: local('Roboto Medium'), local('Roboto-Medium'), url(http://fonts.gstatic.com/s/roboto/v16/ZLqKeelYbATG60EpZBSDyxJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); 175 | unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; 176 | } 177 | /* cyrillic */ 178 | @font-face { 179 | font-family: 'Roboto'; 180 | font-style: normal; 181 | font-weight: 500; 182 | src: local('Roboto Medium'), local('Roboto-Medium'), url(http://fonts.gstatic.com/s/roboto/v16/oHi30kwQWvpCWqAhzHcCSBJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); 183 | unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; 184 | } 185 | /* greek-ext */ 186 | @font-face { 187 | font-family: 'Roboto'; 188 | font-style: normal; 189 | font-weight: 500; 190 | src: local('Roboto Medium'), local('Roboto-Medium'), url(http://fonts.gstatic.com/s/roboto/v16/rGvHdJnr2l75qb0YND9NyBJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); 191 | unicode-range: U+1F00-1FFF; 192 | } 193 | /* greek */ 194 | @font-face { 195 | font-family: 'Roboto'; 196 | font-style: normal; 197 | font-weight: 500; 198 | src: local('Roboto Medium'), local('Roboto-Medium'), url(http://fonts.gstatic.com/s/roboto/v16/mx9Uck6uB63VIKFYnEMXrRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); 199 | unicode-range: U+0370-03FF; 200 | } 201 | /* vietnamese */ 202 | @font-face { 203 | font-family: 'Roboto'; 204 | font-style: normal; 205 | font-weight: 500; 206 | src: local('Roboto Medium'), local('Roboto-Medium'), url(http://fonts.gstatic.com/s/roboto/v16/mbmhprMH69Zi6eEPBYVFhRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); 207 | unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; 208 | } 209 | /* latin-ext */ 210 | @font-face { 211 | font-family: 'Roboto'; 212 | font-style: normal; 213 | font-weight: 500; 214 | src: local('Roboto Medium'), local('Roboto-Medium'), url(http://fonts.gstatic.com/s/roboto/v16/oOeFwZNlrTefzLYmlVV1UBJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); 215 | unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; 216 | } 217 | /* latin */ 218 | @font-face { 219 | font-family: 'Roboto'; 220 | font-style: normal; 221 | font-weight: 500; 222 | src: local('Roboto Medium'), local('Roboto-Medium'), url(http://fonts.gstatic.com/s/roboto/v16/RxZJdnzeo3R5zSexge8UUVtXRa8TVwTICgirnJhmVJw.woff2) format('woff2'); 223 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215; 224 | } 225 | -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/css/font-awesome.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.3.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.3.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.3.0') format('embedded-opentype'),url('fontawesome-webfont.woff2') format('woff2'),url('fontawesome-webfont.woff2') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.3.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.3.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;transform:translate(0, 0)}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-genderless:before,.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"} -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/css/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leader-us/SpringCloud_eShop/e0da11ba480f7043be40d7a1d1bbd3f0a33ba6ea/eshop-web/src/main/resources/static/css/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/css/form-elements.css: -------------------------------------------------------------------------------- 1 | 2 | input[type="text"], 3 | input[type="password"], 4 | textarea, 5 | textarea.form-control { 6 | height: 50px; 7 | margin: 0; 8 | padding: 0 20px; 9 | vertical-align: middle; 10 | background: #f8f8f8; 11 | border: 3px solid #ddd; 12 | font-family: 'Roboto', sans-serif; 13 | font-size: 16px; 14 | font-weight: 300; 15 | line-height: 50px; 16 | color: #888; 17 | -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; 18 | -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; 19 | -o-transition: all .3s; -moz-transition: all .3s; -webkit-transition: all .3s; -ms-transition: all .3s; transition: all .3s; 20 | } 21 | 22 | textarea, 23 | textarea.form-control { 24 | padding-top: 10px; 25 | padding-bottom: 10px; 26 | line-height: 30px; 27 | } 28 | 29 | input[type="text"]:focus, 30 | input[type="password"]:focus, 31 | textarea:focus, 32 | textarea.form-control:focus { 33 | outline: 0; 34 | background: #fff; 35 | border: 3px solid #ccc; 36 | -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; 37 | } 38 | 39 | input[type="text"]:-moz-placeholder, input[type="password"]:-moz-placeholder, 40 | textarea:-moz-placeholder, textarea.form-control:-moz-placeholder { color: #888; } 41 | 42 | input[type="text"]:-ms-input-placeholder, input[type="password"]:-ms-input-placeholder, 43 | textarea:-ms-input-placeholder, textarea.form-control:-ms-input-placeholder { color: #888; } 44 | 45 | input[type="text"]::-webkit-input-placeholder, input[type="password"]::-webkit-input-placeholder, 46 | textarea::-webkit-input-placeholder, textarea.form-control::-webkit-input-placeholder { color: #888; } 47 | 48 | 49 | 50 | button.btn { 51 | height: 50px; 52 | margin: 0; 53 | padding: 0 20px; 54 | vertical-align: middle; 55 | background: #4aaf51; 56 | border: 0; 57 | font-family: 'Roboto', sans-serif; 58 | font-size: 16px; 59 | font-weight: 300; 60 | line-height: 50px; 61 | color: #fff; 62 | -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; 63 | text-shadow: none; 64 | -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; 65 | -o-transition: all .3s; -moz-transition: all .3s; -webkit-transition: all .3s; -ms-transition: all .3s; transition: all .3s; 66 | } 67 | 68 | button.btn:hover { opacity: 0.6; color: #fff; } 69 | 70 | button.btn:active { outline: 0; opacity: 0.6; color: #fff; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; } 71 | 72 | button.btn:focus { outline: 0; opacity: 0.6; background: #4aaf51; color: #fff; } 73 | 74 | button.btn:active:focus, button.btn.active:focus { outline: 0; opacity: 0.6; background: #4aaf51; color: #fff; } 75 | -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/css/product.css: -------------------------------------------------------------------------------- 1 | body{ 2 | font-family: 'microsoft yahei',Arial,sans-serif; 3 | color: #898989; 4 | } 5 | 6 | .shape{ 7 | border-style: solid; border-width: 0 80px 80px 0; float:right; height: 0px; width: 0px; 8 | -ms-transform:rotate(360deg); /* IE 9 */ 9 | -o-transform: rotate(360deg); /* Opera 10.5 */ 10 | -webkit-transform:rotate(360deg); /* Safari and Chrome */ 11 | transform:rotate(360deg); 12 | } 13 | 14 | .speical{ 15 | background:#fff; border:1px solid #ddd; box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2); margin: 15px 0; overflow:hidden; 16 | } 17 | 18 | .speical:hover { 19 | -webkit-transform: scale(1.1); 20 | -moz-transform: scale(1.1); 21 | -ms-transform: scale(1.1); 22 | -o-transform: scale(1.1); 23 | transform:rotate scale(1.1); 24 | -webkit-transition: all 0.4s ease-in-out; 25 | -moz-transition: all 0.4s ease-in-out; 26 | -o-transition: all 0.4s ease-in-out; 27 | transition: all 0.4s ease-in-out; 28 | } 29 | 30 | .shape { 31 | border-color: rgba(255,255,255,0) #d9534f rgba(255,255,255,0) rgba(255,255,255,0); 32 | } 33 | 34 | .speical-default{ 35 | border: 1px solid #d9534f; 36 | } 37 | 38 | .speical-radius{ 39 | border-radius:5px; 40 | } 41 | 42 | .shape-text{ 43 | color:#fff; font-size:14px; position:relative; right:-45px; top:2px; white-space: nowrap; 44 | -ms-transform:rotate(45deg); /* IE 9 */ 45 | -o-transform: rotate(45deg); /* Opera 10.5 */ 46 | -webkit-transform:rotate(45deg); /* Safari and Chrome */ 47 | transform:rotate(45deg); 48 | } 49 | 50 | .text-special-default{ 51 | color:#d9534f; 52 | } 53 | 54 | .speical-content{ 55 | padding:0 20px 10px; 56 | } -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/css/style-responsive.css: -------------------------------------------------------------------------------- 1 | @media (min-width: 980px) { 2 | /*-----*/ 3 | .custom-bar-chart { 4 | margin-bottom: 40px; 5 | } 6 | 7 | } 8 | 9 | @media (min-width: 768px) and (max-width: 979px) { 10 | 11 | /*-----*/ 12 | .custom-bar-chart { 13 | margin-bottom: 40px; 14 | } 15 | 16 | /*chat room*/ 17 | 18 | 19 | } 20 | 21 | @media (max-width: 768px) { 22 | 23 | .header { 24 | position: absolute; 25 | } 26 | 27 | /*sidebar*/ 28 | 29 | #sidebar { 30 | height: auto; 31 | overflow: hidden; 32 | position: absolute; 33 | width: 100%; 34 | z-index: 1001; 35 | } 36 | 37 | 38 | /* body container */ 39 | #main-content { 40 | margin: 0px!important; 41 | position: none !important; 42 | } 43 | 44 | #sidebar > ul > li > a > span { 45 | line-height: 35px; 46 | } 47 | 48 | #sidebar > ul > li { 49 | margin: 0 10px 5px 10px; 50 | } 51 | #sidebar > ul > li > a { 52 | height:35px; 53 | line-height:35px; 54 | padding: 0 10px; 55 | text-align: left; 56 | } 57 | #sidebar > ul > li > a i{ 58 | /*display: none !important;*/ 59 | } 60 | 61 | #sidebar ul > li > a .arrow, #sidebar > ul > li > a .arrow.open { 62 | margin-right: 10px; 63 | margin-top: 15px; 64 | } 65 | 66 | #sidebar ul > li.active > a .arrow, #sidebar ul > li > a:hover .arrow, #sidebar ul > li > a:focus .arrow, 67 | #sidebar > ul > li.active > a .arrow.open, #sidebar > ul > li > a:hover .arrow.open, #sidebar > ul > li > a:focus .arrow.open{ 68 | margin-top: 15px; 69 | } 70 | 71 | #sidebar > ul > li > a, #sidebar > ul > li > ul.sub > li { 72 | width: 100%; 73 | } 74 | #sidebar > ul > li > ul.sub > li > a { 75 | background: transparent !important ; 76 | } 77 | #sidebar > ul > li > ul.sub > li > a:hover { 78 | 79 | } 80 | 81 | 82 | /* sidebar */ 83 | #sidebar { 84 | margin: 0px !important; 85 | } 86 | 87 | /* sidebar collabler */ 88 | #sidebar .btn-navbar.collapsed .arrow { 89 | display: none; 90 | } 91 | 92 | #sidebar .btn-navbar .arrow { 93 | position: absolute; 94 | right: 35px; 95 | width: 0; 96 | height: 0; 97 | top:48px; 98 | border-bottom: 15px solid #282e36; 99 | border-left: 15px solid transparent; 100 | border-right: 15px solid transparent; 101 | } 102 | 103 | 104 | /*---------*/ 105 | 106 | .modal-footer .btn { 107 | margin-bottom: 0px !important; 108 | } 109 | 110 | .btn { 111 | margin-bottom: 5px; 112 | } 113 | 114 | 115 | /* full calendar fix */ 116 | .fc-header-right { 117 | left:25px; 118 | position: absolute; 119 | } 120 | 121 | .fc-header-left .fc-button { 122 | margin: 0px !important; 123 | top: -10px !important; 124 | } 125 | 126 | .fc-header-right .fc-button { 127 | margin: 0px !important; 128 | top: -50px !important; 129 | } 130 | 131 | .fc-state-active, .fc-state-active .fc-button-inner, .fc-state-hover, .fc-state-hover .fc-button-inner { 132 | background: none !important; 133 | color: #FFFFFF !important; 134 | } 135 | 136 | .fc-state-default, .fc-state-default .fc-button-inner { 137 | background: none !important; 138 | } 139 | 140 | .fc-button { 141 | border: none !important; 142 | margin-right: 2px; 143 | } 144 | 145 | .fc-view { 146 | top: 0px !important; 147 | } 148 | 149 | .fc-button .fc-button-inner { 150 | margin: 0px !important; 151 | padding: 2px !important; 152 | border: none !important; 153 | margin-right: 2px !important; 154 | background-color: #fafafa !important; 155 | background-image: -moz-linear-gradient(top, #fafafa, #efefef) !important; 156 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fafafa), to(#efefef)) !important; 157 | background-image: -webkit-linear-gradient(top, #fafafa, #efefef) !important; 158 | background-image: -o-linear-gradient(top, #fafafa, #efefef) !important; 159 | background-image: linear-gradient(to bottom, #fafafa, #efefef) !important; 160 | filter: progid:dximagetransform.microsoft.gradient(startColorstr='#fafafa', endColorstr='#efefef', GradientType=0) !important; 161 | -webkit-box-shadow: 0 1px 0px rgba(255, 255, 255, .8) !important; 162 | -moz-box-shadow: 0 1px 0px rgba(255, 255, 255, .8) !important; 163 | box-shadow: 0 1px 0px rgba(255, 255, 255, .8) !important; 164 | -webkit-border-radius: 3px !important; 165 | -moz-border-radius: 3px !important; 166 | border-radius: 3px !important; 167 | color: #646464 !important; 168 | border: 1px solid #ddd !important; 169 | text-shadow: 0 1px 0px rgba(255, 255, 255, .6) !important; 170 | text-align: center; 171 | } 172 | 173 | .fc-button.fc-state-disabled .fc-button-inner { 174 | color: #bcbbbb !important; 175 | } 176 | 177 | .fc-button.fc-state-active .fc-button-inner { 178 | background-color: #e5e4e4 !important; 179 | background-image: -moz-linear-gradient(top, #e5e4e4, #dddcdc) !important; 180 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#e5e4e4), to(#dddcdc)) !important; 181 | background-image: -webkit-linear-gradient(top, #e5e4e4, #dddcdc) !important; 182 | background-image: -o-linear-gradient(top, #e5e4e4, #dddcdc) !important; 183 | background-image: linear-gradient(to bottom, #e5e4e4, #dddcdc) !important; 184 | filter: progid:dximagetransform.microsoft.gradient(startColorstr='#e5e4e4', endColorstr='#dddcdc', GradientType=0) !important; 185 | } 186 | 187 | .fc-content { 188 | margin-top: 50px; 189 | } 190 | 191 | .fc-header-title h2 { 192 | line-height: 40px !important; 193 | font-size: 12px !important; 194 | } 195 | 196 | .fc-header { 197 | margin-bottom:0px !important; 198 | } 199 | 200 | /*--*/ 201 | 202 | /*.chart-position {*/ 203 | /*margin-top: 0px;*/ 204 | /*}*/ 205 | 206 | .stepy-titles li { 207 | margin: 10px 3px; 208 | } 209 | 210 | /*-----*/ 211 | .custom-bar-chart { 212 | margin-bottom: 40px; 213 | } 214 | 215 | /*menu icon plus minus*/ 216 | .dcjq-icon { 217 | top: 10px; 218 | } 219 | ul.sidebar-menu li ul.sub li a { 220 | padding: 0; 221 | } 222 | 223 | /*---*/ 224 | 225 | .img-responsive { 226 | width: 100%; 227 | } 228 | 229 | } 230 | 231 | 232 | 233 | @media (max-width: 480px) { 234 | 235 | .notify-row, .search, .dont-show , .inbox-head .sr-input, .inbox-head .sr-btn{ 236 | display: none; 237 | } 238 | 239 | #top_menu .nav > li, ul.top-menu > li { 240 | float: right; 241 | } 242 | .hidden-phone { 243 | display: none !important; 244 | } 245 | 246 | .chart-position { 247 | margin-top: 0px; 248 | } 249 | 250 | .navbar-inverse .navbar-toggle:hover, .navbar-inverse .navbar-toggle:focus { 251 | background-color: #ccc; 252 | border-color:#ccc ; 253 | } 254 | 255 | } 256 | 257 | @media (max-width:320px) { 258 | .login-social-link a { 259 | padding: 15px 17px !important; 260 | } 261 | 262 | .notify-row, .search, .dont-show, .inbox-head .sr-input, .inbox-head .sr-btn { 263 | display: none; 264 | } 265 | 266 | #top_menu .nav > li, ul.top-menu > li { 267 | float: right; 268 | } 269 | 270 | .hidden-phone { 271 | display: none !important; 272 | } 273 | 274 | .chart-position { 275 | margin-top: 0px; 276 | } 277 | 278 | .lock-wrapper { 279 | margin: 10% auto; 280 | max-width: 310px; 281 | } 282 | .lock-input { 283 | width: 82%; 284 | } 285 | 286 | .cmt-form { 287 | display: inline-block; 288 | width: 75%; 289 | } 290 | 291 | } 292 | 293 | 294 | 295 | 296 | -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/css/style.css: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | font-family: 'Roboto', sans-serif; 4 | font-size: 16px; 5 | font-weight: 300; 6 | color: #888; 7 | line-height: 30px; 8 | text-align: center; 9 | } 10 | 11 | strong { 12 | font-weight: 500; 13 | } 14 | 15 | a, a:hover, a:focus { 16 | color: #4aaf51; 17 | text-decoration: none; 18 | -o-transition: all .3s; 19 | -moz-transition: all .3s; 20 | -webkit-transition: all .3s; 21 | -ms-transition: all .3s; 22 | transition: all .3s; 23 | } 24 | 25 | h1, h2 { 26 | margin-top: 10px; 27 | font-size: 38px; 28 | font-weight: 100; 29 | color: #555; 30 | line-height: 50px; 31 | } 32 | 33 | h3 { 34 | font-size: 22px; 35 | font-weight: 300; 36 | color: #555; 37 | line-height: 30px; 38 | } 39 | 40 | img { 41 | max-width: 100%; 42 | } 43 | 44 | ::-moz-selection { 45 | background: #4aaf51; 46 | color: #fff; 47 | text-shadow: none; 48 | } 49 | 50 | ::selection { 51 | background: #4aaf51; 52 | color: #fff; 53 | text-shadow: none; 54 | } 55 | 56 | .btn-link-1 { 57 | display: inline-block; 58 | height: 50px; 59 | margin: 5px; 60 | padding: 16px 20px 0 20px; 61 | background: #4aaf51; 62 | font-size: 16px; 63 | font-weight: 300; 64 | line-height: 16px; 65 | color: #fff; 66 | -moz-border-radius: 4px; 67 | -webkit-border-radius: 4px; 68 | border-radius: 4px; 69 | } 70 | 71 | .btn-link-1:hover, .btn-link-1:focus, .btn-link-1:active { 72 | outline: 0; 73 | opacity: 0.6; 74 | color: #fff; 75 | } 76 | 77 | .btn-link-1.btn-link-1-facebook { 78 | background: #4862a3; 79 | } 80 | 81 | .btn-link-1.btn-link-1-twitter { 82 | background: #55acee; 83 | } 84 | 85 | .btn-link-1.btn-link-1-google-plus { 86 | background: #dd4b39; 87 | } 88 | 89 | .btn-link-1 i { 90 | padding-right: 5px; 91 | vertical-align: middle; 92 | font-size: 20px; 93 | line-height: 20px; 94 | } 95 | 96 | .btn-link-2 { 97 | display: inline-block; 98 | height: 50px; 99 | margin: 5px; 100 | padding: 15px 20px 0 20px; 101 | background: rgba(0, 0, 0, 0.3); 102 | border: 1px solid #fff; 103 | font-size: 16px; 104 | font-weight: 300; 105 | line-height: 16px; 106 | color: #fff; 107 | -moz-border-radius: 4px; 108 | -webkit-border-radius: 4px; 109 | border-radius: 4px; 110 | } 111 | 112 | .btn-link-2:hover, .btn-link-2:focus, 113 | .btn-link-2:active, .btn-link-2:active:focus { 114 | outline: 0; 115 | opacity: 0.6; 116 | background: rgba(0, 0, 0, 0.3); 117 | color: #fff; 118 | } 119 | 120 | /***** Top content *****/ 121 | 122 | .inner-bg { 123 | padding: 100px 0 170px 0; 124 | } 125 | 126 | .top-content .text { 127 | color: #fff; 128 | } 129 | 130 | .top-content .text h1 { 131 | color: #fff; 132 | } 133 | 134 | .top-content .description { 135 | margin: 20px 0 10px 0; 136 | } 137 | 138 | .top-content .description p { 139 | opacity: 0.8; 140 | } 141 | 142 | .top-content .description a { 143 | color: #fff; 144 | } 145 | 146 | .top-content .description a:hover, 147 | .top-content .description a:focus { 148 | border-bottom: 1px dotted #fff; 149 | } 150 | 151 | .form-box { 152 | margin-top: 35px; 153 | } 154 | 155 | .form-top { 156 | overflow: hidden; 157 | padding: 0 25px 15px 25px; 158 | background: #fff; 159 | -moz-border-radius: 4px 4px 0 0; 160 | -webkit-border-radius: 4px 4px 0 0; 161 | border-radius: 4px 4px 0 0; 162 | text-align: left; 163 | } 164 | 165 | .form-top-left { 166 | float: left; 167 | width: 75%; 168 | padding-top: 25px; 169 | } 170 | 171 | .form-top-left h3 { 172 | margin-top: 0; 173 | } 174 | 175 | .form-top-right { 176 | float: left; 177 | width: 25%; 178 | padding-top: 5px; 179 | font-size: 66px; 180 | color: #ddd; 181 | line-height: 100px; 182 | text-align: right; 183 | } 184 | 185 | .form-bottom { 186 | padding: 25px 25px 30px 25px; 187 | background: #eee; 188 | -moz-border-radius: 0 0 4px 4px; 189 | -webkit-border-radius: 0 0 4px 4px; 190 | border-radius: 0 0 4px 4px; 191 | text-align: left; 192 | } 193 | 194 | .form-bottom form textarea { 195 | height: 100px; 196 | } 197 | 198 | .form-bottom form button.btn { 199 | width: 100%; 200 | } 201 | 202 | .form-bottom form .input-error { 203 | border-color: #4aaf51; 204 | } 205 | 206 | .social-login { 207 | margin-top: 35px; 208 | } 209 | 210 | .social-login h3 { 211 | color: #fff; 212 | } 213 | 214 | .social-login-buttons { 215 | margin-top: 25px; 216 | } 217 | 218 | /***** Media queries *****/ 219 | 220 | @media (min-width: 992px) and (max-width: 1199px) { 221 | } 222 | 223 | @media (min-width: 768px) and (max-width: 991px) { 224 | } 225 | 226 | @media (max-width: 767px) { 227 | 228 | .inner-bg { 229 | padding: 60px 0 110px 0; 230 | } 231 | 232 | } 233 | 234 | @media (max-width: 415px) { 235 | 236 | h1, h2 { 237 | font-size: 32px; 238 | } 239 | 240 | } 241 | 242 | -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/detail.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | My Shop Plantform 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leader-us/SpringCloud_eShop/e0da11ba480f7043be40d7a1d1bbd3f0a33ba6ea/eshop-web/src/main/resources/static/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leader-us/SpringCloud_eShop/e0da11ba480f7043be40d7a1d1bbd3f0a33ba6ea/eshop-web/src/main/resources/static/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leader-us/SpringCloud_eShop/e0da11ba480f7043be40d7a1d1bbd3f0a33ba6ea/eshop-web/src/main/resources/static/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leader-us/SpringCloud_eShop/e0da11ba480f7043be40d7a1d1bbd3f0a33ba6ea/eshop-web/src/main/resources/static/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/img/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leader-us/SpringCloud_eShop/e0da11ba480f7043be40d7a1d1bbd3f0a33ba6ea/eshop-web/src/main/resources/static/img/background.jpg -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/js/bootbox.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * bootbox.js v4.4.0 3 | * 4 | * http://bootboxjs.com/license.txt 5 | */ 6 | !function(a,b){"use strict";"function"==typeof define&&define.amd?define(["../../../../../../../../../../Desktop/leader_class/video/全栈/第二季/spring-boot-study/src/main/resources/static/js/jquery"],b):"object"==typeof exports?module.exports=b(require("jquery")):a.bootbox=b(a.jQuery)}(this,function a(b, c){"use strict";function d(a){var b=q[o.locale];return b?b[a]:q.en[a]}function e(a, c, d){a.stopPropagation(),a.preventDefault();var e=b.isFunction(d)&&d.call(c,a)===!1;e||c.modal("hide")}function f(a){var b,c=0;for(b in a)c++;return c}function g(a, c){var d=0;b.each(a,function(a, b){c(a,b,d++)})}function h(a){var c,d;if("object"!=typeof a)throw new Error("Please supply an object of options");if(!a.message)throw new Error("Please specify a message");return a=b.extend({},o,a),a.buttons||(a.buttons={}),c=a.buttons,d=f(c),g(c,function(a,e,f){if(b.isFunction(e)&&(e=c[a]={callback:e}),"object"!==b.type(e))throw new Error("button with key "+a+" must be an object");e.label||(e.label=a),e.className||(e.className=2>=d&&f===d-1?"btn-primary":"btn-default")}),a}function i(a,b){var c=a.length,d={};if(1>c||c>2)throw new Error("Invalid argument length");return 2===c||"string"==typeof a[0]?(d[b[0]]=a[0],d[b[1]]=a[1]):d=a[0],d}function j(a,c,d){return b.extend(!0,{},a,i(c,d))}function k(a,b,c,d){var e={className:"bootbox-"+a,buttons:l.apply(null,b)};return m(j(e,d,c),b)}function l(){for(var a={},b=0,c=arguments.length;c>b;b++){var e=arguments[b],f=e.toLowerCase(),g=e.toUpperCase();a[f]={label:d(g)}}return a}function m(a,b){var d={};return g(b,function(a,b){d[b]=!0}),g(a.buttons,function(a){if(d[a]===c)throw new Error("button key "+a+" is not allowed (options are "+b.join("\n")+")")}),a}var n={dialog:"",header:"",footer:"",closeButton:"",form:"
",inputs:{text:"",textarea:"",email:"",select:"",checkbox:"
",date:"",time:"",number:"",password:""}},o={locale:"en",backdrop:"static",animate:!0,className:null,closeButton:!0,show:!0,container:"body"},p={};p.alert=function(){var a;if(a=k("alert",["ok"],["message","callback"],arguments),a.callback&&!b.isFunction(a.callback))throw new Error("alert requires callback property to be a function when provided");return a.buttons.ok.callback=a.onEscape=function(){return b.isFunction(a.callback)?a.callback.call(this):!0},p.dialog(a)},p.confirm=function(){var a;if(a=k("confirm",["cancel","confirm"],["message","callback"],arguments),a.buttons.cancel.callback=a.onEscape=function(){return a.callback.call(this,!1)},a.buttons.confirm.callback=function(){return a.callback.call(this,!0)},!b.isFunction(a.callback))throw new Error("confirm requires a callback");return p.dialog(a)},p.prompt=function(){var a,d,e,f,h,i,k;if(f=b(n.form),d={className:"bootbox-prompt",buttons:l("cancel","confirm"),value:"",inputType:"text"},a=m(j(d,arguments,["title","callback"]),["cancel","confirm"]),i=a.show===c?!0:a.show,a.message=f,a.buttons.cancel.callback=a.onEscape=function(){return a.callback.call(this,null)},a.buttons.confirm.callback=function(){var c;switch(a.inputType){case"text":case"textarea":case"email":case"select":case"date":case"time":case"number":case"password":c=h.val();break;case"checkbox":var d=h.find("input:checked");c=[],g(d,function(a,d){c.push(b(d).val())})}return a.callback.call(this,c)},a.show=!1,!a.title)throw new Error("prompt requires a title");if(!b.isFunction(a.callback))throw new Error("prompt requires a callback");if(!n.inputs[a.inputType])throw new Error("invalid prompt type");switch(h=b(n.inputs[a.inputType]),a.inputType){case"text":case"textarea":case"email":case"date":case"time":case"number":case"password":h.val(a.value);break;case"select":var o={};if(k=a.inputOptions||[],!b.isArray(k))throw new Error("Please pass an array of input options");if(!k.length)throw new Error("prompt with select requires options");g(k,function(a,d){var e=h;if(d.value===c||d.text===c)throw new Error("given options in wrong format");d.group&&(o[d.group]||(o[d.group]=b("").attr("label",d.group)),e=o[d.group]),e.append("")}),g(o,function(a,b){h.append(b)}),h.val(a.value);break;case"checkbox":var q=b.isArray(a.value)?a.value:[a.value];if(k=a.inputOptions||[],!k.length)throw new Error("prompt with checkbox requires options");if(!k[0].value||!k[0].text)throw new Error("given options in wrong format");h=b("
"),g(k,function(c,d){var e=b(n.inputs[a.inputType]);e.find("input").attr("value",d.value),e.find("label").append(d.text),g(q,function(a,b){b===d.value&&e.find("input").prop("checked",!0)}),h.append(e)})}return a.placeholder&&h.attr("placeholder",a.placeholder),a.pattern&&h.attr("pattern",a.pattern),a.maxlength&&h.attr("maxlength",a.maxlength),f.append(h),f.on("submit",function(a){a.preventDefault(),a.stopPropagation(),e.find(".btn-primary").click()}),e=p.dialog(a),e.off("shown.bs.modal"),e.on("shown.bs.modal",function(){h.focus()}),i===!0&&e.modal("show"),e},p.dialog=function(a){a=h(a);var d=b(n.dialog),f=d.find(".modal-dialog"),i=d.find(".modal-body"),j=a.buttons,k="",l={onEscape:a.onEscape};if(b.fn.modal===c)throw new Error("$.fn.modal is not defined; please double check you have included the Bootstrap JavaScript library. See http://getbootstrap.com/javascript/ for more details.");if(g(j,function(a,b){k+="",l[a]=b.callback}),i.find(".bootbox-body").html(a.message),a.animate===!0&&d.addClass("fade"),a.className&&d.addClass(a.className),"large"===a.size?f.addClass("modal-lg"):"small"===a.size&&f.addClass("modal-sm"),a.title&&i.before(n.header),a.closeButton){var m=b(n.closeButton);a.title?d.find(".modal-header").prepend(m):m.css("margin-top","-10px").prependTo(i)}return a.title&&d.find(".modal-title").html(a.title),k.length&&(i.after(n.footer),d.find(".modal-footer").html(k)),d.on("hidden.bs.modal",function(a){a.target===this&&d.remove()}),d.on("shown.bs.modal",function(){d.find(".btn-primary:first").focus()}),"static"!==a.backdrop&&d.on("click.dismiss.bs.modal",function(a){d.children(".modal-backdrop").length&&(a.currentTarget=d.children(".modal-backdrop").get(0)),a.target===a.currentTarget&&d.trigger("escape.close.bb")}),d.on("escape.close.bb",function(a){l.onEscape&&e(a,d,l.onEscape)}),d.on("click",".modal-footer button",function(a){var c=b(this).data("bb-handler");e(a,d,l[c])}),d.on("click",".bootbox-close-button",function(a){e(a,d,l.onEscape)}),d.on("keyup",function(a){27===a.which&&d.trigger("escape.close.bb")}),b(a.container).append(d),d.modal({backdrop:a.backdrop?"static":!1,keyboard:!1,show:!1}),a.show&&d.modal("show"),d},p.setDefaults=function(){var a={};2===arguments.length?a[arguments[0]]=arguments[1]:a=arguments[0],b.extend(o,a)},p.hideAll=function(){return b(".bootbox").modal("hide"),p};var q={bg_BG:{OK:"Ок",CANCEL:"Отказ",CONFIRM:"Потвърждавам"},br:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Sim"},cs:{OK:"OK",CANCEL:"Zrušit",CONFIRM:"Potvrdit"},da:{OK:"OK",CANCEL:"Annuller",CONFIRM:"Accepter"},de:{OK:"OK",CANCEL:"Abbrechen",CONFIRM:"Akzeptieren"},el:{OK:"Εντάξει",CANCEL:"Ακύρωση",CONFIRM:"Επιβεβαίωση"},en:{OK:"OK",CANCEL:"Cancel",CONFIRM:"OK"},es:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Aceptar"},et:{OK:"OK",CANCEL:"Katkesta",CONFIRM:"OK"},fa:{OK:"قبول",CANCEL:"لغو",CONFIRM:"تایید"},fi:{OK:"OK",CANCEL:"Peruuta",CONFIRM:"OK"},fr:{OK:"OK",CANCEL:"Annuler",CONFIRM:"D'accord"},he:{OK:"אישור",CANCEL:"ביטול",CONFIRM:"אישור"},hu:{OK:"OK",CANCEL:"Mégsem",CONFIRM:"Megerősít"},hr:{OK:"OK",CANCEL:"Odustani",CONFIRM:"Potvrdi"},id:{OK:"OK",CANCEL:"Batal",CONFIRM:"OK"},it:{OK:"OK",CANCEL:"Annulla",CONFIRM:"Conferma"},ja:{OK:"OK",CANCEL:"キャンセル",CONFIRM:"確認"},lt:{OK:"Gerai",CANCEL:"Atšaukti",CONFIRM:"Patvirtinti"},lv:{OK:"Labi",CANCEL:"Atcelt",CONFIRM:"Apstiprināt"},nl:{OK:"OK",CANCEL:"Annuleren",CONFIRM:"Accepteren"},no:{OK:"OK",CANCEL:"Avbryt",CONFIRM:"OK"},pl:{OK:"OK",CANCEL:"Anuluj",CONFIRM:"Potwierdź"},pt:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Confirmar"},ru:{OK:"OK",CANCEL:"Отмена",CONFIRM:"Применить"},sq:{OK:"OK",CANCEL:"Anulo",CONFIRM:"Prano"},sv:{OK:"OK",CANCEL:"Avbryt",CONFIRM:"OK"},th:{OK:"ตกลง",CANCEL:"ยกเลิก",CONFIRM:"ยืนยัน"},tr:{OK:"Tamam",CANCEL:"İptal",CONFIRM:"Onayla"},zh_CN:{OK:"OK",CANCEL:"取消",CONFIRM:"确认"},zh_TW:{OK:"OK",CANCEL:"取消",CONFIRM:"確認"}};return p.addLocale=function(a,c){return b.each(["OK","CANCEL","CONFIRM"],function(a,b){if(!c[b])throw new Error("Please supply a translation for '"+b+"'")}),q[a]={OK:c.OK,CANCEL:c.CANCEL,CONFIRM:c.CONFIRM},p},p.removeLocale=function(a){return delete q[a],p},p.setLocale=function(a){return p.setDefaults("locale",a)},p.init=function(c){return a(c||b)},p}); 7 | -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/js/cart.js: -------------------------------------------------------------------------------- 1 | $('.cart_table').bootstrapTable({ 2 | url: "/cart/records", 3 | method: "GET", 4 | columns: [{ 5 | field: 'productId', 6 | title: 'ID' 7 | }, { 8 | field: 'productName', 9 | title: '商品名称' 10 | }, { 11 | field: 'productPrice', 12 | title: '商品价格' 13 | },{ 14 | field: "count", 15 | title: '数量' 16 | }, { 17 | formatter: "amount_formatter", 18 | title: '总额' 19 | }], 20 | responseHandler: handler 21 | }); 22 | 23 | function handler(res) { 24 | if (res == undefined) { 25 | return res; 26 | } 27 | var directUrl = res.redirect; 28 | if (directUrl != undefined) { 29 | navi2page(directUrl); 30 | return "[]"; 31 | } 32 | return res; 33 | } 34 | 35 | 36 | function amount_formatter(value, row) { 37 | return row.productPrice * row.count; 38 | } 39 | -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/js/detail.js: -------------------------------------------------------------------------------- 1 | var id = getQueryString(curPageUrl, 'id'); 2 | var dataUrl = "/products/" + id; 3 | 4 | $('.product_detail_table').bootstrapTable({ 5 | url: dataUrl, 6 | method: "GET", 7 | columns: [{ 8 | field: 'id', 9 | title: 'ID' 10 | }, { 11 | field: 'name', 12 | title: '商品名称' 13 | }, { 14 | field: 'price', 15 | title: '商品价格' 16 | }, { 17 | field: 'desc', 18 | title: '商品描述' 19 | }], 20 | responseHandler: handler 21 | }); 22 | function handler(res) { 23 | return res; 24 | 25 | } -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/js/index.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function () { 2 | navi2page($(".navbar-brand").attr("data-page")); 3 | 4 | $("ul.navbar-nav li").each(function () { 5 | $(this).on("click", function (e) { 6 | var newPage = $(this).attr("data-page"); 7 | navi2page(newPage); 8 | }) 9 | }); 10 | 11 | $(".navbar-brand").on("click", function (e) { 12 | var newPage = $(this).attr("data-page"); 13 | navi2page(newPage); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/js/jquery.backstretch.min.js: -------------------------------------------------------------------------------- 1 | /*! Backstretch - v2.0.4 - 2013-06-19 2 | * http://srobbin.com/jquery-plugins/backstretch/ 3 | * Copyright (c) 2013 Scott Robbin; Licensed MIT */ 4 | (function(a,d,p){a.fn.backstretch=function(c,b){(c===p||0===c.length)&&a.error("No images were supplied for Backstretch");0===a(d).scrollTop()&&d.scrollTo(0,0);return this.each(function(){var d=a(this),g=d.data("backstretch");if(g){if("string"==typeof c&&"function"==typeof g[c]){g[c](b);return}b=a.extend(g.options,b);g.destroy(!0)}g=new q(this,c,b);d.data("backstretch",g)})};a.backstretch=function(c,b){return a("body").backstretch(c,b).data("backstretch")};a.expr[":"].backstretch=function(c){return a(c).data("backstretch")!==p};a.fn.backstretch.defaults={centeredX:!0,centeredY:!0,duration:5E3,fade:0};var r={left:0,top:0,overflow:"hidden",margin:0,padding:0,height:"100%",width:"100%",zIndex:-999999},s={position:"absolute",display:"none",margin:0,padding:0,border:"none",width:"auto",height:"auto",maxHeight:"none",maxWidth:"none",zIndex:-999999},q=function(c,b,e){this.options=a.extend({},a.fn.backstretch.defaults,e||{});this.images=a.isArray(b)?b:[b];a.each(this.images,function(){a("")[0].src=this});this.isBody=c===document.body;this.$container=a(c);this.$root=this.isBody?l?a(d):a(document):this.$container;c=this.$container.children(".backstretch").first();this.$wrap=c.length?c:a('
').css(r).appendTo(this.$container);this.isBody||(c=this.$container.css("position"),b=this.$container.css("zIndex"),this.$container.css({position:"static"===c?"relative":c,zIndex:"auto"===b?0:b,background:"none"}),this.$wrap.css({zIndex:-999998}));this.$wrap.css({position:this.isBody&&l?"fixed":"absolute"});this.index=0;this.show(this.index);a(d).on("resize.backstretch",a.proxy(this.resize,this)).on("orientationchange.backstretch",a.proxy(function(){this.isBody&&0===d.pageYOffset&&(d.scrollTo(0,1),this.resize())},this))};q.prototype={resize:function(){try{var a={left:0,top:0},b=this.isBody?this.$root.width():this.$root.innerWidth(),e=b,g=this.isBody?d.innerHeight?d.innerHeight:this.$root.height():this.$root.innerHeight(),j=e/this.$img.data("ratio"),f;j>=g?(f=(j-g)/2,this.options.centeredY&&(a.top="-"+f+"px")):(j=g,e=j*this.$img.data("ratio"),f=(e-b)/2,this.options.centeredX&&(a.left="-"+f+"px"));this.$wrap.css({width:b,height:g}).find("img:not(.deleteable)").css({width:e,height:j}).css(a)}catch(h){}return this},show:function(c){if(!(Math.abs(c)>this.images.length-1)){var b=this,e=b.$wrap.find("img").addClass("deleteable"),d={relatedTarget:b.$container[0]};b.$container.trigger(a.Event("backstretch.before",d),[b,c]);this.index=c;clearInterval(b.interval);b.$img=a("").css(s).bind("load",function(f){var h=this.width||a(f.target).width();f=this.height||a(f.target).height();a(this).data("ratio",h/f);a(this).fadeIn(b.options.speed||b.options.fade,function(){e.remove();b.paused||b.cycle();a(["after","show"]).each(function(){b.$container.trigger(a.Event("backstretch."+this,d),[b,c])})});b.resize()}).appendTo(b.$wrap);b.$img.attr("src",b.images[c]);return b}},next:function(){return this.show(this.indexe||d.operamini&&"[object OperaMini]"==={}.toString.call(d.operamini)||n&&7458>t||-1e||h&&6>h||"palmGetResource"in d&&e&&534>e||-1=k)})(jQuery,window); -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/js/json2.js: -------------------------------------------------------------------------------- 1 | // json2.js 2 | // 2016-10-28 3 | // Public Domain. 4 | // NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. 5 | // See http://www.JSON.org/js.html 6 | // This code should be minified before deployment. 7 | // See http://javascript.crockford.com/jsmin.html 8 | 9 | // USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO 10 | // NOT CONTROL. 11 | 12 | // This file creates a global JSON object containing two methods: stringify 13 | // and parse. This file provides the ES5 JSON capability to ES3 systems. 14 | // If a project might run on IE8 or earlier, then this file should be included. 15 | // This file does nothing on ES5 systems. 16 | 17 | // JSON.stringify(value, replacer, space) 18 | // value any JavaScript value, usually an object or array. 19 | // replacer an optional parameter that determines how object 20 | // values are stringified for objects. It can be a 21 | // function or an array of strings. 22 | // space an optional parameter that specifies the indentation 23 | // of nested structures. If it is omitted, the text will 24 | // be packed without extra whitespace. If it is a number, 25 | // it will specify the number of spaces to indent at each 26 | // level. If it is a string (such as "\t" or " "), 27 | // it contains the characters used to indent at each level. 28 | // This method produces a JSON text from a JavaScript value. 29 | // When an object value is found, if the object contains a toJSON 30 | // method, its toJSON method will be called and the result will be 31 | // stringified. A toJSON method does not serialize: it returns the 32 | // value represented by the name/value pair that should be serialized, 33 | // or undefined if nothing should be serialized. The toJSON method 34 | // will be passed the key associated with the value, and this will be 35 | // bound to the value. 36 | 37 | // For example, this would serialize Dates as ISO strings. 38 | 39 | // Date.prototype.toJSON = function (key) { 40 | // function f(n) { 41 | // // Format integers to have at least two digits. 42 | // return (n < 10) 43 | // ? "0" + n 44 | // : n; 45 | // } 46 | // return this.getUTCFullYear() + "-" + 47 | // f(this.getUTCMonth() + 1) + "-" + 48 | // f(this.getUTCDate()) + "T" + 49 | // f(this.getUTCHours()) + ":" + 50 | // f(this.getUTCMinutes()) + ":" + 51 | // f(this.getUTCSeconds()) + "Z"; 52 | // }; 53 | 54 | // You can provide an optional replacer method. It will be passed the 55 | // key and value of each member, with this bound to the containing 56 | // object. The value that is returned from your method will be 57 | // serialized. If your method returns undefined, then the member will 58 | // be excluded from the serialization. 59 | 60 | // If the replacer parameter is an array of strings, then it will be 61 | // used to select the members to be serialized. It filters the results 62 | // such that only members with keys listed in the replacer array are 63 | // stringified. 64 | 65 | // Values that do not have JSON representations, such as undefined or 66 | // functions, will not be serialized. Such values in objects will be 67 | // dropped; in arrays they will be replaced with null. You can use 68 | // a replacer function to replace those with JSON values. 69 | 70 | // JSON.stringify(undefined) returns undefined. 71 | 72 | // The optional space parameter produces a stringification of the 73 | // value that is filled with line breaks and indentation to make it 74 | // easier to read. 75 | 76 | // If the space parameter is a non-empty string, then that string will 77 | // be used for indentation. If the space parameter is a number, then 78 | // the indentation will be that many spaces. 79 | 80 | // Example: 81 | 82 | // text = JSON.stringify(["e", {pluribus: "unum"}]); 83 | // // text is '["e",{"pluribus":"unum"}]' 84 | 85 | // text = JSON.stringify(["e", {pluribus: "unum"}], null, "\t"); 86 | // // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' 87 | 88 | // text = JSON.stringify([new Date()], function (key, value) { 89 | // return this[key] instanceof Date 90 | // ? "Date(" + this[key] + ")" 91 | // : value; 92 | // }); 93 | // // text is '["Date(---current time---)"]' 94 | 95 | // JSON.parse(text, reviver) 96 | // This method parses a JSON text to produce an object or array. 97 | // It can throw a SyntaxError exception. 98 | 99 | // The optional reviver parameter is a function that can filter and 100 | // transform the results. It receives each of the keys and values, 101 | // and its return value is used instead of the original value. 102 | // If it returns what it received, then the structure is not modified. 103 | // If it returns undefined then the member is deleted. 104 | 105 | // Example: 106 | 107 | // // Parse the text. Values that look like ISO date strings will 108 | // // be converted to Date objects. 109 | 110 | // myData = JSON.parse(text, function (key, value) { 111 | // var a; 112 | // if (typeof value === "string") { 113 | // a = 114 | // /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); 115 | // if (a) { 116 | // return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], 117 | // +a[5], +a[6])); 118 | // } 119 | // } 120 | // return value; 121 | // }); 122 | 123 | // myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { 124 | // var d; 125 | // if (typeof value === "string" && 126 | // value.slice(0, 5) === "Date(" && 127 | // value.slice(-1) === ")") { 128 | // d = new Date(value.slice(5, -1)); 129 | // if (d) { 130 | // return d; 131 | // } 132 | // } 133 | // return value; 134 | // }); 135 | 136 | // This is a reference implementation. You are free to copy, modify, or 137 | // redistribute. 138 | 139 | /*jslint 140 | eval, for, this 141 | */ 142 | 143 | /*property 144 | JSON, apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, 145 | getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, 146 | lastIndex, length, parse, prototype, push, replace, slice, stringify, 147 | test, toJSON, toString, valueOf 148 | */ 149 | 150 | 151 | // Create a JSON object only if one does not already exist. We create the 152 | // methods in a closure to avoid creating global variables. 153 | 154 | if (typeof JSON !== "object") { 155 | JSON = {}; 156 | } 157 | 158 | (function () { 159 | "use strict"; 160 | 161 | var rx_one = /^[\],:{}\s]*$/; 162 | var rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g; 163 | var rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g; 164 | var rx_four = /(?:^|:|,)(?:\s*\[)+/g; 165 | var rx_escapable = /[\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; 166 | var rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; 167 | 168 | function f(n) { 169 | // Format integers to have at least two digits. 170 | return n < 10 171 | ? "0" + n 172 | : n; 173 | } 174 | 175 | function this_value() { 176 | return this.valueOf(); 177 | } 178 | 179 | if (typeof Date.prototype.toJSON !== "function") { 180 | 181 | Date.prototype.toJSON = function () { 182 | 183 | return isFinite(this.valueOf()) 184 | ? this.getUTCFullYear() + "-" + 185 | f(this.getUTCMonth() + 1) + "-" + 186 | f(this.getUTCDate()) + "T" + 187 | f(this.getUTCHours()) + ":" + 188 | f(this.getUTCMinutes()) + ":" + 189 | f(this.getUTCSeconds()) + "Z" 190 | : null; 191 | }; 192 | 193 | Boolean.prototype.toJSON = this_value; 194 | Number.prototype.toJSON = this_value; 195 | String.prototype.toJSON = this_value; 196 | } 197 | 198 | var gap; 199 | var indent; 200 | var meta; 201 | var rep; 202 | 203 | 204 | function quote(string) { 205 | 206 | // If the string contains no control characters, no quote characters, and no 207 | // backslash characters, then we can safely slap some quotes around it. 208 | // Otherwise we must also replace the offending characters with safe escape 209 | // sequences. 210 | 211 | rx_escapable.lastIndex = 0; 212 | return rx_escapable.test(string) 213 | ? "\"" + string.replace(rx_escapable, function (a) { 214 | var c = meta[a]; 215 | return typeof c === "string" 216 | ? c 217 | : "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4); 218 | }) + "\"" 219 | : "\"" + string + "\""; 220 | } 221 | 222 | 223 | function str(key, holder) { 224 | 225 | // Produce a string from holder[key]. 226 | 227 | var i; // The loop counter. 228 | var k; // The member key. 229 | var v; // The member value. 230 | var length; 231 | var mind = gap; 232 | var partial; 233 | var value = holder[key]; 234 | 235 | // If the value has a toJSON method, call it to obtain a replacement value. 236 | 237 | if (value && typeof value === "object" && 238 | typeof value.toJSON === "function") { 239 | value = value.toJSON(key); 240 | } 241 | 242 | // If we were called with a replacer function, then call the replacer to 243 | // obtain a replacement value. 244 | 245 | if (typeof rep === "function") { 246 | value = rep.call(holder, key, value); 247 | } 248 | 249 | // What happens next depends on the value's type. 250 | 251 | switch (typeof value) { 252 | case "string": 253 | return quote(value); 254 | 255 | case "number": 256 | 257 | // JSON numbers must be finite. Encode non-finite numbers as null. 258 | 259 | return isFinite(value) 260 | ? String(value) 261 | : "null"; 262 | 263 | case "boolean": 264 | case "null": 265 | 266 | // If the value is a boolean or null, convert it to a string. Note: 267 | // typeof null does not produce "null". The case is included here in 268 | // the remote chance that this gets fixed someday. 269 | 270 | return String(value); 271 | 272 | // If the type is "object", we might be dealing with an object or an array or 273 | // null. 274 | 275 | case "object": 276 | 277 | // Due to a specification blunder in ECMAScript, typeof null is "object", 278 | // so watch out for that case. 279 | 280 | if (!value) { 281 | return "null"; 282 | } 283 | 284 | // Make an array to hold the partial results of stringifying this object value. 285 | 286 | gap += indent; 287 | partial = []; 288 | 289 | // Is the value an array? 290 | 291 | if (Object.prototype.toString.apply(value) === "[object Array]") { 292 | 293 | // The value is an array. Stringify every element. Use null as a placeholder 294 | // for non-JSON values. 295 | 296 | length = value.length; 297 | for (i = 0; i < length; i += 1) { 298 | partial[i] = str(i, value) || "null"; 299 | } 300 | 301 | // Join all of the elements together, separated with commas, and wrap them in 302 | // brackets. 303 | 304 | v = partial.length === 0 305 | ? "[]" 306 | : gap 307 | ? "[\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "]" 308 | : "[" + partial.join(",") + "]"; 309 | gap = mind; 310 | return v; 311 | } 312 | 313 | // If the replacer is an array, use it to select the members to be stringified. 314 | 315 | if (rep && typeof rep === "object") { 316 | length = rep.length; 317 | for (i = 0; i < length; i += 1) { 318 | if (typeof rep[i] === "string") { 319 | k = rep[i]; 320 | v = str(k, value); 321 | if (v) { 322 | partial.push(quote(k) + ( 323 | gap 324 | ? ": " 325 | : ":" 326 | ) + v); 327 | } 328 | } 329 | } 330 | } else { 331 | 332 | // Otherwise, iterate through all of the keys in the object. 333 | 334 | for (k in value) { 335 | if (Object.prototype.hasOwnProperty.call(value, k)) { 336 | v = str(k, value); 337 | if (v) { 338 | partial.push(quote(k) + ( 339 | gap 340 | ? ": " 341 | : ":" 342 | ) + v); 343 | } 344 | } 345 | } 346 | } 347 | 348 | // Join all of the member texts together, separated with commas, 349 | // and wrap them in braces. 350 | 351 | v = partial.length === 0 352 | ? "{}" 353 | : gap 354 | ? "{\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "}" 355 | : "{" + partial.join(",") + "}"; 356 | gap = mind; 357 | return v; 358 | } 359 | } 360 | 361 | // If the JSON object does not yet have a stringify method, give it one. 362 | 363 | if (typeof JSON.stringify !== "function") { 364 | meta = { // table of character substitutions 365 | "\b": "\\b", 366 | "\t": "\\t", 367 | "\n": "\\n", 368 | "\f": "\\f", 369 | "\r": "\\r", 370 | "\"": "\\\"", 371 | "\\": "\\\\" 372 | }; 373 | JSON.stringify = function (value, replacer, space) { 374 | 375 | // The stringify method takes a value and an optional replacer, and an optional 376 | // space parameter, and returns a JSON text. The replacer can be a function 377 | // that can replace values, or an array of strings that will select the keys. 378 | // A default replacer method can be provided. Use of the space parameter can 379 | // produce text that is more easily readable. 380 | 381 | var i; 382 | gap = ""; 383 | indent = ""; 384 | 385 | // If the space parameter is a number, make an indent string containing that 386 | // many spaces. 387 | 388 | if (typeof space === "number") { 389 | for (i = 0; i < space; i += 1) { 390 | indent += " "; 391 | } 392 | 393 | // If the space parameter is a string, it will be used as the indent string. 394 | 395 | } else if (typeof space === "string") { 396 | indent = space; 397 | } 398 | 399 | // If there is a replacer, it must be a function or an array. 400 | // Otherwise, throw an error. 401 | 402 | rep = replacer; 403 | if (replacer && typeof replacer !== "function" && 404 | (typeof replacer !== "object" || 405 | typeof replacer.length !== "number")) { 406 | throw new Error("JSON.stringify"); 407 | } 408 | 409 | // Make a fake root object containing our value under the key of "". 410 | // Return the result of stringifying the value. 411 | 412 | return str("", {"": value}); 413 | }; 414 | } 415 | 416 | 417 | // If the JSON object does not yet have a parse method, give it one. 418 | 419 | if (typeof JSON.parse !== "function") { 420 | JSON.parse = function (text, reviver) { 421 | 422 | // The parse method takes a text and an optional reviver function, and returns 423 | // a JavaScript value if the text is a valid JSON text. 424 | 425 | var j; 426 | 427 | function walk(holder, key) { 428 | 429 | // The walk method is used to recursively walk the resulting structure so 430 | // that modifications can be made. 431 | 432 | var k; 433 | var v; 434 | var value = holder[key]; 435 | if (value && typeof value === "object") { 436 | for (k in value) { 437 | if (Object.prototype.hasOwnProperty.call(value, k)) { 438 | v = walk(value, k); 439 | if (v !== undefined) { 440 | value[k] = v; 441 | } else { 442 | delete value[k]; 443 | } 444 | } 445 | } 446 | } 447 | return reviver.call(holder, key, value); 448 | } 449 | 450 | 451 | // Parsing happens in four stages. In the first stage, we replace certain 452 | // Unicode characters with escape sequences. JavaScript handles many characters 453 | // incorrectly, either silently deleting them, or treating them as line endings. 454 | 455 | text = String(text); 456 | rx_dangerous.lastIndex = 0; 457 | if (rx_dangerous.test(text)) { 458 | text = text.replace(rx_dangerous, function (a) { 459 | return "\\u" + 460 | ("0000" + a.charCodeAt(0).toString(16)).slice(-4); 461 | }); 462 | } 463 | 464 | // In the second stage, we run the text against regular expressions that look 465 | // for non-JSON patterns. We are especially concerned with "()" and "new" 466 | // because they can cause invocation, and "=" because it can cause mutation. 467 | // But just to be safe, we want to reject all unexpected forms. 468 | 469 | // We split the second stage into 4 regexp operations in order to work around 470 | // crippling inefficiencies in IE's and Safari's regexp engines. First we 471 | // replace the JSON backslash pairs with "@" (a non-JSON character). Second, we 472 | // replace all simple value tokens with "]" characters. Third, we delete all 473 | // open brackets that follow a colon or comma or that begin the text. Finally, 474 | // we look to see that the remaining characters are only whitespace or "]" or 475 | // "," or ":" or "{" or "}". If that is so, then the text is safe for eval. 476 | 477 | if ( 478 | rx_one.test( 479 | text 480 | .replace(rx_two, "@") 481 | .replace(rx_three, "]") 482 | .replace(rx_four, "") 483 | ) 484 | ) { 485 | 486 | // In the third stage we use the eval function to compile the text into a 487 | // JavaScript structure. The "{" operator is subject to a syntactic ambiguity 488 | // in JavaScript: it can begin a block or an object literal. We wrap the text 489 | // in parens to eliminate the ambiguity. 490 | 491 | j = eval("(" + text + ")"); 492 | 493 | // In the optional fourth stage, we recursively walk the new structure, passing 494 | // each name/value pair to a reviver function for possible transformation. 495 | 496 | return (typeof reviver === "function") 497 | ? walk({"": j}, "") 498 | : j; 499 | } 500 | 501 | // If the text is not JSON parseable, then a SyntaxError is thrown. 502 | 503 | throw new SyntaxError("JSON.parse"); 504 | }; 505 | } 506 | }()); 507 | -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/js/main.js: -------------------------------------------------------------------------------- 1 | var curPageUrl; 2 | var prePageUrl; 3 | 4 | function navi2page(newpage) { 5 | prePageUrl = curPageUrl; 6 | curPageUrl = newpage; 7 | $("#bodymain").load(newpage); 8 | } 9 | 10 | function back2page() { 11 | curPageUrl = prePageUrl; 12 | $("#bodymain").load(curPageUrl); 13 | } 14 | -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/js/product.js: -------------------------------------------------------------------------------- 1 | function oper_detail(value, row) { 2 | var href = "/detail.html?id=" + row.id; 3 | return "商品详情"; 4 | } 5 | 6 | function oper_cart(value, row) { 7 | var json = { 8 | productId: row.id, 9 | productName: row.name, 10 | productPrice: row.price, 11 | count: 1 12 | }; 13 | return "加入购物车"; 14 | } 15 | 16 | function addToCart(row) { 17 | var reqUrl = "/cart/add-cart"; 18 | $.ajax({ 19 | type: 'POST', 20 | url: reqUrl, 21 | data: JSON.stringify(row), 22 | dataType: 'json', 23 | contentType: "application/json ; charset=utf-8", 24 | success: function (data) { 25 | var code = data.code; 26 | if (code != undefined) { 27 | if (code == 200) { 28 | navi2page("/cart.html"); 29 | } else if (code == 503) { 30 | navi2page("/login.html"); 31 | } else { 32 | alert("add to cart error"); 33 | } 34 | return; 35 | } 36 | var directUrl = data.redirect; 37 | if (directUrl != undefined) { 38 | navi2page(directUrl); 39 | return; 40 | } 41 | } 42 | }); 43 | }; 44 | -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/js/urlparam.js: -------------------------------------------------------------------------------- 1 | function getQueryString(url, paramName) { 2 | var result = ""; 3 | if (!url.length) return result; 4 | var parts = url.split(/\?|\&/); 5 | for (var i = 0, len = parts.length; i < len; i++) { 6 | var tokens = parts[i].split("="); 7 | if (tokens[0] == paramName) { 8 | return decodeURIComponent(tokens[1]); 9 | } 10 | } 11 | return result; 12 | } 13 | -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | My Shop Plantform 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | My Shop Plantform 6 | 7 | 8 | 9 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 40 | 41 |
42 | 43 | 44 | -------------------------------------------------------------------------------- /eshop-web/src/main/resources/static/product.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | My Shop Plantform 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
ID商品名称商品价格商品描述加入购物车
29 | 30 | 31 | -------------------------------------------------------------------------------- /eureka-server/pom.xml: -------------------------------------------------------------------------------- 1 |  3 | 4.0.0 4 | 5 | Springcloud_eShop 6 | Springcloud_eShop 7 | 0.0.1-SNAPSHOT 8 | 9 | sc_eureka-server 10 | sc_eureka-server 11 | jar 12 | 13 | 14 | org.springframework.cloud 15 | spring-cloud-starter-eureka-server 16 | ${spring.cloud.version} 17 | 18 | 19 | 20 | 21 | eshop_eureka-server 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-maven-plugin 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /eureka-server/src/main/java/com/mycat/monoeshop/App.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 6 | 7 | /** 8 | * Desc: 9 | * 10 | * @date: 27/08/2017 11 | * @author: Leader us 12 | */ 13 | @SpringBootApplication 14 | @EnableEurekaServer 15 | public class App { 16 | 17 | public static void main(String[] args) { 18 | SpringApplication.run(App.class, args); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /eureka-server/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: micro-eureka-server 4 | info: 5 | app: 6 | name: ${spring.application.name} 7 | version: v1.0.0 8 | logging: 9 | config: classpath:logback.xml 10 | server: 11 | port: 8030 12 | context-path: / 13 | tomcat: 14 | uri-encoding: UTF-8 15 | eureka: 16 | instance: 17 | hostname: 127.0.0.1 18 | prefer-ip-address: true 19 | client: 20 | registerWithEureka: false 21 | fetchRegistry: false 22 | service-url: 23 | defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ -------------------------------------------------------------------------------- /eureka-server/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | Springcloud_eShop 5 | Springcloud_eShop 6 | 0.0.1-SNAPSHOT 7 | pom 8 | 9 | org.springframework.boot 10 | spring-boot-starter-parent 11 | 1.5.3.RELEASE 12 | 13 | 14 | 15 | UTF-8 16 | UTF-8 17 | UTF-8 18 | 1.8 19 | 1.1.1 20 | 1.0.29 21 | 2.4 22 | 1.3.4.RELEASE 23 | 24 | 25 | 26 | eureka-server 27 | zuul-gateway 28 | cart-service 29 | auth-service 30 | product-service 31 | eshop-web 32 | 33 | 34 | 35 | 36 | org.springframework.cloud 37 | spring-cloud-starter-eureka 38 | ${spring.cloud.version} 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-starter-actuator 43 | 44 | 45 | commons-io 46 | commons-io 47 | ${commons.io.version} 48 | 49 | 50 | 51 | ch.qos.logback 52 | logback-classic 53 | 54 | 55 | 57 | 58 | 59 | 60 | 61 | 62 | org.springframework.boot 63 | spring-boot-maven-plugin 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /product-service/pom.xml: -------------------------------------------------------------------------------- 1 |  3 | 4.0.0 4 | 5 | Springcloud_eShop 6 | Springcloud_eShop 7 | 0.0.1-SNAPSHOT 8 | 9 | sc_product-service 10 | sc_product-service 11 | jar 12 | 13 | UTF-8 14 | UTF-8 15 | UTF-8 16 | 1.8 17 | 1.1.1 18 | 1.0.29 19 | 2.4 20 | 21 | 22 | 23 | com.alibaba 24 | druid 25 | ${druid.version} 26 | 27 | 28 | org.mybatis.spring.boot 29 | mybatis-spring-boot-starter 30 | ${mybatis.version} 31 | 32 | 33 | mysql 34 | mysql-connector-java 35 | 36 | 37 | 38 | 39 | eshop_sc_product-service 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-maven-plugin 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /product-service/src/main/java/com/mycat/monoeshop/App.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 7 | 8 | /** 9 | * Desc: 10 | * 11 | * @date: 27/08/2017 12 | * @author: Leader us 13 | */ 14 | @SpringBootApplication 15 | @MapperScan("com.mycat.monoeshop.mapper") 16 | @EnableDiscoveryClient 17 | public class App { 18 | 19 | public static void main(String[] args) { 20 | SpringApplication.run(App.class, args); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /product-service/src/main/java/com/mycat/monoeshop/config/MyAppConfig.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.config; 2 | 3 | import javax.sql.DataSource; 4 | 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | import org.springframework.cache.annotation.CachingConfigurerSupport; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | import com.alibaba.druid.pool.DruidDataSource; 11 | 12 | /** 13 | * Desc: 14 | * 15 | * @date: 27/08/2017 16 | * @author: Leader us 17 | */ 18 | @Configuration 19 | public class MyAppConfig extends CachingConfigurerSupport { 20 | 21 | @Configuration 22 | public class DruidDataSourceConfig { 23 | @Bean 24 | @ConfigurationProperties(prefix = "spring.datasource") 25 | public DataSource druidDataSource() { 26 | DruidDataSource druidDataSource = new DruidDataSource(); 27 | return druidDataSource; 28 | } 29 | } 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /product-service/src/main/java/com/mycat/monoeshop/mapper/ProductMapper.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.mapper; 2 | 3 | import java.util.List; 4 | 5 | import org.apache.ibatis.annotations.Select; 6 | 7 | import com.mycat.monoeshop.model.Product; 8 | 9 | /** 10 | * Desc: 11 | * 12 | * @date: 27/08/2017 13 | * @author: Leader us 14 | */ 15 | public interface ProductMapper { 16 | @Select("select * from product") 17 | List getProducts(); 18 | 19 | @Select("select * from product where id=#{id,jdbcType=INTEGER}") 20 | Product getProductById(Integer id); 21 | } 22 | -------------------------------------------------------------------------------- /product-service/src/main/java/com/mycat/monoeshop/model/Product.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.model; 2 | 3 | import java.math.BigDecimal; 4 | 5 | /** 6 | * Desc: 7 | * 8 | * @date: 27/08/2017 9 | * @author: Leader us 10 | */ 11 | public class Product { 12 | private Integer id; 13 | private String name; 14 | private BigDecimal price; 15 | private String desc; 16 | 17 | public Integer getId() { 18 | return id; 19 | } 20 | 21 | public void setId(Integer id) { 22 | this.id = id; 23 | } 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | 29 | public void setName(String name) { 30 | this.name = name; 31 | } 32 | 33 | public BigDecimal getPrice() { 34 | return price; 35 | } 36 | 37 | public void setPrice(BigDecimal price) { 38 | this.price = price; 39 | } 40 | 41 | public String getDesc() { 42 | return desc; 43 | } 44 | 45 | public void setDesc(String desc) { 46 | this.desc = desc; 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | return "Product{" + 52 | "id=" + id + 53 | ", name='" + name + '\'' + 54 | ", price=" + price + 55 | ", desc='" + desc + '\'' + 56 | '}'; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /product-service/src/main/java/com/mycat/monoeshop/rest/ProductRestService.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.rest; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.PathVariable; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.ResponseBody; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | import com.mycat.monoeshop.model.Product; 12 | import com.mycat.monoeshop.service.ProductService; 13 | 14 | /** 15 | * Desc: 16 | * 17 | * @date: 27/08/2017 18 | * @author: Leader us 19 | */ 20 | @RestController 21 | @RequestMapping("/products") 22 | public class ProductRestService { 23 | @Autowired 24 | private ProductService productService; 25 | 26 | @RequestMapping("/all") 27 | @ResponseBody 28 | public List getProducts() { 29 | return productService.getProducts(); 30 | } 31 | 32 | @RequestMapping("/{id}") 33 | @ResponseBody 34 | public Product getProductById(@PathVariable Integer id) { 35 | return productService.getProductById(id); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /product-service/src/main/java/com/mycat/monoeshop/service/ProductService.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.service; 2 | 3 | import java.util.List; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Service; 9 | 10 | import com.mycat.monoeshop.mapper.ProductMapper; 11 | import com.mycat.monoeshop.model.Product; 12 | 13 | /** 14 | * Desc: 15 | * 16 | * @date: 27/08/2017 17 | * @author: Leader us 18 | */ 19 | @Service 20 | public class ProductService { 21 | private static final Logger LOGGER = LoggerFactory.getLogger(ProductService.class); 22 | 23 | @Autowired 24 | private ProductMapper productMapper; 25 | 26 | public List getProducts() { 27 | LOGGER.info("request for all products"); 28 | List products = productMapper.getProducts(); 29 | LOGGER.info("product size: {}", products == null ? 0 : products.size()); 30 | return products; 31 | } 32 | 33 | public Product getProductById(Integer id) { 34 | 35 | Product result=productMapper.getProductById(id); 36 | LOGGER.info("request for productId: {},founded {}", id,result!=null); 37 | return result; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /product-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: eshop-product-service 4 | datasource: 5 | type: com.alibaba.druid.pool.DruidDataSource 6 | url: jdbc:mysql://192.168.18.134:3306/HPE_APP?useSSL=false 7 | username: lession 8 | password: mypass 9 | driver-class-name: com.mysql.jdbc.Driver 10 | initialSize: 2 11 | minIdle: 2 12 | maxActive: 20 13 | maxWait: 60000 14 | timeBetweenEvictionRunsMillis: 60000 15 | minEvictableIdleTimeMillis: 300000 16 | validationQuery: SELECT 1 FROM DUAL 17 | testWhileIdle: true 18 | testOnBorrow: true 19 | testOnReturn: false 20 | poolPreparedStatements: true 21 | maxPoolPreparedStatementPerConnectionSize: 20 22 | schema: classpath:create-db.sql 23 | data: classpath:demo-data.sql 24 | initialize: true 25 | continueOnError: true 26 | info: 27 | app: 28 | name: ${spring.application.name} 29 | version: v1.0.0 30 | server: 31 | port: 8036 32 | context-path: / 33 | tomcat: 34 | uri-encoding: UTF-8 35 | 36 | logging: 37 | config: classpath:logback.xml 38 | eureka: 39 | instance: 40 | hostname: 127.0.0.1 41 | prefer-ip-address: true 42 | client: 43 | healthcheck: 44 | enabled: true 45 | registerWithEureka: true 46 | fetchRegistry: true 47 | service-url: 48 | defaultZone: http://127.0.0.1:8030/eureka/ 49 | 50 | -------------------------------------------------------------------------------- /product-service/src/main/resources/create-db.sql: -------------------------------------------------------------------------------- 1 | --创建product表 2 | CREATE TABLE IF NOT EXISTS `product`( 3 | `id` INT, 4 | `name` VARCHAR(20), 5 | `price` DECIMAL(10,2), 6 | `desc` VARCHAR(20), 7 | PRIMARY KEY ( `id` ) 8 | )ENGINE=InnoDB DEFAULT CHARSET=utf8; -------------------------------------------------------------------------------- /product-service/src/main/resources/demo-data.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO product VALUES (1,'Apple',5,'Real apple'); 2 | INSERT INTO product VALUES (2,'Car',10000,'Good car'); 3 | INSERT INTO product VALUES (3,'House',20000,'Big House'); -------------------------------------------------------------------------------- /product-service/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /zuul-gateway/pom.xml: -------------------------------------------------------------------------------- 1 |  3 | 4.0.0 4 | 5 | Springcloud_eShop 6 | Springcloud_eShop 7 | 0.0.1-SNAPSHOT 8 | 9 | sc_zuul-gateway 10 | sc_zuul-gateway 11 | jar 12 | 13 | 14 | org.springframework.boot 15 | spring-boot-starter-web 16 | 17 | 18 | org.springframework.boot 19 | spring-boot-starter-data-redis 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-starter-logging 24 | 25 | 26 | 27 | 28 | org.springframework.session 29 | spring-session-data-redis 30 | 31 | 32 | org.springframework.cloud 33 | spring-cloud-starter-zuul 34 | ${spring.cloud.version} 35 | 36 | 37 | com.fasterxml.jackson.core 38 | jackson-core 39 | 40 | 41 | com.fasterxml.jackson.core 42 | jackson-annotations 43 | 44 | 45 | com.fasterxml.jackson.core 46 | jackson-databind 47 | 48 | 49 | 50 | 51 | 52 | eshop_zuul-gateway 53 | 54 | 55 | org.springframework.boot 56 | spring-boot-maven-plugin 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /zuul-gateway/src/main/java/com/mycat/monoeshop/App.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.zuul.EnableZuulProxy; 6 | import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; 7 | 8 | /** 9 | * Desc: 10 | * 11 | * @date: 27/08/2017 12 | * @author: Leader us 13 | */ 14 | @SpringBootApplication 15 | @EnableRedisHttpSession 16 | @EnableZuulProxy 17 | public class App { 18 | /** 19 | * 记录用户Session是否登录过 20 | */ 21 | public final static String SESSION_KEY = "user_sid"; 22 | 23 | public static void main(String[] args) { 24 | SpringApplication.run(App.class, args); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /zuul-gateway/src/main/java/com/mycat/monoeshop/config/FilterConfig.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | import com.mycat.monoeshop.filter.LoginPostFilter; 7 | import com.mycat.monoeshop.filter.SecurityPreFilter; 8 | import com.netflix.zuul.ZuulFilter; 9 | 10 | /** 11 | * Desc: 12 | * 13 | * @date: 02/07/2017 14 | * @author: gaozhiwen 15 | */ 16 | @Configuration 17 | public class FilterConfig { 18 | @Bean 19 | public ZuulFilter securityPreFilter() { 20 | return new SecurityPreFilter(); 21 | } 22 | 23 | @Bean 24 | public ZuulFilter loginPostFilter() { 25 | return new LoginPostFilter(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /zuul-gateway/src/main/java/com/mycat/monoeshop/config/MyAppConfig.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.config; 2 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 3 | import com.fasterxml.jackson.annotation.PropertyAccessor; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | 6 | import javax.sql.DataSource; 7 | 8 | import org.springframework.boot.context.properties.ConfigurationProperties; 9 | import org.springframework.cache.CacheManager; 10 | import org.springframework.cache.annotation.CachingConfigurerSupport; 11 | import org.springframework.context.annotation.Bean; 12 | import org.springframework.context.annotation.Configuration; 13 | import org.springframework.data.redis.cache.RedisCacheManager; 14 | import org.springframework.data.redis.connection.RedisConnectionFactory; 15 | import org.springframework.data.redis.core.RedisTemplate; 16 | import org.springframework.data.redis.core.StringRedisTemplate; 17 | import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; 18 | import org.springframework.data.redis.serializer.RedisSerializer; 19 | import org.springframework.data.redis.serializer.StringRedisSerializer; 20 | 21 | /** 22 | * Desc: 23 | * 24 | * @date: 27/08/2017 25 | * @author: Leader us 26 | */ 27 | @Configuration 28 | public class MyAppConfig extends CachingConfigurerSupport { 29 | 30 | @Bean 31 | public CacheManager cacheManager(RedisTemplate redisTemplate) { 32 | RedisCacheManager rcm = new RedisCacheManager(redisTemplate); 33 | // 设置缓存过期时间 34 | // rcm.setDefaultExpiration(60);//秒 35 | return rcm; 36 | 37 | } 38 | 39 | /** 40 | * RedisTemplate配置 41 | */ 42 | @Bean 43 | public RedisTemplate redisTemplate(RedisConnectionFactory factory) { 44 | StringRedisTemplate template = new StringRedisTemplate(factory); 45 | // 定义key序列化方式 46 | RedisSerializer redisSerializer = new StringRedisSerializer();// Long类型会出现异常信息;需要我们上面的自定义key生成策略,一般没必要 47 | // 定义value的序列化方式 48 | Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); 49 | ObjectMapper om = new ObjectMapper(); 50 | om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); 51 | om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); 52 | jackson2JsonRedisSerializer.setObjectMapper(om); 53 | 54 | template.setKeySerializer(jackson2JsonRedisSerializer); 55 | template.setValueSerializer(jackson2JsonRedisSerializer); 56 | template.setHashKeySerializer(jackson2JsonRedisSerializer); 57 | template.setHashValueSerializer(jackson2JsonRedisSerializer); 58 | template.afterPropertiesSet(); 59 | return template; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /zuul-gateway/src/main/java/com/mycat/monoeshop/controller/SessionController.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.controller; 2 | 3 | import org.apache.commons.lang.StringUtils; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | import com.mycat.monoeshop.App; 10 | import com.mycat.monoeshop.model.Result; 11 | import com.mycat.monoeshop.model.ResultEnum; 12 | 13 | import java.util.Arrays; 14 | import java.util.stream.Stream; 15 | 16 | import javax.servlet.http.HttpServletRequest; 17 | 18 | /** 19 | * Desc: 20 | * 21 | * @date: 27/08/2017 22 | * @author: Leader us 23 | */ 24 | @RestController 25 | public class SessionController { 26 | private static final Logger LOGGER = LoggerFactory.getLogger(SessionController.class); 27 | 28 | @GetMapping("/session/token") 29 | public Result checkToken(HttpServletRequest request) { 30 | Result result = null; 31 | LOGGER.info("session cookied: {}",Arrays.toString(request.getCookies())); 32 | Stream.of(request.getCookies()).forEach(a -> {System.out.println("xxx cookie "+a.getName()+" "+a.getValue());}); 33 | String sessionToken = (String) request.getSession().getAttribute(App.SESSION_KEY); 34 | 35 | if (StringUtils.isEmpty(sessionToken)) { 36 | LOGGER.warn("no session key found ,shoud login "); 37 | result = new Result(ResultEnum.NOT_LOGIN); 38 | } else { 39 | LOGGER.info(" session key found ,ok , session id "+request.getSession().getId()+" "+sessionToken); 40 | result = new Result(ResultEnum.SUCCESS); 41 | } 42 | return result; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /zuul-gateway/src/main/java/com/mycat/monoeshop/filter/JacksonUtil.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.filter; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.core.JsonParser; 5 | import com.fasterxml.jackson.core.Version; 6 | import com.fasterxml.jackson.databind.DeserializationFeature; 7 | import com.fasterxml.jackson.databind.JavaType; 8 | import com.fasterxml.jackson.databind.ObjectMapper; 9 | import com.fasterxml.jackson.databind.SerializationFeature; 10 | import com.fasterxml.jackson.databind.module.SimpleModule; 11 | import org.apache.commons.lang.StringUtils; 12 | 13 | import java.util.List; 14 | 15 | public class JacksonUtil { 16 | private final static ObjectMapper objectMapper = new ObjectMapper(); 17 | 18 | static { 19 | SimpleModule simpleModule = new SimpleModule("SimpleJodaModule", new Version(1, 0, 0, null, null, null)); 20 | objectMapper.registerModule(simpleModule); 21 | objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 22 | objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true); 23 | objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); 24 | objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); 25 | objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true); 26 | objectMapper.configure(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS, true); 27 | objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true); 28 | objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 29 | } 30 | 31 | public static String encode(Object obj) { 32 | try { 33 | return objectMapper.writeValueAsString(obj); 34 | } catch (Exception ignored) { 35 | } 36 | return null; 37 | } 38 | 39 | /** 40 | * 将json string反序列化成对象 41 | * 42 | * @param json 43 | * @param valueType 44 | * @return 45 | */ 46 | public static T decode(String json, Class valueType) { 47 | if (StringUtils.isEmpty(json)) { 48 | return null; 49 | } 50 | try { 51 | return objectMapper.readValue(json, valueType); 52 | } catch (Exception ignored) { 53 | } 54 | return null; 55 | } 56 | 57 | public static List decodeList(String json, Class valueType) { 58 | try { 59 | JavaType javaType = getCollectionType(List.class, valueType); 60 | return (List) objectMapper.readValue(json, javaType); 61 | } catch (Exception ignored) { 62 | } 63 | return null; 64 | } 65 | 66 | private static JavaType getCollectionType(Class collectionClass, Class... elementClasses) { 67 | return objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClasses); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /zuul-gateway/src/main/java/com/mycat/monoeshop/filter/LoginPostFilter.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.filter; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | 6 | import javax.servlet.http.HttpSession; 7 | 8 | import org.apache.commons.io.IOUtils; 9 | import org.apache.commons.lang.StringUtils; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants; 13 | 14 | import com.google.common.base.Charsets; 15 | import com.mycat.monoeshop.App; 16 | import com.netflix.zuul.ZuulFilter; 17 | import com.netflix.zuul.context.RequestContext; 18 | 19 | /** 20 | * Desc: 21 | * 22 | * @date: 27/08/2017 23 | * @author: Leader us 24 | */ 25 | public class LoginPostFilter extends ZuulFilter { 26 | private static final Logger LOGGER = LoggerFactory.getLogger(LoginPostFilter.class); 27 | 28 | @Override 29 | public String filterType() { 30 | return FilterConstants.POST_TYPE; 31 | } 32 | 33 | @Override 34 | public int filterOrder() { 35 | return 10; 36 | } 37 | 38 | @Override 39 | public boolean shouldFilter() { 40 | RequestContext context = RequestContext.getCurrentContext(); 41 | String uri = context.getRequest().getRequestURI(); 42 | if (uri.startsWith("/account/login")) { 43 | LOGGER.info("filter login url "+uri.toString()); 44 | return true; 45 | } 46 | return false; 47 | } 48 | 49 | @Override 50 | public Object run() { 51 | LOGGER.info("security post filter"); 52 | 53 | RequestContext context = RequestContext.getCurrentContext(); 54 | String result = null; 55 | 56 | if (context.getResponseBody() != null) { 57 | result = context.getResponseBody(); 58 | context.setResponseBody(wrapResult(context, result)); 59 | } else if (context.getResponseDataStream() != null) { 60 | InputStream is = context.getResponseDataStream(); 61 | try { 62 | result = IOUtils.toString(is, Charsets.UTF_8.name()); 63 | String tokenId = wrapResult(context, result); 64 | if (StringUtils.isNotEmpty(tokenId)) { 65 | context.setResponseDataStream(IOUtils.toInputStream(tokenId)); 66 | } 67 | } catch (IOException e) { 68 | LOGGER.error("error to handle response "+e); 69 | } 70 | } 71 | 72 | return null; 73 | } 74 | 75 | private String wrapResult(RequestContext context, String result) { 76 | String tokenId = null; 77 | if (StringUtils.isNotEmpty(result)) { 78 | HttpSession session = context.getRequest().getSession(); 79 | tokenId = session.getId(); 80 | session.setAttribute(App.SESSION_KEY, result); 81 | session.setMaxInactiveInterval(60 * 60 * 12); 82 | LOGGER.info("login post filter result: {}, tokenId: {}", result, tokenId); 83 | } 84 | return tokenId; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /zuul-gateway/src/main/java/com/mycat/monoeshop/filter/SecurityPreFilter.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.filter; 2 | 3 | import java.util.stream.Stream; 4 | 5 | import javax.servlet.http.HttpSession; 6 | 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants; 10 | 11 | import com.mycat.monoeshop.App; 12 | import com.mycat.monoeshop.model.Account; 13 | import com.mycat.monoeshop.model.Result; 14 | import com.mycat.monoeshop.model.ResultEnum; 15 | import com.netflix.zuul.ZuulFilter; 16 | import com.netflix.zuul.context.RequestContext; 17 | 18 | /** 19 | * Desc: 20 | * 21 | * @date: 27/08/2017 22 | * @author: Leader us 23 | */ 24 | public class SecurityPreFilter extends ZuulFilter { 25 | private static final Logger LOGGER = LoggerFactory.getLogger(SecurityPreFilter.class); 26 | 27 | @Override 28 | public String filterType() { 29 | return FilterConstants.PRE_TYPE; 30 | } 31 | 32 | @Override 33 | public int filterOrder() { 34 | return -100; 35 | } 36 | 37 | @Override 38 | public boolean shouldFilter() { 39 | String uri = getContext().getRequest().getRequestURI(); 40 | return uri.startsWith("/cart/"); 41 | } 42 | 43 | @Override 44 | public Object run() { 45 | LOGGER.info("security pre filter"); 46 | 47 | HttpSession session = getContext().getRequest().getSession(); 48 | Stream.of(getContext().getRequest().getCookies()).forEach(a -> {System.out.println("yyy cookie "+a.getName()+" "+a.getValue());}); 49 | String accountStr = (String) session.getAttribute(App.SESSION_KEY); 50 | Account account = JacksonUtil.decode(accountStr, Account.class); 51 | LOGGER.info("sessionid "+session.getId()+" account: {}", account); 52 | if (account != null) { 53 | getContext().addZuulRequestHeader("accountName", account.getName()); 54 | 55 | } else { 56 | LOGGER.warn("account no login, send response directly"); 57 | getContext().setSendZuulResponse(true); 58 | getContext().setResponseStatusCode(400); 59 | getContext().setResponseBody(JacksonUtil.encode(new Result(ResultEnum.NOT_LOGIN))); 60 | } 61 | LOGGER.info("session id: {}", session.getId()); 62 | return null; 63 | } 64 | 65 | private RequestContext getContext() { 66 | return RequestContext.getCurrentContext(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /zuul-gateway/src/main/java/com/mycat/monoeshop/model/Account.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.model; 2 | 3 | /** 4 | * Desc: 5 | * 6 | * @date: 27/08/2017 7 | * @author: Leader us 8 | */ 9 | public class Account { 10 | private String name; 11 | private String password; 12 | 13 | public String getName() { 14 | return name; 15 | } 16 | 17 | public void setName(String name) { 18 | this.name = name; 19 | } 20 | 21 | public String getPassword() { 22 | return password; 23 | } 24 | 25 | public void setPassword(String password) { 26 | this.password = password; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /zuul-gateway/src/main/java/com/mycat/monoeshop/model/Result.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.model; 2 | 3 | /** 4 | * Desc: 5 | * 6 | * @date: 27/08/2017 7 | * @author: Leader us 8 | */ 9 | public class Result { 10 | private int code; 11 | private String desc; 12 | private T data; 13 | 14 | public Result() 15 | { 16 | 17 | } 18 | public Result(ResultEnum resultEnum) { 19 | this.code = resultEnum.getCode(); 20 | this.desc = resultEnum.getDesc(); 21 | } 22 | 23 | public Result(ResultEnum resultEnum, T data) { 24 | this.code = resultEnum.getCode(); 25 | this.desc = resultEnum.getDesc(); 26 | this.data = data; 27 | } 28 | 29 | public int getCode() { 30 | return code; 31 | } 32 | 33 | public void setCode(int code) { 34 | this.code = code; 35 | } 36 | 37 | public String getDesc() { 38 | return desc; 39 | } 40 | 41 | public void setDesc(String desc) { 42 | this.desc = desc; 43 | } 44 | 45 | public T getData() { 46 | return data; 47 | } 48 | 49 | public void setData(T data) { 50 | this.data = data; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /zuul-gateway/src/main/java/com/mycat/monoeshop/model/ResultEnum.java: -------------------------------------------------------------------------------- 1 | package com.mycat.monoeshop.model; 2 | 3 | /** 4 | * Desc: 5 | * 6 | * @date: 27/08/2017 7 | * @author: Leader us 8 | */ 9 | public enum ResultEnum { 10 | SUCCESS(200, "success"), ERROR(502, "error"), NOT_LOGIN(503, "not login"); 11 | 12 | private int code; 13 | private String desc; 14 | 15 | ResultEnum(int code, String desc) { 16 | this.code = code; 17 | this.desc = desc; 18 | } 19 | 20 | public int getCode() { 21 | return code; 22 | } 23 | 24 | public String getDesc() { 25 | return desc; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /zuul-gateway/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: micro-gateway 4 | redis: 5 | host: 192.168.18.134 6 | port: 6379 7 | #password: 8 | info: 9 | app: 10 | name: ${spring.application.name} 11 | version: v1.0.0 12 | server: 13 | port: 8031 14 | context-path: / 15 | tomcat: 16 | uri-encoding: UTF-8 17 | 18 | logging: 19 | config: classpath:logback.xml 20 | eureka: 21 | instance: 22 | hostname: 127.0.0.1 23 | prefer-ip-address: true 24 | client: 25 | healthcheck: 26 | enabled: true 27 | registerWithEureka: true 28 | fetchRegistry: true 29 | service-url: 30 | defaultZone: http://127.0.0.1:8030/eureka/ 31 | 32 | zuul: 33 | ribbon-isolation-strategy: THREAD # SEMAPHORE THREAD 34 | sensitive-headers: 35 | ignored-headers: 36 | ignored-services: '*' 37 | retryable: true 38 | routes: 39 | session: 40 | path: /session/** 41 | url: forward:/session 42 | account: 43 | path: /account/** 44 | serviceId: eshop-auth-service 45 | stripPrefix: false 46 | product: 47 | path: /products/** 48 | serviceId: eshop-product-service 49 | stripPrefix: false 50 | cart: 51 | path: /cart/** 52 | serviceId: eshop-cart-service 53 | stripPrefix: false 54 | 55 | hystrix: 56 | command: 57 | default: 58 | execution: 59 | isolation: 60 | thread: 61 | timeoutInMilliseconds: 10000 62 | 63 | ribbon: 64 | MaxAutoRetries: 2 65 | MaxAutoRetriesNextServer: 3 66 | restclient: 67 | enabled: true -------------------------------------------------------------------------------- /zuul-gateway/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | --------------------------------------------------------------------------------