简单构建java demo应用程序包


发布于 2019-08-11 / 40 阅读 / 0 评论 /
学习Java Demo应用源码结构,快速入门Java应用打包

在ToB场景中,常常需要写一些demo,来完成某些测试或者说调试工作。

为了简化大家输出demo应用程序包的成本,我们在这里简单总结了一个Demo应用程序。

在我们需要的时候,只需要替换某些参数即可使用。

1.Demo结构

Demo结构如下图所示:

有五个部分:

(1)bin目录下的启动和停止脚本

(2)assemblies中定义assembly插件对tar包配置

(3)java目录下的业务逻辑源码

(4)resources目录下的配置文件,比如日志配置文件。

(5)pom.xml中定义的依赖项。

2.pom.xml文件定义

我们这里使用maven构建工具。

pom.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>hdfs-client-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <hadoop.version>2.3.0</hadoop.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <assembly.path>src/main/assemblies/hdfs-client-demo-assembly.xml</assembly.path>
        <slf4j.version>1.7.36</slf4j.version>
        <logback.version>1.2.11</logback.version>
    </properties>

    <dependencies>

        <!-- 业务依赖项,可随意替换 -->
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>${hadoop.version}</version>
        </dependency>

        <!-- slf4j -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>

        <!-- logback -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>${logback.version}</version>
        </dependency>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-access</artifactId>
            <version>${logback.version}</version>
        </dependency>

    </dependencies>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.1</version>
                    <configuration>
                        <source>${maven.compiler.source}</source>
                        <target>${maven.compiler.target}</target>
                        <encoding>${project.build.sourceEncoding}</encoding>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-dependency-plugin</artifactId>
                    <version>3.1.2</version>
                    <executions>
                        <execution>
                            <id>mvn-dependencies</id>
                            <phase>package</phase>
                            <goals>
                                <goal>copy-dependencies</goal>
                            </goals>
                            <configuration>
                                <outputDirectory>target/dependency</outputDirectory>
                                <overWriteSnapshots>true</overWriteSnapshots>
                                <includeScope>runtime</includeScope>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-assembly-plugin</artifactId>
                    <version>3.2.0</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>single</goal>
                            </goals>
                            <phase>package</phase>
                            <configuration>
                                <skipAssembly>false</skipAssembly>
                                <descriptors>
                                    <descriptor>${assembly.path}</descriptor>
                                </descriptors>
                                <finalName>hdfs-client-demo-${project.version}</finalName>
                                <appendAssemblyId>false</appendAssemblyId>
                                <outputDirectory>./target</outputDirectory>
                                <!--macOS: posix, linux: gnu-->
                                <tarLongFileMode>posix</tarLongFileMode>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>3.2.0</version>
                    <configuration>
                        <excludes>
                            <exclude>*.yml</exclude>
                            <exclude>*.properties</exclude>
                            <exclude>*.txt</exclude>
                            <exclude>*.xml</exclude>
                            <exclude>*.json</exclude>
                            <exclude>*.dtd</exclude>
                            <exclude>*.sh</exclude>
                            <exclude>conf/**</exclude>
                        </excludes>
                    </configuration>
                    <executions>
                        <execution>
                            <!--使用plugin生成的jar包-->
                            <id>default-jar</id>
                            <phase>package</phase>
                            <goals>
                                <goal>jar</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <profile>
            <id>assembly</id>
            <activation>
                <activeByDefault>false</activeByDefault>
            </activation>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-assembly-plugin</artifactId>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>

</project>

这里包名为hdfs-client-demo,需根据自己应用名称替换。

3.java目录下的源码

这里可随意创建自己的demo类。

4.resources配置文件目录

我们把配置文件放到resources目录下,最简单的就是一个logback.xml文件,内容如下:

<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <property name="log_dir" value="logs"/>
    <property name="log_pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %p %C.%M [%t] [line:%L]- %m%n"/>
    <property name="maxHistory" value="7"/>

    <timestamp key="bySecond" datePattern="yyyyMMddHHmmss"/>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>debug</level>
        </filter>
        <encoder>
            <pattern>${log_pattern}</pattern>
        </encoder>
    </appender>

    <appender name="DEBUG-APPENDER" class="ch.qos.logback.core.FileAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>DEBUG</level>
        </filter>
        <file>${log_dir}/debug-log.${bySecond}.log</file>
        <encoder>
            <pattern>${log_pattern}</pattern>
        </encoder>
        <append>false</append>
    </appender>
<!--    <logger name="org.apache.kafka.clients" level="OFF"></logger>-->

    <root>
        <level value="DEBUG"/>
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="DEBUG-APPENDER"/>
    </root>
</configuration>

如果要禁止某种日志的输出,将对应logger的level置为OFF即可。

5.bin目录下的运维脚本

主要包括start.sh和stop.sh,用于启动和停止demo应用。

start.sh脚本内容如下:

#!/bin/bash

source /etc/profile >/dev/null 2>&1

BIN_DIR=$(cd "$(dirname "$0")" && pwd)
cd "${BIN_DIR}" && cd ..
WORKSPACE=$(pwd)

if [ -z "${MAIN_CLASS}" ]; then
  MAIN_CLASS=example.hadoop.HDFSClientDemo
fi

pid=$(ps aux | grep "${MAIN_CLASS}" | grep -v grep | awk '{print $2}')
if [[ "$pid" != "" ]]; then
  echo "Process (PID = $pid) is already running."
  exit 0
fi

if [ -n "${JAVA_HOME}" ]; then
  if [[ "${JAVA_HOME}" =~ /$ ]]; then
    JAVA=${JAVA_HOME}bin/java
  else
    JAVA=${JAVA_HOME}/bin/java
  fi

elif [ -n "$(which java)" ]; then
  JAVA=$(which java)
fi
if [ -z "${JAVA}" ]; then
  echo "ERROR: could found java"
  exit 1
fi

if [ -z "${CONFIG_DIR}" ]; then
  CONFIG_DIR="${WORKSPACE}/conf"
fi

CLASSPATH=${WORKSPACE}/lib/*:${WORKSPACE}/conf/:/etc/hadoop/conf/

if [ -z "${MEM_SIZE}" ]; then
  MEM_SIZE=4G
fi
MEMORY_OPTS="-Xms${MEM_SIZE} -Xmx${MEM_SIZE}"
if [ -z "${GC_OPTS}" ]; then
  GC_OPTS="-XX:+UseG1GC"
fi

LOG_DIR=${WORKSPACE}/logs
GC_LOG_DIR=${WORKSPACE}/logs/gc
mkdir -p ${LOG_DIR} ${GC_LOG_DIR}

export JAVA_OPTS="${MEMORY_OPTS} ${GC_OPTS} ${JMX_OPTS}"

echo "Starting Server..."

${JAVA} \
  ${JAVA_OPTS} \
  -Dlogback.configuration=${CONFIG_DIR}/logback.xml \
  -XX:+HeapDumpOnOutOfMemoryError \
  -XX:HeapDumpPath=${WORKSPACE}/heap-dump.hprof \
  -XX:OnOutOfMemoryError="\"kill -9 %p\"" \
  -XX:NumberOfGCLogFiles=10 \
  -XX:GCLogFileSize=50M \
  -XX:+PrintGCDetails \
  -XX:+PrintGCDateStamps \
  -Xloggc:${GC_LOG_DIR}/gc-%t.log \
  -cp ${CLASSPATH} \
  ${MAIN_CLASS} "$@" >/dev/null 2>&1 &

server_pid=$!
echo "start hdfs-client-demo successfully, pid is ${server_pid}"

stop.sh脚本比较简单,找到PID,直接kill即可。

6.打包配置文件

这里指的是maven-assembly-plugin插件需要用到的assembly配置文件。如下所示:

<?xml version="1.0" encoding="UTF-8"?>

<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">

    <id>assembly</id>
    <formats>
        <format>tar.gz</format>
        <format>dir</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <fileSets>
        <fileSet>
            <directory>bin</directory>
            <outputDirectory>/bin</outputDirectory>
            <fileMode>0755</fileMode>
        </fileSet>
        <fileSet>
            <directory>src/main/resources/</directory>
            <outputDirectory>/conf</outputDirectory>
        </fileSet>
        <fileSet>
            <directory>target/dependency</directory>
            <outputDirectory>/lib</outputDirectory>
        </fileSet>
    </fileSets>
    <files>
        <file>
            <source>target/hdfs-client-demo-${project.version}.jar</source>
            <outputDirectory>/lib</outputDirectory>
        </file>
    </files>
</assembly>

这里定义了tar包中所包含的内容。

7.打包和运行

当以上都开发完成后,需执行以下命令进行打包。

mvn clean package -Passembly -DskipTests

打包完成后,直接解压,执行start.sh脚本即可启动demo应用。

最好编写README.md文件,详细描述demo应用的功能、设计和使用方式,以便后续可能的交接。