Browse Source

first commit

wuhongshuang 4 năm trước cách đây
commit
a36fefd949
59 tập tin đã thay đổi với 7695 bổ sung0 xóa
  1. 37 0
      .gitignore
  2. 30 0
      README.md
  3. 153 0
      pom.xml
  4. 82 0
      src/main/java/com/shawn/ApiLocator.java
  5. 108 0
      src/main/java/com/shawn/GatewayServerApplication.java
  6. 103 0
      src/main/java/com/shawn/LoadBalancerClientByKeyFilter.java
  7. 573 0
      src/main/java/com/shawn/MyGlobalFilter.java
  8. 26 0
      src/main/java/com/shawn/OprDetlGatewayFilterFactory.java
  9. 43 0
      src/main/java/com/shawn/common/cache/RedisConfig.java
  10. 37 0
      src/main/java/com/shawn/common/myFormat/DateSerializer.java
  11. 16 0
      src/main/java/com/shawn/constant/DatabaseType.java
  12. 19 0
      src/main/java/com/shawn/constant/ErrorCode.java
  13. 19 0
      src/main/java/com/shawn/constant/PageConstant.java
  14. 31 0
      src/main/java/com/shawn/model/bean/PageBean.java
  15. 26 0
      src/main/java/com/shawn/model/dto/Error.java
  16. 29 0
      src/main/java/com/shawn/model/dto/PaginatedResult.java
  17. 26 0
      src/main/java/com/shawn/model/dto/ResultMessage.java
  18. 49 0
      src/main/java/com/shawn/model/entity/GatewayWhiteList.java
  19. 798 0
      src/main/java/com/shawn/model/entity/GatewayWhiteListExample.java
  20. 100 0
      src/main/java/com/shawn/model/entity/ReportOprDetl.java
  21. 1629 0
      src/main/java/com/shawn/model/entity/ReportOprDetlExample.java
  22. 36 0
      src/main/java/com/shawn/model/param/GatewayWhiteListParam.java
  23. 39 0
      src/main/java/com/shawn/model/param/ReportOprDetlParam.java
  24. 65 0
      src/main/java/com/shawn/quartz/SchedulerListener.java
  25. 14 0
      src/main/java/com/shawn/repository/GatewayWhiteListMapper.java
  26. 9 0
      src/main/java/com/shawn/repository/GetNoMapper.java
  27. 16 0
      src/main/java/com/shawn/repository/ReportOprDetlMapper.java
  28. 39 0
      src/main/java/com/shawn/repository/base/BaseDaoInterface.java
  29. 98 0
      src/main/java/com/shawn/rule/NodeBalanceRule.java
  30. 122 0
      src/main/java/com/shawn/service/base/BaseService.java
  31. 70 0
      src/main/java/com/shawn/service/base/BaseServiceInterface.java
  32. 157 0
      src/main/java/com/shawn/service/impl/GatewayWhiteListServiceImpl.java
  33. 80 0
      src/main/java/com/shawn/service/impl/ReportOprDetlServiceImpl.java
  34. 14 0
      src/main/java/com/shawn/service/interfac/GatewayWhiteListServiceInterface.java
  35. 15 0
      src/main/java/com/shawn/service/interfac/ReportOprDetlServiceInterface.java
  36. 53 0
      src/main/java/com/shawn/util/BeanUtils.java
  37. 252 0
      src/main/java/com/shawn/util/DateUtils.java
  38. 492 0
      src/main/java/com/shawn/util/FgObjectUtil.java
  39. 77 0
      src/main/java/com/shawn/util/MD5Util.java
  40. 103 0
      src/main/java/com/shawn/util/PageUtil.java
  41. 36 0
      src/main/java/com/shawn/util/SerializeUtil.java
  42. 39 0
      src/main/java/com/shawn/util/SpringBeanUtil.java
  43. 27 0
      src/main/java/com/shawn/util/UniqueIDUtil.java
  44. 15 0
      src/main/java/com/shawn/web/Response/BodyHandlerFunction.java
  45. 52 0
      src/main/java/com/shawn/web/Response/BodyHandlerServerHttpResponseDecorator.java
  46. 88 0
      src/main/java/com/shawn/web/Response/DefaultClientResponseAdapter.java
  47. 170 0
      src/main/java/com/shawn/web/controller/GatewayWhiteListController.java
  48. 452 0
      src/main/java/com/shawn/web/controller/base/BaseController.java
  49. 24 0
      src/main/java/com/shawn/web/exception/MyException.java
  50. 25 0
      src/main/java/com/shawn/web/exception/ParamNotFoundException.java
  51. 10 0
      src/main/java/com/shawn/web/exception/ParameterIllegalException.java
  52. 25 0
      src/main/java/com/shawn/web/exception/ResourceNotFoundException.java
  53. 10 0
      src/main/java/com/shawn/web/exception/ServerInternalErrorException.java
  54. 66 0
      src/main/resources/application-local.properties
  55. 67 0
      src/main/resources/application-prod.properties
  56. 67 0
      src/main/resources/application-prod2.properties
  57. 2 0
      src/main/resources/application.properties
  58. 312 0
      src/main/resources/com/shawn/repository/mybatis/GatewayWhiteListMapper.xml
  59. 523 0
      src/main/resources/com/shawn/repository/mybatis/ReportOprDetlMapper.xml

+ 37 - 0
.gitignore

@@ -0,0 +1,37 @@
+# Created by .ignore support plugin (hsz.mobi)
+
+# Operating System Files
+
+*.DS_Store
+Thumbs.db
+*.sw?
+.#*
+*#
+*~
+*.sublime-*
+
+# Build Artifacts
+
+.gradle/
+build/
+target/
+bin/
+dependency-reduced-pom.xml
+.factorypath
+
+# Eclipse Project Files
+
+.classpath
+.project
+.settings/
+workspace.xml
+
+# IntelliJ IDEA Files
+
+*.iml
+*.ipr
+*.iws
+*.idea
+
+# other code repositories
+.svn

+ 30 - 0
README.md

@@ -0,0 +1,30 @@
+# GatewayServer
+
+## 如何构建
+### maven命令行
+#### 测试环境
+eureka1和eureka2
+```shell
+mvn clean package
+```
+eureka3和eureka4
+```shell
+mvn clean package -Peureka34
+```
+#### 生产环境
+eureka1和eureka2
+```shell
+mvn clean package -Pprod
+```
+eureka3和eureka4
+```shell
+mvn clean package -Pprod,eureka34
+```
+### idea CE
+在`Run/Debug Configuration`中**Before Launch**将原本的`build`删除,新建`Run Maven Goal`并填入以下内容
+```shell
+clean package
+```
+
+## 相关链接
+- SonarQube: <http://devops.crbank.com.cn:9001/dashboard?id=crbank.7027_gateway-server>

+ 153 - 0
pom.xml

@@ -0,0 +1,153 @@
+<?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.shawn</groupId>
+	<artifactId>GatewayServer</artifactId>
+	<version>0.0.1</version>
+	<packaging>jar</packaging>
+
+	<name>GatewayServer</name>
+
+	<parent>
+		<groupId>org.springframework.boot</groupId>
+		<artifactId>spring-boot-starter-parent</artifactId>
+		<version>2.1.3.RELEASE</version>
+		<!--<version>2.0.2.RELEASE</version>-->
+		<relativePath /> <!-- lookup parent from repository -->
+	</parent>
+
+	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+		<java.version>1.8</java.version>
+		<commons-collections4.version>4.1</commons-collections4.version>
+		<!--<spring-cloud.version>Finchley.RC2</spring-cloud.version>-->
+		<!--<spring-cloud.version>Finchley.RC1</spring-cloud.version>-->
+		<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
+		<!--		<spring-cloud.version>Greenwich.M3</spring-cloud.version>-->
+	</properties>
+
+	<dependencies>
+		<dependency>
+			<groupId>org.springframework.cloud</groupId>
+			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.cloud</groupId>
+			<artifactId>spring-cloud-starter-gateway</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-test</artifactId>
+			<scope>test</scope>
+		</dependency>
+
+		<!--  Hystrix 熔断器 -->
+		<dependency>
+			<groupId>org.springframework.cloud</groupId>
+			<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>org.mybatis.spring.boot</groupId>
+			<artifactId>mybatis-spring-boot-starter</artifactId>
+			<version>1.3.2</version>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-jdbc</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>mysql</groupId>
+			<artifactId>mysql-connector-java</artifactId>
+			<scope>runtime</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.projectlombok</groupId>
+			<artifactId>lombok</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>commons-lang</groupId>
+			<artifactId>commons-lang</artifactId>
+			<version>2.6</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.apache.commons</groupId>
+			<artifactId>commons-collections4</artifactId>
+			<version>${commons-collections4.version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.apache.commons</groupId>
+			<artifactId>commons-lang3</artifactId>
+		</dependency>
+		<!-- json -->
+		<dependency>
+			<groupId>com.alibaba</groupId>
+			<artifactId>fastjson</artifactId>
+			<version>1.2.58</version>
+		</dependency>
+		<!--redis start-->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-data-redis</artifactId>
+		</dependency>
+		<!--		<dependency>-->
+		<!--			<groupId>org.springframework.boot</groupId>-->
+		<!--			<artifactId>spring-boot-starter-data-redis</artifactId>-->
+		<!--			<exclusions>-->
+		<!--				<exclusion>-->
+		<!--					<groupId>io.lettuce</groupId>-->
+		<!--					<artifactId>lettuce-core</artifactId>-->
+		<!--				</exclusion>-->
+		<!--			</exclusions>-->
+		<!--		</dependency>-->
+		<!--		<dependency>-->
+		<!--			<groupId>redis.clients</groupId>-->
+		<!--			<artifactId>jedis</artifactId>-->
+		<!--		</dependency>-->
+		<dependency>
+			<groupId>org.apache.commons</groupId>
+			<artifactId>commons-pool2</artifactId>
+		</dependency>
+		<!--redis end-->
+	</dependencies>
+
+	<dependencyManagement>
+		<dependencies>
+			<dependency>
+				<groupId>org.springframework.cloud</groupId>
+				<artifactId>spring-cloud-dependencies</artifactId>
+				<version>${spring-cloud.version}</version>
+				<type>pom</type>
+				<scope>import</scope>
+			</dependency>
+		</dependencies>
+	</dependencyManagement>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.springframework.boot</groupId>
+				<artifactId>spring-boot-maven-plugin</artifactId>
+			</plugin>
+		</plugins>
+	</build>
+
+	<repositories>
+		<repository>
+			<id>spring-milestones</id>
+			<name>Spring Milestones</name>
+			<url>https://repo.spring.io/milestone</url>
+			<snapshots>
+				<enabled>false</enabled>
+			</snapshots>
+		</repository>
+	</repositories>
+
+
+</project>

+ 82 - 0
src/main/java/com/shawn/ApiLocator.java

@@ -0,0 +1,82 @@
+package com.shawn;
+
+import lombok.extern.log4j.Log4j2;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.cloud.gateway.route.RouteLocator;
+import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.MediaType;
+
+
+/**
+ * 利用 预言类,ReadBodyPredicateFactory ,发现里面缓存了request body的信息
+ **/
+@EnableAutoConfiguration
+@Configuration
+@Log4j2
+public class ApiLocator {
+
+
+    private static final String SERVICE = "/path/**";
+    private static final String URI = "http://127.0.0.1:49005";
+
+    @Bean
+    public RouteLocator myRoutes(RouteLocatorBuilder builder) {
+
+        /*
+        route1 是get请求,get请求使用readBody会报错
+        route2 是post请求,Content-Type是application/x-www-form-urlencoded,readbody为String.class
+        route3 是post请求,Content-Type是application/json,readbody为Object.class
+         */
+        RouteLocatorBuilder.Builder routes = builder.routes();
+        RouteLocatorBuilder.Builder serviceProvider = routes
+                .route("route1",
+                        r -> r
+                                .method(HttpMethod.GET)
+                                .and()
+                                .path(SERVICE)
+                                .uri(URI))
+                .route("route2",
+                        r -> r
+                                .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
+                                .and()
+                                .method(HttpMethod.POST)
+                                .and()
+                                .readBody(String.class, readBody -> { // 缓存body
+//                                    log.info("request method POST, Content-Type is application/x-www-form-urlencoded, body  is:{}", readBody);
+                                    return true;
+                                })
+                                .and()
+                                .path(SERVICE)
+                                .uri(URI))
+                .route("route3",
+                        r -> r
+                                .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
+                                .and()
+                                .method(HttpMethod.POST)
+                                .and()
+                                .readBody(Object.class, readBody -> { // 缓存body
+//                                    log.info("request method POST, Content-Type is application/json, body  is:{}", readBody);
+                                    return true;
+                                })
+                                .and()
+                                .path(SERVICE)
+                                .uri(URI))
+//                .route(p -> p
+//                                .path("/**")
+//                                .filters(f -> f
+//                                        .hystrix(config -> config
+//                                                .setName("mycmd")
+//                                                .setFallbackUri("forward:/GatewayWhiteList/fallback")))
+//                                .uri(URI))
+                ;
+
+        RouteLocator routeLocator = serviceProvider.build();
+        log.info("custom RouteLocator is loading ... {}", routeLocator);
+        return routeLocator;
+    }
+
+}

+ 108 - 0
src/main/java/com/shawn/GatewayServerApplication.java

@@ -0,0 +1,108 @@
+package com.shawn;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
+import org.springframework.cloud.gateway.config.LoadBalancerProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.web.cors.reactive.CorsUtils;
+import org.springframework.web.server.ServerWebExchange;
+import org.springframework.web.server.WebFilter;
+import org.springframework.web.server.WebFilterChain;
+import reactor.core.publisher.Mono;
+
+@Slf4j
+//@SpringBootApplication
+@Configuration
+@EnableAutoConfiguration  //启用自动配置 该框架就能够进行行为的配置,以引导应用程序的启动与运行, 根据导入的starter-pom 自动加载配置
+@ComponentScan
+@MapperScan("com.shawn.repository")
+public class GatewayServerApplication {
+
+	public static void main(String[] args) {
+		SpringApplication.run(GatewayServerApplication.class, args);
+	}
+
+	private static final String ALL = "*";
+
+	private static final String MAX_AGE = "18000L";
+	@Bean
+	public WebFilter corsFilter() {
+		return (ServerWebExchange ctx, WebFilterChain chain) -> {
+			ServerHttpRequest request = ctx.getRequest();
+
+			if (!CorsUtils.isCorsRequest(request)) {
+				return chain.filter(ctx);
+			}
+			HttpHeaders requestHeaders = request.getHeaders();
+
+			ServerHttpResponse response = ctx.getResponse();
+
+			HttpMethod requestMethod = requestHeaders.getAccessControlRequestMethod();
+
+			HttpHeaders headers = response.getHeaders();
+			headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, ALL);
+//			headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, requestHeaders.getOrigin());
+
+			String requestHeadersAllowHeaders = StringUtils.strip(String.valueOf(requestHeaders.get("Access-Control-Request-Headers")), "[]");
+//            log.info("HttpHeaders:",requestHeadersAllowHeaders);
+
+			headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, requestHeadersAllowHeaders);
+//			headers.addAll(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, requestHeaders.getAccessControlRequestHeaders());
+
+//			headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, ALL);
+			if (requestMethod != null) {
+				headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, requestMethod.name());
+			}
+			headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
+			headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, ALL);
+			headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, MAX_AGE);
+
+			HttpMethod requestMethod2 = request.getMethod();
+			if (request.getMethod() == HttpMethod.OPTIONS) {
+				response.setStatusCode(HttpStatus.OK);
+				return Mono.empty();
+			}
+
+			return chain.filter(ctx);
+		};
+	}
+
+	
+	@Bean
+    public LoadBalancerClientByKeyFilter userLoadBalanceClientFilter(LoadBalancerClient client, LoadBalancerProperties properties) {
+        return new LoadBalancerClientByKeyFilter(client, properties);
+    }
+	
+
+	/**
+	 * 获取requestbody参数后
+	 * 对于出现 Only one connection receive subscriber allowed,或者 response is set之类的信息,
+	 * 这个是springboot2.0.5之后的一个bug,
+	 * 需要在类里面添加以下方法去实现(这个是springboot开发成员提供的方法)
+	 */
+//	@Bean
+//	public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
+//		return new HiddenHttpMethodFilter() {
+//			@Override
+//			public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
+//				return chain.filter(exchange);
+//			}
+//		};
+//	}
+
+//
+}
+
+
+

+ 103 - 0
src/main/java/com/shawn/LoadBalancerClientByKeyFilter.java

@@ -0,0 +1,103 @@
+package com.shawn;
+
+import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;
+
+import java.net.URI;
+import java.util.List;
+
+import com.netflix.loadbalancer.Server;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cloud.client.ServiceInstance;
+import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
+import org.springframework.cloud.gateway.config.LoadBalancerProperties;
+import org.springframework.cloud.gateway.filter.LoadBalancerClientFilter;
+import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient;
+import org.springframework.context.annotation.Scope;
+import org.springframework.http.HttpHeaders;
+import org.springframework.stereotype.Component;
+import org.springframework.web.server.ServerWebExchange;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+//@Component
+/**
+ * 根据key 选择负载的节点
+ */
+public class LoadBalancerClientByKeyFilter extends LoadBalancerClientFilter {
+//    @Value("${server.zone.zhuhai:zhuhai}")
+//    private String zone_zhuhai;
+//    @Value("${server.zone.shanwei:shanwei}")
+//    private String zone_shanwei;
+
+    public LoadBalancerClientByKeyFilter(LoadBalancerClient loadBalancer, LoadBalancerProperties properties) {
+        super(loadBalancer, properties);
+    }
+
+    @Override
+    protected ServiceInstance choose(ServerWebExchange exchange) {
+        HttpHeaders headers = exchange.getRequest().getHeaders();
+        if(headers.containsKey("server-key")){
+            String serverKey = exchange.getRequest().getHeaders().getFirst("server-key");
+            return ZabbixLoadBalancerClient(exchange,serverKey);
+        }
+//        if(headers.containsKey("choose-server-zone")){
+//            String serverKey = exchange.getRequest().getHeaders().getFirst("choose-server");
+//            return ChooseServiceByKey(exchange,serverKey);
+//        }
+        return super.choose(exchange);
+    }
+
+
+    /**
+     * 生产上zabbix 珠海、汕尾各有一个,应用每一路去访问一个zabbix
+     * @param exchange
+     * @return
+     */
+    private ServiceInstance ZabbixLoadBalancerClient(ServerWebExchange exchange,String serverKey){
+        if (serverKey == null) {
+            return super.choose(exchange);
+        }
+        if (this.loadBalancer instanceof RibbonLoadBalancerClient) {
+            String clientIp = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
+            // 客户端ip是否汕尾
+            boolean isShanweiClientIp = false;
+            if (clientIp.startsWith("5")) {
+                isShanweiClientIp = true;
+            }
+
+            String serverIp = "";
+            if ("zhuhai".equals(serverKey)) {
+                serverIp = isShanweiClientIp ? "3.27" : "210.67";
+            } else {
+                serverIp = isShanweiClientIp ? "3.26" : "210.66";
+            }
+
+            log.info("serverKey:{} , 客户端ip:{} , 目标zabbix serverIp:{}", serverKey, clientIp, serverIp);
+
+            RibbonLoadBalancerClient client = (RibbonLoadBalancerClient) this.loadBalancer;
+            String serviceId = ((URI) exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR)).getHost();
+            return client.choose(serviceId, serverIp);
+        }
+        return super.choose(exchange);
+    }
+
+    /**
+     * 根据key 选择 加载 汕尾还是珠海 的服务
+     * @param exchange
+     * @return
+     */
+//    private ServiceInstance ChooseServiceByKey(ServerWebExchange exchange,String serverKey){
+//        if (serverKey == null) {
+//            return super.choose(exchange);
+//        }
+//        if (this.loadBalancer instanceof RibbonLoadBalancerClient) {
+//            String serverIp = "zhuhai".equals(serverKey)?zone_zhuhai:zone_shanwei;
+//            log.info("serverKey:{} , 目标 serverIp:{}", serverKey, serverIp);
+//            RibbonLoadBalancerClient client = (RibbonLoadBalancerClient) this.loadBalancer;
+//            String serviceId = ((URI) exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR)).getHost();
+//            return client.choose(serviceId, serverIp);
+//        }
+//        return super.choose(exchange);
+//    }
+}

+ 573 - 0
src/main/java/com/shawn/MyGlobalFilter.java

