xuhy
2023-08-11 de3fa815fa8f9fdf914972a98491e098c90f8441
初始化日月出行,zuul,demo
47个文件已添加
4672 ■■■■■ 已修改文件
EurekaOKTravel/.gitignore 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EurekaOKTravel/.mvn/wrapper/MavenWrapperDownloader.java 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EurekaOKTravel/.mvn/wrapper/maven-wrapper.jar 补丁 | 查看 | 原始文档 | blame | 历史
EurekaOKTravel/.mvn/wrapper/maven-wrapper.properties 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EurekaOKTravel/mvnw 310 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EurekaOKTravel/mvnw.cmd 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EurekaOKTravel/pom.xml 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EurekaOKTravel/src/main/java/com/sinata/eureka/EurekaApplication.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EurekaOKTravel/src/main/java/com/sinata/eureka/config/WebSecurityConfig.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EurekaOKTravel/src/main/resources/application.yml 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/.gitignore 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/.mvn/wrapper/MavenWrapperDownloader.java 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/.mvn/wrapper/maven-wrapper.jar 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/.mvn/wrapper/maven-wrapper.properties 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/mvnw 310 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/mvnw.cmd 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/pom.xml 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/ZuulApplication.java 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/config/RedisConfig.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/controller/NettyController.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/controller/RedisController.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/util/CrossOriginFilter.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/util/GDMapGeocodingUtil.java 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/util/NettyStartListener.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/util/RedisUtil.java 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/util/ResultUtil.java 188 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/util/SinataUtil.java 405 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/util/SpringUtil.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/util/StringUtil.java 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/util/applets/CacheType.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/util/applets/ChildChannelHandler.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/util/applets/ClientPingMessage.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/util/applets/Global.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/util/applets/NettyServer0.java 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/util/applets/NettyWebSocketController.java 215 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/util/applets/WebSocketHandler.java 180 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/util/applets/createSSLContext.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/util/echo/DiscardServerHandler.java 153 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/util/echo/Method.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/util/echo/NettyChannelMap.java 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/util/echo/NettyMsg.java 165 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/util/echo/NettyServer.java 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/util/echo/NettyServerController.java 400 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/java/com/sinata/zuul/util/echo/ServerInit.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/resources/application.yml 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/resources/redis.properties 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ZuulOKTravel/src/main/resources/static/tXQaRbVjpJ.txt 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EurekaOKTravel/.gitignore
New file
@@ -0,0 +1,31 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**
!**/src/test/**
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
### VS Code ###
.vscode/
EurekaOKTravel/.mvn/wrapper/MavenWrapperDownloader.java
New file
@@ -0,0 +1,118 @@
/*
 * Copyright 2007-present the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
    private static final String WRAPPER_VERSION = "0.5.6";
    /**
     * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
     */
    private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
            + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
    /**
     * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
     * use instead of the default one.
     */
    private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
            ".mvn/wrapper/maven-wrapper.properties";
    /**
     * Path where the maven-wrapper.jar will be saved to.
     */
    private static final String MAVEN_WRAPPER_JAR_PATH =
            ".mvn/wrapper/maven-wrapper.jar";
    /**
     * Name of the property which should be used to override the default download url for the wrapper.
     */
    private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
    public static void main(String args[]) {
        System.out.println("- Downloader started");
        File baseDirectory = new File(args[0]);
        System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
        // If the maven-wrapper.properties exists, read it and check if it contains a custom
        // wrapperUrl parameter.
        File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
        String url = DEFAULT_DOWNLOAD_URL;
        if (mavenWrapperPropertyFile.exists()) {
            FileInputStream mavenWrapperPropertyFileInputStream = null;
            try {
                mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
                Properties mavenWrapperProperties = new Properties();
                mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
                url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
            } catch (IOException e) {
                System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
            } finally {
                try {
                    if (mavenWrapperPropertyFileInputStream != null) {
                        mavenWrapperPropertyFileInputStream.close();
                    }
                } catch (IOException e) {
                    // Ignore ...
                }
            }
        }
        System.out.println("- Downloading from: " + url);
        File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
        if (!outputFile.getParentFile().exists()) {
            if (!outputFile.getParentFile().mkdirs()) {
                System.out.println(
                        "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
            }
        }
        System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
        try {
            downloadFileFromURL(url, outputFile);
            System.out.println("Done");
            System.exit(0);
        } catch (Throwable e) {
            System.out.println("- Error downloading");
            e.printStackTrace();
            System.exit(1);
        }
    }
    private static void downloadFileFromURL(String urlString, File destination) throws Exception {
        if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
            String username = System.getenv("MVNW_USERNAME");
            char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
            Authenticator.setDefault(new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(username, password);
                }
            });
        }
        URL website = new URL(urlString);
        ReadableByteChannel rbc;
        rbc = Channels.newChannel(website.openStream());
        FileOutputStream fos = new FileOutputStream(destination);
        fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
        fos.close();
        rbc.close();
    }
}
EurekaOKTravel/.mvn/wrapper/maven-wrapper.jar
Binary files differ
EurekaOKTravel/.mvn/wrapper/maven-wrapper.properties
New file
@@ -0,0 +1,2 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
EurekaOKTravel/mvnw
New file
@@ -0,0 +1,310 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#    https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven Start Up Batch script
#
# Required ENV vars:
# ------------------
#   JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
#   M2_HOME - location of maven2's installed home dir
#   MAVEN_OPTS - parameters passed to the Java VM when running Maven
#     e.g. to debug Maven itself, use
#       set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
#   MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
  if [ -f /etc/mavenrc ] ; then
    . /etc/mavenrc
  fi
  if [ -f "$HOME/.mavenrc" ] ; then
    . "$HOME/.mavenrc"
  fi
fi
# OS specific support.  $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "`uname`" in
  CYGWIN*) cygwin=true ;;
  MINGW*) mingw=true;;
  Darwin*) darwin=true
    # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
    # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
    if [ -z "$JAVA_HOME" ]; then
      if [ -x "/usr/libexec/java_home" ]; then
        export JAVA_HOME="`/usr/libexec/java_home`"
      else
        export JAVA_HOME="/Library/Java/Home"
      fi
    fi
    ;;
esac
if [ -z "$JAVA_HOME" ] ; then
  if [ -r /etc/gentoo-release ] ; then
    JAVA_HOME=`java-config --jre-home`
  fi
fi
if [ -z "$M2_HOME" ] ; then
  ## resolve links - $0 may be a link to maven's home
  PRG="$0"
  # need this for relative symlinks
  while [ -h "$PRG" ] ; do
    ls=`ls -ld "$PRG"`
    link=`expr "$ls" : '.*-> \(.*\)$'`
    if expr "$link" : '/.*' > /dev/null; then
      PRG="$link"
    else
      PRG="`dirname "$PRG"`/$link"
    fi
  done
  saveddir=`pwd`
  M2_HOME=`dirname "$PRG"`/..
  # make it fully qualified
  M2_HOME=`cd "$M2_HOME" && pwd`
  cd "$saveddir"
  # echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
  [ -n "$M2_HOME" ] &&
    M2_HOME=`cygpath --unix "$M2_HOME"`
  [ -n "$JAVA_HOME" ] &&
    JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
  [ -n "$CLASSPATH" ] &&
    CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
  [ -n "$M2_HOME" ] &&
    M2_HOME="`(cd "$M2_HOME"; pwd)`"
  [ -n "$JAVA_HOME" ] &&
    JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
fi
if [ -z "$JAVA_HOME" ]; then
  javaExecutable="`which javac`"
  if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
    # readlink(1) is not available as standard on Solaris 10.
    readLink=`which readlink`
    if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
      if $darwin ; then
        javaHome="`dirname \"$javaExecutable\"`"
        javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
      else
        javaExecutable="`readlink -f \"$javaExecutable\"`"
      fi
      javaHome="`dirname \"$javaExecutable\"`"
      javaHome=`expr "$javaHome" : '\(.*\)/bin'`
      JAVA_HOME="$javaHome"
      export JAVA_HOME
    fi
  fi
fi
if [ -z "$JAVACMD" ] ; then
  if [ -n "$JAVA_HOME"  ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
      # IBM's JDK on AIX uses strange locations for the executables
      JAVACMD="$JAVA_HOME/jre/sh/java"
    else
      JAVACMD="$JAVA_HOME/bin/java"
    fi
  else
    JAVACMD="`which java`"
  fi
fi
if [ ! -x "$JAVACMD" ] ; then
  echo "Error: JAVA_HOME is not defined correctly." >&2
  echo "  We cannot execute $JAVACMD" >&2
  exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
  echo "Warning: JAVA_HOME environment variable is not set."
fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
  if [ -z "$1" ]
  then
    echo "Path not specified to find_maven_basedir"
    return 1
  fi
  basedir="$1"
  wdir="$1"
  while [ "$wdir" != '/' ] ; do
    if [ -d "$wdir"/.mvn ] ; then
      basedir=$wdir
      break
    fi
    # workaround for JBEAP-8937 (on Solaris 10/Sparc)
    if [ -d "${wdir}" ]; then
      wdir=`cd "$wdir/.."; pwd`
    fi
    # end of workaround
  done
  echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
  if [ -f "$1" ]; then
    echo "$(tr -s '\n' ' ' < "$1")"
  fi
}
BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
  exit 1;
fi
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
    if [ "$MVNW_VERBOSE" = true ]; then
      echo "Found .mvn/wrapper/maven-wrapper.jar"
    fi
else
    if [ "$MVNW_VERBOSE" = true ]; then
      echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
    fi
    if [ -n "$MVNW_REPOURL" ]; then
      jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
    else
      jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
    fi
    while IFS="=" read key value; do
      case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
      esac
    done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
    if [ "$MVNW_VERBOSE" = true ]; then
      echo "Downloading from: $jarUrl"
    fi
    wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
    if $cygwin; then
      wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
    fi
    if command -v wget > /dev/null; then
        if [ "$MVNW_VERBOSE" = true ]; then
          echo "Found wget ... using wget"
        fi
        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
            wget "$jarUrl" -O "$wrapperJarPath"
        else
            wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
        fi
    elif command -v curl > /dev/null; then
        if [ "$MVNW_VERBOSE" = true ]; then
          echo "Found curl ... using curl"
        fi
        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
            curl -o "$wrapperJarPath" "$jarUrl" -f
        else
            curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
        fi
    else
        if [ "$MVNW_VERBOSE" = true ]; then
          echo "Falling back to using Java to download"
        fi
        javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
        # For Cygwin, switch paths to Windows format before running javac
        if $cygwin; then
          javaClass=`cygpath --path --windows "$javaClass"`
        fi
        if [ -e "$javaClass" ]; then
            if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
                if [ "$MVNW_VERBOSE" = true ]; then
                  echo " - Compiling MavenWrapperDownloader.java ..."
                fi
                # Compiling the Java class
                ("$JAVA_HOME/bin/javac" "$javaClass")
            fi
            if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
                # Running the downloader
                if [ "$MVNW_VERBOSE" = true ]; then
                  echo " - Running MavenWrapperDownloader.java ..."
                fi
                ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
            fi
        fi
    fi
fi
##########################################################################################
# End of extension
##########################################################################################
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
  echo $MAVEN_PROJECTBASEDIR
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
  [ -n "$M2_HOME" ] &&
    M2_HOME=`cygpath --path --windows "$M2_HOME"`
  [ -n "$JAVA_HOME" ] &&
    JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
  [ -n "$CLASSPATH" ] &&
    CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
  [ -n "$MAVEN_PROJECTBASEDIR" ] &&
    MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
  $MAVEN_OPTS \
  -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
  "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
EurekaOKTravel/mvnw.cmd
New file
@@ -0,0 +1,182 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements.  See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership.  The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License.  You may obtain a copy of the License at
@REM
@REM    https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied.  See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM     e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on"  echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
    IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
    if "%MVNW_VERBOSE%" == "true" (
        echo Found %WRAPPER_JAR%
    )
) else (
    if not "%MVNW_REPOURL%" == "" (
        SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
    )
    if "%MVNW_VERBOSE%" == "true" (
        echo Couldn't find %WRAPPER_JAR%, downloading it ...
        echo Downloading from: %DOWNLOAD_URL%
    )
    powershell -Command "&{"^
        "$webclient = new-object System.Net.WebClient;"^
        "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
        "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
        "}"^
        "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
        "}"
    if "%MVNW_VERBOSE%" == "true" (
        echo Finished downloading %WRAPPER_JAR%
    )
)
@REM End of extension
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%" == "on" pause
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
exit /B %ERROR_CODE%
EurekaOKTravel/pom.xml
New file
@@ -0,0 +1,82 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.sinata</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>eureka</name>
    <description>Eureka project for Spring Boot</description>
    <packaging>jar</packaging>
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.SR1</spring-cloud.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <!-- 添加安全认证依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </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>
</project>
EurekaOKTravel/src/main/java/com/sinata/eureka/EurekaApplication.java
New file
@@ -0,0 +1,22 @@
package com.sinata.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer//开启服务治理
@SpringBootApplication
public class EurekaApplication extends SpringBootServletInitializer {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class, args);
    }
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(EurekaApplication.class);
    }
}
EurekaOKTravel/src/main/java/com/sinata/eureka/config/WebSecurityConfig.java
New file
@@ -0,0 +1,24 @@
package com.sinata.eureka.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
/**
 * 基于web安全认证
 */
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        // Configure HttpSecurity as needed (e.g. enable http basic).
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);
        http.csrf().disable();
        //注意:为了可以使用 http://${user}:${password}@${host}:${port}/eureka/ 这种方式登录,所以必须是httpBasic,
        // 如果是form方式,不能使用url格式登录
        http.authorizeRequests().anyRequest().authenticated().and().httpBasic();
    }
}
EurekaOKTravel/src/main/resources/application.yml
New file
@@ -0,0 +1,24 @@
server:
  port: 8000  #服务端口号
spring:
  application:
    name: eureka-center #服务名称
  security:
    basic:
      enable: true #开启基于HTTP basic的认证
    user: #配置用户的账号信息
      name: sinata
      password: sinata
