wangyishuai 2 years ago
commit
83235b3c37
51 changed files with 4783 additions and 0 deletions
  1. 60 0
      .gitignore
  2. 304 0
      pom.xml
  3. 31 0
      src/main/java/cn/efunbox/base/BaseApplication.java
  4. 75 0
      src/main/java/cn/efunbox/base/configuration/AsyncConfig.java
  5. 23 0
      src/main/java/cn/efunbox/base/configuration/RestTemplateConfig.java
  6. 57 0
      src/main/java/cn/efunbox/base/configuration/Swagger2.java
  7. 67 0
      src/main/java/cn/efunbox/base/configuration/WebApiConfig.java
  8. 20 0
      src/main/java/cn/efunbox/base/configuration/WebExceptionHandler.java
  9. 11 0
      src/main/java/cn/efunbox/base/configuration/annotation/CommonApi.java
  10. 30 0
      src/main/java/cn/efunbox/base/controller/UserController.java
  11. 10 0
      src/main/java/cn/efunbox/base/data/BasicRepository.java
  12. 11 0
      src/main/java/cn/efunbox/base/data/BasicStringRepository.java
  13. 138 0
      src/main/java/cn/efunbox/base/data/ProjectJpaRepository.java
  14. 572 0
      src/main/java/cn/efunbox/base/data/ProjectSimpleJpaRepository.java
  15. 52 0
      src/main/java/cn/efunbox/base/entity/User.java
  16. 19 0
      src/main/java/cn/efunbox/base/enums/BaseOrderEnum.java
  17. 42 0
      src/main/java/cn/efunbox/base/enums/BaseStatusEnum.java
  18. 35 0
      src/main/java/cn/efunbox/base/helper/SortHelper.java
  19. 257 0
      src/main/java/cn/efunbox/base/page/OnePage.java
  20. 83 0
      src/main/java/cn/efunbox/base/page/Pageable.java
  21. 8 0
      src/main/java/cn/efunbox/base/repository/UserRepository.java
  22. 27 0
      src/main/java/cn/efunbox/base/result/AbstractApiCode.java
  23. 75 0
      src/main/java/cn/efunbox/base/result/ApiCode.java
  24. 93 0
      src/main/java/cn/efunbox/base/result/ApiResult.java
  25. 12 0
      src/main/java/cn/efunbox/base/service/UserService.java
  26. 38 0
      src/main/java/cn/efunbox/base/service/impl/UserServiceImpl.java
  27. 22 0
      src/main/java/cn/efunbox/base/util/BaseConstant.java
  28. 62 0
      src/main/java/cn/efunbox/base/util/CommonRedisHelper.java
  29. 53 0
      src/main/java/cn/efunbox/base/util/CurrentWeekUtil.java
  30. 288 0
      src/main/java/cn/efunbox/base/util/DateUtil.java
  31. 260 0
      src/main/java/cn/efunbox/base/util/Encrypt.java
  32. 159 0
      src/main/java/cn/efunbox/base/util/EncryptUtils.java
  33. 63 0
      src/main/java/cn/efunbox/base/util/ExcelUtil.java
  34. 186 0
      src/main/java/cn/efunbox/base/util/HttpUtils.java
  35. 130 0
      src/main/java/cn/efunbox/base/util/HttpsUtils.java
  36. 62 0
      src/main/java/cn/efunbox/base/util/IpUtils.java
  37. 121 0
      src/main/java/cn/efunbox/base/util/MD5.java
  38. 30 0
      src/main/java/cn/efunbox/base/util/MoneyUtil.java
  39. 26 0
      src/main/java/cn/efunbox/base/util/MyX509TrustManager.java
  40. 238 0
      src/main/java/cn/efunbox/base/util/PayCommonUtil.java
  41. 55 0
      src/main/java/cn/efunbox/base/util/QRCodeUtil.java
  42. 109 0
      src/main/java/cn/efunbox/base/util/RSASignature.java
  43. 212 0
      src/main/java/cn/efunbox/base/util/SmsUtil.java
  44. 198 0
      src/main/java/cn/efunbox/base/util/SnowflakeIdUtil.java
  45. 72 0
      src/main/java/cn/efunbox/base/util/WxApiUtil.java
  46. 87 0
      src/main/java/cn/efunbox/base/util/XMLUtil.java
  47. 59 0
      src/main/resources/application-dev.properties
  48. 51 0
      src/main/resources/application-prod.properties
  49. 51 0
      src/main/resources/application-uat.properties
  50. 10 0
      src/main/resources/application.properties
  51. 29 0
      src/main/resources/logback-spring.xml

+ 60 - 0
.gitignore

@@ -0,0 +1,60 @@
+## .gitignore for Efunbox
+
+# Package Files #
+*.jar
+*.war
+*.ear
+
+*.class
+*.bak
+*.tmp
+*.log
+
+## .gitignore for intellij
+*.iml
+*.ipr
+*.iws
+.idea/
+
+## .gitignore for eclipse
+*.pydevproject
+.project
+.metadata
+bin/**
+tmp/**
+tmp/**/*
+*.swp
+local.properties
+.classpath
+.settings/
+
+## .gitignore for windows
+Thumbs.db
+ehthumbs.db
+
+
+## .gitignore for mac os x
+.DS_Store
+.AppleDouble
+.LSOverride
+/.classpath
+/.launch
+/.project
+/.settings
+/*.launch
+/*.tmproj
+/ivy*
+/eclipse
+
+
+# "temporary" build files
+target/
+out/
+build/
+
+
+# CDT-specific
+.cproject
+
+# PDT-specific
+.buildpath

+ 304 - 0
pom.xml

@@ -0,0 +1,304 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>springboot</groupId>
+    <artifactId>base</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+    <packaging>jar</packaging>
+
+    <name>springboot-base</name>
+    <description>springboot-base project for Spring Boot</description>
+
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.0.2.RELEASE</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <java.version>1.8</java.version>
+        <commons-lang3.version>3.3.2</commons-lang3.version>
+        <fastjson.version>1.2.38</fastjson.version>
+        <druid.version>1.0.23</druid.version>
+        <commons-io.version>1.3.2</commons-io.version>
+        <lombok.version>1.16.16</lombok.version>
+        <servlet-api.version>3.1.0</servlet-api.version>
+    </properties>
+
+    <dependencies>
+        <!--  springBoot 依赖-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>5.1.21</version>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid</artifactId>
+            <version>${druid.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>${commons-lang3.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>${commons-io.version}</version>
+        </dependency>
+        <!--简化代码-->
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>${lombok.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun.oss</groupId>
+            <artifactId>aliyun-sdk-oss</artifactId>
+            <version>2.8.1</version>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-core</artifactId>
+            <version>4.4.4</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.jdom</groupId>
+                    <artifactId>jdom</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-dypnsapi</artifactId>
+            <version>1.0.4</version>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+            <version>3.17</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-jpa</artifactId>
+        </dependency>
+
+        <!-- 引入 spring-boot-starter-redis -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>redis.clients</groupId>
+                    <artifactId>jedis</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>io.lettuce</groupId>
+                    <artifactId>lettuce-core</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>redis.clients</groupId>
+            <artifactId>jedis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-pool2</artifactId>
+            <version>2.5.0</version>
+        </dependency>
+        <!--log 相关-->
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+            <version>1.2.16</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>1.7.21</version>
+        </dependency>
+
+        <!--fastjson 引入  -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.71</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-httpclient</groupId>
+            <artifactId>commons-httpclient</artifactId>
+            <version>3.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>4.5.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+            <version>1.55</version>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+            <version>1.9.13</version>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+            <version>1.9.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi</artifactId>
+            <version>3.17</version>
+        </dependency>
+
+        <dependency>
+            <groupId>net.sourceforge.jexcelapi</groupId>
+            <artifactId>jxl</artifactId>
+            <version>2.6.10</version>
+        </dependency>
+        <dependency>
+            <groupId>com.github.ulisesbocchio</groupId>
+            <artifactId>jasypt-spring-boot-starter</artifactId>
+            <version>2.1.0</version>
+        </dependency>
+        <!--<dependency>
+            <groupId>com.alipay</groupId>
+            <artifactId>sdk-java</artifactId>
+            <version>3.3.0</version>
+        </dependency>-->
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger2</artifactId>
+            <version>2.9.2</version>
+        </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger-ui</artifactId>
+            <version>2.9.2</version>
+        </dependency>
+        <dependency>
+            <groupId>com.github.xiaoymin</groupId>
+            <artifactId>swagger-bootstrap-ui</artifactId>
+            <version>1.9.6</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>core</artifactId>
+            <version>3.3.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>javase</artifactId>
+            <version>3.3.1</version>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-core</artifactId>
+            <version>4.5.2</version>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-dypnsapi</artifactId>
+            <version>1.2.1</version>
+        </dependency>
+        <!-- 开启springboot的应用监控 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-actuator</artifactId>
+        </dependency>
+        <!-- 增加prometheus整合 -->
+        <dependency>
+            <groupId>io.micrometer</groupId>
+            <artifactId>micrometer-registry-prometheus</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alipay.sdk</groupId>
+            <artifactId>alipay-sdk-java</artifactId>
+            <version>4.18.0.ALL</version>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>${project.name}</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <outputDirectory>./target</outputDirectory>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <repositories>
+        <repository>
+            <id>nexus</id>
+            <url>http://nexus.efunbox.cn/nexus/content/groups/public/</url>
+            <layout>default</layout>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+    </repositories>
+    <distributionManagement>
+        <repository>
+            <id>nexus-releases</id>
+            <name>Releases</name>
+            <url>http://nexus.efunbox.cn/nexus/content/repositories/releases/</url>
+        </repository>
+        <snapshotRepository>
+            <id>nexus-snapshots</id>
+            <name>Snapshots</name>
+            <url>http://nexus.efunbox.cn/nexus/content/repositories/snapshots/</url>
+        </snapshotRepository>
+    </distributionManagement>
+
+</project>

+ 31 - 0
src/main/java/cn/efunbox/base/BaseApplication.java

@@ -0,0 +1,31 @@
+package cn.efunbox.base;
+
+import cn.efunbox.base.configuration.WebApiConfig;
+import cn.efunbox.base.data.ProjectSimpleJpaRepository;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Import;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@SpringBootApplication
+@RestController
+@EnableScheduling
+@Import(WebApiConfig.class)
+@EnableJpaRepositories(repositoryBaseClass = ProjectSimpleJpaRepository.class)
+public class BaseApplication {
+	public static void main(String[] args) {
+		SpringApplication.run(BaseApplication.class, args);
+	}
+
+    /**
+     * 健康检查check
+     * @return
+     */
+    @GetMapping(value="/check")
+    public String check(){
+        return  "ok";
+    }
+}

+ 75 - 0
src/main/java/cn/efunbox/base/configuration/AsyncConfig.java

@@ -0,0 +1,75 @@
+package cn.efunbox.base.configuration;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.task.SimpleAsyncTaskExecutor;
+import org.springframework.scheduling.annotation.AsyncConfigurer;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+import java.lang.reflect.Method;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+
+
+@Configuration
+@EnableAsync()
+public class AsyncConfig implements AsyncConfigurer {
+    private Logger logger = LoggerFactory.getLogger(getClass());
+
+    @Value("${schedule.threadPoolAsyncTaskExecutor.thread.size}")
+    private Integer threadSize;
+    /**
+     *  name = threadPoolAsyncTaskExecutor 时
+     * 使用基于线程池的 Task 执行器
+     * @return
+     */
+    @Bean(name = "threadPoolAsyncTaskExecutor")
+    public Executor threadPoolAsyncTaskExecutor() {
+        ExecutorService executor = Executors.newFixedThreadPool(threadSize);
+        return  executor;
+    }
+
+    @Bean(name = "scheduledExecutorService")
+    public ScheduledExecutorService threadPoolAsyncScheduleExecutor() {
+        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(threadSize);
+        return  scheduledExecutorService;
+    }
+
+    /**
+     * 只有@Async 注解时
+     * 使用 原生的 SimpleAsyncTaskExecutor 执行器
+     * @return
+     */
+    @Override
+    public Executor getAsyncExecutor() {
+        return new SimpleAsyncTaskExecutor();
+    }
+
+    /**
+     * 实现 异常处理 handler
+     * @return
+     */
+    @Override
+    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
+        return new CustomAsyncExceptionHandler();
+    }
+
+    class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
+
+        @Override
+        public void handleUncaughtException(final Throwable throwable, final Method method, final Object... obj) {
+            logger.error("Exception message - " + throwable.getMessage());
+            logger.error("Method name - " + method.getName());
+            for (final Object param : obj) {
+                logger.error("Param - " + param);
+            }
+        }
+
+    }
+}

+ 23 - 0
src/main/java/cn/efunbox/base/configuration/RestTemplateConfig.java

@@ -0,0 +1,23 @@
+package cn.efunbox.base.configuration;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.client.ClientHttpRequestFactory;
+import org.springframework.http.client.SimpleClientHttpRequestFactory;
+import org.springframework.web.client.RestTemplate;
+
+@Configuration
+public class RestTemplateConfig {
+    @Bean
+    public RestTemplate restTemplate(ClientHttpRequestFactory factory){
+        return new RestTemplate(factory);
+    }  
+      
+    @Bean
+    public ClientHttpRequestFactory simpleClientHttpRequestFactory(){
+        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
+        factory.setReadTimeout(5000);//ms
+        factory.setConnectTimeout(15000);//ms
+        return factory;
+    }  
+}  

+ 57 - 0
src/main/java/cn/efunbox/base/configuration/Swagger2.java

@@ -0,0 +1,57 @@
+package cn.efunbox.base.configuration;
+
+import cn.efunbox.base.configuration.annotation.CommonApi;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.Contact;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+@Configuration
+@EnableSwagger2
+//@Profile("swagger")
+@ComponentScan("cn.efunbox.base.controller")
+public class Swagger2 {
+    
+    /**
+     * 创建API应用
+     * apiInfo() 增加API相关信息
+     * 通过select()函数返回一个ApiSelectorBuilder实例,用来控制哪些接口暴露给Swagger来展现,
+     * 本例采用指定扫描的包路径来定义指定要建立API的目录。
+     * 
+     * @return
+     */
+    @Bean
+    public Docket apiDocket() {
+
+        return new Docket(DocumentationType.SWAGGER_2)
+                .groupName("基础接口")
+                .pathMapping("/")
+                .select()
+                .paths(PathSelectors.any())
+                .apis(RequestHandlerSelectors.withClassAnnotation(CommonApi.class))
+                .build()
+                .apiInfo(apiInfo());
+    }
+
+
+    /**
+     * 创建该API的基本信息(这些基本信息会展现在文档页面中)
+     * 访问地址:http://项目实际地址/doc.html
+     * @return
+     */
+    private ApiInfo apiInfo() {
+        return new ApiInfoBuilder()
+                .title("接口标题")
+                .description("接口文档")
+                .contact(new Contact("author", "127.0.0.1:8032", "sooper@qq.com"))
+                .version("1.0.0")
+                .build();
+    }
+}

+ 67 - 0
src/main/java/cn/efunbox/base/configuration/WebApiConfig.java

@@ -0,0 +1,67 @@
+package cn.efunbox.base.configuration;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+import java.util.List;
+
+@Configuration
+public class WebApiConfig extends WebMvcConfigurationSupport  {
+
+
+   /* @Bean
+    public MappingJackson2HttpMessageConverter customJackson2HttpMessageConverter() {
+        MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
+        ObjectMapper objectMapper = new ObjectMapper();
+        objectMapper.configure(
+                DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+        objectMapper.getSerializerProvider().setNullValueSerializer(
+                new JsonSerializer<Object>() {
+                    @Override
+                    public void serialize(Object value, JsonGenerator jgen,
+                                          SerializerProvider provider) throws IOException,
+                            JsonProcessingException {
+                        jgen.writeString("");
+                    }
+                });
+        // 进行HTML解码
+        objectMapper.registerModule(new SimpleModule().addSerializer(
+                String.class, new JsonSerializer<String>() {
+                    @Override
+                    public void serialize(String value, JsonGenerator jgen,
+                                          SerializerProvider provider) throws IOException,
+                            JsonProcessingException {
+                        jgen.writeString(StringEscapeUtils.unescapeHtml4(value));
+                    }
+                }));
+        jsonConverter.setObjectMapper(objectMapper);
+        return jsonConverter;
+    }*/
+
+    @Override
+    public void configureMessageConverters(
+            List<HttpMessageConverter<?>> converters) {
+
+        super.addDefaultHttpMessageConverters(converters);
+    }
+
+    @Override
+    public void addCorsMappings(CorsRegistry registry) {
+        registry.addMapping("/**")
+                .allowedOrigins("*")
+                .allowedMethods("GET", "POST", "PUT", "OPTIONS", "DELETE", "PATCH")
+                .allowCredentials(true).maxAge(3600);
+    }
+
+    /**
+     * 配置servlet处理
+     */
+    @Override
+    public void configureDefaultServletHandling(
+            DefaultServletHandlerConfigurer configurer) {
+        configurer.enable();
+    }
+}

+ 20 - 0
src/main/java/cn/efunbox/base/configuration/WebExceptionHandler.java

@@ -0,0 +1,20 @@
+package cn.efunbox.base.configuration;
+
+import cn.efunbox.base.result.ApiCode;
+import cn.efunbox.base.result.ApiResult;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+@Slf4j
+@ControllerAdvice
+@ResponseBody
+public class WebExceptionHandler {
+
+    @ExceptionHandler
+    public ApiResult unknownException(Exception e) {
+      log.error("未知异常",e);
+      return ApiResult.error(ApiCode.UNKNOWN_ERROR);
+    }
+}

+ 11 - 0
src/main/java/cn/efunbox/base/configuration/annotation/CommonApi.java

@@ -0,0 +1,11 @@
+package cn.efunbox.base.configuration.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface CommonApi {
+}

+ 30 - 0
src/main/java/cn/efunbox/base/controller/UserController.java

@@ -0,0 +1,30 @@
+package cn.efunbox.base.controller;
+
+import cn.efunbox.base.configuration.annotation.CommonApi;
+import cn.efunbox.base.entity.User;
+import cn.efunbox.base.result.ApiResult;
+import cn.efunbox.base.service.UserService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+@Slf4j
+@CommonApi
+@Api(tags = "用户相关接口")
+@RestController
+@RequestMapping(value = "/user")
+public class UserController {
+
+    @Autowired
+    UserService userService;
+
+    @ApiOperation(value = "获取用户信息", notes = "获取用户信息接口")
+    @GetMapping
+    public ApiResult<User> getMemberById(@RequestHeader(value = "uid") String uid) {
+        return userService.getUserById(uid);
+    }
+
+
+}

