Jelajahi Sumber

first commit

jtoms 4 tahun lalu
melakukan
d57d51bbb5
81 mengubah file dengan 4506 tambahan dan 0 penghapusan
  1. 6 0
      .gitignore
  2. 93 0
      pom.xml
  3. 50 0
      src/main/java/com/zhiqiyun/open/Application.java
  4. 39 0
      src/main/java/com/zhiqiyun/open/apis/UserApi.java
  5. 46 0
      src/main/java/com/zhiqiyun/open/apis/request/LogonRequest.java
  6. 16 0
      src/main/java/com/zhiqiyun/open/controller/IndexController.java
  7. 35 0
      src/main/java/com/zhiqiyun/open/enmus/AccountType.java
  8. 39 0
      src/main/java/com/zhiqiyun/open/enmus/Gender.java
  9. 8 0
      src/main/java/com/zhiqiyun/open/enmus/IEnum.java
  10. 39 0
      src/main/java/com/zhiqiyun/open/enmus/PasswordType.java
  11. 43 0
      src/main/java/com/zhiqiyun/open/enmus/UserLoginLogState.java
  12. 39 0
      src/main/java/com/zhiqiyun/open/enmus/UserState.java
  13. 56 0
      src/main/java/com/zhiqiyun/open/enmus/YN.java
  14. 21 0
      src/main/java/com/zhiqiyun/open/exception/NoFoundException.java
  15. 26 0
      src/main/java/com/zhiqiyun/open/exception/NoLoginException.java
  16. 28 0
      src/main/java/com/zhiqiyun/open/exception/NotSufficientFundsException.java
  17. 20 0
      src/main/java/com/zhiqiyun/open/exception/PermissionDeniedException.java
  18. 42 0
      src/main/java/com/zhiqiyun/open/exception/ServiceException.java
  19. 13 0
      src/main/java/com/zhiqiyun/open/exception/UploadException.java
  20. 22 0
      src/main/java/com/zhiqiyun/open/mapper/AuthorityInfoMapper.java
  21. 68 0
      src/main/java/com/zhiqiyun/open/mapper/RoleInfoMapper.java
  22. 12 0
      src/main/java/com/zhiqiyun/open/mapper/SequenceMapper.java
  23. 119 0
      src/main/java/com/zhiqiyun/open/mapper/UserBaseInfoMapper.java
  24. 47 0
      src/main/java/com/zhiqiyun/open/mapper/UserLoginAccountMapper.java
  25. 29 0
      src/main/java/com/zhiqiyun/open/mapper/UserPasswordMapper.java
  26. 25 0
      src/main/java/com/zhiqiyun/open/models/AuthorityInfo.java
  27. 87 0
      src/main/java/com/zhiqiyun/open/models/OauthInfo.java
  28. 23 0
      src/main/java/com/zhiqiyun/open/models/RoleInfo.java
  29. 15 0
      src/main/java/com/zhiqiyun/open/models/Sequence.java
  30. 24 0
      src/main/java/com/zhiqiyun/open/models/UserBaseInfo.java
  31. 47 0
      src/main/java/com/zhiqiyun/open/models/UserLoginAccount.java
  32. 26 0
      src/main/java/com/zhiqiyun/open/models/UserLoginLog.java
  33. 24 0
      src/main/java/com/zhiqiyun/open/models/UserOperateLog.java
  34. 41 0
      src/main/java/com/zhiqiyun/open/models/UserPassword.java
  35. 203 0
      src/main/java/com/zhiqiyun/open/mybatis/paginator/PaginationInterceptor.java
  36. 66 0
      src/main/java/com/zhiqiyun/open/mybatis/paginator/dialect/DB2Dialect.java
  37. 145 0
      src/main/java/com/zhiqiyun/open/mybatis/paginator/dialect/Dialect.java
  38. 28 0
      src/main/java/com/zhiqiyun/open/mybatis/paginator/dialect/H2Dialect.java
  39. 27 0
      src/main/java/com/zhiqiyun/open/mybatis/paginator/dialect/HSQLDialect.java
  40. 30 0
      src/main/java/com/zhiqiyun/open/mybatis/paginator/dialect/MySQLDialect.java
  41. 50 0
      src/main/java/com/zhiqiyun/open/mybatis/paginator/dialect/OracleDialect.java
  42. 30 0
      src/main/java/com/zhiqiyun/open/mybatis/paginator/dialect/PostgreSQLDialect.java
  43. 83 0
      src/main/java/com/zhiqiyun/open/mybatis/paginator/dialect/SQLServer2005Dialect.java
  44. 43 0
      src/main/java/com/zhiqiyun/open/mybatis/paginator/dialect/SQLServerDialect.java
  45. 18 0
      src/main/java/com/zhiqiyun/open/mybatis/paginator/dialect/SybaseDialect.java
  46. 139 0
      src/main/java/com/zhiqiyun/open/mybatis/paginator/domain/Order.java
  47. 99 0
      src/main/java/com/zhiqiyun/open/mybatis/paginator/domain/PageBounds.java
  48. 45 0
      src/main/java/com/zhiqiyun/open/mybatis/paginator/domain/PageResult.java
  49. 94 0
      src/main/java/com/zhiqiyun/open/mybatis/paginator/support/DefaultParameterHandler.java
  50. 408 0
      src/main/java/com/zhiqiyun/open/mybatis/paginator/support/PropertiesHelper.java
  51. 69 0
      src/main/java/com/zhiqiyun/open/mybatis/paginator/support/SQLHelp.java
  52. 46 0
      src/main/java/com/zhiqiyun/open/mybatis/typeHandler/FastjsonTypeHandler.java
  53. 75 0
      src/main/java/com/zhiqiyun/open/mybatis/typeHandler/IEnumTypeHandler.java
  54. 20 0
      src/main/java/com/zhiqiyun/open/service/AuthorityInfoService.java
  55. 11 0
      src/main/java/com/zhiqiyun/open/service/Ip2RegionService.java
  56. 42 0
      src/main/java/com/zhiqiyun/open/service/OauthService.java
  57. 58 0
      src/main/java/com/zhiqiyun/open/service/RoleInfoService.java
  58. 10 0
      src/main/java/com/zhiqiyun/open/service/SequenceService.java
  59. 166 0
      src/main/java/com/zhiqiyun/open/service/UserBaseInfoService.java
  60. 55 0
      src/main/java/com/zhiqiyun/open/service/impl/BaseOauthService.java
  61. 30 0
      src/main/java/com/zhiqiyun/open/service/impl/Ip2RegionServiceImpl.java
  62. 24 0
      src/main/java/com/zhiqiyun/open/service/impl/OauthAuthorityInfoServiceImpl.java
  63. 71 0
      src/main/java/com/zhiqiyun/open/service/impl/OauthRoleInfoServiceImpl.java
  64. 61 0
      src/main/java/com/zhiqiyun/open/service/impl/OauthServiceRedisImpl.java
  65. 33 0
      src/main/java/com/zhiqiyun/open/service/impl/SequenceServiceImpl.java
  66. 191 0
      src/main/java/com/zhiqiyun/open/service/impl/UserBaseInfoServiceImpl.java
  67. 23 0
      src/main/java/com/zhiqiyun/open/utils/DateUtil.java
  68. 105 0
      src/main/java/com/zhiqiyun/open/utils/PatternUtils.java
  69. 91 0
      src/main/java/com/zhiqiyun/open/utils/RandomUtil.java
  70. 14 0
      src/main/resources/META-INF/spring-configuration-metadata.json
  71. 38 0
      src/main/resources/application.properties
  72. TEMPAT SAMPAH
      src/main/resources/ip2region.db
  73. 117 0
      src/main/resources/logback-spring.xml
  74. 24 0
      src/main/resources/mybatis/mappers/AuthorityInfoMapper.xml
  75. 78 0
      src/main/resources/mybatis/mappers/RoleInfoMapper.xml
  76. 9 0
      src/main/resources/mybatis/mappers/SequenceMapper.xml
  77. 175 0
      src/main/resources/mybatis/mappers/UserBaseInfoMapper.xml
  78. 46 0
      src/main/resources/mybatis/mappers/UserLoginAccountMapper.xml
  79. 37 0
      src/main/resources/mybatis/mappers/UserPasswordMapper.xml
  80. 10 0
      src/main/resources/mybatis/sqlMapConfig.xml
  81. 1 0
      src/main/resources/oap.appSecret.properties

+ 6 - 0
.gitignore

@@ -0,0 +1,6 @@
+*.iml
+.idea
+.DS_Store
+core/target
+sample/target
+target/

+ 93 - 0
pom.xml