eureka:
  instance:
    hostname: 127.0.0.1 #注册中心地址
  client:
    service-url: #客户端调用地址
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
    register-with-eureka: false #是否将自己注册到Eureka服务中,因为该应用本身就是注册中心,不需要再注册自己(集群的时候为true)
    fetch-registry: false #是否从Eureka中获取注册信息,因为自己为注册中心,不会在该应用中的检索服务信息
  server:
    enable-self-preservation: false #禁用自我保护模式,服务不可用时及时从注册中心剔除
    eviction-interval-timer-in-ms: 4000
ZuulOKTravel/.gitignore
New file
@@ -0,0 +1,31 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**
!**/src/test/**
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
### VS Code ###
.vscode/
ZuulOKTravel/.mvn/wrapper/MavenWrapperDownloader.java
New file
@@ -0,0 +1,118 @@
/*
 * Copyright 2007-present the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
    private static final String WRAPPER_VERSION = "0.5.6";
    /**
     * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
     */
    private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
            + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
    /**
     * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
     * use instead of the default one.
     */
    private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
            ".mvn/wrapper/maven-wrapper.properties";
    /**
     * Path where the maven-wrapper.jar will be saved to.
     */
    private static final String MAVEN_WRAPPER_JAR_PATH =
            ".mvn/wrapper/maven-wrapper.jar";
    /**
     * Name of the property which should be used to override the default download url for the wrapper.
     */
    private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
    public static void main(String args[]) {
        System.out.println("- Downloader started");
        File baseDirectory = new File(args[0]);
        System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
        // If the maven-wrapper.properties exists, read it and check if it contains a custom
        // wrapperUrl parameter.
        File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
        String url = DEFAULT_DOWNLOAD_URL;
        if (mavenWrapperPropertyFile.exists()) {
            FileInputStream mavenWrapperPropertyFileInputStream = null;
            try {
                mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
                Properties mavenWrapperProperties = new Properties();
                mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
                url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
            } catch (IOException e) {
                System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
            } finally {
                try {
                    if (mavenWrapperPropertyFileInputStream != null) {
                        mavenWrapperPropertyFileInputStream.close();
                    }
                } catch (IOException e) {
                    // Ignore ...
                }
            }
        }
        System.out.println("- Downloading from: " + url);
        File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
        if (!outputFile.getParentFile().exists()) {
            if (!outputFile.getParentFile().mkdirs()) {
                System.out.println(
                        "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
            }
        }
        System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
        try {
            downloadFileFromURL(url, outputFile);
            System.out.println("Done");
            System.exit(0);
        } catch (Throwable e) {
            System.out.println("- Error downloading");
            e.printStackTrace();
            System.exit(1);
        }
    }
    private static void downloadFileFromURL(String urlString, File destination) throws Exception {
        if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
            String username = System.getenv("MVNW_USERNAME");
            char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
            Authenticator.setDefault(new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(username, password);
                }
            });
        }
        URL website = new URL(urlString);
        ReadableByteChannel rbc;
        rbc = Channels.newChannel(website.openStream());
        FileOutputStream fos = new FileOutputStream(destination);
        fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
        fos.close();
        rbc.close();
    }
}
ZuulOKTravel/.mvn/wrapper/maven-wrapper.jar
Binary files differ
ZuulOKTravel/.mvn/wrapper/maven-wrapper.properties
New file
@@ -0,0 +1,2 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
ZuulOKTravel/mvnw
New file
@@ -0,0 +1,310 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#    https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven Start Up Batch script
#
# Required ENV vars:
# ------------------
#   JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
#   M2_HOME - location of maven2's installed home dir
#   MAVEN_OPTS - parameters passed to the Java VM when running Maven
#     e.g. to debug Maven itself, use
#       set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
#   MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
  if [ -f /etc/mavenrc ] ; then
    . /etc/mavenrc
  fi
  if [ -f "$HOME/.mavenrc" ] ; then
    . "$HOME/.mavenrc"
  fi
fi
# OS specific support.  $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "`uname`" in
  CYGWIN*) cygwin=true ;;
  MINGW*) mingw=true;;
  Darwin*) darwin=true
    # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
    # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
    if [ -z "$JAVA_HOME" ]; then
      if [ -x "/usr/libexec/java_home" ]; then
        export JAVA_HOME="`/usr/libexec/java_home`"
      else
        export JAVA_HOME="/Library/Java/Home"
      fi
    fi
    ;;
esac
if [ -z "$JAVA_HOME" ] ; then
  if [ -r /etc/gentoo-release ] ; then
    JAVA_HOME=`java-config --jre-home`
  fi
fi
if [ -z "$M2_HOME" ] ; then
  ## resolve links - $0 may be a link to maven's home
  PRG="$0"
  # need this for relative symlinks
  while [ -h "$PRG" ] ; do
    ls=`ls -ld "$PRG"`
    link=`expr "$ls" : '.*-> \(.*\)$'`
    if expr "$link" : '/.*' > /dev/null; then
      PRG="$link"
    else
      PRG="`dirname "$PRG"`/$link"
    fi
  done
  saveddir=`pwd`
  M2_HOME=`dirname "$PRG"`/..
  # make it fully qualified
  M2_HOME=`cd "$M2_HOME" && pwd`
  cd "$saveddir"
  # echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
  [ -n "$M2_HOME" ] &&
    M2_HOME=`cygpath --unix "$M2_HOME"`
  [ -n "$JAVA_HOME" ] &&
    JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
  [ -n "$CLASSPATH" ] &&
    CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
  [ -n "$M2_HOME" ] &&
    M2_HOME="`(cd "$M2_HOME"; pwd)`"
  [ -n "$JAVA_HOME" ] &&
    JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
fi
if [ -z "$JAVA_HOME" ]; then
  javaExecutable="`which javac`"
  if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
    # readlink(1) is not available as standard on Solaris 10.
    readLink=`which readlink`
    if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
      if $darwin ; then
        javaHome="`dirname \"$javaExecutable\"`"
        javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
      else
        javaExecutable="`readlink -f \"$javaExecutable\"`"
      fi
      javaHome="`dirname \"$javaExecutable\"`"
      javaHome=`expr "$javaHome" : '\(.*\)/bin'`
      JAVA_HOME="$javaHome"
      export JAVA_HOME
    fi
  fi
fi
if [ -z "$JAVACMD" ] ; then
  if [ -n "$JAVA_HOME"  ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
      # IBM's JDK on AIX uses strange locations for the executables
      JAVACMD="$JAVA_HOME/jre/sh/java"
    else
      JAVACMD="$JAVA_HOME/bin/java"
    fi
  else
    JAVACMD="`which java`"
  fi
fi
if [ ! -x "$JAVACMD" ] ; then
  echo "Error: JAVA_HOME is not defined correctly." >&2
  echo "  We cannot execute $JAVACMD" >&2
  exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
  echo "Warning: JAVA_HOME environment variable is not set."
fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
  if [ -z "$1" ]
  then
    echo "Path not specified to find_maven_basedir"
    return 1
  fi
  basedir="$1"
  wdir="$1"
  while [ "$wdir" != '/' ] ; do
    if [ -d "$wdir"/.mvn ] ; then
      basedir=$wdir
      break
    fi
    # workaround for JBEAP-8937 (on Solaris 10/Sparc)
    if [ -d "${wdir}" ]; then
      wdir=`cd "$wdir/.."; pwd`
    fi
    # end of workaround
  done
  echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
  if [ -f "$1" ]; then
    echo "$(tr -s '\n' ' ' < "$1")"
  fi
}
BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
  exit 1;
fi
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
    if [ "$MVNW_VERBOSE" = true ]; then
      echo "Found .mvn/wrapper/maven-wrapper.jar"
    fi
else
    if [ "$MVNW_VERBOSE" = true ]; then
      echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
    fi
    if [ -n "$MVNW_REPOURL" ]; then
      jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
    else
      jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
    fi
    while IFS="=" read key value; do
      case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
      esac
    done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
    if [ "$MVNW_VERBOSE" = true ]; then
      echo "Downloading from: $jarUrl"
    fi
    wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
    if $cygwin; then
      wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
    fi
    if command -v wget > /dev/null; then
        if [ "$MVNW_VERBOSE" = true ]; then
          echo "Found wget ... using wget"
        fi
        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
            wget "$jarUrl" -O "$wrapperJarPath"
        else
            wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
        fi
    elif command -v curl > /dev/null; then
        if [ "$MVNW_VERBOSE" = true ]; then
          echo "Found curl ... using curl"
        fi
        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
            curl -o "$wrapperJarPath" "$jarUrl" -f
        else
            curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
        fi
    else
        if [ "$MVNW_VERBOSE" = true ]; then
          echo "Falling back to using Java to download"
        fi
        javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
        # For Cygwin, switch paths to Windows format before running javac
        if $cygwin; then
          javaClass=`cygpath --path --windows "$javaClass"`
        fi
        if [ -e "$javaClass" ]; then
            if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
                if [ "$MVNW_VERBOSE" = true ]; then
                  echo " - Compiling MavenWrapperDownloader.java ..."
                fi
                # Compiling the Java class
                ("$JAVA_HOME/bin/javac" "$javaClass")
            fi
            if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
                # Running the downloader
                if [ "$MVNW_VERBOSE" = true ]; then
                  echo " - Running MavenWrapperDownloader.java ..."
                fi
                ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
            fi
        fi
    fi
fi
##########################################################################################
# End of extension
##########################################################################################
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
  echo $MAVEN_PROJECTBASEDIR
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
  [ -n "$M2_HOME" ] &&
    M2_HOME=`cygpath --path --windows "$M2_HOME"`
  [ -n "$JAVA_HOME" ] &&
    JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
  [ -n "$CLASSPATH" ] &&
    CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
  [ -n "$MAVEN_PROJECTBASEDIR" ] &&
    MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
  $MAVEN_OPTS \
  -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
  "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
