Spring Boot【2.使用】

  • 1.系统构建
  • 2.代码构建
  • 3.配置类和相关注解
  • 4.运行

基于版本:Spring Boot 1.5.7.RELEASE

1.系统构建(POM.xml)
1.1 依赖管理说明
  • Spring Boot依赖使用的groupId都是org.springframework.boot
  • spring boot每个版本都提供了该版本支持的依赖列表,包括它们的版本,所以构建POM时不必指定这些依赖的版本(列表包括spring模块和精选的第三方库)
    spring boot依赖列表
  • 也可以自己指定版本覆盖spring boot中默认的版本,但不推荐。因为每版Spring Boot都会关联一个Spring框架的基础版本,所以不建议自己指定这些Spring Framework版本
  • spring boot建议使用Maven/Gradle进行依赖管理
1.2 使用Maven管理依赖

两种方式:继承/不继承spring-boot-starter-parent

  • 1.2.1 继承 spring-boot-starter-parent

实际上spring-boot-starter-parent POM继承了顶层父POM:spring-boot-dependencies
在spring-boot-dependencies中进行dependencyManagement和pluginManagement

spring-boot-starter-parent提供了一些sensible defaults:

  • 默认编译级别为Java 1.6
  • 源码编码为UTF-8
  • 继承spring-boot-dependenciesPOM的Dependency management节点,允许省略常见依赖的<version>
  • 恰到好处的资源过滤
  • 恰到好处的插件配置(exec插件surefireGit commit IDshade
  • 恰到好处的对application.properties和application.yml进行筛选,包括特定profile(profile-specific)的文件,比如application-foo.properties和application-foo.yml

覆盖parent POM中(实际是spring-boot-dependencies中的)个别的依赖的属性,如版本

<!-- 修改个别依赖属性:如版本 -->
<properties>
    <hibernate-validator.version>5.4.1.Final</hibernate-validator.version>
</properties>

使用parent POM时,打包插件pring-boot-maven-plugin只需引用,parent POM中已经做了配置

完成的POM如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.top.test.springboot</groupId>
    <artifactId>test-springboot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    
    <!-- 修改个别依赖属性:如版本 -->
    <properties>
        <hibernate-validator.version>5.4.1.Final</hibernate-validator.version>
    </properties>

    <!-- Inherit defaults from Spring Boot -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.7.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
  • 1.2.2 不继承 spring-boot-starter-parent
  • 仍可享受spring-boot-dependencies的dependencyManagement版本控制(使用scope=import方式引入);但不包括 plugin management
  • spring-boot-starter-parent POM includes <executions> configuration to bind the repackage goal. 如果不用parent POM,就需要自己声明这个配置,参见Spring Boot Maven Plugin
  • 如果不用spring-boot-maven-plugin,或用了但没加<executions> configuration,就不能打成fat/uber jars(项目里引用的jar就没打进去)。如下,打包过程就没用到spring-boot-maven-plugin来repackage:
$ mvn package 
[WARNING] 
[WARNING] Some problems were encountered while building the effective settings
[WARNING] expected START_TAG or END_TAG not TEXT (position: TEXT seen ...<profiles>\n   <profile>dd\n     <i... @16:8)  @ /usr/share/maven/conf/settings.xml, line 16, column 8
[WARNING] 
[INFO] Scanning for projects...
[WARNING] 
[WARNING] Some problems were encountered while building the effective model for com.top.test.springboot:test-springboot:jar:0.0.1-SNAPSHOT
[WARNING] 'build.plugins.plugin.version' for org.springframework.boot:spring-boot-maven-plugin is missing. @ line 76, column 12
[WARNING] 
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING] 
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING] 
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building test-springboot 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ test-springboot ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO] 
[INFO] --- maven-compiler-plugin:3.2:compile (default-compile) @ test-springboot ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ test-springboot ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO] 
[INFO] --- maven-compiler-plugin:3.2:testCompile (default-testCompile) @ test-springboot ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] --- maven-surefire-plugin:2.17:test (default-test) @ test-springboot ---
[INFO] 
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ test-springboot ---
[INFO] Building jar: /home/yuzhou/personalDev/workspace/test-springboot/target/test-springboot-0.0.1-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:13 min
[INFO] Finished at: 2017-10-13T15:05:48+08:00
[INFO] Final Memory: 20M/249M
[INFO] ------------------------------------------------------------------------