@@ -0,0 +1,573 @@
+package com.shawn;
+
+import com.alibaba.fastjson.JSON;
+import com.shawn.model.dto.ResultMessage;
+import com.shawn.model.entity.GatewayWhiteList;
+import com.shawn.model.entity.ReportOprDetl;
+import com.shawn.rule.NodeBalanceRule;
+import com.shawn.service.impl.GatewayWhiteListServiceImpl;
+import com.shawn.service.interfac.ReportOprDetlServiceInterface;
+import com.shawn.util.DateUtils;
+import com.shawn.util.MD5Util;
+import com.shawn.util.UniqueIDUtil;
+import com.shawn.web.Response.BodyHandlerFunction;
+import com.shawn.web.Response.BodyHandlerServerHttpResponseDecorator;
+import com.shawn.web.Response.DefaultClientResponseAdapter;
+import com.shawn.web.exception.MyException;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.GlobalFilter;
+import org.springframework.core.Ordered;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.stereotype.Component;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import java.net.URI;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+/**
+ * 定义全局性filter
+ * 记录日志
+ * 验证token,登录生成token
+ **/
+
+@Log4j2
+@Component
+public class MyGlobalFilter implements GlobalFilter, Ordered {
+    // 记录 api 流水的  redis key
+    public static String API_LOG_REDIS_KEY = "apilog";
+
+//    @Value("${crbank.test.ip}")
+//    private String testIp;
+//    @Value("${crbank.oa.ip}")
+//    private String oaIp;
+    @Value("${spring.profiles.active}")
+    private String profiles;
+
+
+    @Autowired
+    private RedisTemplate redisTemplate;
+    @Autowired
+    public GatewayWhiteListServiceImpl gatewayWhiteListService;
+    @Autowired
+    private ReportOprDetlServiceInterface reportOprDetlService;
+    public static final Long EXPIRE_TIME = 120*60L; // token 过期时间 120分钟
+    public static final String OUT_SIDE_SYS_ = "outSideSys_"; //  标志外系统token
+    private static final String COUNT_START_TIME = "countStartTime";
+    private static final String RESPONSE_BODY = "respBody";
+    private static final String OPR_REMARK = "oprRemark";
+    private static final String OPR_ID = "oprId";
+    private static final String USER_ID = "userid"; // 用户头信息
+    private static final String IF_LOG_RESPONSE = "ifLogResponse"; // 头信息 不读取解释 RESPONSE
+
+    private static final String[] LOGIN_API_LIST = new String[]{"User/PortalPotUser/getUpdatePwdCodeByPhone","User/PortalPotUser/updatePwdByPhone","User/PortalPotUser/getLoginCode","User/PortalPotUser/userLogin", "User/PortalPotUser/userAppLogin", "User/PortalPotUser/binding","User/PortalPotUser/userH5Login"}; // 登录接口url
+    private static ExecutorService pool = Executors.newFixedThreadPool(254);
+
+    /**
+     * 403 网段,401 token,406 param
+     * @param exchange
+     * @param chain
+     * @return
+     */
+    @Override
+    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+        String oprId = UniqueIDUtil.getUniqueID();
+        try {
+            exchange.getAttributes().put(OPR_ID, oprId);
+            String url = exchange.getRequest().getURI().getPath();
+            String userId = exchange.getRequest().getHeaders().getFirst(USER_ID);
+
+            // checkToken 接口不校验
+            if(url.contains("/GatewayWhiteList/checkToken")){
+                return chain.filter(exchange);
+            }
+
+            if("ScheduledServer".equals(userId)){
+                String remark = URLDecoder.decode(exchange.getRequest().getHeaders().getFirst("remark"), "utf-8");
+                log.info("oprId:{},请求url:{},这是定时任务系统请求!任务名:{}",oprId,url,remark);
+            }else{
+                log.info("oprId:{},请求url:{}",oprId,url);
+            }
+
+            // 没有token的,判断是否内系统的白名单,3项不校验,则跳过
+            if(!exchange.getRequest().getHeaders().containsKey(HttpHeaders.AUTHORIZATION)){
+                List<GatewayWhiteList> whiteList = gatewayWhiteListService.getWhiteList();
+                Optional op = whiteList.stream().filter(e -> "0".equals(e.getIfOutsideSys()) && "0".equals(e.getIfCheckParam())
+                        && "0".equals(e.getIfCheckToken())&& "0".equals(e.getIfLogResponse()))
+                        .filter(e -> url.contains(e.getUrl())).findFirst();
+                if(op.isPresent()){
+                    log.info("oprId:{},请求url:{},内系统,白名单3项不校验,则跳过",oprId,url);
+                    return chain.filter(exchange);
+                }
+            }
+//            if(url.contains("/myEureka")){//重定向
+//                final String clientIp = exchange.getRequest().getURI().getHost();
+//                String redictUrl = "http://"+clientIp+":49014";
+//                log.info("redictUrl:"+redictUrl);
+//                ServerHttpResponse response = exchange.getResponse();
+//                response.setStatusCode(HttpStatus.SEE_OTHER);
+//                response.getHeaders().set("Location", redictUrl);
+//                return exchange.getResponse().setComplete();
+//            }
+            // 设置api访问开始时间
+            exchange.getAttributes().put(COUNT_START_TIME, System.currentTimeMillis());
+
+            //校验网段检查
+            try {
+                checkNetwork(exchange);
+            } catch (MyException e) {
+                log.info("oprId:{},校验网段检查 不通过:{}",oprId,HttpStatus.FORBIDDEN);
+                return throwExceptionResponse(exchange.getResponse(), e.getMessage(), HttpStatus.FORBIDDEN);
+            }
+            // 过滤内部服务的httpclient请求,不做校验
+            boolean isInnerServerHttpClient = false;
+            String innerServerHttpClient = exchange.getRequest().getHeaders().getFirst("innerServerHttpClient");
+            if (StringUtils.isNotEmpty(innerServerHttpClient)) {
+                if ("1".equals(innerServerHttpClient)) {
+                    isInnerServerHttpClient = true;
+                    String remark = exchange.getRequest().getHeaders().getFirst("remark");
+                    if(StringUtils.isNotEmpty(remark)){
+                        // 记录请求的remark
+                        exchange.getAttributes().put(OPR_REMARK,remark);
+                    }
+                }
+            }
+            String token = "";
+            if(!isInnerServerHttpClient) {
+                // 校验token
+                try {
+                    token = checkToken(exchange);
+                } catch (MyException e) {
+                    log.info("oprId:{},checkToken 不通过:{}",oprId,HttpStatus.UNAUTHORIZED);
+                    return throwExceptionResponse(exchange.getResponse(), e.getMessage(), HttpStatus.UNAUTHORIZED);
+                }
+
+                // 判断是否外部系统
+                boolean isOutSideSysWhiteList = false;
+                if (token.contains(OUT_SIDE_SYS_)) {
+                    // 判断是否 外部系统白名单url
+                    if (gatewayWhiteListService.ifOutsideSysWhiteList(exchange.getRequest(), token)) {
+                        // 外系统白名单,不做参数校验
+                        isOutSideSysWhiteList = true;
+                    } else { // 外系统,但没有配置该白名单,禁止访问
+                        log.info("oprId:{},外系统,但没有配置该白名单,禁止访问:406",oprId);
+                        return throwExceptionResponse(exchange.getResponse(), "{\"code\":406,\"message\":\"外系统无权限访问,请联系管理员\"}", HttpStatus.NOT_ACCEPTABLE);
+                    }
+                }
+                // 文件上传接口, 不做后面校验,不记录日志
+                String contentType = exchange.getRequest().getHeaders().getFirst("Content-Type");
+                if (StringUtils.isNotEmpty(contentType)) {
+                    if (contentType.contains(MediaType.MULTIPART_FORM_DATA_VALUE)) {
+                        return chain.filter(exchange);
+                    }
+                }
+                // 校验md5 参数加密
+                if (!isOutSideSysWhiteList) { // 外系统白名单,不做参数校验
+                    try {
+                        checkParamMD5(exchange);
+                    } catch (MyException e) {
+                        log.info("oprId:{},校验md5 参数加密 不通过:406",oprId);
+                        return throwExceptionResponse(exchange.getResponse(), e.getMessage(), HttpStatus.NOT_ACCEPTABLE);
+                    }
+                }
+            }
+            // 判断是否 不读取原始相应
+            boolean ifLogResponse = "1".equals(exchange.getRequest().getHeaders().getFirst(IF_LOG_RESPONSE));
+//        log.info("url:{};ifLogResponse:{},ifLogResponse2:{}",exchange.getRequest().getURI().getPath(),exchange.getRequest().getHeaders().getFirst(IF_LOG_RESPONSE),ifLogResponse);
+            if(ifLogResponse){ // 先查看头配置,再看白名单表配置
+                ifLogResponse = gatewayWhiteListService.ifLogResponse(exchange.getRequest());
+            }
+            //重写原始响应
+            BodyHandlerServerHttpResponseDecorator responseDecorator = new BodyHandlerServerHttpResponseDecorator(
+                    initBodyHandler(exchange), exchange.getResponse());
+
+            //添加头信息,向headers 中放userId
+            ServerHttpRequest host = exchange.getRequest().mutate().header(USER_ID, token).build();
+            return chain.filter(ifLogResponse ? exchange.mutate().request(host).response(responseDecorator).build() : exchange).then(Mono.fromRunnable(() -> {
+                // 记录访问日志
+                Thread thread = new InsertLogThread(exchange);
+                pool.execute(thread);
+            }));
+        } catch (Exception e) {
+            log.error("oprId:{},gateway发生错误:{}",oprId,e);
+            return null;
+        }
+    }
+
+    /**
+     * 参数加密 比对校验
+     *
+     * @param exchange
+     * @throws MyException
+     */
+    private void checkParamMD5(ServerWebExchange exchange) throws MyException {
+        // 获取请求的路径
+        if (!gatewayWhiteListService.ifCheckParam(exchange.getRequest())) { // 不校验参数
+            return;
+        }
+        String url = exchange.getRequest().getURI().getPath();
+        MultiValueMap<String, String> queryParam = exchange.getRequest().getQueryParams();
+        Object requestBody = exchange.getAttribute("cachedRequestBodyObject");
+
+        Map param = null;
+        if (!queryParam.isEmpty()) {
+            param = queryParam.toSingleValueMap();
+        } else {
+            if (null != requestBody) {
+                try {
+                    param = JSON.parseObject(String.valueOf(requestBody), Map.class);
+                } catch (Exception e) {
+                    log.debug("是否上传接口?");
+                }
+
+            }
+        }
+
+        List<String> keyList = new ArrayList<>();
+        List<String> valList = new ArrayList<>();
+        if (null != param) {
+            final Map<String, Object> finalParam = param;
+            keyList = finalParam.keySet().stream().sorted().collect(Collectors.toList());
+            valList = keyList.stream().map(key -> {
+                String val = "";
+                if (finalParam.get(key) instanceof String || finalParam.get(key) instanceof Number ) {
+//                    val = new String(String.valueOf(finalParam.get(key)).getBytes(StandardCharsets.UTF_8));
+                    val = String.valueOf(finalParam.get(key));
+                    if("true".equals(val) || "false".equals(val)){
+                        val = "";
+                    }
+                }
+                return val.length() >= 50 ? val.substring(0, 50) : val;
+            }).collect(Collectors.toList());
+        }
+        Object[] md5List = new Object[]{url, keyList, valList};
+        String md5Str = JSON.toJSONString(md5List);
+        String md5 = MD5Util.getMD5(md5Str);
+        String requestMd5 = exchange.getRequest().getHeaders().getFirst("VALIDATE");
+        if (!md5.equals(requestMd5)) {
+//            log.info("参数加密比对不一致,url=[{}],queryParam=[{}], bodyParam=[{}], md5Str=[{}] ,VALIDATE=[{}],md5=[{}]",
+//                    exchange.getRequest().getURI(),queryParam,requestBody,md5Str,requestMd5,md5);
+            if (!this.isDev() ) {
+                throw new MyException("{\"code\":406,\"message\":\"不接受外系统访问!\"}");
+            } else {
+                Map<String, Object> exceptionMap = new HashMap<>();
+                exceptionMap.put("code", 406);
+                exceptionMap.put("message", "不接受外系统访问!");
+                exceptionMap.put("md5Str", md5Str);
+                exceptionMap.put("md5", md5);
+                throw new MyException(JSON.toJSONString(exceptionMap));
+//                throw new MyException("{\"code\":406,\"message\":\"不接受外系统访问!\",\"md5Str\":\""+md5Str+"\",\"md5\":\""+md5+"\"}");
+            }
+        }
+    }
+
+    /**
+     * 返回错误响应
+     *
+     * @param serverHttpResponse
+     * @param msg
+     * @param status
+     * @return
+     */
+    private Mono<Void> throwExceptionResponse(ServerHttpResponse serverHttpResponse, String msg, HttpStatus status) {
+        serverHttpResponse.setStatusCode(status);
+        HttpHeaders httpHeaders = serverHttpResponse.getHeaders();
+        httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
+        byte[] bytes = msg.getBytes(StandardCharsets.UTF_8);
+        DataBuffer buffer = serverHttpResponse.bufferFactory().wrap(bytes);
+        return serverHttpResponse.writeWith(Flux.just(buffer));
+    }
+
+    /**
+     * 网段检查
+     *
+     * @param exchange
+     * @throws MyException
+     */
+    private void checkNetwork(ServerWebExchange exchange) throws MyException {
+        ServerHttpRequest req = exchange.getRequest();
+        String clientIp = req.getRemoteAddress().getAddress().getHostAddress();
+        // 获取请求的路径
+        URI uri = req.getURI();
+        String[] urls = uri.getPath().split("/");
+        String serviceId = urls[0] + urls[1];
+        // 若客户端为测试网,则只允许ITSM访问后台
+//        if (StringUtils.isNotEmpty(clientIp) && testIp.equals(clientIp)) {
+////            log.info("client is sit network, ip is :"+clientIp+",sys id is:"+serviceId);
+//            if ("REMOTE-SERVER".equals(serviceId) // 远程管控.部署平台.指挥
+//                    || "DEPLOY-SERVER".equals(serviceId)
+//                    || "COMMANDER-SERVER".equals(serviceId)
+//            ) {
+//                throw new MyException("{\"code\":403,\"message\":\"当前网络无法访问,请切换生产网络刷新\"}");
+//            }
+//        }
+//        // 限制oa网的部署平台
+//        if (StringUtils.isNotEmpty(clientIp) && oaIp.equals(clientIp)) {
+////            log.info("client is sit network, ip is :"+clientIp+",sys id is:"+serviceId);
+//            String sysId = req.getHeaders().getFirst("sysId");
+//            if ("DEPLOY-SERVER".equals(serviceId) && !"app".equals(sysId)) {
+//                throw new MyException("{\"code\":403,\"message\":\"当前网络无法访问,请切换生产网络刷新\"}");
+//            }
+//        }
+    }
+
+    /**
+     * 是否登录API,不做校验
+     *
+     * @param request
+     * @return
+     */
+    private boolean isLoginApi(ServerHttpRequest request) {
+        // 获取请求的路径
+        String url = request.getURI().getPath();
+        for (String LOGIN_API : LOGIN_API_LIST) {
+            if (url.contains(LOGIN_API)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 校验token
+     *
+     * @return
+     */
+    private String checkToken(ServerWebExchange exchange) throws MyException {
+        ServerHttpRequest request = exchange.getRequest();
+        // 获取请求的路径
+        if (isLoginApi(request) || !gatewayWhiteListService.ifCheckToken(request)) { // 登录接口、白名单url,不校验
+            return "";
+        }
+        //获取认证名称
+        String authName = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
+        String token = null;
+        if (authName != null && !"".equals(authName)) {
+            //用户请求时会在头部 Authorization 传给我之前存储的token, 我用来验证
+            authName = authName.replace("Bearer ", "");
+            //查询redis是否有token
+            if (redisTemplate.hasKey(authName)) {
+                //获取redis里面数据的存活时间
+                Long expirationDate = redisTemplate.getExpire(authName, TimeUnit.SECONDS);
+                //如果还在有效期,重置redis里面数据的存活时间
+                if (expirationDate > 0) {
+                    redisTemplate.expire(authName, EXPIRE_TIME, TimeUnit.SECONDS);
+                    token = (String) redisTemplate.opsForValue().get(authName);
+                }
+            }
+        }
+        //*******************开始拦截****************************
+        //没有加认证token 就没有访问权限
+        if (StringUtils.isEmpty(authName)) {
+            throw new MyException("{\"code\":401,\"message\":\"没有访问权限!\"}");
+        } else if (token == null) {
+            //token失效了
+            //用户提供的token检测出和redis不一样
+            throw new MyException("{\"code\":401,\"message\":\"令牌失效,请重新登录!\"}");
+        }
+        //*******************结束拦截****************************
+        return token;
+    }
+
+    // 设置filter 的执行顺序,越小值,越早执行,其它filter不要大于该值
+    @Override
+    public int getOrder() {
+        return -1;
+    }
+
+    /**
+     * 响应body处理,添加响应的打印
+     *
+     * @param exchange
+     * @return
+     */
+    protected BodyHandlerFunction initBodyHandler(ServerWebExchange exchange) {
+        return (resp, body) -> {
+            MediaType originalResponseContentType = resp.getHeaders().getContentType();
+
+            HttpHeaders httpHeaders = new HttpHeaders();
+            httpHeaders.setContentType(originalResponseContentType);
+
+            DefaultClientResponseAdapter clientResponseAdapter = new DefaultClientResponseAdapter(body, httpHeaders);
+            Mono<String> bodyMono = clientResponseAdapter.bodyToMono(String.class);
+            return bodyMono.flatMap((respBody) -> {
+                //如果是登录接口,并访问成功,则增加token
+                if (resp.getStatusCode().is2xxSuccessful() && isLoginApi(exchange.getRequest())) { // 登录接口,生成token
+                    respBody = addLoginToken(respBody);
+                }
+                //打印返回响应日志
+//                log.info("[Trace:{}]-gateway response:ct=[{}], status=[{}],headers=[{}],body=[{}]", trace,
+//                        System.currentTimeMillis() - startTime, resp.getStatusCode(), resp.getHeaders(), respBody);
+
+                String oprId = exchange.getAttribute(OPR_ID);
+                if(StringUtils.isEmpty(oprId)){
+                    oprId = UniqueIDUtil.getUniqueID();
+                    exchange.getAttributes().put(OPR_ID, oprId);
+                }
+
+                if (resp.getStatusCode().value()!=200) { // 异常,记录返回相应体
+                    //缓存respBody
+                    final String respBody_str = JSON.toJSONString(respBody);
+                    log.error("oprId:{},异常 respBody_str:{}",oprId,respBody_str);
+                    exchange.getAttributes().put(RESPONSE_BODY, respBody_str);
+                }
+                // 如果是5XX服务错误,直接返回统一错误信息
+                if(resp.getStatusCode().is5xxServerError() && !this.isDev()){
+                    Map respBodyJson = JSON.parseObject(respBody, Map.class);
+                    respBodyJson.put("message","服务器后台在"+DateUtils.formatDate(new Date(),DateUtils.PATTERN_yyyy_MM_dd_HH_mm_ss)+" 发生错误:"+oprId + " ; 请联系系统管理员或服务台");
+                    respBody = JSON.toJSONString(respBodyJson);
+                }
+                return resp.writeWith(Flux.just(respBody).map(bx -> resp.bufferFactory().wrap(bx.getBytes(StandardCharsets.UTF_8))));
+            }).then();
+        };
+    }
+
+    /**
+     * 登录后,新增token
+     *
+     * @param respBody
+     * @return
+     */
+    private String addLoginToken(String respBody) {
+        ResultMessage resultMessage = JSON.parseObject(respBody, ResultMessage.class);
+        if (resultMessage.isCode()) {
+            try {
+                Map<String, Object> data = (Map<String, Object>) resultMessage.getData();
+                Map<String, Object> userObj = JSON.parseObject(String.valueOf(data.get("userObj")));
+                String userId = String.valueOf(userObj.get("userId"));
+                //生成token
+                String token = UniqueIDUtil.getToken();
+                data.put("token", token);
+                //存储redis里
+                redisTemplate.opsForValue().set(token, userId, EXPIRE_TIME, TimeUnit.SECONDS);
+                return JSON.toJSONString(resultMessage.setData(data));
+            } catch (Exception e) {
+                log.debug(e);
+            }
+        }
+
+        return respBody;
+    }
+
+    /**
+     * 是否测试环境
+     *
+     * @return
+     */
+    public boolean isDev() {
+        if("dev".equals(profiles)){
+            return true;
+        }
+        if ("prod".equals(profiles)) {
+            return false;
+        }
+        return true;
+    }
+
+
+    /**
+     * 日志打印线程
+     */
+    class InsertLogThread extends Thread {
+        ServerWebExchange exchange;
+
+        public InsertLogThread(ServerWebExchange exchange) {
+            this.exchange = exchange;
+        }
+
+        @Override
+        public void run() {
+            String oprId = "";
+            try {
+                oprId = exchange.getAttribute(OPR_ID);
+                if(StringUtils.isEmpty(oprId)){
+                    oprId = UniqueIDUtil.getUniqueID();
+                }
+
+                ServerHttpRequest req = exchange.getRequest();
+                String clientIp = req.getRemoteAddress().getAddress().getHostAddress();
+                // 获取请求的路径
+                URI uri = req.getURI();
+                String[] urls = uri.getPath().split("/");
+                String serviceId = urls[0] + urls[1];
+                MultiValueMap<String, String> queryParam = req.getQueryParams();
+                Object requestBody = exchange.getAttribute("cachedRequestBodyObject");
+                String method = req.getMethodValue().toUpperCase();
+
+                int statusCode = exchange.getResponse().getStatusCode().value();
+                String userId = req.getHeaders().getFirst(USER_ID);
+                String reportId = req.getHeaders().getFirst("reportId"); // 记录报表查询操作人
+                Date date = new Date();
+                Long startTime = exchange.getAttribute(COUNT_START_TIME);
+                Long endTime = (System.currentTimeMillis() - startTime);
+                ReportOprDetl reportOprDetl = new ReportOprDetl();
+                reportOprDetl.setOprStsCode(String.valueOf(statusCode));
+                reportOprDetl.setOprUser(userId);
+                reportOprDetl.setOprServiceId(serviceId);
+                reportOprDetl.setOprUrl(uri.getPath());
+                reportOprDetl.setOprDate(DateUtils.formatDate(date, DateUtils.PATTERN_yyyyMMdd));
+                reportOprDetl.setOprTime(DateUtils.formatDate(date, DateUtils.PATTERN_HHmmss));
+                reportOprDetl.setOprTimestamp(date);
+                reportOprDetl.setOprMethod(method);
+                reportOprDetl.setOprCost(String.valueOf(endTime) + "ms");
+                String oprRmk = exchange.getAttribute(OPR_REMARK);
+                reportOprDetl.setOprRmk(StringUtils.isNotEmpty(oprRmk)?oprRmk:"");
+                reportOprDetl.setReqIp(clientIp);
+                reportOprDetl.setGatewayIp(NodeBalanceRule.getLocalIP());
+                reportOprDetl.setOprReq(reportId);
+
+
+                String queryParamStr = queryParam.isEmpty() ? "" : JSON.toJSONString(queryParam);
+                String requestBodyStr = "";
+                if (null != requestBody) {
+                    try {
+                        requestBodyStr = JSON.toJSONString(JSON.parse(String.valueOf(requestBody)));
+                    } catch (Exception e) {
+                    }
+                }
+
+                queryParamStr = queryParamStr.substring(0, queryParamStr.length() >= 4000 ? 4000 : queryParamStr.length());
+                requestBodyStr = requestBodyStr.substring(0, requestBodyStr.length() >= 4000 ? 4000 : requestBodyStr.length());
+
+                reportOprDetl.setQueryParam(queryParamStr);
+                reportOprDetl.setBodyParam(requestBodyStr);
+
+
+                if (statusCode != 200) { // 异常,记录返回相应体
+                    String respBody = exchange.getAttribute(RESPONSE_BODY);
+                    log.error("oprId: {} 访问失败 ,statusCode:{},uri:{},requestBody:{},错误信息:{}",oprId,statusCode,uri, requestBody,respBody);
+                    if(StringUtils.isNotEmpty(respBody)){
+                        reportOprDetl.setMsg(respBody.length() > 3900 ? respBody.substring(0, 3900) : respBody);
+                    }
+                }else{
+                    log.info("oprId: {} 访问成功!,statusCode:{},uri:{}",oprId,statusCode,uri);
+                }
+//                log.info("oprId:"+oprId);
+                reportOprDetl.setOprId(oprId);
+                redisTemplate.opsForList().rightPush(API_LOG_REDIS_KEY, reportOprDetl);
+            } catch (Exception e) {
+                log.error("oprId:{}, 新增请求日志报错:{}", oprId, e);
+            }
+        }
+
+    }
+
+}

+ 26 - 0
src/main/java/com/shawn/OprDetlGatewayFilterFactory.java

@@ -0,0 +1,26 @@
+package com.shawn;
+
+import lombok.extern.log4j.Log4j2;
+import org.springframework.cloud.gateway.filter.GatewayFilter;
+import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
+import org.springframework.http.HttpHeaders;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+@Log4j2
+@Component
+public class OprDetlGatewayFilterFactory<C> extends AbstractGatewayFilterFactory<C> {
+	@Override
+	public GatewayFilter apply(C config) {
+		return (exchange, chain) -> {
+//			log.info("run OprDetlGatewayFilter");
+			return chain.filter(exchange).then(Mono.fromRunnable(() -> {
+				// 新版本需要重写ACCESS_CONTROL_ALLOW_ORIGIN,否则会出现2个,前端会报错
+				HttpHeaders headers = exchange.getResponse().getHeaders();
+				headers.remove(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN);
+				headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
+				return;
+			}));
+		};
+	}
+
+}

+ 43 - 0
src/main/java/com/shawn/common/cache/RedisConfig.java

@@ -0,0 +1,43 @@
+//package com.shawn.common.cache;
+//
+//import com.fasterxml.jackson.annotation.JsonAutoDetect;
+//import com.fasterxml.jackson.annotation.PropertyAccessor;
+//import com.fasterxml.jackson.databind.ObjectMapper;
+//import lombok.extern.slf4j.Slf4j;
+//import org.springframework.context.annotation.Bean;
+//import org.springframework.context.annotation.Configuration;
+//import org.springframework.data.redis.connection.RedisConnectionFactory;
+//import org.springframework.data.redis.core.RedisTemplate;
+//import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
+//import org.springframework.data.redis.serializer.StringRedisSerializer;
+//
+//@Slf4j
+//@Configuration
+////@EnableCaching // 开启缓存支持
+//public class RedisConfig {
+//    @Bean
+//    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
+//        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
+//        redisTemplate.setConnectionFactory(redisConnectionFactory);
+//
+//
+//        // 使用Jackson2JsonRedisSerialize 替换默认序列化
+//        @SuppressWarnings("rawtypes")
+//        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
+//
+//
+//        ObjectMapper objectMapper = new ObjectMapper();
+//        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+//        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
+//
+//
+//        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
+//
+//
+//        // 设置value的序列化规则和 key的序列化规则
+//        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
+//        redisTemplate.setKeySerializer(new StringRedisSerializer());
+//        redisTemplate.afterPropertiesSet();
+//        return redisTemplate;
+//    }
+//}

+ 37 - 0
src/main/java/com/shawn/common/myFormat/DateSerializer.java

@@ -0,0 +1,37 @@
+package com.shawn.common.myFormat;
+
+import java.io.IOException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+/**
+ * @author wuhs
+ * 解决json日期绑定问题:
+ *Can not deserialize value of type java.util.Date from String "2017-10-31 14:51:18": not a valid representation (error: Failed to parse Date value '2017-10-31 14:51:18': Can not parse date "2017-10-31 14:51:18Z": while it seems to fit format 'yyyy-MM-dd'T'HH:mm:ss.SSS'Z''
+ *
+ *使用方法:在需要绑定的字段加 @JsonDeserialize(using=DateSerializer.class)
+ */
+public class DateSerializer extends JsonDeserializer<Date> {
+
+    private SimpleDateFormat dateFormat = new SimpleDateFormat(
+            "yyyy-MM-dd HH:mm:ss");
+
+    @Override
+    public Date deserialize(JsonParser paramJsonParser,
+            DeserializationContext paramDeserializationContext)
+            throws IOException, JsonProcessingException {
+        String str = paramJsonParser.getText().trim();
+        try {
+            return dateFormat.parse(str);
+        } catch (ParseException e) {
+
+        }
+        return paramDeserializationContext.parseDate(str);
+    }
+}

+ 16 - 0
src/main/java/com/shawn/constant/DatabaseType.java

@@ -0,0 +1,16 @@
+package com.shawn.constant;
+
+public enum DatabaseType {
+	/**
+	 * Oracle
+	 */
+	db1,
+	/**
+	 * spark hive
+	 */
+	db2,
+	/**
+	 * postgresql
+	 */
+	db3
+}

+ 19 - 0
src/main/java/com/shawn/constant/ErrorCode.java

@@ -0,0 +1,19 @@
+package com.shawn.constant;
+
+/**
+ * @author 吴洪双
+ */
+public class ErrorCode {
+
+    public static final int SERVER_INTERNAL_ERROR = 1000;
+    public static final int PARAMETER_MISSING_ERROR = 1001;
+    public static final int PARAMETER_ILLEGAL_ERROR = 1002;
+    public static final int RESOURCE_NOT_FOUND_ERROR = 1003;
+
+    /**
+     * Prevent instantiation
+     */
+    private ErrorCode() {
+    }
+
+}

+ 19 - 0
src/main/java/com/shawn/constant/PageConstant.java

@@ -0,0 +1,19 @@
+package com.shawn.constant;
+
+/**
+ * @author 吴洪双
+ */
+public class PageConstant {
+
+    public static final int PAGE = 1; // 页码
+    public static final int LIMIT = 10; // 每页条数
+    public static final int OFFSET = 0; // 第几条起
+    public static final String ORDER = "asc"; // 排序
+
+    /**
+     * Prevent instantiation
+     */
+    private PageConstant() {
+    }
+
+}

+ 31 - 0
src/main/java/com/shawn/model/bean/PageBean.java

@@ -0,0 +1,31 @@
+package com.shawn.model.bean;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+
+
+/**
+ * @author 吴洪双
+ */
+@Accessors(chain = true)
+@NoArgsConstructor
+@Getter
+@Setter
+@ToString
+public class PageBean {
+	@JsonIgnore
+    protected String orderByClause;
+    @JsonIgnore
+    protected boolean distinct;
+    @JsonIgnore
+    private Integer limit;
+    @JsonIgnore
+    private Integer offset;
+
+	
+}

+ 26 - 0
src/main/java/com/shawn/model/dto/Error.java

@@ -0,0 +1,26 @@
+package com.shawn.model.dto;
+
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * @author 吴洪双
+ */
+@Accessors(chain = true)
+@NoArgsConstructor
+@Getter
+@Setter
+@ToString
+public class Error implements Serializable {
+
+    private static final long serialVersionUID = 7660756960387438399L;
+
+    private int code; // Error code
+    private String message; // Error message
+
+}

+ 29 - 0
src/main/java/com/shawn/model/dto/PaginatedResult.java

@@ -0,0 +1,29 @@
+package com.shawn.model.dto;
+
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * @author 吴洪双
+ */
+@Accessors(chain = true)
+@NoArgsConstructor
+@Getter
+@Setter
+@ToString
+public class PaginatedResult implements Serializable {
+
+    private static final long serialVersionUID = 6191745064790884707L;
+
+    private boolean code; // Error code
+    private int currentPage; // 当前页数
+    private int totalPage; // 总页数
+    private int total; // 总条数
+    private Object data; // Paginated resources
+
+}

+ 26 - 0
src/main/java/com/shawn/model/dto/ResultMessage.java

@@ -0,0 +1,26 @@
+package com.shawn.model.dto;
+
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * @author 吴洪双
+ */
+@Accessors(chain = true)
+@NoArgsConstructor
+@Getter
+@Setter
+@ToString
+public class ResultMessage<T> implements Serializable {
+	
+    private static final long serialVersionUID = 7660756960387438399L;
+    private boolean code; // Error code
+    private String message; // Error message
+    private T data; // Error message
+
+}

+ 49 - 0
src/main/java/com/shawn/model/entity/GatewayWhiteList.java

@@ -0,0 +1,49 @@
+package com.shawn.model.entity;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+
+@Accessors(chain = true)
+@NoArgsConstructor
+@Getter
+@Setter
+@ToString
+public class GatewayWhiteList {
+    
+	private String id;
+
+	private String ifOutsideSys;
+
+	private String serverId;
+
+	private String url;
+
+	private String ifCheckToken;
+
+	private String ifCheckParam;
+
+	private String ifLogResponse;
+
+	private String remark;
+
+	/**自定义统一方法设置主键**/
+	public void setPrimaryKey(String primaryKey) {
+		 setId(primaryKey);
+	}
+
+	/**自定义统一方法获取主键**/
+	@JsonIgnore
+	public String getPrimaryKey() {
+		 return getId();
+	}
+
+	/**判断该实体是否存在主键**/
+	public boolean hasPrimaryKey() {
+		return true;
+	}
+
+}

+ 798 - 0
src/main/java/com/shawn/model/entity/GatewayWhiteListExample.java

@@ -0,0 +1,798 @@
+package com.shawn.model.entity;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class GatewayWhiteListExample {
+    /**
+     * gateway_white_list
+     */
+    protected String orderByClause;
+
+    /**
+     * gateway_white_list
+     */
+    protected boolean distinct;
+
+    /**
+     * gateway_white_list
+     */
+    protected List<Criteria> oredCriteria;
+
+    private Integer limit;
+
+    private Integer offset;
+
+    public GatewayWhiteListExample() {
+        oredCriteria = new ArrayList<Criteria>();
+    }
+
+    public void setOrderByClause(String orderByClause) {
+        this.orderByClause = orderByClause;
+    }
+
+    public String getOrderByClause() {
+        return orderByClause;
+    }
+
+    public void setDistinct(boolean distinct) {
+        this.distinct = distinct;
+    }
+
+    public boolean isDistinct() {
+        return distinct;
+    }
+
+    public List<Criteria> getOredCriteria() {
+        return oredCriteria;
+    }
+
+    public void or(Criteria criteria) {
+        oredCriteria.add(criteria);
+    }
+
+    public Criteria or() {
+        Criteria criteria = createCriteriaInternal();
+        oredCriteria.add(criteria);
+        return criteria;
+    }
+
+    public Criteria createCriteria() {
+        Criteria criteria = createCriteriaInternal();
+        if (oredCriteria.size() == 0) {
+            oredCriteria.add(criteria);
+        }
+        return criteria;
+    }
+
+    protected Criteria createCriteriaInternal() {
+        Criteria criteria = new Criteria();
+        return criteria;
+    }
+
+    public void clear() {
+        oredCriteria.clear();
+        orderByClause = null;
+        distinct = false;
+    }
+
+    public void setLimit(Integer limit) {
+        this.limit = limit;
+    }
+
+    public Integer getLimit() {
+        return limit;
+    }
+
+    public void setOffset(Integer offset) {
+        this.offset = offset;
+    }
+
+    public Integer getOffset() {
+        return offset;
+    }
+
+    /**
+     * gateway_white_list 2019-07-24
+     */
+    protected abstract static class GeneratedCriteria {
+        protected List<Criterion> criteria;
+
+        protected GeneratedCriteria() {
+            super();
+            criteria = new ArrayList<Criterion>();
+        }
+
+        public boolean isValid() {
+            return criteria.size() > 0;
+        }
+
+        public List<Criterion> getAllCriteria() {
+            return criteria;
+        }
+
+        public List<Criterion> getCriteria() {
+            return criteria;
+        }
+
+        protected void addCriterion(String condition) {
+            if (condition == null) {
+                throw new RuntimeException("Value for condition cannot be null");
+            }
+            criteria.add(new Criterion(condition));
+        }
+
+        protected void addCriterion(String condition, Object value, String property) {
+            if (value == null) {
+                throw new RuntimeException("Value for " + property + " cannot be null");
+            }
+            criteria.add(new Criterion(condition, value));
+        }
+
+        protected void addCriterion(String condition, Object value1, Object value2, String property) {
+            if (value1 == null || value2 == null) {
+                throw new RuntimeException("Between values for " + property + " cannot be null");
+            }
+            criteria.add(new Criterion(condition, value1, value2));
+        }
+
+        public Criteria andIdIsNull() {
+            addCriterion("id is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdIsNotNull() {
+            addCriterion("id is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdEqualTo(String value) {
+            addCriterion("id =", value, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdNotEqualTo(String value) {
+            addCriterion("id <>", value, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdGreaterThan(String value) {
+            addCriterion("id >", value, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdGreaterThanOrEqualTo(String value) {
+            addCriterion("id >=", value, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdLessThan(String value) {
+            addCriterion("id <", value, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdLessThanOrEqualTo(String value) {
+            addCriterion("id <=", value, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdLike(String value) {
+            addCriterion("id like", value, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdNotLike(String value) {
+            addCriterion("id not like", value, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdIn(List<String> values) {
+            addCriterion("id in", values, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdNotIn(List<String> values) {
+            addCriterion("id not in", values, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdBetween(String value1, String value2) {
+            addCriterion("id between", value1, value2, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIdNotBetween(String value1, String value2) {
+            addCriterion("id not between", value1, value2, "id");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfOutsideSysIsNull() {
+            addCriterion("if_outside_sys is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfOutsideSysIsNotNull() {
+            addCriterion("if_outside_sys is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfOutsideSysEqualTo(String value) {
+            addCriterion("if_outside_sys =", value, "ifOutsideSys");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfOutsideSysNotEqualTo(String value) {
+            addCriterion("if_outside_sys <>", value, "ifOutsideSys");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfOutsideSysGreaterThan(String value) {
+            addCriterion("if_outside_sys >", value, "ifOutsideSys");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfOutsideSysGreaterThanOrEqualTo(String value) {
+            addCriterion("if_outside_sys >=", value, "ifOutsideSys");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfOutsideSysLessThan(String value) {
+            addCriterion("if_outside_sys <", value, "ifOutsideSys");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfOutsideSysLessThanOrEqualTo(String value) {
+            addCriterion("if_outside_sys <=", value, "ifOutsideSys");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfOutsideSysLike(String value) {
+            addCriterion("if_outside_sys like", value, "ifOutsideSys");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfOutsideSysNotLike(String value) {
+            addCriterion("if_outside_sys not like", value, "ifOutsideSys");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfOutsideSysIn(List<String> values) {
+            addCriterion("if_outside_sys in", values, "ifOutsideSys");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfOutsideSysNotIn(List<String> values) {
+            addCriterion("if_outside_sys not in", values, "ifOutsideSys");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfOutsideSysBetween(String value1, String value2) {
+            addCriterion("if_outside_sys between", value1, value2, "ifOutsideSys");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfOutsideSysNotBetween(String value1, String value2) {
+            addCriterion("if_outside_sys not between", value1, value2, "ifOutsideSys");
+            return (Criteria) this;
+        }
+
+        public Criteria andServerIdIsNull() {
+            addCriterion("server_id is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andServerIdIsNotNull() {
+            addCriterion("server_id is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andServerIdEqualTo(String value) {
+            addCriterion("server_id =", value, "serverId");
+            return (Criteria) this;
+        }
+
+        public Criteria andServerIdNotEqualTo(String value) {
+            addCriterion("server_id <>", value, "serverId");
+            return (Criteria) this;
+        }
+
+        public Criteria andServerIdGreaterThan(String value) {
+            addCriterion("server_id >", value, "serverId");
+            return (Criteria) this;
+        }
+
+        public Criteria andServerIdGreaterThanOrEqualTo(String value) {
+            addCriterion("server_id >=", value, "serverId");
+            return (Criteria) this;
+        }
+
+        public Criteria andServerIdLessThan(String value) {
+            addCriterion("server_id <", value, "serverId");
+            return (Criteria) this;
+        }
+
+        public Criteria andServerIdLessThanOrEqualTo(String value) {
+            addCriterion("server_id <=", value, "serverId");
+            return (Criteria) this;
+        }
+
+        public Criteria andServerIdLike(String value) {
+            addCriterion("server_id like", value, "serverId");
+            return (Criteria) this;
+        }
+
+        public Criteria andServerIdNotLike(String value) {
+            addCriterion("server_id not like", value, "serverId");
+            return (Criteria) this;
+        }
+
+        public Criteria andServerIdIn(List<String> values) {
+            addCriterion("server_id in", values, "serverId");
+            return (Criteria) this;
+        }
+
+        public Criteria andServerIdNotIn(List<String> values) {
+            addCriterion("server_id not in", values, "serverId");
+            return (Criteria) this;
+        }
+
+        public Criteria andServerIdBetween(String value1, String value2) {
+            addCriterion("server_id between", value1, value2, "serverId");
+            return (Criteria) this;
+        }
+
+        public Criteria andServerIdNotBetween(String value1, String value2) {
+            addCriterion("server_id not between", value1, value2, "serverId");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlIsNull() {
+            addCriterion("url is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlIsNotNull() {
+            addCriterion("url is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlEqualTo(String value) {
+            addCriterion("url =", value, "url");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlNotEqualTo(String value) {
+            addCriterion("url <>", value, "url");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlGreaterThan(String value) {
+            addCriterion("url >", value, "url");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlGreaterThanOrEqualTo(String value) {
+            addCriterion("url >=", value, "url");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlLessThan(String value) {
+            addCriterion("url <", value, "url");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlLessThanOrEqualTo(String value) {
+            addCriterion("url <=", value, "url");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlLike(String value) {
+            addCriterion("url like", value, "url");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlNotLike(String value) {
+            addCriterion("url not like", value, "url");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlIn(List<String> values) {
+            addCriterion("url in", values, "url");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlNotIn(List<String> values) {
+            addCriterion("url not in", values, "url");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlBetween(String value1, String value2) {
+            addCriterion("url between", value1, value2, "url");
+            return (Criteria) this;
+        }
+
+        public Criteria andUrlNotBetween(String value1, String value2) {
+            addCriterion("url not between", value1, value2, "url");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckTokenIsNull() {
+            addCriterion("if_check_token is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckTokenIsNotNull() {
+            addCriterion("if_check_token is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckTokenEqualTo(String value) {
+            addCriterion("if_check_token =", value, "ifCheckToken");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckTokenNotEqualTo(String value) {
+            addCriterion("if_check_token <>", value, "ifCheckToken");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckTokenGreaterThan(String value) {
+            addCriterion("if_check_token >", value, "ifCheckToken");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckTokenGreaterThanOrEqualTo(String value) {
+            addCriterion("if_check_token >=", value, "ifCheckToken");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckTokenLessThan(String value) {
+            addCriterion("if_check_token <", value, "ifCheckToken");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckTokenLessThanOrEqualTo(String value) {
+            addCriterion("if_check_token <=", value, "ifCheckToken");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckTokenLike(String value) {
+            addCriterion("if_check_token like", value, "ifCheckToken");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckTokenNotLike(String value) {
+            addCriterion("if_check_token not like", value, "ifCheckToken");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckTokenIn(List<String> values) {
+            addCriterion("if_check_token in", values, "ifCheckToken");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckTokenNotIn(List<String> values) {
+            addCriterion("if_check_token not in", values, "ifCheckToken");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckTokenBetween(String value1, String value2) {
+            addCriterion("if_check_token between", value1, value2, "ifCheckToken");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckTokenNotBetween(String value1, String value2) {
+            addCriterion("if_check_token not between", value1, value2, "ifCheckToken");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckParamIsNull() {
+            addCriterion("if_check_param is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckParamIsNotNull() {
+            addCriterion("if_check_param is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckParamEqualTo(String value) {
+            addCriterion("if_check_param =", value, "ifCheckParam");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckParamNotEqualTo(String value) {
+            addCriterion("if_check_param <>", value, "ifCheckParam");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckParamGreaterThan(String value) {
+            addCriterion("if_check_param >", value, "ifCheckParam");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckParamGreaterThanOrEqualTo(String value) {
+            addCriterion("if_check_param >=", value, "ifCheckParam");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckParamLessThan(String value) {
+            addCriterion("if_check_param <", value, "ifCheckParam");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckParamLessThanOrEqualTo(String value) {
+            addCriterion("if_check_param <=", value, "ifCheckParam");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckParamLike(String value) {
+            addCriterion("if_check_param like", value, "ifCheckParam");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckParamNotLike(String value) {
+            addCriterion("if_check_param not like", value, "ifCheckParam");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckParamIn(List<String> values) {
+            addCriterion("if_check_param in", values, "ifCheckParam");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckParamNotIn(List<String> values) {
+            addCriterion("if_check_param not in", values, "ifCheckParam");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckParamBetween(String value1, String value2) {
+            addCriterion("if_check_param between", value1, value2, "ifCheckParam");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfCheckParamNotBetween(String value1, String value2) {
+            addCriterion("if_check_param not between", value1, value2, "ifCheckParam");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfLogResponseIsNull() {
+            addCriterion("if_log_response is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfLogResponseIsNotNull() {
+            addCriterion("if_log_response is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfLogResponseEqualTo(String value) {
+            addCriterion("if_log_response =", value, "ifLogResponse");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfLogResponseNotEqualTo(String value) {
+            addCriterion("if_log_response <>", value, "ifLogResponse");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfLogResponseGreaterThan(String value) {
+            addCriterion("if_log_response >", value, "ifLogResponse");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfLogResponseGreaterThanOrEqualTo(String value) {
+            addCriterion("if_log_response >=", value, "ifLogResponse");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfLogResponseLessThan(String value) {
+            addCriterion("if_log_response <", value, "ifLogResponse");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfLogResponseLessThanOrEqualTo(String value) {
+            addCriterion("if_log_response <=", value, "ifLogResponse");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfLogResponseLike(String value) {
+            addCriterion("if_log_response like", value, "ifLogResponse");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfLogResponseNotLike(String value) {
+            addCriterion("if_log_response not like", value, "ifLogResponse");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfLogResponseIn(List<String> values) {
+            addCriterion("if_log_response in", values, "ifLogResponse");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfLogResponseNotIn(List<String> values) {
+            addCriterion("if_log_response not in", values, "ifLogResponse");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfLogResponseBetween(String value1, String value2) {
+            addCriterion("if_log_response between", value1, value2, "ifLogResponse");
+            return (Criteria) this;
+        }
+
+        public Criteria andIfLogResponseNotBetween(String value1, String value2) {
+            addCriterion("if_log_response not between", value1, value2, "ifLogResponse");
+            return (Criteria) this;
+        }
+
+        public Criteria andRemarkIsNull() {
+            addCriterion("remark is null");
+            return (Criteria) this;
+        }
+
+        public Criteria andRemarkIsNotNull() {
+            addCriterion("remark is not null");
+            return (Criteria) this;
+        }
+
+        public Criteria andRemarkEqualTo(String value) {
+            addCriterion("remark =", value, "remark");
+            return (Criteria) this;
+        }
+
+        public Criteria andRemarkNotEqualTo(String value) {
+            addCriterion("remark <>", value, "remark");
+            return (Criteria) this;
+        }
+
+        public Criteria andRemarkGreaterThan(String value) {
+            addCriterion("remark >", value, "remark");
+            return (Criteria) this;
+        }
+
+        public Criteria andRemarkGreaterThanOrEqualTo(String value) {
+            addCriterion("remark >=", value, "remark");
+            return (Criteria) this;
+        }
+
+        public Criteria andRemarkLessThan(String value) {
+            addCriterion("remark <", value, "remark");
+            return (Criteria) this;
+        }
+
+        public Criteria andRemarkLessThanOrEqualTo(String value) {
+            addCriterion("remark <=", value, "remark");
+            return (Criteria) this;
+        }
+
+        public Criteria andRemarkLike(String value) {
+            addCriterion("remark like", value, "remark");
+            return (Criteria) this;
+        }
+
+        public Criteria andRemarkNotLike(String value) {
+            addCriterion("remark not like", value, "remark");
+            return (Criteria) this;
+        }
+
+        public Criteria andRemarkIn(List<String> values) {
+            addCriterion("remark in", values, "remark");
+            return (Criteria) this;
+        }
+
+        public Criteria andRemarkNotIn(List<String> values) {
+            addCriterion("remark not in", values, "remark");
+            return (Criteria) this;
+        }
+
+        public Criteria andRemarkBetween(String value1, String value2) {
+            addCriterion("remark between", value1, value2, "remark");
+            return (Criteria) this;
+        }
+
+        public Criteria andRemarkNotBetween(String value1, String value2) {
+            addCriterion("remark not between", value1, value2, "remark");
+            return (Criteria) this;
+        }
+    }
+
+    /**
+     * gateway_white_list
+     */
+    public static class Criteria extends GeneratedCriteria {
+
+        protected Criteria() {
+            super();
+        }
+    }
+
+    /**
+     * gateway_white_list 2019-07-24
+     */
+    public static class Criterion {
+        private String condition;
+
+        private Object value;
+
+        private Object secondValue;
+
+        private boolean noValue;
+
+        private boolean singleValue;
+
+        private boolean betweenValue;
+
+        private boolean listValue;
+
+        private String typeHandler;
+
+        public String getCondition() {
+            return condition;
+        }
+
+        public Object getValue() {
+            return value;
+        }
+
+        public Object getSecondValue() {
+            return secondValue;
+        }
+
+        public boolean isNoValue() {
+            return noValue;
+        }
+
+        public boolean isSingleValue() {
+            return singleValue;
+        }
+
+        public boolean isBetweenValue() {
+            return betweenValue;
+        }
+
+        public boolean isListValue() {
+            return listValue;
+        }
+
+        public String getTypeHandler() {
+            return typeHandler;
+        }
+
+        protected Criterion(String condition) {
+            super();
+            this.condition = condition;
+            this.typeHandler = null;
+            this.noValue = true;
+        }
+
+        protected Criterion(String condition, Object value, String typeHandler) {
+            super();
+            this.condition = condition;
+            this.value = value;
+            this.typeHandler = typeHandler;
+            if (value instanceof List<?>) {
+                this.listValue = true;
+            } else {
+                this.singleValue = true;
+            }
+        }
+
+        protected Criterion(String condition, Object value) {
+            this(condition, value, null);
+        }
+
+        protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {
+            super();
+            this.condition = condition;
+            this.value = value;
+            this.secondValue = secondValue;
+            this.typeHandler = typeHandler;
+            this.betweenValue = true;
+        }
+
+        protected Criterion(String condition, Object value, Object secondValue) {
+            this(condition, value, secondValue, null);
+        }
+    }
+}

+ 100 - 0
src/main/java/com/shawn/model/entity/ReportOprDetl.java

@@ -0,0 +1,100 @@
+package com.shawn.model.entity;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.util.Date;
+
+@Accessors(chain = true)
+@NoArgsConstructor
+@Getter
+@Setter
+@ToString
+public class ReportOprDetl implements Serializable {
+	private static final long serialVersionUID = 5157638432395610939L;
+
+	private String id;
+
+
+	private String oprId;
+
+
+	private String oprServiceId;
+
+
+	private String oprTime;
+
+
+	private String oprDate;
+
+
+	private String oprUser;
+
+
+	private String oprAuthUser;
+
+//	@ApiModelProperty(value="200,500")
+	private String oprStsCode;
+
+
+	private String oprUrl;
+
+//	@ApiModelProperty(value="外系统额外参数")
+	private String oprReq;
+
+	@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+	@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+
+	private Date oprTimestamp;
+
+
+	private String oprMethod;
+
+
+	private String oprCost;
+
+//	@ApiModelProperty(value="请求参数,get")
+	private String queryParam;
+
+//	@ApiModelProperty(value="body参数,post")
+	private String bodyParam;
+
+//	@ApiModelProperty(value="发起请求的主机ip")
+	private String reqIp;
+
+//	@ApiModelProperty(value="处理的gateway主机ip")
+	private String gatewayIp;
+
+//	@ApiModelProperty(value="报错信息")
+	private String msg;
+
+
+	private String oprRmk;
+
+
+	private String oprRmk2;
+
+	/**自定义统一方法设置主键**/
+	public void setPrimaryKey(String primaryKey) {
+		 setId(primaryKey);
+	}
+
+	/**自定义统一方法获取主键**/
+	@JsonIgnore
+	public String getPrimaryKey() {
+		 return getId();
+	}
+
+	/**判断该实体是否存在主键**/
+	public boolean hasPrimaryKey() {
+		return true;
+	}
+
+}

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1629 - 0
src/main/java/com/shawn/model/entity/ReportOprDetlExample.java


+ 36 - 0
src/main/java/com/shawn/model/param/GatewayWhiteListParam.java

@@ -0,0 +1,36 @@
+/**
+ * Date:2019-54-24 15:54:00
+ * author:吴洪双
+*/
+
+package com.shawn.model.param;
+
+import com.shawn.model.entity.GatewayWhiteList;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+@SuppressWarnings("serial")
+@Accessors(chain = true)
+@NoArgsConstructor
+@Getter
+@Setter
+@ToString
+public class GatewayWhiteListParam extends GatewayWhiteList {
+    private String orderByClause;//排序:"id desc"
+    private boolean distinct;
+    private Integer limit;//分页,展示多少条记录
+    private Integer offset;//分页,从第几条开始,从0开始
+    private List primaryKeyList;//主键id 集合,用于批量删除和批量修改
+    private List<GatewayWhiteList> entityList;//实体集合,用于批量新增
+    
+
+/*==================================以上是自动生成部分字段======================================*/
+    String remark_like;
+    
+    String url_like;
+}

+ 39 - 0
src/main/java/com/shawn/model/param/ReportOprDetlParam.java

@@ -0,0 +1,39 @@
+/**
+ * Date:2018-40-14 12:40:02
+ * author:吴洪双
+*/
+
+package com.shawn.model.param;
+
+import com.shawn.model.entity.ReportOprDetl;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+import java.util.List;
+@SuppressWarnings("serial")
+@Accessors(chain = true)
+@NoArgsConstructor
+@Getter
+@Setter
+@ToString
+public class ReportOprDetlParam extends ReportOprDetl {
+    private String orderByClause;//排序:"id desc"
+    private boolean distinct;
+    private Integer limit;//分页,展示多少条记录
+    private Integer offset;//分页,从第几条开始,从0开始
+    private List primaryKeyList;//主键id 集合,用于批量删除和批量修改
+    private List<ReportOprDetl> entityList;//实体集合,用于批量新增
+    
+	@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+	private Date oprTimestamp_start;
+	@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+	private Date oprTimestamp_end;
+
+/*==================================以上是自动生成部分字段======================================*/
+	
+}

+ 65 - 0
src/main/java/com/shawn/quartz/SchedulerListener.java

@@ -0,0 +1,65 @@
+package com.shawn.quartz;
+
+import com.shawn.service.impl.GatewayWhiteListServiceImpl;
+import com.shawn.service.interfac.ReportOprDetlServiceInterface;
+import lombok.extern.apachecommons.CommonsLog;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+@Configuration
+@EnableScheduling
+@CommonsLog
+@Component
+public class SchedulerListener implements ApplicationListener<ContextRefreshedEvent> {
+	@Autowired
+	GatewayWhiteListServiceImpl whiteListService;
+	@Autowired
+    ReportOprDetlServiceInterface reportOprDetlService;
+
+    /**
+     * 每5分钟,更新白名单
+     */
+	@Scheduled(cron =  "0 0/5 * * * ?")
+	public void initWhiteList(){
+	    log.info("每5分钟,更新白名单");
+		whiteListService.initWhiteList();
+	}
+
+    /**
+     * 每5分钟,持久化访问流水
+     */
+	@Scheduled(cron =  "0 0/5 * * * ?")
+	public void redisLog2Mysql(){
+        log.info("每5分钟,持久化访问流水");
+        reportOprDetlService.redisLog2Mysql();
+	}
+
+    /**
+     * 每小时,删除10天前的 访问流水
+     */
+	@Scheduled(cron =  "0 0 0/1 * * ?")
+	public void delApiLog(){
+        log.info("每小时,删除10天前的 访问流水");
+		whiteListService.delApiLog();
+	}
+
+    /**
+     * 继承ApplicationListener,监听springboot启动完成事件,用于启动相关方法
+     */
+    @Override
+	public void onApplicationEvent(ContextRefreshedEvent event) {
+		try {
+
+		} catch (Exception e) {
+			log.info(e.getMessage());
+			e.printStackTrace();
+		}
+	}
+
+
+}

+ 14 - 0
src/main/java/com/shawn/repository/GatewayWhiteListMapper.java

@@ -0,0 +1,14 @@
+/**
+ * Date:2019-54-24 15:54:00
+ * author:吴洪双
+*/
+
+package com.shawn.repository;
+
+import com.shawn.model.entity.GatewayWhiteList;
+import com.shawn.model.entity.GatewayWhiteListExample;
+import com.shawn.model.param.GatewayWhiteListParam;
+import com.shawn.repository.base.BaseDaoInterface;
+
+public interface GatewayWhiteListMapper extends BaseDaoInterface<GatewayWhiteList,GatewayWhiteListExample,GatewayWhiteListParam, String> {
+}

+ 9 - 0
src/main/java/com/shawn/repository/GetNoMapper.java

@@ -0,0 +1,9 @@
+package com.shawn.repository;
+
+import java.util.Map;
+
+public interface GetNoMapper {
+	public String getNo( Map<String,String> map);
+	
+	public Integer checkDB();
+}

+ 16 - 0
src/main/java/com/shawn/repository/ReportOprDetlMapper.java

@@ -0,0 +1,16 @@
+/**
+ * Date:2018-40-14 12:40:02
+ * author:吴洪双
+*/
+
+package com.shawn.repository;
+
+import com.shawn.model.entity.ReportOprDetl;
+import com.shawn.model.entity.ReportOprDetlExample;
+import com.shawn.model.param.ReportOprDetlParam;
+import com.shawn.repository.base.BaseDaoInterface;
+
+public interface ReportOprDetlMapper extends BaseDaoInterface<ReportOprDetl,ReportOprDetlExample,ReportOprDetlParam, String>{
+
+    public void delApiLog();
+}

+ 39 - 0
src/main/java/com/shawn/repository/base/BaseDaoInterface.java

@@ -0,0 +1,39 @@
+package com.shawn.repository.base;
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+@Mapper
+public interface BaseDaoInterface<ENTITY,ENTITYExample,ENTITYParam, ID extends Serializable> {
+	
+	long countByExample(ENTITYExample example);
+
+    int deleteByExample(ENTITYExample example);
+
+    int deleteByPrimaryKey(ID id);
+
+    int insert(ENTITY record);
+
+    int insertSelective(ENTITY record);
+    
+    List<ENTITY> selectByExample(ENTITYExample example);
+
+    ENTITY selectByPrimaryKey(ID id);
+
+    int updateByExampleSelective(@Param("record") ENTITY record, @Param("example") ENTITYExample example);
+
+    int updateByExample(@Param("record") ENTITY record, @Param("example") ENTITYExample example);
+
+    int updateByPrimaryKeySelective(ENTITY record);
+    
+    int updateByPrimaryKey(ENTITY record);
+	
+    int deleteBatchByIdList(List primaryKeyList);
+    
+    int insertBatch(List<ENTITY> entityList);
+    
+    int updateBatchByIdList(ENTITYParam entity);
+}

+ 98 - 0
src/main/java/com/shawn/rule/NodeBalanceRule.java

@@ -0,0 +1,98 @@
+package com.shawn.rule;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.ThreadLocalRandom;
+
+import org.apache.commons.lang.math.RandomUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+import com.netflix.client.config.IClientConfig;
+import com.netflix.loadbalancer.AbstractLoadBalancerRule;
+import com.netflix.loadbalancer.ILoadBalancer;
+import com.netflix.loadbalancer.RandomRule;
+import com.netflix.loadbalancer.Server;
+import java.net.*;
+import java.util.*;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 
+ * @ClassName: GameCenterBalanceRule
+ * @Description: 根据node对服务进行负载均衡。
+ */
+@Component
+@Scope("prototype")
+@Slf4j
+public class NodeBalanceRule extends RandomRule {
+
+    @Override
+    public Server choose(Object key) {
+        if (key == null) {
+            return super.choose(null);
+        }
+
+        List<Server> servers = getLoadBalancer().getReachableServers();
+//        log.info("server size is : {} , serverList is : {}" , servers.size() ,servers);
+
+
+        Optional<Server> serverOpt = servers.stream().filter(server -> server.getId().contains(String.valueOf(key))).findFirst();
+        if(serverOpt.isPresent()) {
+        	log.info("choose rule..." + key);
+        	return serverOpt.get();
+        }
+
+        // 根据本机ip,走本机的子服务
+        // 获取本机ip
+        String localIp = getLocalIP();
+//        log.info("localIp:" + localIp);
+        Optional<Server> opt_local = servers.stream().filter(server -> server.getId().contains(localIp)).findFirst();
+        if(opt_local.isPresent()) { // 优先走本机
+//            log.info("choose local server: {}" , opt_local.get());
+            return opt_local.get();
+        }else{ // 走同网段
+            String localIp2 = localIp.substring(0,localIp.lastIndexOf("."));
+            Optional<Server> opt_local2 = servers.stream().filter(server -> server.getId().contains(localIp2)).findFirst();
+            if(opt_local2.isPresent()){
+//                log.info("choose same segment: {}" , opt_local2.get());
+                return opt_local2.get();
+            }
+        }
+
+//        log.info("choose Random server");
+        return super.choose(null);
+    }
+
+    /**
+     * 获取本机ip
+     * @return
+     */
+    public static String getLocalIP() {
+        String localIP = "127.0.0.1";
+        try {
+            OK:
+            for (Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); interfaces.hasMoreElements(); ) {
+                NetworkInterface networkInterface = interfaces.nextElement();
+                if (networkInterface.isLoopback() || networkInterface.isVirtual() || !networkInterface.isUp()) {
+                    continue;
+                }
+                Enumeration<InetAddress> addresses = networkInterface.getInetAddresses();
+                while (addresses.hasMoreElements()) {
+                    InetAddress address = addresses.nextElement();
+                    if (address instanceof Inet4Address) {
+                        localIP = address.getHostAddress();
+                        break OK;
+                    }
+                }
+            }
+        } catch (SocketException e) {
+            e.printStackTrace();
+        }
+        return localIP;
+    }
+
+}

+ 122 - 0
src/main/java/com/shawn/service/base/BaseService.java

@@ -0,0 +1,122 @@
+package com.shawn.service.base;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Optional;
+
+import com.shawn.util.UniqueIDUtil;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.shawn.repository.base.BaseDaoInterface;
+
+@Service
+public abstract class BaseService<ENTITY,ENTITYExample,ENTITYParam, ID extends Serializable> {
+
+	protected BaseDaoInterface<ENTITY,ENTITYExample,ENTITYParam, ID> baseDAO;
+	@Autowired
+	public BaseService(BaseDaoInterface<ENTITY,ENTITYExample,ENTITYParam, ID> dao){
+		baseDAO = dao;
+	}
+	/**
+	 * 自定义获取model 表的名称
+	 */
+	protected abstract String getResourceName();
+	
+	/**
+	 * 将ENTITYE转为ENTITYExample
+	 */
+//	public abstract ENTITYExample param2Example(Object param);
+	
+	/**
+	 * 生成唯一id
+	 * @param tableName 表名
+	 * @return
+	 */
+	public String generateUniqueID(String tableName) {
+		return UniqueIDUtil.getUniqueID();
+	}
+	/**
+	 * 生成唯一id
+	 * 根据getResourceName 作为表名
+	 * @return
+	 */
+	public String generateUniqueID() {
+		return UniqueIDUtil.getUniqueID();
+	}
+
+	/**
+	 * 新增
+	 */
+	@Transactional
+	public Integer insert(ENTITY entity) {
+//		return baseDAO.insertSelective(entity);
+		return baseDAO.insert(entity);
+	}
+	/**
+	 * 根据id删除
+	 */
+	@Transactional
+	public Integer deleteById(ID id) {
+		return baseDAO.deleteByPrimaryKey(id);
+	}
+	/**
+	 * 根据条件删除
+	 */
+	@Transactional
+	public Integer deleteByOption(ENTITYExample example) {
+		return baseDAO.deleteByExample(example);
+	}
+	/**
+	 * 根据条件查找总条数
+	 */
+	public Long selectCount(ENTITYExample example){
+		return baseDAO.countByExample(example);
+	}
+	/**
+	 * 根据条件查找,List<ENTITY>
+	 */
+	public List<ENTITY> selectByOption(ENTITYExample example){
+        return baseDAO.selectByExample(example);
+	}
+	/**
+	 * 根据id查找,返回Optional<ENTITY>
+	 */
+	public Optional<ENTITY> selectById(ID id) {
+		return  Optional.ofNullable(baseDAO.selectByPrimaryKey(id));
+	}
+	/**
+	 * 根据id查找,返回实体
+	 */
+	public ENTITY selectEntityById(ID id) {
+		return  baseDAO.selectByPrimaryKey(id);
+	}
+	/**
+	 * 根据id更新,更新字段为空时,则不更新该字段
+	 */
+	@Transactional
+	public boolean updateById(ENTITY entity) {
+		return baseDAO.updateByPrimaryKeySelective(entity)>0;
+	}
+	/**
+	 * 根据条件更新,更新字段为空时,则不更新该字段
+	 */
+	@Transactional
+	public boolean updateByOption(@Param("record") ENTITY record, @Param("example") ENTITYExample example) {
+		return baseDAO.updateByExampleSelective(record,example)>0;
+	}
+	@Transactional
+	public int deleteBatchByIdList(List primaryKeyList) {
+		return baseDAO.deleteBatchByIdList(primaryKeyList);
+	}
+	@Transactional
+	public int insertBatch(List<ENTITY> entityList){
+		return baseDAO.insertBatch(entityList);
+	}
+	@Transactional
+	public int updateBatchByIdList(ENTITYParam entity){
+		return baseDAO.updateBatchByIdList(entity);
+	}
+}

+ 70 - 0
src/main/java/com/shawn/service/base/BaseServiceInterface.java

@@ -0,0 +1,70 @@
+package com.shawn.service.base;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Optional;
+
+import org.apache.ibatis.annotations.Param;
+
+
+public interface BaseServiceInterface<ENTITY,ENTITYExample,ENTITYParam, ID extends Serializable> {
+	/**
+	 * 新增
+	 */
+	public Integer insert(ENTITY entity);
+	/**
+	 * 根据id删除
+	 */
+	public Integer deleteById(ID id);
+	/**
+	 * 根据条件删除
+	 */
+	public Integer deleteByOption(ENTITYExample example);
+	/**
+	 * 根据条件查找总条数
+	 */
+	public Long selectCount(ENTITYExample example);
+	/**
+	 * 根据条件查找,List<ENTITY>
+	 */
+	public List<ENTITY> selectByOption(ENTITYExample example);
+	/**
+	 * 根据id查找,返回Optional<ENTITY>
+	 */
+	public Optional<ENTITY> selectById(ID id);
+	/**
+	 * 根据id查找,返回实体
+	 */
+	public ENTITY selectEntityById(ID id);
+	/**
+	 * 根据id更新,更新字段为空时,则不更新该字段
+	 */
+	public boolean updateById(ENTITY entity);
+	/**
+	 * 根据条件更新,更新字段为空时,则不更新该字段
+	 */
+	public boolean updateByOption(@Param("record") ENTITY record, @Param("example") ENTITYExample example);
+	
+	public int deleteBatchByIdList(List primaryKeyList);
+    
+	public int insertBatch(List<ENTITY> entityList);
+    
+	public int updateBatchByIdList(ENTITYParam entity);
+	/**
+	 * 自定义获取model 表的名称
+	 */
+	public String getResourceName();
+	
+	/**
+	 * 生成唯一id
+	 * @param tableName 表名
+	 * @return
+	 */
+	public String generateUniqueID(String tableName);
+	/**
+	 * 生成唯一id
+	 * 根据getResourceName 作为表名
+	 * @return
+	 */
+	public String generateUniqueID();
+}

+ 157 - 0
src/main/java/com/shawn/service/impl/GatewayWhiteListServiceImpl.java

@@ -0,0 +1,157 @@
+/**
+ * Date:2019-54-24 15:54:00
+ * author:吴洪双
+*/
+
+package com.shawn.service.impl;
+
+import com.shawn.MyGlobalFilter;
+import com.shawn.model.dto.ResultMessage;
+import com.shawn.model.entity.GatewayWhiteList;
+import com.shawn.model.entity.GatewayWhiteListExample;
+import com.shawn.model.param.GatewayWhiteListParam;
+import com.shawn.repository.GatewayWhiteListMapper;
+import com.shawn.repository.ReportOprDetlMapper;
+import com.shawn.service.base.BaseService;
+import com.shawn.service.interfac.GatewayWhiteListServiceInterface;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+@Slf4j
+@Service
+public class GatewayWhiteListServiceImpl extends BaseService<GatewayWhiteList, GatewayWhiteListExample,GatewayWhiteListParam,String> implements GatewayWhiteListServiceInterface{
+	@Autowired
+	private GatewayWhiteListMapper gatewayWhiteListMapper;
+	@Autowired
+	private ReportOprDetlMapper reportOprDetlMapper;
+	@Autowired
+	public GatewayWhiteListServiceImpl(GatewayWhiteListMapper dao) {
+		super(dao);
+	}
+
+	@Override
+	public String getResourceName() {
+		return "GatewayWhiteList";
+	}
+
+	private static List<GatewayWhiteList> whiteList = new ArrayList<>();
+
+
+	/**
+	 * 自动删除10天前的api日志流水
+	 */
+	public void delApiLog(){
+		reportOprDetlMapper.delApiLog();
+	}
+	public void initWhiteList(){
+		whiteList = null;
+		whiteList = this.selectByOption(null);
+	}
+
+	/**
+	 * 获取白名单
+	 */
+	public List<GatewayWhiteList> getWhiteList(){
+		if(CollectionUtils.isNotEmpty(whiteList)){
+			return whiteList;
+		}else{
+			initWhiteList();
+			return whiteList;
+		}
+	}
+
+	/**
+	 * 是否校验token
+	 * @param request
+	 * @return
+	 */
+	public boolean ifCheckToken(ServerHttpRequest request){
+		// 获取请求的路径
+		URI uri = request.getURI();
+		String[] urls = uri.getPath().split("/");
+		String serviceId = urls[0] + urls[1];
+		String url = request.getURI().getPath();
+
+		// 获取该系统对应的token白名单
+		List<GatewayWhiteList> whiteList = getWhiteList();
+		if(CollectionUtils.isNotEmpty(whiteList)){
+			Optional op = whiteList.stream().filter(e -> {
+				return url.contains(e.getUrl()) && serviceId.equals(e.getServerId()) && "0".equals(e.getIfCheckToken());
+			}).findFirst();
+			return !op.isPresent();
+		}
+		return true;
+	}
+	/**
+	 * 是否校验param
+	 * @param request
+	 * @return
+	 */
+	public boolean ifCheckParam(ServerHttpRequest request){
+		// 获取请求的路径
+		URI uri = request.getURI();
+		String[] urls = uri.getPath().split("/");
+		String serviceId = urls[0] + urls[1];
+		String url = request.getURI().getPath();
+
+		// 获取该系统对应的token白名单
+		List<GatewayWhiteList> whiteList = getWhiteList();
+		if(CollectionUtils.isNotEmpty(whiteList)){
+			Optional op = whiteList.stream().filter(e -> {
+				return url.contains(e.getUrl()) && serviceId.equals(e.getServerId()) && "0".equals(e.getIfCheckParam());
+			}).findFirst();
+			return !op.isPresent();
+		}
+		return true;
+	}
+	/**
+	 * 是否读取 记录响应
+	 * @param request
+	 * @return
+	 */
+	public boolean ifLogResponse(ServerHttpRequest request){
+		// 获取请求的路径
+		URI uri = request.getURI();
+		String[] urls = uri.getPath().split("/");
+		String serviceId = urls[0] + urls[1];
+		String url = request.getURI().getPath();
+
+		// 获取该系统对应的token白名单
+		List<GatewayWhiteList> whiteList = getWhiteList();
+		if(CollectionUtils.isNotEmpty(whiteList)){
+			Optional op = whiteList.stream().filter(e -> {
+				return url.contains(e.getUrl()) && serviceId.equals(e.getServerId()) && "0".equals(e.getIfLogResponse());
+			}).findFirst();
+			return !op.isPresent();
+		}
+		return true;
+	}
+	/**
+	 * 是否外部系统白名单
+	 * @param request
+	 * @return
+	 */
+	public boolean ifOutsideSysWhiteList(ServerHttpRequest request,String token){
+		String serviceId = token.replace(MyGlobalFilter.OUT_SIDE_SYS_,"");
+		String url = request.getURI().getPath();
+
+		// 获取该系统对应的token白名单
+		List<GatewayWhiteList> whiteList = getWhiteList();
+		if(CollectionUtils.isNotEmpty(whiteList)){
+			Optional op = whiteList.stream().filter(e -> {
+				return url.contains(e.getUrl()) && serviceId.equals(e.getServerId()) && "1".equals(e.getIfOutsideSys());
+			}).findFirst();
+			return op.isPresent();
+		}
+		return false;
+	}
+}

+ 80 - 0
src/main/java/com/shawn/service/impl/ReportOprDetlServiceImpl.java

@@ -0,0 +1,80 @@
+/**
+ * Date:2018-40-14 12:40:02
+ * author:吴洪双
+*/
+
+package com.shawn.service.impl;
+
+import com.shawn.MyGlobalFilter;
+import com.shawn.util.UniqueIDUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+
+import com.shawn.model.entity.ReportOprDetl;
+import com.shawn.model.entity.ReportOprDetlExample;
+import com.shawn.model.param.ReportOprDetlParam;
+import com.shawn.repository.ReportOprDetlMapper;
+import com.shawn.service.base.BaseService;
+import com.shawn.service.interfac.ReportOprDetlServiceInterface;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+@Slf4j
+public class ReportOprDetlServiceImpl extends BaseService<ReportOprDetl,ReportOprDetlExample,ReportOprDetlParam,String> implements ReportOprDetlServiceInterface{
+	@Autowired
+	private ReportOprDetlMapper reportOprDetlMapper;
+	@Autowired
+	private RedisTemplate redisTemplate;
+	@Autowired
+	public ReportOprDetlServiceImpl(ReportOprDetlMapper dao) {
+		super(dao);
+	}
+
+	@Override
+	public String getResourceName() {
+		return "ReportOprDetl";
+	}
+
+	@Override
+	public void redisLog2Mysql(){
+		try {
+			String redisKey = MyGlobalFilter.API_LOG_REDIS_KEY;
+			if(redisTemplate.hasKey(redisKey)) {
+				List redislist = redisTemplate.opsForList().range(redisKey, 0, -1);
+				redisTemplate.delete(redisKey);
+				if (CollectionUtils.isNotEmpty(redislist)) {
+					List<ReportOprDetl> resultlist = (List<ReportOprDetl>) redislist;
+					for (ReportOprDetl entity:resultlist) {
+						entity.setId(UniqueIDUtil.getUniqueID());
+					}
+					// 批量插入
+					log.info("批量插入到表");
+					int max = 500; // 批量插入最大条数
+					int index = 0;
+					int maxIndex = resultlist.size();
+					while (index <= maxIndex) {
+						List<ReportOprDetl> list = new ArrayList<ReportOprDetl>();
+						if (index + max <= maxIndex) {
+							list = resultlist.subList(index, index + max);
+						} else {
+							list = resultlist.subList(index, maxIndex);
+						}
+						insertBatch(list);
+						index = index + max;
+						log.info("批量插入" + list.size() + "rows");
+					}
+					log.info("批量插入完毕");
+				}
+			}else{
+				log.info("没有api缓存流水");
+			}
+		} catch (Exception e) {
+			log.error("将redis缓存的api流水持久化到mysql失败:"+e.getMessage());
+		}
+	}
+}

+ 14 - 0
src/main/java/com/shawn/service/interfac/GatewayWhiteListServiceInterface.java

@@ -0,0 +1,14 @@
+/**
+ * Date:2019-54-24 15:54:00
+ * author:吴洪双
+*/
+
+package com.shawn.service.interfac;
+
+import com.shawn.model.entity.GatewayWhiteList;
+import com.shawn.model.entity.GatewayWhiteListExample;
+import com.shawn.model.param.GatewayWhiteListParam;
+import com.shawn.service.base.BaseServiceInterface;
+
+public interface GatewayWhiteListServiceInterface extends BaseServiceInterface<GatewayWhiteList, GatewayWhiteListExample,GatewayWhiteListParam,String> {
+}

+ 15 - 0
src/main/java/com/shawn/service/interfac/ReportOprDetlServiceInterface.java

@@ -0,0 +1,15 @@
+/**
+ * Date:2018-40-14 12:40:02
+ * author:吴洪双
+*/
+
+package com.shawn.service.interfac;
+
+import com.shawn.model.entity.ReportOprDetl;
+import com.shawn.model.entity.ReportOprDetlExample;
+import com.shawn.model.param.ReportOprDetlParam;
+import com.shawn.service.base.BaseServiceInterface;
+
+public interface ReportOprDetlServiceInterface extends BaseServiceInterface<ReportOprDetl,ReportOprDetlExample,ReportOprDetlParam,String>{
+    public void redisLog2Mysql();
+}

+ 53 - 0
src/main/java/com/shawn/util/BeanUtils.java

@@ -0,0 +1,53 @@
+package com.shawn.util;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.springframework.beans.BeanWrapper;
+import org.springframework.beans.BeanWrapperImpl;
+
+/**
+ * 
+ * 类说明:实体类赋值
+ * @author 吴洪双
+ * 2016年5月25日上午9:55:16
+ */
+public class BeanUtils {
+    /**
+     * 
+     * 方法说明:获取空属性
+     * @author 吴洪双
+     * 2016年5月25日上午9:56:43
+     * @param source
+     * @return
+     */
+    public static String[] getNullPropertyNames (Object source) {
+    	 final BeanWrapper src = new BeanWrapperImpl(source);
+    	 java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();
+
+    	 Set<String> emptyNames = new HashSet<String>();
+    	 for(java.beans.PropertyDescriptor pd : pds) {
+	    	 Object srcValue = src.getPropertyValue(pd.getName());
+	    	 if (srcValue == null) {
+	    	 	emptyNames.add(pd.getName());
+	    	 }
+    	 }
+    	 String[] result = new String[emptyNames.size()];
+    	 return emptyNames.toArray(result);
+    }
+    /**
+     * 
+     * 方法说明:忽略空值
+     * @author 吴洪双
+     * 2016年5月25日上午9:57:18
+     * @param src
+     * @param target
+     */
+    public static void copyPropertiesIgnoreNull(Object src, Object target,boolean flag){
+    	if(flag){
+    		org.springframework.beans.BeanUtils.copyProperties(src, target, getNullPropertyNames(src));
+    	}else{
+    		org.springframework.beans.BeanUtils.copyProperties(src, target);
+    	}
+    }
+    
+}

+ 252 - 0
src/main/java/com/shawn/util/DateUtils.java

@@ -0,0 +1,252 @@
+package com.shawn.util;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+public class DateUtils
+{
+  public static final String PATTERN_MMdd = "MMdd";
+  public static final String PATTERN_yyyyMMdd = "yyyyMMdd";
+  public static final String PATTERN_yyyyMMddHHmmss = "yyyyMMddHHmmss";
+  public static final String PATTERN_yyyyMMddHHmmssSSS = "yyyyMMddHHmmssSSS";
+  public static final String PATTERN_yyyy_MM_dd = "yyyy-MM-dd";
+  public static final String PATTERN_yyyy_M_d = "yyyy-M-d";
+  public static final String PATTERN_yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss";
+  public static final String PATTERN_yyyy_MM_dd_HH_mm = "yyyy-MM-dd HH:mm";
+  public static final String PATTERN_HH_mm_ss = "HH:mm:ss";
+  public static final String PATTERN_HHmmss = "HHmmss";
+  public static final Map<String, String> mapChDate = new HashMap<String, String>();
+
+  public static Date getNextday(Date now)
+  {
+    Calendar calendar = Calendar.getInstance();
+    calendar.setTime(now);
+    calendar.add(5, 1);
+    return calendar.getTime();
+  }
+  
+  public static Date getPreday(Date now)
+  {
+    Calendar calendar = Calendar.getInstance();
+    calendar.setTime(now);
+    calendar.add(5, -1);
+    return calendar.getTime();
+  }
+
+  public static String formatDate_ch(Date date)
+  {
+    if(date==null){
+   	 throw new IllegalArgumentException("需要转换的对象为空");
+    }
+    String str = formatDate(date, "MMdd");
+    str = (String)mapChDate.get(str.substring(0, 2)) + str.substring(2);
+    return str;
+  }
+
+  public static String formatDate(Date date, String pattern)
+  {
+    if(date==null){
+        return "";
+    }
+    SimpleDateFormat sdf = null;
+    if (pattern == null) {
+      sdf = new SimpleDateFormat();
+    }
+    else {
+      sdf = new SimpleDateFormat(pattern);
+    }
+    return sdf.format(date);
+  }
+
+  public static String formatDate(Date date) {
+    SimpleDateFormat sdf = new SimpleDateFormat();
+    return sdf.format(date);
+  }
+
+  public static Date parseDate(String source, String pattern) throws ParseException
+  {
+    SimpleDateFormat sdf = null;
+    if (pattern == null) {
+      sdf = new SimpleDateFormat();
+    }
+    else {
+      sdf = new SimpleDateFormat(pattern);
+    }
+    return sdf.parse(source);
+  }
+
+  public static Date parseDate(String source) throws ParseException {
+    SimpleDateFormat sdf = new SimpleDateFormat();
+    return sdf.parse(source);
+  }
+
+  public static Date parseDate(String source, Date defaultDate) {
+    try {
+      SimpleDateFormat sdf = new SimpleDateFormat();
+      return sdf.parse(source);
+    }
+    catch (ParseException e)
+    {
+    }
+    return defaultDate;
+  }
+
+  public static Date parseDate(String source, String pattern, Date defaultDate) {
+    try {
+      SimpleDateFormat sdf = null;
+      if (pattern == null) {
+        sdf = new SimpleDateFormat();
+      }
+      else {
+        sdf = new SimpleDateFormat(pattern);
+      }
+      return sdf.parse(source);
+    }
+    catch (ParseException e) {
+    }
+    return defaultDate;
+  }
+
+  public static boolean tryParse(String source) throws ParseException {
+    try {
+      Integer.parseInt(source);
+      return true;
+    } catch (NumberFormatException e) {
+    }
+    return false;
+  }
+
+  public static Date changeDate(Date date, TimeType timeType, int amount)
+  {
+    if ((date == null) || (timeType == null) || (amount == 0)) {
+      return date;
+    }
+    Calendar c = Calendar.getInstance();
+    c.setTime(date);
+    c.add(timeType.getValue(), amount);
+    return c.getTime();
+  }
+
+  public static boolean isSameDay(Date date1, Date date2)
+  {
+    if ((date1 == null) || (date2 == null)) {
+      throw new IllegalArgumentException("The date must not be null");
+    }
+    Calendar cal1 = Calendar.getInstance();
+    cal1.setTime(date1);
+    Calendar cal2 = Calendar.getInstance();
+    cal2.setTime(date2);
+    return isSameDay(cal1, cal2);
+  }
+
+  public static boolean isSameDay(Calendar cal1, Calendar cal2)
+  {
+    if ((cal1 == null) || (cal2 == null)) {
+      throw new IllegalArgumentException("The date must not be null");
+    }
+    return (cal1.get(0) == cal2.get(0)) && (cal1.get(1) == cal2.get(1)) && (cal1.get(6) == cal2.get(6));
+  }
+
+  /** @deprecated */
+  public static Date add(Date date, int calendarField, int amount)
+  {
+    if (date == null) {
+      throw new IllegalArgumentException("The date must not be null");
+    }
+    Calendar c = Calendar.getInstance();
+    c.setTime(date);
+    c.add(calendarField, amount);
+    return c.getTime();
+  }
+
+  public static Date addYears(Date date, int amount)
+  {
+    return add(date, 1, amount);
+  }
+
+  public static Date addMonths(Date date, int amount)
+  {
+    return add(date, 2, amount);
+  }
+
+  public static Date addWeeks(Date date, int amount)
+  {
+    return add(date, 3, amount);
+  }
+
+  public static Date addDays(Date date, int amount)
+  {
+    return add(date, 5, amount);
+  }
+
+  public static Date addHours(Date date, int amount)
+  {
+    return add(date, 11, amount);
+  }
+
+  public static Date addMinutes(Date date, int amount)
+  {
+    return add(date, 12, amount);
+  }
+
+  public static Date addSeconds(Date date, int amount)
+  {
+    return add(date, 13, amount);
+  }
+
+  public static Date addMilliseconds(Date date, int amount)
+  {
+    return add(date, 14, amount);
+  }
+
+  static
+  {
+    mapChDate.put("01", "一月");
+    mapChDate.put("02", "二月");
+    mapChDate.put("03", "三月");
+    mapChDate.put("04", "四月");
+    mapChDate.put("05", "五月");
+    mapChDate.put("06", "六月");
+    mapChDate.put("07", "七月");
+    mapChDate.put("08", "八月");
+    mapChDate.put("09", "九月");
+    mapChDate.put("10", "十月");
+    mapChDate.put("11", "十一月");
+    mapChDate.put("12", "十二月");
+  }
+
+  public static enum TimeType
+  {
+    SECOND(13), MINUTE(12), HOUR(10), DAY(5), 
+    WEEK(4), MONTH(2), 
+    YEAR(1);
+
+    private int value;
+
+    private TimeType(int value) {
+      this.value = value;
+    }
+
+    public int getValue() {
+      return this.value;
+    }
+  }
+  /**
+   * 
+   * 毛龙飞
+   * @Description 获取日期的后几天
+   * @param d
+   * @param day
+   * @return
+   */
+  public static Date getDateAfter(Date d, int day) {  
+      Calendar now = Calendar.getInstance();  
+      now.setTime(d);  
+      now.set(Calendar.DATE, now.get(Calendar.DATE) + day);  
+      return now.getTime();  
+  }
+}

+ 492 - 0
src/main/java/com/shawn/util/FgObjectUtil.java

@@ -0,0 +1,492 @@
+package com.shawn.util;
+
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Date;
+
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.shawn.web.exception.ParamNotFoundException;
+
+
+/**
+ * 
+ * 类说明:对象操作  
+ * @author 吴洪双
+ * 2016年1月13日上午10:57:51
+ */
+@Slf4j
+public class FgObjectUtil implements Serializable{
+	
+	private static final long serialVersionUID = 455370045995076257L;
+	
+	private static Logger logger = LoggerFactory.getLogger(FgObjectUtil.class);
+	/**
+	 * 递归获取所有父类的属性
+	 * @return
+	 */
+	public static ArrayList<Field> getAllFields(Class<?> object,ArrayList<Field> fieldList){
+		Class<?> supperClass = object.getSuperclass();
+		if(supperClass!=null){
+			Field[] fields = supperClass.getDeclaredFields();
+			for (Field field : fields) {
+				fieldList.add(field);
+			}
+			
+			return getAllFields(supperClass,fieldList);
+		}else{
+			return fieldList;
+		}
+	}
+	/**
+	 * 递归获取所有父类的方法
+	 * @return
+	 */
+	public static ArrayList<Method> getAllMethods(Class<?> object,ArrayList<Method> methodList){
+		Class<?> supperClass = object.getSuperclass();
+		if(supperClass!=null){
+			
+			Method[] methods = supperClass.getMethods();
+			for (Method method : methods) {
+				methodList.add(method);
+			}
+			
+			return getAllMethods(supperClass,methodList);
+		}else{
+			return methodList;
+		}
+	}
+	
+	/**
+	 * 
+	 * 方法说明:对象非空校验
+	 * @author 吴洪双
+	 * 2016年1月13日下午4:52:04
+	 * @param object
+	 * @throws NoSuchMethodException
+	 * @throws SecurityException
+	 * @throws Exception
+	 * @throws ParamNotFoundException
+	 */
+	public static void objectNullOrEmpty(Object object) throws ParamNotFoundException{
+		if (object != null ) {// if (object!=null
+			try{
+				// 拿到该类
+				Class<?> clz = object.getClass();
+				// 获取实体类的所有属性,返回Field数组
+				Field[] fields = clz.getDeclaredFields();
+				ArrayList<Field> fieldList= new ArrayList<Field>();
+				for (Field field : fields) {
+					fieldList.add(field);
+				}
+				//获取实体类所有父类的属性
+				fieldList = getAllFields(clz,fieldList);
+				
+				for (Field field : fieldList) {// --for() begin
+					if("serialVersionUID".equals(field.getName())){
+						continue;
+					}
+					// 如果类型是String
+					if (field.getGenericType().toString().equals("class java.lang.String")) { // 如果type是类类型,则前面包含"class ",后面跟类名
+						// 拿到该属性的gettet方法
+						Method m = (Method) object.getClass().getMethod("get" + getMethodName(field.getName()));
+						String val = (String) m.invoke(object);// 调用getter方法获取属性值
+						if(val==null || val.length() == 0){
+							logger.debug(field.getName()+" is null");
+							throw new ParamNotFoundException(field.getName());
+						}
+						continue;
+					}
+					// 如果类型是Date
+					if (field.getGenericType().toString().equals("class java.util.Date")) {
+						Method m = (Method) object.getClass().getMethod("get" + getMethodName(field.getName()));
+						Date val = (Date) m.invoke(object);
+						if(val==null){
+							logger.debug(field.getName()+" is null");
+							throw new ParamNotFoundException(field.getName());
+						}
+						continue;
+					}
+					// 如果类型是Integer
+					if (field.getGenericType().toString().equals("class java.lang.Integer")) {
+						Method m = (Method) object.getClass().getMethod("get" + getMethodName(field.getName()));
+						Integer val = (Integer) m.invoke(object);
+						if(val==null){
+							logger.debug(field.getName()+" is null");
+							throw new ParamNotFoundException(field.getName());
+						}
+						continue;
+					}
+					// 如果类型是Double
+					if (field.getGenericType().toString().equals("class java.lang.Double")) {
+						Method m = (Method) object.getClass().getMethod("get" + getMethodName(field.getName()));
+						Double val = (Double) m.invoke(object);
+						if(val==null){
+							logger.debug(field.getName()+" is null");
+							throw new ParamNotFoundException(field.getName());
+						}
+						continue;
+					}
+					// 如果类型是Boolean 是封装类
+					if (field.getGenericType().toString().equals("class java.lang.Boolean")) {
+						Method m = (Method) object.getClass().getMethod(field.getName());
+						Boolean val = (Boolean) m.invoke(object);
+						if(val==null){
+							logger.debug(field.getName()+" is null");
+							throw new ParamNotFoundException(field.getName());
+						}
+						continue;
+					}
+					// 如果类型是boolean 基本数据类型不一样 这里有点说名如果定义名是 isXXX的 那就全都是isXXX的
+					// 反射找不到getter的具体名
+					if (field.getGenericType().toString().equals("boolean")) {
+						Method m = (Method) object.getClass().getMethod(field.getName());
+						Boolean val = (Boolean) m.invoke(object);
+						if(val==null){
+							logger.debug(field.getName()+"is null");
+							throw new ParamNotFoundException(field.getName());
+						}
+						continue;
+					}
+					// 如果类型是Short
+					if (field.getGenericType().toString().equals("class java.lang.Short")) {
+						Method m = (Method) object.getClass().getMethod("get" + getMethodName(field.getName()));
+						Short val = (Short) m.invoke(object);
+						if(val==null){
+							logger.debug(field.getName()+"is null");
+							throw new ParamNotFoundException(field.getName());
+						}
+						continue;
+					}
+					//如果是枚举类型
+					if(field.getGenericType().toString().contains(".bean.enums.")){
+						Method m = (Method) object.getClass().getMethod("get" + getMethodName(field.getName()));
+						if(m.invoke(object) == null){
+							logger.debug(field.getName()+"is null");
+							throw new ParamNotFoundException(field.getName());
+						}
+						continue;
+					}
+					//其他类型
+					Method m = (Method) object.getClass().getMethod("get" + getMethodName(field.getName()));
+					if(m.invoke(object) == null){
+						logger.debug(field.getName()+"is null");
+						throw new ParamNotFoundException(field.getName());
+					}
+				}
+			} catch (NoSuchMethodException e) {
+				log.error(e.getMessage());
+			} catch (SecurityException e) {
+				log.error(e.getMessage());
+			} catch (ParamNotFoundException e) {
+				throw e;
+			} catch (Exception e){
+				log.error(e.getMessage());
+			}
+		}
+	}
+	
+	/**
+	 * 
+	 * 方法说明:非包含的参数校验
+	 * @author 吴洪双
+	 * 2016年1月13日下午5:27:15
+	 * @param object
+	 * @param del
+	 * @throws NoSuchMethodException
+	 * @throws SecurityException
+	 * @throws Exception
+	 * @throws ParamNotFoundException
+	 */
+	public static void objectNullOrEmptyDel(Object object,String del) throws ParamNotFoundException{
+		if (object != null ) {// if (object!=null
+			try{
+				// 拿到该类
+				Class<?> clz = object.getClass();
+				// 获取实体类的所有属性,返回Field数组
+				Field[] fields = clz.getDeclaredFields();
+				ArrayList<Field> fieldList= new ArrayList<Field>();
+				for (Field field : fields) {
+					fieldList.add(field);
+				}
+				//获取实体类所有父类的属性
+				fieldList = getAllFields(clz,fieldList);
+				
+				for (Field field : fieldList) {// --for() begin
+					if(del.contains(field.getName()+"$") || "serialVersionUID".equals(field.getName())){
+						continue;
+					}
+					// 如果类型是String
+					if (field.getGenericType().toString().equals("class java.lang.String")) { // 如果type是类类型,则前面包含"class ",后面跟类名
+						// 拿到该属性的gettet方法
+						Method m = (Method) object.getClass().getMethod("get" + getMethodName(field.getName()));
+						String val = (String) m.invoke(object);// 调用getter方法获取属性值
+						if(val==null || val.length() == 0){
+							logger.debug(field.getName()+" is null");
+							throw new ParamNotFoundException(field.getName());
+						}
+						continue;
+					}
+					// 如果类型是Date
+					if (field.getGenericType().toString().equals("class java.util.Date")) {
+						Method m = (Method) object.getClass().getMethod("get" + getMethodName(field.getName()));
+						Date val = (Date) m.invoke(object);
+						if(val==null){
+							logger.debug(field.getName()+" is null");
+							throw new ParamNotFoundException(field.getName());
+						}
+						continue;
+					}
+					// 如果类型是Integer
+					if (field.getGenericType().toString().equals("class java.lang.Integer")) {
+						Method m = (Method) object.getClass().getMethod("get" + getMethodName(field.getName()));
+						Integer val = (Integer) m.invoke(object);
+						if(val==null){
+							logger.debug(field.getName()+" is null");
+							throw new ParamNotFoundException(field.getName());
+						}
+						continue;
+					}
+					// 如果类型是Double
+					if (field.getGenericType().toString().equals("class java.lang.Double")) {
+						Method m = (Method) object.getClass().getMethod("get" + getMethodName(field.getName()));
+						Double val = (Double) m.invoke(object);
+						if(val==null){
+							logger.debug(field.getName()+" is null");
+							throw new ParamNotFoundException(field.getName());
+						}
+						continue;
+					}
+					// 如果类型是Boolean 是封装类
+					if (field.getGenericType().toString().equals("class java.lang.Boolean")) {
+						Method m = (Method) object.getClass().getMethod(field.getName());
+						Boolean val = (Boolean) m.invoke(object);
+						if(val==null){
+							logger.debug(field.getName()+" is null");
+							throw new ParamNotFoundException(field.getName());
+						}
+						continue;
+					}
+					// 如果类型是boolean 基本数据类型不一样 这里有点说名如果定义名是 isXXX的 那就全都是isXXX的
+					// 反射找不到getter的具体名
+					if (field.getGenericType().toString().equals("boolean")) {
+						Method m = (Method) object.getClass().getMethod(field.getName());
+						Boolean val = (Boolean) m.invoke(object);
+						if(val==null){
+							logger.debug(field.getName()+"is null");
+							throw new ParamNotFoundException(field.getName());
+						}
+						continue;
+					}
+					// 如果类型是Short
+					if (field.getGenericType().toString().equals("class java.lang.Short")) {
+						Method m = (Method) object.getClass().getMethod("get" + getMethodName(field.getName()));
+						Short val = (Short) m.invoke(object);
+						if(val==null){
+							logger.debug(field.getName()+"is null");
+							throw new ParamNotFoundException(field.getName());
+						}
+						continue;
+					}
+					//如果是枚举类型
+					if(field.getGenericType().toString().contains(".bean.enums.")){
+						Method m = (Method) object.getClass().getMethod("get" + getMethodName(field.getName()));
+						if(m.invoke(object) == null){
+							logger.debug(field.getName()+"is null");
+							throw new ParamNotFoundException(field.getName());
+						}
+						continue;
+					}
+					//其他类型
+					Method m = (Method) object.getClass().getMethod("get" + getMethodName(field.getName()));
+					if(m.invoke(object) == null){
+						logger.debug(field.getName()+"is null");
+						throw new ParamNotFoundException(field.getName());
+					}
+				}
+			} catch (NoSuchMethodException e) {
+				log.error(e.getMessage());
+			} catch (SecurityException e) {
+				log.error(e.getMessage());
+			} catch (ParamNotFoundException e) {
+				throw e;
+			} catch (Exception e){
+				log.error(e.getMessage());
+			}
+		}
+	}
+	
+	/**
+	 * 
+	 * 方法说明:包含的参数校验
+	 * @author 吴洪双
+	 * 2016年1月13日下午5:26:41
+	 * @param object
+	 * @param sel
+	 * @throws NoSuchMethodException
+	 * @throws SecurityException
+	 * @throws Exception
+	 * @throws ParamNotFoundException
+	 */
+	public static void objectNullOrEmptySel(Object object,String sel) throws ParamNotFoundException{
+		if (object != null ) {// if (object!=null
+			try{
+				// 拿到该类
+				Class<?> clz = object.getClass();
+				// 获取实体类的所有属性,返回Field数组
+				Field[] fields = clz.getDeclaredFields();
+				ArrayList<Field> fieldList= new ArrayList<Field>();
+				for (Field field : fields) {
+					fieldList.add(field);
+				}
+				//获取实体类所有父类的属性
+				fieldList = getAllFields(clz,fieldList);
+				
+				for (Field field : fieldList) {// --for() begin
+					if(!sel.contains(field.getName()+"$") || "serialVersionUID".equals(field.getName())){
+						continue;
+					}
+					// 如果类型是String
+					if (field.getGenericType().toString().equals("class java.lang.String")) { // 如果type是类类型,则前面包含"class ",后面跟类名
+						// 拿到该属性的gettet方法
+						Method m = (Method) object.getClass().getMethod("get" + getMethodName(field.getName()));
+						String val = (String) m.invoke(object);// 调用getter方法获取属性值
+						if(val==null || val.length() == 0){
+							logger.debug(field.getName()+" is null");
+							throw new ParamNotFoundException(field.getName());
+						}
+						continue;
+					}
+					// 如果类型是Date
+					if (field.getGenericType().toString().equals("class java.util.Date")) {
+						Method m = (Method) object.getClass().getMethod("get" + getMethodName(field.getName()));
+						Date val = (Date) m.invoke(object);
+						if(val==null){
+							logger.debug(field.getName()+" is null");
+							throw new ParamNotFoundException(field.getName());
+						}
+						continue;
+					}
+					// 如果类型是Integer
+					if (field.getGenericType().toString().equals("class java.lang.Integer")) {
+						Method m = (Method) object.getClass().getMethod("get" + getMethodName(field.getName()));
+						Integer val = (Integer) m.invoke(object);
+						if(val==null){
+							logger.debug(field.getName()+" is null");
+							throw new ParamNotFoundException(field.getName());
+						}
+						continue;
+					}
+					// 如果类型是Double
+					if (field.getGenericType().toString().equals("class java.lang.Double")) {
+						Method m = (Method) object.getClass().getMethod("get" + getMethodName(field.getName()));
+						Double val = (Double) m.invoke(object);
+						if(val==null){
+							logger.debug(field.getName()+" is null");
+							throw new ParamNotFoundException(field.getName());
+						}
+						continue;
+					}
+					// 如果类型是Boolean 是封装类
+					if (field.getGenericType().toString().equals("class java.lang.Boolean")) {
+						Method m = (Method) object.getClass().getMethod(field.getName());
+						Boolean val = (Boolean) m.invoke(object);
+						if(val==null){
+							logger.debug(field.getName()+" is null");
+							throw new ParamNotFoundException(field.getName());
+						}
+						continue;
+					}
+					// 如果类型是boolean 基本数据类型不一样 这里有点说名如果定义名是 isXXX的 那就全都是isXXX的
+					// 反射找不到getter的具体名
+					if (field.getGenericType().toString().equals("boolean")) {
+						Method m = (Method) object.getClass().getMethod(field.getName());
+						Boolean val = (Boolean) m.invoke(object);
+						if(val==null){
+							logger.debug(field.getName()+"is null");
+							throw new ParamNotFoundException(field.getName());
+						}
+						continue;
+					}
+					// 如果类型是Short
+					if (field.getGenericType().toString().equals("class java.lang.Short")) {
+						Method m = (Method) object.getClass().getMethod("get" + getMethodName(field.getName()));
+						Short val = (Short) m.invoke(object);
+						if(val==null){
+							logger.debug(field.getName()+"is null");
+							throw new ParamNotFoundException(field.getName());
+						}
+						continue;
+					}
+					//如果是枚举类型
+					if(field.getGenericType().toString().contains(".bean.enums.")){
+						Method m = (Method) object.getClass().getMethod("get" + getMethodName(field.getName()));
+						if(m.invoke(object) == null){
+							logger.debug(field.getName()+"is null");
+							throw new ParamNotFoundException(field.getName());
+						}
+						continue;
+					}
+					//其他类型
+					Method m = (Method) object.getClass().getMethod("get" + getMethodName(field.getName()));
+					if(m.invoke(object) == null){
+						logger.debug(field.getName()+"is null");
+						throw new ParamNotFoundException(field.getName());
+					}
+				}
+			} catch (NoSuchMethodException e) {
+				log.error(e.getMessage());
+			} catch (SecurityException e) {
+				log.error(e.getMessage());
+			} catch (ParamNotFoundException e) {
+				throw e;
+			} catch (Exception e){
+				log.error(e.getMessage());
+			}
+		}
+		
+	}
+	
+	/**
+	 * 
+	 * 方法说明:返回方法名称   把一个字符串的第一个字母大写、效率是最高的、
+	 * @author 吴洪双
+	 * 2016年1月13日上午11:12:41
+	 * @param fildeName
+	 * @return
+	 * @throws Exception
+	 */
+	public static String getMethodName(String fildeName) throws Exception {
+		byte[] items = fildeName.getBytes();
+		items[0] = (byte) ((char) items[0] - 'a' + 'A');
+		return new String(items);
+	}
+
+	public static Class getPropertyType(Object property) {
+		if(property instanceof String) {
+			return String.class;
+		}
+		else if(property instanceof Integer) {
+			return Integer.class;
+		}
+		else if(property instanceof Long) {
+			return Long.class;
+		}
+		else if(property instanceof Double) {
+			return Double.class;
+		}
+		else if(property instanceof Date) {
+			return Date.class;
+		}
+		else if(property instanceof Boolean) {
+			return Boolean.class;
+		}
+		else {
+			return String.class;
+		}
+	}
+}

+ 77 - 0
src/main/java/com/shawn/util/MD5Util.java

@@ -0,0 +1,77 @@
+package com.shawn.util;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.security.MessageDigest;
+@Slf4j
+public class MD5Util{
+
+
+    /**
+     * 对字符串md5加密(小写+字母)
+     *
+     * @param str 传入要加密的字符串
+     * @return  MD5加密后的字符串
+     */
+    public static String getMD5(String str) {
+        return MD5Util.MD5(str).toLowerCase();
+    }
+//    public static String getMD5(String str) {
+//        try {
+//            // 生成一个MD5加密计算摘要
+//            MessageDigest md = MessageDigest.getInstance("MD5");
+//            // 计算md5函数
+//            md.update(str.getBytes());
+//            // digest()最后确定返回md5 hash值,返回值为8为字符串。因为md5 hash值是16位的hex值,实际上就是8位的字符
+//            // BigInteger函数则将8位的字符串转换成16位hex值,用字符串来表示;得到字符串形式的hash值
+//            return new BigInteger(1, md.digest()).toString(16);
+//
+//        } catch (Exception e) {
+//            log.error(e.getMessage());
+//            return null;
+//        }
+//    }
+
+
+    /**
+     * 对字符串md5加密(大写+数字)
+     * @param s 传入要加密的字符串
+     * @return  MD5加密后的字符串
+     */
+
+    public static String MD5(String s) {
+        char hexDigits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
+
+        try {
+            byte[] btInput = s.getBytes();
+            // 获得MD5摘要算法的 MessageDigest 对象
+            MessageDigest mdInst = MessageDigest.getInstance("MD5");
+            // 使用指定的字节更新摘要
+            mdInst.update(btInput);
+            // 获得密文
+            byte[] md = mdInst.digest();
+            // 把密文转换成十六进制的字符串形式
+            int j = md.length;
+            char str[] = new char[j * 2];
+            int k = 0;
+            for (int i = 0; i < j; i++) {
+                byte byte0 = md[i];
+                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
+                str[k++] = hexDigits[byte0 & 0xf];
+            }
+            return new String(str);
+        } catch (Exception e) {
+            log.debug("md5加密:"+e.getMessage());
+//            log.error(e.getMessage());
+            return null;
+        }
+    }
+
+//    public static void main(String[] args) {
+//        String md5 = MD5Util.MD5("[\"/USER-SERVER/User/HrPotUser/selectUserByOption\",[\"status\",\"supervisorName\"],[\"0\",\"于伟\"]]");
+//        System.out.println(md5);
+//        String md52 = MD5Util.getMD5("[\"/USER-SERVER/User/HrPotUser/selectUserByOption\",[\"status\",\"supervisorName\"],[\"0\",\"于伟\"]]");
+//        System.out.println(md52);
+//    }
+
+}

+ 103 - 0
src/main/java/com/shawn/util/PageUtil.java

@@ -0,0 +1,103 @@
+package com.shawn.util;
+
+import com.shawn.web.exception.ParameterIllegalException;
+
+/**
+ * @author 吴洪双
+ */
+public class PageUtil {
+
+    /**
+     * Calculate offset for LIMIT clause in SQL. If page < 1, it will return 0.
+     *
+     * @param page    page number
+     * @param perPage size of per page
+     * @return offset
+     */
+    public static int calculateOffset(int page, int perPage) {
+        return calculateOffset(page, perPage, 0);
+    }
+
+    /**
+     * Calculate offset for LIMIT clause in SQL. If page < 1, it will return defaultValue.
+     *
+     * @param page         page number
+     * @param perPage      size of per page
+     * @param defaultValue default return value, if page < 1
+     * @return offset
+     */
+    public static int calculateOffset(int page, int perPage, int defaultValue) {
+        return page < 1 ? defaultValue : (page - 1) * perPage;
+    }
+
+    /**
+     * Calculate total number of pages.
+     *
+     * @param rowCount count of rows
+     * @param perPage  size of per page
+     * @return total number of pages
+     */
+    public static int calculateTotalPage(int rowCount, int perPage) {
+        return (rowCount % perPage == 0) ? (rowCount / perPage) : (rowCount / perPage + 1);
+    }
+
+    /**
+     * Parse page from String to int.
+     *
+     * @param pageString   origin
+     * @param defaultValue default page, if pageString == null
+     * @return parsed page
+     */
+    public static int parsePage(String pageString, int defaultValue) {
+        return parseParameter(pageString, defaultValue);
+    }
+
+    /**
+     * Parse size of per page from String to int.
+     *
+     * @param perPageString origin
+     * @param defaultValue  default size of per page, if perPageString == null
+     * @return parsed size of per page
+     */
+    public static int parsePerPage(String perPageString, int defaultValue) {
+        return parsePage(perPageString, defaultValue);
+    }
+    public static int parsePerPage(Integer perPageInteger, int defaultValue) {
+    	return parsePage(perPageInteger.toString(), defaultValue);
+    }
+    
+    public static int parseOffset(String offsetString, int defaultValue) {
+    	return parsePage(offsetString, defaultValue);
+    }
+    public static int parseOffset(Integer offsetInteger, int defaultValue) {
+    	return parsePage(offsetInteger.toString(), defaultValue);
+    }
+
+    /**
+     * A helper method, parsing parameter about pagination.
+     * If the string is null, return the default value.
+     * If the string is not a number or the number < 1,
+     * throw a parameter illegal exception.
+     *
+     * @param parameterString origin
+     * @param defaultValue default value, if parameterString == null
+     * @return parsed parameter
+     */
+    private static int parseParameter(String parameterString, int defaultValue) {
+        if (parameterString == null) {
+            return defaultValue;
+        }
+
+        int parameter;
+        try {
+            parameter = Integer.parseInt(parameterString);
+        } catch (Exception e) {
+            throw new ParameterIllegalException();
+        }
+        if (parameter < 0) {
+            throw new ParameterIllegalException();
+        }
+        return parameter;
+    }
+
+}

+ 36 - 0
src/main/java/com/shawn/util/SerializeUtil.java

@@ -0,0 +1,36 @@
+package com.shawn.util;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+public class SerializeUtil {
+    public static byte[] serialize(Object object) {
+        ObjectOutputStream oos = null;
+        ByteArrayOutputStream baos = null;
+        try {
+            // 序列化
+            baos = new ByteArrayOutputStream();
+            oos = new ObjectOutputStream(baos);
+            oos.writeObject(object);
+            byte[] bytes = baos.toByteArray();
+            return bytes;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    public static Object unserialize(byte[] bytes) {
+        ByteArrayInputStream bais = null;
+        try {
+            // 反序列化
+            bais = new ByteArrayInputStream(bytes);
+            ObjectInputStream ois = new ObjectInputStream(bais);
+            return ois.readObject();
+        } catch (Exception e) {
+
+        }
+        return null;
+    }
+}

+ 39 - 0
src/main/java/com/shawn/util/SpringBeanUtil.java

@@ -0,0 +1,39 @@
+package com.shawn.util;
+
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SpringBeanUtil implements ApplicationContextAware {
+  
+    private static ApplicationContext applicationContext;
+  
+    @Override  
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        if(SpringBeanUtil.applicationContext == null) {
+            SpringBeanUtil.applicationContext = applicationContext;
+        }  
+    }  
+  
+    //获取applicationContext  
+    public static ApplicationContext getApplicationContext() {
+        return applicationContext;  
+    }  
+  
+    //通过name获取 Bean.  
+    public static Object getBean(String name){  
+        return getApplicationContext().getBean(name);  
+    }  
+  
+    //通过class获取Bean.  
+    public static <T> T getBean(Class<T> clazz){  
+        return getApplicationContext().getBean(clazz);  
+    }  
+  
+    //通过name,以及Clazz返回指定的Bean  
+    public static <T> T getBean(String name,Class<T> clazz){  
+        return getApplicationContext().getBean(name, clazz);  
+    }  
+}  

+ 27 - 0
src/main/java/com/shawn/util/UniqueIDUtil.java

@@ -0,0 +1,27 @@
+package com.shawn.util;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.Date;
+import java.util.UUID;
+
+/**
+ * 生成36位的唯一id
+ * wuhs
+ */
+@Slf4j
+public class UniqueIDUtil {
+
+    public static String getUniqueID(){
+        String id = DateUtils.formatDate(new Date(),DateUtils.PATTERN_yyyyMMddHHmmssSSS);
+        UUID uuid=UUID.randomUUID();
+        String uuidStr=uuid.toString().replaceAll("-","");
+        id=(id+uuidStr).substring(0,34);
+        return id;
+    }
+
+    public static String getToken(){
+        String token = UUID.randomUUID().toString().replaceAll("-", "");
+        return token;
+    }
+}

+ 15 - 0
src/main/java/com/shawn/web/Response/BodyHandlerFunction.java

@@ -0,0 +1,15 @@
+package com.shawn.web.Response;
+
+import org.reactivestreams.Publisher;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import reactor.core.publisher.Mono;
+
+import java.util.function.BiFunction;
+
+/**
+ * 响应body拦截处理接口
+ */
+public interface BodyHandlerFunction
+        extends BiFunction<ServerHttpResponse, Publisher<? extends DataBuffer>, Mono<Void>> {
+}

+ 52 - 0
src/main/java/com/shawn/web/Response/BodyHandlerServerHttpResponseDecorator.java

@@ -0,0 +1,52 @@
+package com.shawn.web.Response;
+
+import org.reactivestreams.Publisher;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+/**
+ * ServerHttpResponse包装类,通过ResponseBodyHandlerFunction处理响应body
+ */
+public class BodyHandlerServerHttpResponseDecorator extends ServerHttpResponseDecorator {
+
+    /**
+     * body 处理拦截器
+     */
+    private BodyHandlerFunction bodyHandler = initDefaultBodyHandler();
+
+    /**
+     * 构造函数
+     *
+     * @param bodyHandler
+     * @param delegate
+     */
+    public BodyHandlerServerHttpResponseDecorator(BodyHandlerFunction bodyHandler, ServerHttpResponse delegate) {
+        super(delegate);
+        if (bodyHandler != null) {
+            this.bodyHandler = bodyHandler;
+        }
+    }
+
+    @Override
+    public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
+        //body 拦截处理器处理响应
+        return bodyHandler.apply(getDelegate(), body);
+    }
+
+    @Override
+    public Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) {
+        return writeWith(Flux.from(body).flatMapSequential(p -> p));
+    }
+
+    /**
+     * 默认body拦截处理器
+     *
+     * @return
+     */
+    private BodyHandlerFunction initDefaultBodyHandler() {
+        return (resp, body) -> resp.writeWith(body);
+    }
+}

+ 88 - 0
src/main/java/com/shawn/web/Response/DefaultClientResponseAdapter.java

@@ -0,0 +1,88 @@
+package com.shawn.web.Response;
+
+import org.reactivestreams.Publisher;
+import org.springframework.cloud.gateway.support.DefaultClientResponse;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseCookie;
+import org.springframework.http.client.reactive.ClientHttpResponse;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.reactive.function.client.ExchangeStrategies;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+/**
+ * ClientResponse适配器,用于将body转换为DefaultClientResponse对象进而对body流反序列化
+ *
+ */
+public class DefaultClientResponseAdapter extends DefaultClientResponse {
+
+    /**
+     * @param body
+     * @param httpHeaders
+     */
+    public DefaultClientResponseAdapter(Publisher<? extends DataBuffer> body,
+                                        HttpHeaders httpHeaders) {
+        this(new ResponseAdapter(body, httpHeaders),
+                ExchangeStrategies.withDefaults());
+    }
+
+    /**
+     * @param response
+     * @param strategies
+     */
+    public DefaultClientResponseAdapter(ClientHttpResponse response,
+                                        ExchangeStrategies strategies) {
+        super(response, strategies);
+    }
+
+    /**
+     * ClientHttpResponse 适配器
+     */
+    static class ResponseAdapter implements ClientHttpResponse {
+        /**
+         * 响应数据
+         */
+        private final Flux<DataBuffer> flux;
+        /**
+         *
+         */
+        private final HttpHeaders headers;
+
+        public ResponseAdapter(Publisher<? extends DataBuffer> body,
+                               HttpHeaders headers) {
+            this.headers = headers;
+            if (body instanceof Flux) {
+                flux = (Flux) body;
+            } else {
+                flux = ((Mono) body).flux();
+            }
+        }
+
+        @Override
+        public Flux<DataBuffer> getBody() {
+            return flux;
+        }
+
+        @Override
+        public HttpHeaders getHeaders() {
+            return headers;
+        }
+
+        @Override
+        public HttpStatus getStatusCode() {
+            return null;
+        }
+
+        @Override
+        public int getRawStatusCode() {
+            return 0;
+        }
+
+        @Override
+        public MultiValueMap<String, ResponseCookie> getCookies() {
+            return null;
+        }
+    }
+}

+ 170 - 0
src/main/java/com/shawn/web/controller/GatewayWhiteListController.java

@@ -0,0 +1,170 @@
+/**
+ * Date:2019-16-04 16:16:04
+ * author:吴洪双
+*/
+
+package com.shawn.web.controller;
+
+import com.shawn.MyGlobalFilter;
+import com.shawn.model.dto.ResultMessage;
+import com.shawn.model.entity.GatewayWhiteList;
+import com.shawn.service.impl.GatewayWhiteListServiceImpl;
+import com.shawn.service.interfac.ReportOprDetlServiceInterface;
+import com.shawn.util.UniqueIDUtil;
+import lombok.extern.apachecommons.CommonsLog;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+import static com.shawn.MyGlobalFilter.EXPIRE_TIME;
+
+@CommonsLog
+@RestController
+@RequestMapping("GatewayWhiteList")
+public class GatewayWhiteListController{
+
+	@Autowired
+	private RedisTemplate redisTemplate;
+
+	@Autowired
+	public GatewayWhiteListServiceImpl gatewayWhiteListService;
+
+	@Autowired
+	private ReportOprDetlServiceInterface reportOprDetlService;
+
+	/**
+	 * 持久化流水
+	 */
+	@GetMapping("/redisLog2Mysql")
+	public ResponseEntity<?> redisLog2Mysql(){
+		reportOprDetlService.redisLog2Mysql();
+		return ResponseEntity
+				.status(HttpStatus.OK)
+				.body(new ResultMessage()
+						.setCode(true)
+						.setMessage("SUCCESS"));
+	}
+	/**
+	 * 统一熔断返回信息
+	 * @return
+	 */
+	@RequestMapping("/fallback")
+	public ResponseEntity<?> fallback() {
+		return ResponseEntity
+				.status(HttpStatus.OK)
+				.body(new ResultMessage()
+						.setCode(false)
+						.setMessage("8888,访问服务出错,稍后再试"));
+	}
+
+	/**
+	 * 心跳
+	 * @return
+	 */
+	@RequestMapping("/heartbeat")
+	public ResponseEntity<?> heartbeat() {
+		return ResponseEntity
+				.status(HttpStatus.OK)
+				.body(new ResultMessage()
+						.setCode(true)
+						.setMessage("SUCCESS"));
+	}
+	@GetMapping("/checkToken")
+    public ResponseEntity<?> checkToken(@RequestHeader(value=HttpHeaders.AUTHORIZATION) String authName){
+		//获取认证名称
+		if (StringUtils.isNotEmpty(authName)) {
+			//用户请求时会在头部 Authorization 传给我之前存储的token, 我用来验证
+			authName = authName.replace("Bearer ", "");
+			//查询redis是否有token
+			if (redisTemplate.hasKey(authName)) {
+				//获取redis里面数据的存活时间
+				Long expirationDate = redisTemplate.getExpire(authName, TimeUnit.SECONDS);
+				//如果还在有效期,重置redis里面数据的存活时间
+				if (expirationDate > 0) {
+					return ResponseEntity
+							.status(HttpStatus.OK)
+							.body(new ResultMessage()
+									.setCode(true)
+									.setData(expirationDate)
+							);
+				}
+			}
+		}
+        return ResponseEntity
+                .status(HttpStatus.OK)
+                .body(new ResultMessage()
+                        .setCode(false));
+    }
+//    @GetMapping("/setRedis")
+//    public ResponseEntity<?> setRedis(String name ,String value){
+//        redisTemplate.opsForValue().set(name,value);
+//        return ResponseEntity
+//                .status(HttpStatus.OK)
+//                .body(new ResultMessage()
+//                        .setCode(true));
+//    }
+//    @GetMapping("/getRedis")
+//    public ResponseEntity<?> getRedis(String name ){
+//        String value = (String) redisTemplate.opsForValue().get(name);
+//        return ResponseEntity
+//                .status(HttpStatus.OK)
+//                .body(new ResultMessage()
+//                        .setData(value)
+//                        .setCode(true));
+//    }
+
+	/**
+	 * 外系统获取token
+	 * @param serverId
+	 * @return
+	 */
+	@GetMapping("/getOutSideSysToken")
+	public ResponseEntity<?> getOutSideSysToken(String serverId){
+		if(StringUtils.isEmpty(serverId)){
+			return ResponseEntity
+					.status(HttpStatus.OK)
+					.body(new ResultMessage()
+							.setCode(false)
+							.setMessage("不允许该系统访问,请联系管理员"));
+		}
+		// 获取该系统对应的token白名单
+		List<GatewayWhiteList> whiteList = gatewayWhiteListService.getWhiteList();
+		Optional op = whiteList.stream().filter(e ->{
+			return "1".equals(e.getIfOutsideSys()) && serverId.equals(e.getServerId());
+		}).findFirst();
+
+		if(op.isPresent()){
+			//生成token
+			String token = UniqueIDUtil.getToken();
+			//存储redis里
+			redisTemplate.opsForValue().set(token, MyGlobalFilter.OUT_SIDE_SYS_ + serverId, EXPIRE_TIME, TimeUnit.SECONDS);
+			return ResponseEntity
+					.status(HttpStatus.OK)
+					.body(new ResultMessage()
+							.setCode(true)
+							.setData(token)
+							.setMessage("SUCCESS"));
+		}else{
+			return ResponseEntity
+					.status(HttpStatus.OK)
+					.body(new ResultMessage()
+							.setCode(false)
+							.setMessage("不允许该系统访问,请联系管理员"));
+		}
+
+
+	}
+
+}

+ 452 - 0
src/main/java/com/shawn/web/controller/base/BaseController.java

@@ -0,0 +1,452 @@
+package com.shawn.web.controller.base;
+
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.shawn.constant.PageConstant;
+import com.shawn.model.bean.PageBean;
+import com.shawn.model.dto.PaginatedResult;
+import com.shawn.model.dto.ResultMessage;
+import com.shawn.service.base.BaseServiceInterface;
+import com.shawn.util.FgObjectUtil;
+import com.shawn.util.PageUtil;
+import com.shawn.web.exception.MyException;
+import com.shawn.web.exception.ResourceNotFoundException;
+
+import lombok.extern.apachecommons.CommonsLog;
+import lombok.extern.slf4j.Slf4j;
+/*
+ * 一:@RequestParam 与 @RequestBody
+ * 1、@RequestParam 用来处理 content-type 为 application/x-www-form-urlencoded 编码的内容
+ * 2、@RequestBody 用来处理除content-type 为 application/x-www-form-urlencoded 编码的内容
+ * 如 application/json,application/xml 
+ * 
+ * 二:在不给定注解的情况下,参数默认是怎么绑定的?
+ * 1、若为简单类型:调用@RequestParam
+ * 2、若为复杂类型,如对象,调用@ModelAttribute
+ */
+@Slf4j
+public abstract class BaseController<ENTITY, ENTITYExample,ENTITYParam, ID extends Serializable> {
+	protected BaseServiceInterface<ENTITY,ENTITYExample,ENTITYParam, ID> baseService;
+	public BaseController(BaseServiceInterface<ENTITY,ENTITYExample,ENTITYParam, ID> service){
+		this.baseService = service;
+	}
+	
+	/**
+	 * 自定义获取各model的id
+	 * @param entity
+	 * @return
+	 * @throws InvocationTargetException 
+	 * @throws IllegalArgumentException 
+	 * @throws IllegalAccessException 
+	 * @throws SecurityException 
+	 * @throws NoSuchMethodException 
+	 */
+	protected ID getEntityId(ENTITY entity) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
+        Class entityClass = entity.getClass();
+        Method m = entityClass.getDeclaredMethod("getPrimaryKey");
+        m.setAccessible(true);//因为写成private 所以这里必须设置
+        return (ID)m.invoke(entity);
+	}
+	/**
+	 * 自定义设置各model的id
+	 * @param entity
+	 * @return
+	 * @throws InvocationTargetException 
+	 * @throws IllegalArgumentException 
+	 * @throws IllegalAccessException 
+	 * @throws SecurityException 
+	 * @throws NoSuchMethodException 
+	 */
+	protected void setEntityId(ENTITY entity,ID id) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
+		Class entityClass = entity.getClass();
+        Method m = entityClass.getDeclaredMethod("hasPrimaryKey");
+        m.setAccessible(true);//因为写成private 所以这里必须设置
+        boolean flag = (boolean)m.invoke(entity);
+        if(flag) {
+        	Object property = getEntityId(entity);// 调用getter方法获取属性值
+        	Method m2 = entityClass.getDeclaredMethod("setPrimaryKey",FgObjectUtil.getPropertyType(property));
+        	m2.setAccessible(true);//因为写成private 所以这里必须设置
+        	m2.invoke(entity,id);
+        }
+		
+		/*if(id instanceof String) {
+			Method m = entityClass.getDeclaredMethod("setPrimaryKey",String.class);
+			m.setAccessible(true);//因为写成private 所以这里必须设置
+			m.invoke(entity,id);
+		}else if(id instanceof Long){
+			Method m = entityClass.getDeclaredMethod("setPrimaryKey",Long.class);
+			m.setAccessible(true);//因为写成private 所以这里必须设置
+			m.invoke(entity,id);
+		}else if(id instanceof Integer) {
+			Method m = entityClass.getDeclaredMethod("setPrimaryKey",Integer.class);
+			m.setAccessible(true);//因为写成private 所以这里必须设置
+			m.invoke(entity,id);
+		}*/
+	}
+	/**
+	 * 自定义new 一个实体对应的ENTITYExample
+	 * @return
+	 */
+	protected abstract ENTITYExample createNewExample();
+	/**
+	 * 自定义获取model 表的名称
+	 */
+	protected String getResourceName() {
+		return baseService.getResourceName();
+	}
+	
+	
+	/**
+	 * 根据id获取一条实体表记录
+	 * @param id
+	 * @return
+	 */
+    @GetMapping("/{id}")
+    public ResponseEntity<?> getEntityById(@PathVariable ID id) {
+    	ENTITY entity = baseService.selectEntityById(id);
+    	if(entity==null){
+    		throw new ResourceNotFoundException()
+			.setResourceName(getResourceName())
+			.setId(id.toString());
+    	}
+    	return ResponseEntity
+				.status(HttpStatus.OK)
+				.body(new ResultMessage()
+						.setCode(true)
+						.setData(entity)
+						.setMessage("SUCCESS"));
+    }
+
+    /**
+     * 新增实体表数据
+     * @param entity
+     * @return
+     * @throws SecurityException 
+     * @throws NoSuchMethodException 
+     * @throws InstantiationException 
+     * @throws InvocationTargetException 
+     * @throws IllegalArgumentException 
+     * @throws IllegalAccessException 
+     */
+    @PostMapping("/postEntity")
+    public ResponseEntity<?> postEntity(@RequestBody ENTITY entity) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
+    	Class entityClass = entity.getClass();
+    	setEntityId(entity, (ID)baseService.generateUniqueID());
+    	Integer i = baseService.insert(entity);
+    	return ResponseEntity
+                .status(HttpStatus.OK)
+                .body(new ResultMessage()
+                        .setCode(true)
+                        .setData(i)
+                        .setMessage("SUCCESS"));
+    }
+ 
+    /**
+     * 根据id 更新实体表
+     * @param id
+     * @param entity
+     * @return
+     * @throws SecurityException 
+     * @throws NoSuchMethodException 
+     * @throws InvocationTargetException 
+     * @throws IllegalArgumentException 
+     * @throws IllegalAccessException 
+     */
+    @PutMapping("/{id}")
+    public ResponseEntity<?> putEntity(@PathVariable ID id, @RequestBody ENTITY entity) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
+    	log.debug("id:"+id);
+        assertEntityExist(id);
+        setEntityId(entity,id);
+        baseService.updateById(entity);
+
+        return ResponseEntity
+                .status(HttpStatus.OK)
+                .body(new ResultMessage()
+                        .setCode(true)
+                        .setData(entity)
+                        .setMessage("SUCCESS"));
+    }
+
+    /**
+     * 根据id删除实体表数据
+     * @param id
+     * @return
+     */
+    @DeleteMapping("/{id}")
+    public ResponseEntity<?> deleteEntity(@PathVariable ID id) {
+    	assertEntityExist(id);
+
+    	baseService.deleteById(id);
+
+    	return ResponseEntity
+                .status(HttpStatus.OK)
+                .body(new ResultMessage()
+                        .setCode(true)
+                        .setMessage("SUCCESS"));
+    }
+
+    @GetMapping("/selectAllByPage")
+    public ResponseEntity<?> selectAllByPage(@RequestParam(value = "offset", required = false)String offsetString, 
+    		@RequestParam(value = "limit", required = false) String limitString, 
+    		@RequestParam(value = "order", required = false) String order ) 
+    				throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
+        // Parse request parameters
+        int offset = PageUtil.parseOffset(offsetString, PageConstant.OFFSET);
+        int limit = PageUtil.parsePerPage(limitString, PageConstant.LIMIT);
+        ENTITYExample example = createNewExample();
+        Class exampleClass = example.getClass();
+        Method m = exampleClass.getDeclaredMethod("setLimit", Integer.class);
+        m.setAccessible(true);//因为写成private 所以这里必须设置
+        m.invoke(exampleClass.newInstance(), limit);
+        
+        Method m2 = exampleClass.getDeclaredMethod("setOffset", Integer.class);
+        m2.setAccessible(true);//因为写成private 所以这里必须设置
+        m2.invoke(exampleClass.newInstance(), offset);
+        
+        return ResponseEntity
+                .ok(new PaginatedResult()
+                		.setCode(true)
+                        .setData(baseService.selectByOption(example))
+                        .setTotal(baseService.selectCount(null).intValue()));
+    }
+    /**
+     * 获取实体表所有数据
+     * @return
+     */
+    @GetMapping("/selectAll")
+    public ResponseEntity<?> selectAll() {
+    	
+		List<ENTITY>  entityList = baseService.selectByOption(null);
+		return ResponseEntity
+                .status(HttpStatus.OK)
+                .body(new ResultMessage()
+                        .setCode(true)
+                        .setData(entityList)
+                        .setMessage("SUCCESS"));
+		
+	}
+    /**
+     * 获取实体表总记录数
+     * @return
+     */
+    @GetMapping("/selectCount")
+    public ResponseEntity<?> getCount() {
+    	Long result = baseService.selectCount(null);
+    	return ResponseEntity
+                .status(HttpStatus.OK)
+                .body(new ResultMessage()
+                        .setCode(true)
+                        .setData(result)
+                        .setMessage("SUCCESS"));
+    }
+    
+	/**
+	 * 根据表字段条件查询单表数据
+	 * 只作用于单表,并且所有条件都为EqualTo
+	 * 字段加后缀_like,则做模糊查询
+	 * 字段加后缀_start,则做>=查询
+	 * 字段加后缀_end,则做<=查询
+	 * 
+	 */
+    @GetMapping("/selectEntityByEqualToOption")
+	public ResponseEntity<?> selectEntityByEqualToOption(ENTITYParam param) {
+		ENTITYExample example = (ENTITYExample) entity2example(param,createNewExample());
+		List<ENTITY>  entityList = baseService.selectByOption(example);
+		return ResponseEntity
+                .status(HttpStatus.OK)
+                .body(new ResultMessage()
+                        .setCode(true)
+                        .setData(entityList)
+                        .setMessage("SUCCESS"));
+	}
+    /**
+	 * 根据表字段条件查询单表数据
+	 * 只作用于单表,并且所有条件都为EqualTo
+	 * 字段加后缀_like,则做模糊查询
+	 * 字段加后缀_start,则做>=查询
+	 * 字段加后缀_end,则做<=查询
+	 * 
+	 */
+    @GetMapping("/selectEntityByEqualToOptionByPage")
+    public ResponseEntity<?> selectEntityByEqualToOptionByPage(ENTITYParam param) 
+    		throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
+        ENTITYExample example = (ENTITYExample) entity2example(param,createNewExample());
+        List<ENTITY>  entityList = baseService.selectByOption(example);
+        return ResponseEntity
+                .ok(new PaginatedResult()
+                		.setCode(true)
+                        .setData(entityList)
+                        .setTotal(baseService.selectCount(example).intValue()));
+    }
+    /**
+   	 * 批量更新
+   	 */
+   	@PutMapping("/updateBatchByIdList")
+   	public ResponseEntity<?> updateBatchByIdList(@RequestBody ENTITYParam param) {
+   		
+   		int i= baseService.updateBatchByIdList(param);
+       	return ResponseEntity
+                   .status(HttpStatus.OK)
+                   .body(new ResultMessage()
+                           .setCode(true)
+                           .setData(i)
+   						.setMessage("批量更新"+i+"条数据"));
+   		
+   	}
+   	/**
+   	 * 批量删除
+   	 * @throws InvocationTargetException 
+   	 * @throws IllegalArgumentException 
+   	 * @throws IllegalAccessException 
+   	 * @throws SecurityException 
+   	 * @throws NoSuchMethodException 
+   	 */
+   	@DeleteMapping("/deleteBatchByIdList")
+   	public ResponseEntity<?> deleteBatchByIdList(@RequestBody ENTITYParam param) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
+   		Method method = (Method) param.getClass().getMethod("getPrimaryKeyList");
+           List primaryKeyList = (List)method.invoke(param);//获取主键list
+           
+   		int i= baseService.deleteBatchByIdList(primaryKeyList);
+   		return ResponseEntity
+   				.status(HttpStatus.OK)
+   				.body(new ResultMessage()
+   						.setCode(true)
+   						.setData(i)
+   						.setMessage("批量删除"+i+"条数据"));
+   		
+   	}
+   	/**
+   	 * 批量新增
+   	 * @throws ParseException 
+   	 * @throws SecurityException 
+   	 * @throws NoSuchMethodException 
+   	 * @throws InvocationTargetException 
+   	 * @throws IllegalArgumentException 
+   	 * @throws IllegalAccessException 
+   	 */
+   	@PostMapping("/batchInsert")
+   	public ResponseEntity<?> batchInsert(@RequestBody ENTITYParam param) throws ParseException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+   		Method method = (Method) param.getClass().getMethod("getEntityList");
+   		List<ENTITY> entityList = (List<ENTITY>)method.invoke(param);//获取实体list
+        for (ENTITY entity : entityList) {
+        	setEntityId(entity, (ID)baseService.generateUniqueID());
+		}
+   		int i= baseService.insertBatch(entityList);
+   		return ResponseEntity
+   				.status(HttpStatus.OK)
+   				.body(new ResultMessage()
+   						.setCode(true)
+   						.setData(i)
+   						.setMessage("批量新增"+i+"条数据"));
+   		
+   	}
+    /********************************** HELPER METHOD ***********************************/
+    protected ENTITY assertEntityExist(ID id) {
+    	return baseService
+                .selectById(id)
+                .orElseThrow(() -> new ResourceNotFoundException()
+                        .setResourceName(getResourceName())
+                        .setId(id.toString()));
+    }
+    
+    /**
+     * 将实体的字段自动转为example的EqualTo
+     * @param entity
+     * @param example
+     * @return
+     */
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+	protected Object entity2example(Object entity,Object example){
+    	try {
+	        Class exampleClass = example.getClass();
+	        Method createCriteriaMethod = (Method) exampleClass.getMethod("createCriteria");
+	        Object criteria = createCriteriaMethod.invoke(example);//生成criteria
+	        Class criteriaClass = criteria.getClass();
+	        
+	        //实体
+	        Class entityClass = entity.getClass();
+	        Field[] fields = entityClass.getDeclaredFields();
+	        
+			ArrayList<Field> fieldList= new ArrayList<Field>();
+			for (Field field : fields) {
+				fieldList.add(field);
+			}
+			//获取实体类所有父类的属性
+			fieldList = FgObjectUtil.getAllFields(entityClass,fieldList);
+	        
+	        for (Field field : fieldList) {
+	        	String nameKey = field.getName();
+	    		if("serialVersionUID".equals(nameKey)){
+					continue;
+				}
+	    		
+    			if("distinct".equals(nameKey)) {
+    				Method entityMethod = (Method) entityClass.getMethod("is" + FgObjectUtil.getMethodName(nameKey));
+        			Object  property = entityMethod.invoke(entity);// 调用getter方法获取属性值
+        			if(null ==property || "".equals(property)){
+        				continue;
+        			}
+        			Method m = exampleClass.getMethod("set"+ FgObjectUtil.getMethodName(nameKey), boolean.class);
+    		        m.invoke(example, property);
+    		        continue;
+    			}
+    			
+    			Method entityMethod = (Method) entityClass.getMethod("get" + FgObjectUtil.getMethodName(nameKey));
+    			Object  property = entityMethod.invoke(entity);// 调用getter方法获取属性值
+    			if(null ==property || "".equals(property)){
+    				continue;
+    			}
+    			
+    			if("orderByClause".equals(nameKey)||"limit".equals(nameKey)||"offset".equals(nameKey)) {
+	    			
+	    			Method m = exampleClass.getMethod("set"+ FgObjectUtil.getMethodName(nameKey), FgObjectUtil.getPropertyType(property));
+    		        m.invoke(example, property);
+	    			
+	    		}else if(nameKey.endsWith("_start")||nameKey.endsWith("_end")) {
+	    			String nameKey2 =nameKey.replace("_start", "").replace("_end", "");
+    				if(nameKey.endsWith("_start")) {
+    					Method criteriaMethod = (Method) criteriaClass.getMethod("and" + FgObjectUtil.getMethodName(nameKey2)+"GreaterThanOrEqualTo",FgObjectUtil.getPropertyType(property));
+	    				criteriaMethod.invoke(criteria,property);
+    				}else {
+    					Method criteriaMethod = (Method) criteriaClass.getMethod("and" + FgObjectUtil.getMethodName(nameKey2)+"LessThanOrEqualTo",FgObjectUtil.getPropertyType(property));
+	    				criteriaMethod.invoke(criteria,property);
+    				}
+	    				
+	    		}else if(nameKey.endsWith("_like")){
+	    			String nameKey2 =nameKey.replace("_like", "");
+    				//like 参数必须为string
+					Method criteriaMethod = (Method) criteriaClass.getMethod("and" + FgObjectUtil.getMethodName(nameKey2)+"Like",String.class);
+    				criteriaMethod.invoke(criteria,"%"+property.toString()+"%");
+	    		}else {
+    				Method criteriaMethod = (Method) criteriaClass.getMethod("and" + FgObjectUtil.getMethodName(nameKey)+"EqualTo",FgObjectUtil.getPropertyType(property));
+    				criteriaMethod.invoke(criteria,property);
+	    		}
+	    		
+	        }
+	        return example;  
+        } catch (Exception e) {
+    		log.error(e.getMessage());
+			return null;
+		}
+		
+    }
+   
+}

+ 24 - 0
src/main/java/com/shawn/web/exception/MyException.java

@@ -0,0 +1,24 @@
+package com.shawn.web.exception;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+/**
+ * 违反唯一约束条件
+ * @author 吴洪双
+ */
+@Accessors(chain = true)
+@Setter
+@Getter
+public class MyException extends RuntimeException {
+
+    private static final long serialVersionUID = -2565431806475335331L;
+    
+    String message;
+    
+    public MyException(String message){
+    	this.message = message;
+    }
+    
+}

+ 25 - 0
src/main/java/com/shawn/web/exception/ParamNotFoundException.java

@@ -0,0 +1,25 @@
+package com.shawn.web.exception;
+
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+/**
+ * 参数不符或缺失时报错
+ * @author 吴洪双
+ */
+@Accessors(chain = true)
+@Setter
+public class ParamNotFoundException extends RuntimeException {
+
+    private static final long serialVersionUID = -2565431806475335331L;
+
+    public ParamNotFoundException(String paramName){
+    	this.paramName = paramName;
+    }
+    private String paramName;
+    @Override
+    public String getMessage() {
+        return paramName + " is not null or empty";
+    }
+
+}

+ 10 - 0
src/main/java/com/shawn/web/exception/ParameterIllegalException.java

@@ -0,0 +1,10 @@
+package com.shawn.web.exception;
+
+/**
+ * @author 吴洪双
+ */
+public class ParameterIllegalException extends RuntimeException {
+
+    private static final long serialVersionUID = 8197086462208138875L;
+
+}

+ 25 - 0
src/main/java/com/shawn/web/exception/ResourceNotFoundException.java

@@ -0,0 +1,25 @@
+package com.shawn.web.exception;
+
+import org.apache.commons.lang.StringUtils;
+
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+/**
+ * @author 吴洪双
+ */
+@Accessors(chain = true)
+@Setter
+public class ResourceNotFoundException extends RuntimeException {
+
+    private static final long serialVersionUID = -2565431806475335331L;
+
+    private String resourceName;
+    private String id;
+
+    @Override
+    public String getMessage() {
+        return StringUtils.capitalize(resourceName) + " with id " + id + " is not found.";
+    }
+
+}

+ 10 - 0
src/main/java/com/shawn/web/exception/ServerInternalErrorException.java

@@ -0,0 +1,10 @@
+package com.shawn.web.exception;
+
+/**
+ * @author 吴洪双
+ */
+public class ServerInternalErrorException extends RuntimeException {
+
+    private static final long serialVersionUID = -1168987160778410810L;
+
+}

+ 66 - 0
src/main/resources/application-local.properties

@@ -0,0 +1,66 @@
+server.port=49005
+server.connection-timeout=10000
+server.tomcat.connection-timeout=10000
+spring.http.encoding.charset=utf-8
+spring.http.encoding.force=true
+spring.http.encoding.enabled=true
+# eureka
+spring.application.name=gateway-server
+# ================eureka==========================
+#eureka.instance.hostname=zuul-server
+eureka.instance.prefer-ip-address=true
+eureka.client.service-url.defaultZone=http://eureka1:49014/eureka/
+eureka.instance.ip-address=eureka1
+eureka.client.register-with-eureka=true
+eureka.client.fetch-registry=true
+
+# =================gateway=====================
+spring.cloud.gateway.discovery.locator.enabled=true
+spring.cloud.gateway.default-filters[0]=OprDetl
+
+#=====================log========================
+#Log levels (TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF)
+logging.level.root=INFO
+logging.level.org.springframework=INFO
+logging.level.org.springframework.web=INFO
+logging.level.org.mybatis=ERROR
+logging.level.com.shawn=TRACE
+# File output
+logging.file.max-size=100MB
+#logging.file.max-history=90
+logging.file=/app/applogs/${spring.application.name}/${spring.application.name}.log
+#=========================datasource==================
+spring.datasource.url=jdbc:mysql://mysqlHost:3311/serverwise?characterEncoding=utf-8&useSSL=false
+spring.datasource.username=serverwiseopr
+spring.datasource.password=Serverwiseopr#123
+spring.datasource.driver-class-name=com.mysql.jdbc.Driver
+spring.datasource.type=com.zaxxer.hikari.HikariDataSource
+spring.datasource.hikari.minimum-idle=10
+spring.datasource.hikari.maximum-pool-size=20
+spring.datasource.hikari.auto-commit=true
+spring.datasource.hikari.idle-timeout=30000
+spring.datasource.hikari.pool-name=DatebookHikariCP
+spring.datasource.hikari.max-lifetime=600000
+spring.datasource.hikari.connection-timeout=30000
+spring.datasource.hikari.connection-test-query=SELECT 1
+#=========================mybatis==================
+mybatis.mapper-locations=classpath:com/shawn/repository/mybatis/*Mapper.xml
+mybatis.type-aliases-package=com.shawn.model
+
+
+#=========================redis start==================
+spring.redis.host=redisHost
+spring.redis.port=6379
+#spring.redis.password=
+
+spring.redis.lettuce.pool.max-active=500
+spring.redis.lettuce.pool.max-wait=-1
+spring.redis.lettuce.pool.max-idle=16
+spring.redis.lettuce.pool.min-idle=8
+#spring.redis.lettuce.shutdown-timeout=
+#=========================redis end==================
+
+spring.servlet.multipart.max-file-size=10MB
+spring.servlet.multipart.max-request-size=10MB
+#=========================\u662F\u5426\u8FD4\u56DEmd5\u6BD4\u5BF9\u53C2\u6570==================
+show.param.md5=1

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

@@ -0,0 +1,67 @@
+server.port=49005
+server.connection-timeout=10000
+server.tomcat.connection-timeout=10000
+spring.http.encoding.charset=utf-8
+spring.http.encoding.force=true
+spring.http.encoding.enabled=true
+# eureka
+spring.application.name=gateway-server
+# ================eureka==========================
+#eureka.instance.hostname=zuul-server
+eureka.instance.prefer-ip-address=true
+eureka.client.service-url.defaultZone=http://eureka1:49014/eureka/,http://eureka2:49014/eureka/,http://eureka3:49014/eureka/
+#eureka.instance.ip-address=eureka1
+eureka.client.register-with-eureka=true
+eureka.client.fetch-registry=true
+
+# =================gateway=====================
+spring.cloud.gateway.discovery.locator.enabled=true
+spring.cloud.gateway.default-filters[0]=OprDetl
+
+#=====================log========================
+#Log levels (TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF)
+logging.level.root=INFO
+logging.level.org.springframework=INFO
+logging.level.org.springframework.web=INFO
+logging.level.org.mybatis=ERROR
+logging.level.com.shawn=TRACE
+# File output
+logging.file.max-size=100MB
+#logging.file.max-history=90
+logging.file=/app/applogs/${spring.application.name}/${spring.application.name}.log
+#=========================datasource==================
+spring.datasource.url=jdbc:mysql://syltdb.ywgl.proc.newupbank.com:3311/serverwise?characterEncoding=utf-8&useSSL=false
+spring.datasource.username=serverwiseopr
+spring.datasource.password=Serverwiseopr#123
+spring.datasource.driver-class-name=com.mysql.jdbc.Driver
+spring.datasource.type=com.zaxxer.hikari.HikariDataSource
+spring.datasource.hikari.minimum-idle=10
+spring.datasource.hikari.maximum-pool-size=20
+spring.datasource.hikari.auto-commit=true
+spring.datasource.hikari.idle-timeout=30000
+spring.datasource.hikari.pool-name=DatebookHikariCP
+spring.datasource.hikari.max-lifetime=600000
+spring.datasource.hikari.connection-timeout=30000
+spring.datasource.hikari.connection-test-query=SELECT 1
+#=========================mybatis==================
+mybatis.mapper-locations=classpath:com/shawn/repository/mybatis/*Mapper.xml
+mybatis.type-aliases-package=com.shawn.model
+
+
+#=========================redis start==================
+spring.redis.sentinel.master=mymaster
+spring.redis.sentinel.nodes=21.93.30.47:27000,21.93.30.48:27000,21.93.30.49:27000
+#spring.redis.sentinel.password=redis123456
+spring.redis.password=newupbank
+
+spring.redis.lettuce.pool.max-active=500
+spring.redis.lettuce.pool.max-wait=-1
+spring.redis.lettuce.pool.max-idle=16
+spring.redis.lettuce.pool.min-idle=8
+#spring.redis.lettuce.shutdown-timeout=
+#=========================redis end==================
+
+spring.servlet.multipart.max-file-size=10MB
+spring.servlet.multipart.max-request-size=10MB
+#=========================\u662F\u5426\u8FD4\u56DEmd5\u6BD4\u5BF9\u53C2\u6570==================
+show.param.md5=1

+ 67 - 0
src/main/resources/application-prod2.properties

@@ -0,0 +1,67 @@
+server.port=49005
+server.connection-timeout=10000
+server.tomcat.connection-timeout=10000
+spring.http.encoding.charset=utf-8
+spring.http.encoding.force=true
+spring.http.encoding.enabled=true
+# eureka
+spring.application.name=gateway-server
+# ================eureka==========================
+#eureka.instance.hostname=zuul-server
+eureka.instance.prefer-ip-address=true
+eureka.client.service-url.defaultZone=http://127.0.0.1:49014/eureka/
+#eureka.instance.ip-address=eureka1
+eureka.client.register-with-eureka=true
+eureka.client.fetch-registry=true
+
+# =================gateway=====================
+spring.cloud.gateway.discovery.locator.enabled=true
+spring.cloud.gateway.default-filters[0]=OprDetl
+
+#=====================log========================
+#Log levels (TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF)
+logging.level.root=INFO
+logging.level.org.springframework=INFO
+logging.level.org.springframework.web=INFO
+logging.level.org.mybatis=ERROR
+logging.level.com.shawn=TRACE
+# File output
+logging.file.max-size=100MB
+#logging.file.max-history=90
+logging.file=/app/applogs/${spring.application.name}/${spring.application.name}.log
+#=========================datasource==================
+spring.datasource.url=jdbc:mysql://196.55.6.103:3311/serverwise?characterEncoding=utf-8&useSSL=false
+#spring.datasource.url=jdbc:mysql://appvip.ywgl.proc.newupbank.com:3311/serverwise?characterEncoding=utf-8&useSSL=false
+spring.datasource.username=serverwiseopr
+spring.datasource.password=Serverwiseopr#123
+spring.datasource.driver-class-name=com.mysql.jdbc.Driver
+spring.datasource.type=com.zaxxer.hikari.HikariDataSource
+spring.datasource.hikari.minimum-idle=10
+spring.datasource.hikari.maximum-pool-size=20
+spring.datasource.hikari.auto-commit=true
+spring.datasource.hikari.idle-timeout=30000
+spring.datasource.hikari.pool-name=DatebookHikariCP
+spring.datasource.hikari.max-lifetime=600000
+spring.datasource.hikari.connection-timeout=30000
+spring.datasource.hikari.connection-test-query=SELECT 1
+#=========================mybatis==================
+mybatis.mapper-locations=classpath:com/shawn/repository/mybatis/*Mapper.xml
+mybatis.type-aliases-package=com.shawn.model
+
+
+#=========================redis start==================
+spring.redis.host=196.55.9.246
+spring.redis.port=7000
+spring.redis.password=master123
+
+spring.redis.lettuce.pool.max-active=500
+spring.redis.lettuce.pool.max-wait=-1
+spring.redis.lettuce.pool.max-idle=16
+spring.redis.lettuce.pool.min-idle=8
+#spring.redis.lettuce.shutdown-timeout=
+#=========================redis end==================
+
+spring.servlet.multipart.max-file-size=10MB
+spring.servlet.multipart.max-request-size=10MB
+#=========================\u662F\u5426\u8FD4\u56DEmd5\u6BD4\u5BF9\u53C2\u6570==================
+show.param.md5=1

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

@@ -0,0 +1,2 @@
+spring.profiles.active=prod
+#spring.profiles.active=local

+ 312 - 0
src/main/resources/com/shawn/repository/mybatis/GatewayWhiteListMapper.xml

@@ -0,0 +1,312 @@
+<?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.shawn.repository.GatewayWhiteListMapper">
+  <resultMap id="BaseResultMap" type="com.shawn.model.entity.GatewayWhiteList">
+    <id column="id" jdbcType="VARCHAR" property="id" />
+    <result column="if_outside_sys" jdbcType="CHAR" property="ifOutsideSys" />
+    <result column="server_id" jdbcType="VARCHAR" property="serverId" />
+    <result column="url" jdbcType="VARCHAR" property="url" />
+    <result column="if_check_token" jdbcType="CHAR" property="ifCheckToken" />
+    <result column="if_check_param" jdbcType="CHAR" property="ifCheckParam" />
+    <result column="if_log_response" jdbcType="CHAR" property="ifLogResponse" />
+    <result column="remark" jdbcType="VARCHAR" property="remark" />
+  </resultMap>
+  <sql id="Example_Where_Clause">
+    <where>
+      <foreach collection="oredCriteria" item="criteria" separator="or">
+        <if test="criteria.valid">
+          <trim prefix="(" prefixOverrides="and" suffix=")">
+            <foreach collection="criteria.criteria" item="criterion">
+              <choose>
+                <when test="criterion.noValue">
+                  and ${criterion.condition}
+                </when>
+                <when test="criterion.singleValue">
+                  and ${criterion.condition} #{criterion.value}
+                </when>
+                <when test="criterion.betweenValue">
+                  and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
+                </when>
+                <when test="criterion.listValue">
+                  and ${criterion.condition}
+                  <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
+                    #{listItem}
+                  </foreach>
+                </when>
+              </choose>
+            </foreach>
+          </trim>
+        </if>
+      </foreach>
+    </where>
+  </sql>
+  <sql id="Update_By_Example_Where_Clause">
+    <where>
+      <foreach collection="example.oredCriteria" item="criteria" separator="or">
+        <if test="criteria.valid">
+          <trim prefix="(" prefixOverrides="and" suffix=")">
+            <foreach collection="criteria.criteria" item="criterion">
+              <choose>
+                <when test="criterion.noValue">
+                  and ${criterion.condition}
+                </when>
+                <when test="criterion.singleValue">
+                  and ${criterion.condition} #{criterion.value}
+                </when>
+                <when test="criterion.betweenValue">
+                  and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
+                </when>
+                <when test="criterion.listValue">
+                  and ${criterion.condition}
+                  <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
+                    #{listItem}
+                  </foreach>
+                </when>
+              </choose>
+            </foreach>
+          </trim>
+        </if>
+      </foreach>
+    </where>
+  </sql>
+  <sql id="Base_Column_List">
+    id, if_outside_sys, server_id, url, if_check_token, if_check_param, if_log_response, 
+    remark
+  </sql>
+  <select id="selectByExample" parameterType="com.shawn.model.entity.GatewayWhiteListExample" resultMap="BaseResultMap">
+    select
+    <if test="distinct">
+      distinct
+    </if>
+    <include refid="Base_Column_List" />
+    from gateway_white_list
+    <if test="_parameter != null">
+      <include refid="Example_Where_Clause" />
+    </if>
+    <if test="orderByClause != null">
+      order by ${orderByClause}
+    </if>
+    <if test="limit != null">
+      <if test="offset != null">
+        limit ${offset}, ${limit}
+      </if>
+      <if test="offset == null">
+        limit ${limit}
+      </if>
+    </if>
+  </select>
+  <select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="BaseResultMap">
+    select 
+    <include refid="Base_Column_List" />
+    from gateway_white_list
+    where id = #{id,jdbcType=VARCHAR}
+  </select>
+  <delete id="deleteByPrimaryKey" parameterType="java.lang.String">
+    delete from gateway_white_list
+    where id = #{id,jdbcType=VARCHAR}
+  </delete>
+  <delete id="deleteByExample" parameterType="com.shawn.model.entity.GatewayWhiteListExample">
+    delete from gateway_white_list
+    <if test="_parameter != null">
+      <include refid="Example_Where_Clause" />
+    </if>
+  </delete>
+  <insert id="insert" parameterType="com.shawn.model.entity.GatewayWhiteList">
+    insert into gateway_white_list (id, if_outside_sys, server_id,
+      url, if_check_token, if_check_param, 
+      if_log_response, remark)
+    values (#{id,jdbcType=VARCHAR}, #{ifOutsideSys,jdbcType=CHAR}, #{serverId,jdbcType=VARCHAR}, 
+      #{url,jdbcType=VARCHAR}, #{ifCheckToken,jdbcType=CHAR}, #{ifCheckParam,jdbcType=CHAR}, 
+      #{ifLogResponse,jdbcType=CHAR}, #{remark,jdbcType=VARCHAR})
+  </insert>
+  <insert id="insertSelective" parameterType="com.shawn.model.entity.GatewayWhiteList">
+    insert into gateway_white_list
+    <trim prefix="(" suffix=")" suffixOverrides=",">
+      <if test="id != null">
+        id,
+      </if>
+      <if test="ifOutsideSys != null">
+        if_outside_sys,
+      </if>
+      <if test="serverId != null">
+        server_id,
+      </if>
+      <if test="url != null">
+        url,
+      </if>
+      <if test="ifCheckToken != null">
+        if_check_token,
+      </if>
+      <if test="ifCheckParam != null">
+        if_check_param,
+      </if>
+      <if test="ifLogResponse != null">
+        if_log_response,
+      </if>
+      <if test="remark != null">
+        remark,
+      </if>
+    </trim>
+    <trim prefix="values (" suffix=")" suffixOverrides=",">
+      <if test="id != null">
+        #{id,jdbcType=VARCHAR},
+      </if>
+      <if test="ifOutsideSys != null">
+        #{ifOutsideSys,jdbcType=CHAR},
+      </if>
+      <if test="serverId != null">
+        #{serverId,jdbcType=VARCHAR},
+      </if>
+      <if test="url != null">
+        #{url,jdbcType=VARCHAR},
+      </if>
+      <if test="ifCheckToken != null">
+        #{ifCheckToken,jdbcType=CHAR},
+      </if>
+      <if test="ifCheckParam != null">
+        #{ifCheckParam,jdbcType=CHAR},
+      </if>
+      <if test="ifLogResponse != null">
+        #{ifLogResponse,jdbcType=CHAR},
+      </if>
+      <if test="remark != null">
+        #{remark,jdbcType=VARCHAR},
+      </if>
+    </trim>
+  </insert>
+  <select id="countByExample" parameterType="com.shawn.model.entity.GatewayWhiteListExample" resultType="java.lang.Long">
+    select count(*) from gateway_white_list
+    <if test="_parameter != null">
+      <include refid="Example_Where_Clause" />
+    </if>
+  </select>
+  <update id="updateByExampleSelective" parameterType="map">
+    update gateway_white_list
+    <set>
+      <if test="record.id != null">
+        id = #{record.id,jdbcType=VARCHAR},
+      </if>
+      <if test="record.ifOutsideSys != null">
+        if_outside_sys = #{record.ifOutsideSys,jdbcType=CHAR},
+      </if>
+      <if test="record.serverId != null">
+        server_id = #{record.serverId,jdbcType=VARCHAR},
+      </if>
+      <if test="record.url != null">
+        url = #{record.url,jdbcType=VARCHAR},
+      </if>
+      <if test="record.ifCheckToken != null">
+        if_check_token = #{record.ifCheckToken,jdbcType=CHAR},
+      </if>
+      <if test="record.ifCheckParam != null">
+        if_check_param = #{record.ifCheckParam,jdbcType=CHAR},
+      </if>
+      <if test="record.ifLogResponse != null">
+        if_log_response = #{record.ifLogResponse,jdbcType=CHAR},
+      </if>
+      <if test="record.remark != null">
+        remark = #{record.remark,jdbcType=VARCHAR},
+      </if>
+    </set>
+    <if test="_parameter != null">
+      <include refid="Update_By_Example_Where_Clause" />
+    </if>
+  </update>
+  <update id="updateByExample" parameterType="map">
+    update gateway_white_list
+    set id = #{record.id,jdbcType=VARCHAR},
+      if_outside_sys = #{record.ifOutsideSys,jdbcType=CHAR},
+      server_id = #{record.serverId,jdbcType=VARCHAR},
+      url = #{record.url,jdbcType=VARCHAR},
+      if_check_token = #{record.ifCheckToken,jdbcType=CHAR},
+      if_check_param = #{record.ifCheckParam,jdbcType=CHAR},
+      if_log_response = #{record.ifLogResponse,jdbcType=CHAR},
+      remark = #{record.remark,jdbcType=VARCHAR}
+    <if test="_parameter != null">
+      <include refid="Update_By_Example_Where_Clause" />
+    </if>
+  </update>
+  <update id="updateByPrimaryKeySelective" parameterType="com.shawn.model.entity.GatewayWhiteList">
+    update gateway_white_list
+    <set>
+      <if test="ifOutsideSys != null">
+        if_outside_sys = #{ifOutsideSys,jdbcType=CHAR},
+      </if>
+      <if test="serverId != null">
+        server_id = #{serverId,jdbcType=VARCHAR},
+      </if>
+      <if test="url != null">
+        url = #{url,jdbcType=VARCHAR},
+      </if>
+      <if test="ifCheckToken != null">
+        if_check_token = #{ifCheckToken,jdbcType=CHAR},
+      </if>
+      <if test="ifCheckParam != null">
+        if_check_param = #{ifCheckParam,jdbcType=CHAR},
+      </if>
+      <if test="ifLogResponse != null">
+        if_log_response = #{ifLogResponse,jdbcType=CHAR},
+      </if>
+      <if test="remark != null">
+        remark = #{remark,jdbcType=VARCHAR},
+      </if>
+    </set>
+    where id = #{id,jdbcType=VARCHAR}
+  </update>
+  <update id="updateByPrimaryKey" parameterType="com.shawn.model.entity.GatewayWhiteList">
+    update gateway_white_list
+    set if_outside_sys = #{ifOutsideSys,jdbcType=CHAR},
+      server_id = #{serverId,jdbcType=VARCHAR},
+      url = #{url,jdbcType=VARCHAR},
+      if_check_token = #{ifCheckToken,jdbcType=CHAR},
+      if_check_param = #{ifCheckParam,jdbcType=CHAR},
+      if_log_response = #{ifLogResponse,jdbcType=CHAR},
+      remark = #{remark,jdbcType=VARCHAR}
+    where id = #{id,jdbcType=VARCHAR}
+  </update>
+  <insert id="insertBatch" parameterType="java.util.List">
+    insert into gateway_white_list (id,if_outside_sys,server_id,url,if_check_token,if_check_param,if_log_response,remark) VALUES
+    <foreach collection="list" index="index" item="item" separator=",">
+      ( #{item.id,jdbcType=VARCHAR},#{item.ifOutsideSys,jdbcType=CHAR},#{item.serverId,jdbcType=VARCHAR},#{item.url,jdbcType=VARCHAR},#{item.ifCheckToken,jdbcType=CHAR},#{item.ifCheckParam,jdbcType=CHAR},#{item.ifLogResponse,jdbcType=CHAR},#{item.remark,jdbcType=VARCHAR} )
+    </foreach>
+  </insert>
+  <delete id="deleteBatchByIdList" parameterType="java.util.List">
+    DELETE FROM gateway_white_list where id in
+    <foreach close=")" collection="list" item="item" open="(" separator=",">
+      #{item}
+    </foreach>
+  </delete>
+  <update id="updateBatchByIdList" parameterType="com.shawn.model.param.GatewayWhiteListParam">
+    update gateway_white_list
+    <trim prefix="set" suffixOverrides=",">
+      <if test="id != null">
+        id = #{id},
+      </if>
+      <if test="ifOutsideSys != null">
+        if_outside_sys = #{ifOutsideSys},
+      </if>
+      <if test="serverId != null">
+        server_id = #{serverId},
+      </if>
+      <if test="url != null">
+        url = #{url},
+      </if>
+      <if test="ifCheckToken != null">
+        if_check_token = #{ifCheckToken},
+      </if>
+      <if test="ifCheckParam != null">
+        if_check_param = #{ifCheckParam},
+      </if>
+      <if test="ifLogResponse != null">
+        if_log_response = #{ifLogResponse},
+      </if>
+      <if test="remark != null">
+        remark = #{remark},
+      </if>
+    </trim>
+     where id in 
+    <foreach close=")" collection="primaryKeyList" item="item" open="(" separator=",">
+      #{item}
+    </foreach>
+  </update>
+</mapper>

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 523 - 0
src/main/resources/com/shawn/repository/mybatis/ReportOprDetlMapper.xml