+ 10 - 0
src/main/java/cn/efunbox/base/data/BasicRepository.java

@@ -0,0 +1,10 @@
+package cn.efunbox.base.data;
+
+import org.springframework.data.repository.NoRepositoryBean;
+
+@NoRepositoryBean
+public interface BasicRepository<E> extends ProjectJpaRepository<E,Long> {
+
+
+
+}

+ 11 - 0
src/main/java/cn/efunbox/base/data/BasicStringRepository.java

@@ -0,0 +1,11 @@
+package cn.efunbox.base.data;
+
+import org.springframework.data.repository.NoRepositoryBean;
+
+
+@NoRepositoryBean
+public interface BasicStringRepository<E> extends ProjectJpaRepository<E,String> {
+
+
+
+}

+ 138 - 0
src/main/java/cn/efunbox/base/data/ProjectJpaRepository.java

@@ -0,0 +1,138 @@
+package cn.efunbox.base.data;
+
+import org.springframework.data.domain.Sort;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.repository.NoRepositoryBean;
+
+import java.io.Serializable;
+import java.util.List;
+
+@NoRepositoryBean
+public interface ProjectJpaRepository<E, ID extends Serializable> extends JpaRepository<E, ID> {
+
+	/**
+	 * 功能:统计符合样板的数据条数 <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年3月31日 下午4:56:01 <br/>
+	 */
+	long count(E sample);
+	
+	/**
+	 * 功能:检查是否存在 <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年8月17日 下午12:04:48 <br/>
+	 */
+	boolean exists(E sample);
+
+	/**
+	 * 功能:根据id查询 <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年3月30日 下午6:28:23 <br/>
+	 */
+	E find(ID id);
+	/**
+	 * 功能:查询符合条件的第一条 <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年8月2日 上午11:55:36 <br/>
+	 */
+	E findFirst(E sample);
+
+	/**
+	 * 功能:根据ids查询 <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年3月30日 下午6:28:23 <br/>
+	 */
+	List<E> findByIds(List<ID> id);
+
+	/**
+	 * 功能:查询符合条件的第一条 <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年8月2日 上午11:58:10 <br/>
+	 */
+	E findFirst(E sample, Sort sort);
+
+	/**
+	 * 功能:分页查询所有数据,使用id降序排序 <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年3月31日 下午4:52:30 <br/>
+	 */
+	List<E> find(Long start, Integer offset);
+	
+	/**
+	 * 功能:分页查询,使用sort规则排序 <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年7月29日 上午10:19:05 <br/>
+	 */
+	List<E> find(Long start, Integer offset, Sort sort);
+	
+	/**
+	 * 功能:根据样板查询数据,使用id降序排序 <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年3月30日 下午6:51:00 <br/>
+	 */
+	List<E> find(E sample);
+	
+	/**
+	 * 功能:根据样板查询数据,使用sort规则排序 <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年7月29日 上午10:19:51 <br/>
+	 */
+	List<E> find(E sample, Sort sort);
+	
+	/**
+	 * 功能:分页查询,按id降序排序 <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年3月31日 上午11:58:31 <br/>
+	 */
+	List<E> find(E sample, Long start, Integer offset);
+	
+	/**
+	 * 功能:分页查询,且排序 <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年7月29日 上午9:44:26 <br/>
+	 */
+	List<E> find(E sample, Long start, Integer offset, Sort sort);
+	
+	/**
+	 * 功能:更新操作,不更新为null的字段 <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年8月1日 上午9:35:47 <br/>
+	 */
+	E update(E entity);
+	/**
+	 * 功能:基于原生merge方法的 批量更新操作
+	 *
+	 * @author  tomas <br/>
+	 * @version 2017年8月1日 上午9:35:47 <br/>
+	 */
+	<S extends E> List<S> update(Iterable<S> entities);
+
+	/**
+	 * 功能:基于原生merge方法的 批量save操作
+	 *
+	 * @author  tomas <br/>
+	 * @version 2017年8月1日 上午9:35:47 <br/>
+	 */
+	<S extends E> List<S> save(Iterable<S> entities);
+	
+	/**
+	 * 功能:更新操作,可以选择是否要忽略更新为null的字段 <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年8月1日 上午9:36:20 <br/>
+	 */
+	E update(E entity, boolean ignoreNull);
+}

+ 572 - 0
src/main/java/cn/efunbox/base/data/ProjectSimpleJpaRepository.java

@@ -0,0 +1,572 @@
+package cn.efunbox.base.data;
+
+import cn.efunbox.base.util.SnowflakeIdUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.domain.Sort.Direction;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.data.jpa.repository.support.JpaEntityInformation;
+import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.ReflectionUtils;
+import org.springframework.util.StringUtils;
+
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.Attribute.PersistentAttributeType;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.util.*;
+
+public class ProjectSimpleJpaRepository<E, ID extends Serializable> extends SimpleJpaRepository<E, ID> implements ProjectJpaRepository<E, ID> {
+	
+	// 日志记录器
+	private static final Logger logger = LoggerFactory.getLogger(ProjectSimpleJpaRepository.class);
+	
+	// jpa管理器对象
+	private EntityManager entityManager;
+	
+	// 实体信息
+	private JpaEntityInformation<E, ID> entityInformation;
+	
+	/**
+	 * 构造方法
+	 */
+	public ProjectSimpleJpaRepository(JpaEntityInformation<E, ID> entityInformation, EntityManager entityManager) {
+		super(entityInformation, entityManager);
+		
+		// 保留该对象,方便后续使用
+		this.entityInformation = entityInformation;
+		this.entityManager = entityManager;
+	}
+
+	/**
+	 * 功能: <br/>
+	 * 
+	 * 重写:xtwin <br/>
+	 * 
+	 * @version :2016年7月26日 下午3:23:06<br/>
+	 * 
+	 * @param sample
+	 * @return <br/>
+	 * @see ProjectJpaRepository#count(Object)
+	 */
+	@Override
+	public long count(E sample) {
+		return count(getSpecification(sample));
+	}
+
+	/**
+	 * 功能: <br/>
+	 *
+	 * 重写:xtwin <br/>
+	 *
+	 * @version :2016年8月17日 下午12:05:21<br/>
+	 *
+	 * @param sample
+	 * @return <br/>
+	 * @see ProjectJpaRepository#exists(Object)
+	 */
+	@Override
+	public boolean exists(E sample) {
+		return count(sample) > 0L;
+	}
+
+	/**
+	 * 功能: <br/>
+	 *
+	 * 重写:xtwin <br/>
+	 *
+	 * @version :2016年7月26日 下午3:23:06<br/>
+	 *
+	 * @param id
+	 * @return <br/>
+	 * @see ProjectJpaRepository#find(Serializable)
+	 */
+	@Override
+	public E find(ID id) {
+        Optional<E> optional = findById(id);
+        if (optional.isPresent()) {
+            return optional.get();
+        }
+        return null;
+	}
+	/**
+	 * 功能:根据ids查询 <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年3月30日 下午6:28:23 <br/>
+	 */
+	@Override
+	public List<E> findByIds(List<ID> ids){
+		return findAllById(ids);
+	}
+
+
+	/**
+	 * 功能: <br/>
+	 *
+	 * 重写:xtwin <br/>
+	 *
+	 * @version :2016年7月26日 下午3:23:06<br/>
+	 *
+	 * @param start
+	 * @param offset
+	 * @return <br/>
+	 * @see ProjectJpaRepository#find(Long, Integer)
+	 */
+	@Override
+	public List<E> find(Long start, Integer offset) {
+		return find(start, offset, null);
+	}
+
+	/**
+	 * 功能: <br/>
+	 *
+	 * 重写:xtwin <br/>
+	 *
+	 * @version :2016年7月29日 上午10:20:21<br/>
+	 *
+	 * @param start
+	 * @param offset
+	 * @param sort
+	 * @return <br/>
+	 * @see ProjectJpaRepository#find(Long, Integer, Sort)
+	 */
+	@Override
+	public List<E> find(Long start, Integer offset, Sort sort) {
+		return find(null, start, offset, sort);
+	}
+
+	/**
+	 * 功能: <br/>
+	 *
+	 * 重写:xtwin <br/>
+	 *
+	 * @version :2016年8月2日 上午11:58:30<br/>
+	 *
+	 * @param sample
+	 * @return <br/>
+	 * @see ProjectJpaRepository#findFirst(Object)
+	 */
+	@Override
+	public E findFirst(E sample) {
+		return findFirst(sample, null);
+	}
+
+	/**
+	 * 功能: <br/>
+	 *
+	 * 重写:xtwin <br/>
+	 *
+	 * @version :2016年8月2日 上午11:58:30<br/>
+	 *
+	 * @param sample
+	 * @param sort
+	 * @return <br/>
+	 * @see ProjectJpaRepository#findFirst(Object, Sort)
+	 */
+	@Override
+	public E findFirst(E sample, Sort sort) {
+		List<E> list = find(sample, 0L, 1, sort);
+
+		return null == list || list.isEmpty() ? null : list.get(0);
+	}
+
+	/**
+	 * 功能: <br/>
+	 *
+	 * 重写:xtwin <br/>
+	 *
+	 * @version :2016年7月26日 下午3:23:06<br/>
+	 *
+	 * @param sample
+	 * @return <br/>
+	 * @see ProjectJpaRepository#find(Object)
+	 */
+	@Override
+	public List<E> find(E sample) {
+		return find(sample, null);
+	}
+
+	/**
+	 * 功能: <br/>
+	 *
+	 * 重写:xtwin <br/>
+	 *
+	 * @version :2016年7月29日 上午10:20:21<br/>
+	 *
+	 * @param sample
+	 * @param sort
+	 * @return <br/>
+	 * @see ProjectJpaRepository#find(Object, Sort)
+	 */
+	@Override
+	public List<E> find(E sample, Sort sort) {
+		return find(sample, null, null,sort);
+	}
+
+	/**
+	 * 功能: <br/>
+	 *
+	 * 重写:xtwin <br/>
+	 *
+	 * @version :2016年7月26日 下午3:23:06<br/>
+	 *
+	 * @param sample
+	 * @param start
+	 * @param offset
+	 * @return <br/>
+	 * @see ProjectJpaRepository#find(Object, Long, Integer)
+	 */
+	@Override
+	public List<E> find(E sample, Long start, Integer offset) {
+		return find(sample, start, offset, null);
+	}
+
+	/**
+	 * 功能: <br/>
+	 *
+	 * 重写:xtwin <br/>
+	 *
+	 * @version :2016年7月29日 上午9:44:56<br/>
+	 *
+	 * @param sample
+	 * @param start
+	 * @param offset
+	 * @param sort
+	 * @return <br/>
+	 * @see ProjectJpaRepository#find(Object, Long, Integer, Sort)
+	 */
+	@Override
+	public List<E> find(E sample, Long start, Integer offset, Sort sort) {
+		// 创建qbe
+		Specification<E> spec = getSpecification(sample);
+
+		if (null == sort) {
+			// 默认按id降序排序
+			sort = Sort.by(Direction.DESC, entityInformation.getIdAttribute().getName());
+		}
+
+		// 取得查询对象
+		TypedQuery<E> query = getQuery(spec, sort);
+
+		// 起始条数,从零开始
+		if (null != start) {
+			// TODO 此处只接受整形值
+			query.setFirstResult(start.intValue());
+		}
+
+		// 查询条数
+		if (null != offset) {
+			query.setMaxResults(offset);
+		}
+
+		// 执行查询
+		return query.getResultList();
+	}
+
+
+	/**
+	 * 功能: 更新操作,不更新为null的字段 <br/>
+	 *
+	 * 重写:xtwin <br/>
+	 *
+	 * @version :2016年8月1日 上午9:37:15<br/>
+	 *
+	 * @param entity
+	 * @return <br/>
+	 * @see ProjectJpaRepository#update(Object)
+	 */
+	@Override
+	@Transactional
+	public E update(E entity) {
+		return update(entity, true);
+	}
+
+	/**
+	 * Saves all given entities.
+	 *
+	 * @param entities
+	 * @return the saved entities
+	 * @throws IllegalArgumentException in case the given domain is {@literal null}.
+	 */
+	@Override
+	@Transactional
+	public <S extends E> List<S> save(Iterable<S> entities) {
+
+		return insertOrUpdateBatch(entities);
+	}
+	/**
+	 * Saves a given domain. Use the returned instance for further operations as the save operation might have changed the
+	 * domain instance completely.
+	 *
+	 * @param entity
+	 * @return the saved domain
+	 */
+	@Override
+	@Transactional
+	public <S extends E> S save(S entity) {
+
+		if (entityInformation.isNew(entity)) {
+			setSnowflakeIdId(entity);
+			entityManager.persist(entity);
+			return entity;
+		} else {
+			return entityManager.merge(entity);
+		}
+	}
+	/**
+	 * 功能: 动态数据更新,可以选择是否需要更新null字段 <br/>
+	 *
+	 * 重写:xtwin <br/>
+	 *
+	 * @version :2016年8月1日 上午9:37:05<br/>
+	 *
+	 * @param entity
+	 * @param ignoreNull
+	 * @return <br/>
+	 * @see ProjectJpaRepository#update(Object, boolean)
+	 */
+	@Override
+	@Transactional
+	public E update(E entity, boolean ignoreNull) {
+		// 取得当前实体的id
+		ID id = entityInformation.getId(entity);
+		
+		// 检查id是否为空Ø
+		if (Objects.isNull(id)) {
+			return save(entity);
+		}
+		if (id instanceof String) {
+			if (org.apache.commons.lang3.StringUtils.isBlank((String) id)) {
+				return save(entity);
+			}
+		}
+		
+		// 查询库中当前对象的信息
+		E persist = find(id);
+		
+		// 检查该id对应的数据是否存在
+		if (null == persist) {
+			return save(entity);
+//			throw new RuntimeException("The update domain id is not exist : " + id);
+		}
+		
+		// 标识是否发生了变化
+		boolean isChanged = false;
+		
+		// 取得所有属性
+		for (Attribute<? super E, ?> attr : entityManager.getMetamodel().entity(getDomainClass()).getAttributes()) {
+			// 依次处理每个字段
+			/*PersistentAttributeType patype = attr.getPersistentAttributeType();
+
+			if (PersistentAttributeType.MANY_TO_ONE.equals(patype) 
+					|| PersistentAttributeType.ONE_TO_MANY.equals(patype)) {
+
+				// 忽略
+				continue;
+			}*/
+			
+			Member member = attr.getJavaMember();
+			
+			Field field = null;
+			if (member instanceof Field) {
+				field = (Field) member;
+			} else {
+				field = ReflectionUtils.findField(getDomainClass(), attr.getName());
+			}
+			
+			// 取得字段值
+			Object value = ReflectionUtils.getField(field, entity);
+			if (null != value || ! ignoreNull) {
+				// 旧值
+				Object oldValue = ReflectionUtils.getField(field, persist);
+				
+				if ((null == value && null != oldValue) 
+						|| (null != value && ! value.equals(oldValue))) {
+					
+					// 将新值更新到持久化对象中
+					ReflectionUtils.setField(field, persist, value);
+					
+					// 标记为发生了更新
+					isChanged = true;
+				}
+			}
+		}
+		
+		if (isChanged) {
+			persist = save(persist);
+		} else {
+			// 没有发生变更,忽略更新
+			logger.debug("has no changed : {}", id);
+		}
+		
+		// 执行保存并返回
+		return persist;
+	}
+	/**
+	 * update all given entities.
+	 *
+	 * @param entities
+	 * @return the saved entities
+	 * @throws IllegalArgumentException in case the given domain is {@literal null}.
+	 */
+	@Override
+	@Transactional
+	public <S extends E> List<S> update(Iterable<S> entities) {
+		return insertOrUpdateBatch(entities);
+	}
+
+	private <S extends E> List<S> insertOrUpdateBatch(Iterable<S> entities) {
+		List<S> result = new ArrayList<>();
+		if (entities == null) {
+			return result;
+		}
+		Iterator<S> iterator = entities.iterator();
+		int i = 0;
+		int count = 0;
+		//遍历循环 每20个 insert 批量插入/更新 一次库
+		while (iterator.hasNext()) {
+			S entity = iterator.next();
+			if (entityInformation.isNew(entity)) {
+				setSnowflakeIdId(entity);
+				entityManager.persist(entity);
+			} else {
+				update(entity);
+			}
+			result.add(entity);
+			i++;
+			if (i % 20 == 0) {
+				entityManager.flush();
+				entityManager.clear();
+
+				count=0;
+			}else {
+				count++;
+			}
+		}
+		//判断 是否有剩余未flush的 最后flush
+		if (count>0){
+			entityManager.flush();
+			entityManager.clear();
+		}
+		return result;
+	}
+
+	/**
+	 * 功能:获取qbe <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年7月29日 上午9:43:25 <br/>
+	 */
+	protected Specification<E> getSpecification(E sample) {
+		return null == sample ? null : new Specification<E>() {
+			@Override
+			public Predicate toPredicate(Root<E> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
+				try {
+					// 获取qbe
+					return ProjectSimpleJpaRepository.this.toPredicate(sample, root, query, cb);
+				} catch (Exception e) {
+					throw new RuntimeException("toPredicate fail with error : " + String.valueOf(e), e);
+				}
+			}
+		};
+	}
+
+	/**
+	 * 功能:转为查询样板,可以由子类重写 <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年7月29日 上午10:15:27 <br/>
+	 * @throws IllegalAccessException 
+	 * @throws IllegalArgumentException 
+	 */
+	protected Predicate toPredicate(E sample, Root<E> root, CriteriaQuery<?> query, CriteriaBuilder cb) throws Exception {
+		// 存放查询条件
+		List<Predicate> list = new ArrayList<Predicate>();
+		
+		// 处理实体中的所有字段
+		for (Attribute<? super E, ?> attr : entityManager.getMetamodel().entity(getDomainClass()).getAttributes()) {
+			// 依次处理每个字段
+			PersistentAttributeType patype = attr.getPersistentAttributeType();
+
+			// 打印日志
+			logger.debug("the attr type is : {}", patype);
+
+			if (PersistentAttributeType.MANY_TO_ONE.equals(patype) 
+					|| PersistentAttributeType.ONE_TO_MANY.equals(patype)) {
+
+				// 忽略
+				continue;
+			}
+
+			Object value = null;
+			
+			Member member = attr.getJavaMember();
+			if (member instanceof Method) {
+				value = ReflectionUtils.invokeMethod((Method) member, sample);
+			} else if (member instanceof Field) {
+				//((Field) member).setAccessible(true);
+				// 确保可以访问
+				ReflectionUtils.makeAccessible((Field) member);
+				
+				// 取得字段的值
+				value = ((Field) member).get(sample);
+			}
+			
+			if (null != value) {
+				Predicate tmp = null;
+				//like 查询放在最前面
+				List<Predicate> likePredicate = new ArrayList<Predicate>();
+				if (String.class.isAssignableFrom(attr.getJavaType()) ) {
+					if(!StringUtils.isEmpty(value)){
+						StringBuilder stringBuilder=new StringBuilder(((String) value).trim());
+						//如果以 % 开头和结尾 表示 like 查询
+						if("%".equals(stringBuilder.substring(0,1)) || stringBuilder.toString().endsWith("%")){
+							tmp = cb.like(root.get(attr.getName()), (String) value);
+							likePredicate.add(tmp);
+						}else{
+							tmp = cb.equal(root.get(attr.getName()), value);
+							list.add(tmp);
+						}
+					}
+				} else  {
+					tmp = cb.equal(root.get(attr.getName()), value);
+					list.add(tmp);
+				}
+				if(likePredicate.size()>0){
+					list.addAll(0,likePredicate);
+				}
+			}
+		}
+		
+		// where条件
+		return list.isEmpty() ? null : cb.and(list.toArray(new Predicate[list.size()]));
+	}
+
+
+	protected void setSnowflakeIdId(E entity){
+		try {
+			Field field = ReflectionUtils.findField(entity.getClass(),entityInformation.getIdAttribute().getName());
+			if(entityInformation.getIdAttribute().getType().getJavaType().getName().equals("java.lang.Long")){
+				ReflectionUtils.makeAccessible(field);
+				ReflectionUtils.setField(field, entity, SnowflakeIdUtil.getSnowflakeIdUtil().nextId());
+			}else if(entityInformation.getIdAttribute().getType().getJavaType().getName().equals("java.lang.String")) {
+				logger.debug(" uuid  entityInformation.getIdAttribute().getName() ={}",entityInformation.getIdAttribute().getName());
+				ReflectionUtils.makeAccessible(field);
+				ReflectionUtils.setField(field, entity, SnowflakeIdUtil.getSnowflakeIdUtil().nextCode());
+			}
+		}catch (Exception e){
+			logger.error("Reflect set id 出错 mag ={}",e.getMessage(),e);
+		}
+	}
+}