ZuulOKTravel/mvnw.cmd
New file
@@ -0,0 +1,182 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements.  See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership.  The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License.  You may obtain a copy of the License at
@REM
@REM    https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied.  See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM     e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on"  echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
    IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
    if "%MVNW_VERBOSE%" == "true" (
        echo Found %WRAPPER_JAR%
    )
) else (
    if not "%MVNW_REPOURL%" == "" (
        SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
    )
    if "%MVNW_VERBOSE%" == "true" (
        echo Couldn't find %WRAPPER_JAR%, downloading it ...
        echo Downloading from: %DOWNLOAD_URL%
    )
    powershell -Command "&{"^
        "$webclient = new-object System.Net.WebClient;"^
        "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
        "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
        "}"^
        "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
        "}"
    if "%MVNW_VERBOSE%" == "true" (
        echo Finished downloading %WRAPPER_JAR%
    )
)
@REM End of extension
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%" == "on" pause
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
exit /B %ERROR_CODE%
ZuulOKTravel/pom.xml
New file
@@ -0,0 +1,105 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.sinata</groupId>
    <artifactId>zuul</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>zuul</name>
    <description>Zuul project for Spring Boot</description>
    <packaging>jar</packaging>
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.SR1</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-netflix-zuul</artifactId>
        </dependency>
        <!--引入swagger-->
        <dependency>
            <groupId>com.spring4all</groupId>
            <artifactId>swagger-spring-boot-starter</artifactId>
            <version>1.7.0.RELEASE</version>
        </dependency>
        <!-- jedis -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>
        <!--<dependency>-->
            <!--<groupId>org.springframework.boot</groupId>-->
            <!--<artifactId>spring-boot-starter-tomcat</artifactId>-->
            <!--<scope>provided</scope>-->
        <!--</dependency>-->
        <!--<dependency>-->
            <!--<groupId>javax.servlet</groupId>-->
            <!--<artifactId>javax.servlet-api</artifactId>-->
            <!--<version>3.1.0</version>-->
            <!--<scope>provided</scope>-->
        <!--</dependency>-->
        <!-- netty -->
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.27.Final</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </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>
</project>
ZuulOKTravel/src/main/java/com/sinata/zuul/ZuulApplication.java
New file
@@ -0,0 +1,121 @@
package com.sinata.zuul;
import com.sinata.zuul.util.applets.NettyServer0;
import com.sinata.zuul.util.echo.NettyServer;
import com.spring4all.swagger.EnableSwagger2Doc;
import org.apache.http.client.HttpClient;
import org.apache.http.config.SocketConfig;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
@EnableSwagger2Doc
@EnableZuulProxy//开启网关服务
@EnableDiscoveryClient//开启eureka客户端的消费者
@SpringBootApplication
public class ZuulApplication /*extends SpringBootServletInitializer*/ {
    public static void main(String[] args) {
        SpringApplication.run(ZuulApplication.class, args);
        NettyServer nettyServer = new NettyServer();
        nettyServer.bind();
        NettyServer0 nettyServer0 = new NettyServer0();
        nettyServer0.bind();
    }
    @Bean //SpringCloud内部服务质检使用服务名调用
    @LoadBalanced
    public RestTemplate internalRestTemplate() {
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
        connectionManager.setDefaultSocketConfig(SocketConfig.custom().setTcpNoDelay(true).build());
        connectionManager.setDefaultMaxPerRoute(100);//最大并发连接
        connectionManager.setMaxTotal(200); // 总的最大连接数
        HttpClient httpClient = HttpClientBuilder.create().setConnectionManager(connectionManager).build();
        HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
        httpRequestFactory.setConnectionRequestTimeout(30 * 1000);
        httpRequestFactory.setConnectTimeout(30 * 3000);
        httpRequestFactory.setReadTimeout(30 * 3000);
        RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        return restTemplate;
    }
//    /**
//     * 向Spring容器中定义RestTemplate对象
//     * @return
//     */
//    @Bean //必须new 一个RestTemplate并放入spring容器当中,否则启动时报错
//    public RestTemplate restTemplate() {
//        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
//        connectionManager.setDefaultSocketConfig(SocketConfig.custom().setTcpNoDelay(true).build());
//        connectionManager.setDefaultMaxPerRoute(100);//最大并发连接
//        connectionManager.setMaxTotal(200); // 总的最大连接数
//        HttpClient httpClient = HttpClientBuilder.create().setConnectionManager(connectionManager).build();
//        HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
//        httpRequestFactory.setConnectionRequestTimeout(30 * 1000);
//        httpRequestFactory.setConnectTimeout(30 * 3000);
//        httpRequestFactory.setReadTimeout(30 * 3000);
//        RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
//        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
//        return restTemplate;
//    }
    /**
     * 配置Swagger
     */
    @Component
    @Primary
    class DocumentationConfig implements SwaggerResourcesProvider {
        @Override
        public List<SwaggerResource> get() {
            List resource=new ArrayList<>();
            //name可以随便写,location前缀要与zuul配置的path一致。zuul开了token验证,要加上token,否则不用加?token=1
            resource.add(swaggerResource("user","/user-server/v2/api-docs","1.0"));
            resource.add(swaggerResource("driver","/driver-server/v2/api-docs","1.0"));
//            resource.add(swaggerResource("dispatch","/dispatch-server/v2/api-docs","1.0"));
            return resource;
        }
        //name可以随便写,location前缀要与zuul配置的path一致
        private SwaggerResource swaggerResource(String name, String location, String version){
            SwaggerResource swaggerResource=new SwaggerResource();
            swaggerResource.setName(name);
            swaggerResource.setLocation(location);
            swaggerResource.setSwaggerVersion(version);
            return swaggerResource;
        }
    }
//    @Override
//    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
//        return builder.sources(ZuulApplication.class);
//    }
}
ZuulOKTravel/src/main/java/com/sinata/zuul/config/RedisConfig.java
New file
@@ -0,0 +1,54 @@
package com.sinata.zuul.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
@Configuration
@PropertySource("classpath:redis.properties")
public class RedisConfig {
    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private int port;
    @Value("${spring.redis.timeout}")
    private int timeout;
    @Value("${spring.redis.jedis.pool.max-idle}")
    private int maxIdle;
    @Value("${spring.redis.jedis.pool.min-idle}")
    private int minIdle;
    @Value("${spring.redis.jedis.pool.max-wait}")
    private long maxWaitMillis;
    @Value("${spring.redis.jedis.pool.max-active}")
    private int maxTotal;
    @Value("${spring.redis.password}")
    private String password;
    @Value("${spring.redis.block-when-exhausted}")
    private boolean  blockWhenExhausted;
    @Bean
    public JedisPool redisPoolFactory()  throws Exception{
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(maxIdle);
        jedisPoolConfig.setMinIdle(minIdle);
        jedisPoolConfig.setMaxTotal(maxTotal);
        jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
        // 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true
        jedisPoolConfig.setBlockWhenExhausted(blockWhenExhausted);
        // 是否启用pool的jmx管理功能, 默认true
        jedisPoolConfig.setJmxEnabled(true);
        JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout, password);
        return jedisPool;
    }
}
ZuulOKTravel/src/main/java/com/sinata/zuul/controller/NettyController.java
New file
@@ -0,0 +1,54 @@
package com.sinata.zuul.controller;
import com.alibaba.fastjson.JSON;
import com.sinata.zuul.util.ResultUtil;
import com.sinata.zuul.util.applets.NettyWebSocketController;
import com.sinata.zuul.util.echo.NettyChannelMap;
import com.sinata.zuul.util.echo.NettyServerController;
import io.netty.channel.ChannelHandlerContext;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/netty")
public class NettyController {
    /**
     * 向客户端推送消息
     * @param id
     * @param msg
     */
    @ResponseBody
    @PostMapping("/sendMsgToClient")
    public String sendMsgToClient(Integer id, Integer type, String msg){
        if(type == 1){//用户端
            ChannelHandlerContext channel = NettyChannelMap.getData("Applets" + id);//小程序
            if(null != channel){
                NettyWebSocketController.sendMsgToClient(channel, msg);
                return JSON.toJSONString(ResultUtil.success());
            }
            channel = NettyChannelMap.getData("USER" + id);
            if(null != channel){
                NettyServerController.sendMsgToClient(channel, msg);
                return JSON.toJSONString(ResultUtil.success());
            }
            return JSON.toJSONString(ResultUtil.error("推送失败-----用户id=" + id));
        }
        if(type == 2){//司机端
            ChannelHandlerContext channel = NettyChannelMap.getData("DRIVER" + id);
            if(null != channel){
                NettyServerController.sendMsgToClient(channel, msg);
                return JSON.toJSONString(ResultUtil.success());
            }
            return JSON.toJSONString(ResultUtil.error("推送失败-----司机id=" + id));
        }
        return JSON.toJSONString(ResultUtil.error("推送失败"));
    }
}
ZuulOKTravel/src/main/java/com/sinata/zuul/controller/RedisController.java
New file
@@ -0,0 +1,83 @@
package com.sinata.zuul.controller;
import com.alibaba.fastjson.JSON;
import com.sinata.zuul.util.RedisUtil;
import com.sinata.zuul.util.ResultUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.Arrays;
import java.util.List;
@RestController
@RequestMapping("/redis")
public class RedisController {
    @Autowired
    private RedisUtil redisUtil;
    /**
     * 从redis中获取数据
     * @param key
     * @return
     */
    @ResponseBody
    @PostMapping("/getValue")
    public String getValue(String key){
        String value = redisUtil.getValue(key);
        return JSON.toJSONString(ResultUtil.success(value));
    }
    /**
     * 批量获取
     * @param keys
     * @return
     */
    @ResponseBody
    @PostMapping("/getValues")
    public String getValues(String keys){
        String[] split = keys.split(",");
        List<String> list = Arrays.asList(split);
        List<Object> values = redisUtil.getValues(list);
        return JSON.toJSONString(ResultUtil.success(values));
    }
    /**
     * 存值
     * @param key
     * @param value
     * @param time
     */
    @ResponseBody
    @PostMapping("/setValue")
    public String setValue(String key, String value, int time){
        redisUtil.setStrValue(key, value, time);
        return JSON.toJSONString(ResultUtil.success());
    }
    @ResponseBody
    @PostMapping("/setValue_")
    public String setValue_(String key, String value){
        redisUtil.setStrValue(key, value);
        return JSON.toJSONString(ResultUtil.success());
    }
    /**
     * 删除redis数据
     * @param key
     * @return
     */
    @ResponseBody
    @PostMapping("/remove")
    public String remove(String key){
        redisUtil.remove(key);
        return JSON.toJSONString(ResultUtil.success());
    }
}
ZuulOKTravel/src/main/java/com/sinata/zuul/util/CrossOriginFilter.java
New file
@@ -0,0 +1,54 @@
package com.sinata.zuul.util;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
 * 统一配置跨域处理
 */
@Order(-100)
@Component
@ServletComponentScan
@WebFilter(urlPatterns = "/*",filterName = "crossOriginFilter")
public class CrossOriginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        // 允许哪些Origin发起跨域请求
        // response.setHeader( "Access-Control-Allow-Origin", config.getInitParameter( "AccessControlAllowOrigin" ) );
        response.setHeader( "Access-Control-Allow-Origin", "*" );
        // 允许请求的方法
        response.setHeader( "Access-Control-Allow-Methods", "POST,GET,OPTIONS,DELETE,PUT" );
        //多少秒内,不需要再发送预检验请求,可以缓存该结果
        response.setHeader( "Access-Control-Max-Age", "3600" );
        // 表明它允许跨域请求包含xxx头
        response.setHeader( "Access-Control-Allow-Headers", "x-auth-token,Origin,Access-Token,X-Requested-With,Content-Type, Accept, Authorization" );
        //是否允许浏览器携带用户身份信息(cookie)
        response.setHeader( "Access-Control-Allow-Credentials", "true" );
        //prefight请求
        if (request.getMethod().equals( "OPTIONS" )) {
            response.setStatus( 204 );
            return;
        }
        filterChain.doFilter( servletRequest, response );
    }
    @Override
    public void destroy() {
    }
}
ZuulOKTravel/src/main/java/com/sinata/zuul/util/GDMapGeocodingUtil.java
New file
@@ -0,0 +1,102 @@
package com.sinata.zuul.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * 高德地图的地理编码工具类
 */
@Component
public class GDMapGeocodingUtil {
    private String key = "79293423abef825bf17db8568fa93d98";
    @Autowired
    private RestTemplate restTemplate;
    /**
     * 将行政区域名称转化为坐标
     * @param province
     * @param city
     * @param county
     * @param address
     * @return
     */
    public Map<String, Object> geocoding(String province, String city, String county, String address){
        Map<String, Object> map = new HashMap<>();
        if(StringUtil.isEmpty(province)){
            map.put("status", -1);
            map.put("data", "省不能为空");
            return map;
        }
        if((StringUtil.isEmpty(city) && StringUtil.isNotEmpty(county)) || (StringUtil.isEmpty(city) && StringUtil.isNotEmpty(address))){
            map.put("status", -1);
            map.put("data", "市不能为空");
            return map;
        }
        if((StringUtil.isEmpty(county) && StringUtil.isNotEmpty(address))){
            map.put("status", -1);
            map.put("data", "县/区不能为空");
            return map;
        }
        String url = "https://restapi.amap.com/v3/geocode/geo?key=" + key + "&output=JSON";
        url += "&address=" + province + (StringUtil.isNotEmpty(city) ? city : "") + (StringUtil.isNotEmpty(county) ? county : "") + (StringUtil.isNotEmpty(address) ? address : "");
        String forObject = restTemplate.getForObject(url, String.class);
        JSONObject jsonObject = JSON.parseObject(forObject);
        String status = jsonObject.getString("status");
        List<String> list = new ArrayList<>();
        if(status.equals("1")){
            JSONArray geocodes = jsonObject.getJSONArray("geocodes");
            for(int i = 0; i < geocodes.size(); i++){
                String location = geocodes.getJSONObject(i).getString("location");
                list.add(location);
            }
        }
        map.put("status", 0);
        map.put("data", list);
        return map;
    }
    /**
     * 根据经纬度获取行政区域信息
     * @param lon
     * @param lan
     * @return
     * @throws Exception
     */
    public Map<String, String> geocode(String lon, String lan) throws Exception{
        String url = "https://restapi.amap.com/v3/geocode/regeo?key=" + key + "&location=" + lon + "," + lan;
        String forObject = restTemplate.getForObject(url, String.class);
        JSONObject jsonObject = JSON.parseObject(forObject);
        Map<String, String> map = new HashMap<>();
        if(jsonObject.getString("status").equals("1")){
            JSONObject regeocode = jsonObject.getJSONObject("regeocode");
            JSONObject addressComponent = regeocode.getJSONObject("addressComponent");
            String address = regeocode.getString("formatted_address");
            map.put("address", address);
            String code = addressComponent.getString("adcode");
            String province = addressComponent.getString("province");
            String city = addressComponent.getString("city");
            String district = addressComponent.getString("district");
            map.put("province", province);
            map.put("provinceCode", code.substring(0, 2) + "0000");
            map.put("city", city);
            map.put("cityCode", code.substring(0, 4) + "00");
            map.put("district", district);
            map.put("districtCode", code);
        }
        return map;
    }
}
ZuulOKTravel/src/main/java/com/sinata/zuul/util/NettyStartListener.java
New file
@@ -0,0 +1,36 @@
package com.sinata.zuul.util;
import com.sinata.zuul.util.applets.NettyServer0;
import com.sinata.zuul.util.echo.NettyServer;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
/**
 * 启动netty监听器
 */
@WebListener
public class NettyStartListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
//                NettyServer nettyServer = new NettyServer();
//                nettyServer.bind();
//
//                NettyServer0 nettyServer0 = new NettyServer0();
//                nettyServer0.bind();
            }
        });
        thread.start();
    }
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
    }
}
ZuulOKTravel/src/main/java/com/sinata/zuul/util/RedisUtil.java
New file
@@ -0,0 +1,124 @@
package com.sinata.zuul.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Pipeline;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
 * Redis工具类
 */