打成的jar内文件也不包括项目引用的nested jar

$ jar tvf target/test-springboot-0.0.1-SNAPSHOT.jar 
     0 Fri Oct 13 15:05:50 CST 2017 META-INF/
   132 Fri Oct 13 15:05:48 CST 2017 META-INF/MANIFEST.MF
     0 Fri Oct 13 14:36:26 CST 2017 com/
     0 Fri Oct 13 14:36:26 CST 2017 com/top/
     0 Fri Oct 13 14:36:26 CST 2017 com/top/test/
     0 Fri Oct 13 14:37:00 CST 2017 com/top/test/controller/
     0 Fri Oct 13 14:36:26 CST 2017 com/top/test/springboot/
  1326 Fri Oct 13 14:39:18 CST 2017 com/top/test/controller/HelloApplication$1.class
  1432 Fri Oct 13 14:39:18 CST 2017 com/top/test/controller/HelloApplication.class
   626 Fri Oct 13 14:36:26 CST 2017 com/top/test/springboot/HelloController.class
     0 Fri Oct 13 15:05:50 CST 2017 META-INF/maven/
     0 Fri Oct 13 15:05:50 CST 2017 META-INF/maven/com.top.test.springboot/
     0 Fri Oct 13 15:05:50 CST 2017 META-INF/maven/com.top.test.springboot/test-springboot/
  2316 Fri Oct 13 15:03:46 CST 2017 META-INF/maven/com.top.test.springboot/test-springboot/pom.xml
   139 Thu Oct 12 17:52:08 CST 2017 META-INF/maven/com.top.test.springboot/test-springboot/pom.properties

所以无法启动

$ java -jar target/test-springboot-0.0.1-SNAPSHOT.jar 
target/test-springboot-0.0.1-SNAPSHOT.jar中没有主清单属性
  • parent POM中Maven Plugin的配置,需要将此打包配置添加到自己的POM
<!-- parent POM中Spring Boot Maven Plugin的配置(repackage+mainClass) -->
<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <executions>
        <execution>
            <goals>
                <goal>repackage</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <mainClass>${start-class}</mainClass>
    </configuration>
</plugin>
  • 不使用parent POM时,完整的POM如下
  • 使用scope=import解决单继承(scope只能放在dependencyManagement中)
  • 这样既能使用spring-boot-dependencies中的依赖管理,又能继承别的parent
  • 覆盖spring-boot-dependencies POM中版本也如下(e.g hibernate-validator)
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.top.test.springboot</groupId>
    <artifactId>test-springboot</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <dependencyManagement>
        <dependencies>
            <!-- 覆盖Override hibernate-validator train provided by Spring Boot -->
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-validator</artifactId>
                <version>5.3.5.Final</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- 导入spring-boot-dependencies,使用其依赖管理 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>1.5.7.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <mainClass>${start-class}</mainClass>
                    <!-- 写死也可以 -->
                    <!-- <mainClass>com.top.test.controller.HelloApplication</mainClass> -->
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
  • 1.2.3
    低版本的springboot在spring-boot-starter-parent中选择了保守的Java兼容策略(支持Java6),若要使用其他的Java版本:
<properties>
    <java.version>1.8</java.version>
</properties>
1.3 starter POM

starters中包含了很多搭建&快速运行项目所需的依赖,并提供一致的,可管理传递性的依赖集:
spring boot starters reference

官方starters遵循相似的命名模式: spring-boot-starter-*
第三方starter(acme)通常命名:acme-spring-boot-starter

2.代码构建

两点最佳实践

2.1 default package的影响
  • 当类没有声明package时,它被认为处于default package下;
  • 不推荐使用default package,因为对使用@ComponentScan、@EntityScan或@SpringBootApplication注解的Spring Boot应用来说,它会扫描每个jar中的类,这会造成一定的问题;
  • 建议遵循Java推荐的包命名规范,使用反转的域名。
2.2 main application class的位置
com
 +- example
     +- myproject
         +- Application.java
         |
         +- domain
         |   +- Customer.java
         |   +- CustomerRepository.java
         |
         +- service
         |   +- CustomerService.java
         |
         +- web
             +- CustomerController.java
  • 1.建议将main application class放到其他包的顶层(root package),并将在该main类添加@EnableAutoConfiguration,这样就隐式地定义了一个基础的包搜索路径,(@ComponentScan)以搜索某些特定的注解实体(比如@Service,@Component等)
  • 2.@EnableAutoConfiguration一般只有一个,加在main application class上,开启自动配置
  • 3.这种root package方式,就可以直接使用@ComponentScan而不需要指定basePackage属性;或者也可以使用@SpringBootApplication注解。
  • 4.@SpringBootApplication=@EnableAutoConfiguration+@ComponentScan+@Configuration
  • 5.@ComponentScan收集所有Spring组件,如@Configuration/@Controller等
