本节提供一个SpringBoot参考文档的简明概述。你可以把它作为文档其余部分的导航。你可以从头到尾依次阅读该参考指南,或跳过你不感兴趣的章节。
如果你想从总体上对SpringBoot或Spring入门,本章节就是为你准备的!在这里,我们将回答基本的"what","how"和"why"问题。你会发现一个温雅的SpringBoot介绍及安装指南。然后我们构建第一个SpringBoot应用,并讨论一些我们需要遵循的核心原则。
SpringBoot使开发独立的,产品级别的基于Spring的应用变得非常简单,你只需"justrun"。我们为Spring平台及第三方库提供开箱即用的设置,这样你就可以有条不紊地开始。多数SpringBoot应用需要很少的Spring配置。
你可以使用SpringBoot创建Java应用,并使用java-jar启动它或采用传统的war部署方式。我们也提供了一个运行"spring脚本"的命令行工具。
我们主要的目标是:
注:尽管你可以在Java6或Java7环境下使用SpringBoot,通常我们建议你如果可能的话就使用Java8。
下列内嵌容器支持开箱即用(outofthebox):
你也可以将SpringBoot应用部署到任何兼容Servlet3.0+的容器。
注:尽管SpringBoot兼容Java1.6,如果可能的话,你应该考虑使用Java最新版本。
你可以像使用其他任何标准Java库那样使用SpringBoot,只需简单地在你的classpath下包含正确的spring-boot-*.jar文件。SpringBoot不需要集成任何特殊的工具,所以你可以使用任何IDE或文本编辑器;SpringBoot应用也没有什么特殊之处,所以你可以像任何其他Java程序那样运行和调试。
尽管你可以拷贝SpringBootjars,不过,我们通常推荐你使用一个支持依赖管理的构建工具(比如Maven或Gradle)。
注:在很多操作系统上,你可以通过一个包管理器安装Maven。如果你是一个OSXHomebrew用户,可以尝试brewinstallmaven。Ubuntu用户可以运行sudoapt-getinstallmaven。
下面是一个典型的pom.xml文件:
下面是一个典型的build.gradle文件:
你没有必要为了使用SpringBoot而去用CLI,但它绝对是助力Spring应用的最快方式。
你可以从Spring软件仓库下载SpringCLI分发包:
GVM(Groovy环境管理器)可以用来管理多种不同版本的Groovy和Java二进制包,包括Groovy自身和SpringBootCLI。可以从gvmtool.net获取gvm,并使用以下命令安装SpringBoot:
$gvminstallspringboot$spring--versionSpringBootv1.3.0.BUILD-SNAPSHOT如果你正在为CLI开发新的特性,并想轻松获取你刚构建的版本,可以使用以下命令:
$gvminstallspringbootdev/path/to/spring-boot/spring-boot-cli/target/spring-boot-cli-1.3.0.BUILD-SNAPSHOT-bin/spring-1.3.0.BUILD-SNAPSHOT/$gvmusespringbootdev$spring--versionSpringCLIv1.3.0.BUILD-SNAPSHOT这将会在你的gvm仓库中安装一个名叫dev的本地spring实例。它指向你的目标构建位置,所以每次你重新构建SpringBoot,spring将会是最新的。
你可以通过以下命令来验证:
$brewtappivotal/tap$brewinstallspringbootHomebrew将把spring安装到/usr/local/bin下。
注:如果该方案不可用,可能是因为你的brew版本太老了。你只需执行brewupdate并重试即可。
$.~/.gvm/springboot/current/shell-completion/bash/spring$springgrabhelpjarruntestversion注:如果你使用Homebrew或MacPorts安装SpringBootCLI,命令行实现脚本会自动注册到你的shell。
下面是一个相当简单的web应用,你可以用它测试你的安装是否成功。创建一个名叫app.groovy的文件:
@RestControllerclassThisWillActuallyRun{@RequestMapping("/")Stringhome(){"HelloWorld!"}}然后简单地从一个shell中运行它:
在你最喜欢的浏览器中打开localhost:8080,然后你应该看到以下输出:
让我们使用Java开发一个简单的"HelloWorld!"web应用,来强调下SpringBoot的一些关键特性。我们将使用Maven构建该项目,因为大多数IDEs都支持它。
在开始前,你需要打开一个终端,检查是否安装可用的Java版本和Maven:
$java-versionjavaversion"1.7.0_51"Java(TM)SERuntimeEnvironment(build1.7.0_51-b13)JavaHotSpot(TM)64-BitServerVM(build24.51-b03,mixedmode)$mvn-vApacheMaven3.2.3(33f8c3e1027c3ddde99d3cdebad2656a31e8fdf4;2014-08-11T13:58:10-07:00)Mavenhome:/Users/user/tools/apache-maven-3.1.1Javaversion:1.7.0_51,vendor:OracleCorporation注:该示例需要创建自己的文件夹。后续的操作假设你已创建一个合适的文件夹,并且它是你的“当前目录”。
我们需要以创建一个Mavenpom.xml文件作为开始。该pom.xml是用来构建项目的处方。打开你最喜欢的文本编辑器,然后添加以下内容:
注:目前你可以将该项目导入一个IDE(大多数现代的JavaIDE都包含对Maven的内建支持)。简单起见,我们将继续使用普通的文本编辑器完成该示例。
SpringBoot提供很多"StarterPOMs",这能够让你轻松的将jars添加到你的classpath下。我们的示例程序已经在POM的partent节点使用了spring-boot-starter-parent。spring-boot-starter-parent是一个特殊的starter,它提供了有用的Maven默认设置。同时,它也提供了一个dependency-management节点,这样对于”blessed“依赖你可以省略version标记。
其他的”StarterPOMs“简单的提供依赖,这些依赖可能是你开发特定类型的应用时需要的。由于正在开发一个web应用,我们将添加一个spring-boot-starter-web依赖-但在此之前,让我们看下目前所拥有的:
$mvndependency:tree[INFO]com.example:myproject:jar:0.0.1-SNAPSHOTmvndependency:tree命令以树形表示来打印你的项目依赖。你可以看到spring-boot-starter-parent本身并没有提供依赖。编辑我们的pom.xml,并在parent节点下添加spring-boot-starter-web依赖:
为了完成应用程序,我们需要创建一个单独的Java文件。Maven默认会编译src/main/java下的源码,所以你需要创建那样的文件结构,然后添加一个名为src/main/java/Example.java的文件:
importorg.springframework.boot.*;importorg.springframework.boot.autoconfigure.*;importorg.springframework.stereotype.*;importorg.springframework.web.bind.annotation.*;@RestController@EnableAutoConfigurationpublicclassExample{@RequestMapping("/")Stringhome(){return"HelloWorld!";}publicstaticvoidmain(String[]args)throwsException{SpringApplication.run(Example.class,args);}}尽管这里没有太多代码,但很多事情正在发生。让我们分步探讨重要的部分。
我们的Example类上使用的第一个注解是@RestController。这被称为一个构造型(stereotype)注解。它为阅读代码的人们提供建议。对于Spring,该类扮演了一个特殊角色。在本示例中,我们的类是一个web@Controller,所以当处理进来的web请求时,Spring会询问它。
@RequestMapping注解提供路由信息。它告诉Spring任何来自"/"路径的HTTP请求都应该被映射到home方法。@RestController注解告诉Spring以字符串的形式渲染结果,并直接返回给调用者。
第二个类级别的注解是@EnableAutoConfiguration。这个注解告诉SpringBoot根据添加的jar依赖猜测你想如何配置Spring。由于spring-boot-starter-web添加了Tomcat和SpringMVC,所以auto-configuration将假定你正在开发一个web应用并相应地对Spring进行设置。
StarterPOMs和Auto-Configuration:设计auto-configuration的目的是更好的使用"StarterPOMs",但这两个概念没有直接的联系。你可以自由地挑选starterPOMs以外的jar依赖,并且SpringBoot将仍旧尽最大努力去自动配置你的应用。
我们的应用程序最后部分是main方法。这只是一个标准的方法,它遵循Java对于一个应用程序入口点的约定。我们的main方法通过调用run,将业务委托给了SpringBoot的SpringApplication类。SpringApplication将引导我们的应用,启动Spring,相应地启动被自动配置的Tomcatweb服务器。我们需要将Example.class作为参数传递给run方法来告诉SpringApplication谁是主要的Spring组件。为了暴露任何的命令行参数,args数组也会被传递过去。
到此我们的应用应该可以工作了。由于使用了spring-boot-starter-parentPOM,这样我们就有了一个非常有用的run目标,我们可以用它启动程序。在项目根目录下输入mvnspring-boot:run来启动应用:
$mvnspring-boot:run._________/\\/___'_____(_)______\\\\(()\___|'_|'_||'_\/_`|\\\\\\/___)||_)|||||||(_||))))'|____|.__|_||_|_||_\__,|////=========|_|==============|___/=/_/_/_/::SpringBoot::(v1.3.0.BUILD-SNAPSHOT)....................(logoutputhere)..................StartedExamplein2.222seconds(JVMrunningfor6.514)如果使用一个浏览器打开localhost:8080,你应该可以看到以下输出:
HelloWorld!点击ctrl-c温雅地关闭应用程序。
让我们通过创建一个完全自包含的可执行jar文件来结束我们的示例,该jar文件可以在生产环境运行。可执行jars(有时候被成为胖jars"fatjars")是包含你的编译后的类和你的代码运行所需的依赖jar的存档。
可执行jars和Java:Java没有提供任何标准的加载内嵌jar文件(即jar文件中还包含jar文件)的方法。如果你想发布一个自包含的应用这就是一个问题。为了解决该问题,很多开发者采用"共享的"jars。一个共享的jar简单地将来自所有jars的类打包进一个单独的“超级jar”。采用共享jar方式的问题是很难区分在你的应用程序中可以使用哪些库。在多个jars中如果存在相同的文件名(但内容不一样)也会是一个问题。SpringBoot采取一个不同的途径,并允许你真正的内嵌jars。
为了创建可执行的jar,需要将spring-boot-maven-plugin添加到我们的pom.xml中。在dependencies节点下插入以下内容:
保存你的pom.xml,然后从命令行运行mvnpackage:
$mvnpackage[INFO]Scanningforprojects...[INFO][INFO]------------------------------------------------------------------------[INFO]Buildingmyproject0.0.1-SNAPSHOT[INFO]------------------------------------------------------------------------[INFO]......[INFO]---maven-jar-plugin:2.4:jar(default-jar)@myproject---[INFO]Buildingjar:/Users/developer/example/spring-boot-example/target/myproject-0.0.1-SNAPSHOT.jar[INFO][INFO]---spring-boot-maven-plugin:1.3.0.BUILD-SNAPSHOT:repackage(default)@myproject---[INFO]------------------------------------------------------------------------[INFO]BUILDSUCCESS[INFO]------------------------------------------------------------------------如果查看target目录,你应该看到myproject-0.0.1-SNAPSHOT.jar。该文件应该有10Mb左右的大小。如果想偷看内部结构,你可以运行jartvf:
$jartvftarget/myproject-0.0.1-SNAPSHOT.jar在target目录下,你应该也能看到一个很小的名为myproject-0.0.1-SNAPSHOT.jar.original的文件。这是在SpringBoot重新打包前Maven创建的原始jar文件。
为了运行该应用程序,你可以使用java-jar命令:
$java-jartarget/myproject-0.0.1-SNAPSHOT.jar._________/\\/___'_____(_)______\\\\(()\___|'_|'_||'_\/_`|\\\\\\/___)||_)|||||||(_||))))'|____|.__|_||_|_||_\__,|////=========|_|==============|___/=/_/_/_/::SpringBoot::(v1.3.0.BUILD-SNAPSHOT)....................(logoutputhere)..................StartedExamplein2.536seconds(JVMrunningfor2.864)和以前一样,点击ctrl-c来温柔地退出程序。
本章节将会详细介绍如何使用SpringBoot。它覆盖了构建系统,自动配置和运行/部署选项等主题。我们也覆盖了一些SpringBoot最佳实践。尽管SpringBoot没有什么特别的(只是一个你能消费的库),但仍有一些建议,如果你遵循的话将会让你的开发进程更容易。
强烈建议你选择一个支持依赖管理,能消费发布到Maven中央仓库的artifacts的构建系统。我们推荐你选择Maven或Gradle。选择其他构建系统来使用SpringBoot也是可能的(比如Ant),但它们不会被很好的支持。
Maven用户可以继承spring-boot-starter-parent项目来获取合适的默认设置。该父项目提供以下特性:
最后一点:由于默认配置文件接收Spring风格的占位符(${...}),Mavenfiltering改用@..@占位符(你可以使用Maven属性resource.delimiter来覆盖它)。
想配置你的项目继承spring-boot-starter-parent只需要简单地设置parent为:
如果你不使用spring-boot-starter-parent,通过使用一个scope=import的依赖,你仍能获取到依赖管理的好处:
Gradle用户可以直接在它们的dependencies节点处导入”starterPOMs“。跟Maven不同的是,这里没有用于导入共享配置的"超父"(superparent)。
buildscript{repositories{jcenter()}dependencies{classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.0.BUILD-SNAPSHOT")}}applyplugin:'java'applyplugin:'spring-boot'repositories{jcenter()}dependencies{compile("org.springframework.boot:spring-boot-starter-web")testCompile("org.springframework.boot:spring-boot-starter-test")}3.1.3Ant使用ApacheAnt构建一个SpringBoot项目是完全可能的,然而,SpringBoot没有为它提供特殊的支持或插件。Ant脚本可以使用Ivy依赖管理系统来导入starterPOMs。
该starters包含很多你搭建项目,快速运行所需的依赖,并提供一致的,管理的传递依赖集。
名字有什么含义:所有的starters遵循一个相似的命名模式:spring-boot-starter-*,在这里*是一种特殊类型的应用程序。该命名结构旨在帮你找到需要的starter。很多IDEs集成的Maven允许你通过名称搜索依赖。例如,使用相应的Eclipse或STS插件,你可以简单地在POM编辑器中点击ctrl-space,然后输入"spring-boot-starter"可以获取一个完整列表。
下面的应用程序starters是SpringBoot在org.springframework.boot组下提供的:
SpringBootapplicationstarters
SpringBoot生产准备的starters
最后,SpringBoot包含一些可用于排除或交换具体技术方面的starters。
SpringBoottechnicalstarters
SpringBoot不需要使用任何特殊的代码结构,然而,这里有一些有用的最佳实践。
注:我们建议你遵循Java推荐的包命名规范,使用一个反转的域名(例如com.example.project)。
我们通常建议你将main应用类放在位于其他类上面的根包(rootpackage)中。通常使用@EnableAutoConfiguration注解你的main类,并且暗地里为某些项定义了一个基础“searchpackage”。例如,如果你正在编写一个JPA应用,被EnableAutoConfiguration注解的类所在包将被用来搜索@Entity项。
使用根包允许你使用@ComponentScan注解而不需要定义一个basePackage属性。如果main类位于根包中,你也可以使用@SpringBootApplication注解。
下面是一个典型的结构:
packagecom.example.myproject;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.EnableAutoConfiguration;importorg.springframework.context.annotation.ComponentScan;importorg.springframework.context.annotation.Configuration;@Configuration@EnableAutoConfiguration@ComponentScanpublicclassApplication{publicstaticvoidmain(String[]args){SpringApplication.run(Application.class,args);}}3.3配置类SpringBoot提倡基于Java的配置。尽管你可以使用一个XML源来调用SpringApplication.run(),我们通常建议你使用@Configuration类作为主要源。一般定义main方法的类也是主要@Configuration的一个很好候选。
注:很多使用XML配置的Spring配置示例已经被发布到网络上。你应该总是尽可能的使用基于Java的配置。搜索查看enable*注解就是一个好的开端。
你不需要将所有的@Configuration放进一个单独的类。@Import注解可以用来导入其他配置类。另外,你也可以使用@ComponentScan注解自动收集所有的Spring组件,包括@Configuration类。
如果你绝对需要使用基于XML的配置,我们建议你仍旧从一个@Configuration类开始。你可以使用附加的@ImportResource注解加载XML配置文件。
SpringBoot自动配置(auto-configuration)尝试根据你添加的jar依赖自动配置你的Spring应用。例如,如果你的classpath下存在HSQLDB,并且你没有手动配置任何数据库连接beans,那么我们将自动配置一个内存型(in-memory)数据库。
你可以通过将@EnableAutoConfiguration或@SpringBootApplication注解添加到一个@Configuration类上来选择自动配置。
注:你只需要添加一个@EnableAutoConfiguration注解。我们建议你将它添加到主@Configuration类上。
自动配置是非侵占性的,任何时候你都可以定义自己的配置类来替换自动配置的特定部分。例如,如果你添加自己的DataSourcebean,默认的内嵌数据库支持将不被考虑。
如果需要找出当前应用了哪些自动配置及应用的原因,你可以使用--debug开关启动应用。这将会记录一个自动配置的报告并输出到控制台。
如果发现应用了你不想要的特定自动配置类,你可以使用@EnableAutoConfiguration注解的排除属性来禁用它们。
importorg.springframework.boot.autoconfigure.*;importorg.springframework.boot.autoconfigure.jdbc.*;importorg.springframework.context.annotation.*;@Configuration@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})publicclassMyConfiguration{}3.5SpringBeans和依赖注入你可以自由地使用任何标准的Spring框架技术去定义beans和它们注入的依赖。简单起见,我们经常使用@ComponentScan注解搜索beans,并结合@Autowired构造器注入。
如果使用上面建议的结构组织代码(将应用类放到根包下),你可以添加@ComponentScan注解而不需要任何参数。你的所有应用程序组件(@Component,@Service,@Repository,@Controller等)将被自动注册为SpringBeans。
下面是一个@ServiceBean的示例,它使用构建器注入获取一个需要的RiskAssessorbean。
packagecom.example.service;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;@ServicepublicclassDatabaseAccountServiceimplementsAccountService{privatefinalRiskAssessorriskAssessor;@AutowiredpublicDatabaseAccountService(RiskAssessorriskAssessor){this.riskAssessor=riskAssessor;}//...}注:注意如何使用构建器注入来允许riskAssessor字段被标记为final,这意味着riskAssessor后续是不能改变的。
很多SpringBoot开发者总是使用@Configuration,@EnableAutoConfiguration和@ComponentScan注解他们的main类。由于这些注解被如此频繁地一块使用(特别是你遵循以上最佳实践时),SpringBoot提供一个方便的@SpringBootApplication选择。
该@SpringBootApplication注解等价于以默认属性使用@Configuration,@EnableAutoConfiguration和@ComponentScan。
packagecom.example.myproject;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication//sameas@Configuration@EnableAutoConfiguration@ComponentScanpublicclassApplication{publicstaticvoidmain(String[]args){SpringApplication.run(Application.class,args);}}3.7运行应用程序将应用打包成jar并使用一个内嵌HTTP服务器的一个最大好处是,你可以像其他方式那样运行你的应用程序。调试SpringBoot应用也很简单;你不需要任何特殊IDE或扩展。
注:本章节只覆盖基于jar的打包,如果选择将应用打包成war文件,你最好参考一下服务器和IDE文档。
你可以从IDE中运行SpringBoot应用,就像一个简单的Java应用,但是,你首先需要导入项目。导入步骤跟你的IDE和构建系统有关。大多数IDEs能够直接导入Maven项目,例如Eclipse用户可以选择File菜单的Import…-->ExistingMavenProjects。
如果不能直接将项目导入IDE,你可以需要使用构建系统生成IDE元数据。Maven有针对Eclipse和IDEA的插件;Gradle为各种IDEs提供插件。
注:如果意外地运行一个web应用两次,你将看到一个"端口已在使用中"错误。为了确保任何存在的实例是关闭的,STS用户可以使用Relaunch按钮而不是Run按钮。
如果使用SpringBootMaven或Gradle插件创建一个可执行jar,你可以使用java-jar运行你的应用。例如:
$java-jartarget/myproject-0.0.1-SNAPSHOT.jar运行一个打包的程序并开启远程调试支持是可能的,这允许你将调试器附加到打包的应用程序上:
$java-Xdebug-Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n\-jartarget/myproject-0.0.1-SNAPSHOT.jar3.7.3使用Maven插件运行SpringBootMaven插件包含一个run目标,它可以用来快速编译和运行应用程序。应用程序以一种暴露的方式运行,由于即时"热"加载,你可以编辑资源。
$mvnspring-boot:run你可能想使用有用的操作系统环境变量:
$exportMAVEN_OPTS=-Xmx1024m-XX:MaxPermSize=128M-Djava.security.egd=file:/dev/./urandom("egd"设置是通过为Tomcat提供一个更快的会话keys熵源来加速Tomcat的。)
SpringBootGradle插件也包含一个run目标,它可以用来以暴露的方式运行你的应用程序。不管你什么时候导入spring-boot-plugin,bootRun任务总是被添加进去。
$gradlebootRun你可能想使用那些有用的操作系统环境变量:
关于热交换可以参考“How-to”相应章节。
SpringApplication类提供了一种从main()方法启动Spring应用的便捷方式。在很多情况下,你只需委托给SpringApplication.run这个静态方法:
publicstaticvoidmain(String[]args){SpringApplication.run(MySpringConfiguration.class,args);}当应用启动时,你应该会看到类似下面的东西(这是何方神兽??):
通过在classpath下添加一个banner.txt或设置banner.location来指定相应的文件可以改变启动过程中打印的banner。如果这个文件有特殊的编码,你可以使用banner.encoding设置它(默认为UTF-8)。
在banner.txt中可以使用如下的变量:
注:如果想以编程的方式产生一个banner,可以使用SpringBootApplication.setBanner(…)方法。使用org.springframework.boot.Banner接口,实现你自己的printBanner()方法。
如果默认的SpringApplication不符合你的口味,你可以创建一个本地的实例并自定义它。例如,关闭banner你可以这样写:
publicstaticvoidmain(String[]args){SpringApplicationapp=newSpringApplication(MySpringConfiguration.class);app.setShowBanner(false);app.run(args);}注:传递给SpringApplication的构造器参数是springbeans的配置源。在大多数情况下,这些将是@Configuration类的引用,但它们也可能是XML配置或要扫描包的引用。
如果你需要创建一个分层的ApplicationContext(多个具有父子关系的上下文),或你只是喜欢使用流畅的构建API,你可以使用SpringApplicationBuilder。SpringApplicationBuilder允许你以链式方式调用多个方法,包括可以创建层次结构的parent和child方法。
你可以使用多种方式注册事件监听器,最普通的是使用SpringApplication.addListeners(…)方法。在你的应用运行时,应用事件会以下面的次序发送:
注:你通常不需要使用应用程序事件,但知道它们的存在会很方便(在某些场合可能会使用到)。在Spring内部,SpringBoot使用事件处理各种各样的任务。
一个SpringApplication将尝试为你创建正确类型的ApplicationContext。在默认情况下,使用AnnotationConfigApplicationContext或AnnotationConfigEmbeddedWebApplicationContext取决于你正在开发的是否是web应用。
用于确定一个web环境的算法相当简单(基于是否存在某些类)。如果需要覆盖默认行为,你可以使用setWebEnvironment(booleanwebEnvironment)。通过调用setApplicationContextClass(…),你可以完全控制ApplicationContext的类型。
注:当JUnit测试里使用SpringApplication时,调用setWebEnvironment(false)是可取的。
如果你想获取原始的命令行参数,或一旦SpringApplication启动,你需要运行一些特定的代码,你可以实现CommandLineRunner接口。在所有实现该接口的Springbeans上将调用run(String…args)方法。
importorg.springframework.boot.*importorg.springframework.stereotype.*@ComponentpublicclassMyBeanimplementsCommandLineRunner{publicvoidrun(String...args){//Dosomething...}}如果一些CommandLineRunnerbeans被定义必须以特定的次序调用,你可以额外实现org.springframework.core.Ordered接口或使用org.springframework.core.annotation.Order注解。
每个SpringApplication在退出时为了确保ApplicationContext被优雅的关闭,将会注册一个JVM的shutdown钩子。所有标准的Spring生命周期回调(比如,DisposableBean接口或@PreDestroy注解)都能使用。
此外,如果beans想在应用结束时返回一个特定的退出码(exitcode),可以实现org.springframework.boot.ExitCodeGenerator接口。
SpringBoot允许外化(externalize)你的配置,这样你能够在不同的环境下使用相同的代码。你可以使用properties文件,YAML文件,环境变量和命令行参数来外化配置。使用@Value注解,可以直接将属性值注入到你的beans中,并通过Spring的Environment抽象或绑定到结构化对象来访问。
SpringBoot使用一个非常特别的PropertySource次序来允许对值进行合理的覆盖,需要以下面的次序考虑属性:
下面是一个具体的示例(假设你开发一个使用name属性的@Component):
importorg.springframework.stereotype.*importorg.springframework.beans.factory.annotation.*@ComponentpublicclassMyBean{@Value("${name}")privateStringname;//...}你可以将一个application.properties文件捆绑到jar内,用来提供一个合理的默认name属性值。当运行在生产环境时,可以在jar外提供一个application.properties文件来覆盖name属性。对于一次性的测试,你可以使用特定的命令行开关启动(比如,java-jarapp.jar--name="Spring")。
RandomValuePropertySource在注入随机值(比如,密钥或测试用例)时很有用。它能产生整数,longs或字符串,比如:
my.secret=${random.value}my.number=${random.int}my.bignumber=${random.long}my.number.less.than.ten=${random.int(10)}my.number.in.range=${random.int[1024,65536]}random.int*语法是OPENvalue(,max)CLOSE,此处OPEN,CLOSE可以是任何字符,并且value,max是整数。如果提供max,那么value是最小的值,max是最大的值(不包含在内)。
默认情况下,SpringApplication将任何可选的命令行参数(以'--'开头,比如,--server.port=9000)转化为property,并将其添加到SpringEnvironment中。如上所述,命令行属性总是优先于其他属性源。
如果你不想将命令行属性添加到Environment里,你可以使用SpringApplication.setAddCommandLineProperties(false)来禁止它们。
SpringApplication将从以下位置加载application.properties文件,并把它们添加到SpringEnvironment中:
这个列表是按优先级排序的(列表中位置高的将覆盖位置低的)。
注:你可以使用YAML('.yml')文件替代'.properties'。
如果不喜欢将application.properties作为配置文件名,你可以通过指定spring.config.name环境属性来切换其他的名称。你也可以使用spring.config.location环境属性来引用一个明确的路径(目录位置或文件路径列表以逗号分割)。
$java-jarmyproject.jar--spring.config.name=myproject//or$java-jarmyproject.jar--spring.config.location=classpath:/default.properties,classpath:/override.properties如果spring.config.location包含目录(相对于文件),那它们应该以/结尾(在加载前,spring.config.name产生的名称将被追加到后面)。不管spring.config.location是什么值,默认的搜索路径classpath:,classpath:/config,file:,file:config/总会被使用。以这种方式,你可以在application.properties中为应用设置默认值,然后在运行的时候使用不同的文件覆盖它,同时保留默认配置。
注:如果你使用环境变量而不是系统配置,大多数操作系统不允许以句号分割(period-separated)的key名称,但你可以使用下划线(underscores)代替(比如,使用SPRING_CONFIG_NAME代替spring.config.name)。如果你的应用运行在一个容器中,那么JNDI属性(java:comp/env)或servlet上下文初始化参数可以用来取代环境变量或系统属性,当然也可以使用环境变量或系统属性。
除了application.properties文件,特定配置属性也能通过命令惯例application-{profile}.properties来定义。特定Profile属性从跟标准application.properties相同的路径加载,并且特定profile文件会覆盖默认的配置。
当application.properties里的值被使用时,它们会被存在的Environment过滤,所以你能够引用先前定义的值(比如,系统属性)。
注:如果你使用'starterPOMs',spring-boot-starter会自动提供SnakeYAML。
Spring框架提供两个便利的类用于加载YAML文档,YamlPropertiesFactoryBean会将YAML作为Properties来加载,YamlMapFactoryBean会将YAML作为Map来加载。
示例:
my:servers:-dev.bar.com-foo.bar.com将会转化到下面的属性中:
my.servers[0]=dev.bar.commy.servers[1]=foo.bar.com使用SpringDataBinder工具绑定那样的属性(这是@ConfigurationProperties做的事),你需要确定目标bean中有个java.util.List或Set类型的属性,并且需要提供一个setter或使用可变的值初始化它,比如,下面的代码将绑定上面的属性:
@ConfigurationProperties(prefix="my")publicclassConfig{privateList
你可以在单个文件中定义多个特定配置(profile-specific)的YAML文档,并通过一个spring.profileskey标示应用的文档。例如:
server:address:192.168.1.100---spring:profiles:developmentserver:address:127.0.0.1---spring:profiles:productionserver:address:192.168.1.120在上面的例子中,如果development配置被激活,那server.address属性将是127.0.0.1。如果development和production配置(profiles)没有启用,则该属性的值将是192.168.1.100。
YAML文件不能通过@PropertySource注解加载。所以,在这种情况下,如果需要使用@PropertySource注解的方式加载值,那就要使用properties文件。
使用@Value("${property}")注解注入配置属性有时可能比较笨重,特别是需要使用多个properties或你的数据本身有层次结构。为了控制和校验你的应用配置,SpringBoot提供一个允许强类型beans的替代方法来使用properties。
@Component@ConfigurationProperties(prefix="connection")publicclassConnectionSettings{privateStringusername;privateInetAddressremoteAddress;//...gettersandsetters}当@EnableConfigurationProperties注解应用到你的@Configuration时,任何被@ConfigurationProperties注解的beans将自动被Environment属性配置。这种风格的配置特别适合与SpringApplication的外部YAML配置进行配合使用。
#application.ymlconnection:username:adminremoteAddress:192.168.1.1#additionalconfigurationasrequired为了使用@ConfigurationPropertiesbeans,你可以使用与其他任何bean相同的方式注入它们。
@ServicepublicclassMyService{@AutowiredprivateConnectionSettingsconnection;//...@PostConstructpublicvoidopenConnection(){Serverserver=newServer();this.connection.configure(server);}}你可以通过在@EnableConfigurationProperties注解中直接简单的列出属性类来快捷的注册@ConfigurationPropertiesbean的定义。
正如使用@ConfigurationProperties注解一个类,你也可以在@Bean方法上使用它。当你需要绑定属性到不受你控制的第三方组件时,这种方式非常有用。
为了从Environment属性配置一个bean,将@ConfigurationProperties添加到它的bean注册过程:
@ConfigurationProperties(prefix="foo")@BeanpublicFooComponentfooComponent(){...}和上面ConnectionSettings的示例方式相同,任何以foo为前缀的属性定义都会被映射到FooComponent上。
SpringBoot使用一些宽松的规则用于绑定Environment属性到@ConfigurationPropertiesbeans,所以Environment属性名和bean属性名不需要精确匹配。常见的示例中有用的包括虚线分割(比如,context--path绑定到contextPath)和将环境属性转为大写字母(比如,PORT绑定port)。
@Component@ConfigurationProperties(prefix="person")publicclassConnectionSettings{privateStringfirstName;}下面的属性名都能用于上面的@ConfigurationProperties类:
Spring会尝试强制外部的应用属性在绑定到@ConfigurationPropertiesbeans时类型是正确的。如果需要自定义类型转换,你可以提供一个ConversionServicebean(beanid为conversionService)或自定义属性编辑器(通过一个CustomEditorConfigurerbean)。
SpringBoot将尝试校验外部的配置,默认使用JSR-303(如果在classpath路径中)。你可以轻松的为你的@ConfigurationProperties类添加JSR-303javax.validation约束注解:
@Component@ConfigurationProperties(prefix="connection")publicclassConnectionSettings{@NotNullprivateInetAddressremoteAddress;//...gettersandsetters}你也可以通过创建一个叫做configurationPropertiesValidator的bean来添加自定义的SpringValidator。
SpringProfiles提供了一种隔离应用程序配置的方式,并让这些配置只能在特定的环境下生效。任何@Component或@Configuration都能被@Profile标记,从而限制加载它的时机。
@Configuration@Profile("production")publicclassProductionConfiguration{//...}以正常的Spring方式,你可以使用一个spring.profiles.active的Environment属性来指定哪个配置生效。你可以使用平常的任何方式来指定该属性,例如,可以将它包含到你的application.properties中:
spring.profiles.active=dev,hsqldb或使用命令行开关:
--spring.profiles.active=dev,hsqldb4.3.1添加激活的配置(profiles)spring.profiles.active属性和其他属性一样都遵循相同的排列规则,最高的PropertySource获胜。也就是说,你可以在application.properties中指定生效的配置,然后使用命令行开关替换它们。
有时,将特定的配置属性添加到生效的配置中而不是替换它们是有用的。spring.profiles.include属性可以用来无条件的添加生效的配置。SpringApplication的入口点也提供了一个用于设置额外配置的JavaAPI(比如,在那些通过spring.profiles.active属性生效的配置之上):参考setAdditionalProfiles()方法。
示例:当一个应用使用下面的属性,并用--spring.profiles.active=prod开关运行,那proddb和prodmq配置也会生效:
在应用运行前,你可以通过调用SpringApplication.setAdditionalProfiles(…)方法,以编程的方式设置生效的配置。使用Spring的ConfigurableEnvironment接口激动配置也是可行的。
默认情况下,如果你使用'StarterPOMs',那么就会使用Logback记录日志。为了确保那些使用JavaUtilLogging,CommonsLogging,Log4J或SLF4J的依赖库能够正常工作,正确的Logback路由也被包含进来。
注:如果上面的列表看起来令人困惑,不要担心,Java有很多可用的日志框架。通常,你不需要改变日志依赖,SpringBoot默认的就能很好的工作。
SpringBoot默认的日志输出格式如下:
2014-03-0510:57:51.112INFO45469---[main]org.apache.catalina.core.StandardEngine:StartingServletEngine:ApacheTomcat/7.0.522014-03-0510:57:51.253INFO45469---[ost-startStop-1]o.a.c.c.C.[Tomcat].[localhost].[/]:InitializingSpringembeddedWebApplicationContext2014-03-0510:57:51.253INFO45469---[ost-startStop-1]o.s.web.context.ContextLoader:RootWebApplicationContext:initializationcompletedin1358ms2014-03-0510:57:51.698INFO45469---[ost-startStop-1]o.s.b.c.e.ServletRegistrationBean:Mappingservlet:'dispatcherServlet'to[/]2014-03-0510:57:51.702INFO45469---[ost-startStop-1]o.s.b.c.embedded.FilterRegistrationBean:Mappingfilter:'hiddenHttpMethodFilter'to:[/*]输出的节点(items)如下:
默认的日志配置会在写日志消息时将它们回显到控制台。默认,ERROR,WARN和INFO级别的消息会被记录。可以在启动应用时,通过--debug标识开启控制台的DEBUG级别日志记录。
默认情况下,SpringBoot只会将日志记录到控制台而不会写进日志文件。如果除了输出到控制台你还想写入到日志文件,那你需要设置logging.file或logging.path属性(例如在你的application.properties中)。
下表显示如何组合使用logging.*:
日志文件每达到10M就会被轮换(分割),和控制台一样,默认记录ERROR,WARN和INFO级别的信息。
所有支持的日志系统在Spring的Environment(例如在application.properties里)都有通过'logging.level.*=LEVEL'('LEVEL'是TRACE,DEBUG,INFO,WARN,ERROR,FATAL,OFF中的一个)设置的日志级别。
示例:application.properties
logging.level.org.springframework.web:DEBUGlogging.level.org.hibernate:ERROR4.4.5自定义日志配置通过将适当的库添加到classpath,可以激活各种日志系统。然后在classpath的根目录(root)或通过SpringEnvironment的logging.config属性指定的位置提供一个合适的配置文件来达到进一步的定制(注意由于日志是在ApplicationContext被创建之前初始化的,所以不可能在Spring的@Configuration文件中,通过@PropertySources控制日志。系统属性和平常的SpringBoot外部配置文件能正常工作)。
根据你的日志系统,下面的文件会被加载:
为了帮助定制一些其他的属性,从Spring的Envrionment转换到系统属性:
所有支持的日志系统在解析它们的配置文件时都能查询系统属性。具体可以参考spring-boot.jar中的默认配置。
注:在运行可执行的jar时,JavaUtilLogging有类加载问题,我们建议你尽可能避免使用它。
SpringBoot非常适合开发web应用程序。你可以使用内嵌的Tomcat,Jetty或Undertow轻轻松松地创建一个HTTP服务器。大多数的web应用都使用spring-boot-starter-web模块进行快速搭建和运行。
SpringWebMVC框架(通常简称为"SpringMVC")是一个富"模型,视图,控制器"的web框架。SpringMVC允许你创建特定的@Controller或@RestControllerbeans来处理传入的HTTP请求。使用@RequestMapping注解可以将控制器中的方法映射到相应的HTTP请求。
@RestController@RequestMapping(value="/users")publicclassMyRestController{@RequestMapping(value="/{user}",method=RequestMethod.GET)publicUsergetUser(@PathVariableLonguser){//...}@RequestMapping(value="/{user}/customers",method=RequestMethod.GET)List
如果想全面控制SpringMVC,你可以添加自己的@Configuration,并使用@EnableWebMvc对其注解。如果想保留SpringBootMVC的特性,并只是添加其他的MVC配置(拦截器,formatters,视图控制器等),你可以添加自己的WebMvcConfigurerAdapter类型的@Bean(不使用@EnableWebMvc注解)。
SpringMVC使用HttpMessageConverter接口转换HTTP请求和响应。合理的缺省值被包含的恰到好处(outofthebox),例如对象可以自动转换为JSON(使用Jackson库)或XML(如果JacksonXML扩展可用则使用它,否则使用JAXB)。字符串默认使用UTF-8编码。
如果需要添加或自定义转换器,你可以使用SpringBoot的HttpMessageConverters类:
SpringMVC有一个策略,用于从绑定的errors产生用来渲染错误信息的错误码:MessageCodesResolver。如果设置spring.mvc.message-codes-resolver.format属性为PREFIX_ERROR_CODE或POSTFIX_ERROR_CODE(具体查看DefaultMessageCodesResolver.Format枚举值),SpringBoot会为你创建一个MessageCodesResolver。
默认情况下,SpringBoot从classpath下一个叫/static(/public,/resources或/META-INF/resources)的文件夹或从ServletContext根目录提供静态内容。这使用了SpringMVC的ResourceHttpRequestHandler,所以你可以通过添加自己的WebMvcConfigurerAdapter并覆写addResourceHandlers方法来改变这个行为(加载静态文件)。
在一个单独的web应用中,容器默认的servlet是开启的,如果Spring决定不处理某些请求,默认的servlet作为一个回退(降级)将从ServletContext根目录加载内容。大多数时候,这不会发生(除非你修改默认的MVC配置),因为Spring总能够通过DispatcherServlet处理请求。
注:如果你的应用将被打包成jar,那就不要使用src/main/webapp文件夹。尽管该文件夹是一个共同的标准,但它仅在打包成war的情况下起作用,并且如果产生一个jar,多数构建工具都会静悄悄的忽略它。
正如RESTweb服务,你也可以使用SpringMVC提供动态HTML内容。SpringMVC支持各种各样的模板技术,包括Velocity,FreeMarker和JSPs。很多其他的模板引擎也提供它们自己的SpringMVC集成。
SpringBoot为以下的模板引擎提供自动配置支持:
当你使用这些引擎的任何一种,并采用默认的配置,你的模板将会从src/main/resources/templates目录下自动加载。
注:IntelliJIDEA根据你运行应用的方式会对classpath进行不同的整理。在IDE里通过main方法运行你的应用跟从Maven或Gradle或打包好的jar中运行相比会导致不同的顺序。这可能导致SpringBoot不能从classpath下成功地找到模板。如果遇到这个问题,你可以在IDE里重新对classpath进行排序,将模块的类和资源放到第一位。或者,你可以配置模块的前缀为classpath*:/templates/,这样会查找classpath下的所有模板目录。
SpringBoot默认提供一个/error映射用来以合适的方式处理所有的错误,并且它在servlet容器中注册了一个全局的错误页面。对于机器客户端(相对于浏览器而言,浏览器偏重于人的行为),它会产生一个具有详细错误,HTTP状态,异常信息的JSON响应。对于浏览器客户端,它会产生一个白色标签样式(whitelabel)的错误视图,该视图将以HTML格式显示同样的数据(可以添加一个解析为erro的View来自定义它)。为了完全替换默认的行为,你可以实现ErrorController,并注册一个该类型的bean定义,或简单地添加一个ErrorAttributes类型的bean以使用现存的机制,只是替换显示的内容。
如果在某些条件下需要比较多的错误页面,内嵌的servlet容器提供了一个统一的JavaDSL(领域特定语言)来自定义错误处理。示例:
N.B.如果你为一个路径注册一个ErrorPage,最终被一个过滤器(Filter)处理(对于一些非Springweb框架,像Jersey和Wicket这很常见),然后过滤器需要显式注册为一个ERROR分发器(dispatcher)。
@BeanpublicFilterRegistrationBeanmyFilter(){FilterRegistrationBeanregistration=newFilterRegistrationBean();registration.setFilter(newMyFilter());...registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));returnregistration;}注:默认的FilterRegistrationBean没有包含ERROR分发器类型。
如果你正在开发一个使用超媒体的RESTfulAPI,SpringBoot将为SpringHATEOAS提供自动配置,这在多数应用中都工作良好。自动配置替换了对使用@EnableHypermediaSupport的需求,并注册一定数量的beans来简化构建基于超媒体的应用,这些beans包括一个LinkDiscoverer和配置好的用于将响应正确编排为想要的表示的ObjectMapper。ObjectMapper可以根据spring.jackson.*属性或一个存在的Jackson2ObjectMapperBuilderbean进行自定义。
通过使用@EnableHypermediaSupport,你可以控制SpringHATEOAS的配置。注意这会禁用上述的对ObjectMapper的自定义。
如果喜欢JAX-RS为REST端点提供的编程模型,你可以使用可用的实现替代SpringMVC。如果在你的应用上下文中将Jersey1.x和ApacheCeltix的Servlet或Filter注册为一个@Bean,那它们工作的相当好。Jersey2.x有一些原生的Spring支持,所以我们会在SpringBoot为它提供自动配置支持,连同一个启动器(starter)。
想要开始使用Jersey2.x只需要加入spring-boot-starter-jersey依赖,然后你需要一个ResourceConfig类型的@Bean,用于注册所有的端点(endpoints)。
@ComponentpublicclassJerseyConfigextendsResourceConfig{publicJerseyConfig(){register(Endpoint.class);}}所有注册的端点都应该被@Components和HTTP资源annotations(比如@GET)注解。
@Component@Path("/hello")publicclassEndpoint{@GETpublicStringmessage(){return"Hello";}}由于Endpoint是一个Spring组件(@Component),所以它的生命周期受Spring管理,并且你可以使用@Autowired添加依赖及使用@Value注入外部配置。Jerseyservlet将被注册,并默认映射到/*。你可以将@ApplicationPath添加到ResourceConfig来改变该映射。
默认情况下,Jersey将在一个ServletRegistrationBean类型的@Bean中被设置成名称为jerseyServletRegistration的Servlet。通过创建自己的相同名称的bean,你可以禁止或覆盖这个bean。你也可以通过设置spring.jersey.type=filter来使用一个Filter代替Servlet(在这种情况下,被覆盖或替换的@Bean是jerseyFilterRegistration)。该servlet有@Order属性,你可以通过spring.jersey.filter.order进行设置。不管是Servlet还是Filter注册都可以使用spring.jersey.init.*定义一个属性集合作为初始化参数传递过去。
SpringBoot支持内嵌的Tomcat,Jetty和Undertow服务器。多数开发者只需要使用合适的'StarterPOM'来获取一个完全配置好的实例即可。默认情况下,内嵌的服务器会在8080端口监听HTTP请求。
当使用内嵌的servlet容器时,你可以直接将servlet和filter注册为Spring的beans。在配置期间,如果你想引用来自application.properties的值,这是非常方便的。默认情况下,如果上下文只包含单一的Servlet,那它将被映射到根路径(/)。在多Servletbeans的情况下,bean的名称将被用作路径的前缀。过滤器会被映射到/*。
如果基于约定(convention-based)的映射不够灵活,你可以使用ServletRegistrationBean和FilterRegistrationBean类实现完全的控制。如果你的bean实现了ServletContextInitializer接口,也可以直接注册它们。
SpringBoot底层使用了一个新的ApplicationContext类型,用于对内嵌servlet容器的支持。EmbeddedWebApplicationContext是一个特殊类型的WebApplicationContext,它通过搜索一个单一的EmbeddedServletContainerFactorybean来启动自己。通常,TomcatEmbeddedServletContainerFactory,JettyEmbeddedServletContainerFactory或UndertowEmbeddedServletContainerFactory将被自动配置。
注:你通常不需要知道这些实现类。大多数应用将被自动配置,并根据你的行为创建合适的ApplicationContext和EmbeddedServletContainerFactory。
常见的Servlet容器设置可以通过SpringEnvironment属性进行配置。通常,你会把这些属性定义到application.properties文件中。常见的服务器设置包括:
编程方式的自定义如果需要以编程的方式配置内嵌的servlet容器,你可以注册一个实现EmbeddedServletContainerCustomizer接口的Springbean。EmbeddedServletContainerCustomizer提供对ConfigurableEmbeddedServletContainer的访问,ConfigurableEmbeddedServletContainer包含很多自定义的setter方法。
importorg.springframework.boot.context.embedded.*;importorg.springframework.stereotype.Component;@ComponentpublicclassCustomizationBeanimplementsEmbeddedServletContainerCustomizer{@Overridepublicvoidcustomize(ConfigurableEmbeddedServletContainercontainer){container.setPort(9000);}}直接自定义ConfigurableEmbeddedServletContainer如果上面的自定义手法过于受限,你可以自己注册TomcatEmbeddedServletContainerFactory,JettyEmbeddedServletContainerFactory或UndertowEmbeddedServletContainerFactory。
在内嵌的servlet容器中运行一个SpringBoot应用时(并打包成一个可执行的存档archive),容器对JSP的支持有一些限制。
默认的AuthenticationManager有一个单一的user('user'的用户名和随机密码会在应用启动时以INFO日志级别打印出来)。如下:
Usingdefaultsecuritypassword:78fa095d-3f4c-48b1-ad50-e24c31d5cf35注:如果你对日志配置进行微调,确保org.springframework.boot.autoconfigure.security类别能记录INFO信息,否则默认的密码不会被打印。
在一个web应用中你能得到的基本特性如下:
如果Actuator也在使用,你会发现:
Spring框架为使用SQL数据库提供了广泛的支持。从使用JdbcTemplate直接访问JDBC到完全的对象关系映射技术,比如Hibernate。SpringData提供一个额外的功能,直接从接口创建Repository实现,并使用约定从你的方法名生成查询。
Java的javax.sql.DataSource接口提供了一个标准的使用数据库连接的方法。传统做法是,一个DataSource使用一个URL连同相应的证书去初始化一个数据库连接。
开发应用时使用内存数据库是很实用的。显而易见地,内存数据库不需要提供持久化存储。你不需要在应用启动时填充数据库,也不需要在应用结束时丢弃数据。
示例:典型的POM依赖如下:
在生产环境中,数据库连接可以使用DataSource池进行自动配置。下面是选取一个特定实现的算法:
如果你使用spring-boot-starter-jdbc或spring-boot-starter-data-jpa'starterPOMs',你将会自动获取对tomcat-jdbc的依赖。
注:其他的连接池可以手动配置。如果你定义自己的DataSourcebean,自动配置不会发生。
注:既然SpringBoot能够从大多数数据库的url上推断出driver-class-name,那么你就不需要再指定它了。对于一个将要创建的DataSource连接池,我们需要能够验证Driver是否可用,所以我们会在做任何事情之前检查它。比如,如果你设置spring.datasource.driverClassName=com.mysql.jdbc.Driver,然后这个类就会被加载。
如果正在将SpringBoot应用部署到一个应用服务器,你可能想要用应用服务器内建的特性来配置和管理你的DataSource,并使用JNDI访问它。
spring.datasource.jndi-name属性可以用来替代spring.datasource.url,spring.datasource.username和spring.datasource.password去从一个特定的JNDI路径访问DataSource。比如,下面application.properties中的片段展示了如何获取JBoss定义的DataSource:
spring.datasource.jndi-name=java:jboss/datasources/customers4.7.2使用JdbcTemplateSpring的JdbcTemplate和NamedParameterJdbcTemplate类是被自动配置的,你可以在自己的beans中通过@Autowire直接注入它们。
importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.jdbc.core.JdbcTemplate;importorg.springframework.stereotype.Component;@ComponentpublicclassMyBean{privatefinalJdbcTemplatejdbcTemplate;@AutowiredpublicMyBean(JdbcTemplatejdbcTemplate){this.jdbcTemplate=jdbcTemplate;}//...}4.7.3JPA和SpringDataJava持久化API是一个允许你将对象映射为关系数据库的标准技术。spring-boot-starter-data-jpaPOM提供了一种快速上手的方式。它提供下列关键的依赖:
传统上,JPA实体类被定义到一个persistence.xml文件中。在SpringBoot中,这个文件不是必需的,并被'实体扫描'替代。默认情况下,在你主(main)配置类(被@EnableAutoConfiguration或@SpringBootApplication注解的类)下的所有包都将被查找。
任何被@Entity,@Embeddable或@MappedSuperclass注解的类都将被考虑。一个普通的实体类看起来像下面这样:
对于比较复杂的查询,你可以使用SpringData的Query来注解你的方法。
SpringData仓库通常继承自Repository或CrudRepository接口。如果你使用自动配置,包括在你的主配置类(被@EnableAutoConfiguration或@SpringBootApplication注解的类)的包下的仓库将会被搜索。
下面是一个传统的SpringData仓库:
默认情况下,只有在你使用内嵌数据库(H2,HSQL或Derby)时,JPA数据库才会被自动创建。你可以使用spring.jpa.*属性显示的设置JPA。比如,为了创建和删除表你可以将下面的配置添加到application.properties中:
spring.jpa.hibernate.ddl-auto=create-drop注:Hibernate自己内部对创建,删除表支持(如果你恰好记得这回事更好)的属性是hibernate.hbm2ddl.auto。使用spring.jpa.properties.*(前缀在被添加到实体管理器之前会被剥离掉),你可以设置Hibernate本身的属性,比如hibernate.hbm2ddl.auto。示例:spring.jpa.properties.hibernate.globally_quoted_identifiers=true将传递hibernate.globally_quoted_identifiers到Hibernate实体管理器。
默认情况下,DDL执行(或验证)被延迟到ApplicationContext启动。这也有一个spring.jpa.generate-ddl标识,如果Hibernate自动配置被激活,那该标识就不会被使用,因为ddl-auto设置粒度更细。
SpringData提供其他项目,用来帮你使用各种各样的NoSQL技术,包括MongoDB,Neo4J,Elasticsearch,Solr,Redis,Gemfire,Couchbase和Cassandra。SpringBoot为Redis,MongoDB,Elasticsearch,Solr和Gemfire提供自动配置。你可以充分利用其他项目,但你需要自己配置它们。具体查看projects.spring.io/spring-data中合适的参考文档。
Redis是一个缓存,消息中间件及具有丰富特性的键值存储系统。SpringBoot为Jedis客户端库和由SpringDataRedis提供的基于Jedis客户端的抽象提供自动配置。spring-boot-starter-redis'StarterPOM'为收集依赖提供一种便利的方式。
你可以注入一个自动配置的RedisConnectionFactory,StringRedisTemplate或普通的跟其他SpringBean相同的RedisTemplate实例。默认情况下,这个实例将尝试使用localhost:6379连接Redis服务器。
@ComponentpublicclassMyBean{privateStringRedisTemplatetemplate;@AutowiredpublicMyBean(StringRedisTemplatetemplate){this.template=template;}//...}如果你添加一个你自己的任何自动配置类型的@Bean,它将替换默认的(除了RedisTemplate的情况,它是根据bean的名称'redisTemplate'而不是它的类型进行排除的)。如果在classpath路径下存在commons-pool2,默认你会获得一个连接池工厂。
MongoDB是一个开源的NoSQL文档数据库,它使用一个JSON格式的模式(schema)替换了传统的基于表的关系数据。SpringBoot为使用MongoDB提供了很多便利,包括spring-boot-starter-data-mongodb'StarterPOM'。
你可以注入一个自动配置的org.springframework.data.mongodb.MongoDbFactory来访问Mongo数据库。默认情况下,该实例将尝试使用URL:mongodb://localhost/test连接一个MongoDB服务器。
importorg.springframework.data.mongodb.MongoDbFactory;importcom.mongodb.DB;@ComponentpublicclassMyBean{privatefinalMongoDbFactorymongo;@AutowiredpublicMyBean(MongoDbFactorymongo){this.mongo=mongo;}//...publicvoidexample(){DBdb=mongo.getDb();//...}}你可以通过设置spring.data.mongodb.uri来改变该url,或指定一个host/port。比如,你可能会在你的application.properties中设置如下的属性:
spring.data.mongodb.host=mongoserverspring.data.mongodb.port=27017注:如果没有指定spring.data.mongodb.port,那将使用默认的端口27017。你可以简单的从上面的示例中删除这一行。如果不使用SpringDataMongo,你可以注入com.mongodb.Mongobeans而不是使用MongoDbFactory。
SpringDataMongo提供了一个MongoTemplate类,它的设计和Spring的JdbcTemplate很相似。正如JdbcTemplate一样,SpringBoot会为你自动配置一个bean,你只需简单的注入它即可:
importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.data.mongodb.core.MongoTemplate;importorg.springframework.stereotype.Component;@ComponentpublicclassMyBean{privatefinalMongoTemplatemongoTemplate;@AutowiredpublicMyBean(MongoTemplatemongoTemplate){this.mongoTemplate=mongoTemplate;}//...}具体参考MongoOperationsJavadoc。
SpringData的仓库包括对MongoDB的支持。正如上面讨论的JPA仓库,基本的原则是查询会自动基于你的方法名创建。
实际上,不管是SpringDataJPA还是SpringDataMongoDB都共享相同的基础设施。所以你可以使用上面的JPA示例,并假设那个City现在是一个Mongo数据类而不是JPA@Entity,它将以同样的方式工作。
packagecom.example.myapp.domain;importorg.springframework.data.domain.*;importorg.springframework.data.repository.*;publicinterfaceCityRepositoryextendsRepository
ApacheSolr是一个搜索引擎。SpringBoot为solr客户端库及SpringDataSolr提供的基于solr客户端库的抽象提供了基本的配置。SpringBoot提供了一个用于聚集依赖的spring-boot-starter-data-solr'StarterPOM'。
你可以像其他Springbeans一样注入一个自动配置的SolrServer实例。默认情况下,该实例将尝试使用localhost:8983/solr连接一个服务器。
@ComponentpublicclassMyBean{privateSolrServersolr;@AutowiredpublicMyBean(SolrServersolr){this.solr=solr;}//...}如果你添加一个自己的SolrServer类型的@Bean,它将会替换默认的。
SpringData的仓库包括了对ApacheSolr的支持。正如上面讨论的JPA仓库,基本的原则是查询会自动基于你的方法名创建。
实际上,不管是SpringDataJPA还是SpringDataSolr都共享相同的基础设施。所以你可以使用上面的JPA示例,并假设那个City现在是一个@SolrDocument类而不是JPA@Entity,它将以同样的方式工作。
你可以像其他Springbeans那样注入一个自动配置的ElasticsearchTemplate或Elasticsearch客户端实例。默认情况下,该实例将尝试连接到一个本地内存服务器(在Elasticsearch项目中的一个NodeClient),但你可以通过设置spring.data.elasticsearch.clusterNodes为一个以逗号分割的host:port列表来将其切换到一个远程服务器(比如,TransportClient)。
@ComponentpublicclassMyBean{privateElasticsearchTemplatetemplate;@AutowiredpublicMyBean(ElasticsearchTemplatetemplate){this.template=template;}//...}如果你添加一个你自己的ElasticsearchTemplate类型的@Bean,它将替换默认的。
SpringData的仓库包括了对Elasticsearch的支持。正如上面讨论的JPA仓库,基本的原则是查询会自动基于你的方法名创建。
实际上,不管是SpringDataJPA还是SpringDataElasticsearch都共享相同的基础设施。所以你可以使用上面的JPA示例,并假设那个City现在是一个Elasticsearch@Document类而不是JPA@Entity,它将以同样的方式工作。
SpringFramework框架为集成消息系统提供了扩展(extensive)支持:从使用JmsTemplate简化JMSAPI,到实现一个完整异步消息接收的底层设施。
SpringAMQP提供一个相似的用于'高级消息队列协议'的特征集,并且SpringBoot也为RabbitTemplate和RabbitMQ提供了自动配置选项。
SpringWebsocket提供原生的STOMP消息支持,并且SpringBoot通过starters和一些自动配置也提供了对它的支持。
javax.jms.ConnectionFactory接口提供了一个标准的用于创建一个javax.jms.Connection的方法,javax.jms.Connection用于和JMS代理(broker)交互。
注:如果使用spring-boot-starter-hornetq,连接到一个已存在的HornetQ实例所需的依赖都会被提供,同时还有用于集成JMS的Spring基础设施。将org.hornetq:hornetq-jms-server添加到你的应用中,你就可以使用embedded模式。
没有涉及JNDI查找,目标是通过名字解析的,名字即可以使用HornetQ配置中的name属性,也可以是配置中提供的names。
如果发现ActiveMQ在classpath下可用,SpringBoot会配置一个ConnectionFactory。如果需要代理,将会开启一个内嵌的,已经自动配置好的代理(只要配置中没有指定代理URL)。
默认情况下,如果目标还不存在,ActiveMQ将创建一个,所以目标是通过它们提供的名称解析出来的。
如果你在一个应用服务器中运行你的应用,SpringBoot将尝试使用JNDI定位一个JMSConnectionFactory。默认情况会检查java:/JmsXA和java:/XAConnectionFactory。如果需要的话,你可以使用spring.jms.jndi-name属性来指定一个替代位置。
spring.jms.jndi-name=java:/MyConnectionFactory4.9.1.4发送消息Spring的JmsTemplate会被自动配置,你可以将它直接注入到你自己的beans中:
当JMS基础设施能够使用时,任何bean都能够被@JmsListener注解,以创建一个监听者端点。如果没有定义JmsListenerContainerFactory,一个默认的将会被自动配置。下面的组件在someQueue目标上创建一个监听者端点。
当发现一个JTA环境时,SpringBoot将使用Spring的JtaTransactionManager来管理事务。自动配置的JMS,DataSource和JPAbeans将被升级以支持XA事务。你可以使用标准的Springidioms,比如@Transactional,来参与到一个分布式事务中。如果你处于JTA环境里,但仍旧想使用本地事务,你可以将spring.jta.enabled属性设置为false来禁用JTA自动配置功能。
Atomikos是一个非常流行的开源事务管理器,它可以嵌入到你的SpringBoot应用中。你可以使用spring-boot-starter-jta-atomikosStarterPOM去获取正确的Atomikos库。SpringBoot会自动配置Atomikos,并将合适的depends-on应用到你的SpringBeans上,确保它们以正确的顺序启动和关闭。
注:为了确保多个事务管理器能够安全地和相应的资源管理器配合,每个Atomikos实例必须设置一个唯一的ID。默认情况下,该ID是Atomikos实例运行的机器上的IP地址。为了确保生产环境中该ID的唯一性,你需要为应用的每个实例设置不同的spring.jta.transaction-manager-id属性值。
Bitronix是另一个流行的开源JTA事务管理器实现。你可以使用spring-boot-starter-jta-bitronixstarterPOM为项目添加合适的Birtronix依赖。和Atomikos类似,SpringBoot将自动配置Bitronix,并对beans进行后处理(post-process)以确保它们以正确的顺序启动和关闭。
注:为了确保多个事务管理器能够安全地和相应的资源管理器配合,每个Bitronix实例必须设置一个唯一的ID。默认情况下,该ID是Bitronix实例运行的机器上的IP地址。为了确保生产环境中该ID的唯一性,你需要为应用的每个实例设置不同的spring.jta.transaction-manager-id属性值。
如果你将SpringBoot应用打包为一个war或ear文件,并将它部署到一个J2EE的应用服务器中,那你就能使用应用服务器内建的事务管理器。SpringBoot将尝试通过查找常见的JNDI路径(java:comp/UserTransaction,java:comp/TransactionManager等)来自动配置一个事务管理器。如果使用应用服务器提供的事务服务,你通常需要确保所有的资源都被应用服务器管理,并通过JNDI暴露出去。SpringBoot通过查找JNDI路径java:/JmsXA或java:/XAConnectionFactory获取一个ConnectionFactory来自动配置JMS,并且你可以使用spring.datasource.jndi-name属性配置你的DataSource。
SpringBoot提供很多有用的测试应用的工具。spring-boot-starter-testPOM提供SpringTest,JUnit,Hamcrest和Mockito的依赖。在spring-boot核心模块org.springframework.boot.test包下也有很多有用的测试工具。
如果使用spring-boot-starter-test‘StarterPOM’(在test作用域内),你将发现下列被提供的库:
这也有一些我们写测试用例时经常用到的库。如果它们不能满足你的要求,你可以随意添加其他的测试用的依赖库。
依赖注入最大的优点就是它能够让你的代码更容易进行单元测试。你只需简单的通过new操作符实例化对象,而不需要涉及Spring。你也可以使用模拟对象替换真正的依赖。
你常常需要在进行单元测试后,开始集成测试(在这个过程中只需要涉及到Spring的ApplicationContext)。在执行集成测试时,不需要部署应用或连接到其他基础设施是非常有用的。
一个SpringBoot应用只是一个SpringApplicationContext,所以在测试它时除了正常情况下处理一个vanillaSpringcontext外不需要做其他特别事情。唯一需要注意的是,如果你使用SpringApplication创建上下文,外部配置,日志和SpringBoot的其他特性只会在默认的上下文中起作用。
SpringBoot提供一个@SpringApplicationConfiguration注解用来替换标准的spring-test@ContextConfiguration注解。如果使用@SpringApplicationConfiguration来设置你的测试中使用的ApplicationContext,它最终将通过SpringApplication创建,并且你将获取到SpringBoot的其他特性。
示例如下:
@RunWith(SpringJUnit4ClassRunner.class)@SpringApplicationConfiguration(classes=SampleDataJpaApplication.class)publicclassCityRepositoryIntegrationTests{@AutowiredCityRepositoryrepository;//...}提示:上下文加载器会通过查找@WebIntegrationTest或@WebAppConfiguration注解来猜测你想测试的是否是web应用(例如,是否使用MockMVC,MockMVC和@WebAppConfiguration是spring-test的一部分)。
如果想让一个web应用启动,并监听它的正常的端口,你可以使用HTTP来测试它(比如,使用RestTemplate),并使用@WebIntegrationTest注解你的测试类(或它的一个父类)。这很有用,因为它意味着你可以对你的应用进行全栈测试,但在一次HTTP交互后,你需要在你的测试类中注入相应的组件并使用它们断言应用的内部状态。
@RunWith(SpringJUnit4ClassRunner.class)@SpringApplicationConfiguration(classes=SampleDataJpaApplication.class)@WebIntegrationTestpublicclassCityRepositoryIntegrationTests{@AutowiredCityRepositoryrepository;RestTemplaterestTemplate=newTestRestTemplate();//...interactwiththerunningserver}注:Spring测试框架在每次测试时会缓存应用上下文。因此,只要你的测试共享相同的配置,不管你实际运行多少测试,开启和停止服务器只会发生一次。
你可以为@WebIntegrationTest添加环境变量属性来改变应用服务器端口号,比如@WebIntegrationTest("server.port:9000")。此外,你可以将server.port和management.port属性设置为0来让你的集成测试使用随机的端口号,例如:
如果期望使用Spock测试一个SpringBoot应用,你应该将Spock的spock-spring模块依赖添加到应用的构建中。spock-spring将Spring的测试框架集成到了Spock里。
@ContextConfiguration(loader=SpringApplicationContextLoader.class)classExampleSpecextendsSpecification{//...}注:上面描述的注解在Spock中可以使用,比如,你可以使用@WebIntegrationTest注解你的Specification以满足测试需要。
打包进spring-boot的一些有用的测试工具类。
ConfigFileApplicationContextInitializer是一个ApplicationContextInitializer,可以用来测试加载SpringBoot的application.properties文件。当不需要使用@SpringApplicationConfiguration提供的全部特性时,你可以使用它。
@ContextConfiguration(classes=Config.class,initializers=ConfigFileApplicationContextInitializer.class)4.14.4.2EnvironmentTestUtilsEnvironmentTestUtils允许你快速添加属性到一个ConfigurableEnvironment或ConfigurableApplicationContext。只需简单的使用key=value字符串调用它:```javaEnvironmentTestUtils.addEnvironment(env,"org=Spring","name=Boot");
importorg.junit.Rule;importorg.junit.Test;importorg.springframework.boot.test.OutputCapture;importstaticorg.hamcrest.Matchers.*;importstaticorg.junit.Assert.*;publicclassMyTest{@RulepublicOutputCapturecapture=newOutputCapture();@TestpublicvoidtestName()throwsException{System.out.println("HelloWorld!");assertThat(capture.toString(),containsString("World"));}}4.14.4.4TestRestTemplateTestRestTemplate是一个方便进行集成测试的SpringRestTemplate子类。你会获取到一个普通的模板或一个发送基本HTTP认证(使用用户名和密码)的模板。在任何情况下,这些模板都表现出对测试友好:不允许重定向(这样你可以对响应地址进行断言),忽略cookies(这样模板就是无状态的),对于服务端错误不会抛出异常。推荐使用ApacheHTTPClient(4.3.2或更好的版本),但不强制这样做。如果在classpath下存在ApacheHTTPClient,TestRestTemplate将以正确配置的client进行响应。
你可以浏览spring-boot-autoconfigure的源码,查看我们提供的@Configuration类(查看META-INF/spring.factories文件)。
SpringBoot会检查你发布的jar中是否存在META-INF/spring.factories文件。该文件应该列出以EnableAutoConfiguration为key的配置类:
你几乎总是需要在你的auto-configuration类里添加一个或更多的@Condition注解。@ConditionalOnMissingBean注解是一个常见的示例,它经常用于允许开发者覆盖auto-configuration,如果他们不喜欢你提供的默认行为。
SpringBoot包含很多@Conditional注解,你可以在自己的代码中通过注解@Configuration类或单独的@Bean方法来重用它们。
@ConditionalOnBean和@ConditionalOnMissingBean注解允许根据特定beans是否出现来跳过配置。你可以使用value属性来指定beans(bytype),也可以使用name来指定beans(byname)。search属性允许你限制搜索beans时需要考虑的ApplicationContext的层次。
注:当@Configuration类被解析时@Conditional注解会被处理。Auto-configure@Configuration总是最后被解析(在所有用户定义beans后面),然而,如果你将那些注解用到常规的@Configuration类,需要注意不能引用那些还没有创建好的bean定义。
@ConditionalOnProperty注解允许根据一个SpringEnvironment属性来决定是否包含配置。可以使用prefix和name属性指定要检查的配置属性。默认情况下,任何存在的只要不是false的属性都会匹配。你也可以使用havingValue和matchIfMissing属性创建更高级的检测。
@ConditionalOnResource注解允许只有在特定资源出现时配置才会被包含。资源可以使用常见的Spring约定命名,例如file:/home/user/test.dat。
@ConditionalOnWebApplication和@ConditionalOnNotWebApplication注解允许根据应用是否为一个'web应用'来决定是否包含配置。一个web应用是任何使用SpringWebApplicationContext,定义一个session作用域或有一个StandardServletEnvironment的应用。
SpringBoot包含很多其他的特性,它们可以帮你监控和管理发布到生产环境的应用。你可以选择使用HTTP端点,JMX或远程shell(SSH或Telnet)来管理和监控应用。审计(Auditing),健康(health)和数据采集(metricsgathering)会自动应用到你的应用。
执行器(Actuator)的定义:执行器是一个制造业术语,指的是用于移动或控制东西的一个机械装置。一个很小的改变就能让执行器产生大量的运动。
基于Maven的项目想要添加执行器只需添加下面的'starter'依赖:
dependencies{compile("org.springframework.boot:spring-boot-starter-actuator")}5.2端点执行器端点允许你监控应用及与应用进行交互。SpringBoot包含很多内置的端点,你也可以添加自己的。例如,health端点提供了应用的基本健康信息。
端点暴露的方式取决于你采用的技术类型。大部分应用选择HTTP监控,端点的ID映射到一个URL。例如,默认情况下,health端点将被映射到/health。
下面的端点都是可用的:
注:根据一个端点暴露的方式,sensitive参数可能会被用做一个安全提示。例如,在使用HTTP访问sensitive端点时需要提供用户名/密码(如果没有启用web安全,可能会简化为禁止访问该端点)。
使用Spring属性可以自定义端点。你可以设置端点是否开启(enabled),是否敏感(sensitive),甚至它的id。例如,下面的application.properties改变了敏感性和beans端点的id,也启用了shutdown。
endpoints.beans.id=springbeansendpoints.beans.sensitive=falseendpoints.shutdown.enabled=true注:前缀endpoints+.+name被用来唯一的标识被配置的端点。
默认情况下,除了shutdown外的所有端点都是启用的。如果希望指定选择端点的启用,你可以使用endpoints.enabled属性。例如,下面的配置禁用了除info外的所有端点:
HealthIndicators返回的信息常常性质上有点敏感。例如,你可能不想将数据库服务器的详情发布到外面。因此,在使用一个未认证的HTTP连接时,默认只会暴露健康状态(healthstatus)。如果想将所有的健康信息暴露出去,你可以把endpoints.health.sensitive设置为false。
下面的HealthIndicators会被SpringBoot自动配置(在合适的时候):
例如,假设一个新的,代码为FATAL的Status被用于你的一个HealthIndicator实现中。为了配置严重程度,你需要将下面的配置添加到application属性文件中:
management.health.status.order:DOWN,OUT_OF_SERVICE,UNKNOWN,UP如果使用HTTP访问health端点,你可能想要注册自定义的status,并使用HealthMvcEndpoint进行映射。例如,你可以将FATAL映射为HttpStatus.SERVICE_UNAVAILABLE。
通过设置Spring属性info.*,你可以定义info端点暴露的数据。所有在info关键字下的Environment属性都将被自动暴露。例如,你可以将下面的配置添加到application.properties:
info.app.name=MyServiceinfo.app.description=Myawesomeserviceinfo.app.version=1.0.05.2.4.1在构建时期自动扩展info属性你可以使用已经存在的构建配置自动扩展info属性,而不是对在项目构建配置中存在的属性进行硬编码。这在Maven和Gradle都是可能的。
使用Maven自动扩展属性
对于Maven项目,你可以使用资源过滤来自动扩展info属性。如果使用spring-boot-starter-parent,你可以通过@..@占位符引用Maven的'projectproperties'。
project.artifactId=myprojectproject.name=Demoproject.version=X.X.X.Xproject.description=Demoprojectforinfoendpointinfo.build.artifact=@project.artifactId@info.build.name=@project.name@info.build.description=@project.description@info.build.version=@project.version@注:在上面的示例中,我们使用project.*来设置一些值以防止由于某些原因Maven的资源过滤没有开启。Maven目标spring-boot:run直接将src/main/resources添加到classpath下(出于热加载的目的)。这就绕过了资源过滤和自动扩展属性的特性。你可以使用exec:java替换该目标或自定义插件的配置,具体参考pluginusagepage。
如果你不使用starterparent,在你的pom.xml你需要添加(处于元素内):
通过配置Java插件的processResources任务,你也可以自动使用来自Gradle项目的属性扩展info属性。
processResources{expand(project.properties)}然后你可以通过占位符引用Gradle项目的属性:
info.build.name=${name}info.build.description=${description}info.build.version=${version}5.2.4.2Git提交信息info端点的另一个有用特性是,当项目构建完成后,它可以发布关于你的git源码仓库状态的信息。如果在你的jar中包含一个git.properties文件,git.branch和git.commit属性将被加载。
如果你正在开发一个SpringMVC应用,SpringBoot执行器自动将所有启用的端点通过HTTP暴露出去。默认约定使用端点的id作为URL路径,例如,health暴露为/health。
如果你的项目中添加的有SpringSecurity,所有通过HTTP暴露的敏感端点都会受到保护。默认情况下会使用基本认证(basicauthentication,用户名为user,密码为应用启动时在控制台打印的密码)。
你可以使用Spring属性改变用户名,密码和访问端点需要的安全角色。例如,你可能会在application.properties中添加下列配置:
有时候将所有的管理端口划分到一个路径下是有用的。例如,你的应用可能已经将/info作为他用。你可以用management.contextPath属性为管理端口设置一个前缀:
management.context-path=/manage上面的application.properties示例将把端口从/{id}改为/manage/{id}(比如,/manage/info)。
对于基于云的部署,使用默认的HTTP端口暴露管理端点(endpoints)是明智的选择。然而,如果你的应用是在自己的数据中心运行,那你可能倾向于使用一个不同的HTTP端口来暴露端点。
management.port属性可以用来改变HTTP端口:
management.port=8081由于你的管理端口经常被防火墙保护,不对外暴露也就不需要保护管理端点,即使你的主要应用是安全的。在这种情况下,classpath下会存在SpringSecurity库,你可以设置下面的属性来禁用安全管理策略(managementsecurity):
management.security.enabled=false(如果classpath下不存在SpringSecurity,那也就不需要显示的以这种方式来禁用安全管理策略,它甚至可能会破坏应用程序。)
你可以通过设置management.address属性来定义管理端点可以使用的地址。这在你只想监听内部或面向生产环境的网络,或只监听来自localhost的连接时非常有用。
下面的application.properties示例不允许远程管理连接:
management.port=8081management.address=127.0.0.15.3.5禁用HTTP端点如果不想通过HTTP暴露端点,你可以将管理端口设置为-1:management.port=-1
上述的限制可以被禁止,从而允许匿名用户完全访问health端点。想达到这个效果,可以将endpoints.health.sensitive设为false。
Java管理扩展(JMX)提供了一种标准的监控和管理应用的机制。默认情况下,SpringBoot在org.springframework.boot域下将管理端点暴露为JMXMBeans。
MBean的名称通常产生于端点的id。例如,health端点被暴露为org.springframework.boot/Endpoint/HealthEndpoint。
如果你的应用包含多个SpringApplicationContext,你会发现存在名称冲突。为了解决这个问题,你可以将endpoints.jmx.uniqueNames设置为true,这样MBean的名称总是唯一的。
你也可以自定义JMX域,所有的端点都在该域下暴露。这里有个application.properties示例:···javaendpoints.jmx.domain=myappendpoints.jmx.uniqueNames=true
如果不想通过JMX暴露端点,你可以将spring.jmx.enabled属性设置为false:
spring.jmx.enabled=false5.4.3使用Jolokia通过HTTP实现JMX远程管理Jolokia是一个JMX-HTTP桥,它提供了一种访问JMXbeans的替代方法。想要使用Jolokia,只需添加org.jolokia:jolokia-core的依赖。例如,使用Maven需要添加下面的配置:
Jolokia有很多配置,传统上一般使用servlet参数进行设置。使用SpringBoot,你可以在application.properties中通过把参数加上jolokia.config.前缀来设置:
jolokia.config.debug=true5.4.3.2禁用Jolokia如果你正在使用Jolokia,但不想让SpringBoot配置它,只需要简单的将endpoints.jolokia.enabled属性设置为false:
endpoints.jolokia.enabled=false5.4.4使用远程shell来进行监控和管理SpringBoot支持集成一个称为'CRaSH'的Javashell。你可以在CRaSH中使用ssh或telnet命令连接到运行的应用。为了启用远程shell支持,你只需添加spring-boot-starter-remote-shell的依赖:
默认情况下,远程shell监听端口2000以等待连接。默认用户名为user,密码为随机生成的,并且在输出日志中会显示。如果应用使用SpringSecurity,该shell默认使用相同的配置。如果不是,将使用一个简单的认证策略,你可能会看到类似这样的信息:
Usingdefaultpasswordforshellaccess:ec03e16c-4cf4-49ee-b745-7c8255c1dd7eLinux和OSX用户可以使用ssh连接远程shell,Windows用户可以下载并安装PuTTY。
$ssh-p2000user@localhostuser@localhost'spassword:._________/\\/___'_____(_)______\\\\(()\___|'_|'_||'_\/_`|\\\\\\/___)||_)|||||||(_||))))'|____|.__|_||_|_||_\__,|////=========|_|==============|___/=/_/_/_/::SpringBoot::(v1.3.0.BUILD-SNAPSHOT)onmyhost输入help可以获取一系列命令的帮助。Springboot提供metrics,beans,autoconfig和endpoint命令。
有很多有趣的方式可以用来扩展远程shell。
5.4.4.2.1远程shell命令你可以使用Groovy或Java编写其他的shell命令(具体参考CRaSH文档)。默认情况下,SpringBoot会搜索以下路径的命令:
注:可以通过shell.commandPathPatterns属性改变搜索路径。
下面是一个从src/main/resources/commands/hello.groovy加载的'helloworld'命令:
packagecommandsimportorg.crsh.cli.Usageimportorg.crsh.cli.Commandclasshello{@Usage("SayHello")@Commanddefmain(InvocationContextcontext){return"Hello"}}SpringBoot将一些额外属性添加到了InvocationContext,你可以在命令中访问它们:
5.4.4.2.2远程shell插件除了创建新命令,也可以扩展CRaSHshell的其他特性。所有继承org.crsh.plugin.CRaSHPlugin的SpringBeans将自动注册到shell。
所有HTTP请求的指标都被自动记录,所以如果点击metrics端点,你可能会看到类似以下的响应:
{"counter.status.200.root":20,"counter.status.200.metrics":3,"counter.status.200.star-star":5,"counter.status.401.root":4,"gauge.response.star-star":6,"gauge.response.root":2,"gauge.response.metrics":3,"classes":5808,"classes.loaded":5808,"classes.unloaded":0,"heap":3728384,"heap.committed":986624,"heap.init":262144,"heap.used":52765,"mem":986624,"mem.free":933858,"processors":8,"threads":15,"threads.daemon":11,"threads.peak":15,"uptime":494836,"instance.uptime":489782,"datasource.primary.active":5,"datasource.primary.usage":0.25}此处我们可以看到基本的memory,heap,classloading,processor和threadpool信息,连同一些HTTP指标。在该实例中,root('/'),/metricsURLs分别返回20次,3次HTTP200响应。同时可以看到rootURL返回了4次HTTP401(unauthorized)响应。双asterix(star-star)来自于被SpringMVC/**匹配到的一个请求(通常为一个静态资源)。
SpringBoot暴露以下系统指标:
SpringBoot会为你应用中定义的支持的DataSource暴露以下指标:
所有的数据源指标共用datasoure.前缀。该前缀对每个数据源都非常合适:
通过注册一个自定义版本的DataSourcePublicMetricsbean,你可以覆盖部分或全部的默认行为。默认情况下,SpringBoot提供支持所有数据源的元数据;如果你喜欢的数据源恰好不被支持,你可以添加另外的DataSourcePoolMetadataProviderbeans。具体参考DataSourcePoolMetadataProvidersConfiguration。
下面是一个简单的示例,它记录了方法调用的次数:
想要添加额外的,每次指标端点被调用时都会重新计算的度量指标,只需简单的注册其他的PublicMetrics实现bean(s)。默认情况下,端点会聚合所有这样的beans,通过定义自己的MetricsEndpoint可以轻易改变这种情况。
没有什么能阻止你直接将MetricRepository的数据导入应用中的后端存储,但我们建议你使用默认的InMemoryMetricRepository(如果担心堆使用情况,你可以使用自定义的Map实例),然后通过一个scheduledexportjob填充后端仓库(意思是先将数据保存到内存中,然后通过异步job将数据持久化到数据库,可以提高系统性能)。通过这种方式,你可以将指标数据缓存到内存中,然后通过低频率或批量导出来减少网络拥堵。SpringBoot提供一个Exporter接口及一些帮你开始的基本实现。
用户可以通过使用合适类型的指标名称作为前缀来创建Dropwizard指标(比如,histogram.,meter.)。
如果你的classpath下存在'SpringMessaging'jar,一个名为metricsChannel的MessageChannel将被自动创建(除非已经存在一个)。此外,所有的指标更新事件作为'messages'发布到该渠道上。订阅该渠道的客户端可以进行额外的分析或行动。
SpringBoot执行器具有一个灵活的审计框架,一旦SpringSecurity处于活动状态(默认抛出'authenticationsuccess','failure'和'accessdenied'异常),它就会发布事件。这对于报告非常有用,同时可以基于认证失败实现一个锁定策略。
你也可以使用审计服务处理自己的业务事件。为此,你可以将存在的AuditEventRepository注入到自己的组件,并直接使用它,或者只是简单地通过SpringApplicationEventPublisher发布AuditApplicationEvent(使用ApplicationEventPublisherAware)。
对于所有的HTTP请求SpringBoot自动启用追踪。你可以查看trace端点,并获取最近一些请求的基本信息:
默认情况下,使用的InMemoryTraceRepository将存储最新的100个事件。如果需要扩展该容量,你可以定义自己的InMemoryTraceRepository实例。如果需要,你可以创建自己的替代TraceRepository实现。
在SpringBoot执行器中,你可以找到几个创建有利于进程监控的文件的类:
默认情况下,这些writers没有被激活,但你可以使用下面描述的任何方式来启用它们。
你需要激活META-INF/spring.factories文件里的listener(s):
org.springframework.context.ApplicationListener=\org.springframework.boot.actuate.system.ApplicationPidFileWriter,org.springframework.boot.actuate.system.EmbeddedServerPortFileWriter5.4.8.2以编程方式你也可以通过调用SpringApplication.addListeners(…)方法来激活一个监听器,并传递相应的Writer对象。该方法允许你通过Writer构造器自定义文件名和路径。
对于大多数流行云PaaS(平台即服务)提供商,SpringBoot的可执行jars就是为它们准备的。这些提供商往往要求你带上自己的容器;它们管理应用的进程(不特别针对Java应用程序),所以它们需要一些中间层来将你的应用适配到云概念中的一个运行进程。
两个流行的云提供商,Heroku和CloudFoundry,采取一个打包('buildpack')方法。为了启动你的应用程序,不管需要什么,buildpack都会将它们打包到你的部署代码:它可能是一个JDK和一个java调用,也可能是一个内嵌的webserver,或者是一个成熟的应用服务器。buildpack是可插拔的,但你最好尽可能少的对它进行自定义设置。这可以减少不受你控制的功能范围,最小化部署和生产环境的发散。
理想情况下,你的应用就像一个SpringBoot可执行jar,所有运行需要的东西都打包到它内部。
如果不指定其他打包方式,CloudFoundry会启用它提供的默认打包方式。CloudFoundry的Javabuildpack对Spring应用有出色的支持,包括SpringBoot。你可以部署独立的可执行jar应用,也可以部署传统的.war形式的应用。
一旦你构建了应用(比如,使用mvncleanpackage)并安装了cf命令行工具,你可以使用下面的cfpush命令(将路径指向你编译后的.jar)来部署应用。在发布一个应用前,确保你已登陆cf命令行客户端。
$cfpushacloudyspringtime-ptarget/demo-0.0.1-SNAPSHOT.jar查看cfpush文档获取更多可选项。如果相同目录下存在manifest.yml,CloudFoundry会使用它。
就此,cf开始上传你的应用:
Uploadingacloudyspringtime...OKPreparingtostartacloudyspringtime...OK----->Downloadedapppackage(8.9M)----->JavaBuildpacksource:system----->DownloadingOpenJDK1.7.0_51from.../x86_64/openjdk-1.7.0_51.tar.gz(1.8s)ExpandingOpenJDKto.java-buildpack/open_jdk(1.2s)----->DownloadingSpringAutoReconfigurationfrom0.8.7.../auto-reconfiguration-0.8.7.jar(0.1s)----->Uploadingdroplet(44M)Checkingstatusofapp'acloudyspringtime'...0of1instancesrunning(1starting)...0of1instancesrunning(1down)...0of1instancesrunning(1starting)...1of1instancesrunning(1running)Appstarted恭喜!应用现在处于运行状态!
检验部署应用的状态是很简单的:
默认情况下,运行应用的元数据和服务连接信息被暴露为应用的环境变量(比如,$VCAP_SERVICES)。采用这种架构的原因是因为CloudFoundry多语言特性(任何语言和平台都支持作为buildpack)。进程级别的环境变量是语言无关(languageagnostic)的。
环境变量并不总是有利于设计最简单的API,所以SpringBoot自动提取它们,然后将这些数据导入能够通过SpringEnvironment抽象访问的属性里:
@ComponentclassMyBeanimplementsEnvironmentAware{privateStringinstanceId;@OverridepublicvoidsetEnvironment(Environmentenvironment){this.instanceId=environment.getProperty("vcap.application.instance_id");}//...}所有的CloudFoundry属性都以vcap作为前缀。你可以使用vcap属性获取应用信息(比如应用的公共URL)和服务信息(比如数据库证书)。具体参考VcapApplicationListenerJavadoc。
Heroku是另外一个流行的Paas平台。想要自定义Heroku的构建过程,你可以提供一个Procfile,它提供部署一个应用所需的指令。Heroku为Java应用分配一个端口,确保能够路由到外部URI。
你必须配置你的应用监听正确的端口。下面是用于我们的starterREST应用的Procfile:
web:java-Dserver.port=$PORT-jartarget/demo-0.0.1-SNAPSHOT.jarSpringBoot将-D参数作为属性,通过一个Spring的Environment实例访问。server.port配置属性适合于内嵌的Tomcat,Jetty或Undertow实例启用时使用。$PORT环境变量被分配给HerokuPaas使用。
Heroku默认使用Java1.6。只要你的Maven或Gradle构建时使用相同的版本就没问题(Maven用户可以设置java.version属性)。如果你想使用JDK1.7,在你的pom.xml和Procfile临近处创建一个system.properties文件。在该文件中添加以下设置:
java.runtime.version=1.7这就是你需要做的一切。对于Heroku部署来说,经常做的工作就是使用gitpush将代码推送到生产环境。
Openshift是RedHat公共(和企业)PaaS解决方案。和Heroku相似,它也是通过运行被git提交触发的脚本来工作的,所以你可以使用任何你喜欢的方式编写SpringBoot应用启动脚本,只要Java运行时环境可用(这是在Openshift上可以要求的一个标准特性)。为了实现这样的效果,你可以使用DIYCartridge,并在.openshift/action_scripts下hooks你的仓库:
基本模式如下:
1.确保Java和构建工具已被远程安装,比如使用一个pre_buildhook(默认会安装Java和Maven,不会安装Gradle)。
2.使用一个buildhook去构建你的jar(使用Maven或Gradle),比如
#!/bin/bashcd$OPENSHIFT_REPO_DIRmvnpackage-s.openshift/settings.xml-DskipTests=true3.添加一个调用java-jar…的starthook
#!/bin/bashcd$OPENSHIFT_REPO_DIRnohupjava-jartarget/*.jar--server.port=${OPENSHIFT_DIY_PORT}--server.address=${OPENSHIFT_DIY_IP}&4.使用一个stophook
#!/bin/bashsource$OPENSHIFT_CARTRIDGE_SDK_BASHPID=$(ps-ef|grepjava.*\.jar|grep-vgrep|awk'{print$2}')if[-z"$PID"]thenclient_result"Applicationisalreadystopped"elsekill$PIDfi5.将内嵌的服务绑定到平台提供的在application.properties定义的环境变量,比如
spring.datasource.url:jdbc:mysql://${OPENSHIFT_MYSQL_DB_HOST}:${OPENSHIFT_MYSQL_DB_PORT}/${OPENSHIFT_APP_NAME}spring.datasource.username:${OPENSHIFT_MYSQL_DB_USERNAME}spring.datasource.password:${OPENSHIFT_MYSQL_DB_PASSWORD}在Openshift的网站上有一篇runningGradleinOpenshift博客,如果想使用gradle构建运行的应用可以参考它。由于一个Gradlebug,你不能使用高于1.6版本的Gradle。
GoogleAppEngine跟Servlet2.5API是有联系的,所以在不修改的情况系你是不能部署一个Spring应用的。具体查看本指南的Servlet2.5章节Container.md)。
SpringBootCLI是一个命令行工具,如果想使用Spring进行快速开发可以使用它。它允许你运行Groovy脚本,这意味着你可以使用熟悉的类Java语法,并且没有那么多的模板代码。你也可以启动一个新的项目或为SpringBootCLI编写自己的命令。
一旦安装好CLI,你可以输入spring来运行它。如果你不使用任何参数运行spring,将会展现一个简单的帮助界面:
$springusage:spring[--help][--version][]Availablecommandsare:run[options][--][args]Runaspringgroovyscript...morecommandhelpisshownhere你可以使用help获取任何支持命令的详细信息。例如:
$springhelprunspringrun-Runaspringgroovyscriptusage:springrun[options][--][args]OptionDescription-------------------autoconfigure[Boolean]Addautoconfigurecompilertransformations(default:true)--classpath,-cpAdditionalclasspathentries-e,--editOpenthefilewiththedefaultsystemeditor--no-guess-dependenciesDonotattempttoguessdependencies--no-guess-importsDonotattempttoguessimports-q,--quietQuietlogging-v,--verboseVerboseloggingofdependencyresolution--watchWatchthespecifiedfileforchangesversion命令提供一个检查你正在使用的SpringBoot版本的快速方式:
$springversionSpringCLIv1.3.0.BUILD-SNAPSHOT7.2.1使用CLI运行应用你可以使用run命令编译和运行Groovy源代码。SpringBootCLI完全自包含,以致于你不需要安装任何外部的Groovy。
下面是一个使用Groovy编写的"helloworld"web应用:hello.grooy
@RestControllerclassWebApplication{@RequestMapping("/")Stringhome(){"HelloWorld!"}}想要编译和运行应用,输入:
$springrunhello.groovy想要给应用传递命令行参数,你需要使用一个--来将它们和"spring"命令参数区分开来。例如:
$springrunhello.groovy----server.port=9000想要设置JVM命令行参数,你可以使用JAVA_OPTS环境变量,例如:
SpringBoot进一步延伸了该技术,它会基于你的代码尝试推导你"grab"哪个库。例如,由于WebApplication代码上使用了@RestController注解,"Tomcat"和"SpringMVC"将被获取(grabbed)。
下面items被用作"grabhints":
SpringBoot扩展Groovy标准"@Grab"注解使其能够允许你指定一个没有group或version的依赖,例如@Grab('freemarker')。artifact’s的组和版本是通过查看SpringBoot的依赖元数据推断出来的。注意默认的元数据是和你使用的CLI版本绑定的-只有在你迁移到一个CLI新版本时它才会改变,这样当你的依赖改变时你就可以控制了。在附录的表格中可以查看默认元数据包含的依赖和它们的版本。
为了帮助你减少Groovy代码量,一些import语句被自动包含进来了。注意上面的示例中引用@Component,@RestController和@RequestMapping而没有使用全限定名或import语句。
注:很多Spring注解在不使用import语句的情况下可以正常工作。尝试运行你的应用,看一下在添加imports之前哪些会失败。
跟等效的Java应用不同,你不需要在Groovy脚本中添加一个publicstaticvoidmain(String[]args)方法。SpringBoot会使用你编译后的代码自动创建一个SpringApplication。
SpringBoot提供一个新的@GrabMetadata注解,你可以使用它提供自定义的依赖元数据,以覆盖SpringBoot的默认配置。该元数据通过使用提供一个或多个配置文件坐标的注解来指定(使用一个属性标识符"type"部署到Maven仓库).。配置文件中的每个实体必须遵循group:module=version的格式。
`@GrabMetadata("com.example.custom-versions:1.0.0")`将会加载Maven仓库处于com/example/custom-versions/1.0.0/下的custom-versions-1.0.0.properties文件。
`@GrabMetadata(["com.example.custom-versions:1.0.0","com.example.more-versions:1.0.0"])`意味着位于more-versions的属性将覆盖位于custom-versions的属性。
你可以在任何能够使用@Grab的地方使用@GrabMetadata,然而,为了确保元数据的顺序一致,你在应用程序中最多只能使用一次@GrabMetadata。SpringIOPlatform是一个非常有用的依赖元数据源(SpringBoot的超集),例如:
@GrabMetadata('io.spring.platform:platform-versions:1.0.4.RELEASE')7.2.2测试你的代码test命令允许你编译和运行应用程序的测试用例。常规使用方式如下:
$springtestapp.groovytests.groovyTotal:1,Success:1,:Failures:0Passedtrue在这个示例中,test.groovy包含JUnit@Test方法或SpockSpecification类。所有的普通框架注解和静态方法在不使用import导入的情况下,仍旧可以使用。
下面是我们使用的test.groovy文件(含有一个JUnit测试):
classApplicationTests{@TestvoidhomeSaysHello(){assertEquals("HelloWorld!",newWebApplication().home())}}注:如果有多个测试源文件,你可以倾向于使用一个test目录来组织它们。
你可以在所有接收文件输入的命令中使用shell通配符。这允许你轻松处理来自一个目录下的多个文件,例如:
$springrun*.groovy如果你想将'test'或'spec'代码从主应用代码中分离,这项技术就十分有用了:
$springtestapp/*.groovytest/*.groovy7.2.4应用打包你可以使用jar命令打包应用程序为一个可执行的jar文件。例如:
$springjarmy-app.jar*.groovy最终的jar包括编译应用产生的类和所有依赖,这样你就可以使用java-jar来执行它了。该jar文件也包括来自应用classpath的实体。你可以使用--include和--exclude添加明确的路径(两者都是用逗号分割,同样都接收值为'+'和'-'的前缀,'-'意味着它们将从默认设置中移除)。默认包含(includes):
public/**,resources/**,static/**,templates/**,META-INF/**,*默认排除(excludes):
.*,repository/**,build/**,target/**,**/*.jar,**/*.groovy查看springhelpjar可以获得更多信息。
init命令允许你使用start.spring.io在不离开shell的情况下创建一个新的项目。例如:
$springshellSpringBoot(v1.3.0.BUILD-SNAPSHOT)HitTABtocomplete.Type\'help'andhitRETURNforhelp,and\'exit'toquit.从内嵌shell中可以直接运行其他命令:
$versionSpringCLIv1.3.0.BUILD-SNAPSHOT内嵌shell支持ANSI颜色输出和tab补全。如果需要运行一个原生命令,你可以使用$前缀。点击ctrl-c将退出内嵌shell。
使用install命令可以为CLI添加扩展。该命令接收一个或多个格式为group:artifact:version的artifact坐标集。例如:
$springinstallcom.example:spring-boot-cli-extension:1.0.0.RELEASE除了安装你提供坐标的artifacts标识外,所有依赖也会被安装。使用uninstall可以卸载一个依赖。和install命令一样,它接收一个或多个格式为group:artifact:version的artifact坐标集。例如:
$springuninstallcom.example:spring-boot-cli-extension:1.0.0.RELEASE它会通过你提供的坐标卸载相应的artifacts标识和它们的依赖。
为了卸载所有附加依赖,你可以使用--all选项。例如:
SpringBoot为Maven和Gradle提供构建工具插件。该插件提供各种各样的特性,包括打包可执行jars。本节提供关于插件的更多详情及用于扩展一个不支持的构建系统所需的帮助信息。如果你是刚刚开始,那可能需要先阅读PartIII,“UsingSpringBoot”章节的“Chapter13,Buildsystems”。
SpringBootMaven插件为Maven提供SpringBoot支持,它允许你打包可执行jar或war存档,然后就地运行应用。为了使用它,你需要使用Maven3.2(或更高版本)。
想要使用SpringBootMaven插件只需简单地在你的pom.xml的plugins部分包含相应的XML:
$mvnpackage$lstarget/*.jartarget/myproject-1.0.0.jartarget/myproject-1.0.0.jar.original如果不包含像上面那样的
$mvnpackagespring-boot:repackage$lstarget/*.jartarget/myproject-1.0.0.jartarget/myproject-1.0.0.jar.original如果使用一个里程碑或快照版本,你还需要添加正确的pluginRepository元素:
为了构建和运行一个项目的artifact,你可以输入以下命令:
$mvnpackage$java-jartarget/mymodule-0.0.1-SNAPSHOT.jar为了构建一个即是可执行的,又能部署到一个外部容器的war文件,你需要标记内嵌容器依赖为"provided",例如:
在插件信息页面有高级的配置选项和示例。
SpringBootGradle插件为Gradle提供SpringBoot支持,它允许你打包可执行jar或war存档,运行SpringBoot应用,对于"神圣的"依赖可以在你的build.gradle文件中省略版本信息。
想要使用SpringBootGradle插件,你只需简单的包含一个buildscript依赖,并应用spring-boot插件:
buildscript{dependencies{classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.0.BUILD-SNAPSHOT")}}applyplugin:'spring-boot'如果想使用一个里程碑或快照版本,你可以添加相应的repositories引用:
dependencies{compile("org.thymeleaf:thymeleaf-spring4:2.1.1.RELEASE")}8.2.2.1自定义版本管理如果你需要不同于SpringBoot的"blessed"依赖,有可能的话可以自定义ResolutionStrategy使用的版本。替代的版本元数据使用versionManagement配置。例如:
dependencies{versionManagement("com.mycorp:mycorp-versions:1.0.0.RELEASE@properties")compile("org.springframework.data:spring-data-hadoop")}版本信息需要作为一个.properties文件发布到一个仓库中。对于上面的示例,mycorp-versions.properties文件可能包含以下内容:
org.springframework.data\:spring-data-hadoop=2.0.0.RELEASE属性文件优先于SpringBoot默认设置,如果有必要的话可以覆盖版本号。
为了确保正确的排除被实际应用,SpringBootGradle插件将自动添加排除规则。所有排除被定义在spring-boot-dependenciesPOM,并且针对"starter"POMs的隐式规则也会被添加。
如果不想自动应用排除规则,你可以使用以下配置:
springBoot{applyExcludeRules=false}8.2.4打包可执行jar和war文件一旦spring-boot插件被应用到你的项目,它将使用bootRepackage任务自动尝试重写存档以使它们能够执行。为了构建一个jar或war,你需要按通常的方式配置项目。
你想启动的main类既可以通过一个配置选项指定,也可以通过向manifest添加一个Main-Class属性。如果你没有指定main类,该插件会搜索带有publicstaticvoidmain(String[]args)方法的类。
为了构建和运行一个项目artifact,你可以输入以下内容:
$gradlebuild$java-jarbuild/libs/mymodule-0.0.1-SNAPSHOT.jar为了构建一个即能执行也可以部署到外部容器的war包,你需要将内嵌容器依赖标记为"providedRuntime",比如:
为了在不先构建jar的情况下运行项目,你可以使用"bootRun"任务:
$gradlebootRun默认情况下,以这种方式运行项目可以让你的静态classpath资源(比如,默认位于src/main/resources下)在应用运行期间被重新加载。使静态资源可以重新加载意味着bootRun任务不会使用processResources任务的输出,比如,当调用bootRun时,你的应用将以资源未处理的形式来使用它们。
你可以禁止直接使用静态classpath资源。这意味着资源不再是可重新加载的,但processResources任务的输出将会被使用。想要这样做,只需将bootRun任务的addResources设为false:
bootRun{addResources=false}8.2.6SpringBoot插件配置Gradle插件自动扩展你的构建脚本DSL,它为脚本添加一个springBoot元素以此作为Boot插件的全局配置。你可以像配置其他Gradle扩展那样为springBoot设置相应的属性(下面有配置选项列表)。
springBoot{backupSource=false}8.2.7Repackage配置该插件添加了一个bootRepackage任务,你可以直接配置它,比如:
bootRepackage{mainClass='demo.Application'}下面是可用的配置选项:
有时候不打包解析自compile,runtime和provided作用域的默认依赖可能更合适些。如果创建的可执行jar被原样运行,你需要将所有的依赖内嵌进该jar中;然而,如果目的是explode一个jar文件,并手动运行main类,你可能在CLASSPATH下已经有一些可用的库了。在这种情况下,你可以使用不同的依赖集重新打包(repackage)你的jar。
使用自定义的配置将自动禁用来自compile,runtime和provided作用域的依赖解析。自定义配置即可以定义为全局的(处于springBoot部分内),也可以定义为任务级的。
taskclientJar(type:Jar){appendix='client'fromsourceSets.main.outputexclude('**/*Something*')}taskclientBoot(type:BootRepackage,dependsOn:clientJar){withJarTask=clientJarcustomConfiguration="mycustomconfiguration"}在以上示例中,我们创建了一个新的clientJarJar任务从你编译后的源中打包一个自定义文件集。然后我们创建一个新的clientBootBootRepackage任务,并让它使用clientJar任务和mycustomconfiguration。
可用的配置选项如下:
当spring-boot被应用到你的Gradle项目,一个默认的名叫bootRepackage的任务被自动创建。bootRepackage任务依赖于Gradleassemble任务,当执行时,它会尝试找到所有限定符为空的jarartifacts(也就是说,tests和sourcesjars被自动跳过)。
由于bootRepackage查找'所有'创建jarartifacts的事实,Gradle任务执行的顺序就非常重要了。多数项目只创建一个单一的jar文件,所以通常这不是一个问题。然而,如果你正打算创建一个更复杂的,使用自定义jar和BootRepackage任务的项目setup,有几个方面需要考虑。
如果'仅仅'从项目创建自定义jar文件,你可以简单地禁用默认的jar和bootRepackage任务:
jar.enabled=falsebootRepackage.enabled=false另一个选项是指示默认的bootRepackage任务只能使用一个默认的jar任务:
bootRepackage.withJarTask=jar如果你有一个默认的项目setup,在该项目中,主(main)jar文件被创建和重新打包。并且,你仍旧想创建额外的自定义jars,你可以将自定义的repackage任务结合起来,然后使用dependsOn,这样bootJars任务就会在默认的bootRepackage任务执行以后运行:
taskbootJarsbootJars.dependsOn=[clientBoot1,clientBoot2,clientBoot3]build.dependsOn(bootJars)上面所有方面经常用于避免一个已经创建的bootjar又被重新打包的情况。重新打包一个存在的bootjar不是什么大问题,但你可能会发现它包含不必要的依赖。
SpringBootMaven和Gradle插件都利用spring-boot-loader-tools来实际地产生jars。如果需要,你也可以自由地直接使用该库。
使用org.springframework.boot.loader.tools.Repackager可以将一个存在的存档重新打包,这样它就变成一个自包含的可执行存档。Repackager类需要提供单一的构造器参数,它引用一个存在的jar或war包。使用两个可用的repackage()方法中的一个来替换原始的文件或写入一个新的目标。在repackager运行前还可以设置各种配置。
如果你的存档已经包含libraries,你可以使用Libraries.NONE。
如果你没有使用Repackager.setMainClass()指定一个main类,该repackager将使用ASM去读取class文件,然后尝试查找一个合适的,具有publicstaticvoidmain(String[]args)方法的类。如果发现多个候选者,将会抛出异常。
这里是一个传统的repackage示例:
Repackagerrepackager=newRepackager(sourceJarFile);repackager.setBackupSource(false);repackager.repackage(newLibraries(){@OverridepublicvoiddoWithLibraries(LibraryCallbackcallback)throwsIOException{//Buildsystemspecificimplementation,callbackforeachdependency//callback.library(newLibrary(nestedFile,LibraryScope.COMPILE));}});How-to指南本章节将回答一些常见的"我该怎么做"类型的问题,这些问题在我们使用SpringBoot时经常遇到。这绝不是一个详尽的列表,但它覆盖了很多方面。
SpringBoot自动配置总是尝试尽最大努力去做正确的事,但有时候会失败并且很难说出失败原因。
在每个SpringBootApplicationContext中都存在一个相当有用的ConditionEvaluationReport。如果开启DEBUG日志输出,你将会看到它。如果你使用spring-boot-actuator,则会有一个autoconfig的端点,它将以JSON形式渲染该报告。可以使用它调试应用程序,并能查看SpringBoot运行时都添加了哪些特性(及哪些没添加)。
通过查看源码和javadoc可以获取更多问题的答案。以下是一些经验:
每个SpringApplication都有ApplicationListeners和ApplicationContextInitializers,用于自定义上下文(context)或环境(environment)。SpringBoot从META-INF/spring.factories下加载很多这样的内部使用的自定义。有很多方法可以注册其他的自定义:
SpringApplication会给监听器(即使是在上下文被创建之前就存在的)发送一些特定的ApplicationEvents,然后也会注册监听ApplicationContext发布的事件的监听器。查看SpringBoot特性章节中的Section22.4,“Applicationeventsandlisteners”可以获取一个完整列表。
不是所有的Spring应用都必须是web应用(或web服务)。如果你想在main方法中执行一些代码,但需要启动一个Spring应用去设置需要的底层设施,那使用SpringBoot的SpringApplication特性可以很容易实现。SpringApplication会根据它是否需要一个web应用来改变它的ApplicationContext类。首先你需要做的是去掉servletAPI依赖,如果不能这样做(比如,基于相同的代码运行两个应用),那你可以明确地调用SpringApplication.setWebEnvironment(false)或设置applicationContextClass属性(通过JavaAPI或使用外部配置)。你想运行的,作为业务逻辑的应用代码可以实现为一个CommandLineRunner,并将上下文降级为一个@Bean定义。
SpringApplication已经被属性化(主要是setters),所以你可以在创建应用时使用它的JavaAPI修改它的行为。或者你可以使用properties文件中的spring.main.*来外部化(在应用代码外配置)这些配置。比如,在application.properties中可能会有以下内容:
spring.main.web_environment=falsespring.main.show_banner=false然后SpringBoot在启动时将不会显示banner,并且该应用也不是一个web应用。
默认情况下,来自不同源的属性以一个定义好的顺序添加到Spring的Environment中(查看'SprinBoot特性'章节的Chapter23,ExternalizedConfiguration获取精确的顺序)。
为应用程序源添加@PropertySource注解是一种很好的添加和修改源顺序的方法。传递给SpringApplication静态便利设施(convenience)方法的类和使用setSources()添加的类都会被检查,以查看它们是否有@PropertySources,如果有,这些属性会被尽可能早的添加到Environment里,以确保ApplicationContext生命周期的所有阶段都能使用。以这种方式添加的属性优先于任何使用默认位置添加的属性,但低于系统属性,环境变量或命令行参数。
你也可以提供系统属性(或环境变量)来改变该行为:
不管你在environment设置什么,SpringBoot都将加载上面讨论过的application.properties。如果使用YAML,那具有'.yml'扩展的文件默认也会被添加到该列表。
详情参考ConfigFileApplicationListener
有些人喜欢使用(例如)--port=9000代替--server.port=9000来设置命令行配置属性。你可以通过在application.properties中使用占位符来启用该功能,比如:
注:在这种特殊的情况下,端口绑定能够在一个PaaS环境下工作,比如Heroku和CloudFoundry,因为在这两个平台中PORT环境变量是自动设置的,并且Spring能够绑定Environment属性的大写同义词。
YAML是JSON的一个超集,可以非常方便的将外部配置以层次结构形式存储起来。比如:
spring:application:name:cruncherdatasource:driverClassName:com.mysql.jdbc.Driverurl:jdbc:mysql://localhost/testserver:port:9000创建一个application.yml文件,将它放到classpath的根目录下,并添加snakeyaml依赖(Maven坐标为org.yaml:snakeyaml,如果你使用spring-boot-starter那就已经被包含了)。一个YAML文件会被解析为一个JavaMap
spring.application.name=cruncherspring.datasource.driverClassName=com.mysql.jdbc.Driverspring.datasource.url=jdbc:mysql://localhost/testserver.port=9000查看'SpringBoot特性'章节的Section23.6,“UsingYAMLinsteadofProperties”可以获取更多关于YAML的信息。
SpringEnvironment有一个API可以设置生效的profiles,但通常你会设置一个系统profile(spring.profiles.active)或一个OS环境变量(SPRING_PROFILES_ACTIVE)。比如,使用一个-D参数启动应用程序(记着把它放到main类或jar文件之前):
$java-jar-Dspring.profiles.active=productiondemo-0.0.1-SNAPSHOT.jar在SpringBoot中,你也可以在application.properties里设置生效的profile,例如:
spring.profiles.active=production通过这种方式设置的值会被系统属性或环境变量替换,但不会被SpringApplicationBuilder.profiles()方法替换。因此,后面的JavaAPI可用来在不改变默认设置的情况下增加profiles。
想要获取更多信息可查看'SpringBoot特性'章节的Chapter24,Profiles。
一个YAML文件实际上是一系列以---线分割的文档,每个文档都被单独解析为一个平坦的(flattened)map。
如果一个YAML文档包含一个spring.profiles关键字,那profiles的值(以逗号分割的profiles列表)将被传入Spring的Environment.acceptsProfiles()方法,并且如果这些profiles的任何一个被激活,对应的文档被包含到最终的合并中(否则不会)。
server:port:9000---spring:profiles:developmentserver:port:9001---spring:profiles:productionserver:port:0在这个示例中,默认的端口是9000,但如果Springprofile'development'生效则该端口是9001,如果'production'生效则它是0。
YAML文档以它们遇到的顺序合并(所以后面的值会覆盖前面的值)。
SpringBoot在运行时将来自application.properties(或.yml)的外部属性绑定进一个应用中。在一个地方不可能存在详尽的所有支持属性的列表(技术上也是不可能的),因为你的classpath下的其他jar文件也能够贡献。
每个运行中且有Actuator特性的应用都会有一个configprops端点,它能够展示所有边界和可通过@ConfigurationProperties绑定的属性。
Servlet规范支持的Servlet,Filter,ServletContextListener和其他监听器可以作为@Bean定义添加到你的应用中。需要格外小心的是,它们不会引起太多的其他beans的热初始化,因为在应用生命周期的早期它们已经被安装到容器里了(比如,让它们依赖你的DataSource或JPA配置就不是一个好主意)。你可以通过延迟初始化它们到第一次使用而不是初始化时来突破该限制。
在Filters和Servlets的情况下,你也可以通过添加一个FilterRegistrationBean或ServletRegistrationBean代替或以及底层的组件来添加映射(mappings)和初始化参数。
在一个单独的应用中,主HTTP端口默认为8080,但可以使用server.port设置(比如,在application.properties中或作为一个系统属性)。由于Environment值的宽松绑定,你也可以使用SERVER_PORT(比如,作为一个OS环境变)。
为了完全关闭HTTP端点,但仍创建一个WebApplicationContext,你可以设置server.port=-1(测试时可能有用)。
想获取更多详情可查看'SpringBoot特性'章节的Section26.3.3,“Customizingembeddedservletcontainers”,或ServerProperties源码。
想扫描一个未使用的端口(为了防止冲突使用OS本地端口)可以使用server.port=0。
你可以通过日志输出或它的EmbeddedServletContainer的EmbeddedWebApplicationContext获取服务器正在运行的端口。获取和确认服务器已经初始化的最好方式是添加一个ApplicationListener
使用@WebIntegrationTests的一个有用实践是设置server.port=0,然后使用@Value注入实际的('local')端口。例如:
注:Tomcat要求key存储(如果你正在使用一个可信存储)能够直接在文件系统上访问,即它不能从一个jar文件内读取。Jetty和Undertow没有该限制。
通常你可以遵循Section63.7,“Discoverbuilt-inoptionsforexternalproperties”关于@ConfigurationProperties(这里主要的是ServerProperties)的建议,但也看下EmbeddedServletContainerCustomizer和各种你可以添加的Tomcat-specific的*Customizers。
TomcatAPIs相当丰富,一旦获取到TomcatEmbeddedServletContainerFactory,你就能够以多种方式修改它。或核心选择是添加你自己的TomcatEmbeddedServletContainerFactory。
你可以将一个org.apache.catalina.connector.Connector添加到TomcatEmbeddedServletContainerFactory,这就能够允许多连接器,比如HTTP和HTTPS连接器:
server.tomcat.remote_ip_header=x-forwarded-forserver.tomcat.protocol_header=x-forwarded-proto如果你的代理使用不同的头部(headers),你可以通过向application.properties添加一些条目来自定义该值的配置,比如:
server.tomcat.remote_ip_header=x-your-remote-ip-headerserver.tomcat.protocol_header=x-your-protocol-header该值也可以配置为一个默认的,能够匹配信任的内部代理的正则表达式。默认情况下,受信任的IP包括10/8,192.168/16,169.254/16和127/8。可以通过向application.properties添加一个条目来自定义该值的配置,比如:
server.tomcat.internal_proxies=192\\.168\\.\\d{1,3}\\.\\d{1,3}注:只有在你使用一个properties文件作为配置的时候才需要双反斜杠。如果你使用YAML,单个反斜杠就足够了,192.168.\d{1,3}.\d{1,3}和上面的等价。
另外,通过在一个TomcatEmbeddedServletContainerFactorybean中配置和添加RemoteIpValve,你就可以完全控制它的设置了。
SpringBootstarters(特别是spring-boot-starter-web)默认都是使用Tomcat作为内嵌容器的。你需要排除那些Tomcat的依赖并包含Jetty的依赖。为了让这种处理尽可能简单,SpringBoot将Tomcat和Jetty的依赖捆绑在一起,然后提供单独的starters。
Maven示例:
使用Undertow替代Tomcat和使用Jetty替代Tomcat非常类似。你需要排除Tomat依赖,并包含Undertowstarter。
往UndertowEmbeddedServletContainerFactory添加一个UndertowBuilderCustomizer,然后添加一个监听者到Builder:
@BeanpublicUndertowEmbeddedServletContainerFactoryembeddedServletContainerFactory(){UndertowEmbeddedServletContainerFactoryfactory=newUndertowEmbeddedServletContainerFactory();factory.addBuilderCustomizers(newUndertowBuilderCustomizer(){@Overridepublicvoidcustomize(Builderbuilder){builder.addHttpListener(8080,"0.0.0.0");}});returnfactory;}9.3.14使用Tomcat7Tomcat7可用于SpringBoot,但默认使用的是Tomcat8。如果不能使用Tomcat8(例如,你使用的是Java1.6),你需要改变classpath去引用Tomcat7。
如果正在使用starterpom和parent,你只需要改变Tomcat的version属性,比如,对于一个简单的webapp或service:
如果正在使用starterpom和parent,你只需添加Jettystarter,去掉WebSocket依赖,并改变version属性,比如,对于一个简单的webapp或service:
@BeanpublicServerEndpointExporterserverEndpointExporter(){returnnewServerEndpointExporter();}该bean将用底层的WebSocket容器注册任何的被@ServerEndpoint注解的beans。当部署到一个单独的servlet容器时,该角色将被一个servlet容器初始化方法履行,ServerEndpointExporterbean也就不是必需的了。
SpringBoot提供两种启用HTTP压缩的机制;一种是Tomcat特有的,另一种是使用一个filter,可以配合Jetty,Tomcat和Undertow。
Tomcat对HTTP响应压缩提供内建支持。默认是禁用的,但可以通过application.properties轻松的启用:
server.tomcat.compression:on当设置为on时,Tomcat将压缩响应的长度至少为2048字节。你可以配置一个整型值来设置该限制而不只是on,比如:
server.tomcat.compression:4096默认情况下,Tomcat只压缩某些MIME类型的响应(text/html,text/xml和text/plain)。你可以使用server.tomcat.compressableMimeTypes属性进行自定义,比如:
server.tomcat.compressableMimeTypes=application/json,application/xml9.3.17.2使用GzipFilter开启HTTP响应压缩如果你正在使用Jetty或Undertow,或想要更精确的控制HTTP响应压缩,SpringBoot为Jetty的GzipFilter提供自动配置。虽然该过滤器是Jetty的一部分,但它也兼容Tomcat和Undertow。想要启用该过滤器,只需简单的为你的应用添加org.eclipse.jetty:jetty-servlets依赖。
在SpringBoot应用中,任何Spring@RestController默认应该渲染为JSON响应,只要classpath下存在Jackson2。例如:
@RestControllerpublicclassMyController{@RequestMapping("/thing")publicMyThingthing(){returnnewMyThing();}}只要MyThing能够通过Jackson2序列化(比如,一个标准的POJO或Groovy对象),localhost:8080/thing默认响应一个JSON表示。有时在一个浏览器中你可能看到XML响应因为浏览器倾向于发送XML响应头。
如果classpath下存在JacksonXML扩展(jackson-dataformat-xml),它会被用来渲染XML响应,示例和JSON的非常相似。想要使用它,只需为你的项目添加以下的依赖:
@XmlRootElementpublicclassMyThing{privateStringname;//..gettersandsetters}想要服务器渲染XML而不是JSON,你可能需要发送一个Accept:text/xml头部(或使用浏览器)。
在一个HTTP交互中,SpringMVC(客户端和服务端)使用HttpMessageConverters协商内容转换。如果classpath下存在Jackson,你就已经获取到Jackson2ObjectMapperBuilder提供的默认转换器。
创建的ObjectMapper(或用于JacksonXML转换的XmlMapper)实例默认有以下自定义属性:
SpringBoot也有一些简化自定义该行为的特性。
你可以使用当前的environment配置ObjectMapper和XmlMapper实例。Jackson提供一个扩展套件,可以用来简单的关闭或开启一些特性,你可以用它们配置Jackson处理的不同方面。这些特性在Jackson中使用5个枚举进行描述的,并被映射到environment的属性上:
例如,设置spring.jackson.serialization.indent_output=true可以开启漂亮打印。注意,由于松绑定的使用,indent_output不必匹配对应的枚举常量INDENT_OUTPUT。
如果想彻底替换默认的ObjectMapper,你需要定义一个该类型的@Bean并将它标记为@Primary。
定义一个Jackson2ObjectMapperBuilder类型的@Bean将允许你自定义默认的ObjectMapper和XmlMapper(分别用于MappingJackson2HttpMessageConverter和MappingJackson2XmlHttpMessageConverter)。
另一种自定义Jackson的方法是向你的上下文添加com.fasterxml.jackson.databind.Module类型的beans。它们会被注册入每个ObjectMapper类型的bean,当为你的应用添加新特性时,这就提供了一种全局机制来贡献自定义模块。
最后,如果你提供任何MappingJackson2HttpMessageConverter类型的@Beans,那它们将替换MVC配置中的默认值。同时,也提供一个HttpMessageConverters类型的bean,它有一些有用的方法可以获取默认的和用户增强的message转换器。
Spring使用HttpMessageConverters渲染@ResponseBody(或来自@RestController的响应)。你可以通过在SpringBoot上下文中添加该类型的beans来贡献其他的转换器。如果你添加的bean类型默认已经包含了(像用于JSON转换的MappingJackson2HttpMessageConverter),那它将替换默认的。SpringBoot提供一个方便的HttpMessageConverters类型的bean,它有一些有用的方法可以访问默认的和用户增强的message转换器(有用,比如你想要手动将它们注入到一个自定义的RestTemplate)。
在通常的MVC用例中,任何你提供的WebMvcConfigurerAdapterbeans通过覆盖configureMessageConverters方法也能贡献转换器,但不同于通常的MVC,你可以只提供你需要的转换器(因为SpringBoot使用相同的机制来贡献它默认的转换器)。最终,如果你通过提供自己的@EnableWebMvc注解覆盖SpringBoot默认的MVC配置,那你就可以完全控制,并使用来自WebMvcConfigurationSupport的getMessageConverters手动做任何事。
当你想要接收部分(multipart)编码文件数据作为SpringMVC控制器(controller)处理方法中被@RequestParam注解的MultipartFile类型的参数时,multipart支持就非常有用了。
完全控制MVC配置的最简单方式是提供你自己的被@EnableWebMvc注解的@Configuration。这样所有的MVC配置都逃不出你的掌心。
ViewResolver是SpringMVC的核心组件,它负责转换@Controller中的视图名称到实际的View实现。注意ViewResolvers主要用在UI应用中,而不是REST风格的服务(View不是用来渲染@ResponseBody的)。Spring有很多你可以选择的ViewResolver实现,并且Spring自己对如何选择相应实现也没发表意见。另一方面,SpringBoot会根据classpath上的依赖和应用上下文为你安装一或两个ViewResolver实现。DispatcherServlet使用所有在应用上下文中找到的解析器(resolvers),并依次尝试每一个直到它获取到结果,所以如果你正在添加自己的解析器,那就要小心顺序和你的解析器添加的位置。
WebMvcAutoConfiguration将会为你的上下文添加以下ViewResolvers:
SpringBoot除了commons-loggingAPI外没有其他强制性的日志依赖,你有很多可选的日志实现。想要使用Logback,你需要包含它,及一些对classpath下commons-logging的绑定。最简单的方式是通过依赖spring-boot-starter-logging的starterpom。对于一个web应用程序,你只需添加spring-boot-starter-web依赖,因为它依赖于loggingstarter。例如,使用Maven:
logging.level.org.springframework.web:DEBUGlogging.level.org.hibernate:ERROR你也可以使用logging.file设置日志文件的位置(除控制台之外,默认会输出到控制台)。
想要对日志系统进行更细粒度的配置,你需要使用正在说的LoggingSystem支持的原生配置格式。默认情况下,SpringBoot从系统的默认位置加载原生配置(比如对于Logback为classpath:logback.xml),但你可以使用logging.config属性设置配置文件的位置。
如果你将一个logback.xml放到classpath根目录下,那它将会被从这加载。SpringBoot提供一个默认的基本配置,如果你只是设置日志级别,那你可以包含它,比如:
SpringBoot也提供使用自定义的Logback转换器在控制台上输出一些漂亮的彩色ANSI日志信息(不是日志文件)。具体参考默认的base.xml配置。
如果Groovy在classpath下,你也可以使用logback.groovy配置Logback。
SpringBoot也支持Log4j或Log4j2作为日志配置,但只有在它们中的某个在classpath下存在的情况。如果你正在使用starterpoms进行依赖装配,这意味着你需要排除Logback,然后包含你选择的Log4j版本。如果你不使用starterpoms,那除了你选择的Log4j版本外还要提供commons-logging(至少)。
最简单的方式可能就是通过starterpoms,尽管它需要排除一些依赖,比如,在Maven中:
注:使用Log4j各版本的starters都会收集好依赖以满足commonlogging的要求(比如,Tomcat中使用java.util.logging,但使用Log4j或Log4j2作为输出)。具体查看ActuatorLog4j或Log4j2的示例,了解如何将它用于实战。
除了它的默认XML配置格式,Log4j2也支持YAML和JSON配置文件。想要使用其他配置文件格式来配置Log4j2,你需要添加合适的依赖到classpath。为了使用YAML,你需要添加com.fasterxml.jackson.dataformat:jackson-dataformat-yaml依赖,Log4j2将查找名称为log4j2.yaml或log4j2.yml的配置文件。为了使用JSON,你需要添加com.fasterxml.jackson.core:jackson-databind依赖,Log4j2将查找名称为log4j2.json或log4j2.jsn的配置文件
想要覆盖默认的设置只需要定义一个你自己的DataSource类型的@Bean。SpringBoot提供一个工具构建类DataSourceBuilder,可用来创建一个标准的DataSource(如果它处于classpath下),或者仅创建你自己的DataSource,然后将它和在Section23.7.1,“Third-partyconfiguration”解释的一系列Environment属性绑定。
比如:
创建多个数据源和创建第一个工作都是一样的。如果使用针对JDBC或JPA的默认自动配置,你可能想要将其中一个设置为@Primary(然后它就能被任何@Autowired注入获取)。
@Bean@Primary@ConfigurationProperties(prefix="datasource.primary")publicDataSourceprimaryDataSource(){returnDataSourceBuilder.create().build();}@Bean@ConfigurationProperties(prefix="datasource.secondary")publicDataSourcesecondaryDataSource(){returnDataSourceBuilder.create().build();}9.6.3使用SpringData仓库SpringData可以为你的@Repository接口创建各种风格的实现。SpringBoot会为你处理所有事情,只要那些@Repositories接口跟你的@EnableAutoConfiguration类处于相同的包(或子包)。
SpringBoot会基于它找到的@EnableAutoConfiguration来尝试猜测你的@Repository定义的位置。想要获取更多控制,可以使用@EnableJpaRepositories注解(来自SpringDataJPA)。
SpringBoot会基于它找到的@EnableAutoConfiguration来尝试猜测你的@Entity定义的位置。想要获取更多控制,你可以使用@EntityScan注解,比如:
@Configuration@EnableAutoConfiguration@EntityScan(basePackageClasses=City.class)publicclassApplication{//...}9.6.5配置JPA属性SpringDataJPA已经提供了一些独立的配置选项(比如,针对SQL日志),并且SpringBoot会暴露它们,针对hibernate的外部配置属性也更多些。最常见的选项如下:
spring.jpa.hibernate.ddl-auto:create-dropspring.jpa.hibernate.naming_strategy:org.hibernate.cfg.ImprovedNamingStrategyspring.jpa.database:H2spring.jpa.show-sql:true(由于宽松的数据绑定策略,连字符或下划线作为属性keys作用应该是等效的)ddl-auto配置是个特殊情况,它有不同的默认设置,这取决于你是否使用一个内嵌数据库(create-drop)。当本地EntityManagerFactory被创建时,所有spring.jpa.properties.*属性都被作为正常的JPA属性(去掉前缀)传递进去了。
为了完全控制EntityManagerFactory的配置,你需要添加一个名为entityManagerFactory的@Bean。SpringBoot自动配置会根据是否存在该类型的bean来关闭它的实体管理器(entitymanager)。
即使默认的EntityManagerFactory工作的很好,你也需要定义一个新的EntityManagerFactory,因为一旦出现第二个该类型的bean,默认的将会被关闭。为了轻松的实现该操作,你可以使用SpringBoot提供的EntityManagerBuilder,或者如果你喜欢的话可以直接使用来自SpringORM的LocalContainerEntityManagerFactoryBean。
//addtwodatasourcesconfiguredasabove@BeanpublicLocalContainerEntityManagerFactoryBeancustomerEntityManagerFactory(EntityManagerFactoryBuilderbuilder){returnbuilder.dataSource(customerDataSource()).packages(Customer.class).persistenceUnit("customers").build();}@BeanpublicLocalContainerEntityManagerFactoryBeanorderEntityManagerFactory(EntityManagerFactoryBuilderbuilder){returnbuilder.dataSource(orderDataSource()).packages(Order.class).persistenceUnit("orders").build();}上面的配置靠自己基本可以运行。想要完成作品你也需要为两个EntityManagers配置TransactionManagers。其中的一个会被SpringBoot默认的JpaTransactionManager获取,如果你将它标记为@Primary。另一个需要显式注入到一个新实例。或你可以使用一个JTA事物管理器生成它两个。
Spring不要求使用XML配置JPA提供者(provider),并且SpringBoot假定你想要充分利用该特性。如果你倾向于使用persistence.xml,那你需要定义你自己的id为'entityManagerFactory'的LocalEntityManagerFactoryBean类型的@Bean,并在那设置持久化单元的名称。
SpringDataJPA和SpringDataMongo都能自动为你创建Repository实现。如果它们同时出现在classpath下,你可能需要添加额外的配置来告诉SpringBoot你想要哪个(或两个)为你创建仓库。最明确地方式是使用标准的SpringData@EnableRepositories,然后告诉它你的Repository接口的位置(此处即可以是Jpa,也可以是Mongo,或者两者都是)。
这里也有spring.data.*.repositories.enabled标志,可用来在外部配置中开启或关闭仓库的自动配置。这在你想关闭Mongo仓库,但仍旧使用自动配置的MongoTemplate时非常有用。
相同的障碍和特性也存在于其他自动配置的SpringData仓库类型(Elasticsearch,Solr)。只需要改变对应注解的名称和标志。
SpringDataREST能够将Repository的实现暴露为REST端点,只要该应用启用SpringMVC。
一个数据库可以使用不同的方式进行初始化,这取决于你的技术栈。或者你可以手动完成该任务,只要数据库是单独的过程。
JPA有个生成DDL的特性,这些可以设置为在数据库启动时运行。这可以通过两个外部属性进行控制:
你可以显式设置spring.jpa.hibernate.ddl-auto,标准的Hibernate属性值有none,validate,update,create,create-drop。SpringBoot根据你的数据库是否为内嵌数据库来选择相应的默认值,如果是内嵌型的则默认值为create-drop,否则为none。通过查看Connection类型可以检查是否为内嵌型数据库,hsqldb,h2和derby是内嵌的,其他都不是。当从内存数据库迁移到一个真正的数据库时,你需要当心,在新的平台中不能对数据库表和数据是否存在进行臆断。你也需要显式设置ddl-auto,或使用其他机制初始化数据库。
此外,启动时处于classpath根目录下的import.sql文件会被执行。这在demos或测试时很有用,但在生产环境中你可能不期望这样。这是Hibernate的特性,和Spring没有一点关系。
SpringJDBC有一个DataSource初始化特性。SpringBoot默认启用了该特性,并从标准的位置schema.sql和data.sql(位于classpath根目录)加载SQL。此外,SpringBoot将加载schema-${platform}.sql和data-${platform}.sql文件(如果存在),在这里platform是spring.datasource.platform的值,比如,你可以将它设置为数据库的供应商名称(hsqldb,h2,oracle,mysql,postgresql等)。SpringBoot默认启用SpringJDBC初始化快速失败特性,所以如果脚本导致异常产生,那应用程序将启动失败。脚本的位置可以通过设置spring.datasource.schema和spring.datasource.data来改变,如果设置spring.datasource.initialize=false则哪个位置都不会被处理。
你可以设置spring.datasource.continueOnError=true禁用快速失败特性。一旦应用程序成熟并被部署了很多次,那该设置就很有用,因为脚本可以充当"可怜人的迁移"-例如,插入失败时意味着数据已经存在,也就没必要阻止应用继续运行。
如果你想要在一个JPA应用中使用schema.sql,那如果Hibernate试图创建相同的表,ddl-auto=create-drop将导致错误产生。为了避免那些错误,可以将ddl-auto设置为“”(推荐)或“none”。不管是否使用ddl-auto=create-drop,你总可以使用data.sql初始化新数据。
如果你正在使用SpringBatch,那么它会为大多数的流行数据库平台预装SQL初始化脚本。SpringBoot会检测你的数据库类型,并默认执行那些脚本,在这种情况下将关闭快速失败特性(错误被记录但不会阻止应用启动)。这是因为那些脚本是可信任的,通常不会包含bugs,所以错误会被忽略掉,并且对错误的忽略可以让脚本具有幂等性。你可以使用spring.batch.initializer.enabled=false显式关闭初始化功能。
SpringBoot跟高级别的数据迁移工具Flyway(基于SQL)和Liquibase(XML)工作的很好。通常我们倾向于Flyway,因为它一眼看去好像很容易,另外它通常不需要平台独立:一般一个或至多需要两个平台。
想要在启动时自动运行Flyway数据库迁移,需要将org.flywaydb:flyway-core添加到你的classpath下。
默认情况下,Flyway将自动注入(@Primary)DataSource到你的上下文,并用它进行数据迁移。如果你想使用一个不同的DataSource,你可以创建一个,并将它标记为@FlywayDataSource的@Bean-如果你这样做了,且想要两个数据源,记得创建另一个并将它标记为@Primary。或者你可以通过在外部配置文件中设置flyway.[url,user,password]来使用Flyway的原生DataSource。
想要在启动时自动运行Liquibase数据库迁移,你需要将org.liquibase:liquibase-core添加到classpath下。
你可以在上下文的某个地方添加@EnableBatchProcessing来启用SpringBatch的自动配置功能。
如果应用上下文包含一个JobRegistry,那么处于spring.batch.job.names中的作业将会从registry中查找,而不是从上下文中自动装配。这是复杂系统中常见的一个模式,在这些系统中多个作业被定义在子上下文和注册中心。
在一个单独的应用中,执行器的HTTP端口默认和主HTTP端口相同。想要让应用监听不同的端口,你可以设置外部属性management.port。为了监听一个完全不同的网络地址(比如,你有一个用于管理的内部网络和一个用于用户应用程序的外部网络),你可以将management.address设置为一个可用的IP地址,然后将服务器绑定到该地址。
如果你提供了一个AuthenticationManager类型的@Bean,那么默认的就不会被创建了,所以你可以获得SpringSecurity可用的全部特性(比如,不同的认证选项)。
SpringSecurity也提供了一个方便的AuthenticationManagerBuilder,可用于构建具有常见选项的AuthenticationManager。在一个webapp中,推荐将它注入到WebSecurityConfigurerAdapter的一个void方法中,比如:
@ConfigurationpublicclassSecurityConfigurationextendsWebSecurityConfigurerAdapter{@AutowiredpublicvoidconfigureGlobal(AuthenticationManagerBuilderauth)throwsException{auth.inMemoryAuthentication().withUser("barry").password("password").roles("USER");//...etc.}//...otherstuffforapplicationsecurity}如果把它放到一个内部类或一个单独的类中,你将得到最好的结果(也就是不跟很多其他@Beans混合在一起将允许你改变实例化的顺序)。securewebsample是一个有用的参考模板。
如果你遇到了实例化问题(比如,使用JDBC或JPA进行用户详细信息的存储),那将AuthenticationManagerBuilder回调提取到一个GlobalAuthenticationConfigurerAdapter(放到init()方法内以防其他地方也需要authenticationmanager)可能是个不错的选择,比如:
@ConfigurationpublicclassAuthenticationManagerConfigurationextendsGlobalAuthenticationConfigurerAdapter{@Overridepublicvoidinit(AuthenticationManagerBuilderauth){auth.inMemoryAuthentication()//...etc.}}9.10.3当前端使用代理服务器时,启用HTTPS对于任何应用来说,确保所有的主端点(URL)都只在HTTPS下可用是个重要的苦差事。如果你使用Tomcat作为servlet容器,那SpringBoot如果发现一些环境设置的话,它将自动添加Tomcat自己的RemoteIpValve,你也可以依赖于HttpServletRequest来报告是否请求是安全的(即使代理服务器的downstream处理真实的SSL终端)。这个标准行为取决于某些请求头是否出现(x-forwarded-for和x-forwarded-proto),这些请求头的名称都是约定好的,所以对于大多数前端和代理都是有效的。
你可以向application.properties添加以下设置里开启该功能,比如:
server.tomcat.remote_ip_header=x-forwarded-forserver.tomcat.protocol_header=x-forwarded-proto(这些属性出现一个就会开启该功能,或者你可以通过添加一个TomcatEmbeddedServletContainerFactorybean自己添加RemoteIpValve)
SpringSecurity也可以配置成针对所以或某些请求需要一个安全渠道(channel)。想要在一个SpringBoot应用中开启它,你只需将application.properties中的security.require_ssl设置为true即可。
SpringBoot有很多用于热加载的选项。使用IDE开发是一个不错的方式,特别是需要调试的时候(所有的现代IDEs都允许重新加载静态资源,通常也支持对变更的Java类进行热交换)。Maven和Gradle插件也支持命令行下的静态文件热加载。如果你使用其他高级工具编写css/js,并使用外部的css/js编译器,那你就可以充分利用该功能。
如果你正在使用Thymeleaf,那就将spring.thymeleaf.cache设置为false。查看ThymeleafAutoConfiguration可以获取其他Thymeleaf自定义选项。
如果你正在使用FreeMarker,那就将spring.freemarker.cache设置为false。查看FreeMarkerAutoConfiguration可以获取其他FreeMarker自定义选项。
如果你正在使用Groovy模板,那就将spring.groovy.template.cache设置为false。查看GroovyTemplateAutoConfiguration可以获取其他Groovy自定义选项。
如果你正在使用Velocity,那就将spring.velocity.cache设置为false。查看VelocityAutoConfiguration可以获取其他Velocity自定义选项。
现代IDEs(Eclipse,IDEA等)都支持字节码的热交换,所以如果你做了一个没有影响类或方法签名的改变,它会利索地重新加载并没有任何影响。
如果想将SpringLoaded和Gradle,IntelliJ结合起来,那你需要付出代价。默认情况下,IntelliJ将类编译到一个跟Gradle不同的位置,这会导致SpringLoaded监控失败。
为了正确配置IntelliJ,你可以使用ideaGradle插件:
buildscript{repositories{jcenter()}dependencies{classpath"org.springframework.boot:spring-boot-gradle-plugin:1.3.0.BUILD-SNAPSHOT"classpath'org.springframework:springloaded:1.2.0.RELEASE'}}applyplugin:'idea'idea{module{inheritOutputDirs=falseoutputDir=file("$buildDir/classes/main/")}}//...注:IntelliJ必须配置跟命令行Gradle任务相同的Java版本,并且springloaded必须作为一个buildscript依赖被包含进去。
此外,你也可以启用Intellij内部的MakeProjectAutomatically,这样不管什么时候只要文件被保存都会自动编译你的代码。
如果你使用Maven进行一个直接或间接继承spring-boot-dependencies(比如spring-boot-starter-parent)的构建,并想覆盖一个特定的第三方依赖,那你可以添加合适的
注:每个SpringBoot发布都是基于一些特定的第三方依赖集进行设计和测试的,覆盖版本可能导致兼容性问题。
如果你想将自己的项目以libraryjar的形式被其他项目依赖,并且需要它是一个可执行版本(例如demo),你需要使用略微不同的方式来配置该构建。
对于Maven来说,正常的JAR插件和SpringBoot插件都有一个'classifier',你可以添加它来创建另外的JAR。示例如下(使用SpringBootStarterParent管理插件版本,其他配置采用默认设置):
对于Gradle用户来说,步骤类似。示例如下:
bootRepackage{classifier='exec'}9.12.4在可执行jar运行时提取特定的版本在一个可执行jar中,为了运行,多数内嵌的库不需要拆包(unpacked),然而有一些库可能会遇到问题。例如,JRuby包含它自己的内嵌jar,它假定jruby-complete.jar本身总是能够直接作为文件访问的。
为了处理任何有问题的库,你可以标记那些特定的内嵌jars,让它们在可执行jar第一次运行时自动解压到一个临时文件夹中。例如,为了将JRuby标记为使用Maven插件拆包,你需要添加如下的配置:
想要为使用Gradle启动的SpringBoot应用添加一个远程调试器,你可以使用build.gradle的applicationDefaultJvmArgs属性或--debug-jvm命令行选项。
build.gradle:applicationDefaultJvmArgs=["-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005"]命令行:
想要使用Ant进行构建,你需要抓取依赖,编译,然后像通常那样创建一个jar或war存档。为了让它可以执行:
示例:
$ant-lib/ivy-2.2.jar在上述操作之后,你可以使用以下命令运行该应用:
$java-jartarget/*.jar9.12.9如何使用Java6如果想在Java6环境中使用SpringBoot,你需要改变一些配置。具体的变化取决于你应用的功能。
Java事务API自身并不要求Java7,而是官方的APIjar包含的已构建类要求Java7。如果你正在使用JTA,那么你需要使用能够在Java6工作的构建版本替换官方的JTA1.2APIjar。为了完成该操作,你需要排除任何对javax.transaction:javax.transaction-api的传递依赖,并使用org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.0.0.Final依赖替换它们。
产生一个可部署war包的第一步是提供一个SpringBootServletInitializer子类,并覆盖它的configure方法。这充分利用了Spring框架对Servlet3.0的支持,并允许你在应用通过servlet容器启动时配置它。通常,你只需把应用的主类改为继承SpringBootServletInitializer即可:
@SpringBootApplicationpublicclassApplicationextendsSpringBootServletInitializer{@OverrideprotectedSpringApplicationBuilderconfigure(SpringApplicationBuilderapplication){returnapplication.sources(Application.class);}publicstaticvoidmain(String[]args)throwsException{SpringApplication.run(Application.class,args);}}下一步是更新你的构建配置,这样你的项目将产生一个war包而不是jar包。如果你使用Maven,并使用spring-boot-starter-parent(为了配置Maven的war插件),所有你需要做的就是更改pom.xml的packaging为war:
applyplugin:'war'该过程最后的一步是确保内嵌的servlet容器不能干扰war包将部署的servlet容器。为了达到这个目的,你需要将内嵌容器的依赖标记为provided。
如果使用Maven:
老的Servlet容器不支持在Servlet3.0中使用的ServletContextInitializer启动处理。你仍旧可以在这些容器使用Spring和SpringBoot,但你需要为应用添加一个web.xml,并将它配置为通过一个DispatcherServlet加载一个ApplicationContext。
对于一个非web项目,转换为SpringBoot应用很容易(抛弃创建ApplicationContext的代码,取而代之的是调用SpringApplication或SpringApplicationBuilder)。SpringMVCweb应用通常先创建一个可部署的war应用,然后将它迁移为一个可执行的war或jar。建议阅读GettingStartedGuideonConvertingajartoawar.。
通过继承SpringBootServletInitializer创建一个可执行war(比如,在一个名为Application的类中),然后添加SpringBoot的@EnableAutoConfiguration注解。示例:
@Configuration@EnableAutoConfiguration@ComponentScanpublicclassApplicationextendsSpringBootServletInitializer{@OverrideprotectedSpringApplicationBuilderconfigure(SpringApplicationBuilderapplication){//Customizetheapplicationorcallapplication.sources(...)toaddsources//Sinceourexampleisitselfa@Configurationclassweactuallydon't//needtooverridethismethod.returnapplication;}}记住不管你往sources放什么东西,它仅是一个SpringApplicationContext,正常情况下,任何生效的在这里也会起作用。有一些beans你可以先移除,然后让SpringBoot提供它的默认实现,不过有可能需要先完成一些事情。
静态资源可以移到classpath根目录下的/public(或/static,/resources,/META-INF/resources)。同样的方式也适合于messages.properties(SpringBoot在classpath根目录下自动发现这些配置)。
美妙的(Vanillausageof)SpringDispatcherServlet和SpringSecurity不需要改变。如果你的应用有其他特性,比如使用其他servlets或filters,那你可能需要添加一些配置到你的Application上下文中,按以下操作替换web.xml的那些元素:
一旦war可以使用,我们就通过添加一个main方法到Application来让它可以执行,比如:
publicstaticvoidmain(String[]args){SpringApplication.run(Application.class,args);}应用可以划分为多个类别:
所有这些都可以进行适当的转化,但每个可能需要稍微不同的技巧。
对于还不是Spring应用的应用来说,上面的指南有助于你把应用转换为一个SpringBoot应用,但你也可以选择其他方式。
想要将SpringBoot应用部署到Weblogic,你需要确保你的servlet初始化器直接实现WebApplicationInitializer(即使你继承的基类已经实现了它)。
一个传统的Weblogic初始化器可能如下所示:
importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.boot.context.web.SpringBootServletInitializer;importorg.springframework.web.WebApplicationInitializer;@SpringBootApplicationpublicclassMyApplicationextendsSpringBootServletInitializerimplementsWebApplicationInitializer{}如果使用logback,你需要告诉Weblogic你倾向使用的打包版本而不是服务器预装的版本。你可以通过添加一个具有如下内容的WEB-INF/weblogic.xml实现该操作:
SpringBoot参考指南涵盖了SpringBoot的基本概念、安装方法、应用构建、运行和打包,以及高级配置和生产部署等多方面的内容。该指南为Java开发者提供了一个全面的入门手册,帮助他们从零开始创建自己的SpringBoot...
《SpringBoot参考指南》是SpringBoot开发者的重要参考资料,它详细阐述了如何利用SpringBoot构建高效、简洁的Java应用。SpringBoot是由Pivotal团队提供的全新框架,旨在简化Spring应用程序的初始搭建以及开发...
SpringBoot参考指南SpringBoot是一个基于Spring框架的框架,旨在简化Spring应用程序的开发过程。SpringBoot提供了一些默认配置和starters,以便快速构建生产级别的应用程序。SpringBoot的特点1....
《SpringBoot参考指南》是SpringBoot开发者的重要参考资料,它详细阐述了SpringBoot框架的核心特性、配置方式、自动配置原理以及如何构建微服务应用等关键知识点。SpringBoot是Java开发领域中一个极其流行的轻量...
###SpringBoot参考指南知识点解析####一、SpringBoot概览-**SpringBoot**是一个基于Spring平台的框架,旨在简化新Spring应用程序的初始设置和开发过程。-**版本**:本指南适用于1.3.0.BUILD-...
SpringBoot参考指南SpringBoot是一个基于Java的框架,用于构建独立的、生产级别的基于Spring的应用程序。该框架提供了许多便捷的特性,以简化Spring应用程序的开发、配置和部署。1.SpringBoot文档...
《SpringBoot参考指南》是一份详尽的文档,它为开发者提供了关于SpringBoot框架的全面指导。SpringBoot是基于Spring的一个开源框架,旨在简化新Spring应用的初始搭建以及开发过程。这份指南涵盖从基础入门到高级...
SpringBootReferenceGuide中文翻译-《SpringBoot参考指南》SpringBootReferenceGuide中文翻译-《SpringBoot参考指南》SpringBootReferenceGuide中文翻译-《SpringBoot参考指南...
###SpringBoot参考指南知识点总结####一、SpringBoot概览-**SpringBoot**是一种简化新Spring应用程序的初始设置以及依赖管理的框架。它利用了一种称为“约定优于配置”的理念,来简化了配置过程,使得...
GitBook:SpringBoot参考指南整合示例:程序猿DD-SpringBoot教程Email:qibaoguang@gmail.com从这里开始交流群:springboot最佳实践2:460560346springboot最佳实践(已满):445015546注1.3版本...
**SpringBoot中文参考指南****一、SpringBoot概述**SpringBoot是由Pivotal团队提供的全新框架,旨在简化Spring应用程序的初始搭建以及开发过程。它集成了大量的常用第三方库配置,如JDBC、MongoDB、...
SpringBootReferenceGuide中文翻译,详细的中文springboot中文文档,包含快速创建springbootdemo,与maven的结合使用等;各类注解的使用,以及服务器的部署等等……