+ 52 - 0
src/main/java/cn/efunbox/base/entity/User.java

@@ -0,0 +1,52 @@
+package cn.efunbox.base.entity;
+
+import cn.efunbox.base.enums.BaseStatusEnum;
+import lombok.Data;
+import lombok.ToString;
+import org.hibernate.annotations.DynamicInsert;
+import org.hibernate.annotations.DynamicUpdate;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * Member
+ * Created by xusq on 2019/12/31.
+ */
+@Data
+@ToString
+@Entity
+@DynamicInsert
+@DynamicUpdate
+@Table(name = "user")
+public class User implements Serializable {
+
+    @Id
+    private String uid;
+
+    private String eid;
+
+    @Column(name = "mobile_no")
+    private String mobileNo;
+
+    @Column(name = "open_id")
+    private String openId;
+
+    @Column(name = "nick_name")
+    private String nickName;
+
+    private Integer gender;
+
+    @Enumerated(EnumType.ORDINAL)
+    private BaseStatusEnum status;
+
+    private String avatar;
+
+    @Column(name = "gmt_created")
+    private Date gmtCreated;
+
+    @Column(name = "gmt_modified")
+    private Date gmtModified;
+
+}

+ 19 - 0
src/main/java/cn/efunbox/base/enums/BaseOrderEnum.java

@@ -0,0 +1,19 @@
+package cn.efunbox.base.enums;
+
+public enum BaseOrderEnum {
+
+    DESC("降序"), ASC("升序");
+    String name;
+    BaseOrderEnum(String name) {
+        this.name = name;  
+    }
+      
+    public String getName() {  
+        return name;  
+    }
+    @Override
+    public String toString() {
+        return this.name;
+    }
+
+}  

+ 42 - 0
src/main/java/cn/efunbox/base/enums/BaseStatusEnum.java

@@ -0,0 +1,42 @@
+package cn.efunbox.base.enums;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public enum BaseStatusEnum {
+
+    NORMAL("正常"),ABNORMAL("不正常");
+
+    /**
+     * 未删除 需要在列表查询
+     */
+    public static Set<BaseStatusEnum>  show = new HashSet<>();
+
+    static {
+        show.add(BaseStatusEnum.NORMAL);
+    }
+
+    public static BaseStatusEnum getBaseStatusEnum(Integer value) {
+    	 switch (value) {
+         case 0:
+             return NORMAL;
+         case 1:
+             return ABNORMAL;
+         default:
+             return null;
+     }
+    }  
+    String name;
+    BaseStatusEnum(String name) {
+        this.name = name;  
+    }
+      
+    public String getName() {  
+        return name;  
+    }
+    @Override
+    public String toString() {
+        return this.name;
+    }
+
+}  

+ 35 - 0
src/main/java/cn/efunbox/base/helper/SortHelper.java

@@ -0,0 +1,35 @@
+package cn.efunbox.base.helper;
+
+import cn.efunbox.base.enums.BaseOrderEnum;
+import org.springframework.data.domain.Sort;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+
+/**
+ * SortHelper
+ * Created by xusq on 2017/5/22.
+ */
+public class SortHelper {
+
+
+    public static Sort sortMap2Sort(LinkedHashMap<String, BaseOrderEnum> sortMap){
+        if (CollectionUtils.isEmpty(sortMap)) {
+            return null;
+        }
+
+        List<Sort.Order> sorts = new ArrayList<>();
+        sortMap.forEach((prop, order) -> {
+            if (BaseOrderEnum.ASC.equals(order)) {
+                sorts.add(new Sort.Order(Sort.Direction.ASC, prop));
+            } else {
+                sorts.add(new Sort.Order(Sort.Direction.DESC, prop));
+            }
+        });
+
+        return  Sort.by(sorts);
+
+    }
+}

+ 257 - 0
src/main/java/cn/efunbox/base/page/OnePage.java

@@ -0,0 +1,257 @@
+/**
+ * 文件名:@OnePage.java <br/>
+ * 包名:cn.efunbox.afw.core.domain.page <br/>
+ * 项目名:afw-core <br/>
+ * @author xtwin <br/>
+ */
+package cn.efunbox.base.page;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * 类名:OnePage  <br />
+ *
+ * 功能:分页,一页
+ *
+ * @author xtwin <br />
+ * 创建时间:2016年7月28日 上午11:26:12  <br />
+ * @version 2016年7月28日
+ */
+public class OnePage<E> implements Pageable<List<E>> ,Serializable {
+
+	private static final long serialVersionUID = 1L;
+	// 默认分页数据条数
+	public final static int DEFAULT_PAGE_SIZE = 10;
+	
+	// 当前页
+	private int pageNo = 1;
+	
+	// 当前页大小
+	private int pageSize = DEFAULT_PAGE_SIZE;
+	
+	// 总条数
+	private long totalSize;
+	
+	// 数据内容
+	private List<E> list;
+
+	/**
+	 * 构造方法
+	 */
+	protected OnePage() {
+		// 默认构造方法
+	}
+	
+	/**
+	 * 构造方法
+	 */
+	public OnePage(Long totalSize) {
+		this(totalSize, null, null);
+	}
+	
+	/**
+	 * 构造方法
+	 */
+	public OnePage(Long totalSize, Integer pageNo) {
+		this(totalSize, pageNo, null);
+	}
+	
+	/**
+	 * 构造方法
+	 */
+	public OnePage(Long totalSize, Integer pageNo, Integer pageSize) {
+		// 总记录数
+		if (null != totalSize) {
+			if (totalSize < 0) {
+				throw new RuntimeException("totalSize must be not less than zero!");
+			}
+			this.totalSize = totalSize;
+		}
+		
+		// 当前页码
+		if (null != pageNo) {
+			if (pageNo < 0) {
+				throw new RuntimeException("pageNo must be not less than zero!");
+			}
+			this.pageNo = pageNo;
+		}
+
+		
+		// 当前页数据条数
+		if (null != pageSize) {
+			if (pageSize < 0) {
+				throw new RuntimeException("pageSize must be not less than zero!");
+			}
+			
+			this.pageSize = pageSize;
+		}
+
+	}
+
+	/**
+	 * 功能: <br/>
+	 * 
+	 * 重写:xtwin <br/>
+	 * 
+	 * @version :2016年7月31日 上午9:27:27<br/>
+	 * 
+	 * @return <br/>
+	 */
+	@Override
+	public int getTotalNo() {
+		return totalSize == 0 ? 1 : (int) ((totalSize / pageSize) + (totalSize % pageSize == 0 ? 0 : 1));
+	}
+
+	/**
+	 * 功能: <br/>
+	 * 
+	 * 重写:xtwin <br/>
+	 * 
+	 * @version :2016年7月31日 上午9:27:27<br/>
+	 * 
+	 * @return <br/>
+	 */
+	@Override
+	public long getTotalSize() {
+		return totalSize;
+	}
+
+	/**
+	 * 功能: <br/>
+	 * 
+	 * 重写:xtwin <br/>
+	 * 
+	 * @version :2016年7月31日 上午9:27:27<br/>
+	 * 
+	 * @return <br/>
+	 */
+	@Override
+	public int getPageNo() {
+		return pageNo;
+	}
+
+	/**
+	 * 功能: <br/>
+	 * 
+	 * 重写:xtwin <br/>
+	 * 
+	 * @version :2016年7月31日 上午9:27:27<br/>
+	 * 
+	 * @return <br/>
+	 */
+	@Override
+	public int getPageSize() {
+		return pageSize;
+	}
+
+	/**
+	 * 功能: <br/>
+	 * 
+	 * 重写:xtwin <br/>
+	 * 
+	 * @version :2016年7月31日 上午9:27:27<br/>
+	 * 
+	 * @return <br/>
+	 */
+	@Override
+	public boolean hasNext() {
+		return getPageNo() < getTotalNo();
+	}
+
+	/**
+	 * 功能: <br/>
+	 * 
+	 * 重写:xtwin <br/>
+	 * 
+	 * @version :2016年7月31日 上午9:27:27<br/>
+	 * 
+	 * @return <br/>
+	 */
+	@Override
+	public boolean hasPrevious() {
+		return getPageNo() > 1;
+	}
+
+	/**
+	 * @version 2016年7月31日-上午10:57:49
+	 */
+	public void setPageNo(int pageNo) {
+		this.pageNo = pageNo;
+	}
+
+	/**
+	 * @version 2016年7月31日-上午10:57:49
+	 */
+	public void setPageSize(int pageSize) {
+		this.pageSize = pageSize;
+	}
+
+	/**
+	 * @version 2016年7月31日-上午10:57:49
+	 */
+	public void setTotalSize(int totalSize) {
+		/*if (totalSize < 0) {
+			throw new AfwRuntimeException("totalSize must be not less than zero!");
+		}*/
+		this.totalSize = totalSize;
+	}
+	
+	/**
+	 * 功能:bean规范 <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年7月31日 下午12:54:59 <br/>
+	 */
+	public boolean isHasNext() {
+		return hasNext();
+	}
+	
+	/**
+	 * 功能:bean规范 <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年7月31日 下午12:55:22 <br/>
+	 */
+	public boolean isHasPrevious() {
+		return hasPrevious();
+	}
+
+	/**
+	 * @version 2016年8月1日-上午10:00:32
+	 */
+	public void setList(List<E> list) {
+		this.list = list;
+	}
+
+	/**
+	 * 功能: <br/>
+	 * 
+	 * 重写:xtwin <br/>
+	 * 
+	 * @version :2016年8月1日 上午9:49:32<br/>
+	 * 
+	 * @return <br/>
+	 * @see Pageable#getList()
+	 */
+	@Override
+	public List<E> getList() {
+		return null == list ? Collections.emptyList() : list;
+	}
+
+	/**
+	 * 功能: <br/>
+	 * 
+	 * 重写:xtwin <br/>
+	 * 
+	 * @version :2016年8月1日 上午10:05:48<br/>
+	 * 
+	 * @return <br/>
+	 * @see Pageable#getStart()
+	 */
+	@Override
+	public long getStart() {
+		return (getPageNo() - 1) * getPageSize();
+	}
+}

+ 83 - 0
src/main/java/cn/efunbox/base/page/Pageable.java

@@ -0,0 +1,83 @@
+/**
+ * 文件名:@Pageable.java <br/>
+ * 包名:cn.efunbox.afw.core.domain.page <br/>
+ * 项目名:afw-core <br/>
+ * @author xtwin <br/>
+ */
+package cn.efunbox.base.page;
+
+/**
+ * 类名:Pageable  <br />
+ *
+ * 功能:分页接口
+ *
+ * @author xtwin <br />
+ * 创建时间:2016年7月28日 上午11:18:56  <br />
+ * @version 2016年7月28日
+ */
+public interface Pageable<E> {
+	
+	/**
+	 * 功能:当前页的数据内容 <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年7月28日 上午11:43:27 <br/>
+	 */
+	E getList();
+
+	/**
+	 * 功能:总页数 <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年8月1日 上午9:47:45 <br/>
+	 */
+	int getTotalNo();
+	
+	/**
+	 * 功能:总记录数 <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年8月1日 上午9:48:40 <br/>
+	 */
+	long getTotalSize();
+
+	/**
+	 * 功能:页码 <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年8月1日 上午9:48:33 <br/>
+	 */
+	int getPageNo();
+	
+	/**
+	 * 功能:每页数据条数 <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年8月1日 上午9:48:25 <br/>
+	 */
+	int getPageSize();
+	
+	/**
+	 * 功能:起始位置 <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年8月1日 上午10:02:52 <br/>
+	 */
+	long getStart();
+	
+	/**
+	 * 功能:是否还有下一页 <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年8月1日 上午9:48:07 <br/>
+	 */
+	boolean hasNext();
+	
+	/**
+	 * 功能:是否还有上一页 <br/>
+	 *
+	 * @author xtwin <br/>
+	 * @version 2016年8月1日 上午9:47:58 <br/>
+	 */
+	boolean hasPrevious();
+}

+ 8 - 0
src/main/java/cn/efunbox/base/repository/UserRepository.java

@@ -0,0 +1,8 @@
+package cn.efunbox.base.repository;
+
+import cn.efunbox.base.data.BasicStringRepository;
+import cn.efunbox.base.entity.User;
+
+public interface UserRepository extends BasicStringRepository<User> {
+
+}

+ 27 - 0
src/main/java/cn/efunbox/base/result/AbstractApiCode.java

@@ -0,0 +1,27 @@
+package cn.efunbox.base.result;
+
+import java.io.Serializable;
+
+public abstract class AbstractApiCode implements Serializable {
+    private int code;
+    private String message;
+    private final AbstractApiCode display;
+
+    protected AbstractApiCode(int code, String messasge) {
+        this.code = code;
+        this.message = messasge;
+        this.display = this;
+    }
+
+    public int getCode() {
+        return this.code;
+    }
+
+    public String getMessage() {
+        return this.message;
+    }
+
+    public AbstractApiCode getDisplay() {
+        return this.display;
+    }
+}

+ 75 - 0
src/main/java/cn/efunbox/base/result/ApiCode.java

@@ -0,0 +1,75 @@
+package cn.efunbox.base.result;
+
+
+public class ApiCode extends AbstractApiCode {
+    public static final int _C_OK = 200;
+    public static final ApiCode OK = new ApiCode((String)null, _C_OK);
+    public static final int _C_NOT_FOUND = 404;
+    public static final ApiCode NOT_FOUND = new ApiCode("请求资源不存在", _C_NOT_FOUND);
+    public static final int _C_UNKNOWN_ERROR = 500;
+    public static final ApiCode UNKNOWN_ERROR = new ApiCode("服务端内部错误", _C_UNKNOWN_ERROR);
+    public static final int _C_NO_MOBILE = 505;
+    public static final ApiCode NO_MOBILE = new ApiCode("手机号不存在", _C_NO_MOBILE);
+    public static final int _C_MOBILE_ERROR = 506;
+    public static final ApiCode MOBILE_ERROR  = new ApiCode("手机号码异常", _C_MOBILE_ERROR);
+    public static final int _C_SERVER_ERROR = 500;
+    public static final ApiCode SERVER_ERROR = new ApiCode("网络正忙,请稍后再试......", _C_SERVER_ERROR);
+    public static final int _C_PARAMETER_ERROR = 400;
+    public static final ApiCode PARAMETER_ERROR = new ApiCode("参数错误", _C_PARAMETER_ERROR);
+    public static final int _C_UNAUTHORIZED = 401;
+    public static final ApiCode UNAUTHORIZED = new ApiCode("未认证", _C_UNAUTHORIZED);
+    public static final int _C_INVALID_TOKEN = 402;
+    public static final ApiCode INVALID_TOKEN = new ApiCode("无效的Token", _C_INVALID_TOKEN);
+    public static final int _C_ACCESS_DENIED = 403;
+    public static final ApiCode ACCESS_DENIED = new ApiCode("访问被拒绝", _C_ACCESS_DENIED);
+    public static final int _C_SIGNATURE_ERROR = 510;
+    public static final ApiCode SIGNATURE_ERROR = new ApiCode("签名错误", _C_SIGNATURE_ERROR);
+    public static final int _C_API_UPGRADE = 520;
+    public static final ApiCode API_UPGRADE = new ApiCode("接口已升级", _C_API_UPGRADE);
+    public static final int _C_APPID_NOT_EXIST = 530;
+    public static final ApiCode APPID_NOT_EXIST = new ApiCode("应用id不存在", _C_APPID_NOT_EXIST);
+    public static final int _C_RECORD_EXIST = 531;
+    public static final int _C_MOBILE_EXIST = 430;
+    public static final ApiCode RECORD_EXIST = new ApiCode("记录已存在", _C_RECORD_EXIST);
+    public static final int _C_PARAMETER_INVALID = 540;
+    public static final ApiCode PARAMETER_INVALID = new ApiCode("参数验证不通过", _C_PARAMETER_INVALID);
+    public static final int _C_OPERATION_FAIL = 550;
+    public static final ApiCode OPERATION_FAIL = new ApiCode("操作失败", _C_OPERATION_FAIL);
+    public static final int _C_RESOURCE_NULL=600;
+    public static final ApiCode RESOURCE_NULL=new ApiCode("用户对应资源为空",_C_RESOURCE_NULL);
+    public static final int _C_SIGN=555;
+    public static final ApiCode SIGN=new ApiCode("获取验证码过于频繁",_C_SIGN);
+    public static final int _C_NOT_RESOURSE=300	;
+    public static final ApiCode NOT_RESOURSE = new ApiCode("暂无数据", _C_NOT_RESOURSE);
+
+    public static final int _C_NO_UID=506;
+    public static final ApiCode NO_UID=new ApiCode("没有找到相关用户",_C_NO_UID);
+    public static final int _C_PASSWORD_ERROR=507;
+    public static final ApiCode PASSWORD_ERROR=new ApiCode("没有找到相关用户",_C_PASSWORD_ERROR);
+    public static final int U_USER_ERROR=508;
+    public static final ApiCode USER_ERROR=new ApiCode("没有权限",U_USER_ERROR);
+
+
+    public final static int     _C_FILE_TO_BIG = 405;
+    public final static ApiCode FILE_TO_BIG    = new ApiCode("文件过大", _C_FILE_TO_BIG);
+
+    public final static int     _C_FILE_UPLOAD_ERROR= 407;
+    public final static ApiCode FILE_UPLOAD_ERROR    = new ApiCode("上传文件失败", _C_FILE_UPLOAD_ERROR);
+    
+    public final static int     _C_DEVICE_ERROR= 700;
+    public final static ApiCode DEVICE_ERROR    = new ApiCode("没有相关deviceCode信息", _C_DEVICE_ERROR);
+    public final static int     _C_DATA_ERROR= 701;
+    public final static ApiCode DATA_ERROR    = new ApiCode("数据异常", _C_DATA_ERROR);
+    
+    public final static int     _C_UNIONID_ERROR= 703;
+    public final static ApiCode UNIONID_ERROR    = new ApiCode(" unionId为空", _C_UNIONID_ERROR);
+
+    public static final int _C_VERIFICATION_CODE_ERROR=556;
+    public static final ApiCode VERIFICATION_CODE_ERROR = new ApiCode("验证码错误",_C_VERIFICATION_CODE_ERROR);
+
+
+    protected ApiCode(String message, int code) {
+        super(code, message);
+    }
+}
+