@Component
public class RedisUtil {
    @Autowired
    private JedisPool jedisPool;
    /**
     * 向redis中存储字符串没有过期时间
     * @param key
     * @param value
     */
    public void setStrValue(String key, String value){
        if(StringUtil.isNotEmpty(key)){
            Jedis resource = jedisPool.getResource();
            String set = resource.set(key, value);
            closeJedis(resource);
        }
    }
    /**
     * 以分钟为单位设置存储值(设置过期时间)
     * @param key
     * @param value
     * @param time 秒
     */
    public void setStrValue(String key, String value, int time){
        if(StringUtil.isNotEmpty(key)){
            Jedis resource = jedisPool.getResource();
            String setex = resource.setex(key, time, value);
            closeJedis(resource);
        }
    }
    /**
     * 从redis中获取值
     * @param key
     * @return
     */
    public String getValue(String key){
        if(StringUtil.isNotEmpty(key)){
            Jedis resource = jedisPool.getResource();
            String data = resource.get(key);
            closeJedis(resource);
            return data;
        }
        return null;
    }
    /**
     * 批量获取
     * @param kes
     * @return
     */
    public List<Object> getValues(List<String> kes){
        if(null != kes){
            Jedis resource = jedisPool.getResource();
            Pipeline pipelined = resource.pipelined();
            for(String key : kes){
                pipelined.get(key);
            }
            List<Object> list = pipelined.syncAndReturnAll();
            closeJedis(resource);
            pipelined.clear();
            try {
                pipelined.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            List<Object> data = new ArrayList<>();
            for(Object o : list){
                if(null != o){
                    data.add(o);
                }
            }
            return data;
        }
        return null;
    }
    /**
     * 删除key
     * @param key
     */
    public void remove(String key){
        if(StringUtil.isNotEmpty(key)){
            Jedis resource = jedisPool.getResource();
            Long del = resource.del(key);
            closeJedis(resource);
        }
    }
    /**
     * 删除资源
     * @param jedis
     */
    public void closeJedis(Jedis jedis){
        if(null != jedis){
            jedis.close();
        }
    }
}
ZuulOKTravel/src/main/java/com/sinata/zuul/util/ResultUtil.java
New file
@@ -0,0 +1,188 @@
package com.sinata.zuul.util;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
 * 定义统一返回对象
 */
@ApiModel(value = "统一返回结果集")
public class ResultUtil<T> {
    public static final Integer SUCCESS = 200;
    public static final Integer PARAM_ERROR = 300;
    public static final Integer RUNTIME_ERROR = 400;
    public static final Integer ERROR = 500;
    public static final Integer TOKEN_ERROR = 600;
    public static final Integer SIGN_ERROR = 700;
    public static final String Token = "TOKEN_INVALID";
    public static final String SIGN = "SIGN_INVALID";
    @ApiModelProperty(name = "code", value = "业务状态码 200:成功,300:参数错误,400:运行异常,500:其他异常, 600:token无效,需重新登录,700:签名无效")
    private Integer code;//备用状态码
    @ApiModelProperty(name = "msg", value = "返回结果说明")
    private String msg;//返回说明
    @ApiModelProperty(name = "data", value = "返回结果值")
    private T data;//返回数据
    public String getMsg() {
        return msg;
    }
    public T getData() {
        return data;
    }
    public Integer getCode() {
        return code;
    }
    private ResultUtil(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }
    private ResultUtil(Integer code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }
    public static <T> ResultUtil<T> getResult(Integer code, String msg){
        return new ResultUtil<>(code, msg);
    }
    public static <T> ResultUtil<T> getResult(Integer code, String msg, T data){
        return new ResultUtil<>(code, msg, data);
    }
    /**
     * 错误信息
     * @return
     */
    public static ResultUtil error(String mag){
        return ResultUtil.getResult(ResultUtil.ERROR, mag, new JSONObject());
    }
    /**
     * 错误信息
     * @return
     */
    public static <T> ResultUtil <T> error(String mag, T obj){
        return ResultUtil.getResult(ResultUtil.ERROR, mag, obj);
    }
    /**
     * token失效
     * @return
     */
    public static ResultUtil tokenErr(){
        return ResultUtil.getResult(ResultUtil.TOKEN_ERROR, ResultUtil.Token, new JSONObject());
    }
    /**
     * token失效
     * @return
     */
    public static ResultUtil tokenErr(String msg){
        return ResultUtil.getResult(ResultUtil.TOKEN_ERROR, msg, new JSONObject());
    }
    /**
     * 参数异常
     * @return
     */
    public static  ResultUtil paranErr(){
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "PARAM_ERROR", new JSONObject());
    }
    /**
     * 参数异常
     * @return
     */
    public static <T> ResultUtil<T> paranErr(T data){
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "SYSTEM_RUN_ERROR", data);
    }
    /**
     * 运行异常
     * @return
     */
    public static ResultUtil runErr(){
        return ResultUtil.getResult(ResultUtil.RUNTIME_ERROR, "SYSTEM_RUN_ERROR", new JSONObject());
    }
    /**
     * 运行异常
     * @return
     */
    public static <T>ResultUtil<T> runErr(T data){
        return ResultUtil.getResult(ResultUtil.RUNTIME_ERROR, "SYSTEM_RUN_ERROR", data);
    }
    /**
     * 运行异常
     * @return
     */
    public static <T>ResultUtil<T> runErr(T data, String msg){
        return ResultUtil.getResult(ResultUtil.RUNTIME_ERROR, msg, data);
    }
    /**
     * 返回成功
     * @param
     * @return
     */
    public static ResultUtil success(){
        return ResultUtil.getResult(ResultUtil.SUCCESS, "SUCCESS", new JSONObject());
    }
    /**
     * 返回成功
     * @param data
     * @param <T>
     * @return
     */
    public static <T> ResultUtil<T> success(T data){
        return ResultUtil.getResult(ResultUtil.SUCCESS, "SUCCESS", data);
    }
    /**
     * 返回成功
     * @param msg
     * @param data
     * @param <T>
     * @return
     */
    public static <T> ResultUtil<T> success(String msg, T data){
        return ResultUtil.getResult(ResultUtil.SUCCESS, msg, data);
    }
    /**
     * 签名无效
     * @param <T>
     * @return
     */
    public static <T> ResultUtil<T> sign(){
        return ResultUtil.getResult(ResultUtil.SIGN_ERROR, SIGN);
    }
}
ZuulOKTravel/src/main/java/com/sinata/zuul/util/SinataUtil.java
New file
@@ -0,0 +1,405 @@
package com.sinata.zuul.util;
import java.io.UnsupportedEncodingException;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
 * 基本数据处理工具类
 */
public class SinataUtil {
    /**
     * List集合分页<br/>
     * 创建人:Mryang<br/>
     * 时间:2016年7月28日-下午2:58:14 <br/>
     * @param <T>
     * @param pageNo
     * @param pageSize
     * @param list
     * @throws Exception List<UserOrderList> <br/>
     */
    public static <T> List<T> listpage(int pageNo, int pageSize, List<T> list) throws Exception {
        List<T> result = new ArrayList<T>();
        if (list != null && list.size() > 0) {
            int allCount = list.size();
            if(pageNo > 1 && allCount < pageSize) {
                return new ArrayList<>();
            }
            int pageCount = (allCount + pageSize - 1) / pageSize;
            if (pageNo >= pageCount) {
                pageNo = pageCount;
            }
            int start = (pageNo - 1) * pageSize;
            int end = pageNo * pageSize;
            if (end >= allCount) {
                end = allCount;
            }
            for (int i = start; i < end; i++) {
                result.add(list.get(i));
            }
        }
        return (result != null && result.size() > 0) ? result : new ArrayList<T>();
    }
    /**
     * Double类型取整
     * @param num
     * @return
     */
    public static String doubleTrans(double num) {
        return String.valueOf((long) num);
    }
    /**
     * Double类型保留1位小数
     *
     * @param num
     * @return
     */
    public static String doubleRetainOne(double num) {
        DecimalFormat dfs = new DecimalFormat("0.0");
        return dfs.format(num);
    }
    /**
     * Double类型保留2位小数
     *
     * @param num
     * @return
     */
    public static String doubleRetainTwo(double num) {
        DecimalFormat dfs = new DecimalFormat("0.00");
        String.format("%.2f", num);
        return dfs.format(num);
    }
    /**
     * Double类型保留1位小数(四舍五入)
     *
     * @param num
     * @return
     */
    public static String doubleForwardOne(double num) {
        return String.format("%.1f", num);
    }
    /**
     * Double类型保留2位小数(四舍五入)
     *
     * @param num
     * @return
     */
    public static String doubleForwardTwo(double num) {
        return String.format("%.2f", num);
    }
    /**
     * 字符串转换成Ascii
     *
     * @param value
     * @return
     */
    public static String stringToAscii(String value) {
        StringBuffer sbu = new StringBuffer();
        char[] chars = value.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            if (i != chars.length - 1) {
                sbu.append((int) chars[i]);
            } else {
                sbu.append((int) chars[i]);
            }
        }
        return sbu.toString();
    }
    /**
     * 小数转换为百分比
     *
     * @param decimal
     * @return
     * @author TaoNingBo
     */
    public static String decTurnPercent(double decimal) {
        NumberFormat num = NumberFormat.getPercentInstance();
        num.setMaximumIntegerDigits(3);
        num.setMaximumFractionDigits(2);
        return num.format(decimal);
    }
    /**
     * Ascii转换成字符串
     *
     * @param value
     * @return
     */
    public static String asciiToString(String value) {
        String[] chars = value.split(",");
        StringBuffer sbu = new StringBuffer();
        for (int i = 0; i < chars.length; i++) {
            sbu.append((char) Integer.parseInt(chars[i]));
        }
        return sbu.toString();
    }
    /**
     * 字符串转换unicode
     *
     * @param string
     * @return
     * @author TaoNingBo
     */
    public static String string2Unicode(String string) {
        StringBuffer unicode = new StringBuffer();
        for (int i = 0; i < string.length(); i++) {
            // 取出每一个字符
            char c = string.charAt(i);
            // 转换为unicode
            unicode.append("\\u" + Integer.toHexString(c));
        }
        return unicode.toString();
    }
    /**
     * unicode 转字符串
     *
     * @param unicode
     * @return
     * @author TaoNingBo
     */
    public static String unicode2String(String unicode) {
        StringBuffer string = new StringBuffer();
        String[] hex = unicode.split("\\\\u");
        for (int i = 1; i < hex.length; i++) {
            // 转换出每一个代码点
            int data = Integer.parseInt(hex[i], 16);
            // 追加成string
            string.append((char) data);
        }
        return string.toString();
    }
    /**
     * 字符串编码转换的实现方法
     *
     * @param str
     *            待转换编码的字符串
     * @param newCharset
     *            目标编码
     * @return
     * @throws UnsupportedEncodingException
     */
    public static String changeCharset(String str, String newCharset) throws UnsupportedEncodingException {
        if (str != null) {
            // 用默认字符编码解码字符串。
            byte[] bs = str.getBytes();
            // 用新的字符编码生成字符串
            return new String(bs, newCharset);
        }
        return null;
    }
    /**
     * 注: \n 回车( ) \t 水平制表符( ) \s 空格(\u0008) \r 换行( )
     *
     * @param str
     * @return
     */
    public static String replaceBlank(String str) {
        String dest = "";
        if (str != null) {
            Pattern p = Pattern.compile("\\s*|\t|\r|\n");
            Matcher m = p.matcher(str);
            dest = m.replaceAll("");
        }
        return dest;
    }
    /**
     * 判断该字符串不能为空
     *
     * @param str
     * @return
     * @author TaoNingBo
     */
    public static boolean isNotEmpty(Object str) {
        return !isEmpty(str);
    }
    public static boolean isNotEmptyUndefined(Object str) {
        return !isEmpty(str) && !str.toString().equals("undefined");
    }
    /**
     * 字符串编码转换的实现方法
     *
     * @param str
     *            待转换编码的字符串
     * @param oldCharset
     *            原编码
     * @param newCharset
     *            目标编码
     * @return
     * @throws UnsupportedEncodingException
     */
    public static String changeCharset(String str, String oldCharset, String newCharset) throws UnsupportedEncodingException {
        if (str != null) {
            // 用旧的字符编码解码字符串。解码可能会出现异常。
            byte[] bs = str.getBytes(oldCharset);
            // 用新的字符编码生成字符串
            return new String(bs, newCharset);
        }
        return null;
    }
    /**
     * 给手机号码加分割符
     *
     * @param phone
     * @return
     * @author TaoNingBo
     */
    public static String splitPhone(String phone) {
        if (isNotEmpty(phone)) {
            String strone = phone.substring(0, 3);
            String strtwo = phone.substring(strone.length(), 7);
            String strthree = phone.substring(strtwo.length() + strone.length(), phone.length());
            return strone + "-" + strtwo + "-" + strthree;
        }
        return "";
    }
    /**
     * 非空判断
     *
     * @param str
     * @return
     * @author TaoNingBo
     */
    public static boolean isEmpty(Object str) {
        return str == null || str.toString().length() == 0 || str.equals("") || str.toString().matches("\\s*");
    }
    /**
     * 把米转换成公里
     *
     * @param km
     * @return
     * @author TaoNingBo
     */
    public static Double kmTransKilo(Integer m) {
        return Math.round(m / 100d) / 10d;
    }
    /**
     * 将List<{@link Object}>转换成List<{@link T}>
     *
     * @param list
     *            将要转换的对象
     * @param clazs
     *            需要转换的泛型对象
     * @return
     * @author TaoNingBo
     */
    @SuppressWarnings("unchecked")
    public static <T> List<T> fromToObject(List<?> list, Class<T> clazs) {
        List<T> t = new ArrayList<T>();
        for (Object object : list) {
            t.add((T) object);
        }
        return t;
    }
     /**
     * 生成 uuid, 即用来标识一笔单,也用做 nonce_str
     * @return
     */
    public static String generateUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
    }
    /**
     * 将List<{@link Object}>转换成List<{@link Map<String, Object>}>
     *
     * @param list
     * @return
     * @author TaoNingBo
     */
    @SuppressWarnings("unchecked")
    public static List<Map<String, Object>> fromToObject_M(List<?> list) {
        List<Map<String, Object>> t = new ArrayList<Map<String, Object>>();
        for (Object object : list) {
            t.add((Map<String, Object>) object);
        }
        return t;
    }
/**
 * 将对象中的null转换为空
 * @param obj
 * @return
 * @throws IllegalAccessException
 */
public static  Object checkObjFieldIsNull(Object obj) throws IllegalAccessException {
    if(obj!=null){
        for(java.lang.reflect.Field f : obj.getClass().getDeclaredFields()){
            f.setAccessible(true);
            if(f.get(obj) == null){
                if(f.getType()==String.class){
                    f.set(obj, "");
                }
                if(f.getType()==Double.class){
                    f.set(obj, 0d);
                }
                if(f.getType()==Integer.class){
                    f.set(obj, 0);
                }
                if(f.getType()==Date.class){
                    f.set(obj, new Date());
                }
            }
        }
        return obj;
    }
    return obj;
}
/**
 * 获取六位标识码
 * @param length
 * @return
 */