@@ -0,0 +1,93 @@
+<?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>com.zhiqiyun</groupId>
+    <artifactId>open-platform</artifactId>
+    <version>1.0-SNAPSHOT</version>
+
+    <properties>
+        <maven.compiler.source>1.8</maven.compiler.source>
+        <maven.compiler.target>1.8</maven.compiler.target>
+        <file.encoding>UTF-8</file.encoding>
+        <junit.version>4.13.2</junit.version>
+
+        <commons-lang3.version>3.12.0</commons-lang3.version>
+        <commons-codec.version>1.15</commons-codec.version>
+        <ip2region.version>1.7.2</ip2region.version>
+
+        <spring.version>5.3.14</spring.version>
+        <spring-boot.version>2.6.2</spring-boot.version>
+
+        <mariadb-java-client.version>2.7.3</mariadb-java-client.version>
+        <mybatis-spring-boot-starter.version>2.2.0</mybatis-spring-boot-starter.version>
+        <mybatis.version>3.5.7</mybatis.version>
+
+<!--        <fastjson.version>1.2.79</fastjson.version>-->
+<!--        <slf4j.version>1.7.32</slf4j.version>-->
+<!--        <commons-lang3.version>3.12.0</commons-lang3.version>-->
+<!--        <lombok.version>1.18.22</lombok.version>-->
+<!--        <javax.servlet.version>4.0.1</javax.servlet.version>-->
+<!--        <hibernate-validator.version>6.0.22.Final</hibernate-validator.version>-->
+<!--        <okhttp.version>4.9.3</okhttp.version>-->
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.dliyun</groupId>
+            <artifactId>framework-sprint-boot</artifactId>
+            <version>1.0.6</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <version>${spring-boot.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <version>${spring-boot.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+            <version>${spring-boot.version}</version>
+        </dependency>
+        <!--Mysql相关包-->
+        <dependency>
+            <groupId>org.mariadb.jdbc</groupId>
+            <artifactId>mariadb-java-client</artifactId>
+            <version>${mariadb-java-client.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-jdbc</artifactId>
+            <version>${spring-boot.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.mybatis.spring.boot</groupId>
+            <artifactId>mybatis-spring-boot-starter</artifactId>
+            <version>${mybatis-spring-boot-starter.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>${commons-lang3.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+            <version>${commons-codec.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.lionsoul</groupId>
+            <artifactId>ip2region</artifactId>
+            <version>${ip2region.version}</version>
+        </dependency>
+    </dependencies>
+</project>

+ 50 - 0
src/main/java/com/zhiqiyun/open/Application.java

@@ -0,0 +1,50 @@
+package com.zhiqiyun.open;
+
+import lombok.extern.slf4j.Slf4j;
+import org.lionsoul.ip2region.DbConfig;
+import org.lionsoul.ip2region.DbSearcher;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.web.servlet.ServletComponentScan;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+
+/**
+ * @author stjdydayou
+ */
+@Slf4j
+@Configuration
+@ServletComponentScan
+@SpringBootApplication
+public class Application {
+
+    public static void main(String[] args) {
+        SpringApplication app = new SpringApplication(Application.class);
+        app.run(args);
+    }
+
+
+    @Bean
+    public DbSearcher dbSearcher() throws Exception {
+
+        DbConfig config = new DbConfig();
+
+        InputStream inStream = Application.class.getResourceAsStream("/ip2region.db");
+
+        byte[] buff = new byte[1024];
+
+        ByteArrayOutputStream o = new ByteArrayOutputStream();
+
+        int rc = 0;
+        while ((rc = inStream.read(buff, 0, 1024)) > 0) {
+            o.write(buff, 0, rc);
+        }
+
+        byte[] in2b = o.toByteArray();
+
+        return new DbSearcher(config, in2b);
+    }
+}

+ 39 - 0
src/main/java/com/zhiqiyun/open/apis/UserApi.java

@@ -0,0 +1,39 @@
+package com.zhiqiyun.open.apis;
+
+import com.dliyun.oap.framework.annotation.ServiceMethod;
+import com.dliyun.oap.framework.annotation.ServiceMethodBean;
+import com.dliyun.oap.framework.response.OapResponse;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.zhiqiyun.open.apis.request.LogonRequest;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * <pre>
+ * 功能说明:
+ * </pre>
+ *
+ * @author stjdydayou
+ * @version 1.0
+ */
+@Slf4j
+@ServiceMethodBean
+public class UserApi {
+
+    @Autowired
+    private ObjectMapper objectMapper;
+
+    @ServiceMethod(method = "user.login", title = "用户登录", groupTitle = "")
+    public OapResponse login(LogonRequest request) {
+
+        Map<String, Object> m = new HashMap<>();
+        m.put("userName", request.getUserName());
+        m.put("password", request.getPassword());
+        m.put("ss", request.getSs());
+
+        return OapResponse.success().setBody(m);
+    }
+}

+ 46 - 0
src/main/java/com/zhiqiyun/open/apis/request/LogonRequest.java

@@ -0,0 +1,46 @@
+/**
+ * 版权声明:中图一购网络科技有限公司 版权所有 违者必究 2012
+ * 日    期:12-7-14
+ */
+package com.zhiqiyun.open.apis.request;
+
+import com.dliyun.oap.framework.annotation.ServiceParamField;
+import com.dliyun.oap.framework.request.AbstractOapRequest;
+import com.dliyun.oap.framework.request.UploadFile;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import java.util.List;
+
+
+/**
+ * <pre>
+ * 功能说明:
+ * </pre>
+ *
+ * @author 陈雄华
+ * @version 1.0
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class LogonRequest extends AbstractOapRequest {
+
+	@ServiceParamField(describe = "用户名")
+	@NotNull
+	@Pattern(regexp = "\\w{4,30}")
+	private String userName;
+
+	@ServiceParamField(describe = "密码")
+	@NotBlank
+	@Pattern(regexp = "\\w{6,30}")
+	private String password;
+
+	private List<String> ss;
+
+	@ServiceParamField(describe = "上传文件")
+	private UploadFile file;
+}
+

+ 16 - 0
src/main/java/com/zhiqiyun/open/controller/IndexController.java

@@ -0,0 +1,16 @@
+package com.zhiqiyun.open.controller;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+@Slf4j
+@RestController
+public class IndexController {
+
+    @RequestMapping(method = {RequestMethod.POST, RequestMethod.GET}, value = {"/", "/index", "/index.do"})
+    public String index() {
+        return "OK";
+    }
+}

+ 35 - 0
src/main/java/com/zhiqiyun/open/enmus/AccountType.java

@@ -0,0 +1,35 @@
+package com.zhiqiyun.open.enmus;
+
+
+public enum AccountType implements IEnum<Integer> {
+    /**
+     *
+     */
+    userName(0, "账号"), email(1, "邮箱"), mp(2, "手机号");
+
+    private final int value;
+    private final String text;
+
+    AccountType(int value, String text) {
+        this.value = value;
+        this.text = text;
+    }
+
+    public static AccountType valueOf(int value) {
+        AccountType[] values = AccountType.values();
+        for (AccountType type : values) {
+            if (type.value == value) {
+                return type;
+            }
+        }
+        return null;
+    }
+
+    public String getText() {
+        return text;
+    }
+
+    public Integer getValue() {
+        return value;
+    }
+}

+ 39 - 0
src/main/java/com/zhiqiyun/open/enmus/Gender.java

@@ -0,0 +1,39 @@
+package com.zhiqiyun.open.enmus;
+
+
+/**
+ * @author jtoms
+ */
+
+public enum Gender implements IEnum<Integer> {
+    /**
+     *
+     */
+    secret(0, "保密"), male(1, "男"), female(2, "女");
+
+    private final int value;
+    private final String text;
+
+    Gender(int value, String text) {
+        this.value = value;
+        this.text = text;
+    }
+
+    public static Gender valueOf(int code) {
+        Gender[] values = Gender.values();
+        for (Gender type : values) {
+            if (type.value == code) {
+                return type;
+            }
+        }
+        return null;
+    }
+
+    public String getText() {
+        return text;
+    }
+
+    public Integer getValue() {
+        return value;
+    }
+}

+ 8 - 0
src/main/java/com/zhiqiyun/open/enmus/IEnum.java

@@ -0,0 +1,8 @@
+package com.zhiqiyun.open.enmus;
+
+
+import java.io.Serializable;
+
+public interface IEnum<T extends Serializable> {
+    T getValue();
+}

+ 39 - 0
src/main/java/com/zhiqiyun/open/enmus/PasswordType.java

@@ -0,0 +1,39 @@
+package com.zhiqiyun.open.enmus;
+
+
+/**
+ * @author jtoms
+ */
+
+public enum PasswordType implements IEnum<Integer> {
+    /**
+     *
+     */
+    login(1, "登录密码"), trade(2, "交易密码");
+
+    private final int value;
+    private final String text;
+
+    PasswordType(int value, String text) {
+        this.value = value;
+        this.text = text;
+    }
+
+    public static PasswordType valueOf(int value) {
+        PasswordType[] values = PasswordType.values();
+        for (PasswordType type : values) {
+            if (type.value == value) {
+                return type;
+            }
+        }
+        return null;
+    }
+
+    public String getText() {
+        return text;
+    }
+
+    public Integer getValue() {
+        return value;
+    }
+}

+ 43 - 0
src/main/java/com/zhiqiyun/open/enmus/UserLoginLogState.java

@@ -0,0 +1,43 @@
+package com.zhiqiyun.open.enmus;
+
+
+/**
+ * @author jtoms
+ */
+
+public enum UserLoginLogState implements IEnum<Integer> {
+    /**
+     *
+     */
+    LOGIN_EXCEPTION(0, "登录异常"),
+    SUCCESS(1, "正常"),
+    CAPTCHA_ERROR(2, "验证码错误"),
+    ACCOUNT_NOT_EXIST(3, "账号不存在"),
+    PASSWORD_ERROR(4, "密码错误");
+
+    private final int value;
+    private final String text;
+
+    UserLoginLogState(int value, String text) {
+        this.value = value;
+        this.text = text;
+    }
+
+    public static UserLoginLogState valueOf(int value) {
+        UserLoginLogState[] values = UserLoginLogState.values();
+        for (UserLoginLogState type : values) {
+            if (type.value == value) {
+                return type;
+            }
+        }
+        return null;
+    }
+
+    public String getText() {
+        return text;
+    }
+
+    public Integer getValue() {
+        return value;
+    }
+}

+ 39 - 0
src/main/java/com/zhiqiyun/open/enmus/UserState.java

@@ -0,0 +1,39 @@
+package com.zhiqiyun.open.enmus;
+
+
+/**
+ * @author jtoms
+ */
+
+public enum UserState implements IEnum<Integer> {
+    /**
+     *
+     */
+    normal(1, "正常"), disable(0, "禁用");
+
+    private final int value;
+    private final String text;
+
+    UserState(int value, String text) {
+        this.value = value;
+        this.text = text;
+    }
+
+    public static UserState valueOf(int value) {
+        UserState[] values = UserState.values();
+        for (UserState type : values) {
+            if (type.value == value) {
+                return type;
+            }
+        }
+        return null;
+    }
+
+    public String getText() {
+        return text;
+    }
+
+    public Integer getValue() {
+        return value;
+    }
+}

+ 56 - 0
src/main/java/com/zhiqiyun/open/enmus/YN.java

@@ -0,0 +1,56 @@
+package com.zhiqiyun.open.enmus;
+
+
+/**
+ * @author jtoms
+ */
+
+public enum YN implements IEnum<Integer> {
+    /**
+     *
+     */
+    N(0, "否"), Y(1, "是");
+
+    private final int code;
+    private final String text;
+
+    YN(Integer code, String text) {
+        this.code = code;
+        this.text = text;
+    }
+
+    public static YN enumOf(Integer code) {
+        YN[] values = YN.values();
+        for (YN type : values) {
+            if (type.code == code) {
+                return type;
+            }
+        }
+        return null;
+    }
+
+    public boolean getBoolean() {
+        return this.code == 1;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getText() {
+        return text;
+    }
+
+    @Override
+    public Integer getValue() {
+        return code;
+    }
+
+    public String getName() {
+        YN yn = YN.enumOf(code);
+        if (yn == null) {
+            return "";
+        }
+        return yn.name();
+    }
+}

+ 21 - 0
src/main/java/com/zhiqiyun/open/exception/NoFoundException.java

@@ -0,0 +1,21 @@
+package com.zhiqiyun.open.exception;
+
+public class NoFoundException extends RuntimeException {
+
+    private static final long serialVersionUID = -6599531762911251584L;
+
+    public NoFoundException() {
+    }
+
+    public NoFoundException(String message) {
+        super(message);
+    }
+
+    public NoFoundException(Throwable cause) {
+        super(cause);
+    }
+
+    public NoFoundException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}

+ 26 - 0
src/main/java/com/zhiqiyun/open/exception/NoLoginException.java

@@ -0,0 +1,26 @@
+package com.zhiqiyun.open.exception;
+
+/**
+ * @author jtoms
+ */
+public class NoLoginException extends Exception {
+
+    private static final long serialVersionUID = 3934335121640650570L;
+
+    private String loginUrl;
+
+    public NoLoginException() {
+    }
+
+    public NoLoginException(String message) {
+        super(message);
+    }
+
+    public String getLoginUrl() {
+        return loginUrl;
+    }
+
+    public void setLoginUrl(String loginUrl) {
+        this.loginUrl = loginUrl;
+    }
+}

+ 28 - 0
src/main/java/com/zhiqiyun/open/exception/NotSufficientFundsException.java

@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2008 Happy Fish / YuQing
+ * 
+ * FastDFS Java Client may be copied only under the terms of the GNU Lesser
+ * General Public License (LGPL). Please visit the FastDFS Home Page
+ * http://www.csource.org/ for more detail.
+ */
+
+package com.zhiqiyun.open.exception;
+
+/**
+* My Exception
+* @author Happy Fish / YuQing
+* @version Version 1.0
+*/
+public class NotSufficientFundsException extends Exception {
+    /**
+     *
+     */
+    private static final long serialVersionUID = 2699517589111700417L;
+
+    public NotSufficientFundsException() {
+    }
+
+    public NotSufficientFundsException(String message) {
+        super(message);
+    }
+}

+ 20 - 0
src/main/java/com/zhiqiyun/open/exception/PermissionDeniedException.java

@@ -0,0 +1,20 @@
+package com.zhiqiyun.open.exception;
+
+public class PermissionDeniedException extends Exception {
+    private static final long serialVersionUID = -438346846416711065L;
+
+    public PermissionDeniedException() {
+    }
+
+    public PermissionDeniedException(String message) {
+        super(message);
+    }
+
+    public PermissionDeniedException(Throwable cause) {
+        super(cause);
+    }
+
+    public PermissionDeniedException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}

+ 42 - 0
src/main/java/com/zhiqiyun/open/exception/ServiceException.java

@@ -0,0 +1,42 @@
+package com.zhiqiyun.open.exception;
+
+public class ServiceException extends RuntimeException {
+
+    private static final long serialVersionUID = 4109764123357142460L;
+
+    /**
+     * 空构造
+     */
+    public ServiceException() {
+        super("ServiceException 异常");
+    }
+
+    /**
+     * 自定义错误日志
+     *
+     * @param e
+     */
+    public ServiceException(String e) {
+        super(e);
+    }
+
+    /**
+     * 只抛错误信息
+     *
+     * @param e
+     */
+    public ServiceException(Throwable e) {
+        super(e);
+    }
+
+    /**
+     * 两者皆抛
+     *
+     * @param er
+     * @param e
+     */
+    public ServiceException(String er, Throwable e) {
+        super(er, e);
+    }
+
+}

+ 13 - 0
src/main/java/com/zhiqiyun/open/exception/UploadException.java

@@ -0,0 +1,13 @@
+package com.zhiqiyun.open.exception;
+
+public class UploadException extends Exception {
+
+    private static final long serialVersionUID = -1700379405389534667L;
+
+    public UploadException() {
+    }
+
+    public UploadException(String message) {
+        super(message);
+    }
+}

+ 22 - 0
src/main/java/com/zhiqiyun/open/mapper/AuthorityInfoMapper.java

@@ -0,0 +1,22 @@
+package com.zhiqiyun.open.mapper;
+
+import com.zhiqiyun.open.models.AuthorityInfo;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * @author jtoms
+ */
+@Mapper
+public interface AuthorityInfoMapper {
+
+    /**
+     * 查询下级ID
+     *
+     * @param parentId
+     * @return
+     */
+    List<AuthorityInfo> findChildren(@Param("parentId") Long parentId);
+}

+ 68 - 0
src/main/java/com/zhiqiyun/open/mapper/RoleInfoMapper.java

@@ -0,0 +1,68 @@
+package com.zhiqiyun.open.mapper;
+
+import com.zhiqiyun.open.models.RoleInfo;
+import com.zhiqiyun.open.mybatis.paginator.domain.PageBounds;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author jtoms
+ */
+@Mapper
+public interface RoleInfoMapper {
+
+    /**
+     * 插入角色信息
+     *
+     * @param roleInfo
+     */
+    void insert(RoleInfo roleInfo);
+
+    /**
+     * 更新角色信息
+     *
+     * @param roleInfo
+     */
+    void updateById(RoleInfo roleInfo);
+
+    /**
+     * 删除角色下的权限值
+     *
+     * @param roleIds
+     */
+    void deleteAuthorities(@Param("roleIds") List<Long> roleIds);
+
+    /**
+     * 查询角色的权限值
+     *
+     * @param roleId
+     * @return
+     */
+    List<Long> findAuthorities(@Param("roleId") Long roleId);
+
+    /**
+     * 查询用户的权限值
+     *
+     * @param roleId
+     * @param authorities
+     */
+    void insertAuthority(@Param("roleId") Long roleId, @Param("authorities") Long[] authorities);
+
+    /**
+     * 批量删除角色信息
+     *
+     * @param roleIds
+     */
+    void deleteBatchIds(@Param("roleIds") List<Long> roleIds);
+
+    /**
+     * 分页查询角色列表
+     *
+     * @param toQueryWrapper
+     * @return
+     */
+    List<RoleInfo> findPage(PageBounds bounds, Map<String, Object> toQueryWrapper);
+}

+ 12 - 0
src/main/java/com/zhiqiyun/open/mapper/SequenceMapper.java

@@ -0,0 +1,12 @@
+package com.zhiqiyun.open.mapper;
+
+import com.zhiqiyun.open.models.Sequence;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface SequenceMapper {
+    /**
+     * 生成一个新的ID
+     */
+    void generateNextId(Sequence sequence);
+}

+ 119 - 0
src/main/java/com/zhiqiyun/open/mapper/UserBaseInfoMapper.java

@@ -0,0 +1,119 @@
+package com.zhiqiyun.open.mapper;
+
+import com.zhiqiyun.open.models.RoleInfo;
+import com.zhiqiyun.open.models.UserBaseInfo;
+import com.zhiqiyun.open.models.UserLoginLog;
+import com.zhiqiyun.open.models.UserOperateLog;
+import com.zhiqiyun.open.mybatis.paginator.domain.PageBounds;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Administrator
+ * @date 2017-6-7
+ */
+@Mapper
+public interface UserBaseInfoMapper {
+    /**
+     * 分页查询用户基本信息
+     *
+     * @param bounds
+     * @param queryWrapper
+     * @return
+     */
+    List<UserBaseInfo> findPage(PageBounds bounds, Map<String, Object> queryWrapper);
+
+    /**
+     * 插入用户基本信息
+     *
+     * @param userInfo
+     */
+    void insert(UserBaseInfo userInfo);
+
+    /**
+     * 更新用户基本信息
+     *
+     * @param userInfo
+     */
+    void updateById(UserBaseInfo userInfo);
+
+    /**
+     * 查询用户基本信息
+     *
+     * @param id
+     * @return
+     */
+    UserBaseInfo findById(@Param("id") Long id);
+
+    /**
+     * 查询用户所拥有的权限
+     *
+     * @param uid
+     * @return
+     */
+    List<String> findUserAuthorities(@Param("uid") Long uid);
+
+    /**
+     * 删除用户所有角色
+     *
+     * @param uid
+     */
+    void deleteRoles(@Param("uid") Long uid);
+
+    /**
+     * 插入用户角色
+     *
+     * @param uid
+     * @param roles
+     */
+    void insertRoles(@Param("uid") Long uid, @Param("roles") Long[] roles);
+
+    /**
+     * 查询用户角色
+     *
+     * @param uid
+     * @return
+     */
+    List<RoleInfo> findRoles(@Param("uid") Long uid);
+
+    /**
+     * 插入日志信息
+     *
+     * @param userOperateLog
+     */
+    void insertOperateLog(UserOperateLog userOperateLog);
+
+    /**
+     * 更新日志信息
+     *
+     * @param userOperateLog
+     */
+    void updateOperateLogById(UserOperateLog userOperateLog);
+
+    /**
+     * 插入登录日志
+     *
+     * @param userLoginLog
+     */
+    void insertLoginLog(UserLoginLog userLoginLog);
+
+    /**
+     * 分页查询登录日志
+     *
+     * @param bounds
+     * @param uid
+     * @return
+     */
+    List<UserLoginLog> findLoginLogPage(PageBounds bounds, @Param("uid") Long uid);
+
+    /**
+     * 查询搜索账号
+     *
+     * @param searchKey
+     * @return
+     */
+    List<Map<String, Object>> findSelectAccounts(@Param("searchKey") String searchKey);
+}

+ 47 - 0
src/main/java/com/zhiqiyun/open/mapper/UserLoginAccountMapper.java

@@ -0,0 +1,47 @@
+package com.zhiqiyun.open.mapper;
+
+import com.zhiqiyun.open.enmus.AccountType;
+import com.zhiqiyun.open.models.UserLoginAccount;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * @author Administrator
+ * @date 2017-6-7
+ */
+@Mapper
+public interface UserLoginAccountMapper {
+
+    /**
+     * 插入账号信息
+     *
+     * @param loginAccount
+     */
+    void insertOrUpdate(UserLoginAccount loginAccount);
+
+    /**
+     * 查询用户所有账户
+     *
+     * @param uid
+     * @return
+     */
+    List<UserLoginAccount> findLoginAccounts(@Param("uid") Long uid);
+
+    /**
+     * 查询用户账号
+     *
+     * @param loginAccount
+     * @param accountType
+     * @return
+     */
+    UserLoginAccount findLoginAccount(@Param("loginAccount") String loginAccount, @Param("accountType") AccountType accountType);
+
+    /**
+     * 删除用户账号
+     *
+     * @param uid
+     */
+    void deleteByUid(@Param("uid") Long uid);
+}

+ 29 - 0
src/main/java/com/zhiqiyun/open/mapper/UserPasswordMapper.java

@@ -0,0 +1,29 @@
+package com.zhiqiyun.open.mapper;
+
+import com.zhiqiyun.open.enmus.PasswordType;
+import com.zhiqiyun.open.models.UserPassword;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * @author Administrator
+ * @date 2017-6-7
+ */
+@Mapper
+public interface UserPasswordMapper {
+    /**
+     * 更新用户密码
+     *
+     * @param userPassword
+     */
+    void insertOrUpdatePassword(UserPassword userPassword);
+
+    /**
+     * 查询用户密码
+     *
+     * @param uid
+     * @param passwordType
+     * @return
+     */
+    UserPassword findPassword(@Param("uid") Long uid, @Param("passwordType") PasswordType passwordType);
+}

+ 25 - 0
src/main/java/com/zhiqiyun/open/models/AuthorityInfo.java

@@ -0,0 +1,25 @@
+package com.zhiqiyun.open.models;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author jtoms
+ */
+@Data
+public class AuthorityInfo implements Serializable {
+
+    private static final long serialVersionUID = -2758642222540483582L;
+
+    private Long id;
+
+    private Long parentId;
+
+    private String name;
+
+    private String remark;
+
+    private List<AuthorityInfo> children;
+}

+ 87 - 0
src/main/java/com/zhiqiyun/open/models/OauthInfo.java

@@ -0,0 +1,87 @@
+package com.zhiqiyun.open.models;
+
+import com.zhiqiyun.open.enmus.Gender;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author jtoms
+ */
+@Data
+public class OauthInfo implements Serializable {
+
+    private static final long serialVersionUID = -7252878048497511413L;
+
+    /**
+     * 唯一标识
+     */
+    private Long id;
+
+    /**
+     * 用户昵称
+     */
+    private String nickName;
+
+    /**
+     * 用户性别
+     */
+    private Gender gender;
+
+    /**
+     * 最后登录时间
+     */
+    private Date loginTime;
+
+    /**
+     * 用户登录令牌
+     */
+    private String accessToken;
+
+    /**
+     * 用户头像
+     */
+    private String avatar;
+
+    /**
+     * 用户权限
+     */
+    private List<String> authorities;
+
+    public OauthInfo setId(Long id) {
+        this.id = id;
+        return this;
+    }
+
+    public OauthInfo setNickName(String nickName) {
+        this.nickName = nickName;
+        return this;
+    }
+
+    public OauthInfo setLoginTime(Date loginTime) {
+        this.loginTime = loginTime;
+        return this;
+    }
+
+    public OauthInfo setAccessToken(String accessToken) {
+        this.accessToken = accessToken;
+        return this;
+    }
+
+    public OauthInfo setAvatar(String avatar) {
+        this.avatar = avatar;
+        return this;
+    }
+
+    public OauthInfo setAuthorities(List<String> authorities) {
+        this.authorities = authorities;
+        return this;
+    }
+
+    public OauthInfo setGender(Gender gender) {
+        this.gender = gender;
+        return this;
+    }
+}

+ 23 - 0
src/main/java/com/zhiqiyun/open/models/RoleInfo.java

@@ -0,0 +1,23 @@
+package com.zhiqiyun.open.models;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author jtoms
+ */
+@Data
+public class RoleInfo implements Serializable {
+
+    private static final long serialVersionUID = 5241138963805332125L;
+
+    private Long id;
+
+    private String name;
+
+    private String remark;
+
+    private List<Long> listAuthorities;
+}

+ 15 - 0
src/main/java/com/zhiqiyun/open/models/Sequence.java

@@ -0,0 +1,15 @@
+package com.zhiqiyun.open.models;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+public class Sequence implements Serializable {
+    private static final long serialVersionUID = 4503888339206128827L;
+
+    private Long id;
+    private Integer saltRandom;
+    private Date createdTime;
+}

+ 24 - 0
src/main/java/com/zhiqiyun/open/models/UserBaseInfo.java

@@ -0,0 +1,24 @@
+package com.zhiqiyun.open.models;
+
+import com.zhiqiyun.open.enmus.Gender;
+import com.zhiqiyun.open.enmus.UserState;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @author Administrator
+ * @date 2017-6-7
+ */
+@Data
+public class UserBaseInfo implements Serializable {
+    private static final long serialVersionUID = 925241835389657323L;
+    private Long id;
+    private String nickName;
+    private String avatar;
+    private Gender gender;
+    private Date registerTime;
+    private String registerIp;
+    private UserState state;
+}

+ 47 - 0
src/main/java/com/zhiqiyun/open/models/UserLoginAccount.java

@@ -0,0 +1,47 @@
+package com.zhiqiyun.open.models;
+
+import com.zhiqiyun.open.enmus.AccountType;
+import lombok.Data;
+import org.apache.commons.codec.digest.DigestUtils;
+
+import java.io.Serializable;
+
+/**
+ * @author Administrator
+ * @date 2017-6-7
+ */
+@Data
+public class UserLoginAccount implements Serializable {
+
+    private static final long serialVersionUID = -6476815660455154143L;
+
+    private String id;
+
+    private Long uid;
+
+    private String loginAccount;
+
+    private AccountType accountType;
+
+    public UserLoginAccount() {
+    }
+
+    public UserLoginAccount(Long uid, String loginAccount, AccountType accountType) {
+        this.uid = uid;
+        this.loginAccount = loginAccount;
+        this.accountType = accountType;
+    }
+
+    public UserLoginAccount(String loginAccount, AccountType accountType) {
+        this.loginAccount = loginAccount;
+        this.accountType = accountType;
+    }
+
+    public String getId() {
+        if (id == null || "".equals(id.trim())) {
+            id = DigestUtils.md5Hex(String.format("%s@%s", accountType.name(), uid));
+        }
+        return id;
+    }
+
+}

+ 26 - 0
src/main/java/com/zhiqiyun/open/models/UserLoginLog.java

@@ -0,0 +1,26 @@
+package com.zhiqiyun.open.models;
+
+import com.zhiqiyun.open.enmus.AccountType;
+import com.zhiqiyun.open.enmus.UserLoginLogState;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @author Administrator
+ * @date 2017-6-7
+ */
+@Data
+public class UserLoginLog implements Serializable {
+    private static final long serialVersionUID = -6352081881437839365L;
+    private String id;
+    private String loginAccount;
+    private AccountType accountType;
+    private String loginIp;
+    private String loginLocal;
+    private String fromSource;
+    private String deviceId;
+    private Date loginTime;
+    private UserLoginLogState state;
+}

+ 24 - 0
src/main/java/com/zhiqiyun/open/models/UserOperateLog.java

@@ -0,0 +1,24 @@
+package com.zhiqiyun.open.models;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @author jtoms
+ */
+@Data
+public class UserOperateLog implements Serializable {
+    private static final long serialVersionUID = -734912919219229259L;
+    private String id;
+    private Long uid;
+    private String tags;
+    private String fromSource;
+    private String requestIp;
+    private String requestUrl;
+    private String requestParams;
+    private String requestData;
+    private Date requestTime;
+    private Date responseTime;
+}

+ 41 - 0
src/main/java/com/zhiqiyun/open/models/UserPassword.java

@@ -0,0 +1,41 @@
+package com.zhiqiyun.open.models;
+
+import com.zhiqiyun.open.enmus.PasswordType;
+import lombok.Data;
+import org.apache.commons.codec.digest.DigestUtils;
+
+import java.io.Serializable;
+
+@Data
+public class UserPassword implements Serializable {
+
+    private static final long serialVersionUID = 5320982429919793484L;
+
+    private String id;
+
+    private Long uid;
+
+    private String passwd;
+
+    private String salt;
+
+    private PasswordType passwordType;
+
+    UserPassword() {
+    }
+
+    public UserPassword(Long uid, String passwd, String salt, PasswordType passwordType) {
+        this.uid = uid;
+        this.passwd = passwd;
+        this.salt = salt;
+        this.passwordType = passwordType;
+    }
+
+
+    public String getId() {
+        if (id == null || "".equals(id.trim())) {
+            id = DigestUtils.md5Hex(String.format("%s@%s", passwordType.name(), uid));
+        }
+        return id;
+    }
+}

+ 203 - 0
src/main/java/com/zhiqiyun/open/mybatis/paginator/PaginationInterceptor.java

@@ -0,0 +1,203 @@
+package com.zhiqiyun.open.mybatis.paginator;
+
+
+import com.zhiqiyun.open.mybatis.paginator.dialect.Dialect;
+import com.zhiqiyun.open.mybatis.paginator.domain.PageBounds;
+import com.zhiqiyun.open.mybatis.paginator.support.PropertiesHelper;
+import com.zhiqiyun.open.mybatis.paginator.support.SQLHelp;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.ibatis.cache.Cache;
+import org.apache.ibatis.cache.CacheKey;
+import org.apache.ibatis.executor.Executor;
+import org.apache.ibatis.mapping.BoundSql;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.mapping.MappedStatement.Builder;
+import org.apache.ibatis.mapping.ParameterMapping;
+import org.apache.ibatis.mapping.SqlSource;
+import org.apache.ibatis.plugin.*;
+import org.apache.ibatis.session.ResultHandler;
+import org.apache.ibatis.session.RowBounds;
+
+import java.lang.reflect.Constructor;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.*;
+
+
+/**
+ * 为MyBatis提供基于方言(Dialect)的分页查询的插件
+ * <p>
+ * 将拦截Executor.query()方法实现分页方言的插入.
+ *
+ * @author badqiu
+ * @author miemiedev
+ */
+@Slf4j
+@Intercepts({@Signature(
+        type = Executor.class,
+        method = "query",
+        args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})
+public class PaginationInterceptor implements Interceptor {
+    public static ExecutorService Pool;
+    private static final int MAPPED_STATEMENT_INDEX = 0;
+    private static final int PARAMETER_INDEX = 1;
+    private static final int ROWBOUNDS_INDEX = 2;
+    String dialectClass;
+//    boolean asyncTotalCount = false;
+
+    @Override
+    public Object intercept(final Invocation invocation) throws Throwable {
+        final Executor executor = (Executor) invocation.getTarget();
+        final Object[] queryArgs = invocation.getArgs();
+        final MappedStatement ms = (MappedStatement) queryArgs[MAPPED_STATEMENT_INDEX];
+        final Object parameter = queryArgs[PARAMETER_INDEX];
+        final RowBounds rowBounds = (RowBounds) queryArgs[ROWBOUNDS_INDEX];
+
+        if (rowBounds instanceof PageBounds) {
+            PageBounds bounds = (PageBounds) rowBounds;
+
+            if (bounds.getOffset() == RowBounds.NO_ROW_OFFSET && bounds.getLimit() == RowBounds.NO_ROW_LIMIT && bounds.getOrders().isEmpty()) {
+                return invocation.proceed();
+            }
+
+            final Dialect dialect;
+            try {
+                Class<?> clazz = Class.forName(dialectClass);
+                Constructor<?> constructor = clazz.getConstructor(MappedStatement.class, Object.class, PageBounds.class);
+                dialect = (Dialect) constructor.newInstance(new Object[]{ms, parameter, bounds});
+            } catch (Exception e) {
+                throw new ClassNotFoundException("Cannot create dialect instance: " + dialectClass, e);
+            }
+
+            final BoundSql boundSql = ms.getBoundSql(parameter);
+
+            queryArgs[MAPPED_STATEMENT_INDEX] = copyFromNewSql(ms, boundSql, dialect.getPageSQL(), dialect.getParameterMappings(), dialect.getParameterObject());
+            queryArgs[PARAMETER_INDEX] = dialect.getParameterObject();
+            queryArgs[ROWBOUNDS_INDEX] = new RowBounds(RowBounds.NO_ROW_OFFSET, RowBounds.NO_ROW_LIMIT);
+
+            Future<Object> listFuture = call(invocation::proceed);
+
+
+            Callable<Integer> totalCountTask = () -> {
+                Integer totalCount;
+                Cache cache = ms.getCache();
+                if (cache != null && ms.isUseCache() && ms.getConfiguration().isCacheEnabled()) {
+                    CacheKey cacheKey = executor.createCacheKey(ms, parameter, new PageBounds(), copyFromBoundSql(ms, boundSql, dialect.getCountSQL(), boundSql.getParameterMappings(), boundSql.getParameterObject()));
+                    totalCount = (Integer) cache.getObject(cacheKey);
+                    if (totalCount == null) {
+                        totalCount = SQLHelp.getCount(ms, executor.getTransaction(), parameter, boundSql, dialect);
+                        cache.putObject(cacheKey, totalCount);
+                    }
+                } else {
+                    totalCount = SQLHelp.getCount(ms, executor.getTransaction(), parameter, boundSql, dialect);
+                }
+                return totalCount;
+            };
+            Future<Integer> totalCountFuture = call(totalCountTask);
+            bounds.setTotal(totalCountFuture.get());
+
+            return listFuture.get();
+
+        }
+        return invocation.proceed();
+    }
+
+    private <T> Future<T> call(Callable<T> callable) {
+        FutureTask<T> future = new FutureTask<>(callable);
+        future.run();
+        return future;
+    }
+
+    private MappedStatement copyFromNewSql(MappedStatement ms, BoundSql boundSql, String sql, List<ParameterMapping> parameterMappings, Object parameter) {
+        BoundSql newBoundSql = copyFromBoundSql(ms, boundSql, sql, parameterMappings, parameter);
+        return copyFromMappedStatement(ms, new BoundSqlSqlSource(newBoundSql));
+    }
+
+    private BoundSql copyFromBoundSql(MappedStatement ms, BoundSql boundSql, String sql, List<ParameterMapping> parameterMappings, Object parameter) {
+        BoundSql newBoundSql = new BoundSql(ms.getConfiguration(), sql, parameterMappings, parameter);
+        for (ParameterMapping mapping : boundSql.getParameterMappings()) {
+            String prop = mapping.getProperty();
+            if (boundSql.hasAdditionalParameter(prop)) {
+                newBoundSql.setAdditionalParameter(prop, boundSql.getAdditionalParameter(prop));
+            }
+        }
+        return newBoundSql;
+    }
+
+    private MappedStatement copyFromMappedStatement(MappedStatement ms, SqlSource newSqlSource) {
+        Builder builder = new Builder(ms.getConfiguration(), ms.getId(), newSqlSource, ms.getSqlCommandType());
+
+        builder.resource(ms.getResource());
+        builder.fetchSize(ms.getFetchSize());
+        builder.statementType(ms.getStatementType());
+        builder.keyGenerator(ms.getKeyGenerator());
+        if (ms.getKeyProperties() != null && ms.getKeyProperties().length != 0) {
+            StringBuilder keyProperties = new StringBuilder();
+            for (String keyProperty : ms.getKeyProperties()) {
+                keyProperties.append(keyProperty).append(",");
+            }
+            keyProperties.delete(keyProperties.length() - 1, keyProperties.length());
+            builder.keyProperty(keyProperties.toString());
+        }
+
+        //setStatementTimeout()
+        builder.timeout(ms.getTimeout());
+
+        //setStatementResultMap()
+        builder.parameterMap(ms.getParameterMap());
+
+        //setStatementResultMap()
+        builder.resultMaps(ms.getResultMaps());
+        builder.resultSetType(ms.getResultSetType());
+
+        //setStatementCache()
+        builder.cache(ms.getCache());
+        builder.flushCacheRequired(ms.isFlushCacheRequired());
+        builder.useCache(ms.isUseCache());
+
+        return builder.build();
+    }
+
+    @Override
+    public Object plugin(Object target) {
+        return Plugin.wrap(target, this);
+    }
+
+    @Override
+    public void setProperties(Properties properties) {
+        PropertiesHelper propertiesHelper = new PropertiesHelper(properties);
+        String dialectClass = propertiesHelper.getRequiredString("dialectClass");
+        setDialectClass(dialectClass);
+        setPoolMaxSize(propertiesHelper.getInt("poolMaxSize", 0));
+
+    }
+
+    public void setDialectClass(String dialectClass) {
+        log.debug("dialectClass: {} ", dialectClass);
+        this.dialectClass = dialectClass;
+    }
+
+    public void setPoolMaxSize(int poolMaxSize) {
+        if (poolMaxSize > 0) {
+            log.debug("poolMaxSize: {} ", poolMaxSize);
+            Pool = Executors.newFixedThreadPool(poolMaxSize);
+        } else {
+            Pool = Executors.newCachedThreadPool();
+        }
+
+
+    }
+
+    public static class BoundSqlSqlSource implements SqlSource {
+        BoundSql boundSql;
+
+        public BoundSqlSqlSource(BoundSql boundSql) {
+            this.boundSql = boundSql;
+        }
+
+        @Override
+        public BoundSql getBoundSql(Object parameterObject) {
+            return boundSql;
+        }
+    }
+}

+ 66 - 0
src/main/java/com/zhiqiyun/open/mybatis/paginator/dialect/DB2Dialect.java

@@ -0,0 +1,66 @@
+package com.zhiqiyun.open.mybatis.paginator.dialect;
+
+import com.zhiqiyun.open.mybatis.paginator.domain.PageBounds;
+import org.apache.ibatis.mapping.MappedStatement;
+
+/**
+ * @author badqiu
+ * @author miemiedev
+ */
+public class DB2Dialect extends Dialect {
+
+    public DB2Dialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
+        super(mappedStatement, parameterObject, pageBounds);
+    }
+
+    private static String getRowNumber(String sql) {
+        StringBuffer rownumber = new StringBuffer(50)
+                .append("rownumber() over(");
+
+        int orderByIndex = sql.toLowerCase().indexOf("order by");
+
+        if (orderByIndex > 0 && !hasDistinct(sql)) {
+            rownumber.append(sql.substring(orderByIndex));
+        }
+
+        rownumber.append(") as rownumber_,");
+
+        return rownumber.toString();
+    }
+
+    private static boolean hasDistinct(String sql) {
+        return sql.toLowerCase().indexOf("select distinct") >= 0;
+    }
+
+    @Override
+    protected String getLimitString(String sql, String offsetName, int offset, String limitName, int limit) {
+        int startOfSelect = sql.toLowerCase().indexOf("select");
+
+        StringBuffer pagingSelect = new StringBuffer(sql.length() + 100)
+                .append(sql.substring(0, startOfSelect)) //add the comment
+                .append("select * from ( select ") //nest the main query in an outer select
+                .append(getRowNumber(sql)); //add the rownnumber bit into the outer query select list
+
+        if (hasDistinct(sql)) {
+            pagingSelect.append(" row_.* from ( ") //add another (inner) nested select
+                    .append(sql.substring(startOfSelect)) //add the main query
+                    .append(" ) as row_"); //close off the inner nested select
+        } else {
+            pagingSelect.append(sql.substring(startOfSelect + 6)); //add the main query
+        }
+
+        pagingSelect.append(" ) as temp_ where rownumber_ ");
+
+        //add the restriction to the outer select
+        if (offset > 0) {
+            pagingSelect.append("between ?+1 and ?");
+            setPageParameter(offsetName, offset, Integer.class);
+            setPageParameter("__offsetEnd", offset + limit, Integer.class);
+        } else {
+            pagingSelect.append("<= ?");
+            setPageParameter(limitName, limit, Integer.class);
+        }
+
+        return pagingSelect.toString();
+    }
+}

+ 145 - 0
src/main/java/com/zhiqiyun/open/mybatis/paginator/dialect/Dialect.java

@@ -0,0 +1,145 @@
+package com.zhiqiyun.open.mybatis.paginator.dialect;
+
+import com.zhiqiyun.open.mybatis.paginator.domain.Order;
+import com.zhiqiyun.open.mybatis.paginator.domain.PageBounds;
+import org.apache.ibatis.mapping.BoundSql;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.mapping.ParameterMapping;
+import org.apache.ibatis.reflection.MetaObject;
+import org.apache.ibatis.reflection.property.PropertyTokenizer;
+import org.apache.ibatis.reflection.wrapper.ObjectWrapper;
+import org.apache.ibatis.session.RowBounds;
+import org.apache.ibatis.type.SimpleTypeRegistry;
+import org.apache.ibatis.type.TypeHandlerRegistry;
+
+import java.util.*;
+
+/**
+ * 类似hibernate的Dialect,但只精简出分页部分
+ * 
+ * @author badqiu
+ * @author miemiedev
+ */
+public class Dialect {
+    protected TypeHandlerRegistry typeHandlerRegistry;
+    protected MappedStatement mappedStatement;
+    protected PageBounds pageBounds;
+    protected Object parameterObject;
+    protected BoundSql boundSql;
+    protected List<ParameterMapping> parameterMappings;
+    protected Map<String, Object> pageParameters = new HashMap<String, Object>();
+
+    private String pageSQL;
+    private String countSQL;
+
+    public Dialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
+        this.mappedStatement = mappedStatement;
+        this.parameterObject = parameterObject;
+        this.pageBounds = pageBounds;
+        this.typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry();
+
+        init();
+    }
+
+    protected void init() {
+
+        boundSql = mappedStatement.getBoundSql(parameterObject);
+        parameterMappings = new ArrayList<>(boundSql.getParameterMappings());
+        if (parameterObject instanceof Map) {
+            pageParameters.putAll((Map) parameterObject);
+        } else if (parameterObject != null) {
+            Class<?> cls = parameterObject.getClass();
+            if (cls.isPrimitive() || cls.isArray() || SimpleTypeRegistry.isSimpleType(cls)
+                    || Enum.class.isAssignableFrom(cls) || Collection.class.isAssignableFrom(cls)) {
+                for (ParameterMapping parameterMapping : parameterMappings) {
+                    pageParameters.put(parameterMapping.getProperty(), parameterObject);
+                }
+            } else {
+                MetaObject metaObject = mappedStatement.getConfiguration().newMetaObject(parameterObject);
+                ObjectWrapper wrapper = metaObject.getObjectWrapper();
+                for (ParameterMapping parameterMapping : parameterMappings) {
+                    PropertyTokenizer prop = new PropertyTokenizer(parameterMapping.getProperty());
+                    pageParameters.put(parameterMapping.getProperty(), wrapper.get(prop));
+                }
+            }
+
+        }
+
+        StringBuffer bufferSql = new StringBuffer(boundSql.getSql().trim());
+        if (bufferSql.lastIndexOf(";") == bufferSql.length() - 1) {
+            bufferSql.deleteCharAt(bufferSql.length() - 1);
+        }
+        String sql = bufferSql.toString();
+        pageSQL = sql;
+        if (pageBounds.getOrders() != null && !pageBounds.getOrders().isEmpty()) {
+            pageSQL = getSortString(sql, pageBounds.getOrders());
+        }
+        if (pageBounds.getOffset() != RowBounds.NO_ROW_OFFSET || pageBounds.getLimit() != RowBounds.NO_ROW_LIMIT) {
+            pageSQL = getLimitString(pageSQL, "__offset", pageBounds.getOffset(), "__limit", pageBounds.getLimit());
+        }
+
+        countSQL = getCountString(sql);
+    }
+
+    public List<ParameterMapping> getParameterMappings() {
+        return parameterMappings;
+    }
+
+    public Object getParameterObject() {
+        return pageParameters;
+    }
+
+    public String getPageSQL() {
+        return pageSQL;
+    }
+
+    protected void setPageParameter(String name, Object value, Class<?> type) {
+        ParameterMapping parameterMapping = new ParameterMapping.Builder(mappedStatement.getConfiguration(), name, type)
+                .build();
+        parameterMappings.add(parameterMapping);
+        pageParameters.put(name, value);
+    }
+
+    public String getCountSQL() {
+        return countSQL;
+    }
+
+    /**
+     * 将sql变成分页sql语句
+     */
+    protected String getLimitString(String sql, String offsetName, int offset, String limitName, int limit) {
+        throw new UnsupportedOperationException("paged queries not supported");
+    }
+
+    /**
+     * 将sql转换为总记录数SQL
+     * 
+     * @param sql SQL语句
+     * @return 总记录数的sql
+     */
+    protected String getCountString(String sql) {
+        return "select count(1) from (" + sql + ") tmp_count";
+    }
+
+    /**
+     * 将sql转换为带排序的SQL
+     * 
+     * @param sql SQL语句
+     * @return 总记录数的sql
+     */
+    protected String getSortString(String sql, List<Order> orders) {
+        if (orders == null || orders.isEmpty()) {
+            return sql;
+        }
+
+        StringBuffer buffer = new StringBuffer("select * from (").append(sql).append(") temp_order order by ");
+        for (Order order : orders) {
+            if (order != null) {
+                buffer.append(order.toString()).append(", ");
+            }
+
+        }
+        buffer.delete(buffer.length() - 2, buffer.length());
+        return buffer.toString();
+    }
+}

+ 28 - 0
src/main/java/com/zhiqiyun/open/mybatis/paginator/dialect/H2Dialect.java

@@ -0,0 +1,28 @@
+package com.zhiqiyun.open.mybatis.paginator.dialect;
+
+
+import com.zhiqiyun.open.mybatis.paginator.domain.PageBounds;
+import org.apache.ibatis.mapping.MappedStatement;
+
+/**
+ * A dialect compatible with the H2 database.
+ * 
+ * @author Thomas Mueller
+ * @author miemiedev
+ */
+public class H2Dialect extends Dialect {
+
+    public H2Dialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
+        super(mappedStatement, parameterObject, pageBounds);
+    }
+
+    @Override
+	protected String getLimitString(String sql, String offsetName, int offset, String limitName, int limit) {
+		return new StringBuffer(sql.length() + 40).
+			append(sql).
+			append((offset > 0) ? " limit "+String.valueOf(limit)+" offset "+String.valueOf(offset) : " limit "+String.valueOf(limit)).
+			toString();
+	}
+
+
+}

+ 27 - 0
src/main/java/com/zhiqiyun/open/mybatis/paginator/dialect/HSQLDialect.java

@@ -0,0 +1,27 @@
+package com.zhiqiyun.open.mybatis.paginator.dialect;
+
+import com.zhiqiyun.open.mybatis.paginator.domain.PageBounds;
+import org.apache.ibatis.mapping.MappedStatement;
+
+/**
+ * Dialect for HSQLDB
+ *
+ * @author badqiu
+ * @author miemiedev
+ */
+public class HSQLDialect extends Dialect {
+
+    public HSQLDialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
+        super(mappedStatement, parameterObject, pageBounds);
+    }
+
+    @Override
+    protected String getLimitString(String sql, String offsetName, int offset, String limitName, int limit) {
+        boolean hasOffset = offset > 0;
+        return new StringBuffer(sql.length() + 10)
+                .append(sql)
+                .insert(sql.toLowerCase().indexOf("select") + 6, hasOffset ? " limit " + String.valueOf(offset) + " " + String.valueOf(limit) : " top " + String.valueOf(limit))
+                .toString();
+    }
+
+}

+ 30 - 0
src/main/java/com/zhiqiyun/open/mybatis/paginator/dialect/MySQLDialect.java

@@ -0,0 +1,30 @@
+package com.zhiqiyun.open.mybatis.paginator.dialect;
+
+import com.zhiqiyun.open.mybatis.paginator.domain.PageBounds;
+import org.apache.ibatis.mapping.MappedStatement;
+
+/**
+ *  @author badqiu
+ *  @author miemiedev
+ */
+public class MySQLDialect extends Dialect{
+
+    public MySQLDialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
+        super(mappedStatement, parameterObject, pageBounds);
+    }
+    
+	@Override
+    protected String getLimitString(String sql, String offsetName, int offset, String limitName, int limit) {
+        StringBuilder buffer = new StringBuilder( sql.length()+20 ).append(sql);
+        if (offset > 0) {
+            buffer.append(" limit ?, ?");
+            setPageParameter(offsetName, offset, Integer.class);
+            setPageParameter(limitName, limit, Integer.class);
+        } else {
+            buffer.append(" limit ?");
+            setPageParameter(limitName, limit, Integer.class);
+        }
+        return buffer.toString();
+	}   
+  
+}

+ 50 - 0
src/main/java/com/zhiqiyun/open/mybatis/paginator/dialect/OracleDialect.java

@@ -0,0 +1,50 @@
+package com.zhiqiyun.open.mybatis.paginator.dialect;
+
+import com.zhiqiyun.open.mybatis.paginator.domain.PageBounds;
+import org.apache.ibatis.mapping.MappedStatement;
+
+/**
+ *  @author badqiu
+ *  @author miemiedev
+ */
+public class OracleDialect extends Dialect{
+
+    public OracleDialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
+        super(mappedStatement, parameterObject, pageBounds);
+    }
+
+    @Override
+	protected String getLimitString(String sql, String offsetName, int offset, String limitName, int limit) {
+		sql = sql.trim();
+		boolean isForUpdate = false;
+		if ( sql.toLowerCase().endsWith(" for update") ) {
+			sql = sql.substring( 0, sql.length()-11 );
+			isForUpdate = true;
+		}
+		
+		StringBuffer pagingSelect = new StringBuffer( sql.length()+100 );
+		if (offset > 0) {
+			pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");
+		}
+		else {
+			pagingSelect.append("select * from ( ");
+		}
+		pagingSelect.append(sql);
+		if (offset > 0) {
+			pagingSelect.append(" ) row_ ) where rownum_ <= ? and rownum_ > ?");
+            setPageParameter("__offsetEnd",offset+limit,Integer.class);
+            setPageParameter(offsetName,offset,Integer.class);
+		}
+		else {
+			pagingSelect.append(" ) where rownum <= ?");
+            setPageParameter(limitName,limit,Integer.class);
+		}
+
+		if ( isForUpdate ) {
+			pagingSelect.append( " for update" );
+		}
+		
+		return pagingSelect.toString();
+	}
+
+}

+ 30 - 0
src/main/java/com/zhiqiyun/open/mybatis/paginator/dialect/PostgreSQLDialect.java

@@ -0,0 +1,30 @@
+package com.zhiqiyun.open.mybatis.paginator.dialect;
+
+import com.zhiqiyun.open.mybatis.paginator.domain.PageBounds;
+import org.apache.ibatis.mapping.MappedStatement;
+
+/**
+ * @author badqiu
+ * @author miemiedev
+ */
+public class PostgreSQLDialect extends Dialect{
+
+    public PostgreSQLDialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
+        super(mappedStatement, parameterObject, pageBounds);
+    }
+
+    @Override
+    protected String getLimitString(String sql, String offsetName, int offset, String limitName, int limit) {
+        StringBuffer buffer = new StringBuffer( sql.length()+20 ).append(sql);
+        if(offset > 0){
+            buffer.append(" limit ? offset ?");
+            setPageParameter(limitName, limit, Integer.class);
+            setPageParameter(offsetName, offset, Integer.class);
+
+        }else{
+            buffer.append(" limit ?");
+            setPageParameter(limitName, limit, Integer.class);
+        }
+		return buffer.toString();
+	}
+}

+ 83 - 0
src/main/java/com/zhiqiyun/open/mybatis/paginator/dialect/SQLServer2005Dialect.java

@@ -0,0 +1,83 @@
+package com.zhiqiyun.open.mybatis.paginator.dialect;
+
+import com.zhiqiyun.open.mybatis.paginator.domain.PageBounds;
+import org.apache.ibatis.mapping.MappedStatement;
+
+/**
+ * @author badqiu
+ * @author miemiedev
+ */
+// Hibernate BUG: http://opensource.atlassian.com/projects/hibernate/browse/HHH-2655
+public class SQLServer2005Dialect extends Dialect {
+
+    public SQLServer2005Dialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
+        super(mappedStatement, parameterObject, pageBounds);
+    }
+
+    static String getOrderByPart(String sql) {
+        String loweredString = sql.toLowerCase();
+        int orderByIndex = loweredString.indexOf("order by");
+        if (orderByIndex != -1) {
+            // if we find a new "order by" then we need to ignore
+            // the previous one since it was probably used for a subquery
+            return sql.substring(orderByIndex);
+        } else {
+            return "";
+        }
+    }
+
+    /**
+     * Add a LIMIT clause to the given SQL SELECT
+     * <p>
+     * The LIMIT SQL will look like:
+     * <p>
+     * WITH query AS
+     * (SELECT TOP 100 percent ROW_NUMBER() OVER (ORDER BY CURRENT_TIMESTAMP) as __row_number__, * from table_name)
+     * SELECT *
+     * FROM query
+     * WHERE __row_number__ BETWEEN :offset and :lastRows
+     * ORDER BY __row_number__
+     *
+     * @param sql    The SQL statement to base the limit query off of.
+     * @param offset Offset of the first row to be returned by the query (zero-based)
+     * @param limit  Maximum number of rows to be returned by the query
+     * @return A new SQL statement with the LIMIT clause applied.
+     */
+    @Override
+    protected String getLimitString(String sql, String offsetName, int offset, String limitName, int limit) {
+        StringBuffer pagingBuilder = new StringBuffer();
+        String orderby = getOrderByPart(sql);
+        String distinctStr = "";
+
+        String loweredString = sql.toLowerCase();
+        String sqlPartString = sql;
+        if (loweredString.trim().startsWith("select")) {
+            int index = 6;
+            if (loweredString.startsWith("select distinct")) {
+                distinctStr = "DISTINCT ";
+                index = 15;
+            }
+            sqlPartString = sqlPartString.substring(index);
+        }
+        pagingBuilder.append(sqlPartString);
+
+        // if no ORDER BY is specified use fake ORDER BY field to avoid errors
+        if (orderby == null || orderby.length() == 0) {
+            orderby = "ORDER BY CURRENT_TIMESTAMP";
+        }
+
+        StringBuffer result = new StringBuffer();
+        result.append("WITH query AS (SELECT ")
+                .append(distinctStr)
+                .append("TOP 100 PERCENT ")
+                .append(" ROW_NUMBER() OVER (")
+                .append(orderby)
+                .append(") as __row_number__, ")
+                .append(pagingBuilder)
+                .append(") SELECT * FROM query WHERE __row_number__ > ? AND __row_number__ <= ?")
+                .append(" ORDER BY __row_number__");
+        setPageParameter(offsetName, offset, Integer.class);
+        setPageParameter("__offsetEnd", offset + limit, Integer.class);
+        return result.toString();
+    }
+}