+ 93 - 0
src/main/java/cn/efunbox/base/result/ApiResult.java

@@ -0,0 +1,93 @@
+package cn.efunbox.base.result;
+
+import java.io.Serializable;
+import java.util.Map;
+
+public class ApiResult<T> implements Serializable {
+    private static final long serialVersionUID = 1L;
+    private boolean success;
+    private int code;
+    private String message;
+    private T data;
+
+    public ApiResult() {
+        this.success = true;
+    }
+
+    public ApiResult(ApiCode apiCode) {
+        this(apiCode.getCode(),apiCode.getMessage());
+    }
+
+    private ApiResult(int code, String message) {
+        this.success = true;
+        this.code = code;
+        if(code != 200) {
+            this.success = false;
+        }
+
+        this.message = message;
+    }
+
+    private ApiResult(ApiCode apiCode, T data) {
+        this(apiCode.getCode(), apiCode.getMessage());
+        this.data = data;
+    }
+
+    public static ApiResult ok() {
+        return new ApiResult(ApiCode.OK);
+    }
+
+    public static ApiResult ok(Object value) {
+        return new ApiResult(ApiCode.OK, value);
+    }
+
+
+    public static ApiResult ok(Map<String, Object> data) {
+        return new ApiResult(ApiCode.OK, data);
+    }
+
+
+    public static ApiResult error(ApiCode code) {
+        return new ApiResult(code);
+    }
+
+    public static ApiResult error(ApiCode code, Object value) {
+        return new ApiResult(code, value);
+    }
+
+    public static ApiResult error(ApiCode code, Map<String, Object> data) {
+        return new ApiResult(code, data);
+    }
+
+    public boolean getSuccess() {
+        return this.success;
+    }
+
+    public void setSuccess(boolean success) {
+        this.success = success;
+    }
+
+    public int getCode() {
+        return this.code;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
+    public String getMessage() {
+        return this.message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public T getData() {
+        return this.data;
+    }
+
+    public void setData(T data) {
+        this.data = data;
+    }
+}

+ 12 - 0
src/main/java/cn/efunbox/base/service/UserService.java

@@ -0,0 +1,12 @@
+package cn.efunbox.base.service;
+
+
+import cn.efunbox.base.entity.User;
+import cn.efunbox.base.result.ApiResult;
+
+public interface UserService {
+
+    ApiResult getUserById(String id);
+
+    ApiResult update(User member);
+}

+ 38 - 0
src/main/java/cn/efunbox/base/service/impl/UserServiceImpl.java

@@ -0,0 +1,38 @@
+package cn.efunbox.base.service.impl;
+
+import cn.efunbox.base.entity.User;
+import cn.efunbox.base.repository.UserRepository;
+import cn.efunbox.base.result.ApiCode;
+import cn.efunbox.base.result.ApiResult;
+import cn.efunbox.base.service.UserService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Objects;
+
+@Slf4j
+@Service
+public class UserServiceImpl implements UserService {
+
+
+    @Autowired
+    UserRepository userRepository;
+
+    @Override
+    public ApiResult getUserById(String id) {
+        User user = userRepository.find(id);
+
+        return ApiResult.ok(user);
+    }
+
+    @Override
+    public ApiResult update(User member) {
+        if (Objects.isNull(member)) {
+            return ApiResult.error(ApiCode.PARAMETER_ERROR);
+        }
+        userRepository.update(member);
+        return ApiResult.ok(member);
+    }
+
+}

+ 22 - 0
src/main/java/cn/efunbox/base/util/BaseConstant.java

@@ -0,0 +1,22 @@
+package cn.efunbox.base.util;
+
+public class BaseConstant {
+
+
+    public static String BIZ_CODE = "1007";
+    public static String ORDER_BIZ_CODE = "1009";
+
+    public static String APP_CODE = "1007";
+
+    public static String MEMBER_ORDER_TYPE = "0";
+
+    public static String PAY_APP_CHANNEL = "yfklxt";
+
+    public static String SUBJECT_KEY = "cn:efunbox:ott:subject_";   //学前主题
+    public static String SCHEDULE_KEY = "cn:efunbox:ott:schedule_";   //小学课程
+
+    public static String VERIFICATION_CODE_PREFIX = "verify:code:mobile_";   //小学课程
+
+    public static long WEEK_TIME = 7 * 24 * 60 * 60 * 1000;   //一周时间
+
+}

+ 62 - 0
src/main/java/cn/efunbox/base/util/CommonRedisHelper.java

@@ -0,0 +1,62 @@
+package cn.efunbox.base.util;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+/**
+ * CommonRedisHelper
+ * Created by wangys on 2019/04/09
+ */
+
+/**
+ * Description: 通用Redis帮助类
+ * User: zhouzhou
+ * Date: 2018-09-05
+ * Time: 15:39
+ */
+@Component
+public class CommonRedisHelper {
+    @Autowired
+    private RedisTemplate<String, String> redisTemplate;
+
+    /**
+     * 加锁
+     *
+     * @param key   键
+     * @param value 当前时间 + 超时时间
+     * @return 是否拿到锁
+     */
+    public boolean lock(String key, String value) {
+        if (redisTemplate.opsForValue().setIfAbsent(key, value)) {
+            return true;
+        }
+        String currentValue = redisTemplate.opsForValue().get(key);
+        //如果锁过期
+        if (!StringUtils.isEmpty(currentValue)
+                && Long.parseLong(currentValue) < System.currentTimeMillis()) {
+            String oldValue = redisTemplate.opsForValue().getAndSet(key, value);
+            //是否已被别人抢占
+            return StringUtils.isNotEmpty(oldValue) && oldValue.equals(currentValue);
+        }
+        return false;
+    }
+
+    /**
+     * 解锁
+     *
+     * @param key   键
+     * @param value 当前时间 + 超时时间
+     */
+    public void unlock(String key, String value) {
+        try {
+            String currentValue = redisTemplate.opsForValue().get(key);
+            if (!StringUtils.isEmpty(currentValue) && currentValue.equals(value)) {
+                redisTemplate.opsForValue().getOperations().delete(key);
+            }
+        } catch (Exception e) {
+//            log.error("redis解锁异常");
+        }
+    }
+
+}

+ 53 - 0
src/main/java/cn/efunbox/base/util/CurrentWeekUtil.java

@@ -0,0 +1,53 @@
+package cn.efunbox.base.util;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+
+/**
+ * CurrentWeekUtil
+ * Created by xusq on 2018/1/30.
+ */
+public class CurrentWeekUtil {
+
+    public static int currentWeek(){
+
+        Calendar c = Calendar.getInstance();
+//        c.add(Calendar.DATE,7);
+
+        int currentWeek = c.get(Calendar.WEEK_OF_YEAR);
+        int year = c.get(Calendar.YEAR);
+
+        int weekNumber = year * 100 + currentWeek;
+
+        return  weekNumber;
+    }
+
+    public static List<Integer> getWeekDay(int weekNum){
+        Calendar c = Calendar.getInstance();
+        c.setFirstDayOfWeek(Calendar.SATURDAY);
+        c.set(Calendar.YEAR, weekNum/100);
+        c.set(Calendar.WEEK_OF_YEAR, weekNum%100);
+        c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek());
+        SimpleDateFormat sdf=new SimpleDateFormat("d");
+        List<Integer> dayList = new ArrayList<>();
+        for (int i = 0 ; i < 7 ; i++) {
+            c.add(Calendar.DAY_OF_WEEK, 1);
+            dayList.add(Integer.valueOf(sdf.format(c.getTime())));
+        }
+        return dayList;
+    }
+
+    public static void main(String[] args) {
+        List<Integer> i = CurrentWeekUtil.getWeekDay(201836);
+        System.out.println(i);
+        int i1 = CurrentWeekUtil.currentWeek();
+        System.out.println(i1);
+
+//        String s = UUID.randomUUID().toString();
+//        System.out.println(s);
+//        String s1 = UUID.randomUUID().toString();
+//        System.out.println(s1);
+    }
+}

+ 288 - 0
src/main/java/cn/efunbox/base/util/DateUtil.java

@@ -0,0 +1,288 @@
+package cn.efunbox.base.util;
+
+
+import org.apache.commons.lang3.time.DateFormatUtils;
+import org.apache.commons.lang3.time.DateUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+
+/**
+ * 日期工具类
+ */
+public class DateUtil {
+    private static Logger log = LoggerFactory.getLogger(DateUtil.class);
+
+    private static final String DEFAULT_PATTERN = "yyyy-MM-dd";
+    /**
+     * 一天的毫秒数
+     */
+    public static long TIME_OF_ONE_DAY = 24 * 60 * 60 * 1000;
+    /**
+     * 将日期转换为字符串
+     *
+     * @return
+     */
+    public static String dateFormat() {
+        return dateFormat(new Date(), "yyyy-MM-dd HH:mm:ss");
+    }
+
+    public static String dateFormat(String pattern) {
+        return dateFormat(new Date(), pattern);
+    }
+
+    public static String dateFormat(Date date, String pattern) {
+        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
+        return sdf.format(date);
+    }
+
+
+    public static String dateFormatDay(Date date) {
+        SimpleDateFormat sdf = new SimpleDateFormat(DEFAULT_PATTERN);
+        return sdf.format(date);
+    }
+
+    /**
+     * 字符串转换为日期
+     *
+     * @param source
+     * @return
+     * @throws ParseException
+     */
+    public static Date StrToDate(String source) {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+        try {
+            return sdf.parse(source);
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    public static Date StrToDate(String source, String pattern) throws ParseException {
+        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
+        return sdf.parse(source);
+    }
+
+    /**
+     * 增加年
+     *
+     * @param date
+     * @param i
+     * @return
+     */
+    public static Date addYears(Date date, int i) {
+        return DateUtils.addYears(date, i);
+    }
+
+    /**
+     * 增加月
+     *
+     * @param date
+     * @param i
+     * @return
+     */
+    public static Date addMonths(Date date, int i) {
+        return DateUtils.addMonths(date, i);
+    }
+
+    /**
+     * 增加小时
+     *
+     * @param date
+     * @param amount
+     * @return
+     */
+    public static Date addHours(Date date, int amount) {
+        return DateUtils.addHours(date, amount);
+    }
+
+    /**
+     * 增加天数
+     *
+     * @param date
+     * @param amount
+     * @return
+     */
+    public static Date addDays(Date date, int amount) {
+        return DateUtils.addDays(date, amount);
+    }
+
+    /**
+     * 日期格式换行为GMT格式
+     *
+     * @param date
+     * @return
+     */
+    public static String toGMTString(Date date) {
+        SimpleDateFormat df = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z", Locale.UK);
+        df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));
+        return df.format(date);
+    }
+
+    /**
+     * 获取传入日期和当前当前日期相隔分钟数
+     *
+     * @param date
+     * @return
+     * @throws ParseException
+     */
+    public static int getDateDiffMinutes(String date){
+        long intervalMilli = 0;
+        try {
+            long now = System.currentTimeMillis();
+            long ago = StrToDate(date, "yyyy-MM-dd HH:mm:ss").getTime();
+
+            intervalMilli = now - ago;
+            if (intervalMilli < 0) {
+                return 0;
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+            return 0;
+        }
+        return (int)(intervalMilli / (60 * 1000));
+    }
+
+    /**
+     * 获取传入日期相隔分钟数
+     * date1 - data
+     * @param date
+     * @param date1
+     * @return
+     * @throws ParseException
+     */
+    public static int getDateDiffMinutes(String date,String date1){
+        long intervalMilli = 0;
+        try {
+            long time = StrToDate(date, "yyyy-MM-dd HH:mm:ss").getTime();
+            long time1 = StrToDate(date1, "yyyy-MM-dd HH:mm:ss").getTime();
+
+            intervalMilli = time1 - time;
+            if (intervalMilli < 0) {
+                return 0;
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+            return 0;
+        }
+        return (int)(intervalMilli / (60 * 1000));
+    }
+
+    /**
+     * 获取传入日期和当前当前日期相隔天数
+     *
+     * @param date
+     * @return
+     * @throws ParseException
+     */
+    public static int getDateDiffDays(String date) throws ParseException {
+        long now = System.currentTimeMillis();
+        long ago = StrToDate(date, "yyyy-MM-dd").getTime();
+
+        long intervalMilli = now - ago;
+        if (intervalMilli < 0) {
+            return 0;
+        }
+        return (int) (intervalMilli / (24 * 3600 * 1000));
+    }
+
+    public static int getDateDiffDays2(String date) throws ParseException {
+        long now = System.currentTimeMillis();
+        long ago = StrToDate(date, "yyyy-MM-dd").getTime();
+
+        long intervalMilli = ago - now;
+        if (intervalMilli < 0) {
+            return 0;
+        }
+        return (int) (intervalMilli / (24 * 3600 * 1000));
+    }
+
+    /**
+     * 获取传入日期和当前当前日期相隔年数
+     *
+     * @param date
+     * @return
+     * @throws ParseException
+     */
+    public static int getDateDiffYears(Date date) {
+        Calendar cal1 = Calendar.getInstance();
+        cal1.setTime(date);
+
+        Calendar cal2 = Calendar.getInstance();
+        cal2.setTime(new Date());
+
+        return cal2.get(Calendar.YEAR) - cal1.get(Calendar.YEAR);
+    }
+
+    /**
+     * 将DATE类型转成String类型,pattern默认为yyyy-MM-dd
+     *
+     * @return
+     */
+    public static String getDateStr() {
+        Date  date = new Date();
+        SimpleDateFormat formater = new SimpleDateFormat(DEFAULT_PATTERN);
+        return formater.format(date);
+    }
+
+    public static String getTomorrowDateStr() {
+        Date  date = new Date(System.currentTimeMillis() + TIME_OF_ONE_DAY);
+        SimpleDateFormat formater = new SimpleDateFormat(DEFAULT_PATTERN);
+        return formater.format(date);
+    }
+
+    public static String getPreDateStr() {
+        Date  date = new Date(System.currentTimeMillis() - TIME_OF_ONE_DAY);
+        SimpleDateFormat formater = new SimpleDateFormat(DEFAULT_PATTERN);
+        return formater.format(date);
+    }
+
+    public static String formatPreDayEndTime(String date) {
+//        Date  date = new Date(System.currentTimeMillis() - TIME_OF_ONE_DAY);
+//        return  DateFormatUtils.format(date, "yyyy-MM-dd 23:59:59");
+        return date + " 23:59:59";
+    }
+
+
+
+    public static String formatPreDayStartTime(String date) {
+//        Date  date = new Date(System.currentTimeMillis() - TIME_OF_ONE_DAY);
+//        return  DateFormatUtils.format(date, "yyyy-MM-dd 00:00:00");
+        return date + " 00:00:00";
+    }
+
+    public static Date getPreDayStartTime() {
+
+        String format = DateFormatUtils.format(new Date(System.currentTimeMillis() - TIME_OF_ONE_DAY), "yyyy-MM-dd 00:00:00");
+        java.text.DateFormat dfNew = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        try {
+            return dfNew.parse(format);
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        return new Date();
+    }
+
+
+    public static void main(String[] args) throws Exception {
+        //Date preDayStartTime = getPreDayStartTime();
+        //System.out.println(preDayStartTime);
+
+        //System.out.println(formatPreDayEndTime());
+        //System.out.println(dateFormat(new Date(),"yyyyMMdd"));
+        //System.out.println(getDateDiffMinutes("2020-05-13 12:23:30","2020-05-13 12:25:59"));
+        //String questionList = "BD1521101|BD1521102|BD1521103";
+        //String[] questionCodeList = questionList.splitc("\\|");
+        System.out.println(getDateDiffDays2("2021-02-22"));
+        Date date = addDays(new Date(),getDateDiffDays2("2021-03-02")+1);
+        System.out.println(dateFormat(date,"yyyy-MM-dd"));
+
+    }
+
+}

+ 260 - 0
src/main/java/cn/efunbox/base/util/Encrypt.java

@@ -0,0 +1,260 @@
+package cn.efunbox.base.util;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.binary.Hex;
+import sun.misc.BASE64Decoder;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Field;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.*;
+
+/**
+ * 常見的几种加密方式
+ */
+@Slf4j
+public class Encrypt {
+
+    public static final String SIGN = "sign";
+
+    public static String createSHA256Sign(Map<String, Object> paramMap, String signKey) {
+
+        List<String> sortedKeys = new ArrayList<String>();
+        for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
+            if (SIGN.equals(entry.getKey())) {
+                continue;
+            }
+
+            sortedKeys.add(entry.getKey());
+        }
+
+        if (sortedKeys.size() == 0) {
+            // 没有参数
+            return "";
+        }
+
+        Collections.sort(sortedKeys);
+
+        StringBuffer buff = new StringBuffer("");
+        for (String key : sortedKeys) {
+            Object val = paramMap.get(key);
+            if (Objects.isNull(val)) {
+                continue;
+            }
+
+            buff.append(key).append("=").append(val).append("&");
+        }
+
+        buff.deleteCharAt(buff.length()-1);
+        buff.append(signKey);
+
+        try {
+            return Encrypt.String2SHA256(buff.toString());
+        } catch (Exception e) {
+            throw new RuntimeException("签名错误");
+        }
+    }
+
+    public static String createOutSideSHA256Sign(Map<String, Object> paramMap, String signKey) {
+
+        List<String> sortedKeys = new ArrayList<>();
+        for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
+            if (SIGN.equals(entry.getKey())) {
+                continue;
+            }
+
+            sortedKeys.add(entry.getKey());
+        }
+
+        if (sortedKeys.size() == 0) {
+            // 没有参数
+            return "";
+        }
+
+        Collections.sort(sortedKeys);
+
+        StringBuffer buff = new StringBuffer("");
+        for (String key : sortedKeys) {
+            Object val = paramMap.get(key);
+            if (Objects.isNull(val)) {
+                continue;
+            }
+
+            buff.append(key).append("=").append(val).append("&");
+        }
+
+        buff.append("sign=");
+        buff.append(signKey);
+
+        try {
+            return Encrypt.String2SHA256(buff.toString());
+        } catch (Exception e) {
+            throw new RuntimeException("签名错误");
+        }
+    }
+
+    /**
+     *  利用Apache的工具类实现SHA-256加密
+     * @param str 加密后的报文
+     * @return
+     */
+    public static String String2SHA256(String str){
+        MessageDigest messageDigest;
+        String encdeStr = "";
+        try {
+            messageDigest = MessageDigest.getInstance("SHA-256");
+            byte[] hash = messageDigest.digest(str.getBytes("UTF-8"));
+            encdeStr = Hex.encodeHexString(hash);
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return encdeStr;
+    }
+    //---------
+    /**
+     * 利用java原生的摘要实现SHA256加密
+     * @param str 加密后的报文
+     * @return
+     */
+    public static String String2SHA256StrJava(String str){
+        MessageDigest messageDigest;
+        String encodeStr = "";
+        try {
+            messageDigest = MessageDigest.getInstance("SHA-256");
+            messageDigest.update(str.getBytes("UTF-8"));
+            encodeStr = byte2Hex(messageDigest.digest());
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return encodeStr;
+    }
+ 
+    /**
+     * 将byte转为16进制
+     * @param bytes
+     * @return
+     */
+    private static String byte2Hex(byte[] bytes){
+        StringBuffer stringBuffer = new StringBuffer();
+        String temp = null;
+        for (int i=0;i<bytes.length;i++){
+            temp = Integer.toHexString(bytes[i] & 0xFF);
+            if (temp.length()==1){
+                //1得到一位的进行补0操作
+                stringBuffer.append("0");
+            }
+            stringBuffer.append(temp);
+        }
+        return stringBuffer.toString();
+    }
+
+    public static Map<String,Object> objectToMap(Object obj) throws Exception {
+        if(obj == null){
+            return null;
+        }
+        Map<String, Object> map = new HashMap<String, Object>();
+
+        Field[] declaredFields = obj.getClass().getDeclaredFields();
+        for (Field field : declaredFields){
+            field.setAccessible(true);
+        map.put(field.getName(), field.get(obj));
+        }
+        return map;
+    }
+
+    /**
+     * SHA1加密
+     * @param arr
+     * @return
+     */
+    public static String createSHA1Sign(String... arr) {
+        try {
+            Arrays.sort(arr);
+            StringBuilder content = new StringBuilder();
+            for (int i = 0; i < arr.length; i++) {
+                content.append(arr[i]);
+            }
+            MessageDigest md = MessageDigest.getInstance("SHA-1");
+            byte[] digest = md.digest(content.toString().getBytes());
+            return byte2Hex(digest);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * AES 加密
+     * 参考 https://www.cnblogs.com/sunliyuan/p/11130446.html
+     * @return
+     * @throws Exception
+     */
+    public static String encrypt(String data,String key) throws Exception {
+        try {
+            Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
+            int blockSize = cipher.getBlockSize();
+
+            byte[] dataBytes = data.getBytes();
+            int plaintextLength = dataBytes.length;
+            if (plaintextLength % blockSize != 0) {
+                plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
+            }
+
+            byte[] plaintext = new byte[plaintextLength];
+            System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
+
+            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
+
+            cipher.init(Cipher.ENCRYPT_MODE, keyspec);
+            byte[] encrypted = cipher.doFinal(plaintext);
+
+            return new sun.misc.BASE64Encoder().encode(encrypted);
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * AES解密
+     * 参考 https://www.cnblogs.com/sunliyuan/p/11130446.html
+     * @param data 待解密内容
+     * @param key 密钥
+     * @return
+     * @throws Exception
+     */
+    public static String desEncrypt(String data,String key) throws Exception {
+        try {
+            byte[] encrypted1 = new BASE64Decoder().decodeBuffer(data);
+
+            Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
+            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
+
+            cipher.init(Cipher.DECRYPT_MODE, keyspec);
+
+            byte[] original = cipher.doFinal(encrypted1);
+            String originalString = new String(original);
+            return originalString;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+
+        //String signature = "20200114_86570b47-1ac7-532f-531c-4e761f322ce9_efunbox_sRTI2TEFENNZRu2fyEArvhn9giX0QHTze08cV/onriU=";
+        //System.out.println(createSHA1Sign(signature));
+        //System.out.println(desEncrypt("ps0MIFj3jQzh/swEr5v3SmzZyOfeg7+ghbyGTn7MS4I=","efunbox_xyyfxxbg"));
+//        System.out.println(encrypt("===","efunbox_xyyfxxbg"));
+//        System.out.println(desEncrypt("JbeqomEM1MoPWVE0tcK5FA==","efunbox_xyyfxxbg"));
+    }
+}

+ 159 - 0
src/main/java/cn/efunbox/base/util/EncryptUtils.java

@@ -0,0 +1,159 @@
+package cn.efunbox.base.util;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.lang3.StringUtils;
+import sun.misc.BASE64Decoder;
+
+import javax.crypto.Cipher;
+import javax.crypto.KeyGenerator;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * EncryptUtils
+ * Created by wangys on
+ */
+public class EncryptUtils {
+    /**
+     * 密钥
+     */
+    private static final String KEY = "GfqqwfctR8gdNGUS";// AES加密要求key必须要128个比特位(这里需要长度为16,否则会报错)
+
+    /**
+     * 算法
+     */
+    private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding";
+
+//   private static String content = "http://baidu-yuwen-video.ai160.com/vs2m/001/00103050/00103050001/00103050001.m3u8";
+//   private static String content = "http://baidu-yuwen-video.ai160.com/vs2m/001/00103050/00103050002/00103050002.m3u8";
+//   private static String content = "http://baidu-yuwen-video.ai160.com/vs2m/001/00103050/00103050003/00103050003.m3u8";
+//   private static String content = "http://baidu-yuwen-video.ai160.com/vs2m/001/00103050/00103050004/00103050004.m3u8";
+//   private static String content = "http://baidu-yuwen-video.ai160.com/vs2m/001/00103050/00103050005/00103050005.m3u8";
+//   private static String content = "http://baidu-yuwen-video.ai160.com/vs2m/001/00103050/00103050011/00103050011.m3u8";
+//   private static String content = "http://baidu-yuwen-video.ai160.com/vs2m/001/00103050/00103050012/00103050012.m3u8";
+//   private static String content = "http://baidu-yuwen-video.ai160.com/vs2m/001/00103050/00103050013/00103050013.m3u8";
+//   private static String content = "http://baidu-yuwen-video.ai160.com/vs2m/001/00103050/00103050014/00103050014.m3u8";
+//   private static String content = "http://baidu-yuwen-video.ai160.com/vs2m/001/00103050/00103050015/00103050015.m3u8";
+//   private static String content = "http://baidu-yuwen-video.ai160.com/vs2m/001/00103050/00103050016/00103050016.m3u8";
+//   private static String content = "http://baidu-yuwen-video.ai160.com/vs2m/001/00103050/00103050017/00103050017.m3u8";
+//   private static String content = "http://baidu-yuwen-video.ai160.com/vs2m/001/00103050/00103050018/00103050018.m3u8";
+//   private static String content = "http://baidu-yuwen-video.ai160.com/vs2m/001/00103050/00103050019/00103050019.m3u8";
+//   private static String content = "http://baidu-yuwen-video.ai160.com/vs2m/001/00103050/00103050020/00103050020.m3u8";
+//   private static String content = "http://baidu-yuwen-video.ai160.com/vs2m/001/00103050/00103050021/00103050021.m3u8";
+//   private static String content = "http://baidu-yuwen-video.ai160.com/vs2m/001/00103050/00103050022/00103050022.m3u8";
+//   private static String content = "http://baidu-yuwen-video.ai160.com/vs2m/001/00103050/00103050023/00103050023.m3u8";
+//   private static String content = "http://baidu-yuwen-video.ai160.com/vs2m/001/00103050/00103050024/00103050024.m3u8";
+//   private static String content = "http://baidu-yuwen-video.ai160.com/vs2m/001/00103050/00103050025/00103050025.m3u8";
+  private static String content = "http://baidu-yuwen-video.ai160.com/vs2m/001/00103050/00103050026/00103050026.m3u8";
+    public static void main(String[] args) throws Exception {
+        //content = "http://baidu-yuwen-video.ai160.com/vs2m/001/00103050/00103050001/00103050001.m3u8";
+        System.out.println("加密前:" + content);
+
+        System.out.println("加密密钥和解密密钥:" + KEY);
+
+        String encrypt = aesEncrypt(content);
+        System.out.println("加密后:" + encrypt);
+
+        String decrypt = aesDecrypt(encrypt, KEY);
+
+        System.out.println("解密后:" + decrypt);
+    }
+
+    /**
+     * base 64 encode
+     * @param bytes 待编码的byte[]
+     * @return 编码后的base 64 code
+     */
+    private static String base64Encode(byte[] bytes){
+        return Base64.encodeBase64String(bytes);
+    }
+
+    /**
+     * base 64 decode
+     * @param base64Code 待解码的base 64 code
+     * @return 解码后的byte[]
+     * @throws Exception 抛出异常
+     */
+    private static byte[] base64Decode(String base64Code) throws Exception{
+        return StringUtils.isEmpty(base64Code) ? null : new BASE64Decoder().decodeBuffer(base64Code);
+    }
+
+
+    /**
+     * AES加密
+     * @param content 待加密的内容
+     * @param encryptKey 加密密钥
+     * @return 加密后的byte[]
+     */
+    private static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {
+        KeyGenerator kgen = KeyGenerator.getInstance("AES");
+        kgen.init(128);
+        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
+        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"));
+
+        return cipher.doFinal(content.getBytes("utf-8"));
+    }
+
+
+    /**
+     * AES加密为base 64 code
+     *
+     * @param content 待加密的内容
+     * @return 加密后的base 64 code
+     */
+    public static String aesEncrypt(String content)  {
+        String encode = null;
+        try {
+            encode = base64Encode(aesEncryptToBytes(content, KEY));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return encode;
+    }
+
+    /**
+     * AES加密为base 64 code
+     *
+     * @param content 待加密的内容
+     * @return 加密后的base 64 code
+     */
+    public static String aesEncrypt(String content,String secret)  {
+        String encode = null;
+        try {
+            encode = base64Encode(aesEncryptToBytes(content, secret));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return encode;
+    }
+
+    /**
+     * AES解密
+     *
+     * @param encryptBytes 待解密的byte[]
+     * @param decryptKey 解密密钥
+     * @return 解密后的String
+     */
+    private static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception {
+        KeyGenerator kgen = KeyGenerator.getInstance("AES");
+        kgen.init(128);
+
+        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
+        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"));
+        byte[] decryptBytes = cipher.doFinal(encryptBytes);
+
+        return new String(decryptBytes);
+    }
+
+
+    /**
+     * 将base 64 code AES解密
+     *
+     * @param encryptStr 待解密的base 64 code
+     * @param decryptKey 解密密钥
+     * @return 解密后的string
+     */
+    public static String aesDecrypt(String encryptStr, String decryptKey) throws Exception {
+        return StringUtils.isEmpty(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr), decryptKey);
+    }
+
+}

+ 63 - 0
src/main/java/cn/efunbox/base/util/ExcelUtil.java

@@ -0,0 +1,63 @@
+package cn.efunbox.base.util;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.util.Objects;
+
+/**
+ * ExcelUtil
+ * Created by xusq on 2020/9/14.
+ */
+@Slf4j
+public class ExcelUtil {
+
+    private final static String EXCEL_2003 = ".xls";    //2003- 版本的excel
+    private final static String EXCEL_2007 = ".xlsx";   //2007+ 版本的excel
+
+    public static Workbook getWorkbook(MultipartFile file) {
+        Workbook wb = null;
+        String fileName = file.getOriginalFilename();
+        String fileType = fileName.substring(fileName.lastIndexOf("."));
+        try {
+            if (EXCEL_2003.equals(fileType)) {
+                wb = new HSSFWorkbook(file.getInputStream());  //2003-
+            } else if (EXCEL_2007.equals(fileType)) {
+                wb = new XSSFWorkbook(file.getInputStream());  //2007+
+            }
+        } catch (IOException e) {
+            log.error("find input stream is error , {}",e.getMessage(),e);
+        }
+
+        return wb;
+    }
+
+    /**
+     * 单表值获取
+     *
+     * @param cell 获取
+     * @return 类型
+     */
+    public static String getCell(Cell cell) {
+        if (Objects.nonNull(cell)) {
+            CellType cellType = cell.getCellTypeEnum();
+            if (cellType == CellType.STRING) {//字符串类型
+                //System.out.println(cell.getStringCellValue());
+                return cell.getStringCellValue().trim();
+            }
+            if (cellType == CellType.NUMERIC) {//数字类型
+                long numericCellValue = (long) cell.getNumericCellValue();
+                //System.out.println(numericCellValue);
+                return numericCellValue + "";
+            }
+        }
+        return null;
+    }
+
+}

+ 186 - 0
src/main/java/cn/efunbox/base/util/HttpUtils.java

@@ -0,0 +1,186 @@
+package cn.efunbox.base.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import java.io.*;
+import java.net.ConnectException;
+import java.net.URL;
+import java.util.UUID;
+
+public class HttpUtils {
+	private static Logger LOGGER = LoggerFactory.getLogger(HttpUtils.class);
+
+	public static String doRequest(String requestUrl, String requestMethod, String paramBody) {
+
+		String log = "UUID = "+UUID.randomUUID() + " ; HttpUtils : ";
+
+		LOGGER.info(log + " http weixin api request >>> request = " + requestUrl + " ;paramBody = " + paramBody);
+
+		String result = null;
+
+		try {
+
+			HttpsURLConnection httpUrlConn = setSSLContext(requestUrl,requestMethod);
+
+
+			// 当有数据需要提交时
+			if (null != paramBody) {
+				OutputStream outputStream = httpUrlConn.getOutputStream();
+				// 注意编码格式,防止中文乱码
+				outputStream.write(paramBody.getBytes("UTF-8"));
+				outputStream.close();
+			}
+
+			result = connection2String(httpUrlConn);
+
+			LOGGER.info(log + " http weixin api result >>> request = " + requestUrl + " ;paramBody = " + paramBody + " ;result" + result);
+		} catch (ConnectException ce) {
+			LOGGER.error(log + "Weixin request { " + requestUrl + " } connection timed out. paramBody : " + paramBody + ce.getMessage(),ce);
+		} catch (Exception e) {
+			LOGGER.error(log + "http request error:{} requestUrl : " + requestUrl + "paramBody : " + paramBody, e);
+		}
+
+		return result;
+	}
+
+
+	public static byte[] doRequestByte(String requestUrl, String requestMethod, String paramBody) {
+
+		String log = "UUID = "+UUID.randomUUID() + " ; HttpUtils : ";
+
+		LOGGER.info(log + " http weixin api request >>> request = " + requestUrl + " ;paramBody = " + paramBody);
+
+		byte[] result = null;
+
+		try {
+
+			HttpsURLConnection httpUrlConn = setSSLContext(requestUrl,requestMethod);
+
+
+			// 当有数据需要提交时
+			if (null != paramBody) {
+				OutputStream outputStream = httpUrlConn.getOutputStream();
+				// 注意编码格式,防止中文乱码
+				outputStream.write(paramBody.getBytes("UTF-8"));
+				outputStream.close();
+			}
+
+			InputStream inputStream = httpUrlConn.getInputStream();
+			ByteArrayOutputStream outstream = new ByteArrayOutputStream(httpUrlConn.getContentLength());
+			byte[] buffer = new byte[4096];
+			int len;
+			while ((len = inputStream.read(buffer)) > 0) {
+				outstream.write(buffer, 0, len);
+			}
+			outstream.close();
+			result = outstream.toByteArray();
+
+			LOGGER.info(log + " http weixin api result >>> request = " + requestUrl + " ;paramBody = " + paramBody );
+		} catch (ConnectException ce) {
+			LOGGER.error(log + "Weixin request { " + requestUrl + " } connection timed out. paramBody : " + paramBody + ce.getMessage(),ce);
+		} catch (Exception e) {
+			LOGGER.error(log + "http request error:{} requestUrl : " + requestUrl + "paramBody : " + paramBody, e);
+		}
+
+		return result;
+	}
+
+	private static String connection2String(HttpsURLConnection httpUrlConn) {
+
+
+		StringBuffer buffer = new StringBuffer();
+		// 将返回的输入流转换成字符串
+		BufferedReader bufferedReader = null;
+		try {
+
+			bufferedReader = new BufferedReader(new InputStreamReader(httpUrlConn.getInputStream(), "utf-8"));
+
+
+			String str = null;
+			while ((str = bufferedReader.readLine()) != null) {
+				buffer.append(str);
+			}
+
+		} catch (IOException e) {
+			LOGGER.error("HttpsURLConnection2String is error," + e.getMessage(), e);
+		} finally {
+			if (bufferedReader != null) {
+				try {
+					bufferedReader.close();
+				} catch (IOException e) {
+					LOGGER.error("bufferedReader close error," + e.getMessage(), e);
+				}
+			}
+		}
+
+		httpUrlConn.disconnect();
+
+		String result = buffer.toString();
+
+		return result;
+	}
+
+	public static String doGet(String requestUrl, String paramBody) {
+		return doRequest(requestUrl, "GET", paramBody);
+	}
+
+	public static String doPost(String requestUrl, String paramBody) {
+		return doRequest(requestUrl, "POST", paramBody);
+	}
+
+	public static String doRequest(String requestUrl, String requestMethod) {
+
+		String result = null;
+
+		String log = "UUID = "+UUID.randomUUID();
+		LOGGER.info(log + " http weixin api request >>> request = " + requestUrl);
+
+		try {
+			HttpsURLConnection httpUrlConn = setSSLContext(requestUrl,requestMethod);
+			// 将返回的输入流转换成字符串
+			result = connection2String(httpUrlConn);
+
+			LOGGER.info(log + " http weixin api result >>> request = " + requestUrl + " ;result" + result);
+		} catch (ConnectException ce) {
+			LOGGER.error(log + " Weixin request {" + requestUrl + "} connection timed out." + ce.getMessage(),ce);
+		} catch (Exception e) {
+			LOGGER.error(log + " http request error:{} requestUrl :" + requestUrl + e.getMessage(), e);
+		}
+
+		return result;
+	}
+
+
+	private static HttpsURLConnection setSSLContext(String requestUrl,String requestMethod) throws Exception{
+
+		HttpsURLConnection httpUrlConn = null;
+		// 创建SSLContext对象,并使用我们指定的信任管理器初始化
+		TrustManager[] tm = { new MyX509TrustManager() };
+		SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
+		sslContext.init(null, tm, new java.security.SecureRandom());
+		// 从上述SSLContext对象中得到SSLSocketFactory对象
+		SSLSocketFactory ssf = sslContext.getSocketFactory();
+
+		URL url = new URL(requestUrl);
+		httpUrlConn = (HttpsURLConnection) url.openConnection();
+		httpUrlConn.setSSLSocketFactory(ssf);
+
+		httpUrlConn.setDoOutput(true);
+		httpUrlConn.setDoInput(true);
+		httpUrlConn.setUseCaches(false);
+		// 设置请求方式(GET/POST)
+		httpUrlConn.setRequestMethod(requestMethod);
+
+		if ("GET".equalsIgnoreCase(requestMethod)) {
+			httpUrlConn.connect();
+		}
+
+
+		return httpUrlConn;
+	}
+}

+ 130 - 0
src/main/java/cn/efunbox/base/util/HttpsUtils.java

@@ -0,0 +1,130 @@
+package cn.efunbox.base.util;
+
+import org.apache.http.*;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.conn.ssl.TrustStrategy;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.ssl.SSLContextBuilder;
+import org.apache.http.util.EntityUtils;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class HttpsUtils {
+	private static final String HTTP = "http";
+	private static final String HTTPS = "https";
+	private static SSLConnectionSocketFactory sslsf = null;
+	private static PoolingHttpClientConnectionManager cm = null;
+	private static SSLContextBuilder builder = null;
+	static {
+		try {
+			builder = new SSLContextBuilder();
+			// 全部信任 不做身份鉴定
+			builder.loadTrustMaterial(null, new TrustStrategy() {
+				@Override
+				public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
+					return true;
+				}
+			});
+			sslsf = new SSLConnectionSocketFactory(builder.build(), new String[] { "SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.2" }, null, NoopHostnameVerifier.INSTANCE);
+			Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create().register(HTTP, new PlainConnectionSocketFactory()).register(HTTPS, sslsf).build();
+			cm = new PoolingHttpClientConnectionManager(registry);
+			cm.setMaxTotal(200);// max connection
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * httpClient post请求
+	 * 
+	 * @param url 请求url
+	 * @param header 头部信息
+	 * @param param 请求参数 form提交适用
+	 * @param entitys 请求实体 json/xml提交适用
+	 * @return 可能为空 需要处理
+	 * @throws Exception */
+	public static String post(String url, Map<String, String> header, Map<String, String> param, HttpEntity entity) throws Exception {
+		String result = "";
+		CloseableHttpClient httpClient = null;
+		try {
+			httpClient = getHttpClient();
+			HttpPost httpPost = new HttpPost(url);
+			// 设置头信息
+			if (null != header && header.size() > 0) {
+				for (Map.Entry<String, String> entry : header.entrySet()) {
+					httpPost.addHeader(entry.getKey(), entry.getValue());
+				}
+			}
+			// 设置请求参数
+			if (null != param && param.size() > 0) {
+				List<NameValuePair> formparams = new ArrayList<NameValuePair>();
+				for (Map.Entry<String, String> entry : param.entrySet()) {
+					// 给参数赋值
+					formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
+				}
+				UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);
+				httpPost.setEntity(urlEncodedFormEntity);
+			}
+			// 设置实体 优先级高
+			if (entity != null) {
+				httpPost.setEntity(entity);
+			}
+			HttpResponse httpResponse = httpClient.execute(httpPost);
+			int statusCode = httpResponse.getStatusLine().getStatusCode();
+			if (statusCode == HttpStatus.SC_OK) {
+				HttpEntity resEntity = httpResponse.getEntity();
+				result = EntityUtils.toString(resEntity);
+			} else {
+				readHttpResponse(httpResponse);
+			}
+		} catch (Exception e) {
+			throw e;
+		} finally {
+			if (httpClient != null) {
+				httpClient.close();
+			}
+		}
+		return result;
+	}
+
+	public static CloseableHttpClient getHttpClient() throws Exception {
+		CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).setConnectionManager(cm).setConnectionManagerShared(true).build();
+		return httpClient;
+	}
+
+	public static String readHttpResponse(HttpResponse httpResponse) throws ParseException, IOException {
+		StringBuilder builder = new StringBuilder();
+		// 获取响应消息实体
+		HttpEntity entity = httpResponse.getEntity();
+		// 响应状态
+		builder.append("status:" + httpResponse.getStatusLine());
+		builder.append("headers:");
+		HeaderIterator iterator = httpResponse.headerIterator();
+		while (iterator.hasNext()) {
+			builder.append("\t" + iterator.next());
+		}
+		// 判断响应实体是否为空
+		if (entity != null) {
+			String responseString = EntityUtils.toString(entity);
+			builder.append("response length:" + responseString.length());
+			builder.append("response content:" + responseString.replace("\r\n", ""));
+		}
+		System.out.println("rsponse:"+builder);
+		return builder.toString();
+	}
+}

+ 62 - 0
src/main/java/cn/efunbox/base/util/IpUtils.java

@@ -0,0 +1,62 @@
+package cn.efunbox.base.util;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * IpUtils
+ * Created by xusq on 2017/10/19.
+ */
+@Slf4j
+public class IpUtils {
+    private IpUtils(){}
+
+    public static String getIp(HttpServletRequest request) {
+
+        String ip = request.getHeader("X-Forwarded-For");
+        if(StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)){
+            //多次反向代理后会有多个ip值,第一个ip才是真实ip
+            int index = ip.indexOf(",");
+            if(index != -1){
+                return ip.substring(0,index);
+            }else{
+                return ip;
+            }
+        }
+        ip = request.getHeader("X-Real-IP");
+        if(StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)){
+            return ip;
+        }
+        return request.getRemoteAddr();
+    }
+    private static final String[] HEADERS_TO_TRY = {
+            "X-Forwarded-For",
+            "Proxy-Client-IP",
+            "WL-Proxy-Client-IP",
+            "HTTP_X_FORWARDED_FOR",
+            "HTTP_X_FORWARDED",
+            "HTTP_X_CLUSTER_CLIENT_IP",
+            "HTTP_CLIENT_IP",
+            "HTTP_FORWARDED_FOR",
+            "HTTP_FORWARDED",
+            "HTTP_VIA",
+            "REMOTE_ADDR",
+            "X-Real-IP"};
+
+    /***
+     * 获取客户端ip地址(可以穿透代理)
+     * @param request
+     * @return
+     */
+    public static String getClientIpAddress(HttpServletRequest request) {
+        for (String header : HEADERS_TO_TRY) {
+            String ip = request.getHeader(header);
+            if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
+                return ip;
+            }
+        }
+        return request.getRemoteAddr();
+    }
+}

+ 121 - 0
src/main/java/cn/efunbox/base/util/MD5.java

@@ -0,0 +1,121 @@
+package cn.efunbox.base.util;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.digest.DigestUtils;
+
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SignatureException;
+
+@Slf4j
+public class MD5 {
+	public MD5() {
+	}
+
+	public static final String byte2hexString(byte[] bytes) {
+		StringBuffer buf = new StringBuffer(bytes.length * 2);
+		for (int i = 0; i < bytes.length; i++) {
+			if (((int) bytes[i] & 0xff) < 0x10) {
+				buf.append("0");
+			}
+			buf.append(Long.toString((int) bytes[i] & 0xff, 16));
+		}
+		return buf.toString();
+	}
+
+	/**
+	 * md5加密
+	 * @param sourceString
+	 * @return
+	 */
+	public static String MD5Encode(String sourceString) {
+		String resultString = null;
+		try {
+			resultString = new String(sourceString);
+			MessageDigest md = MessageDigest.getInstance("MD5");
+			resultString = byte2hexString(md.digest(resultString.getBytes()));
+		} catch (Exception ex) {
+		}
+		return resultString;
+	}
+	
+	 public static String getMD5Str(String str) {
+	        MessageDigest messageDigest = null;
+
+	        try {
+	            messageDigest = MessageDigest.getInstance("MD5");
+
+	            messageDigest.reset();
+
+	            messageDigest.update(str.getBytes("UTF-8"));
+	        } catch (NoSuchAlgorithmException e) {
+	            System.out.println("NoSuchAlgorithmException caught!");
+	            System.exit(-1);
+	        } catch (UnsupportedEncodingException e) {
+	            e.printStackTrace();
+	        }
+
+	        byte[] byteArray = messageDigest.digest();
+
+	        StringBuffer md5StrBuff = new StringBuffer();
+
+	        for (int i = 0; i < byteArray.length; i++) {
+	            if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)  {
+	                md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i]));
+	            } else {
+					md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
+				}
+	        }  
+	  
+	        return md5StrBuff.toString();  
+	    }
+
+
+	/**
+	 * 签名字符串
+	 * @param text 需要签名的字符串
+	 * @param sign 签名结果
+	 * @param key 密钥
+	 * @return 签名结果
+	 */
+	public static boolean verify(String text, String sign, String key) {
+		text = text + key;
+		String mysign = DigestUtils.md5Hex(getContentBytes(text, "utf-8"));
+		log.info("text : " + text);
+		log.info("sign : " + mysign);
+		if(mysign.equals(sign)) {
+			return true;
+		}
+		else {
+			return false;
+		}
+	}
+
+	/**
+	 * @param content
+	 * @param charset
+	 * @return
+	 * @throws SignatureException
+	 * @throws UnsupportedEncodingException
+	 */
+	private static byte[] getContentBytes(String content, String charset) {
+		if (charset == null || "".equals(charset)) {
+			return content.getBytes();
+		}
+		try {
+			return content.getBytes(charset);
+		} catch (UnsupportedEncodingException e) {
+			throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
+		}
+	}
+
+
+	public static void main(String[] args) throws UnsupportedEncodingException {
+
+		String md5Str = getMD5Str("ylXny2u:tUagqa8e,#1596164432");
+		System.out.println(md5Str);
+
+	}
+
+}

+ 30 - 0
src/main/java/cn/efunbox/base/util/MoneyUtil.java

@@ -0,0 +1,30 @@
+package cn.efunbox.base.util;
+
+import java.math.BigDecimal;
+import java.text.DecimalFormat;
+
+/**
+ * MoneyUtil
+ * Created by xusq on 2020/1/6.
+ */
+public class MoneyUtil {
+
+    /**
+     * 元转分,确保price保留两位有效数字
+     * @return
+     */
+    public static long changeY2F(double price) {
+        DecimalFormat df = new DecimalFormat("#.00");
+        price = Double.valueOf(df.format(price));
+        long money = (long)price * 100;
+        return money;
+    }
+
+    /**
+     * 分转元,转换为bigDecimal在toString
+     * @return
+     */
+    public static String changeF2Y(long price) {
+        return BigDecimal.valueOf(price).divide(new BigDecimal(100)).toString();
+    }
+}

+ 26 - 0
src/main/java/cn/efunbox/base/util/MyX509TrustManager.java

@@ -0,0 +1,26 @@
+package cn.efunbox.base.util;
+
+import javax.net.ssl.X509TrustManager;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+/**
+ * 证书信任管理器(用于https请求)
+ * 
+ * @author 张超
+ * @date 2013-08-08  
+ */
+public class MyX509TrustManager implements X509TrustManager {
+
+	@Override
+	public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+	}
+	@Override
+	public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+	}
+	@Override
+	public X509Certificate[] getAcceptedIssuers() {
+
+		return null;
+	}
+}