public static String createRandomCharData()
{
    StringBuilder sb=new StringBuilder();
    Random rand=new Random();//随机用以下三个随机生成器
    Random randdata=new Random();
    int data=0;
    for(int i=0;i<6;i++)
    {
        int index=rand.nextInt(3);
        //目的是随机选择生成数字,大小写字母
        switch(index)
        {
        case 0:
             data=randdata.nextInt(10);//仅仅会生成0~9
             sb.append(data);
            break;
        case 1:
            data=randdata.nextInt(26)+65;//保证只会产生65~90之间的整数
            sb.append((char)data);
            break;
        case 2:
            data=randdata.nextInt(26)+97;//保证只会产生97~122之间的整数
            sb.append((char)data);
            break;
        }
    }
    String result=sb.toString().toLowerCase();
    return result;
}
}
ZuulOKTravel/src/main/java/com/sinata/zuul/util/SpringUtil.java
New file
@@ -0,0 +1,34 @@
package com.sinata.zuul.util;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringUtil implements ApplicationContextAware {
    @Autowired
    private static ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContextParam) throws BeansException {
        applicationContext = applicationContextParam;
    }
    public static Object getObject(String id) {
        Object object = null;
        object = applicationContext.getBean(id);
        return object;
    }
    public static <T> T getObject(Class<T> tClass) {
        return applicationContext.getBean(tClass);
    }
    public static Object getBean(String tClass) {
        return applicationContext.getBean(tClass);
    }
    public <T> T getBean(Class<T> tClass) {
        return applicationContext.getBean(tClass);
    }
}
ZuulOKTravel/src/main/java/com/sinata/zuul/util/StringUtil.java
New file
@@ -0,0 +1,121 @@
package com.sinata.zuul.util;
import org.apache.commons.lang.StringUtils;
public class StringUtil {
    /**
     * 判断字符串中是否包含表情
     * @param source
     * @return
     */
    public static boolean containsEmoji(String source) {
        int len = 0;
        if(null != source){
            len = source.length();
        }
        boolean isEmoji = false;
        for (int i = 0; i < len; i++) {
            char hs = source.charAt(i);
            if (0xd800 <= hs && hs <= 0xdbff) {
                if (source.length() > 1) {
                    char ls = source.charAt(i + 1);
                    int uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;
                    if (0x1d000 <= uc && uc <= 0x1f77f) {
                        return true;
                    }
                }
            } else {
                // non surrogate
                if (0x2100 <= hs && hs <= 0x27ff && hs != 0x263b) {
                    return true;
                } else if (0x2B05 <= hs && hs <= 0x2b07) {
                    return true;
                } else if (0x2934 <= hs && hs <= 0x2935) {
                    return true;
                } else if (0x3297 <= hs && hs <= 0x3299) {
                    return true;
                } else if (hs == 0xa9 || hs == 0xae || hs == 0x303d
                        || hs == 0x3030 || hs == 0x2b55 || hs == 0x2b1c
                        || hs == 0x2b1b || hs == 0x2b50 || hs == 0x231a) {
                    return true;
                }
                if (!isEmoji && source.length() > 1 && i < source.length() - 1) {
                    char ls = source.charAt(i + 1);
                    if (ls == 0x20e3) {
                        return true;
                    }
                }
            }
        }
        return isEmoji;
    }
    /**
     * 判断某个字符是不是表情
     * @param codePoint
     * @return
     */
    private static boolean isEmojiCharacter(char codePoint) {
        return (codePoint == 0x0) || (codePoint == 0x9) || (codePoint == 0xA)
                || (codePoint == 0xD)
                || ((codePoint >= 0x20) && (codePoint <= 0xD7FF))
                || ((codePoint >= 0xE000) && (codePoint <= 0xFFFD))
                || ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF));
    }
    /**
     * 过滤掉字符串中的表情
     * @param source
     * @return
     */
    public static String filterEmoji(String source) {
        if (StringUtils.isBlank(source)) {
            return source;
        }
        StringBuilder buf = null;
        int len = source.length();
        for (int i = 0; i < len; i++) {
            char codePoint = source.charAt(i);
            if (isEmojiCharacter(codePoint)) {
                if (buf == null) {
                    buf = new StringBuilder(source.length());
                }
                buf.append(codePoint);
            }
        }
        if (buf == null) {
            return source;
        } else {
            if (buf.length() == len) {
                buf = null;
                return source;
            } else {
                return buf.toString();
            }
        }
    }
    /**
     * 判断字符串为空
     * @param value
     * @return
     */
    public static boolean isEmpty(String value){
        if(null == value || value.trim().equals("")){
            return true;
        }
        return false;
    }
    /**
     * 判断字符串非空
     * @param value
     * @return
     */
    public static boolean isNotEmpty(String value){
        return !isEmpty(value);
    }
}
ZuulOKTravel/src/main/java/com/sinata/zuul/util/applets/CacheType.java
New file
@@ -0,0 +1,86 @@
package com.sinata.zuul.util.applets;
/**
 * 缓存消息类型
 *
 * @author TaoNingBo
 * @data 2016年9月21日
 * @version 1.0
 */
public class CacheType {
    /**
     * 用户通讯通道标识
     */
    public static final String userCtx = "USER_CTX_";
    /**
     * 司机通讯通道标识
     */
    public static final String driverCtx = "DRIVER_CTX_";
    /**
     * 出行-快车/专车/代驾-订单消息队列-自营车辆
     */
    public static final String travelOrder1 = "TRAVEL_ORDER1_";
    /**
     * 出行-快车/专车/代驾-订单消息队列-外来车辆
     */
    public static final String travelOrder2 = "TRAVEL_ORDER2_";
    /**
     * 快车-司机位置-自营车辆
     */
    public static final String location1 = "_LOCATION1";
    /**
     * 快车-司机位置-外来车辆
     */
    public static final String location2 = "_LOCATION2";
    /**
     * 快车-司机抢单成功后的消息
     */
    public static final String travelOrder = "TRAVEL_ORDER_";
    /**
     * 开始服务时间
     */
    public static final String startServerT = "START_SERVER_TIME_";
    /**
     * 司机上一次的位置(经纬度)
     */
    public static final String location = "LAST_DRIVER_LOCATION_";
    /**
     * 司机上一次总共行驶距离
     */
    public static final String triverd = "LAST_TRIVER_Distance_";
    /**
     * 记录订单数据 司机 异常处理
     */
    public static final String dreco = "DRIVER_DATA_RECO";
    /**
     * 记录订单数据 用户  异常处理
     */
    public static final String ureco = "USER_DATA_RECO";
    /**
     * 记录司机跟用户的关系ID
     */
    public final static String udID = "USER_DRIVER_ID_";
    /**
     * 记录下单乘客的出发点位置坐标
     */
    public final static String userLoc = "USER_LOCATION_";
    /**
     * 记录计费规则【用订单号获取】
     */
    public final static String rules = "RULES_ORDER_";
}
ZuulOKTravel/src/main/java/com/sinata/zuul/util/applets/ChildChannelHandler.java
New file
@@ -0,0 +1,36 @@
package com.sinata.zuul.util.applets;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
public class ChildChannelHandler extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
//        String path = "C:\\Program Files\\Apache Software Foundation\\Tomcat 8.5\\cert\\SHA256withRSA_lzhyc.cn.pfx";
//        String path = "/usr/local/server/apache-tomcat-80/conf/cert/6064978_okyueche.com.pfx";
//        SSLContext sslContext = createSSLContext.createSSLContext("PKCS12"
//                , path, "lio03Bb9");
//        //SSLEngine 此类允许使用ssl安全套接层协议进行安全通信
//        SSLEngine engine = sslContext.createSSLEngine();
//        engine.setUseClientMode(false);
//        socketChannel.pipeline().addLast("ssl", new SslHandler(engine));
        // 设置30秒没有读到数据,则触发一个READER_IDLE事件。
        // pipeline.addLast(new IdleStateHandler(30, 0, 0));
        // HttpServerCodec:将请求和应答消息解码为HTTP消息
        socketChannel.pipeline().addLast("http-codec", new HttpServerCodec());
        // HttpObjectAggregator:将HTTP消息的多个部分合成一条完整的HTTP消息
        socketChannel.pipeline().addLast("aggregator", new HttpObjectAggregator(65536));
        // ChunkedWriteHandler:向客户端发送HTML5文件
        socketChannel.pipeline().addLast("http-chunked", new ChunkedWriteHandler());
        // 在管道中添加我们自己的接收数据实现方法
        socketChannel.pipeline().addLast("handler", new WebSocketHandler());
    }
}
ZuulOKTravel/src/main/java/com/sinata/zuul/util/applets/ClientPingMessage.java
New file
@@ -0,0 +1,59 @@
package com.sinata.zuul.util.applets;
import java.io.Serializable;
/**
 * 客户端心跳消息处理
 *
 * @author TaoNingBo
 * @data 2016年7月26日
 * @version 1.0
 */
public class ClientPingMessage implements Serializable {
    private static final long serialVersionUID = -4953410803742767757L;
    /**
     * 客户端标识ID
     */
    private Integer id;
    /**
     * 角色【0:用户,1:司机】
     */
    private Integer role;
    /**
     * 客户端单点登录标识TOKEN
     */
    private String token;
    public ClientPingMessage() {
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public Integer getRole() {
        return role;
    }
    public void setRole(Integer role) {
        this.role = role != null ? role : 0;
    }
    public String getToken() {
        return token;
    }
    public void setToken(String token) {
        this.token = token;
    }
}
ZuulOKTravel/src/main/java/com/sinata/zuul/util/applets/Global.java
New file
@@ -0,0 +1,9 @@
package com.sinata.zuul.util.applets;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
public class Global {
    public static ChannelGroup group = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
}
ZuulOKTravel/src/main/java/com/sinata/zuul/util/applets/NettyServer0.java
New file
@@ -0,0 +1,77 @@
package com.sinata.zuul.util.applets;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import java.util.Timer;
import java.util.TimerTask;
/**
 * 即时通讯服务启动类
 *
 * @date 2016年6月25日
 * @version 1.0
 */
public class NettyServer0 {
    /**
     * 延迟启动设置
     *
     * NettyServer启动方法.
     */
    public void bind() {
        final Thread thread = new Thread(new NettyRunnable());
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                thread.start();
            }
        }, 1000 * 2);
    }
    /**
     * 即时通讯服务启动
     *
     * @date 2016年6月24日
     * @version 1.0
     */
    public class NettyRunnable implements Runnable {
        /**
         * 获取即时通讯启动端口
         */
        @Override
        public void run() {
            System.out.println("===========================Netty端口启动========");
            // Boss线程:由这个线程池提供的线程是boss种类的,用于创建、连接、绑定socket,
            // (有点像门卫)然后把这些socket传给worker线程池。
            // 在服务器端每个监听的socket都有一个boss线程来处理。在客户端,只有一个boss线程来处理所有的socket。
            EventLoopGroup bossGroup = new NioEventLoopGroup();
            // Worker线程:Worker线程执行所有的异步I/O,即处理操作
            EventLoopGroup workrGroup = new NioEventLoopGroup();
            try {
                // ServerBootstrap 启动NIO服务的辅助启动类,负责初始话netty服务器,并且开始监听端口的socket请求
                ServerBootstrap b = new ServerBootstrap();
                b.group(bossGroup, workrGroup);
                // 设置非阻塞,用它来建立新accept的连接,用于构造serversocketchannel的工厂类
                b.channel(NioServerSocketChannel.class);
                // ChildChannelHandler 对出入的数据进行的业务操作,其继承ChannelInitializer
                b.childHandler(new ChildChannelHandler());
                System.out.println("服务端开启等待客户端连接 ... ...");
                Channel ch = b.bind(9090).sync().channel();
                ch.closeFuture().sync();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                bossGroup.shutdownGracefully();
                workrGroup.shutdownGracefully();
            }
        }
    }
}
ZuulOKTravel/src/main/java/com/sinata/zuul/util/applets/NettyWebSocketController.java
New file
@@ -0,0 +1,215 @@
package com.sinata.zuul.util.applets;
import com.alibaba.fastjson.JSONObject;
import com.sinata.zuul.util.RedisUtil;
import com.sinata.zuul.util.SinataUtil;
import com.sinata.zuul.util.SpringUtil;
import com.sinata.zuul.util.StringUtil;
import com.sinata.zuul.util.echo.Method;
import com.sinata.zuul.util.echo.NettyChannelMap;
import com.sinata.zuul.util.echo.NettyMsg;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Timer;
import java.util.TimerTask;
public class NettyWebSocketController {
    public static Hashtable<String, Hashtable<ChannelHandlerContext, String>> map = new Hashtable<String, Hashtable<ChannelHandlerContext, String>>();
    private RedisUtil redisUtil = SpringUtil.getObject(RedisUtil.class);
    public static Hashtable<String, String> table;
    static {
        if (table == null) {
            table = new Hashtable<>();
        }
    }
    public static boolean isdebug = false;
    public static int i = 0;
    /**
     * 判断客户端要执行什么操作
     *
     * @param ctx
     * @param msg
     * @author TaoNingBo
     */
    public void JudgeOperation(ChannelHandlerContext ctx, String msg) {
        try {
            // 验证即时通讯命令是否正确有效
            if (SinataUtil.isEmpty(msg)) {
                return;
            }
            String msgStr = msg.toString();
            if (msgStr.indexOf("{") == -1 || msgStr.indexOf("}") == -1 || msgStr.indexOf("code") == -1 || msgStr.indexOf("msg") == -1 || msgStr.indexOf("data") == -1 || msgStr.indexOf("method") == -1) {
                return;
            }
            if (isdebug) {
//            System.out.println("<<<--receive-->>>111" + msg);
            }
            // 获取socket信息,保存相应的socket
            JSONObject jsonMsg = JSONObject.parseObject(msg.toString());
            int code = jsonMsg.getIntValue("code");
            String message = jsonMsg.getString("msg");
            String method = jsonMsg.getString("method");
            if (code != 200 || !message.equals("SUCCESS")) {
                return;
            }
            JSONObject jsonCon = JSONObject.parseObject(jsonMsg.get("data").toString());
            if (null != ctx && ctx.channel().isActive()) {
                jsonMsg.put("method", Method.pong);
                sendMsgToClient(ctx, jsonMsg.toJSONString());
            }
            // ############################### 心跳  ############################
            // 心跳
            if (method.equals(Method.ping)) {
                String token = jsonCon.getString("token");
                String userId1 = jsonCon.getString("userId");
                if (StringUtil.isNotEmpty(userId1)) {
                    //确保账号在单个设备上登录
                    if (StringUtil.isNotEmpty(token)) {
                        String token_ = redisUtil.getValue("USER_Applets_" + userId1);//获取缓存中最新的数据
                        if (StringUtil.isNotEmpty(token_) && !token.equals(token_)) {//不在同一设备上登录,向其他设备发送数据
                            ChannelHandlerContext data_ = NettyChannelMap.getData_(token_.substring(0, 23));
                            JSONObject msg_ = new JSONObject();
                            msg_.put("code", 200);
                            msg_.put("msg", "SUCCESS");
                            msg_.put("method", "OFFLINE");
                            msg_.put("data", new Object());
                            this.sendMsgToClient(data_, msg_.toJSONString());//给当前通道发送消息
                            TimerTask timerTask = new TimerTask() {
                                @Override
                                public void run() {
                                    NettyChannelMap.remove_(data_);
                                    NettyChannelMap.remove(data_);
                                }
                            };
                            Timer timer = new Timer();
                            timer.schedule(timerTask, 3000);
                            timer.cancel();
                        }
                        NettyChannelMap.update_(token.substring(0, 23), ctx);
                        NettyChannelMap.update("Applets" + userId1, ctx);
                        String s = NettyMsg.setMsg(Method.ok, new HashMap<String, Object>());
                        ctx.writeAndFlush(Unpooled.copiedBuffer((s).getBytes()));
                        if (StringUtil.isEmpty(token_)) {//确保登录的时候存储token失败的情况
                            redisUtil.setStrValue("USER_Applets_" + userId1, token);
                        }
                    }
                    //存储业务使用的通道
                    if (null != ctx && ctx.channel().isActive()) {
                        NettyChannelMap.update("Applets" + userId1, ctx);
//                    String s = NettyMsg.setMsg(Method.ok, new HashMap<String, Object>());
//                    ctx.writeAndFlush(Unpooled.copiedBuffer((s).getBytes()));
                    }
                }
            }
        } catch (Exception e) {
            if (isdebug) {
                NettyWebSocketController.sendMsgToClient(ctx, "__error__" + msg.toString());
            }
            e.printStackTrace();
        }
    }
    /**
     * 向客户端发送消息
     *
     * @param ctx
     * @param msg
     * @author TaoNingBo
     */
    public static void sendMsgToClient(ChannelHandlerContext ctx, String msg) {
//        System.out.println(ctx.channel().isActive());
        if (ctx != null && ctx.channel().isActive()) {
            ByteBuf buffer = Unpooled.copiedBuffer((msg).getBytes());
            ChannelFuture sync;
            try {
                sync = ctx.channel().writeAndFlush(new TextWebSocketFrame(msg)).sync();
                if (!sync.isSuccess()) {
                    boolean b = true;
                    for (int i = 0; i < 10; i++) {
                        ctx.wait(3000);
                        sync = ctx.channel().write(new TextWebSocketFrame(msg)).sync();
                        if (sync.isSuccess()) {
                            b = false;
                            break;
                        }
                        System.err.println("小程序-》推送不成功,将继续推送" + msg);
                    }
                    if (b) {
                        NettyChannelMap.remove(ctx);
                    }
                }
            } catch (Exception e) {
                System.err.println("小程序-》推送发生异常,记录:" + msg);
                NettyChannelMap.remove(ctx);
            }
            if (isdebug) {
                System.err.println("小程序-》 <<<--send-->>>" + msg);
            }
        } else {
            System.err.println("小程序-》推送失败,长连接不存在");
            NettyChannelMap.remove(ctx);
        }
    }
    //    **链接断开 将推送消息记录
    public static void sendMsgToClient(String cacheType, Integer id, String msg) {
        ChannelHandlerContext ctx = NettyChannelMap.getData(cacheType + id);
        if (ctx != null) {
            ChannelFuture sync;
            try {
                sync = ctx.channel().write(new TextWebSocketFrame(msg)).sync();
                if (!sync.isSuccess()) {
                    for (int i = 0; i < 10; i++) {
                        sync = ctx.channel().write(new TextWebSocketFrame(msg)).sync();
                        ;
                        if (!sync.isSuccess()) {
                            sync = ctx.channel().write(new TextWebSocketFrame(msg)).sync();
                            ;
                            System.err.println("推送不成功,将继续推送" + msg);
                            if (i == 9) {
                                table.put(cacheType + id, msg);
                                ctx.close();
                                System.err.println("推送发生异常,记录:" + msg);
                            }
                        } else {
                            break;
                        }
                    }
                }
            } catch (Exception e) {
                table.put(cacheType + id, msg);
                System.err.println("推送发生异常,记录:" + msg);
            }
            if (isdebug) {
                System.err.println("<<<--send-->>>" + msg);
            }
        } else {
            table.put(cacheType + id, msg);
            System.err.println("链接断开,记录:id=" + cacheType + id + ",消息:" + msg);
        }
    }
}
ZuulOKTravel/src/main/java/com/sinata/zuul/util/applets/WebSocketHandler.java
New file
@@ -0,0 +1,180 @@
package com.sinata.zuul.util.applets;
import com.alibaba.fastjson.JSONObject;
import com.sinata.zuul.util.echo.Method;
import com.sinata.zuul.util.echo.NettyChannelMap;
import com.sinata.zuul.util.echo.NettyMsg;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.handler.codec.http.websocketx.*;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.CharsetUtil;
import java.util.HashMap;
public class WebSocketHandler extends SimpleChannelInboundHandler<Object> {
    //用于websocket握手的处理类
    private WebSocketServerHandshaker handshaker;
    private static final String WEB_SOCKET_URL = "wss://localhost:9090/websocket";
//   @Override
//    protected void messageReceived(ChannelHandlerContext ctx, Object msg) throws Exception {
//        if (msg instanceof FullHttpRequest) {
//            // websocket连接请求
//            handleHttpRequest(ctx, (FullHttpRequest)msg);
//        } else if (msg instanceof WebSocketFrame) {
//            // websocket业务处理
//            handleWebSocketRequest(ctx, (WebSocketFrame)msg);
//        }
//    }
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }
    /** 心跳 */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state().equals(IdleState.READER_IDLE))
            {
                //
            }
            else if (event.state().equals(IdleState.WRITER_IDLE))
            {
                //
            }
            else if (event.state().equals(IdleState.ALL_IDLE))
            {
                String msg = NettyMsg.setMsg(Method.ok, new HashMap<String, Object>());
                if(ctx != null && ctx.channel().isActive()) {
                    ctx.writeAndFlush(Unpooled.copiedBuffer((msg).getBytes()));
                }
            }
        }
