diff --git a/01jvm/Hello.java b/01jvm/Hello.java new file mode 100644 index 00000000..e7d787f2 --- /dev/null +++ b/01jvm/Hello.java @@ -0,0 +1,17 @@ +public class Hello { + public static void main(String[] args) { + int num1 = 1; // 字面量1; + double num2 = 2.0D; // 大小写的D都可以 + long num3 = 3L; // 大小写的L都可以, 加L是好习惯; + byte num4 = 4; // 可以直接赋予 [-128, 127] 范围内的字面量; + if ("".length() < 10) { + // 错误用法: num2 + num3 = 2.03 + System.out.println("错误用法: num2 + num3 = " + num2 + num3); + } + for (int i = 0; i < num1; i++) { + // 四则运算: num1 * num4 = 4 + System.out.print("四则运算: num1 * num4 = "); + System.out.println(num1 * num4); + } + } +} diff --git a/01jvm/JvmClassLoaderPrintPath.java b/01jvm/JvmClassLoaderPrintPath.java new file mode 100644 index 00000000..5ff32757 --- /dev/null +++ b/01jvm/JvmClassLoaderPrintPath.java @@ -0,0 +1,62 @@ +import java.lang.reflect.Field; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.List; + +public class JvmClassLoaderPrintPath { + + public static void main(String[] args) { + + // 启动类加载器 + URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs(); + System.out.println("启动类加载器"); + for (URL url : urls) { + System.out.println(" ===> " + url.toExternalForm()); + } + + // 扩展类加载器 + printClassloader("扩展类加载器",JvmClassLoaderPrintPath.class.getClassLoader().getParent()); + + // 应用类加载器 + printClassloader("应用类加载器",JvmClassLoaderPrintPath.class.getClassLoader()); + + } + + private static void printClassloader(String name, ClassLoader classLoader) { + System.out.println(); + if (null != classLoader) { + System.out.println(name + " Classloader -> " + classLoader.toString()); + printURLForClassloader(classLoader); + } else { + System.out.println(name + " Classloader -> null"); + } + } + + private static void printURLForClassloader(ClassLoader classLoader) { + Object ucp = insightField(classLoader,"ucp"); + Object path = insightField(ucp,"path"); + List paths = (List) path; + for (Object p : paths) { + System.out.println(" ===> " + p.toString()); + } + } + + private static Object insightField(Object obj, String fName) { + Field f = null; + try { + if (obj instanceof URLClassLoader) { + f = URLClassLoader.class.getDeclaredField(fName); + } else { + f = obj.getClass().getDeclaredField(fName); + } + f.setAccessible(true); + return f.get(obj); + } + catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + +} diff --git a/01jvm/README.md b/01jvm/README.md index d74bbed1..f9021845 100644 --- a/01jvm/README.md +++ b/01jvm/README.md @@ -6,7 +6,7 @@ ## 作业内容 -> Week01 作业题目(周四): +> Week01 作业题目: 1.(选做)自己写一个简单的 Hello.java,里面需要涉及基本类型,四则运行,if 和 for,然后自己分析一下对应的字节码,有问题群里讨论。 @@ -18,24 +18,102 @@ 注意:如果没有线上系统,可以自己 run 一个 web/java 项目。 -> Week01 作业题目(周六): +5.(选做)本机使用 G1 GC 启动一个程序,仿照课上案例分析一下 JVM 情况。 -1.(选做)本机使用 G1 GC 启动一个程序,仿照课上案例分析一下 JVM 情况。 ## 操作步骤 -### 作业2 +### 作业1(选做) + +1. 编写代码, 根据自己的意愿随意编写, 可参考: [Hello.java](./Hello.java) +2. 编译代码, 执行命令: `javac -g Hello.java` +3. 查看反编译的代码。 + - 3.1 可以安装并使用idea的jclasslib插件, 选中 [Hello.java](./Hello.java) 文件, 选择 `View --> Show Bytecode With jclasslib` 即可。 + - 3.2 或者直接通过命令行工具 javap, 执行命令: `javap -v Hello.class` +4. 分析相关的字节码。【此步骤需要各位同学自己进行分析】 + + +### 作业2(必做) 1. 打开 Spring 官网: https://spring.io/ 2. 找到 Projects --> Spring Initializr: https://start.spring.io/ 3. 填写项目信息, 生成 maven 项目; 下载并解压。 4. Idea或者Eclipse从已有的Source导入Maven项目。 -5. 增加课程资源 Hello.xlass 文件到 src/main/resources 目录。 -6. 编写代码,实现 findClass 方法,解码方法 +5. 从课件资料中找到资源 Hello.xlass 文件并复制到 src/main/resources 目录。 +6. 编写代码,实现 findClass 方法,以及对应的解码方法 7. 编写main方法,调用 loadClass 方法; 8. 创建实例,以及调用方法 9. 执行. -具体的参见: [https://github.com/renfufei/JAVA-000/blob/main/Week_01/homework01/src/main/java/com/renfufei/homework01/XlassLoader.java](XlassLoader.java) +具体代码可参考: [XlassLoader.java](./XlassLoader.java) + + +### 作业3(必做) + +对应的图片需要各位同学自己绘制,可以部分参考PPT课件。 + +提示: + +- Xms 设置堆内存的初始值 +- Xmx 设置堆内存的最大值 +- Xmn 设置堆内存中的年轻代的最大值 +- Meta 区不属于堆内存, 归属为非堆 +- DirectMemory 直接内存, 属于 JVM 内存中开辟出来的本地内存空间。 +- Xss设置的是单个线程栈的最大空间; + +JVM进程空间中的内存一般来说包括以下这些部分: + +- 堆内存(Xms ~ Xmx) = 年轻代(~Xmn) + 老年代 +- 非堆 = Meta + CodeCache + ... +- Native内存 = 直接内存 + Native + ... +- 栈内存 = n * Xss + +另外,注意区分规范与实现的区别, 需要根据具体实现以及版本, 才能确定。 一般来说,我们的目的是为了排查故障和诊断问题,大致弄清楚这些参数和空间的关系即可。 具体设置时还需要留一些冗余量。 + + +### 4.(选做) + +这个是具体案例分析, 请各位同学自己分析。 + +比如我们一个生产系统应用的启动参数为: + +``` +JAVA_OPTS=-Xmx200g -Xms200g -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -XX:ZCollectionInterval=30 -XX:ZAllocationSpikeTolerance=5 -XX:ReservedCodeCacheSize=2g -XX:InitialCodeCacheSize=2g -XX:ConcGCThreads=8 -XX:ParallelGCThreads=16 +``` + +另一个系统的启动参数为: + +``` +JAVA_OPTS=-Xmx4g -Xms4g -XX:+UseG1GC -XX:MaxGCPauseMillis=50 +``` + +具体如何设置, 需要考虑的因素包括: + +- 系统容量: 业务规模, 并发, 成本预算; 需要兼顾性能与成本; +- 延迟要求: 最坏情况下能接受多少时间的延迟尖刺。 +- 吞吐量: 根据业务特征来确定, 比如, 网关, 大数据底层平台, 批处理作业系统, 在线实时应用, 他们最重要的需求不一样。 +- 系统架构: 比如拆分为小内存更多节点, 还是大内存少量节点。 +- 其他... + + +### 5.(选做) + +例如使用以下命令: + +``` +# 编译 +javac -g GCLogAnalysis.java +# JDK8 启动程序 +java -Xmx2g -Xms2g -XX:+UseG1GC -verbose:gc -XX:+PrintGCDateStamps -XX:+PrintGCDetails -Xloggc:gc.log GCLogAnalysis +``` + +尝试使用课程中介绍的各种工具JDK命令行和图形工具来进行分析。 + +其中 [GCLogAnalysis.java](./GCLogAnalysis.java) 文件也可以从课件资料zip中找到. + +## 更多资料 + +更多中英文的技术文章和参考资料: + diff --git a/01jvm/TestAddUrl.java b/01jvm/TestAddUrl.java new file mode 100644 index 00000000..9d1b9de6 --- /dev/null +++ b/01jvm/TestAddUrl.java @@ -0,0 +1,22 @@ + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +public class TestAddUrl { + + public static void main(String[] args) throws Exception { + URLClassLoader classLoader = (URLClassLoader) TestAddUrl.class.getClassLoader(); + String dir = "/Users/kimmking/Downloads/Hello"; + Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); + method.setAccessible(true); + method.invoke(classLoader, new File(dir).toURL()); + + Class klass = Class.forName("Hello",true, classLoader); + Object obj = klass.newInstance(); + Method hello = klass.getDeclaredMethod("hello"); + hello.invoke(obj); + } + +} diff --git a/01jvm/XlassLoader.java b/01jvm/XlassLoader.java new file mode 100644 index 00000000..f4f19fbc --- /dev/null +++ b/01jvm/XlassLoader.java @@ -0,0 +1,74 @@ +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Method; + +/* + 第一周作业: + 2.(必做)自定义一个 Classloader,加载一个 Hello.xlass 文件,执行 hello 方法,此文件内容是一个 Hello.class 文件所有字节(x=255-x)处理后的文件。文件群里提供。 + */ +public class XlassLoader extends ClassLoader { + + public static void main(String[] args) throws Exception { + // 相关参数 + final String className = "Hello"; + final String methodName = "hello"; + // 创建类加载器 + ClassLoader classLoader = new XlassLoader(); + // 加载相应的类 + Class clazz = classLoader.loadClass(className); + // 看看里面有些什么方法 + for (Method m : clazz.getDeclaredMethods()) { + System.out.println(clazz.getSimpleName() + "." + m.getName()); + } + // 创建对象 + Object instance = clazz.getDeclaredConstructor().newInstance(); + // 调用实例方法 + Method method = clazz.getMethod(methodName); + method.invoke(instance); + } + + @Override + protected Class findClass(String name) throws ClassNotFoundException { + // 如果支持包名, 则需要进行路径转换 + String resourcePath = name.replace(".", "/"); + // 文件后缀 + final String suffix = ".xlass"; + // 获取输入流 + InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(resourcePath + suffix); + try { + // 读取数据 + int length = inputStream.available(); + byte[] byteArray = new byte[length]; + inputStream.read(byteArray); + // 转换 + byte[] classBytes = decode(byteArray); + // 通知底层定义这个类 + return defineClass(name, classBytes, 0, classBytes.length); + } catch (IOException e) { + throw new ClassNotFoundException(name, e); + } finally { + close(inputStream); + } + } + + // 解码 + private static byte[] decode(byte[] byteArray) { + byte[] targetArray = new byte[byteArray.length]; + for (int i = 0; i < byteArray.length; i++) { + targetArray[i] = (byte) (255 - byteArray[i]); + } + return targetArray; + } + + // 关闭 + private static void close(Closeable res) { + if (null != res) { + try { + res.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } +} diff --git a/01jvm/java11/.gitignore b/01jvm/java11/.gitignore new file mode 100644 index 00000000..549e00a2 --- /dev/null +++ b/01jvm/java11/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### 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/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/01jvm/java11/.mvn/wrapper/MavenWrapperDownloader.java b/01jvm/java11/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 00000000..a45eb6ba --- /dev/null +++ b/01jvm/java11/.mvn/wrapper/MavenWrapperDownloader.java @@ -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(); + } + +} diff --git a/01jvm/java11/.mvn/wrapper/maven-wrapper.jar b/01jvm/java11/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 00000000..2cc7d4a5 Binary files /dev/null and b/01jvm/java11/.mvn/wrapper/maven-wrapper.jar differ diff --git a/01jvm/java11/.mvn/wrapper/maven-wrapper.properties b/01jvm/java11/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 00000000..642d572c --- /dev/null +++ b/01jvm/java11/.mvn/wrapper/maven-wrapper.properties @@ -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 diff --git a/01jvm/java11/mvnw b/01jvm/java11/mvnw new file mode 100755 index 00000000..a16b5431 --- /dev/null +++ b/01jvm/java11/mvnw @@ -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 "$@" diff --git a/01jvm/java11/mvnw.cmd b/01jvm/java11/mvnw.cmd new file mode 100644 index 00000000..c8d43372 --- /dev/null +++ b/01jvm/java11/mvnw.cmd @@ -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% diff --git a/01jvm/java11/pom.xml b/01jvm/java11/pom.xml new file mode 100644 index 00000000..eb1d5df3 --- /dev/null +++ b/01jvm/java11/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.4.4 + + + com.example + demo + 0.0.1-SNAPSHOT + demo + Demo project for Spring Boot + + 11 + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/01jvm/java11/src/main/java/com/example/demo/DemoApplication.java b/01jvm/java11/src/main/java/com/example/demo/DemoApplication.java new file mode 100644 index 00000000..af9fd1da --- /dev/null +++ b/01jvm/java11/src/main/java/com/example/demo/DemoApplication.java @@ -0,0 +1,26 @@ +package com.example.demo; + +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DemoApplication implements ApplicationRunner { + + public static void main(String[] args) { + SpringApplication.run(DemoApplication.class, args); + } + + @Override + public void run(ApplicationArguments args) throws Exception { + + ClassLoader app = this.getClass().getClassLoader(); + System.out.println(" APP Classloader => " + app.getName()); + for (Package definedPackage : app.getDefinedPackages()) { + System.out.println(definedPackage.getName()); + } + + + } +} diff --git a/01jvm/java11/src/main/resources/application.properties b/01jvm/java11/src/main/resources/application.properties new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/01jvm/java11/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/01jvm/java11/src/test/java/com/example/demo/DemoApplicationTests.java b/01jvm/java11/src/test/java/com/example/demo/DemoApplicationTests.java new file mode 100644 index 00000000..eaa99696 --- /dev/null +++ b/01jvm/java11/src/test/java/com/example/demo/DemoApplicationTests.java @@ -0,0 +1,13 @@ +package com.example.demo; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class DemoApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/01jvm/jvm/HelloClassLoader.java b/01jvm/jvm/HelloClassLoader.java new file mode 100644 index 00000000..c465f987 --- /dev/null +++ b/01jvm/jvm/HelloClassLoader.java @@ -0,0 +1,21 @@ +package jvm; + +import java.util.Base64; + +public class HelloClassLoader extends ClassLoader { + + public static void main(String[] args) throws Exception { + new HelloClassLoader().findClass("jvm.Hello").newInstance(); + } + + @Override + protected Class findClass(String name) throws ClassNotFoundException { + String helloBase64 = "yv66vgAAADQAHAoABgAOCQAPABAIABEKABIAEwcAFAcAFQEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAAg8Y2xpbml0PgEAClNvdXJjZUZpbGUBAApIZWxsby5qYXZhDAAHAAgHABYMABcAGAEAGEhlbGxvIENsYXNzIEluaXRpYWxpemVkIQcAGQwAGgAbAQAJanZtL0hlbGxvAQAQamF2YS9sYW5nL09iamVjdAEAEGphdmEvbGFuZy9TeXN0ZW0BAANvdXQBABVMamF2YS9pby9QcmludFN0cmVhbTsBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAFShMamF2YS9sYW5nL1N0cmluZzspVgAhAAUABgAAAAAAAgABAAcACAABAAkAAAAdAAEAAQAAAAUqtwABsQAAAAEACgAAAAYAAQAAAAMACAALAAgAAQAJAAAAJQACAAAAAAAJsgACEgO2AASxAAAAAQAKAAAACgACAAAABQAIAAYAAQAMAAAAAgAN"; + byte[] bytes = decode(helloBase64); + return defineClass(name,bytes,0,bytes.length); + } + + public byte[] decode(String base64) { + return Base64.getDecoder().decode(base64); + } +} diff --git a/01jvm/jvm/TestMem.java b/01jvm/jvm/TestMem.java new file mode 100644 index 00000000..cb915121 --- /dev/null +++ b/01jvm/jvm/TestMem.java @@ -0,0 +1,11 @@ +package jvm; + +public class TestMem { + public static void main(String[] args) { + int[] arr1 = new int[256]; + int[][] arr2 = new int[128][2]; + int[][][] arr3 = new int[64][2][2]; + + System.out.println(); + } +} diff --git a/01jvm/out/production/01jvm/README.md b/01jvm/out/production/01jvm/README.md new file mode 100644 index 00000000..d74bbed1 --- /dev/null +++ b/01jvm/out/production/01jvm/README.md @@ -0,0 +1,41 @@ +# 第1周作业 + + +参见 我的教室 -> 本周作业 + +## 作业内容 + + +> Week01 作业题目(周四): + +1.(选做)自己写一个简单的 Hello.java,里面需要涉及基本类型,四则运行,if 和 for,然后自己分析一下对应的字节码,有问题群里讨论。 + +2.(必做)自定义一个 Classloader,加载一个 Hello.xlass 文件,执行 hello 方法,此文件内容是一个 Hello.class 文件所有字节(x=255-x)处理后的文件。文件群里提供。 + +3.(必做)画一张图,展示 Xmx、Xms、Xmn、Meta、DirectMemory、Xss 这些内存参数的关系。 + +4.(选做)检查一下自己维护的业务系统的 JVM 参数配置,用 jstat 和 jstack、jmap 查看一下详情,并且自己独立分析一下大概情况,思考有没有不合理的地方,如何改进。 + +注意:如果没有线上系统,可以自己 run 一个 web/java 项目。 + +> Week01 作业题目(周六): + +1.(选做)本机使用 G1 GC 启动一个程序,仿照课上案例分析一下 JVM 情况。 + + +## 操作步骤 + + +### 作业2 + +1. 打开 Spring 官网: https://spring.io/ +2. 找到 Projects --> Spring Initializr: https://start.spring.io/ +3. 填写项目信息, 生成 maven 项目; 下载并解压。 +4. Idea或者Eclipse从已有的Source导入Maven项目。 +5. 增加课程资源 Hello.xlass 文件到 src/main/resources 目录。 +6. 编写代码,实现 findClass 方法,解码方法 +7. 编写main方法,调用 loadClass 方法; +8. 创建实例,以及调用方法 +9. 执行. + +具体的参见: [https://github.com/renfufei/JAVA-000/blob/main/Week_01/homework01/src/main/java/com/renfufei/homework01/XlassLoader.java](XlassLoader.java) diff --git "a/01jvm/out/production/01jvm/\347\216\257\345\242\203\345\207\206\345\244\207.txt" "b/01jvm/out/production/01jvm/\347\216\257\345\242\203\345\207\206\345\244\207.txt" new file mode 100644 index 00000000..a1458b85 --- /dev/null +++ "b/01jvm/out/production/01jvm/\347\216\257\345\242\203\345\207\206\345\244\207.txt" @@ -0,0 +1,38 @@ + + +## Windows + +1.管理员身份打开powershell + +2.运行 +Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) + +3.执行choco install superbenchmarker + +4.输入 sb + +执行 sb -u http://localhost:8088/api/hello -c 20 -N 60 + +## Mac + +1.执行brew install wrk +如果显式brew update很慢,可以ctrl+C打断更新 + +2.输入 wrk + +执行 wrk -t8 -c40 -d60s http://localhost:8088/api/hello + +## 压测程序 + +1.可以从github获取 +git clone https://github.com/kimmking/atlantis +cd atlantis\gateway-server +mvn clean package +然后在target目录可以找到gateway-server-0.0.1-SNAPSHOT.jar + +2.也可以从此处下载已经编译好的: +链接:https://pan.baidu.com/s/1NbpYX4M3YKLYM1JJeIzgSQ +提取码:sp85 + +java -jar -Xmx512m -Xms512 gateway-server-0.0.1-SNAPSHOT.jar + diff --git a/02nio/GCLogAnalysis.java b/02nio/GCLogAnalysis.java new file mode 100644 index 00000000..d2570b27 --- /dev/null +++ b/02nio/GCLogAnalysis.java @@ -0,0 +1,63 @@ +import java.util.Random; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.LongAdder; +/* +演示GC日志生成与解读 +*/ +public class GCLogAnalysis { + // 随机数; 记得这里可以设置随机数种子; + private static Random random = new Random(); + public static void main(String[] args) { + // 当前毫秒时间戳 + long startMillis = System.currentTimeMillis(); + // 持续运行毫秒数; 可根据需要进行修改 + long timeoutMillis = TimeUnit.SECONDS.toMillis(1); + // 结束时间戳 + long endMillis = startMillis + timeoutMillis; + LongAdder counter = new LongAdder(); + System.out.println("正在执行..."); + // 缓存一部分对象; 进入老年代 + int cacheSize = 2000; + Object[] cachedGarbage = new Object[cacheSize]; + // 在此时间范围内,持续循环 + while (System.currentTimeMillis() < endMillis) { + // 生成垃圾对象 + Object garbage = generateGarbage(100*1024); + counter.increment(); + int randomIndex = random.nextInt(2 * cacheSize); + if (randomIndex < cacheSize) { + cachedGarbage[randomIndex] = garbage; + } + } + System.out.println("执行结束!共生成对象次数:" + counter.longValue()); + } + + // 生成对象 + private static Object generateGarbage(int max) { + int randomSize = random.nextInt(max); + int type = randomSize % 4; + Object result = null; + switch (type) { + case 0: + result = new int[randomSize]; + break; + case 1: + result = new byte[randomSize]; + break; + case 2: + result = new double[randomSize]; + break; + default: + StringBuilder builder = new StringBuilder(); + String randomString = "randomString-Anything"; + while (builder.length() < randomSize) { + builder.append(randomString); + builder.append(max); + builder.append(randomSize); + } + result = builder.toString(); + break; + } + return result; + } +} diff --git a/02nio/README.md b/02nio/README.md index 0681f025..79e9f518 100644 --- a/02nio/README.md +++ b/02nio/README.md @@ -3,24 +3,21 @@ ## 作业内容 -> Week02 作业题目(周四): +> Week02 作业题目: -1.使用 GCLogAnalysis.java 自己演练一遍串行 / 并行 /CMS/G1 的案例。 -2.使用压测工具(wrk 或 sb),演练 gateway-server-0.0.1-SNAPSHOT.jar 示例。 -3.(选做) 如果自己本地有可以运行的项目,可以按照 2 的方式进行演练。 -4.(必做) 根据上述自己对于 1 和 2 的演示,写一段对于不同 GC 的总结,提交到 Github。 +1. (选做)使用 [GCLogAnalysis.java](./GCLogAnalysis.java) 自己演练一遍 串行/并行/CMS/G1 的案例。 +2. (选做)使用压测工具(wrk 或 sb),演练 gateway-server-0.0.1-SNAPSHOT.jar 示例。 +3. (选做)如果自己本地有可以运行的项目,可以按照 2 的方式进行演练。 +4. (必做)根据上述自己对于 1 和 2 的演示,写一段对于不同 GC 和堆内存的总结,提交到 GitHub。 +5. (选做)运行课上的例子,以及 Netty 的例子,分析相关现象。 +6. (必做)写一段代码,使用 HttpClient 或 OkHttp 访问 http://localhost:8801 ,代码提交到 GitHub -> Week02 作业题目(周六): - -1.(选做)运行课上的例子,以及 Netty 的例子,分析相关现象。 - -2.(必做)写一段代码,使用 HttpClient 或 OkHttp 访问 http://localhost:8801 ,代码提交到 Github。 ## 操作步骤 -### 第二周-周六-作业2 +### 第二周-作业6.(必做) 1. 打开 Spring 官网: https://spring.io/ 2. 找到 Projects --> Spring Initializr: https://start.spring.io/ diff --git a/02nio/nio01/dependency-reduced-pom.xml b/02nio/nio01/dependency-reduced-pom.xml new file mode 100644 index 00000000..1646aa28 --- /dev/null +++ b/02nio/nio01/dependency-reduced-pom.xml @@ -0,0 +1,45 @@ + + + 4.0.0 + java0.nio01 + nio01 + 1.0 + + + + maven-compiler-plugin + + ${maven.compile.source} + ${maven.compile.target} + + + + maven-shade-plugin + 3.2.0 + + + + shade + + + + + + ${app.main.class} + ${maven.compile.source} + ${maven.compile.target} + + + + + + + + + + + Main + 8 + 8 + + diff --git a/02nio/nio01/pom.xml b/02nio/nio01/pom.xml index cf74139d..e42a62f2 100644 --- a/02nio/nio01/pom.xml +++ b/02nio/nio01/pom.xml @@ -7,19 +7,52 @@ java0.nio01 nio01 1.0 + + + Main + 8 + 8 + + org.apache.maven.plugins maven-compiler-plugin - 8 - 8 + ${maven.compile.source} + ${maven.compile.target} + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.0 + + + + shade + + + + + + ${app.main.class} + ${maven.compile.source} + ${maven.compile.target} + + + + + + + + + io.netty diff --git a/02nio/nio01/src/main/java/Main.java b/02nio/nio01/src/main/java/Main.java new file mode 100644 index 00000000..b07dca92 --- /dev/null +++ b/02nio/nio01/src/main/java/Main.java @@ -0,0 +1,34 @@ +import java0.nio01.HttpServer01; +import java0.nio01.HttpServer02; +import java0.nio01.HttpServer03; +import java0.nio01.netty.NettyHttpServer; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +public class Main { + + public static void main(String[] args) { + Map map = new HashMap<>(); + map.put("1", HttpServer01.class); + map.put("2", HttpServer02.class); + map.put("3", HttpServer03.class); + map.put("8", NettyHttpServer.class); + + String id = (null == args || args.length == 0) ? "1" : args[0]; + Class clazz = map.get(id); + if( null == clazz ) { + System.out.println("No class for id: " + id); + } + + try { + Method method = clazz.getDeclaredMethod("main", new Class[]{String[].class}); + method.invoke(null, new Object[]{new String[]{}}); + } catch (Exception e) { + e.printStackTrace(); + } + + } + +} diff --git a/02nio/nio01/src/main/java/java0/nio01/HttpServer01.java b/02nio/nio01/src/main/java/java0/nio01/HttpServer01.java index 6d8fd42d..ea62e1c2 100644 --- a/02nio/nio01/src/main/java/java0/nio01/HttpServer01.java +++ b/02nio/nio01/src/main/java/java0/nio01/HttpServer01.java @@ -21,17 +21,16 @@ public static void main(String[] args) throws IOException{ private static void service(Socket socket) { try { -// Thread.sleep(5); PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true); printWriter.println("HTTP/1.1 200 OK"); printWriter.println("Content-Type:text/html;charset=utf-8"); - String body = "hello,nio"; + String body = "hello,nio1"; printWriter.println("Content-Length:" + body.getBytes().length); printWriter.println(); printWriter.write(body); printWriter.close(); socket.close(); - } catch (IOException e) { // | InterruptedException e) { + } catch (Exception e) { e.printStackTrace(); } } diff --git a/02nio/nio01/src/main/java/java0/nio01/HttpServer02.java b/02nio/nio01/src/main/java/java0/nio01/HttpServer02.java index 542dc10a..298814ac 100644 --- a/02nio/nio01/src/main/java/java0/nio01/HttpServer02.java +++ b/02nio/nio01/src/main/java/java0/nio01/HttpServer02.java @@ -23,17 +23,16 @@ public static void main(String[] args) throws IOException{ private static void service(Socket socket) { try { -// Thread.sleep(5); PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true); printWriter.println("HTTP/1.1 200 OK"); printWriter.println("Content-Type:text/html;charset=utf-8"); - String body = "hello,nio"; + String body = "hello,nio2"; printWriter.println("Content-Length:" + body.getBytes().length); printWriter.println(); printWriter.write(body); printWriter.close(); socket.close(); - } catch (IOException e) { // | InterruptedException e) { + } catch (Exception e) { e.printStackTrace(); } } diff --git a/02nio/nio01/src/main/java/java0/nio01/HttpServer03.java b/02nio/nio01/src/main/java/java0/nio01/HttpServer03.java index 3545a33c..bd9b4acb 100644 --- a/02nio/nio01/src/main/java/java0/nio01/HttpServer03.java +++ b/02nio/nio01/src/main/java/java0/nio01/HttpServer03.java @@ -10,9 +10,8 @@ // 创建了一个固定大小的线程池处理请求 public class HttpServer03 { public static void main(String[] args) throws IOException{ - ExecutorService executorService = Executors.newFixedThreadPool( - Runtime.getRuntime().availableProcessors() + 2); + Runtime.getRuntime().availableProcessors() * 4); final ServerSocket serverSocket = new ServerSocket(8803); while (true) { try { @@ -26,17 +25,16 @@ public static void main(String[] args) throws IOException{ private static void service(Socket socket) { try { -// Thread.sleep(5); PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true); printWriter.println("HTTP/1.1 200 OK"); printWriter.println("Content-Type:text/html;charset=utf-8"); - String body = "hello,nio"; + String body = "hello,nio3"; printWriter.println("Content-Length:" + body.getBytes().length); printWriter.println(); printWriter.write(body); printWriter.close(); socket.close(); - } catch (IOException e) { // | InterruptedException e) { + } catch (Exception e) { e.printStackTrace(); } } diff --git a/02nio/nio01/src/main/java/java0/nio01/netty/HttpHandler.java b/02nio/nio01/src/main/java/java0/nio01/netty/HttpHandler.java index 1dbe0b9f..81f31d2e 100644 --- a/02nio/nio01/src/main/java/java0/nio01/netty/HttpHandler.java +++ b/02nio/nio01/src/main/java/java0/nio01/netty/HttpHandler.java @@ -31,7 +31,9 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) { String uri = fullRequest.uri(); //logger.info("接收到的请求url为{}", uri); if (uri.contains("/test")) { - handlerTest(fullRequest, ctx); + handlerTest(fullRequest, ctx, "hello,kimmking"); + } else { + handlerTest(fullRequest, ctx, "hello,others"); } } catch(Exception e) { @@ -41,10 +43,15 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) { } } - private void handlerTest(FullHttpRequest fullRequest, ChannelHandlerContext ctx) { + private void handlerTest(FullHttpRequest fullRequest, ChannelHandlerContext ctx, String body) { FullHttpResponse response = null; try { - String value = "hello,kimmking"; + String value = body; // 对接上次作业的httpclient或者okhttp请求另一个url的响应数据 + +// httpGet ... http://localhost:8801 +// 返回的响应,"hello,nio"; +// value = reponse.... + response = new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.wrappedBuffer(value.getBytes("UTF-8"))); response.headers().set("Content-Type", "application/json"); response.headers().setInt("Content-Length", response.content().readableBytes()); @@ -60,6 +67,7 @@ private void handlerTest(FullHttpRequest fullRequest, ChannelHandlerContext ctx) response.headers().set(CONNECTION, KEEP_ALIVE); ctx.write(response); } + ctx.flush(); } } } diff --git a/02nio/nio01/src/main/java/java0/nio01/netty/NettyHttpServer.java b/02nio/nio01/src/main/java/java0/nio01/netty/NettyHttpServer.java index c0570bf6..487d7283 100644 --- a/02nio/nio01/src/main/java/java0/nio01/netty/NettyHttpServer.java +++ b/02nio/nio01/src/main/java/java0/nio01/netty/NettyHttpServer.java @@ -22,14 +22,14 @@ public static void main(String[] args) throws InterruptedException { try { ServerBootstrap b = new ServerBootstrap(); b.option(ChannelOption.SO_BACKLOG, 128) - .option(ChannelOption.TCP_NODELAY, true) - .option(ChannelOption.SO_KEEPALIVE, true) - .option(ChannelOption.SO_REUSEADDR, true) - .option(ChannelOption.SO_RCVBUF, 32 * 1024) - .option(ChannelOption.SO_SNDBUF, 32 * 1024) - .option(EpollChannelOption.SO_REUSEPORT, true) + .childOption(ChannelOption.TCP_NODELAY, true) .childOption(ChannelOption.SO_KEEPALIVE, true) - .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT); + .childOption(ChannelOption.SO_REUSEADDR, true) + .childOption(ChannelOption.SO_RCVBUF, 32 * 1024) + .childOption(ChannelOption.SO_SNDBUF, 32 * 1024) + .childOption(EpollChannelOption.SO_REUSEPORT, true) + .childOption(ChannelOption.SO_KEEPALIVE, true) + .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT); b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) .handler(new LoggingHandler(LogLevel.INFO)) diff --git a/02nio/nio02/pom.xml b/02nio/nio02/pom.xml index 6cbbeffd..005de90a 100644 --- a/02nio/nio02/pom.xml +++ b/02nio/nio02/pom.xml @@ -52,6 +52,11 @@ httpasyncclient 4.1.4 + + + org.projectlombok + lombok + + + io.kimmking.javacourse + demo + 0.0.1-SNAPSHOT + demo + Demo project for Spring Boot + + 1.8 + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/04fx/demo/src/main/java/io/kimmking/javacourse/demo/DemoApplication.java b/04fx/demo/src/main/java/io/kimmking/javacourse/demo/DemoApplication.java new file mode 100644 index 00000000..70a3c8d7 --- /dev/null +++ b/04fx/demo/src/main/java/io/kimmking/javacourse/demo/DemoApplication.java @@ -0,0 +1,13 @@ +package io.kimmking.javacourse.demo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DemoApplication { + + public static void main(String[] args) { + SpringApplication.run(DemoApplication.class, args); + } + +} diff --git a/04fx/demo/src/main/resources/application.properties b/04fx/demo/src/main/resources/application.properties new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/04fx/demo/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/04fx/demo/src/test/java/io/kimmking/javacourse/demo/DemoApplicationTests.java b/04fx/demo/src/test/java/io/kimmking/javacourse/demo/DemoApplicationTests.java new file mode 100644 index 00000000..23f5cda4 --- /dev/null +++ b/04fx/demo/src/test/java/io/kimmking/javacourse/demo/DemoApplicationTests.java @@ -0,0 +1,13 @@ +package io.kimmking.javacourse.demo; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class DemoApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/04fx/java8/pom.xml b/04fx/java8/pom.xml index d26fcb56..695421a5 100644 --- a/04fx/java8/pom.xml +++ b/04fx/java8/pom.xml @@ -27,6 +27,11 @@ + + org.openjdk.jol + jol-core + 0.9 + com.google.guava guava diff --git a/04fx/java8/src/main/java/io/kimmking/java8/A.java b/04fx/java8/src/main/java/io/kimmking/java8/A.java index 569631ef..e3027fce 100644 --- a/04fx/java8/src/main/java/io/kimmking/java8/A.java +++ b/04fx/java8/src/main/java/io/kimmking/java8/A.java @@ -1,10 +1,24 @@ package io.kimmking.java8; -import lombok.Data; +import lombok.*; +import lombok.extern.slf4j.Slf4j; -@Data +@ToString +@NoArgsConstructor +@AllArgsConstructor +@Slf4j +@Builder +@Getter +@Setter public class A { - + private int age; - + + private String name; + +// public void test(){ +// log.info("this message is logged by lombok"); +// System.out.println(this.toString()); +// } + } diff --git a/04fx/java8/src/main/java/io/kimmking/java8/GenericDemo.java b/04fx/java8/src/main/java/io/kimmking/java8/GenericDemo.java index d6851736..7de88d61 100644 --- a/04fx/java8/src/main/java/io/kimmking/java8/GenericDemo.java +++ b/04fx/java8/src/main/java/io/kimmking/java8/GenericDemo.java @@ -1,9 +1,10 @@ package io.kimmking.java8; +import java.io.Serializable; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; -public class GenericDemo { +public class GenericDemo implements Serializable { public static void main(String[] args) { Demo demo = new Demo(); Class clazz = demo.getClass(); @@ -20,7 +21,7 @@ public static void main(String[] args) { System.out.println(c); } - public static class Person { + public static class Person { } diff --git a/04fx/java8/src/main/java/io/kimmking/java8/GuavaDemo.java b/04fx/java8/src/main/java/io/kimmking/java8/GuavaDemo.java index a2540278..e505fec7 100644 --- a/04fx/java8/src/main/java/io/kimmking/java8/GuavaDemo.java +++ b/04fx/java8/src/main/java/io/kimmking/java8/GuavaDemo.java @@ -48,7 +48,7 @@ private static void testEventBus() { // Callback/Listener // Student student2 = new Student(2, "KK02"); - System.out.println("I want " + student2 + " run now."); + System.out.println(Thread.currentThread().getName()+" I want " + student2 + " run now."); bus.post(new AEvent(student2)); } @@ -81,6 +81,7 @@ private static List testList() { List list = Lists.newArrayList(4,2,3,5,1,2,2,7,6); List> list1 = Lists.partition(list,3); + print(list1); return list; } @@ -89,10 +90,11 @@ private static List testString() { // 字符串处理 // List lists = Lists.newArrayList("a","b","g","8","9"); + String result = Joiner.on(",").join(lists); System.out.println(result); - String test = "34344,34,34,哈哈"; + String test = "34344,,,34,34,哈哈"; lists = Splitter.on(",").splitToList(test); System.out.println(lists); return lists; @@ -111,7 +113,7 @@ public static class AEvent{ @Subscribe public void handle(AEvent ae){ - System.out.println(ae.student + " is running."); + System.out.println(Thread.currentThread().getName()+" "+ae.student + " is running."); } diff --git a/04fx/java8/src/main/java/io/kimmking/java8/LambdaDemo.java b/04fx/java8/src/main/java/io/kimmking/java8/LambdaDemo.java index f1dffef0..94996f3b 100644 --- a/04fx/java8/src/main/java/io/kimmking/java8/LambdaDemo.java +++ b/04fx/java8/src/main/java/io/kimmking/java8/LambdaDemo.java @@ -17,17 +17,25 @@ public Integer operation(int a, int b) { }; MathOperation op1 = (a, b) -> 1; + + + MathOperation op2 = new MathOperation() { + @Override + public Integer operation(int a, int b) { + return a+b; + } + }; // 类型声明 MathOperation addition = (int a, int b) -> a + b; // 不用类型声明 - MathOperation subtraction = (a, b) -> a - b + 1.0; + MathOperation subtraction = (int a, int b) -> a - b ; // 大括号中的返回语句 MathOperation multiplication = (int a, int b) -> { - int c = 1000; - return a * b + c; + //int c = 1000; + return a * b;// + c; }; // 没有大括号及返回语句 @@ -41,22 +49,26 @@ public Integer operation(int a, int b) { //System.out.println("10 ^ 5 = " + demo.operate(10, 5, (a, b) -> new Double(Math.pow(a,b)).intValue())); System.out.println("10 ^ 5 = " + demo.operate(10, 5, (a, b) -> Math.pow(a,b))); - + + Runnable task = () -> System.out.println(1111); + // 不用括号 GreetingService greetService1 = message -> System.out.println("Hello " + message); // 用括号 - GreetingService greetService2 = (message) -> - System.out.println("Hello " + message); - + GreetingService greetService2 = (message) -> { + System.out.println(message); + }; + GreetingService greetService3 = System.out::println; - + Arrays.asList(1,2,3).forEach( x -> System.out.println(x+3)); Arrays.asList(1,2,3).forEach( LambdaDemo::println ); greetService1.sayMessage("kimmking"); greetService2.sayMessage("Java"); + greetService3.sayMessage("CuiCuilaoshi"); } private static void println(int x) { diff --git a/04fx/java8/src/main/java/io/kimmking/java8/LombokDemo.java b/04fx/java8/src/main/java/io/kimmking/java8/LombokDemo.java index 1fe98cc2..a1333f4f 100644 --- a/04fx/java8/src/main/java/io/kimmking/java8/LombokDemo.java +++ b/04fx/java8/src/main/java/io/kimmking/java8/LombokDemo.java @@ -1,14 +1,24 @@ package io.kimmking.java8; import lombok.extern.java.Log; +import org.slf4j.LoggerFactory; import java.io.IOException; @Log public class LombokDemo { - + public static void main(String[] args) throws IOException { - + + // Spring IoC + // ServiceLoader.load SPI + // Listener/Callback + // EventBus + + A a = new A(1, "KK"); + System.out.println(a.toString()); + A b = A.builder().age(1).name("KKK").build(); + new LombokDemo().demo(); Student student1 = new Student(); @@ -17,6 +27,7 @@ public static void main(String[] args) throws IOException { System.out.println(student1.toString()); Student student2 = new Student(2, "KK02"); + //student2.init(); System.out.println(student2.toString()); } diff --git a/04fx/java8/src/main/java/io/kimmking/java8/StreamDemo.java b/04fx/java8/src/main/java/io/kimmking/java8/StreamDemo.java index 4ec48773..b2771ff3 100644 --- a/04fx/java8/src/main/java/io/kimmking/java8/StreamDemo.java +++ b/04fx/java8/src/main/java/io/kimmking/java8/StreamDemo.java @@ -3,11 +3,7 @@ import com.alibaba.fastjson.JSON; import java.io.IOException; -import java.util.Arrays; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; import java.util.stream.Collectors; public class StreamDemo { @@ -19,14 +15,21 @@ public static void main(String[] args) throws IOException { // Optional Optional first = list.stream().findFirst(); - + System.out.println(first.map(i -> i * 100).orElse(100)); - + + //1,2,3 + // 0, 1, 2, 3 int sum = list.stream().filter( i -> i<4).distinct().reduce(0,(a,b)->a+b); System.out.println("sum="+sum); + + //1,2,3 + // 1, 1, 2, 3 + int multi = list.stream().filter( i -> i<4).distinct().reduce(1,(a,b)->a*b); + System.out.println("multi="+multi); - //Map map = list.stream().collect(Collectors.toMap(a->a,a->(a+1))); - Map map = list.parallelStream().collect(Collectors.toMap(a->a,a->(a+1),(a,b)->a, LinkedHashMap::new)); + //Map map1 = list.stream().collect(Collectors.toMap(a->a,a->(a+1))); + Map map = list.stream().parallel().collect(Collectors.toMap(a->a,a->(a+1),(a,b)->a, LinkedHashMap::new)); print(map); diff --git a/04fx/java8/src/main/java/io/kimmking/java8/TestMem.java b/04fx/java8/src/main/java/io/kimmking/java8/TestMem.java new file mode 100644 index 00000000..1ffcf8f7 --- /dev/null +++ b/04fx/java8/src/main/java/io/kimmking/java8/TestMem.java @@ -0,0 +1,27 @@ +package io.kimmking.java8; + +import org.openjdk.jol.info.ClassLayout; +import org.openjdk.jol.info.GraphLayout; + +public class TestMem { + public static void main(String[] args) { + int[] arr1 = new int[256]; + int[][] arr2 = new int[128][2]; + int[][][] arr3 = new int[64][2][2]; + + print("1-size : " + GraphLayout.parseInstance(arr1).totalSize()); + print(ClassLayout.parseInstance(arr1).toPrintable()); + print("2-size : " + GraphLayout.parseInstance(arr2).totalSize()); + print(ClassLayout.parseInstance(arr2).toPrintable()); + print(GraphLayout.parseInstance(arr2).toPrintable()); + print("3-size : " + GraphLayout.parseInstance(arr3).totalSize()); + print(ClassLayout.parseInstance(arr3).toPrintable()); + print(GraphLayout.parseInstance(arr3).toPrintable()); + System.out.println(); + } + + static void print(String message) { + System.out.println(message); + System.out.println("-------------------------"); + } +} \ No newline at end of file diff --git a/04fx/spring01/pom.xml b/04fx/spring01/pom.xml index 52e59f6d..505009a7 100644 --- a/04fx/spring01/pom.xml +++ b/04fx/spring01/pom.xml @@ -152,11 +152,6 @@ test - - org.springframework - spring-jms - 4.3.29.RELEASE - org.apache.activemq activemq-client diff --git a/04fx/spring01/src/main/java/io/kimmking/spring01/GuavaDemo.java b/04fx/spring01/src/main/java/io/kimmking/spring01/GuavaDemo.java index 98ef1c51..697b680c 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring01/GuavaDemo.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring01/GuavaDemo.java @@ -79,7 +79,7 @@ public static void main(String[] args) throws IOException { // SPI+service loader // Callback/Listener // - Student student2 = new Student(2, "KK02"); + Student student2 = Student.create(); System.out.println("I want " + student2 + " run now."); bus.post(new AEvent(student2)); diff --git a/04fx/spring01/src/main/java/io/kimmking/spring01/LombokDemo.java b/04fx/spring01/src/main/java/io/kimmking/spring01/LombokDemo.java index 470db3b7..c28b48e2 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring01/LombokDemo.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring01/LombokDemo.java @@ -16,7 +16,7 @@ public static void main(String[] args) throws IOException { student1.setName("KK01"); System.out.println(student1.toString()); - Student student2 = new Student(2, "KK02"); + Student student2 = Student.create(); System.out.println(student2.toString()); } diff --git a/04fx/spring01/src/main/java/io/kimmking/spring01/Student.java b/04fx/spring01/src/main/java/io/kimmking/spring01/Student.java index db8e0061..a2357bf6 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring01/Student.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring01/Student.java @@ -5,6 +5,10 @@ import lombok.Data; import lombok.NoArgsConstructor; import lombok.ToString; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanNameAware; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; import java.io.Serializable; @@ -13,17 +17,29 @@ @AllArgsConstructor @NoArgsConstructor @ToString +public class Student implements Serializable, BeanNameAware, ApplicationContextAware { + -public class Student implements Serializable { - private int id; private String name; - + + private String beanName; + private ApplicationContext applicationContext; + public void init(){ System.out.println("hello..........."); } - public Student create(){ - return new Student(101,"KK101"); + public static Student create(){ + return new Student(102,"KK102",null, null); } + + public void print() { + System.out.println(this.beanName); + System.out.println(" context.getBeanDefinitionNames() ===>> " + + String.join(",", applicationContext.getBeanDefinitionNames())); + + } + + } diff --git a/04fx/spring01/src/main/java/io/kimmking/spring02/Aop1.java b/04fx/spring01/src/main/java/io/kimmking/spring02/Aop1.java index 35447d56..fa919d39 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring02/Aop1.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring02/Aop1.java @@ -6,21 +6,21 @@ public class Aop1 { //前置通知 public void startTransaction(){ - System.out.println(" ====>begin ding... "); + System.out.println(" ====>begin ding... "); //2 } //后置通知 public void commitTransaction(){ - System.out.println(" ====>finish ding... "); + System.out.println(" ====>finish ding... "); //4 } //环绕通知 public void around(ProceedingJoinPoint joinPoint) throws Throwable{ - System.out.println(" ====>around begin ding"); + System.out.println(" ====>around begin ding"); //1 //调用process()方法才会真正的执行实际被代理的方法 joinPoint.proceed(); - System.out.println(" ====>around finish ding"); + System.out.println(" ====>around finish ding"); //3 } } diff --git a/04fx/spring01/src/main/java/io/kimmking/spring02/Aop2.java b/04fx/spring01/src/main/java/io/kimmking/spring02/Aop2.java index b8eae255..4edbe006 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring02/Aop2.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring02/Aop2.java @@ -18,19 +18,19 @@ public void point(){ @Before(value="point()") public void before(){ - System.out.println("========>begin klass dong..."); + System.out.println("========>begin klass dong... //2"); } @AfterReturning(value = "point()") public void after(){ - System.out.println("========>after klass dong..."); + System.out.println("========>after klass dong... //4"); } @Around("point()") public void around(ProceedingJoinPoint joinPoint) throws Throwable{ - System.out.println("========>around begin klass dong"); + System.out.println("========>around begin klass dong //1"); joinPoint.proceed(); - System.out.println("========>around after klass dong"); + System.out.println("========>around after klass dong //3"); } diff --git a/04fx/spring01/src/main/java/io/kimmking/spring02/HelloBeanDefinitionRegistryPostProcessor.java b/04fx/spring01/src/main/java/io/kimmking/spring02/HelloBeanDefinitionRegistryPostProcessor.java new file mode 100644 index 00000000..d6433bd6 --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/spring02/HelloBeanDefinitionRegistryPostProcessor.java @@ -0,0 +1,29 @@ +package io.kimmking.spring02; + +import io.kimmking.spring01.Student; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.stereotype.Component; + +@Component +public class HelloBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { + @Override + public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { + System.out.println(" ==> postProcessBeanDefinitionRegistry: "+registry.getBeanDefinitionCount()); + System.out.println(" ==> postProcessBeanDefinitionRegistry: "+String.join(",",registry.getBeanDefinitionNames())); + RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Student.class); + rootBeanDefinition.getPropertyValues().add("id", 101); + rootBeanDefinition.getPropertyValues().add("name", "KK101"); + registry.registerBeanDefinition("s101", rootBeanDefinition); + } + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + System.out.println(" ==> postProcessBeanFactory: "+beanFactory.getBeanDefinitionCount()); + System.out.println(" ==> postProcessBeanFactory: "+String.join(",",beanFactory.getBeanDefinitionNames())); + beanFactory.registerSingleton("s102", Student.create()); + } +} diff --git a/04fx/spring01/src/main/java/io/kimmking/spring02/HelloBeanPostProcessor.java b/04fx/spring01/src/main/java/io/kimmking/spring02/HelloBeanPostProcessor.java new file mode 100644 index 00000000..451c829b --- /dev/null +++ b/04fx/spring01/src/main/java/io/kimmking/spring02/HelloBeanPostProcessor.java @@ -0,0 +1,27 @@ +package io.kimmking.spring02; + +import io.kimmking.spring01.Student; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.stereotype.Component; + +@Component +public class HelloBeanPostProcessor implements BeanPostProcessor { + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + System.out.println(" ====> postProcessBeforeInitialization " + beanName +":"+ bean); + // 可以加点额外处理 + // 例如 + if (bean instanceof Student) { + Student student = (Student) bean; + student.setName(student.getName() + "-" + System.currentTimeMillis()); + } + return bean; + } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + System.out.println(" ====> postProcessAfterInitialization " + beanName +":"+ bean); + return bean; + } +} diff --git a/04fx/spring01/src/main/java/io/kimmking/spring02/SpringDemo01.java b/04fx/spring01/src/main/java/io/kimmking/spring02/SpringDemo01.java index 8241be04..a6263369 100644 --- a/04fx/spring01/src/main/java/io/kimmking/spring02/SpringDemo01.java +++ b/04fx/spring01/src/main/java/io/kimmking/spring02/SpringDemo01.java @@ -14,9 +14,13 @@ public static void main(String[] args) { Student student123 = (Student) context.getBean("student123"); System.out.println(student123.toString()); + + student123.print(); Student student100 = (Student) context.getBean("student100"); System.out.println(student100.toString()); + + student100.print(); Klass class1 = context.getBean(Klass.class); System.out.println(class1); @@ -36,7 +40,14 @@ public static void main(String[] args) { class1.dong(); System.out.println(" context.getBeanDefinitionNames() ===>> "+ String.join(",", context.getBeanDefinitionNames())); - + Student s101 = (Student) context.getBean("s101"); + if (s101 != null) { + System.out.println(s101); + } + Student s102 = (Student) context.getBean("s102"); + if (s102 != null) { + System.out.println(s102); + } } } diff --git a/04fx/spring01/src/main/java/io/kimmking/springjms/JmsSender.java b/04fx/spring01/src/main/java/io/kimmking/springjms/JmsSender.java index e9b65a01..2b1e72f3 100644 --- a/04fx/spring01/src/main/java/io/kimmking/springjms/JmsSender.java +++ b/04fx/spring01/src/main/java/io/kimmking/springjms/JmsSender.java @@ -8,7 +8,7 @@ public class JmsSender { public static void main( String[] args ) { - Student student2 = new Student(200, "KK0200"); + Student student2 = Student.create(); ApplicationContext context = new ClassPathXmlApplicationContext("classpath:springjms-sender.xml"); diff --git a/04fx/spring01/src/main/java/io/kimmking/springjms/SendService.java b/04fx/spring01/src/main/java/io/kimmking/springjms/SendService.java index 1c09e4c5..15bafce1 100644 --- a/04fx/spring01/src/main/java/io/kimmking/springjms/SendService.java +++ b/04fx/spring01/src/main/java/io/kimmking/springjms/SendService.java @@ -1,5 +1,6 @@ package io.kimmking.springjms; +import com.alibaba.fastjson.JSON; import io.kimmking.spring01.Student; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jms.core.JmsTemplate; @@ -19,7 +20,7 @@ public void send(final Student user) { jmsTemplate.send("test.queue", new MessageCreator() { public Message createMessage(Session session) throws JMSException { - return session.createObjectMessage(user); + return session.createObjectMessage(JSON.toJSONString(user)); } }); } diff --git a/04fx/springboot01/src/main/java/io/kimmking/springboot01/Springboot01Application.java b/04fx/springboot01/src/main/java/io/kimmking/springboot01/Springboot01Application.java index 331167c1..0cfd0cb6 100644 --- a/04fx/springboot01/src/main/java/io/kimmking/springboot01/Springboot01Application.java +++ b/04fx/springboot01/src/main/java/io/kimmking/springboot01/Springboot01Application.java @@ -7,8 +7,8 @@ import org.springframework.jms.annotation.EnableJms; @SpringBootApplication -@EnableJms //启动消息队列 -@EnableMongoRepositories +//@EnableJms //启动消息队列 +//@EnableMongoRepositories public class Springboot01Application { public static void main(String[] args) { diff --git a/04fx/springboot01/src/main/resources/application.yml b/04fx/springboot01/src/main/resources/application.yml index fa5370a3..048ab343 100644 --- a/04fx/springboot01/src/main/resources/application.yml +++ b/04fx/springboot01/src/main/resources/application.yml @@ -18,7 +18,7 @@ spring: enabled: true max-connections: 10 #连接池最大连接数 idle-timeout: 30000 #空闲的连接过期时间,默认为30秒 - + data: diff --git a/06db/shardingsphere/config-replica-query.yaml b/06db/shardingsphere/config-replica-query.yaml new file mode 100644 index 00000000..d060ab5e --- /dev/null +++ b/06db/shardingsphere/config-replica-query.yaml @@ -0,0 +1,30 @@ + +schemaName: replica_query_db + +dataSourceCommon: + username: root + password: + connectionTimeoutMilliseconds: 30000 + idleTimeoutMilliseconds: 60000 + maxLifetimeMilliseconds: 1800000 + maxPoolSize: 10 + minPoolSize: 1 + maintenanceIntervalMilliseconds: 30000 + +dataSources: + primary_ds: + url: jdbc:mysql://127.0.0.1:3306/demo_master?serverTimezone=UTC&useSSL=false + replica_ds_0: + url: jdbc:mysql://127.0.0.1:3306/demo_slave_0?serverTimezone=UTC&useSSL=false + replica_ds_1: + url: jdbc:mysql://127.0.0.1:3306/demo_slave_1?serverTimezone=UTC&useSSL=false + +rules: +- !REPLICA_QUERY + dataSources: + pr_ds: + name: pr_ds + primaryDataSourceName: primary_ds + replicaDataSourceNames: + - replica_ds_0 + - replica_ds_1 diff --git a/06db/shardingsphere/config-sharding.yaml b/06db/shardingsphere/config-sharding.yaml new file mode 100644 index 00000000..ffbc1546 --- /dev/null +++ b/06db/shardingsphere/config-sharding.yaml @@ -0,0 +1,68 @@ + +schemaName: sharding_db + +dataSourceCommon: + username: root + password: + connectionTimeoutMilliseconds: 30000 + idleTimeoutMilliseconds: 60000 + maxLifetimeMilliseconds: 1800000 + maxPoolSize: 5 + minPoolSize: 1 + maintenanceIntervalMilliseconds: 30000 + +dataSources: + ds_0: + url: jdbc:mysql://127.0.0.1:3306/demo_ds_0?serverTimezone=UTC&useSSL=false + ds_1: + url: jdbc:mysql://127.0.0.1:3306/demo_ds_1?serverTimezone=UTC&useSSL=false + +rules: +- !SHARDING + tables: + t_order: + actualDataNodes: ds_${0..1}.t_order_${0..1} + tableStrategy: + standard: + shardingColumn: order_id + shardingAlgorithmName: t_order_inline + keyGenerateStrategy: + column: order_id + keyGeneratorName: snowflake + t_order_item: + actualDataNodes: ds_${0..1}.t_order_item_${0..1} + tableStrategy: + standard: + shardingColumn: order_id + shardingAlgorithmName: t_order_item_inline + keyGenerateStrategy: + column: order_item_id + keyGeneratorName: snowflake + bindingTables: + - t_order,t_order_item + defaultDatabaseStrategy: + standard: + shardingColumn: user_id + shardingAlgorithmName: database_inline + defaultTableStrategy: + none: + + shardingAlgorithms: + database_inline: + type: INLINE + props: + algorithm-expression: ds_${user_id % 2} + t_order_inline: + type: INLINE + props: + algorithm-expression: t_order_${order_id % 2} + t_order_item_inline: + type: INLINE + props: + algorithm-expression: t_order_item_${order_id % 2} + + keyGenerators: + snowflake: + type: SNOWFLAKE + props: + worker-id: 123 diff --git a/06db/shardingsphere/init.sql b/06db/shardingsphere/init.sql new file mode 100644 index 00000000..7c1adb0c --- /dev/null +++ b/06db/shardingsphere/init.sql @@ -0,0 +1,31 @@ + +## 读写分离 + +create schema demo_master; +create schema demo_slave_0; +create schema demo_slave_1; + +create table demo_master.users(id bigint, name varchar(8), comment varchar(16)); +create table demo_slave_0.users(id bigint, name varchar(8), comment varchar(16)); +create table demo_slave_1.users(id bigint, name varchar(8), comment varchar(16)); + +insert into demo_master.users values(1,'KK01','master'),(2,'KK02','master'),(3,'KK03','master'); +insert into demo_slave_0.users values(1,'KK01','slave0'),(2,'KK02','slave0'),(3,'KK03','slave0'); +insert into demo_slave_1.users values(1,'KK01','slave1'),(2,'KK02','slave1'),(3,'KK03','slave1'); + + +## 分库分表 + +create schema demo_ds_0; +create schema demo_ds_1; + +CREATE TABLE IF NOT EXISTS demo_ds_0.t_order_0 (order_id BIGINT NOT NULL AUTO_INCREMENT, user_id INT NOT NULL, status VARCHAR(50), PRIMARY KEY (order_id)); +CREATE TABLE IF NOT EXISTS demo_ds_0.t_order_1 (order_id BIGINT NOT NULL AUTO_INCREMENT, user_id INT NOT NULL, status VARCHAR(50), PRIMARY KEY (order_id)); +CREATE TABLE IF NOT EXISTS demo_ds_1.t_order_0 (order_id BIGINT NOT NULL AUTO_INCREMENT, user_id INT NOT NULL, status VARCHAR(50), PRIMARY KEY (order_id)); +CREATE TABLE IF NOT EXISTS demo_ds_1.t_order_1 (order_id BIGINT NOT NULL AUTO_INCREMENT, user_id INT NOT NULL, status VARCHAR(50), PRIMARY KEY (order_id)); + +CREATE TABLE IF NOT EXISTS demo_ds_0.t_order_item_0 (order_item_id BIGINT NOT NULL AUTO_INCREMENT, order_id BIGINT NOT NULL, user_id INT NOT NULL, status VARCHAR(50), PRIMARY KEY (order_item_id)); +CREATE TABLE IF NOT EXISTS demo_ds_0.t_order_item_1 (order_item_id BIGINT NOT NULL AUTO_INCREMENT, order_id BIGINT NOT NULL, user_id INT NOT NULL, status VARCHAR(50), PRIMARY KEY (order_item_id)); +CREATE TABLE IF NOT EXISTS demo_ds_1.t_order_item_0 (order_item_id BIGINT NOT NULL AUTO_INCREMENT, order_id BIGINT NOT NULL, user_id INT NOT NULL, status VARCHAR(50), PRIMARY KEY (order_item_id)); +CREATE TABLE IF NOT EXISTS demo_ds_1.t_order_item_1 (order_item_id BIGINT NOT NULL AUTO_INCREMENT, order_id BIGINT NOT NULL, user_id INT NOT NULL, status VARCHAR(50), PRIMARY KEY (order_item_id)); + diff --git a/06db/shardingsphere/server.yaml b/06db/shardingsphere/server.yaml new file mode 100644 index 00000000..87df2ef0 --- /dev/null +++ b/06db/shardingsphere/server.yaml @@ -0,0 +1,35 @@ + +# governance: +# name: governance_ds +# registryCenter: +# type: ZooKeeper +# serverLists: localhost:2181 +# props: +# retryIntervalMilliseconds: 500 +# timeToLiveSeconds: 60 +# maxRetries: 3 +# operationTimeoutMilliseconds: 500 +# overwrite: true + +authentication: + users: + root: + password: root +# sharding: +# password: sharding +# authorizedSchemas: sharding_db + +props: + max-connections-size-per-query: 1 + acceptor-size: 16 # The default value is available processors count * 2. + executor-size: 16 # Infinite by default. + proxy-frontend-flush-threshold: 128 # The default value is 128. + # LOCAL: Proxy will run with LOCAL transaction. + # XA: Proxy will run with XA transaction. + # BASE: Proxy will run with B.A.S.E transaction. + proxy-transaction-type: LOCAL + proxy-opentracing-enabled: false + proxy-hint-enabled: false + query-with-cipher-column: false + sql-show: true + check-table-metadata-enabled: false diff --git a/07rpc/rpc01/rpcfx-core/src/main/java/io/kimmking/rpcfx/client/Rpcfx.java b/07rpc/rpc01/rpcfx-core/src/main/java/io/kimmking/rpcfx/client/Rpcfx.java index 74adbcc6..5d1ae517 100644 --- a/07rpc/rpc01/rpcfx-core/src/main/java/io/kimmking/rpcfx/client/Rpcfx.java +++ b/07rpc/rpc01/rpcfx-core/src/main/java/io/kimmking/rpcfx/client/Rpcfx.java @@ -41,7 +41,7 @@ public static T createFromRegistry(final Class serviceClass, fin public static T create(final Class serviceClass, final String url, Filter... filters) { - // 0. 替换动态代理 -> AOP + // 0. 替换动态代理 -> 字节码生成 return (T) Proxy.newProxyInstance(Rpcfx.class.getClassLoader(), new Class[]{serviceClass}, new RpcfxInvocationHandler(serviceClass, url, filters)); } diff --git a/07rpc/rpc01/rpcfx-demo-consumer/src/main/java/io/kimmking/rpcfx/demo/consumer/RpcfxClientApplication.java b/07rpc/rpc01/rpcfx-demo-consumer/src/main/java/io/kimmking/rpcfx/demo/consumer/RpcfxClientApplication.java index b6371f0d..a4187d14 100644 --- a/07rpc/rpc01/rpcfx-demo-consumer/src/main/java/io/kimmking/rpcfx/demo/consumer/RpcfxClientApplication.java +++ b/07rpc/rpc01/rpcfx-demo-consumer/src/main/java/io/kimmking/rpcfx/demo/consumer/RpcfxClientApplication.java @@ -32,12 +32,12 @@ public static void main(String[] args) { User user = userService.findById(1); System.out.println("find user id=1 from server: " + user.getName()); - OrderService orderService = Rpcfx.create(OrderService.class, "http://localhost:8080/"); - Order order = orderService.findOrderById(1992129); - System.out.println(String.format("find order name=%s, amount=%f",order.getName(),order.getAmount())); - - // - UserService userService2 = Rpcfx.createFromRegistry(UserService.class, "localhost:2181", new TagRouter(), new RandomLoadBalancer(), new CuicuiFilter()); +// OrderService orderService = Rpcfx.create(OrderService.class, "http://localhost:8080/"); +// Order order = orderService.findOrderById(1992129); +// System.out.println(String.format("find order name=%s, amount=%f",order.getName(),order.getAmount())); +// +// // +// UserService userService2 = Rpcfx.createFromRegistry(UserService.class, "localhost:2181", new TagRouter(), new RandomLoadBalancer(), new CuicuiFilter()); // SpringApplication.run(RpcfxClientApplication.class, args); } diff --git a/07rpc/rpc01/rpcfx-demo-provider/src/main/java/io/kimmking/rpcfx/demo/provider/RpcfxServerApplication.java b/07rpc/rpc01/rpcfx-demo-provider/src/main/java/io/kimmking/rpcfx/demo/provider/RpcfxServerApplication.java index f29a6d9d..d79e422e 100644 --- a/07rpc/rpc01/rpcfx-demo-provider/src/main/java/io/kimmking/rpcfx/demo/provider/RpcfxServerApplication.java +++ b/07rpc/rpc01/rpcfx-demo-provider/src/main/java/io/kimmking/rpcfx/demo/provider/RpcfxServerApplication.java @@ -31,19 +31,19 @@ public class RpcfxServerApplication { public static void main(String[] args) throws Exception { - // start zk client - RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3); - CuratorFramework client = CuratorFrameworkFactory.builder().connectString("localhost:2181").namespace("rpcfx").retryPolicy(retryPolicy).build(); - client.start(); - - - // register service - // xxx "io.kimmking.rpcfx.demo.api.UserService" - - String userService = "io.kimking.rpcfx.demo.api.UserService"; - registerService(client, userService); - String orderService = "io.kimking.rpcfx.demo.api.OrderService"; - registerService(client, orderService); +// // start zk client +// RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3); +// CuratorFramework client = CuratorFrameworkFactory.builder().connectString("localhost:2181").namespace("rpcfx").retryPolicy(retryPolicy).build(); +// client.start(); +// +// +// // register service +// // xxx "io.kimmking.rpcfx.demo.api.UserService" +// +// String userService = "io.kimking.rpcfx.demo.api.UserService"; +// registerService(client, userService); +// String orderService = "io.kimking.rpcfx.demo.api.OrderService"; +// registerService(client, orderService); // 进一步的优化,是在spring加载完成后,从里面拿到特定注解的bean,自动注册到zk diff --git a/08cache/cache/src/main/java/io/kimmking/cache/CacheConfig.java b/08cache/cache/src/main/java/io/kimmking/cache/CacheConfig.java index 7b23c300..d4bdd8b1 100644 --- a/08cache/cache/src/main/java/io/kimmking/cache/CacheConfig.java +++ b/08cache/cache/src/main/java/io/kimmking/cache/CacheConfig.java @@ -36,7 +36,7 @@ public KeyGenerator keyGenerator() { sb.append(o.getClass().getName()).append("."); sb.append(method.getName()).append("."); for (Object obj : objects) { - sb.append(obj.toString()); + sb.append(obj.toString()).append("."); } //System.out.println("keyGenerator=" + sb.toString()); return sb.toString(); diff --git a/08cache/cache/src/main/java/io/kimmking/cache/service/UserServiceImpl.java b/08cache/cache/src/main/java/io/kimmking/cache/service/UserServiceImpl.java index 25d70d3d..4a1f5acf 100644 --- a/08cache/cache/src/main/java/io/kimmking/cache/service/UserServiceImpl.java +++ b/08cache/cache/src/main/java/io/kimmking/cache/service/UserServiceImpl.java @@ -12,7 +12,7 @@ public class UserServiceImpl implements UserService { @Autowired - UserMapper userMapper; + UserMapper userMapper; //DAO // Repository // 开启spring cache @Cacheable(key="#id",value="userCache") diff --git a/08cache/cache/test.sql b/08cache/cache/test.sql index 3a6ef771..2296f238 100644 --- a/08cache/cache/test.sql +++ b/08cache/cache/test.sql @@ -36,7 +36,7 @@ CREATE TABLE `user` ( LOCK TABLES `user` WRITE; /*!40000 ALTER TABLE `user` DISABLE KEYS */; -INSERT INTO `user` VALUES (1,'KK',19),(2,'CC',20),(3,'MM',21); +INSERT INTO `user` VALUES (1,'KK',20),(2,'CC',18),(3,'MK',21); /*!40000 ALTER TABLE `user` ENABLE KEYS */; UNLOCK TABLES; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; diff --git a/08cache/ha/conf/redis6379.conf b/08cache/ha/conf/redis6379.conf index b74bf28a..e33949fa 100644 --- a/08cache/ha/conf/redis6379.conf +++ b/08cache/ha/conf/redis6379.conf @@ -1864,6 +1864,6 @@ jemalloc-bg-thread yes # Set bgsave child process to cpu affinity 1,10,11 # bgsave_cpulist 1,10-11 # Generated by CONFIG REWRITE -user default on nopass ~* +@all +user default on nopass sanitize-payload ~* &* +@all replicaof 127.0.0.1 6380 diff --git a/08cache/ha/conf/redis6380.conf b/08cache/ha/conf/redis6380.conf index cac4461a..20311df0 100644 --- a/08cache/ha/conf/redis6380.conf +++ b/08cache/ha/conf/redis6380.conf @@ -1864,5 +1864,5 @@ jemalloc-bg-thread yes # Set bgsave child process to cpu affinity 1,10,11 # bgsave_cpulist 1,10-11 # Generated by CONFIG REWRITE -user default on nopass ~* +@all +user default on nopass sanitize-payload ~* &* +@all diff --git a/08cache/ha/conf/sentinel0.conf b/08cache/ha/conf/sentinel0.conf index 0157b2f2..df262af1 100644 --- a/08cache/ha/conf/sentinel0.conf +++ b/08cache/ha/conf/sentinel0.conf @@ -5,10 +5,11 @@ sentinel down-after-milliseconds mymaster 10000 # Generated by CONFIG REWRITE protected-mode no port 26379 -user default on nopass ~* +@all +user default on nopass sanitize-payload ~* &* +@all dir "/Users/kimmking/kimmking/JavaCourseCodes/08cache/ha/conf" -sentinel config-epoch mymaster 5 -sentinel leader-epoch mymaster 6 + +sentinel config-epoch mymaster 1 +sentinel leader-epoch mymaster 1 sentinel known-replica mymaster 127.0.0.1 6379 +sentinel current-epoch 1 sentinel known-sentinel mymaster 127.0.0.1 26380 8d992c54df8f8677b0b345825f61fb733c73d14d -sentinel current-epoch 6 diff --git a/08cache/ha/conf/sentinel1.conf b/08cache/ha/conf/sentinel1.conf index eb0738b9..ad487fd0 100644 --- a/08cache/ha/conf/sentinel1.conf +++ b/08cache/ha/conf/sentinel1.conf @@ -1,14 +1,14 @@ sentinel myid 8d992c54df8f8677b0b345825f61fb733c73d14d sentinel deny-scripts-reconfig yes sentinel monitor mymaster 127.0.0.1 6380 2 +port 26380 sentinel down-after-milliseconds mymaster 10000 # Generated by CONFIG REWRITE protected-mode no -port 26380 -user default on nopass ~* +@all +user default on nopass sanitize-payload ~* &* +@all dir "/Users/kimmking/kimmking/JavaCourseCodes/08cache/ha/conf" -sentinel config-epoch mymaster 5 -sentinel leader-epoch mymaster 6 +sentinel config-epoch mymaster 1 +sentinel leader-epoch mymaster 1 sentinel known-replica mymaster 127.0.0.1 6379 +sentinel current-epoch 1 sentinel known-sentinel mymaster 127.0.0.1 26379 8d992c54df8f8677b0b345825f61fb733c73d14c -sentinel current-epoch 6 diff --git a/08cache/redis/src/main/java/io/kimmking/cache/RedisApplication.java b/08cache/redis/src/main/java/io/kimmking/cache/RedisApplication.java index 2773df21..f685a7b8 100644 --- a/08cache/redis/src/main/java/io/kimmking/cache/RedisApplication.java +++ b/08cache/redis/src/main/java/io/kimmking/cache/RedisApplication.java @@ -21,16 +21,18 @@ public static void main(String[] args) { System.out.println(jedis.info()); jedis.set("uptime", new Long(System.currentTimeMillis()).toString()); System.out.println(jedis.get("uptime")); - - // C2.基于sentinel和连接池的demo + jedis.set("teacher", "Cuijing"); + System.out.println(jedis.get("teacher")); +// +// // C2.基于sentinel和连接池的demo // Jedis sjedis = SentinelJedis.getJedis(); // System.out.println(sjedis.info()); // sjedis.set("uptime2", new Long(System.currentTimeMillis()).toString()); // System.out.println(sjedis.get("uptime2")); // SentinelJedis.close(); - - // C3. 直接连接sentinel进行操作 -// Jedis jedisSentinel = new Jedis("localhost", 26380); // 连接到sentinel +// +// // C3. 直接连接sentinel进行操作 +// Jedis jedisSentinel = new Jedis("localhost", 26379); // 连接到sentinel // List> masters = jedisSentinel.sentinelMasters(); // System.out.println(JSON.toJSONString(masters)); // List> slaves = jedisSentinel.sentinelSlaves("mymaster"); diff --git a/08cache/redis/src/main/java/io/kimmking/cache/redission/RedissionDemo.java b/08cache/redis/src/main/java/io/kimmking/cache/redission/RedissionDemo.java index c52adcd1..bd86f2fb 100644 --- a/08cache/redis/src/main/java/io/kimmking/cache/redission/RedissionDemo.java +++ b/08cache/redis/src/main/java/io/kimmking/cache/redission/RedissionDemo.java @@ -13,8 +13,7 @@ public class RedissionDemo { @SneakyThrows public static void main(String[] args) { Config config = new Config(); - config.useSingleServer().setAddress("redis://127.0.0.1:6380"); - //config.useSingleServer().setPassword(""); + config.useSingleServer().setAddress("redis://127.0.0.1:6379"); final RedissonClient client = Redisson.create(config); RMap rmap = client.getMap("map1"); @@ -24,20 +23,21 @@ public static void main(String[] args) { lock.lock(); for (int i = 0; i < 15; i++) { - rmap.put("rkey:"+i, "rvalue:"+i); + rmap.put("rkey:"+i, "111rvalue:"+i); } // 如果代码块 W1 在这里会怎么样? + // 代码块 W1 + while(true) { + Thread.sleep(2000); + System.out.println(rmap.get("rkey:10")); + } }finally{ lock.unlock(); } - // 代码块 W1 - while(true) { - Thread.sleep(2000); - System.out.println(rmap.get("rkey:10")); - } + } diff --git a/08cache/redis/src/main/java/io/kimmking/cache/redission/RedissionDemo1.java b/08cache/redis/src/main/java/io/kimmking/cache/redission/RedissionDemo1.java index 603be446..8534b3c8 100644 --- a/08cache/redis/src/main/java/io/kimmking/cache/redission/RedissionDemo1.java +++ b/08cache/redis/src/main/java/io/kimmking/cache/redission/RedissionDemo1.java @@ -10,8 +10,7 @@ public class RedissionDemo1 { public static void main(String[] args) { Config config = new Config(); - config.useSingleServer().setAddress("redis://127.0.0.1:6380"); - //config.useSingleServer().setPassword(""); + config.useSingleServer().setAddress("redis://127.0.0.1:6379"); final RedissonClient client = Redisson.create(config); RLock lock = client.getLock("lock1"); @@ -22,7 +21,7 @@ public static void main(String[] args) { RMap rmap = client.getMap("map1"); for (int i = 0; i < 15; i++) { - rmap.put("rkey:"+i, "rvalue:1-"+i); + rmap.put("rkey:"+i, "rvalue:22222-"+i); } System.out.println(rmap.get("rkey:10")); diff --git a/09mq/activemq-demo/src/main/java/io/kimmking/javacourse/mq/activemq/ActivemqApplication.java b/09mq/activemq-demo/src/main/java/io/kimmking/javacourse/mq/activemq/ActivemqApplication.java index 75e13283..834f015f 100644 --- a/09mq/activemq-demo/src/main/java/io/kimmking/javacourse/mq/activemq/ActivemqApplication.java +++ b/09mq/activemq-demo/src/main/java/io/kimmking/javacourse/mq/activemq/ActivemqApplication.java @@ -62,7 +62,7 @@ public void onMessage(Message message) { producer.send(message); } - Thread.sleep(2000); + Thread.sleep(20000); session.close(); conn.close(); diff --git a/09mq/kafka-demo/src/main/java/io/kimmking/javacourse/kafka/KafkaConsumerDemo.java b/09mq/kafka-demo/src/main/java/io/kimmking/javacourse/kafka/KafkaConsumerDemo.java index 253074cf..a950facc 100644 --- a/09mq/kafka-demo/src/main/java/io/kimmking/javacourse/kafka/KafkaConsumerDemo.java +++ b/09mq/kafka-demo/src/main/java/io/kimmking/javacourse/kafka/KafkaConsumerDemo.java @@ -1,7 +1,6 @@ package io.kimmking.javacourse.kafka; import io.kimmking.javacourse.kafka.kimmking.ConsumerImpl; -import io.kimmking.javacourse.kafka.kimmking.ProducerImpl; public class KafkaConsumerDemo { diff --git a/09mq/kafka-demo/src/main/java/io/kimmking/javacourse/kafka/KafkaProducerDemo.java b/09mq/kafka-demo/src/main/java/io/kimmking/javacourse/kafka/KafkaProducerDemo.java index 29847ad1..1467492a 100644 --- a/09mq/kafka-demo/src/main/java/io/kimmking/javacourse/kafka/KafkaProducerDemo.java +++ b/09mq/kafka-demo/src/main/java/io/kimmking/javacourse/kafka/KafkaProducerDemo.java @@ -1,6 +1,5 @@ package io.kimmking.javacourse.kafka; -import io.kimmking.javacourse.kafka.kimmking.ConsumerImpl; import io.kimmking.javacourse.kafka.kimmking.ProducerImpl; public class KafkaProducerDemo { diff --git a/09mq/kafka-demo/src/main/resources/log4j.xml b/09mq/kafka-demo/src/main/resources/log4j.xml index 1a35f82b..e7915d2e 100644 --- a/09mq/kafka-demo/src/main/resources/log4j.xml +++ b/09mq/kafka-demo/src/main/resources/log4j.xml @@ -1,22 +1,23 @@ - - - + + + - - - - - + + + + + + - - - - + + + + + - - - - + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/09mq/pulsar/src/main/java/io/kimmking/mq/pulsar/ProducerDemo.java b/09mq/pulsar/src/main/java/io/kimmking/mq/pulsar/ProducerDemo.java index 3e082358..9c1c6bf4 100644 --- a/09mq/pulsar/src/main/java/io/kimmking/mq/pulsar/ProducerDemo.java +++ b/09mq/pulsar/src/main/java/io/kimmking/mq/pulsar/ProducerDemo.java @@ -17,7 +17,7 @@ public ProducerDemo(){ } @SneakyThrows - public void sendMsg() { + public void sendMessage() { for (int i = 0; i < 1000; i++) { stringProducer.send(i + " message from pulsar."); } diff --git a/09mq/pulsar/src/main/java/io/kimmking/mq/pulsar/PulsarApplication.java b/09mq/pulsar/src/main/java/io/kimmking/mq/pulsar/PulsarApplication.java index feeb09d4..89938c6a 100644 --- a/09mq/pulsar/src/main/java/io/kimmking/mq/pulsar/PulsarApplication.java +++ b/09mq/pulsar/src/main/java/io/kimmking/mq/pulsar/PulsarApplication.java @@ -27,7 +27,7 @@ ApplicationRunner run() { consumer.consume(); }).start(); - producer.sendMsg(); + producer.sendMessage(); }; } diff --git a/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MsgProducer.java b/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MessageProducer.java similarity index 80% rename from 09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MsgProducer.java rename to 09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MessageProducer.java index 29acddee..2480046b 100644 --- a/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MsgProducer.java +++ b/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MessageProducer.java @@ -10,7 +10,7 @@ @Component @Slf4j -public class MsgProducer implements RabbitTemplate.ConfirmCallback { +public class MessageProducer implements RabbitTemplate.ConfirmCallback { //由于rabbitTemplate的scope属性设置为ConfigurableBeanFactory.SCOPE_PROTOTYPE,所以不能自动注入 private RabbitTemplate rabbitTemplate; @@ -18,12 +18,12 @@ public class MsgProducer implements RabbitTemplate.ConfirmCallback { * 构造方法注入rabbitTemplate */ @Autowired - public MsgProducer(RabbitTemplate rabbitTemplate) { + public MessageProducer(RabbitTemplate rabbitTemplate) { this.rabbitTemplate = rabbitTemplate; rabbitTemplate.setConfirmCallback(this); //rabbitTemplate如果为单例的话,那回调就是最后设置的内容 } - public void sendMsg(String content) { + public void sendMessage(String content) { CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString()); //把消息放入ROUTINGKEY_A对应的队列当中去,对应的是队列A rabbitTemplate.convertAndSend(RabbitConfig.EXCHANGE_A, RabbitConfig.ROUTINGKEY_B, content, correlationId); @@ -35,9 +35,9 @@ public void sendMsg(String content) { public void confirm(CorrelationData correlationData, boolean ack, String cause) { log.info(" 回调id:" + correlationData); if (ack) { - log.info("消息成功消费"); + log.info("消息成功消费!!!!!" + correlationData); } else { - log.info("消息消费失败:" + cause); + log.info("消息消费失败:" + cause + correlationData); } } } \ No newline at end of file diff --git a/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MsgReceiverA.java b/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MessageReceiverA.java similarity index 86% rename from 09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MsgReceiverA.java rename to 09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MessageReceiverA.java index 798add99..6cea0d3a 100644 --- a/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MsgReceiverA.java +++ b/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MessageReceiverA.java @@ -8,7 +8,7 @@ @Component @RabbitListener(queues = RabbitConfig.QUEUE_A) @Slf4j -public class MsgReceiverA { //guava , EventBus 的一些语法糖 +public class MessageReceiverA { //guava , EventBus 的一些语法糖 @RabbitHandler public void process(String content) { diff --git a/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MsgReceiverB.java b/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MessageReceiverB.java similarity index 93% rename from 09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MsgReceiverB.java rename to 09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MessageReceiverB.java index be962f7e..7b0e81db 100644 --- a/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MsgReceiverB.java +++ b/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/MessageReceiverB.java @@ -8,7 +8,7 @@ @Component @RabbitListener(queues = RabbitConfig.QUEUE_B) @Slf4j -public class MsgReceiverB { +public class MessageReceiverB { @RabbitHandler public void process(String content) { diff --git a/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/RabbitApplication.java b/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/RabbitApplication.java index 4357ddb5..787c57a3 100644 --- a/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/RabbitApplication.java +++ b/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/RabbitApplication.java @@ -14,13 +14,13 @@ public static void main(String[] args) { } @Autowired - MsgProducer producer; + MessageProducer producer; @Bean ApplicationRunner run() { return args -> { for (int i = 0; i < 1000; i++) { - producer.sendMsg(i+" message."); + producer.sendMessage(i+" message by cuicuilaoshi."); } }; } diff --git a/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/RabbitConfig.java b/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/RabbitConfig.java index 9f3b0b53..440db166 100644 --- a/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/RabbitConfig.java +++ b/09mq/rabbit/src/main/java/io/kimmking/mq/rabbit/RabbitConfig.java @@ -90,7 +90,7 @@ public Queue queueC() { @Bean public Binding bindingA() { - return BindingBuilder.bind(queueA()).to(defaultExchange()).with(RabbitConfig.ROUTINGKEY_B); + return BindingBuilder.bind(queueA()).to(defaultExchange()).with(RabbitConfig.ROUTINGKEY_A); } @Bean public Binding bindingB() { diff --git a/09mq/rocket/src/main/java/io/kimmking/mq/rocket/OrderConsumerDemo.java b/09mq/rocket/src/main/java/io/kimmking/mq/rocket/OrderConsumerDemo.java index 2a87dded..2c4ba4ed 100644 --- a/09mq/rocket/src/main/java/io/kimmking/mq/rocket/OrderConsumerDemo.java +++ b/09mq/rocket/src/main/java/io/kimmking/mq/rocket/OrderConsumerDemo.java @@ -1,5 +1,6 @@ package io.kimmking.mq.rocket; +import org.apache.rocketmq.spring.annotation.ConsumeMode; import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; import org.apache.rocketmq.spring.core.RocketMQReplyListener; import org.springframework.stereotype.Component; @@ -9,7 +10,7 @@ public class OrderConsumerDemo implements RocketMQReplyListener { @Override - public String onMessage(Order order) { + public String onMessage(Order order) { // request-response System.out.println(this.getClass().getName() + " -> " + order); return "Process&Return [" + order + "]."; } diff --git a/09mq/rocket/src/main/java/io/kimmking/mq/rocket/RocketApplication.java b/09mq/rocket/src/main/java/io/kimmking/mq/rocket/RocketApplication.java index 8f20ecf5..13d6c89c 100644 --- a/09mq/rocket/src/main/java/io/kimmking/mq/rocket/RocketApplication.java +++ b/09mq/rocket/src/main/java/io/kimmking/mq/rocket/RocketApplication.java @@ -37,18 +37,22 @@ public void run(String... args) throws Exception { System.out.printf("syncSend1 to topic %s sendResult=%s %n", topic, sendResult); String topic1 = "test-k2"; - rocketMQTemplate.asyncSend(topic1, new Order(System.currentTimeMillis(),"CNY2USD", 0.1502d), new SendCallback() { - @Override - public void onSuccess(SendResult result) { - System.out.printf("async onSucess SendResult=%s %n", result); - } - - @Override - public void onException(Throwable throwable) { - System.out.printf("async onException Throwable=%s %n", throwable); - } - - }); + + String result = rocketMQTemplate.sendAndReceive(topic1, new Order(System.currentTimeMillis(),"CNY2USD", 0.1502d), String.class); + System.out.println(" consumer result => " + result); + +// rocketMQTemplate.asyncSend(topic1, new Order(System.currentTimeMillis(),"CNY2USD", 0.1502d), new SendCallback() { +// @Override +// public void onSuccess(SendResult result) { +// System.out.printf("async onSucess SendResult=%s %n", result); +// } +// +// @Override +// public void onException(Throwable throwable) { +// System.out.printf("async onException Throwable=%s %n", throwable); +// } +// +// }); } diff --git a/09mq/rocket/src/main/java/io/kimmking/mq/rocket/StringConsumerDemo.java b/09mq/rocket/src/main/java/io/kimmking/mq/rocket/StringConsumerDemo.java index 5984beeb..f2534bdb 100644 --- a/09mq/rocket/src/main/java/io/kimmking/mq/rocket/StringConsumerDemo.java +++ b/09mq/rocket/src/main/java/io/kimmking/mq/rocket/StringConsumerDemo.java @@ -9,7 +9,7 @@ public class StringConsumerDemo implements RocketMQListener { @Override - public void onMessage(String message) { + public void onMessage(String message) { // one way System.out.println(this.getClass().getName() + " -> " + message); } } diff --git a/README.md b/README.md index e6a677d6..252447c6 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,14 @@ # JavaCourse -JavaCourse +Java进阶训练营示例代码。此处代码,一方面作为作业的基本版本,另一方面需要大家通过调整加深自己对技术点的认识。 + +本课程的三个要素: + +1)40%是课程,包括预习、听课、复习总结,形成自己对知识体系的认识和经验,这是最基本的学习方法。 + +2)30%是作业,作业包括基础版本的必做作业,补充的选做作业,高难度的挑战作业。基本上完成必做可以通过P6的技术面试,完成选做可以通过P7的技术面试,高难度的话可以达到P7+/P8的技术面试水平。这是通过练习,得到第一手的体验。 + +3)30%是活动,包括且不限于源码分析学习小组,技术文章活动,读书活动,线下技术沙龙,线上技术分享等。通过一群愿意学习的人,在更好的学习氛围中,实现长期深入学习。 + +## 挑战作业 + +每个模块的挑战作业:[homework2.0.md](./homework2.0.md) , 能做出来70%的题目,直接联系我,给你推荐一线大厂工作。 \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 00000000..549e00a2 --- /dev/null +++ b/app/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### 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/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/app/.mvn/wrapper/MavenWrapperDownloader.java b/app/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 00000000..a45eb6ba --- /dev/null +++ b/app/.mvn/wrapper/MavenWrapperDownloader.java @@ -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(); + } + +} diff --git a/app/.mvn/wrapper/maven-wrapper.jar b/app/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 00000000..2cc7d4a5 Binary files /dev/null and b/app/.mvn/wrapper/maven-wrapper.jar differ diff --git a/app/.mvn/wrapper/maven-wrapper.properties b/app/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 00000000..642d572c --- /dev/null +++ b/app/.mvn/wrapper/maven-wrapper.properties @@ -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 diff --git a/app/mvnw b/app/mvnw new file mode 100755 index 00000000..a16b5431 --- /dev/null +++ b/app/mvnw @@ -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 "$@" diff --git a/app/mvnw.cmd b/app/mvnw.cmd new file mode 100644 index 00000000..c8d43372 --- /dev/null +++ b/app/mvnw.cmd @@ -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% diff --git a/app/pom.xml b/app/pom.xml new file mode 100644 index 00000000..3d06aa6c --- /dev/null +++ b/app/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.4.4 + + + com.example + app + 0.0.1-SNAPSHOT + app + Demo project for Spring Boot + + 1.8 + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/app/src/main/java/com/example/app/App.java b/app/src/main/java/com/example/app/App.java new file mode 100644 index 00000000..bcd641a1 --- /dev/null +++ b/app/src/main/java/com/example/app/App.java @@ -0,0 +1,26 @@ +package com.example.app; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; + +@SpringBootApplication +public class App { + + public static void main(String[] args) { + SpringApplication.run(App.class, args); + } + + + + // ==== 测试自动配置 ==== + @Autowired + WebInfo info; + + @Bean + public void printInfo(){ + System.out.println(info.getName()); + } + +} diff --git a/app/src/main/java/com/example/app/WebAutoConfiguration.java b/app/src/main/java/com/example/app/WebAutoConfiguration.java new file mode 100644 index 00000000..e63d295f --- /dev/null +++ b/app/src/main/java/com/example/app/WebAutoConfiguration.java @@ -0,0 +1,25 @@ +package com.example.app; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +@Configuration +@Import(WebConfiguration.class) +@EnableConfigurationProperties(WebProperties.class) +public class WebAutoConfiguration { + + @Autowired + WebProperties properties; + + @Autowired + WebConfiguration configuration; + + @Bean + public WebInfo creatInfo(){ + return new WebInfo(configuration.name + "-"+properties.getA()); + } + +} diff --git a/app/src/main/java/com/example/app/WebConfiguration.java b/app/src/main/java/com/example/app/WebConfiguration.java new file mode 100644 index 00000000..d645d77b --- /dev/null +++ b/app/src/main/java/com/example/app/WebConfiguration.java @@ -0,0 +1,10 @@ +package com.example.app; + +import org.springframework.context.annotation.Configuration; + +@Configuration +public class WebConfiguration { + + public String name = "java"; + +} diff --git a/app/src/main/java/com/example/app/WebInfo.java b/app/src/main/java/com/example/app/WebInfo.java new file mode 100644 index 00000000..5fd4345b --- /dev/null +++ b/app/src/main/java/com/example/app/WebInfo.java @@ -0,0 +1,19 @@ +package com.example.app; + +public class WebInfo { + + public WebInfo(String name) { + this.name = name; + } + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/app/src/main/java/com/example/app/WebProperties.java b/app/src/main/java/com/example/app/WebProperties.java new file mode 100644 index 00000000..713fbeed --- /dev/null +++ b/app/src/main/java/com/example/app/WebProperties.java @@ -0,0 +1,17 @@ +package com.example.app; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties(prefix = "web") +public class WebProperties { + + private String a = "aaa"; + + public String getA() { + return a; + } + + public void setA(String a) { + this.a = a; + } +} diff --git a/app/src/main/resources/META-INF/spring.factories b/app/src/main/resources/META-INF/spring.factories new file mode 100644 index 00000000..e69de29b diff --git a/app/src/main/resources/application.properties b/app/src/main/resources/application.properties new file mode 100644 index 00000000..5167366f --- /dev/null +++ b/app/src/main/resources/application.properties @@ -0,0 +1 @@ +web.a=kimmking diff --git a/app/src/test/java/com/example/app/AppApplicationTests.java b/app/src/test/java/com/example/app/AppApplicationTests.java new file mode 100644 index 00000000..a9afa13c --- /dev/null +++ b/app/src/test/java/com/example/app/AppApplicationTests.java @@ -0,0 +1,13 @@ +package com.example.app; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class AppApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/demo/.gitignore b/demo/.gitignore new file mode 100644 index 00000000..549e00a2 --- /dev/null +++ b/demo/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### 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/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/demo/.mvn/wrapper/MavenWrapperDownloader.java b/demo/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 00000000..e76d1f32 --- /dev/null +++ b/demo/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,117 @@ +/* + * 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(); + } + +} diff --git a/demo/.mvn/wrapper/maven-wrapper.jar b/demo/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 00000000..2cc7d4a5 Binary files /dev/null and b/demo/.mvn/wrapper/maven-wrapper.jar differ diff --git a/demo/.mvn/wrapper/maven-wrapper.properties b/demo/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 00000000..642d572c --- /dev/null +++ b/demo/.mvn/wrapper/maven-wrapper.properties @@ -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 diff --git a/demo/mvnw b/demo/mvnw new file mode 100755 index 00000000..a16b5431 --- /dev/null +++ b/demo/mvnw @@ -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 "$@" diff --git a/demo/mvnw.cmd b/demo/mvnw.cmd new file mode 100644 index 00000000..c8d43372 --- /dev/null +++ b/demo/mvnw.cmd @@ -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% diff --git a/demo/pom.xml b/demo/pom.xml new file mode 100644 index 00000000..52076da9 --- /dev/null +++ b/demo/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.4.4 + + + com.example + demo + 0.0.1-SNAPSHOT + demo + Demo project for Spring Boot + + 1.8 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/demo/src/main/java/com/example/demo/DemoApplication.java b/demo/src/main/java/com/example/demo/DemoApplication.java new file mode 100644 index 00000000..64b538a1 --- /dev/null +++ b/demo/src/main/java/com/example/demo/DemoApplication.java @@ -0,0 +1,13 @@ +package com.example.demo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DemoApplication { + + public static void main(String[] args) { + SpringApplication.run(DemoApplication.class, args); + } + +} diff --git a/demo/src/main/java/com/example/demo/controller/DemoController.java b/demo/src/main/java/com/example/demo/controller/DemoController.java new file mode 100644 index 00000000..10cac5a7 --- /dev/null +++ b/demo/src/main/java/com/example/demo/controller/DemoController.java @@ -0,0 +1,17 @@ +package com.example.demo.controller; + +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +@EnableAutoConfiguration +@RequestMapping("/demo") +public class DemoController { + + @RequestMapping("/hello") + public String hello() { + return "KK-" + System.currentTimeMillis(); + } + +} diff --git a/demo/src/main/java/com/example/demo/controller/UserController.java b/demo/src/main/java/com/example/demo/controller/UserController.java new file mode 100644 index 00000000..6a9e87f9 --- /dev/null +++ b/demo/src/main/java/com/example/demo/controller/UserController.java @@ -0,0 +1,17 @@ +package com.example.demo.controller; + +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +@EnableAutoConfiguration +@RequestMapping("/user") +public class UserController { + + @RequestMapping("/list") + public String list() { + return "KK-" + System.currentTimeMillis(); + } + +} diff --git a/demo/src/main/resources/application.yml b/demo/src/main/resources/application.yml new file mode 100644 index 00000000..a7afc92b --- /dev/null +++ b/demo/src/main/resources/application.yml @@ -0,0 +1,2 @@ +server: + port: 8080 diff --git a/demo/src/test/java/com/example/demo/DemoApplicationTests.java b/demo/src/test/java/com/example/demo/DemoApplicationTests.java new file mode 100644 index 00000000..2778a6a7 --- /dev/null +++ b/demo/src/test/java/com/example/demo/DemoApplicationTests.java @@ -0,0 +1,13 @@ +package com.example.demo; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class DemoApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/demoidea/.gitignore b/demoidea/.gitignore new file mode 100644 index 00000000..549e00a2 --- /dev/null +++ b/demoidea/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### 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/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/demoidea/.mvn/wrapper/MavenWrapperDownloader.java b/demoidea/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 00000000..a45eb6ba --- /dev/null +++ b/demoidea/.mvn/wrapper/MavenWrapperDownloader.java @@ -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(); + } + +} diff --git a/demoidea/.mvn/wrapper/maven-wrapper.jar b/demoidea/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 00000000..2cc7d4a5 Binary files /dev/null and b/demoidea/.mvn/wrapper/maven-wrapper.jar differ diff --git a/demoidea/.mvn/wrapper/maven-wrapper.properties b/demoidea/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 00000000..642d572c --- /dev/null +++ b/demoidea/.mvn/wrapper/maven-wrapper.properties @@ -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 diff --git a/demoidea/mvnw b/demoidea/mvnw new file mode 100755 index 00000000..a16b5431 --- /dev/null +++ b/demoidea/mvnw @@ -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 "$@" diff --git a/demoidea/mvnw.cmd b/demoidea/mvnw.cmd new file mode 100644 index 00000000..c8d43372 --- /dev/null +++ b/demoidea/mvnw.cmd @@ -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% diff --git a/demoidea/pom.xml b/demoidea/pom.xml new file mode 100644 index 00000000..4ca50254 --- /dev/null +++ b/demoidea/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.4.4 + + + io.github.kimmking + demoidea + 0.0.1-SNAPSHOT + demoidea + Demo project for Spring Boot + + 1.8 + + + + org.springframework.boot + spring-boot-starter-activemq + + + org.springframework.boot + spring-boot-starter-data-jdbc + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/demoidea/src/main/java/io/github/kimmking/demoidea/DemoideaApplication.java b/demoidea/src/main/java/io/github/kimmking/demoidea/DemoideaApplication.java new file mode 100644 index 00000000..ba5c61cf --- /dev/null +++ b/demoidea/src/main/java/io/github/kimmking/demoidea/DemoideaApplication.java @@ -0,0 +1,13 @@ +package io.github.kimmking.demoidea; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DemoideaApplication { + + public static void main(String[] args) { + SpringApplication.run(DemoideaApplication.class, args); + } + +} diff --git a/demoidea/src/main/resources/application.properties b/demoidea/src/main/resources/application.properties new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/demoidea/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/demoidea/src/test/java/io/github/kimmking/demoidea/DemoideaApplicationTests.java b/demoidea/src/test/java/io/github/kimmking/demoidea/DemoideaApplicationTests.java new file mode 100644 index 00000000..428c4548 --- /dev/null +++ b/demoidea/src/test/java/io/github/kimmking/demoidea/DemoideaApplicationTests.java @@ -0,0 +1,13 @@ +package io.github.kimmking.demoidea; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class DemoideaApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/homework2.0.md b/homework2.0.md index 0077b243..ab6193f2 100644 --- a/homework2.0.md +++ b/homework2.0.md @@ -31,19 +31,167 @@ #### 3.2-侧重应用: -1. 10-根据课程提供的场景,实现一个订单处理Service,模拟处理100万订单:后面提供模拟数据。 +1. 10-根据课程提供的场景,实现一个订单处理Service,模拟处理100万订单:后面提供模拟数据 2. 20-使用多线程方法优化订单处理,对比处理性能 3. 30-使用并发工具和集合类改进订单Service,对比处理性能 -4. 30-使用分布式集群+分库分表方式处理拆分订单,对比处理性能:第6模块讲解分库分表。 -5. 30-使用读写分离和分布式缓存优化订单的读性能:第6、8模块讲解读写分离和缓存。 +4. 30-使用分布式集群+分库分表方式处理拆分订单,对比处理性能:第6模块讲解分库分表 +5. 30-使用读写分离和分布式缓存优化订单的读性能:第6、8模块讲解读写分离和缓存 ### 4. 框架 #### 4.1 Spring AOP -1. 10-讲网关的frontend/backend/filter/router/线程池都改造成Spring配置方式; -2. 20-基于AOP改造Netty网关,filter和router使用AOP方式实现; -3. 30-基于前述改造,将网关请求前后端分离,中级使用JMS传递消息; -4. 30-尝试使用ByteBuddy实现一个简单的基于类的AOP; -5. 30-尝试使用ByteBuddy与Instrument实现一个简单JavaAgent实现无侵入下的AOP; +1. 10-讲网关的frontend/backend/filter/router/线程池都改造成Spring配置方式 +2. 20-基于AOP改造Netty网关,filter和router使用AOP方式实现 +3. 30-基于前述改造,将网关请求前后端分离,中级使用JMS传递消息 +4. 30-尝试使用ByteBuddy实现一个简单的基于类的AOP +5. 30-尝试使用ByteBuddy与Instrument实现一个简单JavaAgent实现无侵入下的AOP +#### 4.2 Spring ORM + +1. 基于AOP和自定义注解,实现@MyCache(60)对于指定方法返回值缓存60秒 +2. 自定义实现一个数据库连接池,并整合Hibernate/Mybatis/Spring/SpringBoot +3. 基于MyBatis实现一个简单的分库分表+读写分离+分布式ID生成方案 + +### 5. 数据库与性能 + +1. 模拟1000万订单数据,测试不同方式下导入导出(数据备份还原)MySQL的速度,包括jdbc程序处理和命令行处理,思考和实践,如何提升处理效率 +2. 对MySQL配置不同的数据库连接池(DBCP、C3P0、Druid、Hikari),测试增删改查100万次,对比性能,生成报告 +3. 尝试自己做一个ID生成器(可以模拟Seq或Snowflake) +4. 尝试实现或改造一个非精确分页的组件,思考是否可以用于改造自己的业务系统 +5. 基于必做作业2.0版本,实现读写分离-数据库中间件版本3.0 + +### 6. 分库分表 + +1. 思考总结常用的数据拆分和数据迁移同步方案,以及它们的优势劣势,适用场景,考虑是否可以引入到自己的工作中 +2. 设计实现一个简单的XA分布式事务框架demo,只需要能管理和调用2个MySQL的本地事务即可,不需要考虑全局事务的持久化和恢复、高可用等 +3. 设计实现一个TCC分布式事务框架的简单Demo,需要实现事务管理器,不需要实现全局事务的持久化和恢复、高可用等 +4. 设计实现一个AT分布式事务框架的简单Demo,仅需要支持根据主键id进行的单个删改操作的SQL或插入操作的事务 + +### 7. RPC与分布式服务化 + +#### 7.1 RPC与Dubbo + +1. 升级作业中的自定义RPC程序: +- 尝试使用压测并分析优化RPC性能 +- 尝试使用Netty+TCP作为两端传输方式 +- 尝试自定义二进制序列化或者使用kyro/fst等 +- 尝试压测改进后的RPC并分析优化,有问题欢迎群里讨论 +- 尝试将fastjson改成xstream +- 尝试使用字节码生成方式代替服务端反射 + +2. 尝试扩展Dubbo +- 基于上次作业的自定义序列化,实现Dubbo的序列化扩展; +- 基于上次作业的自定义RPC,实现Dubbo的RPC扩展; +- 在Dubbo的filter机制上,实现REST权限控制,可参考dubbox; +- 实现自定义Dubbo的Cluster/Loadbalance扩展,如果一分钟内调用某个服务/提供者超过10次,则拒绝提供服务直到下一分钟; +- 整合Dubbo+Sentinel,实现限流功能; +- 整合Dubbo与Skywalking,实现全链路性能监控。 + +#### 7.2 自定义RPC + +1. rpcfx1.1: 给自定义RPC实现简单的分组(group)和版本(version)。 + +2. rpcfx2.0: 给自定义RPC实现: + - 基于zookeeper的注册中心,消费者和生产者可以根据注册中心查找可用服务进行调用(直接选择列表里的最后一个)。 + - 当有生产者启动或者下线时,通过zookeeper通知并更新各个消费者,使得各个消费者可以调用新生产者或者不调用下线生产者。 + +3. 在2.0的基础上继续增强rpcfx实现: +- 3.0: 实现基于zookeeper的配置中心,消费者和生产者可以根据配置中心配置参数(分组,版本,线程池大小等)。 +- 3.1:实现基于zookeeper的元数据中心,将服务描述元数据保存到元数据中心。 +- 3.2:实现基于etcd/nacos/apollo等基座的配置/注册/元数据中心。 + +4. 在3.2的基础上继续增强rpcfx实现: +- 4.0:实现基于tag的简单路由; +- 4.1:实现基于Weight/ConsistentHash的负载均衡; +- 4.2:实现基于IP黑名单的简单流控; +- 4.3:完善RPC框架里的超时处理,增加重试参数; + +5. 在4.3的基础上继续增强rpcfx实现: +- 5.0:实现利用HTTP头跨进程传递Context参数(隐式传参); +- 5.1:实现消费端mock一个指定对象的功能(Mock功能); +- 5.2:实现消费端可以通过一个泛化接口调用不同服务(泛化调用); +- 5.3:实现基于Weight/ConsistentHash的负载均衡; +- 5.4:实现基于单位时间调用次数的流控,可以基于令牌桶等算法; + +6. 实现最终版本6.0:压测并分析调优5.4版本。 + +### 8. 分布式缓存 + +1. 基于其他各类场景,设计并在示例代码中实现简单demo: +- 实现分数排名或者排行榜; +- 实现全局ID生成; +- 基于Bitmap实现id去重; +- 基于HLL实现点击量计数。 +- 以redis作为数据库,模拟使用lua脚本实现前面课程的外汇交易事务。 + +2. 升级改造项目: +- 实现guava cache的spring cache适配; +- 替换jackson序列化为fastjson或者fst,kryo; +- 对项目进行分析和性能调优。 + +3. 以redis作为基础实现上个模块的自定义rpc的注册中心; +4. 练习redission的各种功能; +5. 练习hazelcast的各种功能; +6. 搭建hazelcast 3节点集群,写入100万数据到一个map,模拟和演示高可用,测试一下性能。 + +### 9. 分布式消息 + +#### 9.1 消息队列原理与应用 + +1. 基于数据库的订单表,模拟消息队列处理订单: +- 一个程序往表里写新订单,标记状态为未处理(status=0); +- 另一个程序每隔100ms定时从表里读取所有status=0的订单,打印一下订单数据,然后改成完成status=1; +- 考虑失败重试策略,考虑多个消费程序如何协作; +- 将上述订单处理场景,改成使用ActiveMQ发送消息处理模式; +- 使用java代码,创建一个ActiveMQ Broker Server,并测试它; + +2. ActiveMQ/RabbitMQ作业 +- 搭建ActiveMQ的network集群和master-slave主从结构; +- 基于ActiveMQ的MQTT实现简单的聊天功能或者Android消息推送; +- 创建一个RabbitMQ,用Java代码实现简单的AMQP协议操作; +- 搭建RabbitMQ集群,重新实现前面的订单处理; +- 使用Apache Camel打通上述ActiveMQ集群和RabbitMQ集群,实现所有写入到ActiveMQ上的一个队列q24的消息,自动转发到RabbitMQ; +- 压测ActiveMQ和RabbitMQ的性能; + +3. 演练本课提及的各种生产者和消费者特性。 + +4. Kafka金融领域实战:在证券或者外汇、数字货币类金融核心交易系统里,对于订单的处理,大概可以分为收单、定序、撮合、清算等步骤。其中我们一般可以用mq来实现订单定序,然后将订单发送给撮合模块。 +- 收单:请实现一个订单的rest接口,能够接收一个订单Order对象; +- 定序:将Order对象写入到kafka集群的order.usd2cny队列,要求数据有序并且不丢失; +- 撮合:模拟撮合程序(不需要实现撮合逻辑),从kafka获取order数据,并打印订单信息,要求可重放, 顺序消费, 消息仅处理一次。 + +#### 9.2 自定义消息中间件 + +1. v1.0-内存队列:基于内存Queue实现生产和消费API(示例代码已经完成) +- 创建内存BlockingQueue,作为底层消息存储 +- 定义Topic,支持多个Topic +- 定义Producer,支持Send消息 +- 定义Consumer,支持Poll消息 + +2. v2.0-自定义队列:去掉内存Queue,设计自定义Queue,实现消息确认和消费offset +- 自定义内存Message数组模拟Queue。 +- 使用指针记录当前消息写入位置。 +- 对于每个命名消费者,用指针记录消费位置。 + +3. v3.0-基于SpringMVC实现MQServer:拆分broker和client(包括producer和consumer),从单机走向服务器模式。 +- 将Queue保存到web server端 +- 设计消息读写API接口,确认接口,提交offset接口 +- producer和consumer通过httpclient访问Queue +- 实现消息确认,offset提交 +- 实现consumer从offset增量拉取 + +4. v4.0-功能全面:增加多种策略(各条之间没有关系,可以任意选择实现),基于TCP实现server->client,从而实现 PUSH模式 +- 考虑实现消息过期,消息重试,消息定时投递等策略 +- 考虑批量操作,包括读写,可以打包和压缩 +- 考虑消息清理策略,包括定时清理,按容量清理、LRU等 +- 考虑消息持久化,存入数据库,或WAL日志文件,或BookKeeper +- 考虑将spring mvc替换成netty下的tcp传输协议,rsocket/websocket + +5. v5.0-优化完善:对接各种技术(各条之间没有关系,可以任意选择实现) +- 考虑封装 JMS 1.1 接口规范 +- 考虑实现 STOMP 消息规范 +- 考虑实现消息事务机制与事务管理器 +- 对接Spring +- 对接Camel或Spring Integration +- 优化内存和磁盘的使用