+ 238 - 0
src/main/java/cn/efunbox/base/util/PayCommonUtil.java

@@ -0,0 +1,238 @@
+package cn.efunbox.base.util;
+
+import com.alibaba.fastjson.JSONObject;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import java.io.*;
+import java.net.ConnectException;
+import java.net.URL;
+import java.util.*;
+
+public class PayCommonUtil {
+    public static String CreateNoncestr(int length) {
+        String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+        String res = "";
+        for (int i = 0; i < length; i++) {
+            Random rd = new Random();
+            res += chars.indexOf(rd.nextInt(chars.length() - 1));
+        }
+        return res;
+    }
+
+    public static String CreateNoncestr() {
+        String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+        String res = "";
+        for (int i = 0; i < 16; i++) {
+            Random rd = new Random();
+            res += chars.charAt(rd.nextInt(chars.length() - 1));
+        }
+        return res;
+    }
+
+
+    /** 
+     * 是否签名正确,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。 
+     * @return boolean 
+     */  
+    public static boolean isTenpaySign(SortedMap<Object, Object> packageParams,String signKey) {
+        StringBuffer sb = new StringBuffer();  
+        Set es = packageParams.entrySet();  
+        Iterator it = es.iterator();  
+        while(it.hasNext()) {  
+            Map.Entry entry = (Map.Entry)it.next();  
+            String k = (String)entry.getKey();  
+            String v = (String)entry.getValue();  
+            if(!"sign".equals(k) && null != v && !"".equals(v)) {  
+                sb.append(k + "=" + v + "&");  
+            }  
+        }  
+
+        sb.append("key=" + signKey);
+
+        //算出摘要  
+        String mysign = MD5.MD5Encode(sb.toString()).toLowerCase();
+        String tenpaySign = ((String)packageParams.get("sign")).toLowerCase();  
+
+        //System.out.println(tenpaySign + "    " + mysign);  
+        return tenpaySign.equals(mysign);  
+    }  
+
+
+    /**
+     * @Description:sign签名
+     * @param parameters 请求参数
+     * @return
+     */
+    public static String createSign(SortedMap<String,String> parameters,String signKey){
+        StringBuffer sb = new StringBuffer();
+        Set es = parameters.entrySet();
+        Iterator it = es.iterator();
+        while(it.hasNext()) {
+            Map.Entry<String,String> entry = (Map.Entry)it.next();
+            String k = entry.getKey();
+            String v = entry.getValue();
+            if(null != v && !"".equals(v) 
+                    && !"sign".equals(k) && !"key".equals(k)) {
+                sb.append(k + "=" + v + "&");
+            }
+        }
+        sb.append("key="+signKey);
+        String sign = MD5.MD5Encode(sb.toString()).toUpperCase();
+        return sign;
+    }
+    /**
+     * @Description:将请求参数转换为xml格式的string
+     * @param parameters  请求参数
+     * @return
+     */
+    public static String getRequestXml(SortedMap<String,String> parameters){
+        StringBuffer sb = new StringBuffer();
+        sb.append("<xml>");
+        Set es = parameters.entrySet();
+        Iterator it = es.iterator();
+        while(it.hasNext()) {
+            Map.Entry<String,String> entry = (Map.Entry)it.next();
+            String k = entry.getKey();
+            String v = entry.getValue();
+            if ("attach".equalsIgnoreCase(k)||"body".equalsIgnoreCase(k)) {
+                sb.append("<"+k+">"+"<![CDATA["+v+"]]></"+k+">");
+            }else {
+                sb.append("<"+k+">"+v+"</"+k+">");
+            }
+        }
+        sb.append("</xml>");
+        return sb.toString();
+    }
+    /**
+     * @Description:返回给微信的参数
+     * @param return_code 返回编码
+     * @param return_msg  返回信息
+     * @return
+     */
+    public static String setXML(String return_code, String return_msg) {
+        return "<xml><return_code><![CDATA[" + return_code
+                + "]]></return_code><return_msg><![CDATA[" + return_msg
+                + "]]></return_msg></xml>";
+    }
+
+
+    /**
+     * 发送https请求
+     * @param requestUrl 请求地址
+     * @param requestMethod 请求方式(GET、POST)
+     * @param outputStr 提交的数据
+     * @return 返回微信服务器响应的信息
+     */
+    public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {
+        try {
+            // 创建SSLContext对象,并使用我们指定的信任管理器初始化
+            TrustManager[] tm = { new MyX509TrustManager() };
+            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
+            sslContext.init(null, tm, new java.security.SecureRandom());
+            // 从上述SSLContext对象中得到SSLSocketFactory对象
+            SSLSocketFactory ssf = sslContext.getSocketFactory();
+            URL url = new URL(requestUrl);
+            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
+            //conn.setSSLSocketFactory(ssf);
+            conn.setDoOutput(true);
+            conn.setDoInput(true);
+            conn.setUseCaches(false);
+            // 设置请求方式(GET/POST)
+            conn.setRequestMethod(requestMethod);
+            conn.setRequestProperty("content-type", "application/x-www-form-urlencoded"); 
+            // 当outputStr不为null时向输出流写数据
+            if (null != outputStr) {
+                OutputStream outputStream = conn.getOutputStream();
+                // 注意编码格式
+                outputStream.write(outputStr.getBytes("UTF-8"));
+                outputStream.close();
+            }
+            // 从输入流读取返回内容
+            InputStream inputStream = conn.getInputStream();
+            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
+            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
+            String str = null;
+            StringBuffer buffer = new StringBuffer();
+            while ((str = bufferedReader.readLine()) != null) {
+                buffer.append(str);
+            }
+            // 释放资源
+            bufferedReader.close();
+            inputStreamReader.close();
+            inputStream.close();
+            inputStream = null;
+            conn.disconnect();
+            return buffer.toString();
+        } catch (ConnectException ce) {
+//          log.error("连接超时:{}", ce);
+        } catch (Exception e) {
+//          log.error("https请求异常:{}", e);
+        }
+        return null;
+    }
+
+    /**
+     * 发送https请求
+     * 
+     * @param requestUrl 请求地址
+     * @param requestMethod 请求方式(GET、POST)
+     * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
+     */
+     public static JSONObject httpsRequest(String requestUrl, String requestMethod) {
+            JSONObject jsonObject = null;
+            try {
+                    // 创建SSLContext对象,并使用我们指定的信任管理器初始化
+                    TrustManager[] tm = { new MyX509TrustManager() };
+                    SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
+                    sslContext.init(null, tm, new java.security.SecureRandom());
+                    // 从上述SSLContext对象中得到SSLSocketFactory对象
+                    SSLSocketFactory ssf = sslContext.getSocketFactory();
+                    URL url = new URL(requestUrl);
+                    HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
+                    //conn.setSSLSocketFactory(ssf);
+                    conn.setDoOutput(true);
+                    conn.setDoInput(true);
+                    conn.setUseCaches(false);
+                    conn.setConnectTimeout(3000);
+                    // 设置请求方式(GET/POST)
+                    conn.setRequestMethod(requestMethod);
+                    //conn.setRequestProperty("content-type", "application/x-www-form-urlencoded"); 
+                    // 当outputStr不为null时向输出流写数据
+                    // 从输入流读取返回内容
+                    InputStream inputStream = conn.getInputStream();
+                    InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
+                    BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
+                    String str = null;
+                    StringBuffer buffer = new StringBuffer();
+                    while ((str = bufferedReader.readLine()) != null) {
+                            buffer.append(str);
+                    }
+                    // 释放资源
+                    bufferedReader.close();
+                    inputStreamReader.close();
+                    inputStream.close();
+                    inputStream = null;
+                    conn.disconnect();
+                    jsonObject = JSONObject.parseObject(buffer.toString());
+            } catch (ConnectException ce) {
+//                    log.error("连接超时:{}", ce);
+            } catch (Exception e) {
+                    System.out.println(e);
+//                    log.error("https请求异常:{}", e);
+            }
+            return jsonObject;
+}
+
+    public static String urlEncodeUTF8(String source){
+        String result = source;
+        try {
+            result = java.net.URLEncoder.encode(source,"utf-8");
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return result;
+    }
+}

+ 55 - 0
src/main/java/cn/efunbox/base/util/QRCodeUtil.java

@@ -0,0 +1,55 @@
+package cn.efunbox.base.util;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.EncodeHintType;
+import com.google.zxing.MultiFormatWriter;
+import com.google.zxing.WriterException;
+import com.google.zxing.client.j2se.MatrixToImageWriter;
+import com.google.zxing.common.BitMatrix;
+import lombok.extern.log4j.Log4j;
+import sun.misc.BASE64Encoder;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Hashtable;
+
+@Log4j
+public class QRCodeUtil {
+
+    /**
+     * 根据内容,生成指定宽高、指定格式的二维码图片
+     *
+     * @param url   内容
+     * @return 生成的二维码图片路径
+     * @throws Exception
+     */
+    public static String generateQRCode(String url) {
+        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
+        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
+        hints.put(EncodeHintType.MARGIN, 0);
+        BitMatrix bitMatrix = null;
+        ByteArrayOutputStream os = new ByteArrayOutputStream();
+        String QRCode="";
+        try {
+            bitMatrix = new MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE, 360, 360, hints);
+            BufferedImage image = MatrixToImageWriter.toBufferedImage(bitMatrix);
+            ImageIO.write(image, "png", os);
+            byte b[] = os.toByteArray();
+            QRCode = new BASE64Encoder().encode(b);
+        } catch (WriterException e) {
+            log.error("WriterException:{}",e);
+        } catch (IOException e) {
+            log.error("IOEXCEPITON:{}",e);
+        }finally {
+            try {
+                os.close();
+            } catch (IOException e) {
+                log.error("IOEXCEPITON:{}",e);
+            }
+        }
+        return QRCode;
+    }
+
+}