//        super.userEventTriggered(ctx, evt);
    }
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
    }
    private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) {
        // Http解码失败,向服务器指定传输的协议为Upgrade:websocket
        if(!req.getDecoderResult().isSuccess() || !("websocket").equals(req.headers().get("Upgrade"))){
            sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST));
            return;
        }
        // 握手相应处理,创建websocket握手的工厂类,
        WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(WEB_SOCKET_URL, null, false);
        // 根据工厂类和HTTP请求创建握手类
        handshaker = wsFactory.newHandshaker(req);
        if (handshaker == null) {
            // 不支持websocket
            WebSocketServerHandshakerFactory.sendUnsupportedWebSocketVersionResponse(ctx.channel());
        } else {
            // 通过它构造握手响应消息返回给客户端
            handshaker.handshake(ctx.channel(), req);
        }
    }
    private void handleWebSocketRequest(ChannelHandlerContext ctx, WebSocketFrame req) throws Exception {
        if (req instanceof CloseWebSocketFrame) {
            // 关闭websocket连接
            handshaker.close(ctx.channel(), (CloseWebSocketFrame)req.retain());
            return;
        }
        if (req instanceof PingWebSocketFrame) {
            ctx.channel().write(new PongWebSocketFrame(req.content().retain()));
            return;
        }
        if (!(req instanceof TextWebSocketFrame)) {
            throw new UnsupportedOperationException("当前只支持文本消息,不支持二进制消息");
        }
        if (ctx == null || this.handshaker == null || ctx.isRemoved()) {
            throw new Exception("尚未握手成功,无法向客户端发送WebSocket消息");
        }
        String requestmsg = ((TextWebSocketFrame) req).text();
        //给连接的客户端返回数据
        //返回心跳
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", 200);
        jsonObject.put("method", Method.ok);
        jsonObject.put("msg", "SUCCESS");
        jsonObject.put("data", new JSONObject());
        TextWebSocketFrame tws = new TextWebSocketFrame(jsonObject.toJSONString());
//        ctx.channel().writeAndFlush(tws);
        new NettyWebSocketController().JudgeOperation(ctx,requestmsg);//小程序心跳处理
        // 群发服务端心跳响应
        Global.group.writeAndFlush(new TextWebSocketFrame((tws).text()));
    }
    private void sendHttpResponse(ChannelHandlerContext ctx, FullHttpRequest req, FullHttpResponse res) {
        // BAD_REQUEST(400) 客户端请求错误返回的应答消息
        if(res.getStatus().code() != 200){
            ByteBuf buf = Unpooled.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8);
            res.content().writeBytes(buf);
            buf.release();
        }
        //服务端向客户端发送数据
        ChannelFuture f = ctx.channel().writeAndFlush(res);
        // 非法连接直接关闭连接
        if(res.getStatus().code() != 200){
            f.addListener(ChannelFutureListener.CLOSE);
        }
    }
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        Global.group.add(ctx.channel());
        System.err.println("客户端与服务器端开启");
    }
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Global.group.remove(ctx.channel());
        NettyChannelMap.remove(ctx);
        System.err.println("客户端与服务器链接关闭");
    }
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof FullHttpRequest) {
            // websocket连接请求
            handleHttpRequest(ctx, (FullHttpRequest)msg);
        } else if (msg instanceof WebSocketFrame) {
            // websocket业务处理
            handleWebSocketRequest(ctx, (WebSocketFrame)msg);
        }
    }
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof FullHttpRequest) {
            // websocket连接请求
            handleHttpRequest(ctx, (FullHttpRequest)msg);
        } else if (msg instanceof WebSocketFrame) {
            // websocket业务处理
            handleWebSocketRequest(ctx, (WebSocketFrame)msg);
        }
    }
}
ZuulOKTravel/src/main/java/com/sinata/zuul/util/applets/createSSLContext.java
New file
@@ -0,0 +1,31 @@
package com.sinata.zuul.util.applets;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
public class createSSLContext {
    /**
     * 获取SSLContext
     * @param type
     * @param path
     * @param password
     * @return
     * @throws Exception
     */
    public static SSLContext createSSLContext(String type , String path , String password) throws Exception {
        KeyStore ks = KeyStore.getInstance(type); /// "JKS"
        InputStream ksInputStream = new FileInputStream(path); /// 证书存放地址
        ks.load(ksInputStream, password.toCharArray());
        //KeyManagerFactory充当基于密钥内容源的密钥管理器的工厂。
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());//getDefaultAlgorithm:获取默认的 KeyManagerFactory 算法名称。
        kmf.init(ks, password.toCharArray());
        //SSLContext的实例表示安全套接字协议的实现,它充当用于安全套接字工厂或 SSLEngine 的工厂。
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(kmf.getKeyManagers(), null, null);
        return sslContext;
    }
}
ZuulOKTravel/src/main/java/com/sinata/zuul/util/echo/DiscardServerHandler.java
New file
@@ -0,0 +1,153 @@
package com.sinata.zuul.util.echo;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.ReferenceCountUtil;
import java.net.InetSocketAddress;
import java.util.HashMap;
public class DiscardServerHandler extends SimpleChannelInboundHandler<String>  {
    private NettyServerController nettyServerController = new NettyServerController();
    public static boolean isdebug = true;
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
        if(isdebug) {
//            System.err.println(insocket.getAddress() + ": 收到客户端数据.......");
        }
        try {
            // 调用service
            nettyServerController.JudgeOperation(ctx, msg);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ReferenceCountUtil.release(msg);
        }
    }
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
        if(isdebug) {
//            System.err.println(insocket.getAddress() + ": 收到客户端数据.......");
        }
        try {
            // 调用service
            nettyServerController.JudgeOperation(ctx, msg);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ReferenceCountUtil.release(msg);
        }
    }
//    @Override
//    protected void messageReceived(ChannelHandlerContext channelHandlerContext, String s) throws Exception {
//
//    }
//    @Override
//    protected void channelRead0(ChannelHandlerContext channelHandlerContext, String s) throws Exception {
//
//    }
//    @Override
//    protected void messageReceived(ChannelHandlerContext channelHandlerContext, String s) throws Exception {
//
//    }
    /** 在连接被建立并且准备进行通信时被调用 */
    public void channelActive(final ChannelHandlerContext ctx) throws Exception {
        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
        if(isdebug) {
//            System.err.println(insocket.getAddress() + ": Connect successful......");
        }
    }
    /** 心跳 */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state().equals(IdleState.READER_IDLE))
            {
                //
            }
            else if (event.state().equals(IdleState.WRITER_IDLE))
            {
                //
            }
            else if (event.state().equals(IdleState.ALL_IDLE))
            {
                String msg = NettyMsg.setMsg(Method.ok, new HashMap<String, Object>());
                if(ctx != null && ctx.channel().isActive()) {
                    ctx.writeAndFlush(Unpooled.copiedBuffer((msg).getBytes()));
//                    System.err.println(msg);
                }
            }
        }
        //super.userEventTriggered(ctx, evt);
    }
    /** 连接处于不活跃时调用(连接关闭) **/
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        if(isdebug) {
            InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
//            System.err.println(insocket.getAddress() + ": Disconnect connection......");
        }
        NettyChannelMap.remove(ctx);
//        System.err.println("清除通道" + ctx);
//        super.channelInactive(ctx);
    }
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }
    /** 处理方法是当出现Throwable对象才会被调用 **/
    public void exceptionCaught(ChannelHandlerContext ctx,Throwable cause) throws Exception {
        ctx.close();
    }
    public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
        if(isdebug) {
            InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
//            System.err.println("close......." + insocket.getAddress());
        }
        ctx.close(promise);
    }
    public void read(ChannelHandlerContext ctx) throws Exception {
        ctx.read();
    }
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        ctx.write(msg, promise);
    }
//    @Override
//    protected void channelRead(ChannelHandlerContext ctx, String msg) throws Exception {
//        // TODO Auto-generated method stub
//        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
//        if(isdebug) {
//            System.out.println(insocket.getAddress() + ": 收到客户端数据.......");
//        }
//        try {
//            // 调用service
//            nettyServerController.JudgeOperation(ctx, msg);
//        } catch (Exception e) {
//            e.printStackTrace();
//        } finally {
//            ReferenceCountUtil.release(msg);
//        }
//    }
}
ZuulOKTravel/src/main/java/com/sinata/zuul/util/echo/Method.java
New file
@@ -0,0 +1,26 @@
package com.sinata.zuul.util.echo;
/**
 * 即时通讯【通讯类型类】
 *
 * @author TaoNingBo
 * @createDate 2016年6月14日
 * @version 1.0
 */
