• 补习系列(1)-springboot项目基础搭建课


    目录

    前言

    springboot 最近火的不行,目前几乎已经是 spring 家族最耀眼的项目了。抛开微服务、技术社区这些推广因素不说,框架本身的确有非常多的优点。比如

    • 更简化的配置,摒除了许多繁杂的xml配置(事实证明,越简单的东西越容易让人记住);
    • 内置Servlet容器,不再依赖外部环境
    • 大量的starter模块,随手拈来
    • 支持热部署

    作为一名老程序员来说,仍然需要保持一个积极学习的态度。
    哎,简单点说就是少点伤感,认清现实。你曾经引以为傲的某某EE 技术已经被颠覆了,赶紧换车道 .....

    废话不多说,以下内容主要讲的是怎么利用springboot 这个脚手架搭建一个最精简的项目。
    其中几个模块会非常实用,这包括结构、配置、日志、部署..

    一、基础结构

    springboot 项目仍然是使用maven 进行初始化及构建,下面是一个典型的结构:

    大致看一下就行了,不了解maven的话,点击这里先学习入门,项目的构建工具是一定要先了解的。
    可以通过eclipse 或idea 创建一个maven项目,再引入springboot依赖,pom文件的定义参考如下:

    <?xml version="1.0"?>
    <project
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
        xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
       <modelVersion>4.0.0</modelVersion>
       <groupId>org.zales</groupId>
       <artifactId>dmo-boot</artifactId>
       <version>0.0.1-SNAPSHOT</version>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <spring-boot.version>1.5.1.RELEASE</spring-boot.version>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <!-- springboot application dependencies -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
    
            <!-- springweb -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
                <version>${spring-boot.version}</version>
                <exclusions>
                    <!-- exclude the default logging module -->
                    <exclusion>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-logging</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <!-- log4j2 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-log4j2</artifactId>
                <version>${spring-boot.version}</version>
            </dependency>
    
            <!-- springboot test -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <version>${spring-boot.version}</version>
            </dependency>
    
            <!-- used for livereload -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <version>${spring-boot.version}</version>
                <optional>true</optional>
            </dependency>
    
            <!-- used for template -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
                <version>${spring-boot.version}</version>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <configuration>
                        <source>${java.version}</source>
                        <target>${java.version}</target>
                        <encoding>${project.build.sourceEncoding}</encoding>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </project>

    springboot 官方的示例是让你继承一个spring-boot-parent,但这个很鸡肋,通常的项目都会有自己的继承结构。
    所以我们间接利用spring-boot-dependencies将所有依赖引入,其他模块的引入都是按需。
    maven-compiler-plugin的定义用于将项目指定为Java1.8的编译级别

    其他途径
    你还可以利用spring的在线网站初始化一个springboot项目,点击这里

    二、添加代码

    启动代码非常简单,新建一个名为"DemoBoot**的类:

    /**
     * 入口类
     *
     */
    @SpringBootApplication
    public class DemoBoot {
    
        public static void main(String[] args) throws Exception {
            SpringApplication app = new SpringApplication(DemoBoot.class);
    
            // 指定PID生成,默认输出到application.pid
            app.addListeners(new ApplicationPidFileWriter());
            app.run(args);
        }
    }

    再创建一个DemoController类:

    @Controller
    public class DemoController {
        
        @RequestMapping("/")
        @ResponseBody
        String home() {
            return "Hello World! ";
        }
    }

    至此,我们已经完成了框架代码!

    热部署
    我们在定义项目依赖时添加了springboot-devtools,该模块可以实现热部署的功能,即在开发过程中可以不重启应用令代码生效,非常方便
    livereload 组件会定时扫描类路径下的class,一旦发现变更即重启服务,默认1000毫秒检测一次。
    在定义依赖时指定optional 选项使得该模块仅在开发时启用。
    livereload 在扫描会自动忽略以下范围的变更:

    META-INF/maven/**
    META-INF/resources/**
    resources/**,static/**
    public/**
    templates/**
    **/*Test.class
    **/*Tests.class
    git.properties
    META-INF/build-info.properties 

    三、应用配置

    在src/main/resources/下新建一个application.properties文件,内容如下:
    application.properties

    server.address=0.0.0.0
    server.port=8090

    此时在IDE执行"DemoBoot",你应该可以看到一些描述程序启动的日志信息,访问本机的8090端口能看到"HelloWorld“输出。

    application.properties可包含大量的配置,你可以在这里找到全部的配置

    四、日志配置

    接下来需要为应用准备一个日志配置用于定制,springboot 默认是使用logback的,但由于更加熟悉log4j的缘故,我们选用了log4j2.x
    在src/main/resources/下新建一个log4j2.xml文件,内容如下:

    log4j2.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration status="INFO" monitorInterval="300">  
        <properties>  
            <property name="LOG_ROOT">log</property>  
            <property name="FILE_NAME">application</property>  
        </properties>  
        <Appenders>  
            <Console name="Console" target="SYSTEM_OUT">  
                <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS}–[%t] %-5level -%l - %msg%n" />  
            </Console>  
            <RollingRandomAccessFile name="MainFile"  
                fileName="${LOG_ROOT}/${FILE_NAME}.log"  
                filePattern="${LOG_ROOT}/$${date:yyyy-MM}/${FILE_NAME}-%d{yyyy-MM-dd HH}-%i.log">  
                <PatternLayout  
                    pattern="%d{yyyy-MM-dd HH:mm:ss.SSS}–[%t] %-5level -%l - %msg%n" />  
                <Policies>  
                    <TimeBasedTriggeringPolicy interval="1" />  
                    <SizeBasedTriggeringPolicy size="50 MB" />  
                </Policies>  
                <DefaultRolloverStrategy max="20" />  
            </RollingRandomAccessFile>  
        </Appenders>  
    
        <Loggers>  
            <Logger name="org.zales" level="info" additivity="true">  
                <AppenderRef ref="MainFile" />  
            </Logger>  
            <Root level="info">  
                <AppenderRef ref="Console" />  
                <AppenderRef ref="MainFile" />  
            </Root>  
        </Loggers>  
    </Configuration>  

    这里配置了两个日志记录方式,Console是控制台打印,RollingRandomAccessFile 指向一个日志文件,我们为该日志文件设定了滚动的规则:

    1. 当大小超过50M时会生成新的日志;
    2. 每小时生成一个新的日志;
      指定了最多存在20个日志文件。
      之后,我们为主模块(这里是org.zales,你可以定义自己的包名)和ROOT都分别做了关联和日志级别定义。
      关于log4j2的用法,可以参考这个文章

    五、打包部署

    应用最终需要发布到某个环境,那么我们怎么对springboot应用进行打包呢?
    利用spring-boot-maven-plugin可以将springboot项目达成jar包。
    随后执行java -jar xxx.jar的方式即可以启动应用。
    这看起来好像很美好,但真实的项目发布并非这么简单。

    • 首先是配置,springboot的maven插件会将所有配置文件都打进jar包内,而某些配置可能与环境相关。
      比如应用端口,安全证书、或是日志配置等,这时我们希望在jar包外部存放这些文件;
    • 其次是执行脚本,在云环境上发布应用,通常需要提供启停脚本,包括一些监控功能脚本,这些需要作为项目打包的一部分
    • 最后,将应用程序发布为tgz或zip格式的压缩包会更加灵活,你可以添加更多的东西。

    为实现灵活的打包方式,我们需要同时引用spring-boot-maven-plugin和maven-assembly-plugin两个插件,如下:
    pom.xml

    <build>
            <plugins>
                <!-- build for springboot jar -->
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <executions>
                        <execution>
                            <goals>
                                <goal>repackage</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
                <!-- build for application package -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-assembly-plugin</artifactId>
                    <version>2.4</version>
                    <executions>
                        <execution>
                            <id>bundle</id>
                            <phase>package</phase>
                            <goals>
                                <goal>single</goal>
                            </goals>
                            <configuration>
                                <descriptors>
                                    <descriptor>${basedir}/src/main/build/assembly.xml</descriptor>
                                </descriptors>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>

    plugin可以实现在maven的某个生命周期绑定一组动作,如上面的两个插件都绑定到了package阶段,执行顺序由声明的先后决定。
    于是项目在执行mvn package这样的命令时,会先执行springboot插件的repackage动作,将程序打包成jar文件;随后通过assembly插件执行bundle任务,
    再作最终的组装。
    /src/main/build/assembly.xml定义了程序包的结构,如下:

    <assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
        <id>bundle</id>
        <formats>
            <format>tar.gz</format>
        </formats>
        <includeBaseDirectory>false</includeBaseDirectory> <!-- disable the creation of root's distribution dir in the archive -->
    
         <fileSets>  
            <!-- config files -->
            <fileSet>  
                <directory>${basedir}/src/main/build/config</directory>  
                <excludes></excludes>  
                 <includes>
                    <include>application*.properties</include>
                    <include>log4j2.xml</include> 
                </includes>
                <fileMode>0644</fileMode>
                <outputDirectory>/</outputDirectory>  
            </fileSet>  
            <!-- scripts -->
            <fileSet>
                <directory>${basedir}/src/main/build/bin</directory>
                <includes>
                    <include>*.sh</include>
                </includes>
                <fileMode>0755</fileMode>
                <outputDirectory>/</outputDirectory>
            </fileSet>
            <!-- executable jar -->
             <fileSet>
                <directory>${project.build.directory}</directory>
                <outputDirectory>/</outputDirectory>
                <includes>
                    <include>${project.artifactId}-${project.version}.jar</include>
                </includes>
                <fileMode>0755</fileMode>
            </fileSet>
        </fileSets>  
    
    </assembly>

    assembly文件的定义比较简单,目标程序包中除了jar文件之外,还会包含几个脚本和配置文件。

    • 启动脚本
      /src/main/build/bin/start.sh
    nohup java -jar dmo-boot-0.0.1-SNAPSHOT.jar > console.log &
    tail -n100 -f console.log
    • 停止脚本
      /src/main/build/bin/stop.sh
    kill `cat application.pid`
    rm application.pid
    • 配置文件
      /src/main/build/application.properties
      /src/main/build/log4j2.xml

    最终执行"mvn package"打包,会输出压缩包文件,结构如下:

    dmo-boot.0.0.1-SNAPSHOT.jar
    application.properties
    log4j2.xml
    start.sh
    stop.sh

    码云同步代码

    小结

    本文将一个springboot项目从初始化、开发、配置、打包的整个流程进行了详细介绍,希望读者对该框架能产生整体性的了解。
    由于篇幅有限,部分章节仅做了简单说明。springboot是一个优秀的脚手架,借助于框架可以快速的完成各种特性的实现。
    在随后的文章里,将会跟大家一起继续深入学习,欢迎随时关注"美码师的补习系列-springboot篇"

    作者:美码师

  • 相关阅读:
    (转)NandFlash详述
    (转)Redhat Linux 硬盘挂载方法!!!
    为Linux虚拟机挂载SD卡!
    DECLARE_GLOBAL_DATA_PTR 作用
    NAND FLASH ECC校验原理与实现
    Ehcache学习笔记(三) 与Spring集成
    ExtJs ComponentQuery 组件选择器
    好记性不如烂博客之 Quartz HowTo: Update an existing job
    使用WeakReference 与 ReferenceQueue 简单实现弱引用缓存
    Ehcache学习笔记(四) Web Caching 页面级别缓存
  • 原文地址:https://www.cnblogs.com/huaweicloud/p/11861584.html
Copyright © 2020-2023  润新知