+ 43 - 0
src/main/java/com/zhiqiyun/open/mybatis/paginator/dialect/SQLServerDialect.java

@@ -0,0 +1,43 @@
+package com.zhiqiyun.open.mybatis.paginator.dialect;
+
+import com.zhiqiyun.open.mybatis.paginator.domain.PageBounds;
+import org.apache.ibatis.mapping.MappedStatement;
+
+/**
+ * @author badqiu
+ * @author miemiedev
+ */
+public class SQLServerDialect extends Dialect {
+
+    public SQLServerDialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
+        super(mappedStatement, parameterObject, pageBounds);
+    }
+
+
+    static int getAfterSelectInsertPoint(String sql) {
+        int selectIndex = sql.toLowerCase().indexOf("select");
+        final int selectDistinctIndex = sql.toLowerCase().indexOf("select distinct");
+        return selectIndex + (selectDistinctIndex == selectIndex ? 15 : 6);
+    }
+
+
+    @Override
+    protected String getLimitString(String sql, String offsetName, int offset, String limitName, int limit) {
+        if (offset > 0) {
+            throw new UnsupportedOperationException("sql server has no offset");
+        }
+//		if(limitPlaceholder != null) {
+//			throw new UnsupportedOperationException(" sql server not support variable limit");
+//		}
+        setPageParameter(limitName, limit, Integer.class);
+        return new StringBuffer(sql.length() + 8)
+                .append(sql)
+                .insert(getAfterSelectInsertPoint(sql), " top " + limit)
+                .toString();
+    }
+
+//	public boolean supportsVariableLimit() {
+//		return false;
+//	}
+
+}