public class Method {
    /** 心跳【推送】 */
    public static final String ok = "OK";
    /** 心跳【接收】 */
    public final static String ping = "PING";
    /** 心跳【响应】 */
    public final static String pong = "PONG";
    /** 司机上传位置 */
    public static final String location = "LOCATION";
}
ZuulOKTravel/src/main/java/com/sinata/zuul/util/echo/NettyChannelMap.java
New file
@@ -0,0 +1,133 @@
package com.sinata.zuul.util.echo;
import io.netty.channel.ChannelHandlerContext;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
public class NettyChannelMap {
    protected static Map<String, ChannelHandlerContext> map = new ConcurrentHashMap<>();
    public static Map<String, ChannelHandlerContext> ctxMap = new HashMap<>();//单点登录存储的通道
    private NettyChannelMap() {
        // 放置外部实例化
    }
    /**
     * Get data from source.
     *
     * @param key
     * @return
     */
    public static ChannelHandlerContext getData(String key) {
        if(map==null){
            map = new HashMap<String, ChannelHandlerContext>();
        }
        return map.get(key);
    }
    public static ChannelHandlerContext getData_(String key) {
        if(ctxMap==null){
            ctxMap = new HashMap<String, ChannelHandlerContext>();
        }
        return ctxMap.get(key);
    }
    /**
     * Save data from source.
     *
     * @param key
     * @param val
     */
    public static synchronized void saveData(String key, ChannelHandlerContext val) {
        map.put(key, val);
    }
    /**
     * Determine whether the cache key contains the key.
     *
     * @param key
     * @return    true|false
     * @author TaoNingBo
     */
    public static synchronized boolean containsKey(String key) {
        return map.containsKey(key);
    }
    /**
     * Determine whether the cache value contains the value.
     *
     * @param val
     * @return
     */
    public static synchronized boolean containsVal(ChannelHandlerContext val) {
        return map.containsValue(val);
    }
    /**
     * Remove the data resources.
     *
     * @param value
     */
    @SuppressWarnings("rawtypes")
    public static synchronized void remove(ChannelHandlerContext value) {
        Set<String> strings = map.keySet();
        for(String key : strings){
            ChannelHandlerContext channelHandlerContext = map.get(key);
            String s = channelHandlerContext.channel().remoteAddress().toString();
            String s1 = value.channel().remoteAddress().toString();
            if(s.equals(s1)){
                channelHandlerContext.close();//关闭通道
                map.remove(key);
            }
        }
    }
    public static synchronized void remove_(ChannelHandlerContext value) {
        Set<String> strings = ctxMap.keySet();
        for(String key : strings){
            ChannelHandlerContext channelHandlerContext = ctxMap.get(key);
            String s = channelHandlerContext.channel().remoteAddress().toString();
            String s1 = value.channel().remoteAddress().toString();
            if(s.equals(s1)){
                channelHandlerContext.close();//关闭通道
                ctxMap.remove(key);
            }
        }
    }
    /**
     * Remove the data resources.
     *
     * @param key
     * @author TaoNingBo
     */
    public static synchronized void remove(String key) {
        map.remove(key);
    }
    /**
     * Update the data resources.
     *
     * @param key
     * @param value
     */
    public static synchronized void update(String key, ChannelHandlerContext value) {
        map.put(key, value);
    }
    public static synchronized void update_(String key, ChannelHandlerContext value) {
        ctxMap.put(key, value);
    }
}
ZuulOKTravel/src/main/java/com/sinata/zuul/util/echo/NettyMsg.java
New file
@@ -0,0 +1,165 @@
package com.sinata.zuul.util.echo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class NettyMsg {
    public static void main(String[] args) {
        Map<String,Object> map = new HashMap<String, Object>();
        //用户信息
        map.put("imgUrl","1");
        map.put("nickName","1");
        map.put("licensePlate","1");
        map.put("phone",1);
        map.put("driverId",1);
        map.put("carColor","1");
        map.put("modelName","1");
        map.put("brandName","1");
        map.put("driverOrderNums",1);
        map.put("score",1);
        map.put("id",1);
        map.put("orderNum", "123456");
        map.put("startAddress", "测试");
        map.put("endAddress", "测试1");
        map.put("departureTime", 1533608196000L);
        map.put("type",1);
        map.put("mileage",1);
        map.put("mileageMoney",10);
        map.put("duration",10);
        map.put("durationMoney",10);
        map.put("nightMoney",1);
        map.put("serverMoney",1);
        map.put("nightMileage",10);
        map.put("longMileage",10);
        map.put("longDurationMoney",10);
        map.put("orderMoney",10);
        map.put("payMoney",10);
        map.put("couponsMoney",10);
        System.out.println(setMsg(Method.ping, new HashMap<String, Object>()));
    }
    /**
     * 返回一个正确数据
     *
     * @param method
     * @param data
     * @return
     * @author TaoNingBo
     */
    public static String setMsg(String method, Map<String, Object> data) {
        StringBuffer json = new StringBuffer();
        json.append(getHeader(200, "SUCCESS", method));
        json.append(JSON.toJSONString(data));
        json.append("}");
        //return JSON.toJSONString(json);
        return json.toString();
    }
    /**
     * 返回一个正确数据
     *
     * @param method
     * @param data
     * @return
     */
    public static String setMsg(String method, List<Map<String, Object>> data) {
        StringBuffer json = new StringBuffer();
        json.append(getHeader(200, "SUCCESS", method));
        List<JSONObject> jsonList = new ArrayList<JSONObject>();
        for(Map<String, Object> map : data) {
            JSONObject dataJson = new JSONObject(map);
            jsonList.add(dataJson);
        }
        json.append(jsonList);
        json.append("}");
//        return JSON.toJSONString(json);
        return json.toString();
    }
    /**
     * 返回一个错误数据
     *
     * @param method
     * @param data
     * @return
     * @author TaoNingBo
     */
    public static String setErrMsg(String method, String data) {
        StringBuffer json = new StringBuffer();
        json.append(getHeader(-1, "FAILURE", method));
        json.append("\"" + data + "\"");
        json.append("}");
//        return JSON.toJSONString(json);
        return json.toString();
    }
    /**
     * 生成一个返回JSON的头
     *
     * @param code
     * @param msg
     * @param method
     * @return
     * @author TaoNingBo
     */
    private static String getHeader(int code, String msg, String method) {
        StringBuffer header = new StringBuffer();
        header.append("{");
        header.append("\"code\":\"" + code);
        header.append("\",\"msg\":\"" + msg);
        header.append("\",\"method\":\"" + method);
        header.append("\",\"data\":");
        return header.toString();
    }
    /**
     * 发送消息给客户端
     *
     * @param cacheType
     * @param id
     * @param method
     * @param data
     * @author TaoNingBo
     */
    public static void sendMsg(String cacheType, Integer id, String method, Map<String, Object> data) {
        //NettyServerController.sendMsgToClient(NettyChannelMap.getData(cacheType + id), setMsg(method, data));
        NettyServerController.sendMsgToClient(cacheType,id, setMsg(method, data));
    }
    public static void resendMsg(String token){
        String msg = NettyServerController.table.get(token);
        ChannelHandlerContext ctx = NettyChannelMap.getData(token);
        if(null != msg && !"".equals(msg) && ctx != null && ctx.channel().isActive()){
            ByteBuf buffer = Unpooled.copiedBuffer((msg).getBytes());
            ChannelFuture sync;
            try {
                sync = ctx.writeAndFlush(buffer).sync();
                System.err.println("重发异常推送状态"+sync.isSuccess()+",位置:"+token+",消息内容:"+msg);
                if(!sync.isSuccess()){
                    resendMsg(token);
                    System.err.println("重发异常推送不成功,将继续推送"+msg);
                }
                NettyServerController.table.remove(token);
            } catch (Exception e) {
                resendMsg(token);
                System.err.println("重发推送发生异常,记录:"+msg);
            }
        }
    }
}
ZuulOKTravel/src/main/java/com/sinata/zuul/util/echo/NettyServer.java
New file
@@ -0,0 +1,95 @@
package com.sinata.zuul.util.echo;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.timeout.IdleStateHandler;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
/**
 * 即时通讯服务启动类
 *
 * @date 2016年6月25日
 * @version 1.0
 */
public class NettyServer {
    /**
     * NettyServer启动方法.
     */
    public void bind() {
        final Thread thread = new Thread(new NettyRunnable());
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                thread.start();
            }
        }, 10000);
    }
    /**
     * 即时通讯服务启动
     *
     * @date 2016年6月24日
     * @version 1.0
     */
    public class NettyRunnable implements Runnable {
        /**
         * 获取即时通讯启动端口
         */
        private Integer nettyPort = 8888;
        @Override
        public void run() {
            EventLoopGroup bossGroup = new NioEventLoopGroup();
            EventLoopGroup workerGroup = new NioEventLoopGroup();
            try {
                ServerBootstrap bootstrap = new ServerBootstrap();
                bootstrap.group(bossGroup, workerGroup);
                bootstrap.channel(NioServerSocketChannel.class);
                bootstrap.option(ChannelOption.SO_BACKLOG, 1024);
                // 通过TCP_NODELAY禁用NAGLE,使消息立即发出去,不用等待到一定的数据量才发出去
                bootstrap.option(ChannelOption.TCP_NODELAY, true);
                // 保持长连接状态
                bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
                bootstrap.childHandler(new ServerInit() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        ChannelPipeline pipeline = socketChannel.pipeline();
                        pipeline.addLast("ping", new IdleStateHandler(120, 60, 5, TimeUnit.SECONDS));
                        pipeline.addLast("decoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
                        pipeline.addLast("encoder", new LengthFieldPrepender(4));
                        //pipeline.addLast(new LineBasedFrameDecoder(1048576 * 10));
                        //pipeline.addLast(new StringDecoder(Charset.forName("UTF-8")));
                        //pipeline.addLast(new StringEncoder(Charset.forName("UTF-8")));
                        pipeline.addLast(new DiscardServerHandler());
                    }
                });
                // 服务器绑定端口监听
                ChannelFuture f = bootstrap.bind(nettyPort).sync();
                if(f.isSuccess()) {
                    System.out.println("******************************Netty启动成功******************************");
                }
                // 监听服务器关闭监听
                f.channel().closeFuture().sync();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                bossGroup.shutdownGracefully();
                workerGroup.shutdownGracefully();
            }
        }
    }
}
ZuulOKTravel/src/main/java/com/sinata/zuul/util/echo/NettyServerController.java
New file
@@ -0,0 +1,400 @@
package com.sinata.zuul.util.echo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sinata.zuul.util.*;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.util.*;
/**
 * Netty业务逻辑层
 * @author sinata
 * @createDate 2016年6月3日
 * @version 1.0
 */