3.配置类和相关注解

@Configuration
@EnableAutoConfiguration
@ComponentScan
@SpringBootApplication

3.1 @Configuration:
  • 不需要:当该类已经作为参数传递到SpringApplication.run()中

注:虽然SpringApplication.run(HelloApplication.class, args); 中已经把main application class传进了run(),一般还是在main类=HelloApplication.class加上@Configuration,作为主配置类候补
Usually the class that defines the main method is also a good candidate as the primary @Configuration.

----------测试类(不加@Configuration)----------
public class test1 {
    @Bean
    public String haha() {
        return new String("haha");
    }
}
----------main类(把test1.class也作为参数传递给run())----------
@EnableAutoConfiguration
@ComponentScan
public class HelloApplication {
    public static void main(String[] args) {
        Object[] classes = new Object[]{HelloApplication.class,test1.class};
        SpringApplication.run(classes, args);
    }
}
----------启动结果:创建了test1和haha实例----------
Let's inspect the beans provided by Spring Boot:
...
commandLineRunner(就在HelloApplication.class中,作为参数传给了run())
haha
helloApplication
helloController(有@Controller注解&&@ComponentScan能扫描到)
test1
...
  • 需要:当该类没有作为参数传递到run()中,就需要加@Configuration,并且@ComponentScan(main configuration class上)要能扫描到该配置类
----------测试类(需要加@Configuration)----------
@Configuration
public class test1 {
    @Bean
    public String haha() {
        return new String("haha");
    }
}
----------main类(test1.class没有传递给run())----------
@EnableAutoConfiguration
@ComponentScan
public class HelloApplication {
    public static void main(String[] args) {
        //Object[] classes = new Object[]{HelloApplication.class,test1.class};
        //SpringApplication.run(classes, args);
        SpringApplication.run(HelloApplication.class, args);
    }
}
----------启动结果:创建了test1和haha实例----------
Let's inspect the beans provided by Spring Boot:
...
commandLineRunner(就在HelloApplication.class中,作为参数传给了run())
haha
helloApplication
helloController(有@Controller注解&&@ComponentScan能扫描到)
test1
...
  • 如果必须使用XML配置,建议从一个标记@Configuration的类开始。与@Import、@ImportResource配合使用。用来引入其他类中的@Bean或XML配置文件(用@Import导入的Bean,即使它们所在的类有@Configuration注解,也不会创建它们所在的类的实例,相当于都在一个配置文件中)
3.2 @EnableAutoConfiguration

Spring Boot的自动配置,尝试根据添加的jar依赖自动配置Spring应用

  • 实现自动配置:添加@EnableAutoConfiguration或@SpringBootApplication注解到其中一个@Configuration类上
  • 应该只添加一个@EnableAutoConfiguration注解,通常建议添加到主配置类(primary @Configuration)上(一般用main入口类作为主配置类)
  • 替换:Auto-configuration是非侵入性的,可定义自己的配置类来替换
  • 禁用:可以从annotation || properties 禁用:
    @EnableAutoConfiguration注解的exclude/excludeName属性禁用自动配置
    也可以在配置文件中指定:spring.autoconfigure.exclude
  • 查看使用了哪些自动配置:java -jar xxx.jar --debug
3.3 @ComponentScan

spring框架的注解,自动收集spring组件:@Service/@Component/@Configuration等

3.4 @SpringBootApplication

@SpringBootApplication=@Configuration+@EnableAutoConfiguration+@ComponentScan

3.5 Spring Beans和依赖注入

SpringBoot的Beans注解和@Autowired的用法跟Spring Framework一样

4.运行
  • 1.在project目录下,命令行执行mvn spring-boot:run
  • 2.借助IDE:执行main方法Run as Java Application || 配置maven build(原理同1)
  • 3.打包成jar(内嵌了HTTP服务器), java -jar xxx.jar
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,258评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,335评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,225评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,126评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,140评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,098评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,018评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,857评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,298评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,518评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,400评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,993评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,638评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,661评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容