+ 18 - 0
src/main/java/com/zhiqiyun/open/mybatis/paginator/dialect/SybaseDialect.java

@@ -0,0 +1,18 @@
+package com.zhiqiyun.open.mybatis.paginator.dialect;
+
+import com.zhiqiyun.open.mybatis.paginator.domain.PageBounds;
+import org.apache.ibatis.mapping.MappedStatement;
+
+public class SybaseDialect extends Dialect {
+
+    public SybaseDialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
+        super(mappedStatement, parameterObject, pageBounds);
+    }
+
+
+    @Override
+    protected String getLimitString(String sql, String offsetName, int offset, String limitName, int limit) {
+        throw new UnsupportedOperationException("paged queries not supported");
+    }
+
+}

+ 139 - 0
src/main/java/com/zhiqiyun/open/mybatis/paginator/domain/Order.java

@@ -0,0 +1,139 @@
+package com.zhiqiyun.open.mybatis.paginator.domain;
+
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.regex.Pattern;
+
+/**
+ * @author miemiedev
+ */
+public class Order implements Serializable {
+    private static final long serialVersionUID = 8138022018100161833L;
+    private static final String INJECTION_REGEX = "[A-Za-z0-9\\_\\-\\+\\.]+";
+    private Direction direction;
+    private String property;
+    private String orderExpr;
+
+    public Order(String property, Direction direction, String orderExpr) {
+        this.direction = direction;
+        this.property = property;
+        this.orderExpr = orderExpr;
+    }
+
+    public static boolean isSQLInjection(String str) {
+        return !Pattern.matches(INJECTION_REGEX, str);
+    }
+
+    public static List<Order> formString(String orderSegment) {
+        return formString(orderSegment, null);
+    }
+
+    /**
+     * @param orderSegment ex: "id.asc,code.desc" or "code.desc"
+     */
+    public static List<Order> formString(String orderSegment, String orderExpr) {
+        if (orderSegment == null || orderSegment.trim().equals("")) {
+            return new ArrayList<>(0);
+        }
+
+        List<Order> results = new ArrayList<>();
+        String[] orderSegments = orderSegment.trim().split(",");
+        for (String sortSegment : orderSegments) {
+            Order order = _formString(sortSegment, orderExpr);
+            if (order != null) {
+                results.add(order);
+            }
+        }
+        return results;
+    }
+
+    private static Order _formString(String orderSegment, String orderExpr) {
+
+        if (orderSegment == null || orderSegment.trim().equals("") ||
+                orderSegment.startsWith("null.") || orderSegment.startsWith(".")) {
+            return null;
+        }
+
+        String[] array = orderSegment.trim().split("\\.");
+        if (array.length != 1 && array.length != 2) {
+            throw new IllegalArgumentException("orderSegment pattern must be {property}.{direction}, input is: " + orderSegment);
+        }
+
+        return create(array[0], Direction.fromString(array.length == 2 ? array[1] : "asc"), orderExpr);
+    }
+
+    public static Order create(String property, Direction direction) {
+        return create(property, direction, null);
+    }
+
+    /**
+     * @param property
+     * @param direction
+     * @param orderExpr placeholder is "?", in oracle like: "nlssort( ? ,'NLS_SORT=SCHINESE_PINYIN_M')".
+     *                  Warning: you must prevent orderExpr SQL injection.
+     * @return
+     */
+    public static Order create(String property, Direction direction, String orderExpr) {
+        return new Order(property, direction, orderExpr);
+    }
+
+    public Direction getDirection() {
+        return direction;
+    }
+
+    public void setDirection(Direction direction) {
+        this.direction = direction;
+    }
+
+    public String getProperty() {
+        return property;
+    }
+
+    public void setProperty(String property) {
+        this.property = property;
+    }
+
+    public String getOrderExpr() {
+        return orderExpr;
+    }
+
+    public void setOrderExpr(String orderExpr) {
+        this.orderExpr = orderExpr;
+    }
+
+    @Override
+    public String toString() {
+        if (isSQLInjection(property)) {
+            throw new IllegalArgumentException("SQLInjection property: " + property);
+        }
+        if (orderExpr != null && orderExpr.contains("?")) {
+            String[] exprs = orderExpr.split("\\?");
+            if (exprs.length == 2) {
+                return String.format(orderExpr.replaceAll("\\?", "%s"), property) + (direction == null ? "" : " " + direction.name());
+            }
+            return String.format(orderExpr.replaceAll("\\?", "%s"), property, direction == null ? "" : " " + direction.name());
+        }
+        return property + (direction == null ? "" : " " + direction.name());
+    }
+
+
+    /**
+     * PropertyPath implements the pairing of an {@link Direction} and a property. It is used to provide input for
+     *
+     * @author Oliver Gierke
+     */
+    public static enum Direction {
+        ASC, DESC;
+
+        public static Direction fromString(String value) {
+            try {
+                return Direction.valueOf(value.toUpperCase(Locale.US));
+            } catch (Exception e) {
+                return ASC;
+            }
+        }
+    }
+}

+ 99 - 0
src/main/java/com/zhiqiyun/open/mybatis/paginator/domain/PageBounds.java

@@ -0,0 +1,99 @@
+package com.zhiqiyun.open.mybatis.paginator.domain;
+
+import org.apache.ibatis.session.RowBounds;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 分页查询对象
+ *
+ * @author badqiu
+ * @author hunhun
+ * @author miemiedev
+ */
+public class PageBounds extends RowBounds implements Serializable {
+    private final static int NO_PAGE = 1;
+    private static final long serialVersionUID = -6414350656252331011L;
+    private int current = NO_PAGE;
+    private List<Order> orders = new ArrayList<>();
+
+    private int total;
+
+    public PageBounds() {
+    }
+
+    public PageBounds(int current, int limit) {
+        this(current, limit, new ArrayList<>());
+    }
+
+
+    public PageBounds(List<Order> orders) {
+        this(NO_PAGE, NO_ROW_LIMIT, orders);
+    }
+
+
+    public PageBounds(Order... order) {
+        this(NO_PAGE, NO_ROW_LIMIT, order);
+    }
+
+    public PageBounds(int current, int limit, Order... order) {
+        this(current, limit, Arrays.asList(order));
+    }
+
+    public PageBounds(int current, int limit, List<Order> orders) {
+        super(((Math.max(current, 1)) - 1) * limit, limit);
+        this.current = current;
+        this.orders = orders;
+    }
+
+
+    public int getCurrent() {
+        return current;
+    }
+
+
+    public int getTotal() {
+        return total;
+    }
+
+    public void setTotal(int total) {
+        this.total = total;
+    }
+
+    public List<Order> getOrders() {
+        return orders;
+    }
+
+    public void setOrders(List<Order> orders) {
+        this.orders = orders;
+    }
+
+    public PageBounds addOrder(Order order) {
+        this.orders.add(order);
+        return this;
+    }
+
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder("PageBounds{");
+        sb.append("current=").append(current);
+        sb.append(", limit=").append(this.getLimit());
+        sb.append(", offset=").append(this.getOffset());
+        sb.append(", orders=").append(orders);
+        sb.append('}');
+        return sb.toString();
+    }
+
+
+    public <E> PageResult<E> newPageResult(List<E> listData) {
+        PageResult<E> pageResult = new PageResult<>();
+        pageResult.setPageBounds(this);
+        pageResult.setData(listData);
+        return pageResult;
+    }
+
+}

+ 45 - 0
src/main/java/com/zhiqiyun/open/mybatis/paginator/domain/PageResult.java