+ 109 - 0
src/main/java/cn/efunbox/base/util/RSASignature.java

@@ -0,0 +1,109 @@
+package cn.efunbox.base.util;
+
+import org.apache.commons.codec.binary.Base64;
+import org.bouncycastle.util.encoders.UrlBase64;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+
+public class RSASignature {
+	public static final String KEY_ALGORITHM = "RSA";
+	public static final String SIGNATURE_ALGORITHM = "SHA1WithRSA";
+	public static final String ENCODING = "utf-8";
+	public static final String X509 = "X.509";
+
+	/**
+	 * query RSA private key
+	 *
+	 * @param key
+	 * @return
+	 * @throws Exception
+	 */
+	public static PrivateKey getPrivateKey(String key) throws Exception {
+		byte[] keyBytes = Base64.decodeBase64(key.getBytes(ENCODING));
+		PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
+		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
+		PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
+		return privateKey;
+	}
+
+	/**
+	 * query RSA public key
+	 *
+	 * @param key
+	 * @return
+	 * @throws Exception
+	 */
+	public static PublicKey getPublicKey(String key) throws Exception {
+		byte[] keyBytes = Base64.decodeBase64(key.getBytes(ENCODING));
+		CertificateFactory certificateFactory = CertificateFactory.getInstance(X509);
+		InputStream in = new ByteArrayInputStream(keyBytes);
+		Certificate certificate = certificateFactory.generateCertificate(in);
+		PublicKey publicKey = certificate.getPublicKey();
+		return publicKey;
+	}
+
+	/**
+	 * sign by private key
+	 *
+	 * @param content
+	 *            content data which will be signed
+	 * @param privateKey
+	 *            private key data
+	 * @return signed data
+	 */
+	public static String signByPrivateKey(String content, String privateKey) {
+		return signByPrivateKey(content, privateKey, true);
+	}
+
+	public static boolean verifySignByPublicKey(String content, String sign, String publicKey) {		
+		return verifySignByPublicKey(content, sign, publicKey, true);
+	}
+	
+	public static String signByPrivateKey(String content, String privateKey, boolean useUrlBase64) {
+		try {
+			PrivateKey priKey = getPrivateKey(privateKey);
+			Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
+			signature.initSign(priKey);
+			signature.update(content.getBytes(ENCODING));
+			byte[] signed = signature.sign();
+			if (useUrlBase64) {
+				return new String(UrlBase64.encode(signed), ENCODING);
+			} else {
+				return new String(Base64.encodeBase64(signed), ENCODING);
+			}
+		} catch (Exception e) {
+			//ignore exception
+		}
+		return null;
+	}
+
+	public static boolean verifySignByPublicKey(String content, String sign, String publicKey, boolean useUrlBase64) {
+		try {
+			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+			byte[] encodedKey = Base64.decodeBase64(publicKey.getBytes(ENCODING));
+			PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
+
+			Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
+			signature.initVerify(pubKey);
+			signature.update(content.getBytes(ENCODING));
+
+			if (useUrlBase64) {
+				return signature.verify(UrlBase64.decode(sign.getBytes(ENCODING)));
+			} else {
+				return signature.verify(Base64.decodeBase64(sign.getBytes(ENCODING)));
+			}
+		} catch (Exception e) {
+			// ignore exception
+		}
+		return false;
+	}
+}