public class NettyServerController {
    public static Hashtable<String, Hashtable<ChannelHandlerContext, String>> map = new Hashtable<String, Hashtable<ChannelHandlerContext,String>>();
    public static Hashtable<String,String> table;
    private RedisUtil redisUtil = SpringUtil.getObject(RedisUtil.class);
    private GDMapGeocodingUtil gdMapGeocodingUtil = SpringUtil.getObject(GDMapGeocodingUtil.class);
    private RestTemplate internalRestTemplate = SpringUtil.getObject(RestTemplate.class);
    static{
        if(table == null){
            table = new Hashtable<>();
        }
    }
    public static boolean isdebug = false;
    public static int i = 0;
    /**
     * 判断客户端要执行什么操作
     *
     * @param ctx
     * @param msg
     * @author TaoNingBo
     */
    public void JudgeOperation(ChannelHandlerContext ctx, Object msg) {
        try {
            // ByteBuf转String
            ByteBuf byteBuf = (ByteBuf) msg;
            byte[] req = new byte[byteBuf.readableBytes()];
            byteBuf.readBytes(req);
            msg = new String(req, "UTF-8");
            // 验证即时通讯命令是否正确有效
            if(SinataUtil.isEmpty(msg)) {
                return;
            }
            String msgStr = msg.toString();
            if(msgStr.indexOf("{") == -1 || msgStr.indexOf("}") == -1 || msgStr.indexOf("code") == -1 || msgStr.indexOf("msg") == -1 || msgStr.indexOf("data") == -1 || msgStr.indexOf("method") == -1) {
                return;
            }
            if(isdebug) {
//                System.out.println("<<<--receive-->>>" + msg);
            }
            // 获取socket信息,保存相应的socket
            JSONObject jsonMsg = JSONObject.parseObject(msg.toString());
            int code = jsonMsg.getInteger("code");
            String message = jsonMsg.getString("msg");
            String method = jsonMsg.getString("method");
            if(code != 200 || !message.equals("SUCCESS")) {
                return;
            }
            JSONObject jsonCon = JSONObject.parseObject(jsonMsg.get("data").toString());
            if(null != ctx && ctx.channel().isActive()){
                jsonMsg.put("method", Method.pong);
                sendMsgToClient(ctx, jsonMsg.toJSONString());
            }
            //心跳
            if(method.equals(Method.ping)) {
                Integer type = jsonCon.getInteger("type");
                String token = jsonCon.getString("token");
                String userId1 = jsonCon.getString("userId");
                String device = jsonCon.getString("device");
                String version = jsonCon.getString("version");
                if(StringUtil.isNotEmpty(userId1)){
                    //判断用户或者司机长连接
                    if(type==1){
                        //确保账号在单个设备上登录
                        if(StringUtil.isNotEmpty(token)){
                            String token_ = redisUtil.getValue("USER_APP_"+ userId1);//获取缓存中最新的数据
                            if(StringUtil.isNotEmpty(token_) && !token.equals(token_)){//不在同一设备上登录,向其他设备发送数据
                                ChannelHandlerContext data_ = NettyChannelMap.getData_(token_.substring(0, 23));
                                JSONObject msg_ = new JSONObject();
                                msg_.put("code", 200);
                                msg_.put("msg", "SUCCESS");
                                msg_.put("method", "OFFLINE");
                                msg_.put("data", new Object());
                                this.sendMsgToClient(data_, msg_.toJSONString());//给当前通道发送消息
                                TimerTask timerTask = new TimerTask() {
                                    @Override
                                    public void run() {
                                        NettyChannelMap.remove_(data_);
                                        NettyChannelMap.remove(data_);
                                    }
                                };
                                Timer timer = new Timer();
                                timer.schedule(timerTask, 3000);
                                timer.cancel();
                            }
                            NettyChannelMap.update_(token.substring(0, 23), ctx);
                            NettyChannelMap.update("USER" + userId1, ctx);
                            String s = NettyMsg.setMsg(Method.ok, new HashMap<String, Object>());
                            ctx.writeAndFlush(Unpooled.copiedBuffer((s).getBytes()));
                            if(StringUtil.isEmpty(token_)){//确保登录的时候存储token失败的情况
                                redisUtil.setStrValue("USER_APP_" + userId1, token);
                            }
                        }
                    }else{
                        //添加司机在线
                        HttpHeaders headers = new HttpHeaders();
                        // 以表单的方式提交
                        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
                        //将请求头部和参数合成一个请求
                        MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
                        params.add("driverId", userId1);
                        params.add("device", (null != device && device.equals("carDevice")) ? "2" : "1");
                        params.add("version", version);
                        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, headers);
                        String w = internalRestTemplate.postForObject("http://driver-server/base/driverOnline/addDriverOnline",requestEntity , String.class);
                        JSONObject jsonObject = JSON.parseObject(w, JSONObject.class);
                        if(jsonObject.getIntValue("code") != 200){
                            System.err.println("调用driver-server添加司机在线数据出错了");
                        }
                        //TODO 存储最后一次上传的时间(用于保证车载端断电后1小时自动下班)
                        if(StringUtil.isNotEmpty(device) && device.equals("carDevice")){
                            redisUtil.setStrValue("DEVICE_" + userId1, String.valueOf(System.currentTimeMillis()));
                            String token_ = redisUtil.getValue("DRIVER_" + userId1);//缓存中拿最新数据
                            if(StringUtil.isNotEmpty(token_) && !token_.equals(token)){
                                ChannelHandlerContext data_ = NettyChannelMap.getData_(token_.substring(0, 23));
                                //如果是车载端登录,则将其它端都强迫下线
                                JSONObject msg_ = new JSONObject();
                                msg_.put("code", 200);
                                msg_.put("msg", "SUCCESS");
                                msg_.put("method", "OFFLINE");
                                msg_.put("data", new Object());
                                this.sendMsgToClient(data_, msg_.toJSONString());//给当前通道发送消息
                                TimerTask timerTask = new TimerTask() {
                                    @Override
                                    public void run() {
                                        NettyChannelMap.remove_(data_);
                                        NettyChannelMap.remove(data_);
                                    }
                                };
                                Timer timer = new Timer();
                                timer.schedule(timerTask, 3000);
                                timer.cancel();
                            }
                            NettyChannelMap.update("DRIVER" + userId1, ctx);
                            NettyChannelMap.update_(token.substring(0, 23), ctx);
                            String s = NettyMsg.setMsg(Method.ok, new HashMap<String, Object>());
                            ctx.writeAndFlush(Unpooled.copiedBuffer((s).getBytes()));
                            if(StringUtil.isEmpty(token_)){//确保登录的时候存储token失败的情况
                                redisUtil.setStrValue("DRIVER_" + userId1, token);
                            }
                        }
                        //确保账号在单个设备上登录
                        String value = redisUtil.getValue("DEVICE_" + userId1);
                        if(StringUtil.isNotEmpty(token) && StringUtil.isEmpty(device) && StringUtil.isEmpty(value)){//APP端登录的操作
                            String token_ = redisUtil.getValue("DRIVER_" + userId1);//缓存中拿最新数据
                            if(StringUtil.isNotEmpty(token_) && !token.equals(token_)){//不在同一设备上登录,向当前设备发送数据
                                ChannelHandlerContext data_ = NettyChannelMap.getData_(token_.substring(0, 23));
                                JSONObject msg_ = new JSONObject();
                                msg_.put("code", 200);
                                msg_.put("msg", "SUCCESS");
                                msg_.put("method", "OFFLINE");
                                msg_.put("data", new Object());
                                this.sendMsgToClient(data_, msg_.toJSONString());//给当前通道发送消息
                                TimerTask timerTask = new TimerTask() {
                                    @Override
                                    public void run() {
                                        NettyChannelMap.remove_(data_);
                                        NettyChannelMap.remove(data_);
                                    }
                                };
                                Timer timer = new Timer();
                                timer.schedule(timerTask, 3000);
                                timer.cancel();
                            }
                            NettyChannelMap.update("DRIVER" + userId1, ctx);
                            NettyChannelMap.update_(token.substring(0, 23), ctx);
                            String s = NettyMsg.setMsg(Method.ok, new HashMap<String, Object>());
                            ctx.writeAndFlush(Unpooled.copiedBuffer((s).getBytes()));
                            if(StringUtil.isEmpty(token_)){//确保登录的时候存储token失败的情况
                                redisUtil.setStrValue("DRIVER_" + userId1, token);
                            }
                        }
                        //存储通讯通道
                        if(null != ctx && ctx.channel().isActive()){
//                            System.err.println("开始存储司机通道" + userId1);
                            NettyChannelMap.update("DRIVER" + userId1, ctx);
                            String s = NettyMsg.setMsg(Method.ok, new HashMap<String, Object>());
                            ctx.writeAndFlush(Unpooled.copiedBuffer((s).getBytes()));
                        }
                    }
                }
            }
            //司机上传位置
            if(method.equals(Method.location)){
                Integer driverId = jsonCon.getInteger("driverId");
                Integer orderId = jsonCon.getInteger("orderId");
                Integer orderType = jsonCon.getInteger("orderType");
                Double lon = jsonCon.getDouble("lon");
                Double lat = jsonCon.getDouble("lat");
                Double computeAzimuth = jsonCon.getDouble("computeAzimuth");
                Double altitude = jsonCon.getDouble("altitude");
                if(SinataUtil.isNotEmpty(driverId)){
                    if(null !=  lon && 0 != lon && null !=  lat && 0 != lat){
                        if(null != orderId && 0 != driverId && null != orderType && 0 != orderType){//开始存入数据库
                            HttpHeaders headers = new HttpHeaders();
                            // 以表单的方式提交
                            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
                            //将请求头部和参数合成一个请求
                            MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
                            params.add("orderType", String.valueOf(orderType));
                            params.add("orderId", String.valueOf(orderId));
                            params.add("driverId", String.valueOf(driverId));
                            params.add("lon", String.valueOf(lon));
                            params.add("lat", String.valueOf(lat));
                            params.add("directionAngle", String.valueOf(computeAzimuth));
                            params.add("altitude", String.valueOf(altitude));
                            HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, headers);
                            String s = internalRestTemplate.postForObject("http://driver-server/base/savePosition",requestEntity , String.class);
                            JSONObject jsonObject = JSON.parseObject(s, JSONObject.class);
                            if(jsonObject.getIntValue("code") != 200){
                                System.err.println("调用driver-server存储位置数据出错了");
                            }
                        }
                        redisUtil.setStrValue("DRIVER" + driverId, lon + "," + lat, 300);//实时位置存入redis中
                    }else{
                        NettyServerController.sendMsgToClient(ctx, "__error__" + msg.toString());
                    }
                }else{
                    NettyServerController.sendMsgToClient(ctx, "__error__" + msg.toString());
                }
            }
        } catch (Exception e) {
            if(isdebug) {
                NettyServerController.sendMsgToClient(ctx, "__error__" + msg.toString());
            }
            e.printStackTrace();
        }
    }
    /**
     * 向客户端发送消息
     *
     * @param ctx
     * @param msg
     * @author TaoNingBo
     */
    public static void sendMsgToClient(ChannelHandlerContext ctx, String msg) {
        if (ctx != null && ctx.channel().isActive()) {
            ByteBuf buffer = Unpooled.copiedBuffer((msg).getBytes());
            ChannelFuture sync;
            try {
                sync = ctx.writeAndFlush(buffer).sync();
                if(!sync.isSuccess()){//如果推送失败则继续推送10次
                    boolean b = true;
                    for (int i = 0; i < 10; i++) {
                        ctx.wait(3000);
                        sync = ctx.writeAndFlush(buffer).sync();
                        if(sync.isSuccess()){
                            b = false;
                            break;
                        }
                        System.err.println("推送不成功,将继续推送"+msg);
                    }
                    if(b){
                        NettyChannelMap.remove(ctx);
                    }
                }
            } catch (Exception e) {
                System.err.println("推送发生异常,记录:"+msg);
                NettyChannelMap.remove(ctx);
            }
            if(isdebug) {
                System.err.println("<<<--send-->>>" + msg) ;
            }
        }else{
            System.err.println("推送失败,长连接不存在");
            NettyChannelMap.remove(ctx);
        }
    }
//    **链接断开 将推送消息记录
    public static void sendMsgToClient(String cacheType, Integer id,String msg) {
        ChannelHandlerContext ctx = NettyChannelMap.getData(cacheType + id);
        if (ctx != null) {
            ByteBuf buffer = Unpooled.copiedBuffer((msg).getBytes());
            ChannelFuture sync;
            try {
                sync = ctx.writeAndFlush(buffer).sync();
//                System.out.println("推送状态"+sync.isSuccess());
                if(!sync.isSuccess()){
                    for (int i = 0; i < 10; i++) {
                        sync = ctx.writeAndFlush(buffer).sync();
                        if(!sync.isSuccess()){
                            sync = ctx.writeAndFlush(buffer).sync();
                            System.err.println("推送不成功,将继续推送"+msg);
                            if(i == 9){
                                table.put(cacheType+id, msg);
                                ctx.close();
                                System.err.println("推送发生异常,记录:"+msg);
                            }
                        }else{
                            break;
                        }
                    }
                }
            } catch (Exception e) {
                table.put(cacheType+id, msg);
                System.err.println("推送发生异常,记录:"+msg);
            }
            if(isdebug) {
//                System.out.println("<<<--send-->>>" + msg);
            }
        }else{
            table.put(cacheType+id, msg);
            System.err.println("链接断开,记录:id="+cacheType+id+",消息:"+msg);
        }
    }
    /**
     * 记录推送不成功消息,并在心跳连接续推
     * @param token
     */
    public static void resendMsg(String token){
        String msg = table.get(token);
        ChannelHandlerContext ctx = NettyChannelMap.getData(token);
        if(SinataUtil.isNotEmpty(msg) && ctx != null && ctx.channel().isActive()){
            ByteBuf buffer = Unpooled.copiedBuffer((msg).getBytes());
            ChannelFuture sync;
            try {
                sync = ctx.writeAndFlush(buffer).sync();
                System.err.println("重发异常推送状态"+sync.isSuccess()+",位置:"+token+",消息内容:"+msg);
                if(!sync.isSuccess()){
                    i++;
                    if(i == 10){
                        i =0;
                        ctx.close();
                        return;
                    }
                    System.err.println("重发异常推送不成功,将继续推送"+msg);
                    resendMsg(token);
                }else{
                    i=0;
                }
                table.remove(token);
            } catch (Exception e) {
                resendMsg(token);
                System.err.println("重发推送发生异常,记录:"+msg);
            }
        }
    }
}
ZuulOKTravel/src/main/java/com/sinata/zuul/util/echo/ServerInit.java
New file
@@ -0,0 +1,25 @@
package com.sinata.zuul.util.echo;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import java.nio.charset.Charset;
public class ServerInit extends ChannelInitializer<SocketChannel> {
    private DiscardServerHandler discardServerHandler = new DiscardServerHandler();
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addLast(new StringDecoder(Charset.forName("utf-8")));
        pipeline.addLast(new StringEncoder(Charset.forName("utf-8")));
        // 心跳监测机制
//            pipeline.addLast(new IdleStateHandler(5,7,10, TimeUnit.SECONDS));
        pipeline.addLast(discardServerHandler);
    }
}
ZuulOKTravel/src/main/resources/application.yml
New file
@@ -0,0 +1,39 @@
server:
  port: 80
spring:
  application:
    name: zuul-gateway #服务名称
eureka:
  client:
    service-url: #注册中心地址
      defaultZone: http://sinata:sinata@127.0.0.1:8000/eureka #启用身份验证的方式连接
    register-with-eureka: true #在注册中心进行注册
    fetch-registry: true #从Eureka中获取注册信息。
zuul:
#  prefix: /api #添加URL前缀
  sensitive-headers: #将默认过滤掉的敏感数据清除,不进行过滤("Cookie", "Set-Cookie", "Authorization")
  routes:
    user-server: #接口调用路由服务,名字任意取。(用户端服务)
      path: /user/** #配置请求URL的请求规则
      url: http://127.0.0.1:8006 #真正的微服务地址,path匹配的请求都转发到这里
      service-id: user-server #指定Eureka注册中心的服务id
    driver-server: #路由司机相关请求
      path: /driver/** #配置请求URL的请求规则
      url: http://127.0.0.1:8007 #真正的微服务地址,path匹配的请求都转发到这里
      service-id: driver-server #指定Eureka注册中心的服务id
    dispatch-server: #路由调度相关请求
      path: /dispatch/** #配置请求URL的请求规则
      url: http://127.0.0.1:8008 #真正的微服务地址,path匹配的请求都转发到这里
      service-id: dispatch-server #指定Eureka注册中心的服务id
  #  配置zuul超时时间
  host:
    connect-timeout-millis: 150000
    socket-timeout-millis: 15000
# 配置ribbon超时时间
ribbon:
  ReadTimeout: 10000
  ConnectTimeout: 10000
ZuulOKTravel/src/main/resources/redis.properties
New file
@@ -0,0 +1,23 @@
#redisÅäÖÿªÊ¼
# RedisÊý¾Ý¿âË÷Òý£¨Ä¬ÈÏΪ0£©
spring.redis.database=0
# Redis·þÎñÆ÷µØÖ·
spring.redis.host=127.0.0.1
# Redis·þÎñÆ÷Á¬½Ó¶Ë¿Ú
#spring.redis.port=16379
spring.redis.port=6379
# Redis·þÎñÆ÷Á¬½ÓÃÜÂ루ĬÈÏΪ¿Õ£©
#spring.redis.password=mPMHThYzlT8DWgl8HLqwPEyPOiHDPPB5
spring.redis.password=123456
# Á¬½Ó³Ø×î´óÁ¬½ÓÊý£¨Ê¹ÓøºÖµ±íʾûÓÐÏÞÖÆ£©
spring.redis.jedis.pool.max-active=1024
# Á¬½Ó³Ø×î´ó×èÈûµÈ´ýʱ¼ä£¨Ê¹ÓøºÖµ±íʾûÓÐÏÞÖÆ£©
spring.redis.jedis.pool.max-wait=10000
# Á¬½Ó³ØÖеÄ×î´ó¿ÕÏÐÁ¬½Ó
spring.redis.jedis.pool.max-idle=200
# Á¬½Ó³ØÖеÄ×îС¿ÕÏÐÁ¬½Ó
spring.redis.jedis.pool.min-idle=50
# Á¬½Ó³¬Ê±Ê±¼ä£¨ºÁÃ룩
spring.redis.timeout=10000
#redisÅäÖýáÊø
spring.redis.block-when-exhausted=true
ZuulOKTravel/src/main/resources/static/tXQaRbVjpJ.txt
New file
@@ -0,0 +1 @@
0ef42640d32181b65822b974b89492d4