@@ -0,0 +1,45 @@
+package com.zhiqiyun.open.mybatis.paginator.domain;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author jtoms
+ */
+@Data
+public class PageResult<T> implements Serializable {
+
+    private static final long serialVersionUID = -2857504782717596783L;
+
+    private int pageSize;
+    private int current;
+    private int total;
+
+    private List<T> data;
+
+    public PageResult<T> setData(List<T> data) {
+        this.data = data;
+        return this;
+    }
+
+    public PageResult<T> setPageBounds(PageBounds bounds) {
+        this.pageSize = bounds.getLimit();
+        this.current = bounds.getCurrent();
+        this.total = bounds.getTotal();
+        return this;
+    }
+
+    public int getTotalPages() {
+        if (this.getPageSize() == 0) {
+            return 0;
+        } else {
+            int totalPages = this.getTotal() / this.getPageSize();
+            if (this.getTotal() % this.getPageSize() != 0L) {
+                ++totalPages;
+            }
+            return totalPages;
+        }
+    }
+}

+ 94 - 0
src/main/java/com/zhiqiyun/open/mybatis/paginator/support/DefaultParameterHandler.java

@@ -0,0 +1,94 @@
+/*
+ *    Copyright 2009-2012 The MyBatis Team
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+package com.zhiqiyun.open.mybatis.paginator.support;
+
+import org.apache.ibatis.executor.ErrorContext;
+import org.apache.ibatis.executor.ExecutorException;
+import org.apache.ibatis.executor.parameter.ParameterHandler;
+import org.apache.ibatis.mapping.BoundSql;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.mapping.ParameterMapping;
+import org.apache.ibatis.mapping.ParameterMode;
+import org.apache.ibatis.reflection.MetaObject;
+import org.apache.ibatis.session.Configuration;
+import org.apache.ibatis.type.JdbcType;
+import org.apache.ibatis.type.TypeHandler;
+import org.apache.ibatis.type.TypeHandlerRegistry;
+
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.List;
+
+
+/**
+ * @author jtoms
+ */
+public class DefaultParameterHandler implements ParameterHandler {
+
+    private final TypeHandlerRegistry typeHandlerRegistry;
+
+    private final MappedStatement mappedStatement;
+    private final Object parameterObject;
+    private BoundSql boundSql;
+    private Configuration configuration;
+
+    public DefaultParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
+        this.mappedStatement = mappedStatement;
+        this.configuration = mappedStatement.getConfiguration();
+        this.typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry();
+        this.parameterObject = parameterObject;
+        this.boundSql = boundSql;
+    }
+
+    @Override
+    public Object getParameterObject() {
+        return parameterObject;
+    }
+
+    @Override
+    public void setParameters(PreparedStatement ps) throws SQLException {
+        ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
+        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
+        if (parameterMappings != null) {
+            MetaObject metaObject = parameterObject == null ? null : configuration.newMetaObject(parameterObject);
+            for (int i = 0; i < parameterMappings.size(); i++) {
+                ParameterMapping parameterMapping = parameterMappings.get(i);
+                if (parameterMapping.getMode() != ParameterMode.OUT) {
+                    Object value;
+                    String propertyName = parameterMapping.getProperty();
+                    // issue #448 ask first for additional params
+                    if (boundSql.hasAdditionalParameter(propertyName)) {
+                        value = boundSql.getAdditionalParameter(propertyName);
+                    } else if (parameterObject == null) {
+                        value = null;
+                    } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
+                        value = parameterObject;
+                    } else {
+                        value = metaObject == null ? null : metaObject.getValue(propertyName);
+                    }
+                    TypeHandler typeHandler = parameterMapping.getTypeHandler();
+                    if (typeHandler == null) {
+                        throw new ExecutorException("There was no TypeHandler found for parameter " + propertyName + " of statement " + mappedStatement.getId());
+                    }
+                    JdbcType jdbcType = parameterMapping.getJdbcType();
+                    if (value == null && jdbcType == null) jdbcType = configuration.getJdbcTypeForNull();
+                    typeHandler.setParameter(ps, i + 1, value, jdbcType);
+                }
+            }
+        }
+    }
+
+}

+ 408 - 0
src/main/java/com/zhiqiyun/open/mybatis/paginator/support/PropertiesHelper.java

@@ -0,0 +1,408 @@
+package com.zhiqiyun.open.mybatis.paginator.support;
+
+import java.io.*;
+import java.util.*;
+import java.util.Map.Entry;
+
+/**
+ * Properties的操作的工具类,为Properties提供一个代理增加相关工具方法如 getRequiredString(),getInt(),getBoolean()等方法
+ * 并可以通过systemPropertiesMode属性指定是否搜索System.getProperty()及System.getenv()来查找值.
+ * 默认不搜索系统属性
+ * 
+ * <pre>
+ * 使用1:
+ * public class ConnectionUtils {
+ *     static Properties properties = new Properties(); 
+ *     // ... do load properties 
+ *     
+ *     // delegate to properties
+ * 	   static PropertiesHelper props = new PropertiesHelper(properties);
+ *     public static Connection getConnection() {
+ *     		// use getRequiredProperty() 
+ *     		DriverManager.getConnection(props.getRequiredString("jdbc.url"));
+ *     }
+ * }
+ * 指定是否搜索系统属性:
+ * new PropertiesHelper(properties,PropertiesHelper.SYSTEM_PROPERTIES_MODE_OVERRIDE)
+ * </pre>
+ * @author badqiu
+ */
+public class PropertiesHelper {
+	/** Never check system properties. */
+	public static final int SYSTEM_PROPERTIES_MODE_NEVER = 0;
+
+	/**
+	 * Check system properties if not resolvable in the specified properties.
+	 * This is the default.
+	 */
+	public static final int SYSTEM_PROPERTIES_MODE_FALLBACK = 1;
+
+	/**
+	 * Check system properties first, before trying the specified properties.
+	 * This allows system properties to override any other property source.
+	 */
+	public static final int SYSTEM_PROPERTIES_MODE_OVERRIDE = 2;
+	
+	private int systemPropertiesMode = SYSTEM_PROPERTIES_MODE_NEVER;
+	private Properties p;
+
+	public PropertiesHelper(Properties p) {
+		setProperties(p);
+	}
+	
+	public PropertiesHelper(Properties p, int systemPropertiesMode) {
+		setProperties(p);
+		if(systemPropertiesMode != SYSTEM_PROPERTIES_MODE_NEVER && systemPropertiesMode != SYSTEM_PROPERTIES_MODE_FALLBACK && systemPropertiesMode != SYSTEM_PROPERTIES_MODE_OVERRIDE) {
+			throw new IllegalArgumentException("error systemPropertiesMode mode:"+systemPropertiesMode);
+		}
+		this.systemPropertiesMode = systemPropertiesMode;
+	}
+	
+	public Properties getProperties() {
+		return p;
+	}
+	
+	public void setProperties(Properties props) {
+		if(props == null) throw new IllegalArgumentException("properties must be not null");
+		this.p = props;
+	}
+	
+	public String getRequiredString(String key) {
+		String value = getProperty(key);
+		if(isBlankString(value)) {
+			throw new IllegalStateException("required property is blank by key="+key);
+		}
+		return value;
+	}
+	
+	public String getNullIfBlank(String key) {
+		String value = getProperty(key);
+		if(isBlankString(value)) {
+			return null;
+		}
+		return value;
+	}
+	
+	public String getNullIfEmpty(String key) {
+		String value = getProperty(key);
+		if(value == null || "".equals(value)) {
+			return null;
+		}
+		return value;
+	}
+	
+	/**
+	 * 尝试从System.getProperty(key)及System.getenv(key)得到值
+	 * @return
+	 */
+	public String getAndTryFromSystem(String key) {
+		String value = getProperty(key);
+		if(isBlankString(value)) {
+			value = getSystemProperty(key);
+		}
+		return value;
+	}
+
+	private String getSystemProperty(String key) {
+		String value;
+		value = System.getProperty(key);
+		if(isBlankString(value)) {
+			value = System.getenv(key);
+		}
+		return value;
+	}
+	
+	public Integer getInteger(String key) {
+		String v = getProperty(key);
+		if(v == null){
+			return null;
+		}
+		return Integer.parseInt(v);
+	}
+	
+	public int getInt(String key,int defaultValue) {
+		if(getProperty(key) == null) {
+			return defaultValue;
+		}
+		return Integer.parseInt(getRequiredString(key));
+	}
+	
+	public int getRequiredInt(String key) {
+		return Integer.parseInt(getRequiredString(key));
+	}
+	
+	public Long getLong(String key) {
+		if(getProperty(key) == null) {
+			return null;
+		}
+		return Long.parseLong(getRequiredString(key));
+	}
+	
+	public long getLong(String key,long defaultValue) {
+		if(getProperty(key) == null) {
+			return defaultValue;
+		}
+		return Long.parseLong(getRequiredString(key));
+	}
+	
+	public Long getRequiredLong(String key) {
+		return Long.parseLong(getRequiredString(key));
+	}
+	
+	public Boolean getBoolean(String key) {
+		if(getProperty(key) == null) {
+			return null;
+		}
+		return Boolean.parseBoolean(getRequiredString(key));
+	}
+	
+	public boolean getBoolean(String key,boolean defaultValue) {
+		if(getProperty(key) == null) {
+			return defaultValue;
+		}
+		return Boolean.parseBoolean(getRequiredString(key));
+	}
+	
+	public boolean getRequiredBoolean(String key) {
+		return Boolean.parseBoolean(getRequiredString(key));
+	}
+	
+	public Float getFloat(String key) {
+		if(getProperty(key) == null) {
+			return null;
+		}
+		return Float.parseFloat(getRequiredString(key));
+	}
+	
+	public float getFloat(String key,float defaultValue) {
+		if(getProperty(key) == null) {
+			return defaultValue;
+		}
+		return Float.parseFloat(getRequiredString(key));
+	}
+	
+	public Float getRequiredFloat(String key) {
+		return Float.parseFloat(getRequiredString(key));
+	}
+	
+	public Double getDouble(String key) {
+		if(getProperty(key) == null) {
+			return null;
+		}
+		return Double.parseDouble(getRequiredString(key));
+	}
+	
+	public double getDouble(String key,double defaultValue) {
+		if(getProperty(key) == null) {
+			return defaultValue;
+		}
+		return Double.parseDouble(getRequiredString(key));
+	}
+	
+	public Double getRequiredDouble(String key) {
+		return Double.parseDouble(getRequiredString(key));
+	}
+	
+	/** setProperty(String key,int value) ... start */
+	
+	public Object setProperty(String key,int value) {
+		return setProperty(key, String.valueOf(value));
+	}
+	
+	public Object setProperty(String key,long value) {
+		return setProperty(key, String.valueOf(value));
+	}
+	
+	public Object setProperty(String key,float value) {
+		return setProperty(key, String.valueOf(value));
+	}
+	
+	public Object setProperty(String key,double value) {
+		return setProperty(key, String.valueOf(value));
+	}
+	
+	public Object setProperty(String key,boolean value) {
+		return setProperty(key, String.valueOf(value));
+	}
+
+	public String[] getStringArray(String key) {
+		String v = getProperty(key);
+		if(v == null) {
+			return new String[0];
+		}else {
+		    return tokenizeToStringArray(v, ", \t\n\r\f");
+		}
+	}
+
+	public int[] getIntArray(String key) {
+		return toIntArray(getStringArray(key));
+	}
+
+	public Properties getStartsWithProperties(String prefix) {
+		if(prefix == null) throw new IllegalArgumentException("'prefix' must be not null");
+		
+		Properties props = getProperties();
+		Properties result = new Properties();
+		for(Entry<Object, Object> entry : props.entrySet()) {
+			String key = (String)entry.getKey();
+			if(key != null && key.startsWith(prefix)) {
+				result.put(key.substring(prefix.length()), entry.getValue());
+			}
+		}
+		return result;
+	}
+	
+	/** delegate method start */
+	
+	public String getProperty(String key, String defaultValue) {
+	    String value = getProperty(key);
+	    if(isBlankString(value)) {
+	        return defaultValue;
+	    }
+		return value;
+	}
+
+	public String getProperty(String key) {
+		String propVal = null;
+		if (systemPropertiesMode == SYSTEM_PROPERTIES_MODE_OVERRIDE) {
+			propVal = getSystemProperty(key);
+		}
+		if (propVal == null) {
+			propVal = p.getProperty(key);
+		}
+		if (propVal == null && systemPropertiesMode == SYSTEM_PROPERTIES_MODE_FALLBACK) {
+			propVal = getSystemProperty(key);
+		}
+		return propVal;
+	}
+
+	public Object setProperty(String key,String value) {
+		return p.setProperty(key, value);
+	}
+
+	public void clear() {
+		p.clear();
+	}
+
+	public Set<Entry<Object, Object>> entrySet() {
+		return p.entrySet();
+	}
+
+	public Enumeration<?> propertyNames() {
+		return p.propertyNames();
+	}
+
+	public boolean contains(Object value) {
+		return p.contains(value);
+	}
+
+	public boolean containsKey(Object key) {
+		return p.containsKey(key);
+	}
+
+	public boolean containsValue(Object value) {
+		return p.containsValue(value);
+	}
+
+	public Enumeration<Object> elements() {
+		return p.elements();
+	}
+
+	public Object get(Object key) {
+		return p.get(key);
+	}
+
+	public boolean isEmpty() {
+		return p.isEmpty();
+	}
+
+	public Enumeration<Object> keys() {
+		return p.keys();
+	}
+
+	public Set<Object> keySet() {
+		return p.keySet();
+	}
+
+	public void list(PrintStream out) {
+		p.list(out);
+	}
+
+	public void list(PrintWriter out) {
+		p.list(out);
+	}
+
+	public void load(InputStream inStream) throws IOException {
+		p.load(inStream);
+	}
+
+	public void loadFromXML(InputStream in) throws IOException,
+			InvalidPropertiesFormatException {
+		p.loadFromXML(in);
+	}
+
+	public Object put(Object key, Object value) {
+		return p.put(key, value);
+	}
+
+	public void putAll(Map<? extends Object, ? extends Object> t) {
+		p.putAll(t);
+	}
+
+	public Object remove(Object key) {
+		return p.remove(key);
+	}
+
+	/** @deprecated */
+	public void save(OutputStream out, String comments) {
+		p.save(out, comments);
+	}
+
+	public int size() {
+		return p.size();
+	}
+
+	public void store(OutputStream out, String comments) throws IOException {
+		p.store(out, comments);
+	}
+
+	public void storeToXML(OutputStream os, String comment, String encoding)
+			throws IOException {
+		p.storeToXML(os, comment, encoding);
+	}
+
+	public void storeToXML(OutputStream os, String comment) throws IOException {
+		p.storeToXML(os, comment);
+	}
+
+	public Collection<Object> values() {
+		return p.values();
+	}
+	
+	public String toString() {
+		return p.toString();
+	}
+
+	private static boolean isBlankString(String value) {
+		return value == null || "".equals(value.trim());
+	}
+	
+	private static String[] tokenizeToStringArray(String str,String seperators) {
+		StringTokenizer tokenlizer = new StringTokenizer(str,seperators);
+		List result = new ArrayList();
+		
+		while(tokenlizer.hasMoreElements()) {
+			Object s = tokenlizer.nextElement();
+			result.add(s);
+		}
+		return (String[])result.toArray(new String[result.size()]);
+	}
+	
+	private static int[] toIntArray(String[] array) {
+		int[] result = new int[array.length];
+		for(int i = 0; i < array.length; i++) {
+			result[i] = Integer.parseInt(array[i]);
+		}
+		return result;
+	}
+}

+ 69 - 0
src/main/java/com/zhiqiyun/open/mybatis/paginator/support/SQLHelp.java

@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2012-2013, Poplar Yfyang 杨友峰 (poplar1123@gmail.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.zhiqiyun.open.mybatis.paginator.support;
+
+import com.zhiqiyun.open.mybatis.paginator.dialect.Dialect;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.ibatis.mapping.BoundSql;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.transaction.Transaction;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * @author poplar.yfyang
+ * @author miemiedev
+ */
+@Slf4j
+public class SQLHelp {
+
+    /**
+     * 查询总纪录数
+     *
+     * @param mappedStatement mapped
+     * @param parameterObject 参数
+     * @param boundSql        boundSql
+     * @param dialect         database dialect
+     * @return 总记录数
+     * @throws SQLException sql查询错误
+     */
+    public static int getCount(
+            final MappedStatement mappedStatement, final Transaction transaction, final Object parameterObject,
+            final BoundSql boundSql, Dialect dialect) throws SQLException {
+        final String count_sql = dialect.getCountSQL();
+        log.debug("Total count SQL [{}] ", count_sql);
+        log.debug("Total count Parameters: {} ", parameterObject);
+
+        Connection connection = transaction.getConnection();
+        PreparedStatement countStmt = connection.prepareStatement(count_sql);
+        DefaultParameterHandler handler = new DefaultParameterHandler(mappedStatement, parameterObject, boundSql);
+        handler.setParameters(countStmt);
+
+        ResultSet rs = countStmt.executeQuery();
+        int count = 0;
+        if (rs.next()) {
+            count = rs.getInt(1);
+        }
+        log.debug("Total count: {}", count);
+        return count;
+
+    }
+
+}

+ 46 - 0
src/main/java/com/zhiqiyun/open/mybatis/typeHandler/FastjsonTypeHandler.java

@@ -0,0 +1,46 @@
+package com.zhiqiyun.open.mybatis.typeHandler;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.TypeReference;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.ibatis.type.BaseTypeHandler;
+import org.apache.ibatis.type.JdbcType;
+import org.apache.ibatis.type.MappedJdbcTypes;
+import org.apache.ibatis.type.MappedTypes;
+
+import java.sql.CallableStatement;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+@Slf4j
+@MappedTypes({Object.class})
+@MappedJdbcTypes({JdbcType.VARCHAR})
+public class FastjsonTypeHandler<E> extends BaseTypeHandler<E> {
+
+    private E parse(String jsonValue) {
+        return jsonValue != null && jsonValue.length() != 0 ? JSON.parseObject(jsonValue, new TypeReference<E>() {
+        }) : null;
+    }
+
+    @Override
+    public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
+        ps.setString(i, JSON.toJSONString(parameter));
+    }
+
+
+    @Override
+    public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
+        return this.parse(rs.getString(columnName));
+    }
+
+    @Override
+    public E getNullableResult(ResultSet rs, int i) throws SQLException {
+        return this.parse(rs.getString(i));
+    }
+
+    @Override
+    public E getNullableResult(CallableStatement cs, int i) throws SQLException {
+        return this.parse(cs.getString(i));
+    }
+}

+ 75 - 0
src/main/java/com/zhiqiyun/open/mybatis/typeHandler/IEnumTypeHandler.java