+ 212 - 0
src/main/java/cn/efunbox/base/util/SmsUtil.java

@@ -0,0 +1,212 @@
+package cn.efunbox.base.util;
+
+import cn.efunbox.base.result.ApiCode;
+import cn.efunbox.base.result.ApiResult;
+import com.alibaba.fastjson.JSON;
+import com.aliyuncs.DefaultAcsClient;
+import com.aliyuncs.IAcsClient;
+import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsRequest;
+import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsResponse;
+import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
+import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
+import com.aliyuncs.exceptions.ClientException;
+import com.aliyuncs.profile.DefaultProfile;
+import com.aliyuncs.profile.IClientProfile;
+import lombok.extern.slf4j.Slf4j;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * Created on 17/6/7.
+ * 短信API产品的DEMO程序,工程中包含了一个SmsDemo类,直接通过
+ * 执行main函数即可体验短信产品API功能(只需要将AK替换成开通了云通信-短信产品功能的AK即可)
+ * 工程依赖了2个jar包(存放在工程的libs目录下)
+ * 1:aliyun-java-sdk-core.jar
+ * 2:aliyun-java-sdk-dysmsapi.jar
+ *
+ * 备注:Demo工程编码采用UTF-8
+ * 国际短信发送请勿参照此DEMO
+ */
+@Slf4j
+public class SmsUtil {
+
+    // TODO 此处需要替换成开发者自己的AK(在阿里云访问控制台寻找)
+    static final String accessKeyId = "LTAIKVC7LxUTi9tO";
+    static final String accessKeySecret = "4mZUJGWfwbBZUkmYjVJJTAF6uNEKgf";
+    
+
+    public static ApiResult sendSms(String phone) {
+
+        //可自助调整超时时间
+        System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
+        System.setProperty("sun.net.client.defaultReadTimeout", "10000");
+
+        //初始化acsClient,暂不支持region化
+        DefaultProfile profile = DefaultProfile.getProfile("cn-beijing", accessKeyId, accessKeySecret);
+        IAcsClient acsClient = new DefaultAcsClient(profile);
+
+        //组装请求对象-具体描述见控制台-文档部分内容
+        SendSmsRequest request = new SendSmsRequest();
+
+        //必填:待发送手机号
+        request.setPhoneNumbers(phone);
+        //必填:短信签名-可在短信控制台中找到
+        request.setSignName("义方快乐学堂");
+        //必填:短信模板-可在短信控制台中找到
+        request.setTemplateCode("SMS_92260012");
+        String code=Code();
+        //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
+        request.setTemplateParam("{\"code\":"+code+"}");
+
+        //选填-上行短信扩展码(无特殊需求用户请忽略此字段)
+        //request.setSmsUpExtendCode("90997");
+
+        //可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
+        request.setOutId("yourOutId");
+
+        //hint 此处可能会抛出异常,注意catch
+        SendSmsResponse sendSmsResponse = null;
+        try {
+            sendSmsResponse = acsClient.getAcsResponse(request);
+        } catch (ClientException e) {
+            e.printStackTrace();
+        }
+        log.info("sendSms response : {}", JSON.toJSONString(sendSmsResponse));
+
+        if ("OK".equalsIgnoreCase(sendSmsResponse.getCode())) {
+            return ApiResult.ok(code);
+        }
+
+        return ApiResult.error(ApiCode.SIGN);
+    }
+
+
+    public static QuerySendDetailsResponse querySendDetails(String bizId, String phone) throws ClientException {
+
+        //可自助调整超时时间
+        System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
+        System.setProperty("sun.net.client.defaultReadTimeout", "10000");
+
+        //初始化acsClient,暂不支持region化
+        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
+        IAcsClient acsClient = new DefaultAcsClient(profile);
+
+        //组装请求对象
+        QuerySendDetailsRequest request = new QuerySendDetailsRequest();
+        //必填-号码
+        request.setPhoneNumber(phone);
+        //可选-流水号
+        request.setBizId(bizId);
+        //必填-发送日期 支持30天内记录查询,格式yyyyMMdd
+        SimpleDateFormat ft = new SimpleDateFormat("yyyyMMdd");
+        request.setSendDate(ft.format(new Date()));
+        //必填-页大小
+        request.setPageSize(10L);
+        //必填-当前页码从1开始计数
+        request.setCurrentPage(1L);
+
+        //hint 此处可能会抛出异常,注意catch
+        QuerySendDetailsResponse querySendDetailsResponse = acsClient.getAcsResponse(request);
+
+        return querySendDetailsResponse;
+    }
+
+    /**
+     * 验证码的生成
+     * @return
+     */
+    public static String Code(){
+        return String.valueOf((int)(Math.random()*9000)+1000);
+    }
+    
+    public static void main(String[] args) throws ClientException, InterruptedException {
+
+        for(int i = 0; i< 1000; i++){
+            System.out.println(Code());
+        }
+
+//    	String phone="18611822573";
+//    	System.out.println(Code());
+//        //发短信
+////        SendSmsResponse response = sendSms(phone);
+//        String response = sendSms(phone);
+
+
+//        System.out.println("短信接口返回的数据----------------");
+//        System.out.println("Code=" + response.getCode());
+//        System.out.println("Message=" + response.getMessage());
+//        System.out.println("RequestId=" + response.getRequestId());
+//        System.out.println("BizId=" + response.getBizId());
+//
+//        Thread.sleep(3000L);
+//       // String phone="";
+//        //查明细
+//        if(response.getCode() != null && response.getCode().equals("OK")) {
+//            QuerySendDetailsResponse querySendDetailsResponse = querySendDetails(response.getBizId(),phone);
+//            System.out.println("短信明细查询接口返回数据----------------");
+//            System.out.println("Code=" + querySendDetailsResponse.getCode());
+//            System.out.println("Message=" + querySendDetailsResponse.getMessage());
+//            int i = 0;
+//            for(QuerySendDetailsResponse.SmsSendDetailDTO smsSendDetailDTO : querySendDetailsResponse.getSmsSendDetailDTOs())
+//            {
+//                System.out.println("SmsSendDetailDTO["+i+"]:");
+//                System.out.println("Content=" + smsSendDetailDTO.getContent());
+//                System.out.println("ErrCode=" + smsSendDetailDTO.getErrCode());
+//                System.out.println("OutId=" + smsSendDetailDTO.getOutId());
+//                System.out.println("PhoneNum=" + smsSendDetailDTO.getPhoneNum());
+//                System.out.println("ReceiveDate=" + smsSendDetailDTO.getReceiveDate());
+//                System.out.println("SendDate=" + smsSendDetailDTO.getSendDate());
+//                System.out.println("SendStatus=" + smsSendDetailDTO.getSendStatus());
+//                System.out.println("Template=" + smsSendDetailDTO.getTemplateCode());
+//            	String regEx="[^0-9]";
+//            	Pattern p = Pattern.compile(regEx);
+//            	Matcher m = p.matcher(smsSendDetailDTO.getContent());
+//            	String sign = m.replaceAll("").trim();
+//            	System.out.println("验证码-===="+sign);
+//            }
+//            System.out.println("TotalCount=" + querySendDetailsResponse.getTotalCount());
+//            System.out.println("RequestId=" + querySendDetailsResponse.getRequestId());
+//        }
+
+    }
+
+    public static void sendRegisterSms(String mobileNo) {
+        //可自助调整超时时间
+        System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
+        System.setProperty("sun.net.client.defaultReadTimeout", "10000");
+
+        //初始化acsClient,暂不支持region化
+        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
+        IAcsClient acsClient = new DefaultAcsClient(profile);
+
+        //组装请求对象-具体描述见控制台-文档部分内容
+        SendSmsRequest request = new SendSmsRequest();
+
+        //必填:待发送手机号
+        request.setPhoneNumbers(mobileNo);
+        //必填:短信签名-可在短信控制台中找到
+        request.setSignName("学有义方");
+        //必填:短信模板-可在短信控制台中找到
+        request.setTemplateCode("SMS_218279684");
+//        String code=Code();
+        //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
+//        request.setTemplateParam("{\"name\":\"Tom\", \"code\":"+code+"}");
+
+        //选填-上行短信扩展码(无特殊需求用户请忽略此字段)
+        //request.setSmsUpExtendCode("90997");
+
+        //可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
+        request.setOutId("yourOutId");
+
+        //hint 此处可能会抛出异常,注意catch
+        SendSmsResponse sendSmsResponse = null;
+        try {
+            sendSmsResponse = acsClient.getAcsResponse(request);
+        } catch (ClientException e) {
+            e.printStackTrace();
+        }
+        log.info("sendSms response : {}", JSON.toJSONString(sendSmsResponse));
+
+    }
+}

+ 198 - 0
src/main/java/cn/efunbox/base/util/SnowflakeIdUtil.java

@@ -0,0 +1,198 @@
+package cn.efunbox.base.util;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Twitter_Snowflake<br>
+ * SnowFlake的结构如下(每部分用-分开):<br>
+ * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 <br>
+ * 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0<br>
+ * 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截)
+ * 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69<br>
+ * 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId<br>
+ * 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号<br>
+ * 加起来刚好64位,为一个Long型。<br>
+ * SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。
+ */
+public class SnowflakeIdUtil {
+
+    private static volatile SnowflakeIdUtil singleton = null;
+    // ==============================Fields===========================================
+    /** 开始时间截 (2015-01-01) */
+    private final long twepoch = 1420041600000L;
+
+    /** 机器id所占的位数 */
+    private final long workerIdBits = 5L;
+
+    /** 数据标识id所占的位数 */
+    private final long datacenterIdBits = 5L;
+
+    /** 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */
+    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
+
+    /** 支持的最大数据标识id,结果是31 */
+    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
+
+    /** 序列在id中占的位数 */
+    private final long sequenceBits = 12L;
+
+    /** 机器ID向左移12位 */
+    private final long workerIdShift = sequenceBits;
+
+    /** 数据标识id向左移17位(12+5) */
+    private final long datacenterIdShift = sequenceBits + workerIdBits;
+
+    /** 时间截向左移22位(5+5+12) */
+    private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
+
+    /** 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) */
+    private final long sequenceMask = -1L ^ (-1L << sequenceBits);
+
+    /** 工作机器ID(0~31) */
+    private long workerId=1L;
+
+    /** 数据中心ID(0~31) */
+    private long datacenterId=1L;
+
+    /** 毫秒内序列(0~4095) */
+    private long sequence = 0L;
+
+    /** 上次生成ID的时间截 */
+    private long lastTimestamp = -1L;
+
+
+
+    //==============================Constructors=====================================
+    private SnowflakeIdUtil(){}
+    /**
+     * 构造函数
+     */
+    public static SnowflakeIdUtil getSnowflakeIdUtil(){
+        if(singleton == null){
+            synchronized (SnowflakeIdUtil.class){
+                if(singleton == null){
+                    singleton = new SnowflakeIdUtil(0,0);
+                }
+            }
+        }
+        return singleton;
+    }
+    public static SnowflakeIdUtil getSnowflakeIdUtil(long workerId, long datacenterId){
+        if(singleton == null){
+            synchronized (SnowflakeIdUtil.class){
+                if(singleton == null){
+                    singleton = new SnowflakeIdUtil(workerId,datacenterId);
+                }
+            }
+        }
+        return singleton;
+    }
+    /**
+     * 构造函数
+     * @param workerId 工作ID (0~31)
+     * @param datacenterId 数据中心ID (0~31)
+     */
+    public SnowflakeIdUtil(long workerId, long datacenterId) {
+        if (workerId > maxWorkerId || workerId < 0) {
+            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
+        }
+        if (datacenterId > maxDatacenterId || datacenterId < 0) {
+            throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
+        }
+        this.workerId = workerId;
+        this.datacenterId = datacenterId;
+    }
+
+    // ==============================Methods==========================================
+    /**
+     * 获得下一个ID (该方法是线程安全的)
+     * @return SnowflakeId
+     */
+    public synchronized long nextId() {
+        long timestamp = timeGen();
+
+        //如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
+        if (timestamp < lastTimestamp) {
+            throw new RuntimeException(
+                    String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
+        }
+
+        //如果是同一时间生成的,则进行毫秒内序列
+        if (lastTimestamp == timestamp) {
+            sequence = (sequence + 1) & sequenceMask;
+            //毫秒内序列溢出
+            if (sequence == 0) {
+                //阻塞到下一个毫秒,获得新的时间戳
+                timestamp = tilNextMillis(lastTimestamp);
+            }
+        }
+        //时间戳改变,毫秒内序列重置
+        else {
+            sequence = 0L;
+        }
+        //上次生成ID的时间截
+        lastTimestamp = timestamp;
+
+       /* //移位并通过或运算拼到一起组成64位的ID
+        return ((timestamp - twepoch) << timestampLeftShift) //
+                | (datacenterId << datacenterIdShift) //
+                | (workerId << workerIdShift) //
+                | sequence;*/
+
+        // modify by tomas 2017-08-28
+        try {
+            Thread.sleep(1);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        return  Long.parseLong(timestamp+ getNewAppend() );
+    }
+
+    protected String getNewAppend() {
+        StringBuilder stringBuilder=new StringBuilder((System.nanoTime() + "").substring(7, 10));
+        return  stringBuilder.toString();
+
+    }
+    /**
+     * 阻塞到下一个毫秒,直到获得新的时间戳
+     * @param lastTimestamp 上次生成ID的时间截
+     * @return 当前时间戳
+     */
+    protected long tilNextMillis(long lastTimestamp) {
+        long timestamp = timeGen();
+        while (timestamp <= lastTimestamp) {
+            timestamp = timeGen();
+        }
+        return timestamp;
+    }
+
+    /**
+     * 返回字符串类型 code
+     * @return
+     */
+    public String nextCode() {
+        return  String.valueOf(nextId());
+    }
+    /**
+     * 返回以毫秒为单位的当前时间
+     * @return 当前时间(毫秒)
+     */
+    protected long timeGen() {
+        return System.currentTimeMillis();
+    }
+
+
+    public static void main(String[] args) throws Exception{
+
+        Set<Long> ids= new HashSet<>();
+        long start=System.currentTimeMillis();
+        for (int j=0 ;j<1000;j++){
+            long id = SnowflakeIdUtil.getSnowflakeIdUtil().nextId();
+            ids.add(id);
+            //System.out.println(id);
+        }
+        System.out.println(ids.size()+"---time="+ (System.currentTimeMillis()-start));
+
+    }
+}

+ 72 - 0
src/main/java/cn/efunbox/base/util/WxApiUtil.java

@@ -0,0 +1,72 @@
+package cn.efunbox.base.util;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+
+@Slf4j
+public class WxApiUtil {
+
+	private static String appId = "wxf05800eea975a68b";
+	private static String appSecret = "f0b98db85fab75286aba3971270985db";
+	private static String accessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={APPID}&secret={SECRET}&code={CODE}&grant_type=authorization_code";
+	private static String userInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token={ACCESS_TOKEN}&openid={OPENID}&lang=zh_CN";
+
+	/**
+	 * 请求微信时的错误标志字段
+	 */
+	public static final String WEIXIN_ERROR_CODE_FIELD = "errcode";
+
+	/**
+	 * 请求微信时,成功标志字段
+	 */
+	public static final int WEIXIN_SUCCESS_CODE = 0;
+
+	public static boolean isWeixinRequestSuccess(JSONObject jsonObj) {
+		if (jsonObj == null || (jsonObj.containsKey(WEIXIN_ERROR_CODE_FIELD)
+				&& jsonObj.getIntValue(WEIXIN_ERROR_CODE_FIELD) != WEIXIN_SUCCESS_CODE)) {
+			return false;
+		}
+		return true;
+	}
+
+
+	public static JSONObject getWXAccessInfo(String code) {
+		String requestUrl = accessTokenUrl.replace("{APPID}", appId).replace("{SECRET}", appSecret).replace("{CODE}", code);
+		log.info("find wx access token requestUrl=="+requestUrl);
+		String resp = HttpUtils.doRequest(requestUrl, "GET");
+		JSONObject jsonObject = JSONObject.parseObject(resp);
+		log.info("find wx access token resp:"+jsonObject.toString());
+		if (WxApiUtil.isWeixinRequestSuccess(jsonObject)) {
+			return jsonObject;
+		}
+		return null;
+	}
+
+	public static JSONObject getWxUserInfo(JSONObject accessObject) {
+
+
+		String openid = accessObject.getString("openid");
+		String access_token = accessObject.getString("access_token");
+		if (StringUtils.isEmpty(openid) || StringUtils.isEmpty(access_token)) {
+			return null;
+		}
+		JSONObject jsonObject = requestWxUserInfo(openid, access_token);
+		log.info("requestWxUserInfo: {}", JSON.toJSONString(jsonObject));
+		if (!WxApiUtil.isWeixinRequestSuccess(jsonObject)) {
+			return null;
+		}
+		return jsonObject;
+
+	}
+
+
+	public static JSONObject requestWxUserInfo(String openid, String accessToken) {
+		String requestUrl = userInfoUrl.replace("{ACCESS_TOKEN}", accessToken).replace("{OPENID}", openid);
+		String resp = HttpUtils.doRequest(requestUrl, "GET");
+		JSONObject jsonObject = JSONObject.parseObject(resp);
+		return jsonObject;
+	}
+	
+}

+ 87 - 0
src/main/java/cn/efunbox/base/util/XMLUtil.java

@@ -0,0 +1,87 @@
+package cn.efunbox.base.util;
+
+
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jdom.input.SAXBuilder;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+
+public class XMLUtil {
+    /**
+     * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。
+     * @param strxml
+     * @return
+     * @throws JDOMException
+     * @throws IOException
+     */
+    public static Map doXMLParse(String strxml) throws JDOMException, IOException {
+        strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");
+
+        if(null == strxml || "".equals(strxml)) {
+            return null;
+        }
+
+        Map m = new HashMap();
+
+        InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
+        SAXBuilder builder = new SAXBuilder();
+        Document doc = builder.build(in);
+        Element root = doc.getRootElement();
+        List list = root.getChildren();
+        Iterator it = list.iterator();
+        while(it.hasNext()) {
+            Element e = (Element) it.next();
+            String k = e.getName();
+            String v = "";
+            List children = e.getChildren();
+            if(children.isEmpty()) {
+                v = e.getTextNormalize();
+            } else {
+                v = getChildrenText(children);
+            }
+
+            m.put(k, v);
+        }
+
+        //关闭流
+        in.close();
+
+        return m;
+    }
+
+    /**
+     * 获取子结点的xml
+     * @param children
+     * @return String
+     */
+    public static String getChildrenText(List children) {
+        StringBuffer sb = new StringBuffer();
+        if(!children.isEmpty()) {
+            Iterator it = children.iterator();
+            while(it.hasNext()) {
+                Element e = (Element) it.next();
+                String name = e.getName();
+                String value = e.getTextNormalize();
+                List list = e.getChildren();
+                sb.append("<" + name + ">");
+                if(!list.isEmpty()) {
+                    sb.append(getChildrenText(list));
+                }
+                sb.append(value);
+                sb.append("</" + name + ">");
+            }
+        }
+
+        return sb.toString();
+    }
+
+}

+ 59 - 0
src/main/resources/application-dev.properties

@@ -0,0 +1,59 @@
+
+########################################################
+### Spring Cloud \u57FA\u672C\u914D\u7F6E\uFF1B
+########################################################
+spring.application.name=springboot-base
+
+
+########################################################
+### MYSQL\u57FA\u672C\u914D\u7F6E\uFF1B
+########################################################
+#dev
+#spring.datasource.url=jdbc:mysql://127.0.0.1:3306/xyyf?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&allowMultiQueries=true
+#spring.datasource.username=root
+#spring.datasource.password=123456
+spring.datasource.url=jdbc:mysql://rm-2ze7x5d259k389c208o.mysql.rds.aliyuncs.com/springboot_base?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&allowMultiQueries=true
+spring.datasource.username=efunbox
+spring.datasource.password=wo3^C@6ImAhr
+#spring.datasource.password=ENC(biCFTGXqdNiYt2I+Le0109paSm/+QIzL)
+spring.datasource.driver-class-name=com.mysql.jdbc.Driver
+
+spring.jpa.properties.hibernate.hbm2ddl.auto=update
+spring.jpa.properties.hibernate.format_sql=true
+spring.jpa.show-sql=true
+
+
+########################################################
+### REDIS (RedisProperties) redis\u57FA\u672C\u914D\u7F6E\uFF1B
+########################################################
+# prd Redis\u6570\u636E\u5E93\u7D22\u5F15\uFF08\u9ED8\u8BA4\u4E3A0\uFF09
+spring.redis.database=5
+# Redis\u670D\u52A1\u5668\u5730\u5740
+spring.redis.host=r-2zejxpj3s868rovvexpd.redis.rds.aliyuncs.com
+# Redis\u670D\u52A1\u5668\u8FDE\u63A5\u7AEF\u53E3
+spring.redis.port=6379
+# Redis\u670D\u52A1\u5668\u8FDE\u63A5\u5BC6\u7801\uFF08\u9ED8\u8BA4\u4E3A\u7A7A\uFF09
+spring.redis.password=6N*bfHVlR!FEejZV
+
+# \u8FDE\u63A5\u6C60\u6700\u5927\u8FDE\u63A5\u6570\uFF08\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236\uFF09
+spring.redis.jedis.pool.max-active=8
+# \u8FDE\u63A5\u6C60\u6700\u5927\u963B\u585E\u7B49\u5F85\u65F6\u95F4\uFF08\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236\uFF09
+spring.redis.jedis.pool.max-wait=-1
+# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5927\u7A7A\u95F2\u8FDE\u63A5
+spring.redis.jedis.pool.max-idle=8
+# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5
+spring.redis.jedis.pool.min-idle=0
+# \u8FDE\u63A5\u8D85\u65F6\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09
+spring.redis.timeout=1000
+
+# \u6267\u884C\u5F02\u6B65\u4EFB\u52A1\u7684 \u7EBF\u7A0B\u6C60\u5927\u5C0F
+schedule.threadPoolAsyncTaskExecutor.thread.size= 16
+
+
+
+
+
+management.endpoint.health.show-details=always
+management.endpoint.prometheus.enabled=true
+management.endpoints.web.exposure.include=*
+management.metrics.tags.application=${spring.application.name}

+ 51 - 0
src/main/resources/application-prod.properties

@@ -0,0 +1,51 @@
+
+########################################################
+### Spring Cloud \u57FA\u672C\u914D\u7F6E\uFF1B
+########################################################
+spring.application.name=springboot-base
+
+
+########################################################
+### MYSQL\u57FA\u672C\u914D\u7F6E\uFF1B
+########################################################
+#prd
+spring.datasource.url=jdbc:mysql://rm-2ze9d5b4gpb12aty1490.mysql.rds.aliyuncs.com:3306/efunbox_ott90_plus?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&allowMultiQueries=true
+spring.datasource.username=efundata
+spring.datasource.password=Efunbox@201704$
+spring.datasource.driver-class-name=com.mysql.jdbc.Driver
+spring.jpa.properties.hibernate.hbm2ddl.auto=update
+spring.jpa.properties.hibernate.format_sql=true
+spring.jpa.show-sql=false
+
+########################################################
+### REDIS (RedisProperties) redis\u57FA\u672C\u914D\u7F6E\uFF1B
+########################################################
+# prd Redis\u6570\u636E\u5E93\u7D22\u5F15\uFF08\u9ED8\u8BA4\u4E3A0\uFF09
+spring.redis.database=5
+# Redis\u670D\u52A1\u5668\u5730\u5740
+spring.redis.host=r-2zejxpj3s868rovvex.redis.rds.aliyuncs.com
+# Redis\u670D\u52A1\u5668\u8FDE\u63A5\u7AEF\u53E3
+spring.redis.port=6379
+# Redis\u670D\u52A1\u5668\u8FDE\u63A5\u5BC6\u7801\uFF08\u9ED8\u8BA4\u4E3A\u7A7A\uFF09
+spring.redis.password=6N*bfHVlR!FEejZV
+
+# \u8FDE\u63A5\u6C60\u6700\u5927\u8FDE\u63A5\u6570\uFF08\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236\uFF09
+spring.redis.jedis.pool.max-active=8
+# \u8FDE\u63A5\u6C60\u6700\u5927\u963B\u585E\u7B49\u5F85\u65F6\u95F4\uFF08\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236\uFF09
+spring.redis.jedis.pool.max-wait=-1
+# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5927\u7A7A\u95F2\u8FDE\u63A5
+spring.redis.jedis.pool.max-idle=8
+# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5
+spring.redis.jedis.pool.min-idle=0
+# \u8FDE\u63A5\u8D85\u65F6\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09
+spring.redis.timeout=1000
+
+# \u6267\u884C\u5F02\u6B65\u4EFB\u52A1\u7684 \u7EBF\u7A0B\u6C60\u5927\u5C0F
+schedule.threadPoolAsyncTaskExecutor.thread.size= 16
+
+
+
+management.endpoint.health.show-details=always
+management.endpoint.prometheus.enabled=true
+management.endpoints.web.exposure.include=*
+management.metrics.tags.application=${spring.application.name}

+ 51 - 0
src/main/resources/application-uat.properties

@@ -0,0 +1,51 @@
+
+########################################################
+### Spring Cloud \u57FA\u672C\u914D\u7F6E\uFF1B
+########################################################
+spring.application.name=springboot-base
+
+
+########################################################
+### MYSQL\u57FA\u672C\u914D\u7F6E\uFF1B
+########################################################
+#prd
+spring.datasource.url=jdbc:mysql://rm-2ze7x5d259k389c20.mysql.rds.aliyuncs.com:3306/efunbox_90_plus?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&allowMultiQueries=true
+spring.datasource.username=efunbox
+spring.datasource.password=wo3^C@6ImAhr
+spring.datasource.driver-class-name=com.mysql.jdbc.Driver
+spring.jpa.properties.hibernate.hbm2ddl.auto=update
+spring.jpa.properties.hibernate.format_sql=true
+spring.jpa.show-sql=true
+
+########################################################
+### REDIS (RedisProperties) redis\u57FA\u672C\u914D\u7F6E\uFF1B
+########################################################
+# prd Redis\u6570\u636E\u5E93\u7D22\u5F15\uFF08\u9ED8\u8BA4\u4E3A0\uFF09
+spring.redis.database=0
+# Redis\u670D\u52A1\u5668\u5730\u5740
+spring.redis.host=r-2zejxpj3s868rovvex.redis.rds.aliyuncs.com
+# Redis\u670D\u52A1\u5668\u8FDE\u63A5\u7AEF\u53E3
+spring.redis.port=6379
+# Redis\u670D\u52A1\u5668\u8FDE\u63A5\u5BC6\u7801\uFF08\u9ED8\u8BA4\u4E3A\u7A7A\uFF09
+spring.redis.password=6N*bfHVlR!FEejZV
+
+# \u8FDE\u63A5\u6C60\u6700\u5927\u8FDE\u63A5\u6570\uFF08\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236\uFF09
+spring.redis.jedis.pool.max-active=8
+# \u8FDE\u63A5\u6C60\u6700\u5927\u963B\u585E\u7B49\u5F85\u65F6\u95F4\uFF08\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236\uFF09
+spring.redis.jedis.pool.max-wait=-1
+# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5927\u7A7A\u95F2\u8FDE\u63A5
+spring.redis.jedis.pool.max-idle=8
+# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5
+spring.redis.jedis.pool.min-idle=0
+# \u8FDE\u63A5\u8D85\u65F6\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09
+spring.redis.timeout=1000
+
+# \u6267\u884C\u5F02\u6B65\u4EFB\u52A1\u7684 \u7EBF\u7A0B\u6C60\u5927\u5C0F
+schedule.threadPoolAsyncTaskExecutor.thread.size= 16
+
+
+
+management.endpoint.health.show-details=always
+management.endpoint.prometheus.enabled=true
+management.endpoints.web.exposure.include=*
+management.metrics.tags.application=${spring.application.name}

+ 10 - 0
src/main/resources/application.properties

@@ -0,0 +1,10 @@
+# 监听端口
+server.port=8032
+# 默认激活哪一个环境的配置文件,时也可以在运行动态指定:java -jar myapp.jar --spring.profiles.active=prd
+spring.profiles.active=dev
+
+#配置请求文件大小
+#设置单个文件的大小
+spring.servlet.multipart.max-file-size = 10MB
+#设置单次请求的文件的总大小
+spring.servlet.multipart.max-request-size=100MB

+ 29 - 0
src/main/resources/logback-spring.xml

@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<configuration>
+    <springProperty scope="context" name="applicationname" source="spring.application.name"/>
+    <!-- 声明变量 -->
+    <substitutionProperty name="log.base" value="${LOG_PATH:-/opt/logs/${applicationname}}/${LOG_FILE:-${applicationname}}"/>
+
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <layout class="ch.qos.logback.classic.PatternLayout">
+            <pattern>%-4d [%green(%thread)] %highlight(%-5level)  %cyan(%-40.40logger{39}:%L) - %m%n</pattern>
+        </layout>
+    </appender>
+
+    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>${log.base}.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <maxHistory>30</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>[%d{yy-MM-dd HH:mm:ss.SSS}] [%cn] [%thread] %-5level %-40.40logger{39} - %msg%n</pattern>
+            <charset>utf-8</charset>
+        </encoder>
+    </appender>
+
+    <root level="INFO">
+        <appender-ref ref="STDOUT"/>
+        <appender-ref ref="FILE"/>
+    </root>
+    <jmxConfigurator/>
+</configuration>