@@ -0,0 +1,75 @@
+package com.zhiqiyun.open.mybatis.typeHandler;
+
+import com.zhiqiyun.open.enmus.IEnum;
+import org.apache.ibatis.type.BaseTypeHandler;
+import org.apache.ibatis.type.JdbcType;
+
+import java.sql.CallableStatement;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * @author jtoms
+ */
+public class IEnumTypeHandler<E extends IEnum<Integer>> extends BaseTypeHandler<E> {
+
+    private final Class<E> type;
+
+    public IEnumTypeHandler(Class<E> type) {
+        if (type == null) {
+            throw new IllegalArgumentException("Type argument cannot be null");
+        }
+        this.type = type;
+    }
+
+    @Override
+    public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
+        ps.setInt(i, parameter.getValue());
+    }
+
+    @Override
+    public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
+        int i = rs.getInt(columnName);
+        if (rs.wasNull()) {
+            return null;
+        } else {
+            return this.getEnum(i);
+        }
+    }
+
+    @Override
+    public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
+        int i = rs.getInt(columnIndex);
+        if (rs.wasNull()) {
+            return null;
+        } else {
+            return this.getEnum(i);
+        }
+    }
+
+    @Override
+    public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
+        int i = cs.getInt(columnIndex);
+        if (cs.wasNull()) {
+            return null;
+        } else {
+            return this.getEnum(i);
+        }
+    }
+
+    public E getEnum(int value) {
+        E[] enums = this.type.getEnumConstants();
+        E em = null;
+        if (enums != null) {
+            for (E e : enums) {
+                if (e.getValue() == value) {
+                    em = e;
+                    break;
+                }
+            }
+        }
+        return em;
+    }
+
+}

+ 20 - 0
src/main/java/com/zhiqiyun/open/service/AuthorityInfoService.java

@@ -0,0 +1,20 @@
+package com.zhiqiyun.open.service;
+
+
+import com.zhiqiyun.open.models.AuthorityInfo;
+
+import java.util.List;
+
+/**
+ * @author shenyj
+ * @date 17-3-24
+ */
+public interface AuthorityInfoService {
+    /**
+     * 查询下级ID
+     *
+     * @param parentId
+     * @return
+     */
+    List<AuthorityInfo> findChildren(Long parentId);
+}

+ 11 - 0
src/main/java/com/zhiqiyun/open/service/Ip2RegionService.java

@@ -0,0 +1,11 @@
+package com.zhiqiyun.open.service;
+
+public interface Ip2RegionService {
+    /**
+     * 查询IP所在地区
+     *
+     * @param ipAddress
+     * @return
+     */
+    String getRegion(String ipAddress);
+}

+ 42 - 0
src/main/java/com/zhiqiyun/open/service/OauthService.java

@@ -0,0 +1,42 @@
+package com.zhiqiyun.open.service;
+
+
+import com.zhiqiyun.open.models.OauthInfo;
+
+/**
+ * @author jtoms
+ */
+public interface OauthService {
+
+    /**
+     * 生成密码
+     *
+     * @param loginPwd
+     * @param secret
+     * @return
+     */
+    String generatePassword(String loginPwd, String secret);
+
+    /**
+     * 保存用户登录信息
+     *
+     * @param accessToken
+     * @param oauthInfo
+     */
+    void setAuth(String accessToken, OauthInfo oauthInfo);
+
+    /**
+     * 获取用户登录信息
+     *
+     * @param accessToken
+     * @return
+     */
+    OauthInfo getAuth(String accessToken);
+
+    /**
+     * 销毁用户登录信息
+     *
+     * @param accessToken
+     */
+    void destroy(String accessToken);
+}

+ 58 - 0
src/main/java/com/zhiqiyun/open/service/RoleInfoService.java

@@ -0,0 +1,58 @@
+package com.zhiqiyun.open.service;
+
+import com.zhiqiyun.open.mybatis.paginator.domain.PageBounds;
+import com.zhiqiyun.open.mybatis.paginator.domain.PageResult;
+import com.zhiqiyun.open.models.RoleInfo;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author jtoms
+ */
+public interface RoleInfoService {
+    /**
+     * 更新角色信息
+     *
+     * @param roleInfo
+     */
+    void updateById(RoleInfo roleInfo);
+
+    /**
+     * 插入角色信息
+     *
+     * @param roleInfo
+     */
+    void insert(RoleInfo roleInfo);
+
+    /**
+     * 删除系统角色
+     *
+     * @param roleIds
+     * @throws Exception
+     */
+    void deleteByIds(List<Long> roleIds) throws Exception;
+
+    /**
+     * 查询角色拥有的权限值
+     *
+     * @param roleId
+     * @return
+     */
+    List<Long> findAuthorities(Long roleId);
+
+    /**
+     * 保存角色的权限值
+     *
+     * @param roleId
+     * @param authorities
+     */
+    void saveAuthorities(Long roleId, Long[] authorities) throws Exception;
+
+    /**
+     * 分页查询角色列表
+     *
+     * @return
+     */
+    PageResult<RoleInfo> findPage(PageBounds bounds, Map<String, Object> queryWrapper);
+}

+ 10 - 0
src/main/java/com/zhiqiyun/open/service/SequenceService.java

@@ -0,0 +1,10 @@
+package com.zhiqiyun.open.service;
+
+public interface SequenceService {
+    /**
+     * 生成下一个序列号
+     *
+     * @return 序列号
+     */
+    Long nextId();
+}

+ 166 - 0
src/main/java/com/zhiqiyun/open/service/UserBaseInfoService.java

@@ -0,0 +1,166 @@
+package com.zhiqiyun.open.service;
+
+import com.zhiqiyun.open.enmus.AccountType;
+import com.zhiqiyun.open.enmus.PasswordType;
+import com.zhiqiyun.open.models.*;
+import com.zhiqiyun.open.mybatis.paginator.domain.PageBounds;
+import com.zhiqiyun.open.mybatis.paginator.domain.PageResult;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Administrator
+ * @date 2017-6-5
+ */
+public interface UserBaseInfoService {
+    /**
+     * 查询用户基本信息
+     *
+     * @param id
+     * @return
+     */
+    UserBaseInfo findById(Long id);
+
+    /**
+     * 分页查询用户基本信息
+     *
+     * @param bounds
+     * @param queryWrapper
+     * @return
+     */
+    PageResult<UserBaseInfo> findPage(PageBounds bounds, Map<String, Object> queryWrapper);
+
+    /**
+     * 更新用户基本信息
+     *
+     * @param userInfo
+     */
+    void updateById(UserBaseInfo userInfo);
+
+    /**
+     * 查询用户单个的登录账号
+     *
+     * @param loginAccount
+     * @param accountType
+     * @return
+     */
+    UserLoginAccount findLoginAccount(String loginAccount, AccountType accountType);
+
+    /**
+     * 查询用户登录密码
+     *
+     * @param uid
+     * @param passwordType
+     * @return
+     */
+    UserPassword findPassword(Long uid, PasswordType passwordType);
+
+    /**
+     * 查询用户所拥有的权限
+     *
+     * @param uid
+     * @return
+     */
+    List<String> findUserAuthorities(Long uid);
+
+    /**
+     * 查询用户所拥有的权限
+     *
+     * @param uid
+     * @return
+     */
+    List<RoleInfo> findRoles(Long uid);
+
+
+    /**
+     * 查询用户名下所有账号
+     *
+     * @param uid
+     * @return
+     */
+    List<UserLoginAccount> findLoginAccounts(Long uid);
+
+    /**
+     * 添加或者修改用户基本信息
+     *
+     * @param userInfo
+     * @param loginAccounts
+     * @return
+     * @throws Exception
+     */
+    String insertOrUpdate(UserBaseInfo userInfo, List<UserLoginAccount> loginAccounts) throws Exception;
+
+    /**
+     * 设置用户的角色
+     *
+     * @param uid
+     * @param roles
+     * @throws Exception
+     */
+    void saveRoles(Long uid, Long[] roles) throws Exception;
+
+    /**
+     * 插入日志信息
+     *
+     * @param userOperateLog
+     */
+    void insertOperateLog(UserOperateLog userOperateLog);
+
+    /**
+     * 更新日志信息
+     *
+     * @param userOperateLog
+     */
+    void updateOperateLogById(UserOperateLog userOperateLog);
+
+    /**
+     * 插入用户登录日志
+     *
+     * @param userLoginLog
+     */
+    void insertLoginLog(UserLoginLog userLoginLog);
+
+    /**
+     * 查询用户登录日志
+     *
+     * @param bounds
+     * @param uid
+     * @return
+     */
+    PageResult<UserLoginLog> findLoginLogPage(PageBounds bounds, Long uid);
+
+    /**
+     * 更新用户密码
+     *
+     * @param uid
+     * @param password
+     * @param salt
+     * @param passwordType
+     */
+    void updatePassword(Long uid, String password, String salt, PasswordType passwordType);
+
+    /**
+     * 更新用户基本信息
+     *
+     * @param uid
+     * @param userBaseInfo
+     */
+    void updateBaseInfo(Long uid, UserBaseInfo userBaseInfo);
+
+    /**
+     * 更新用户登录账号
+     *
+     * @param uid
+     * @param account
+     */
+    void updateLoginAccount(Long uid, String account, AccountType accountType);
+
+    /**
+     * 查询搜索账号
+     *
+     * @param searchKey
+     * @return
+     */
+    List<Map<String, Object>> findSelectAccounts(String searchKey);
+}

+ 55 - 0
src/main/java/com/zhiqiyun/open/service/impl/BaseOauthService.java

@@ -0,0 +1,55 @@
+package com.zhiqiyun.open.service.impl;
+
+
+import com.zhiqiyun.open.models.OauthInfo;
+import com.zhiqiyun.open.service.OauthService;
+import org.apache.commons.codec.digest.DigestUtils;
+
+/**
+ * @author jtoms
+ */
+public abstract class BaseOauthService implements OauthService {
+
+
+    /**
+     * 生成密码
+     *
+     * @param loginPwd
+     * @param secret
+     * @return
+     */
+    @Override
+    public String generatePassword(String loginPwd, String secret) {
+        if (loginPwd == null) {
+            return "";
+        }
+        loginPwd = DigestUtils.sha256Hex(loginPwd);
+        return DigestUtils.md5Hex(loginPwd + "@" + secret);
+    }
+
+    /**
+     * 保存用户登录信息
+     *
+     * @param accessToken
+     * @param oauthInfo
+     */
+    @Override
+    public abstract void setAuth(String accessToken, OauthInfo oauthInfo);
+
+    /**
+     * 获取用户登录信息
+     *
+     * @param accessToken
+     * @return
+     */
+    @Override
+    public abstract OauthInfo getAuth(String accessToken);
+
+    /**
+     * 销毁用户登录信息
+     *
+     * @param accessToken
+     */
+    @Override
+    public abstract void destroy(String accessToken);
+}

+ 30 - 0
src/main/java/com/zhiqiyun/open/service/impl/Ip2RegionServiceImpl.java

@@ -0,0 +1,30 @@
+package com.zhiqiyun.open.service.impl;
+
+import com.zhiqiyun.open.service.Ip2RegionService;
+import lombok.extern.slf4j.Slf4j;
+import org.lionsoul.ip2region.DataBlock;
+import org.lionsoul.ip2region.DbSearcher;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+
+@Slf4j
+@Service
+public class Ip2RegionServiceImpl implements Ip2RegionService {
+
+    @Autowired
+    private DbSearcher dbSearcher;
+
+    @Override
+    public String getRegion(String ipAddress) {
+        String ipRegion = "未知地址";
+        try {
+            DataBlock dataBlock = dbSearcher.memorySearch(ipAddress);
+            ipRegion = dataBlock.getRegion();
+        } catch (IOException e) {
+            log.warn("get IP Address", e);
+        }
+        return ipRegion;
+    }
+}

+ 24 - 0
src/main/java/com/zhiqiyun/open/service/impl/OauthAuthorityInfoServiceImpl.java

@@ -0,0 +1,24 @@
+package com.zhiqiyun.open.service.impl;
+
+import com.zhiqiyun.open.mapper.AuthorityInfoMapper;
+import com.zhiqiyun.open.models.AuthorityInfo;
+import com.zhiqiyun.open.service.AuthorityInfoService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * @author jtoms
+ */
+@Service
+public class OauthAuthorityInfoServiceImpl implements AuthorityInfoService {
+
+    @Autowired
+    private AuthorityInfoMapper authorityInfoMapper;
+
+    @Override
+    public List<AuthorityInfo> findChildren(Long parentId) {
+        return authorityInfoMapper.findChildren(parentId);
+    }
+}

+ 71 - 0
src/main/java/com/zhiqiyun/open/service/impl/OauthRoleInfoServiceImpl.java

@@ -0,0 +1,71 @@
+package com.zhiqiyun.open.service.impl;
+
+import com.zhiqiyun.open.exception.ServiceException;
+import com.zhiqiyun.open.mapper.RoleInfoMapper;
+import com.zhiqiyun.open.models.RoleInfo;
+import com.zhiqiyun.open.mybatis.paginator.domain.PageBounds;
+import com.zhiqiyun.open.mybatis.paginator.domain.PageResult;
+import com.zhiqiyun.open.service.RoleInfoService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author jtoms
+ */
+@Service
+public class OauthRoleInfoServiceImpl implements RoleInfoService {
+
+    @Autowired
+    private RoleInfoMapper roleInfoMapper;
+
+    @Override
+    public void updateById(RoleInfo roleInfo) {
+        this.roleInfoMapper.updateById(roleInfo);
+    }
+
+    @Override
+    public void insert(RoleInfo roleInfo) {
+        this.roleInfoMapper.insert(roleInfo);
+    }
+
+    @Override
+    @Transactional(rollbackFor = ServiceException.class)
+    public void deleteByIds(List<Long> roleIds) throws ServiceException {
+        try {
+            this.roleInfoMapper.deleteAuthorities(roleIds);
+            this.roleInfoMapper.deleteBatchIds(roleIds);
+        } catch (Exception e) {
+            throw new ServiceException(e);
+        }
+    }
+
+    @Override
+    public List<Long> findAuthorities(Long roleId) {
+        return this.roleInfoMapper.findAuthorities(roleId);
+    }
+
+    @Override
+    @Transactional(rollbackFor = ServiceException.class)
+    public void saveAuthorities(Long roleId, Long[] authorities) throws ServiceException {
+        try {
+            this.roleInfoMapper.deleteAuthorities(Collections.singletonList(roleId));
+            if (authorities != null && authorities.length > 0) {
+                this.roleInfoMapper.insertAuthority(roleId, authorities);
+            }
+        } catch (Exception e) {
+            throw new ServiceException(e);
+        }
+    }
+
+    @Override
+    public PageResult<RoleInfo> findPage(PageBounds bounds, Map<String, Object> queryWrapper) {
+        List<RoleInfo> listData = this.roleInfoMapper.findPage(bounds, queryWrapper);
+
+        return bounds.newPageResult(listData);
+    }
+}

+ 61 - 0
src/main/java/com/zhiqiyun/open/service/impl/OauthServiceRedisImpl.java

@@ -0,0 +1,61 @@
+package com.zhiqiyun.open.service.impl;
+
+import com.zhiqiyun.open.models.OauthInfo;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.data.redis.core.BoundValueOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.concurrent.TimeUnit;
+
+@Slf4j
+@Service
+public class OauthServiceRedisImpl extends BaseOauthService {
+
+    @Resource
+    private RedisTemplate<String, OauthInfo> redisTemplate;
+
+    private final String OAUTH_INFO_KEY = "OAUTH_INFO:%s";
+
+    @Override
+    public void setAuth(String accessToken, OauthInfo oauthInfo) {
+        try {
+            String redisKey = String.format(OAUTH_INFO_KEY, accessToken);
+            this.redisTemplate.boundValueOps(redisKey).set(oauthInfo, 30, TimeUnit.DAYS);
+        } catch (Exception e) {
+            log.error("save oauth error", e);
+        }
+
+    }
+
+    @Override
+    public OauthInfo getAuth(String accessToken) {
+        try {
+            if (StringUtils.isBlank(accessToken)) {
+                return null;
+            }
+            String redisKey = String.format(OAUTH_INFO_KEY, accessToken);
+
+            BoundValueOperations<String, OauthInfo> boundValueOperations = this.redisTemplate.boundValueOps(redisKey);
+            boundValueOperations.expire(30, TimeUnit.DAYS);
+            OauthInfo oauthInfo = boundValueOperations.get();
+            if (oauthInfo != null && accessToken.equals(oauthInfo.getAccessToken())) {
+                return oauthInfo;
+            }
+        } catch (Exception e) {
+            log.error("get oauth error", e);
+        }
+        return null;
+    }
+
+
+    @Override
+    public void destroy(String accessToken) {
+        //销毁登录信息
+        String redisKey = String.format(OAUTH_INFO_KEY, accessToken);
+
+        this.redisTemplate.delete(redisKey);
+    }
+}

+ 33 - 0
src/main/java/com/zhiqiyun/open/service/impl/SequenceServiceImpl.java

@@ -0,0 +1,33 @@
+package com.zhiqiyun.open.service.impl;
+
+import com.zhiqiyun.open.mapper.SequenceMapper;
+import com.zhiqiyun.open.models.Sequence;
+import com.zhiqiyun.open.service.SequenceService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.time.DateFormatUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.Random;
+
+@Slf4j
+@Service
+public class SequenceServiceImpl implements SequenceService {
+
+    @Autowired
+    private SequenceMapper sequenceMapper;
+
+    private final Random random = new Random();
+
+    @Override
+    public Long nextId() {
+        Sequence sequence = new Sequence();
+        Integer saltRandom = random.nextInt(9);
+        sequence.setSaltRandom(saltRandom);
+        sequence.setCreatedTime(new Date());
+        this.sequenceMapper.generateNextId(sequence);
+        String idString = String.format("%s%05d%s", DateFormatUtils.format(sequence.getCreatedTime(), "yyMMdd"), sequence.getId(), saltRandom);
+        return Long.valueOf(idString);
+    }
+}

+ 191 - 0
src/main/java/com/zhiqiyun/open/service/impl/UserBaseInfoServiceImpl.java

@@ -0,0 +1,191 @@
+package com.zhiqiyun.open.service.impl;
+
+import com.zhiqiyun.open.enmus.AccountType;
+import com.zhiqiyun.open.enmus.PasswordType;
+import com.zhiqiyun.open.enmus.UserState;
+import com.zhiqiyun.open.exception.ServiceException;
+import com.zhiqiyun.open.mapper.UserBaseInfoMapper;
+import com.zhiqiyun.open.mapper.UserLoginAccountMapper;
+import com.zhiqiyun.open.mapper.UserPasswordMapper;
+import com.zhiqiyun.open.models.*;
+import com.zhiqiyun.open.mybatis.paginator.domain.PageBounds;
+import com.zhiqiyun.open.mybatis.paginator.domain.PageResult;
+import com.zhiqiyun.open.service.Ip2RegionService;
+import com.zhiqiyun.open.service.OauthService;
+import com.zhiqiyun.open.service.SequenceService;
+import com.zhiqiyun.open.service.UserBaseInfoService;
+import com.zhiqiyun.open.utils.DateUtil;
+import com.zhiqiyun.open.utils.RandomUtil;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author jtoms
+ */
+@Service
+public class UserBaseInfoServiceImpl implements UserBaseInfoService {
+
+    @Autowired
+    private UserBaseInfoMapper userBaseInfoMapper;
+
+    @Autowired
+    private UserLoginAccountMapper userLoginAccountMapper;
+
+    @Autowired
+    private UserPasswordMapper userPasswordMapper;
+
+    @Autowired
+    private OauthService oauthService;
+
+    @Autowired
+    private SequenceService sequenceService;
+
+    @Autowired
+    private Ip2RegionService ip2RegionService;
+
+    @Override
+    public UserBaseInfo findById(Long id) {
+        return this.userBaseInfoMapper.findById(id);
+    }
+
+    @Override
+    public PageResult<UserBaseInfo> findPage(PageBounds bounds, Map<String, Object> queryWrapper) {
+        List<UserBaseInfo> listData = this.userBaseInfoMapper.findPage(bounds, queryWrapper);
+
+        return bounds.newPageResult(listData);
+    }
+
+    @Override
+    public void updateById(UserBaseInfo userInfo) {
+        this.userBaseInfoMapper.updateById(userInfo);
+    }
+
+    @Override
+    public UserLoginAccount findLoginAccount(String loginAccount, AccountType accountType) {
+        return this.userLoginAccountMapper.findLoginAccount(loginAccount, accountType);
+    }
+
+    @Override
+    public UserPassword findPassword(Long uid, PasswordType passwordType) {
+        return this.userPasswordMapper.findPassword(uid, passwordType);
+    }
+
+    @Override
+    public List<String> findUserAuthorities(Long uid) {
+        return this.userBaseInfoMapper.findUserAuthorities(uid);
+    }
+
+    @Override
+    public List<RoleInfo> findRoles(Long uid) {
+        return this.userBaseInfoMapper.findRoles(uid);
+    }
+
+    @Override
+    public void updatePassword(Long uid, String password, String salt, PasswordType passwordType) {
+        UserPassword userPassword = new UserPassword(uid, password, salt, passwordType);
+        this.userPasswordMapper.insertOrUpdatePassword(userPassword);
+    }
+
+    @Override
+    public void updateBaseInfo(Long uid, UserBaseInfo userBaseInfo) {
+        userBaseInfo.setId(uid);
+        this.userBaseInfoMapper.updateById(userBaseInfo);
+    }
+
+    @Override
+    public void updateLoginAccount(Long uid, String account, AccountType accountType) {
+        UserLoginAccount loginAccount = new UserLoginAccount(uid, account, accountType);
+        userLoginAccountMapper.insertOrUpdate(loginAccount);
+    }
+
+    @Override
+    public List<Map<String, Object>> findSelectAccounts(String searchKey) {
+        return this.userBaseInfoMapper.findSelectAccounts(searchKey);
+    }
+
+    @Override
+    public List<UserLoginAccount> findLoginAccounts(Long uid) {
+        return this.userLoginAccountMapper.findLoginAccounts(uid);
+    }
+
+    @Override
+    @Transactional(rollbackFor = ServiceException.class)
+    public String insertOrUpdate(UserBaseInfo userInfo, List<UserLoginAccount> loginAccounts) throws ServiceException {
+        try {
+            String loginPassword = null;
+            if (userInfo.getId() == null) {
+                Long uid = this.sequenceService.nextId();
+                userInfo.setId(uid);
+                userInfo.setState(UserState.normal);
+                userInfo.setRegisterTime(DateUtil.current());
+                if (StringUtils.isBlank(userInfo.getAvatar())) {
+                    userInfo.setAvatar("");
+                }
+                loginPassword = RandomUtil.get(6);
+                this.userBaseInfoMapper.insert(userInfo);
+            } else {
+                this.updateById(userInfo);
+            }
+
+            userLoginAccountMapper.deleteByUid(userInfo.getId());
+            for (UserLoginAccount loginAccount : loginAccounts) {
+                loginAccount.setUid(userInfo.getId());
+                userLoginAccountMapper.insertOrUpdate(loginAccount);
+            }
+
+            if (StringUtils.isNotBlank(loginPassword)) {
+                String salt = RandomUtil.getSalt();
+                String secretPassword = this.oauthService.generatePassword(loginPassword, salt);
+
+                UserPassword userPassword = new UserPassword(userInfo.getId(), secretPassword, salt, PasswordType.login);
+                this.userPasswordMapper.insertOrUpdatePassword(userPassword);
+            }
+            return loginPassword;
+        } catch (Exception e) {
+            throw new ServiceException(e);
+        }
+    }
+
+    @Override
+    @Transactional(rollbackFor = ServiceException.class)
+    public void saveRoles(Long uid, Long[] roles) throws ServiceException {
+        try {
+            userBaseInfoMapper.deleteRoles(uid);
+            if (roles != null && roles.length > 0) {
+                userBaseInfoMapper.insertRoles(uid, roles);
+            }
+        } catch (Exception e) {
+            throw new ServiceException(e);
+        }
+    }
+
+    @Override
+    public void insertOperateLog(UserOperateLog userOperateLog) {
+        this.userBaseInfoMapper.insertOperateLog(userOperateLog);
+    }
+
+    @Override
+    public void updateOperateLogById(UserOperateLog userOperateLog) {
+        this.userBaseInfoMapper.updateOperateLogById(userOperateLog);
+    }
+
+    @Override
+    public void insertLoginLog(UserLoginLog userLoginLog) {
+        try {
+            userLoginLog.setLoginLocal(this.ip2RegionService.getRegion(userLoginLog.getLoginIp()));
+        } finally {
+            userBaseInfoMapper.insertLoginLog(userLoginLog);
+        }
+    }
+
+    @Override
+    public PageResult<UserLoginLog> findLoginLogPage(PageBounds bounds, Long uid) {
+        List<UserLoginLog> listData = userBaseInfoMapper.findLoginLogPage(bounds, uid);
+        return bounds.newPageResult(listData);
+    }
+}

+ 23 - 0
src/main/java/com/zhiqiyun/open/utils/DateUtil.java

@@ -0,0 +1,23 @@
+package com.zhiqiyun.open.utils;
+
+import org.apache.commons.lang3.time.DateFormatUtils;
+
+import java.util.Date;
+
+public class DateUtil {
+
+    /**
+     * <p>
+     * 当前日期时间
+     * </p>
+     *
+     * @return
+     */
+    public static Date current() {
+        return new Date();
+    }
+
+    public static Object format(String pattern) {
+        return DateFormatUtils.format(DateUtil.current(), pattern);
+    }
+}

+ 105 - 0
src/main/java/com/zhiqiyun/open/utils/PatternUtils.java

@@ -0,0 +1,105 @@
+package com.zhiqiyun.open.utils;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author jtoms
+ */
+@Slf4j
+public class PatternUtils {
+
+
+    /**
+     * Email正则表达式
+     */
+    public static final String EMAIL_EXPRESSION = "^([_A-Za-z0-9-])+@(([A-Za-z0-9-])+\\.)+([a-zA-Z0-9]{2,4})+";
+
+    /**
+     * 中国大陆手机号
+     */
+    public static final String MOBILE_EXPRESSION = "^1[3|4|5|6|7|8|9][0-9]{9}";
+
+    /**
+     * 域名
+     * DNS规定,域名中的标号都由英文字母和数字组成,每一个标号不超过63个字符,也不区分大小写字母。
+     * 标号中除连字符(-)外不能使用其他的标点符号。级别最低的域名写在最左边,而级别最高的域名写在最右边。
+     * 由多个标号组成的完整域名总共不超过255个字符。
+     */
+    public static final String DOMAIN_NAME_EXPRESSION = "^(?=^.{3,255}$)[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$";
+
+    /**
+     * 强密码正则表达式
+     */
+    public static final String STRONG_PASSWORD_EXPRESSION = "^(?![\\d]+$)(?![a-zA-Z]+$)(?![^\\da-zA-Z]+$).{6,20}$";
+
+    /**
+     * IPV4正则表达式
+     */
+    public static final String IPV4_EXPRESSION = "([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}";
+
+
+    private static final String IMAGE_SRC_REGEX = "<img.+?src=\"(.+?)\".+?/?>";
+
+
+    /**
+     * 正则表达试的验证
+     *
+     * @param value
+     * @param expression
+     * @return
+     */
+    public static boolean validExpression(String value, String expression) {
+        return value.matches(expression);
+    }
+
+
+    public static List<String> getImgUrlFromHtml(String htmlStr) {
+        List<String> listImgUrl = new ArrayList<>();
+        try {
+            Matcher matcher = Pattern.compile(IMAGE_SRC_REGEX).matcher(htmlStr);
+            while (matcher.find()) {
+                listImgUrl.add(matcher.group(1));
+            }
+        } catch (Exception e) {
+            log.warn("", e);
+        }
+        return listImgUrl;
+    }
+
+
+    public static String buildUrl(String urlExpression, Map<String, Object> params) {
+        List<String> listExpressions = new ArrayList<>();
+        while (true) {
+            int startIndex = urlExpression.indexOf("{");
+            if (startIndex == -1) {
+                break;
+            }
+            int endIndex = urlExpression.indexOf("}");
+            if (endIndex < startIndex) {
+                return String.format("%s 分页表达试错误", urlExpression);
+            }
+
+            String expression = urlExpression.substring(startIndex, endIndex + 1);
+
+            listExpressions.add(expression);
+            urlExpression = urlExpression.replace(expression, "%s");
+        }
+        for (int i = 0; i < listExpressions.size(); i++) {
+            String expressions = listExpressions.get(i);
+
+            for (String key : params.keySet()) {
+                if (expressions.contains(key) && params.get(key) != null) {
+                    listExpressions.set(i, params.get(key).toString());
+                }
+            }
+        }
+
+        return String.format(urlExpression, listExpressions.toArray());
+    }
+}

+ 91 - 0
src/main/java/com/zhiqiyun/open/utils/RandomUtil.java

@@ -0,0 +1,91 @@
+package com.zhiqiyun.open.utils;
+
+import java.security.SecureRandom;
+import java.util.Random;
+import java.util.UUID;
+
+/**
+ * @author jtoms
+ */
+public class RandomUtil {
+
+    /**
+     * 获取密码盐值
+     *
+     * @return
+     */
+    public static String getSalt() {
+        return get(8);
+    }
+
+    /**
+     * 生成UUID
+     *
+     * @return
+     */
+    public static String getuuid() {
+        String uuid = UUID.randomUUID().toString();
+        uuid = uuid.replace("-", "");
+        return uuid;
+    }
+
+    /**
+     * 获取纯数字
+     *
+     * @param len
+     * @return
+     */
+    public static String getNumber(int len) {
+        return get(len, 0);
+    }
+
+    /**
+     * 获取纯字母
+     *
+     * @param len
+     * @return
+     */
+    public static String getLetter(int len) {
+        return get(len, 1);
+    }
+
+    /**
+     * 获取数字加字母
+     *
+     * @param len
+     * @return
+     */
+    public static String get(int len) {
+        return get(len, 2);
+    }
+
+    /**
+     * 生成随机码
+     *
+     * @param len  长度
+     * @param type 0-全数字,1-全字母,2数字与字母混合
+     * @return
+     */
+    private static String get(int len, int type) {
+        String[] codes = new String[]{"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
+                "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y",
+                "z"};
+        Random random = new SecureRandom();
+        StringBuilder code = new StringBuilder();
+        for (int i = 0; i < len; i++) {
+            if (type == 0) {
+                code.append(codes[random.nextInt(10)]);
+            } else if (type == 1) {
+                code.append(codes[10 + random.nextInt(codes.length - 10)]);
+            } else {
+                code.append(codes[random.nextInt(codes.length)]);
+            }
+        }
+        return code.toString();
+    }
+
+    public static int getInt(int min, int max) {
+        Random random = new SecureRandom();
+        return min + random.nextInt(max - min);
+    }
+}

+ 14 - 0
src/main/resources/META-INF/spring-configuration-metadata.json

@@ -0,0 +1,14 @@
+{
+  "properties": [
+    {
+      "name": "logger.root.path",
+      "type": "java.lang.String",
+      "description": "Description for logger.root.path."
+    },
+    {
+      "name": "logger.root.level",
+      "type": "java.lang.String",
+      "description": "Description for logger.root.level."
+    }
+  ]
+}

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

@@ -0,0 +1,38 @@
+spring.profiles.active=dev
+server.port=9800
+spring.application.name=zhiqiyun-open-platform
+####################### logger ###############################
+logger.root.level=DEBUG
+logger.root.path=/tmp/${spring.application.name}/logs/
+
+####################### mysql ###############################
+spring.datasource.driverClassName=org.mariadb.jdbc.Driver
+spring.datasource.url=jdbc:mysql://192.168.0.200:3306/lanli-oauth?characterEncoding=UTF-8&autoReconnect=true
+spring.datasource.username=app
+spring.datasource.password=!@qwaszx
+#######################mybatis###############################
+mybatis.config-location=classpath:mybatis/sqlMapConfig.xml
+mybatis.mapper-locations=classpath:mybatis/mappers/*.xml
+#######################redis###############################
+spring.redis.password=123456
+spring.redis.host=192.168.0.200
+spring.redis.port=6379
+spring.redis.database=0
+
+####################### oap config ###############################
+#spring.oap.security.file-upload-controller-class=com.dliyun.oap.framework.impl.DefaultFileUploadController
+#spring.oap.security.app-secret-manager-class=com.dliyun.oap.framework.impl.FileBaseAppSecretManager
+#spring.oap.security.service-access-controller-class=com.dliyun.oap.framework.impl.DefaultServiceAccessController
+#spring.oap.security.invoke-times-controller-class=com.dliyun.oap.framework.impl.DefaultInvokeTimesController
+#\u7EBF\u7A0B\u6C60\u914D\u7F6E
+#spring.oap.executor.core-pool-size=5
+#spring.oap.executor.max-pool-size=1024
+#spring.oap.executor.keep-alive-seconds=120
+#spring.oap.executor.queue-capacity=30
+#spring.oap.executor.thread-ferry-class=com.dliyun.oap.framework.impl.DumbThreadFerry
+#\u6587\u4EF6\u4E0A\u4F20\u914D\u7F6E
+#spring.oap.upload.file-max-size=1
+#spring.oap.upload.file-types=jpg,png,doc,zip
+#\u7CFB\u7EDF\u914D\u7F6E
+#spring.oap.service.timeout-seconds=60
+#spring.oap.service.transport-security-class=com.dliyun.demo.apis.RsaTransportSecurity

TEMPAT SAMPAH
src/main/resources/ip2region.db


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

@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration scan="true" scanPeriod="10 seconds">
+    <include resource="org/springframework/boot/logging/logback/defaults.xml" />
+    <springProperty scope="context" name="SPRING_APP_NAME" source="spring.application.name" />
+    <springProperty scope="context" name="LOGGER_ROOT_LEVEL" source="logger.root.level" />
+    <springProperty scope="context" name="LOGGER_ROOT_PATH" source="logger.root.path" />
+    <!-- %m输出的信息,%p日志级别,%t线程名,%d日期,%c类的全名,%i索引【从数字0开始递增】,,, -->
+    <!-- appender是configuration的子节点,是负责写日志的组件。 -->
+    <!-- ConsoleAppender:把日志输出到控制台 -->
+    <logger name="org.springframework" level="INFO" />
+    <logger name="com.alibaba" level="INFO" />
+    <logger name="org.apache" level="INFO" />
+    <logger name="org.hibernate" level="INFO" />
+    <logger name="springfox" level="INFO" />
+    <logger name="com.baomidou" level="INFO" />
+    <logger name="org.flywaydb" level="INFO" />
+    <logger name="io.lettuce" level="INFO" />
+    <logger name="com.zaxxer" level="INFO" />
+    <logger name="org.ehcache" level="INFO" />
+
+    <property name="LOG_PATH" value="${LOGGER_ROOT_PATH}/${SPRING_APP_NAME}" />
+    <property name="MAX_HISTORY" value="10" />
+    <property name="MAX_FILE_SIZE" value="200MB" />
+    <property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} -%msg%n" />
+
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>%d %p (%file:%line\)- %m%n</pattern>
+            <!-- 控制台也要使用UTF-8,不要使用GBK,否则会中文乱码 -->
+            <charset>UTF-8</charset>
+        </encoder>
+    </appender>
+
+    <appender name="FILE_ALL_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <File>${LOG_PATH}/logger.log</File>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>${LOG_PATTERN}</pattern>
+        </encoder>
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <!--日志文件输出的文件名 -->
+            <FileNamePattern>${LOG_PATH}/logger-%d{yyyyMMddHH}.log.%i</FileNamePattern>
+            <!--日志文件保留天数 -->
+            <MaxHistory>${MAX_HISTORY}</MaxHistory>
+            <maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
+        </rollingPolicy>
+    </appender>
+
+    <!--日志文件配置error -->
+    <appender name="FILE_ERROR_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <File>${LOG_PATH}/error.log</File>
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>ERROR</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>${LOG_PATTERN}</pattern>
+        </encoder>
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <!--日志文件输出的文件名 -->
+            <FileNamePattern>${LOG_PATH}/error-%d{yyyyMMddHH}.log.%i</FileNamePattern>
+            <!--日志文件保留天数 -->
+            <MaxHistory>${MAX_HISTORY}</MaxHistory>
+            <maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
+        </rollingPolicy>
+    </appender>
+
+    <!-- 为logstash输出的JSON格式的Appender -->
+    <!--    <appender name="logstash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">-->
+    <!--        <destination>${elkLoggerUrl}</destination>-->
+    <!--        &lt;!&ndash; 日志输出编码 &ndash;&gt;-->
+    <!--        <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">-->
+    <!--            <providers>-->
+    <!--                <mdc/>-->
+    <!--                <timestamp>-->
+    <!--                    <timeZone>UTC</timeZone>-->
+    <!--                </timestamp>-->
+    <!--                <pattern>-->
+    <!--                    <pattern>-->
+    <!--                        {-->
+    <!--                        "severity": "%level",-->
+    <!--                        "applicationName": "${SPRING_APP_NAME:-}",-->
+    <!--                        "requestId": "%X{requestId:-}",-->
+    <!--                        "pid": "${PID:-}",-->
+    <!--                        "thread": "%thread",-->
+    <!--                        "class": "%logger{40}",-->
+    <!--                        "message": "%message"-->
+    <!--                        }-->
+    <!--                    </pattern>-->
+    <!--                </pattern>-->
+    <!--                <stackTrace>-->
+    <!--                    <throwableConverter class="net.logstash.logback.stacktrace.ShortenedThrowableConverter">-->
+    <!--                        <maxDepthPerThrowable>50</maxDepthPerThrowable>-->
+    <!--                        <maxLength>4048</maxLength>-->
+    <!--                        <shortenedClassNameLength>50</shortenedClassNameLength>-->
+    <!--                        <exclude>^sun\.reflect\..*\.invoke</exclude>-->
+    <!--                        <exclude>^net\.sf\.cglib\.proxy\.MethodProxy\.invoke</exclude>-->
+    <!--                        <rootCauseFirst>true</rootCauseFirst>-->
+    <!--                    </throwableConverter>-->
+    <!--                </stackTrace>-->
+    <!--            </providers>-->
+    <!--        </encoder>-->
+    <!--    </appender>-->
+    <!-- 控制台输出日志级别 -->
+    <!--    <springProfile name="dev">-->
+    <!--        <property name="LOG_ROOT_LEVEL" value="DEBUG"/>-->
+    <!--    </springProfile>-->
+    <!--    <springProfile name="prod">-->
+    <!--        <property name="LOG_ROOT_LEVEL" value="INFO"/>-->
+    <!--    </springProfile>-->
+
+    <root level="${LOGGER_ROOT_LEVEL}">
+        <appender-ref ref="FILE_ALL_LOG" />
+        <appender-ref ref="FILE_ERROR_LOG" />
+        <appender-ref ref="STDOUT" />
+    </root>
+</configuration>

+ 24 - 0
src/main/resources/mybatis/mappers/AuthorityInfoMapper.xml

@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.zhiqiyun.open.mapper.AuthorityInfoMapper">
+    <resultMap id="BaseResultMap" type="com.zhiqiyun.open.models.AuthorityInfo">
+        <id column="id" property="id" jdbcType="BIGINT"/>
+        <result column="parent_id" property="parentId" jdbcType="BIGINT"/>
+        <result column="name" property="name" jdbcType="VARCHAR"/>
+        <result column="remark" property="remark" jdbcType="VARCHAR"/>
+    </resultMap>
+
+    <sql id="Base_Column">
+        `id`
+        , `parent_id`, `name`, `remark`
+    </sql>
+
+    <select id="findChildren" resultMap="BaseResultMap" parameterType="java.lang.Long">
+        select
+        <include refid="Base_Column"/>
+        from authority_info
+        <where>
+            `parent_id` = #{parentId}
+        </where>
+    </select>
+</mapper>

+ 78 - 0
src/main/resources/mybatis/mappers/RoleInfoMapper.xml

@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.zhiqiyun.open.mapper.RoleInfoMapper">
+    <resultMap id="BaseResultMap" type="com.zhiqiyun.open.models.RoleInfo">
+        <id column="id" property="id" jdbcType="BIGINT"/>
+        <result column="name" property="name" jdbcType="VARCHAR"/>
+        <result column="remark" property="remark" jdbcType="VARCHAR"/>
+    </resultMap>
+
+    <sql id="Base_Column">
+        `id`
+        , `name`, `remark`
+    </sql>
+
+    <insert id="insert" parameterType="com.zhiqiyun.open.models.RoleInfo">
+        insert into `role_info` (`name`, remark)
+        values (#{name,jdbcType=VARCHAR}, #{remark,jdbcType=VARCHAR})
+    </insert>
+
+    <update id="updateById" parameterType="com.zhiqiyun.open.models.RoleInfo">
+        update `role_info`
+        <set>
+            <if test="name != null and name !=''">
+                `name` = #{name,jdbcType=VARCHAR},
+            </if>
+            <if test="remark != null and remark !=''">
+                `remark` = #{remark,jdbcType=VARCHAR},
+            </if>
+        </set>
+        <where>
+            `id` = #{id, jdbcType=BIGINT}
+        </where>
+    </update>
+
+    <insert id="insertAuthority">
+        insert into role_authority (authority_id, role_id)
+        values
+        <foreach collection="authorities" item="item" index="index" separator=",">
+            (#{item,jdbcType=BIGINT}, #{roleId,jdbcType=BIGINT})
+        </foreach>
+    </insert>
+
+    <select id="findAuthorities" resultType="java.lang.Long">
+        select authority_id
+        from role_authority
+        WHERE role_id = #{roleId,jdbcType=BIGINT}
+    </select>
+    <select id="findPage" resultMap="BaseResultMap">
+        select
+        <include refid="Base_Column"/>
+        from `role_info`
+        <where>
+            <if test="name != null and name != ''">
+                `name` like CONCAT('%',#{name,jdbcType=BIGINT},'%')
+            </if>
+        </where>
+        order by id desc
+    </select>
+    <delete id="deleteAuthorities" parameterType="java.lang.Long">
+        delete FROM role_authority
+        <where>
+            role_id in
+            <foreach collection="roleIds" item="roleId" separator="," open="(" close=")">
+                #{roleId,jdbcType=BIGINT}
+            </foreach>
+        </where>
+    </delete>
+
+    <delete id="deleteBatchIds">
+        delete FROM role_info
+        <where>
+            id in
+            <foreach collection="roleIds" item="roleId" separator="," open="(" close=")">
+                #{roleId,jdbcType=BIGINT}
+            </foreach>
+        </where>
+    </delete>
+</mapper>

+ 9 - 0
src/main/resources/mybatis/mappers/SequenceMapper.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.zhiqiyun.open.mapper.SequenceMapper">
+    <insert id="generateNextId" parameterType="com.zhiqiyun.open.models.Sequence" useGeneratedKeys="true"
+            keyProperty="id">
+        insert into `sequence` (`salt_random`, `created_time`)
+        values (#{saltRandom}, #{createdTime})
+    </insert>
+</mapper>

+ 175 - 0
src/main/resources/mybatis/mappers/UserBaseInfoMapper.xml

@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.zhiqiyun.open.mapper.UserBaseInfoMapper">
+    <resultMap id="BaseResultMap" type="com.zhiqiyun.open.models.UserBaseInfo">
+        <id column="id" property="id" jdbcType="BIGINT"/>
+        <result column="nick_name" property="nickName" jdbcType="VARCHAR"/>
+        <result column="avatar" property="avatar" jdbcType="VARCHAR"/>
+        <result column="gender" property="gender" typeHandler="com.zhiqiyun.open.mybatis.typeHandler.IEnumTypeHandler"/>
+        <result column="register_time" property="registerTime" jdbcType="TIMESTAMP"/>
+        <result column="register_ip" property="registerIp" jdbcType="VARCHAR"/>
+        <result column="state" property="state" typeHandler="com.zhiqiyun.open.mybatis.typeHandler.IEnumTypeHandler"/>
+    </resultMap>
+
+    <resultMap id="UserLoginLogResultMap" type="com.zhiqiyun.open.models.UserLoginLog">
+        <id column="id" property="id" jdbcType="BIGINT"/>
+        <result column="login_account" property="loginAccount" jdbcType="VARCHAR"/>
+        <result column="account_type" property="accountType" typeHandler="com.zhiqiyun.open.mybatis.typeHandler.IEnumTypeHandler"/>
+        <result column="login_ip" property="loginIp" jdbcType="VARCHAR"/>
+        <result column="login_local" property="loginLocal" jdbcType="VARCHAR"/>
+        <result column="from_source" property="fromSource" jdbcType="VARCHAR"/>
+        <result column="device_id" property="deviceId" jdbcType="VARCHAR"/>
+        <result column="login_time" property="loginTime" jdbcType="TIMESTAMP"/>
+        <result column="state" property="state" typeHandler="com.zhiqiyun.open.mybatis.typeHandler.IEnumTypeHandler"/>
+    </resultMap>
+    <sql id="Base_Column">
+        `id`
+        , `nick_name`, `avatar`, `gender`, `state`, `register_time`, `register_ip`
+    </sql>
+
+    <select id="findPage" resultMap="BaseResultMap">
+        select
+        <include refid="Base_Column"/>
+        from `user_base_info`
+        <where>
+            <if test="nickName != null and nickName !=''">
+                AND `nick_name` = #{nickName,jdbcType=VARCHAR}
+            </if>
+            <if test="userName != null and userName !=''">
+                AND `id` in (select `uid` from `user_login_account` where `login_account` like CONCAT('%',#{userName,jdbcType=VARCHAR},'%'))
+            </if>
+            <if test="state != null">
+                AND `state` = #{state, typeHandler=com.dliyun.commons.typeHandler.IEnumTypeHandler}
+            </if>
+            <if test="gender != null">
+                AND `gender` = #{gender, typeHandler=com.dliyun.commons.typeHandler.IEnumTypeHandler}
+            </if>
+            <if test="registerTime != null">
+                AND `register_time` between #{registerTime.statDate, jdbcType=TIMESTAMP} and #{registerTime.endDate, jdbcType=TIMESTAMP}
+            </if>
+        </where>
+        order by id desc
+    </select>
+    <select id="findById" resultMap="BaseResultMap" parameterType="java.lang.Long">
+        select
+        <include refid="Base_Column"/>
+        from user_base_info
+        <where>
+            id = #{id,jdbcType=BIGINT}
+        </where>
+    </select>
+
+    <delete id="deleteRoles">
+        delete
+        FROM user_role
+        WHERE uid = #{uid,jdbcType=BIGINT}
+    </delete>
+    <insert id="insertRoles">
+        insert into user_role (uid, role_id)
+        values
+        <foreach collection="roles" item="item" index="index" separator=",">
+            (#{uid,jdbcType=BIGINT},#{item,jdbcType=BIGINT})
+        </foreach>
+    </insert>
+    <insert id="insert" parameterType="com.zhiqiyun.open.models.UserBaseInfo">
+        insert into `user_base_info` (`id`, `nick_name`, `avatar`, `gender`, `state`, `register_time`, `register_ip`)
+        values (#{id, jdbcType=BIGINT},
+        #{nickName, jdbcType=VARCHAR},
+        #{avatar, jdbcType=VARCHAR},
+        #{gender, typeHandler=com.zhiqiyun.open.mybatis.typeHandler.IEnumTypeHandler},
+        #{state, typeHandler=com.zhiqiyun.open.mybatis.typeHandler.IEnumTypeHandler},
+        #{registerTime, jdbcType=TIMESTAMP},
+        #{registerIp, jdbcType=VARCHAR})
+    </insert>
+    <insert id="insertOperateLog" parameterType="com.zhiqiyun.open.models.UserOperateLog">
+        insert into `user_operate_logs` (`id`, `uid`, `tags`, `from_source`, `request_url`, `request_ip`, `request_params`, `request_data`, `request_time`)
+        values (#{id, jdbcType=VARCHAR},
+        #{uid, jdbcType=BIGINT},
+        #{tags, jdbcType=VARCHAR},
+        #{fromSource, jdbcType=VARCHAR},
+        #{requestUrl, jdbcType=VARCHAR},
+        #{requestIp, jdbcType=VARCHAR},
+        #{requestParams, jdbcType=VARCHAR},
+        #{requestData, jdbcType=VARCHAR},
+        #{requestTime, jdbcType=TIMESTAMP})
+    </insert>
+    <insert id="insertLoginLog">
+        insert into `user_login_logs` (`login_account`, `account_type`, `login_ip`, `login_local`, `from_source`, `device_id`, `login_time`, `state`)
+        values (#{loginAccount},
+        #{accountType, typeHandler=com.zhiqiyun.open.mybatis.typeHandler.IEnumTypeHandler},
+        #{loginIp},
+        #{loginLocal},
+        #{fromSource},
+        #{deviceId},
+        #{loginTime, jdbcType=TIMESTAMP},
+        #{state, typeHandler=com.zhiqiyun.open.mybatis.typeHandler.IEnumTypeHandler})
+    </insert>
+    <update id="updateById" parameterType="com.zhiqiyun.open.models.UserBaseInfo">
+        update `user_base_info`
+        <set>
+            <if test="nickName != null and nickName !=''">
+                `nick_name` = #{nickName,jdbcType=VARCHAR},
+            </if>
+            <if test="avatar != null">
+                `avatar` = #{avatar,jdbcType=VARCHAR},
+            </if>
+            <if test="gender != null">
+                `gender` = #{gender, typeHandler=com.zhiqiyun.open.mybatis.typeHandler.IEnumTypeHandler},
+            </if>
+            <if test="state != null">
+                `state` = #{state, typeHandler=com.zhiqiyun.open.mybatis.typeHandler.IEnumTypeHandler},
+            </if>
+        </set>
+        <where>id=#{id}</where>
+    </update>
+    <update id="updateOperateLogById">
+        update `user_operate_logs`
+        <set>
+            <if test="responseTime != null">
+                `response_time` = #{responseTime,jdbcType=TIMESTAMP},
+            </if>
+        </set>
+        <where>id=#{id}</where>
+    </update>
+    <select id="findUserAuthorities" resultType="java.lang.String">
+        SELECT name
+        FROM authority_info
+        WHERE id IN (
+        SELECT authority_id
+        FROM role_authority
+        WHERE role_id IN (
+        SELECT role_id
+        FROM user_role
+        WHERE uid = #{uid,jdbcType=BIGINT}
+        )
+        )
+    </select>
+    <select id="findRoles" resultMap="com.zhiqiyun.open.mapper.RoleInfoMapper.BaseResultMap" parameterType="java.lang.Long">
+        select
+        <include refid="com.zhiqiyun.open.mapper.RoleInfoMapper.Base_Column"/>
+        from `role_info`
+        <where>
+            `id` in (select `role_id` from `user_role` where `uid` = #{uid,jdbcType=BIGINT})
+        </where>
+    </select>
+    <select id="findLoginLogPage" resultMap="UserLoginLogResultMap">
+        select
+        a.`id`, a.`login_account`, a.`account_type`, a.`login_ip`, a.`login_local`, a.`from_source`, a.`device_id`, a.`login_time`, a.`state`
+        from user_login_logs a
+        left join user_login_account b on a.`login_account`=b.`login_account`
+        <where>
+            b.`uid`=#{uid}
+        </where>
+    </select>
+    <select id="findSelectAccounts" resultType="java.util.Map">
+        select id,`nick_name` as nickName from `user_base_info`
+        <where>
+            <if test="searchKey != null and searchKey !=''">
+                or `nick_name` like CONCAT("%",#{searchKey},"%")
+                or `id` like CONCAT("%",#{searchKey},"%")
+                or `id` in (select `uid` from `user_login_account` where `login_account` like CONCAT("%",#{searchKey},"%"))
+            </if>
+        </where>
+        limit 10
+    </select>
+</mapper>

+ 46 - 0
src/main/resources/mybatis/mappers/UserLoginAccountMapper.xml

@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.zhiqiyun.open.mapper.UserLoginAccountMapper">
+    <resultMap id="BaseResultMap" type="com.zhiqiyun.open.models.UserLoginAccount">
+        <id column="id" property="id" jdbcType="VARCHAR"/>
+        <result column="uid" property="uid" jdbcType="BIGINT"/>
+        <result column="login_account" property="loginAccount" jdbcType="VARCHAR"/>
+        <result column="account_type" property="accountType" typeHandler="com.zhiqiyun.open.mybatis.typeHandler.IEnumTypeHandler"/>
+    </resultMap>
+
+    <sql id="Base_Column">
+        `id`
+        , `uid`, `login_account`, `account_type`
+    </sql>
+    <insert id="insertOrUpdate">
+        replace
+        into `user_login_account` (`id`, `uid`, `login_account`, `account_type`)
+        values (
+        #{id, jdbcType=BIGINT},
+        #{uid, jdbcType=BIGINT},
+        #{loginAccount, jdbcType=VARCHAR},
+        #{accountType, typeHandler=com.zhiqiyun.open.mybatis.typeHandler.IEnumTypeHandler}
+        )
+    </insert>
+    <delete id="deleteByUid">
+        delete
+        from `user_login_account`
+        where uid = #{uid}
+    </delete>
+    <select id="findLoginAccount" resultMap="BaseResultMap">
+        select
+        <include refid="Base_Column"/>
+        from `user_login_account`
+        <where>
+            `login_account`=#{loginAccount} and `account_type`=#{accountType,typeHandler=com.zhiqiyun.open.mybatis.typeHandler.IEnumTypeHandler}
+        </where>
+    </select>
+    <select id="findLoginAccounts" resultMap="BaseResultMap">
+        select
+        <include refid="Base_Column"/>
+        from `user_login_account`
+        <where>
+            `uid` = #{uid,jdbcType=BIGINT}
+        </where>
+    </select>
+</mapper>

+ 37 - 0
src/main/resources/mybatis/mappers/UserPasswordMapper.xml

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.zhiqiyun.open.mapper.UserPasswordMapper">
+    <resultMap id="BaseResultMap" type="com.zhiqiyun.open.models.UserPassword">
+        <id column="id" property="id" jdbcType="BIGINT"/>
+        <result column="uid" property="uid" jdbcType="BIGINT"/>
+        <result column="passwd" property="passwd" jdbcType="VARCHAR"/>
+        <result column="salt" property="salt" jdbcType="VARCHAR"/>
+        <result column="password_type" property="passwordType" typeHandler="com.zhiqiyun.open.mybatis.typeHandler.IEnumTypeHandler"/>
+    </resultMap>
+
+    <sql id="Base_Column">
+        `id`
+        , `uid`, `passwd`, `salt`, `password_type`
+    </sql>
+
+    <select id="findPassword" parameterType="java.lang.Object" resultMap="BaseResultMap">
+        select
+        <include refid="Base_Column"/>
+        from `user_password`
+        <where>
+            and uid = #{uid, jdbcType=BIGINT}
+            and `password_type`=#{passwordType, typeHandler=com.zhiqiyun.open.mybatis.typeHandler.IEnumTypeHandler}
+        </where>
+    </select>
+    <insert id="insertOrUpdatePassword" parameterType="com.zhiqiyun.open.models.UserPassword">
+        replace
+        into `user_password` (`id`, `uid`, `passwd`, `salt`, `password_type`)
+        values (
+        #{id},
+        #{uid},
+        #{passwd},
+        #{salt},
+        #{passwordType.value}
+        )
+    </insert>
+</mapper>

+ 10 - 0
src/main/resources/mybatis/sqlMapConfig.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-config.dtd">
+<configuration>
+    <plugins>
+        <plugin interceptor="com.zhiqiyun.open.mybatis.paginator.PaginationInterceptor">
+            <property name="dialectClass" value="com.zhiqiyun.open.mybatis.paginator.dialect.MySQLDialect"/>
+        </plugin>
+    </plugins>
+</configuration>

+ 1 - 0
src/main/resources/oap.appSecret.properties

@@ -0,0 +1 @@
+A100=1234567890