Spring Boot 1.3.0 入门笔记
虽然我有一些使用Spring的经验,但我从未真正接触过Spring Boot。这是我第一次尝试使用Spring Boot,我通过查阅官方文档整理了一份类似于屏幕录像的备忘录。
目前Spring Boot的版本是最新的1.3.0.RELEASE。我在Mac OS X上工作。从Getting Started开始做,发现文档非常充实,真不错。
使用Gradle设置项目
如果您的电脑还没有安装Gradle,请先安装。截至本文发布时,最新版本是2.9。
brew install gradle
请贴出一个build.gradle的示例,并执行gradle wrapper。
buildscript {
repositories {
jcenter()
maven { url "http://repo.spring.io/snapshot" }
maven { url "http://repo.spring.io/milestone" }
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.0.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'spring-boot'
jar {
baseName = 'myproject'
version = '0.0.1-SNAPSHOT'
}
repositories {
jcenter()
maven { url "http://repo.spring.io/snapshot" }
maven { url "http://repo.spring.io/milestone" }
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
testCompile("org.springframework.boot:spring-boot-starter-test")
}
目前的情况是这样的。
$ tree
.
├── build.gradle
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
└── gradlew.bat
如果尝试使用Gradle Daemon来减少构建时间呢?
BUILD SUCCESSFUL
Total time: 16.058 secs
This build could be faster, please consider using the Gradle Daemon: https://docs.gradle.org/2.9/userguide/gradle_daemon.html
The Gradle Daemon is a background process that does the heavy lifting of running builds, then stays alive between builds waiting for the next build. This allows data and code that is likely to be required in the next build to be kept in memory, ready to go. This dramatically improves the performance of subsequent builds. Enabling the Gradle Daemon is an extremely cheap way to decrease build times.
立即进行设置。在Mac OS中,操作如下所示。
touch ~/.gradle/gradle.properties && echo "org.gradle.daemon=true" >> ~/.gradle/gradle.properties
安装Spring Boot CLI
鑑於此,由於聽說建立原型非常迅速,我打算先安裝Spring Boot的CLI工具來嘗試一下。
The Spring Boot CLI is a command line tool that can be used if you want to quickly prototype with Spring
我最初以为要下载zip并设置PATH,但好像可以使用一个叫作sdkman的工具来安装。虽然我不太了解,但似乎它曾经是受到RVM / rbenv这种工具的影响,用于管理Groovy环境的GVM(Groovy enVironment Manager)。
链接:
http://sdkman.io/
http://qiita.com/saba1024/items/967ee3d8a79440a97336
暂时先试试这个。
$ curl -s http://get.sdkman.io | bash
Thanks for using...
SSSSSSSSSSSSSSS DDDDDDDDDDDDD KKKKKKKKK KKKKKKK
SS:::::::::::::::SD::::::::::::DDD K:::::::K K:::::K
S:::::SSSSSS::::::SD:::::::::::::::DD K:::::::K K:::::K
S:::::S SSSSSSSDDD:::::DDDDD:::::D K:::::::K K::::::K
S:::::S D:::::D D:::::DKK::::::K K:::::KKK
S:::::S D:::::D D:::::D K:::::K K:::::K
S::::SSSS D:::::D D:::::D K::::::K:::::K
SS::::::SSSSS D:::::D D:::::D K:::::::::::K
SSS::::::::SS D:::::D D:::::D K:::::::::::K
SSSSSS::::S D:::::D D:::::D K::::::K:::::K
S:::::S D:::::D D:::::D K:::::K K:::::K
S:::::S D:::::D D:::::DKK::::::K K:::::KKK
SSSSSSS S:::::SDDD:::::DDDDD:::::D K:::::::K K::::::K
S::::::SSSSSS:::::SD:::::::::::::::DD K:::::::K K:::::K
S:::::::::::::::SS D::::::::::::DDD K:::::::K K:::::K
SSSSSSSSSSSSSSS DDDDDDDDDDDDD KKKKKKKKK KKKKKKK
mmmmmmm mmmmmmm aaaaaaaaaaaaa nnnn nnnnnnnn
mm:::::::m m:::::::mm a::::::::::::a n:::nn::::::::nn
m::::::::::mm::::::::::m aaaaaaaaa:::::an::::::::::::::nn
m::::::::::::::::::::::m a::::ann:::::::::::::::n
m:::::mmm::::::mmm:::::m aaaaaaa:::::a n:::::nnnn:::::n
m::::m m::::m m::::m aa::::::::::::a n::::n n::::n
m::::m m::::m m::::m a::::aaaa::::::a n::::n n::::n
m::::m m::::m m::::ma::::a a:::::a n::::n n::::n
m::::m m::::m m::::ma::::a a:::::a n::::n n::::n
m::::m m::::m m::::ma:::::aaaa::::::a n::::n n::::n
m::::m m::::m m::::m a::::::::::aa:::a n::::n n::::n
mmmmmm mmmmmm mmmmmm aaaaaaaaaa aaaa nnnnnn nnnnnn
Now attempting installation...
Looking for a previous installation of SDKMAN...
Looking for unzip...
Looking for curl...
Looking for sed...
Installing SDKMAN scripts...
Create distribution directories...
Getting available candidates...
Prime the config file...
Download script archive...
Extract script archive...
Install scripts...
Set version to 3.2.4 ...
Attempt update of bash profiles...
Updated existing /Users/seratch/.bash_profile
Created and initialised /Users/seratch/.bashrc
Attempt update of zsh profiles...
Created and initialised /Users/seratch/.zshrc
All done!
Please open a new terminal, or run the following in the existing one:
source "/Users/seratch/.sdkman/bin/sdkman-init.sh"
Then issue the following command:
sdk help
Enjoy!!!
$ source "/Users/seratch/.sdkman/bin/sdkman-init.sh"
$ sdk help
==== BROADCAST =================================================================
* 17/11/15: Gradle 2.9 released on SDKMAN! #gradle
* 16/11/15: Springboot 1.3.0.RELEASE released on SDKMAN! #springboot
* 05/11/15: Vertx 3.1.0 released on SDKMAN! #vertx
================================================================================
Usage: sdk <command> [candidate] [version]
sdk offline <enable|disable>
commands:
install or i <candidate> [version]
uninstall or rm <candidate> <version>
list or ls [candidate]
use or u <candidate> [version]
default or d <candidate> [version]
current or c [candidate]
outdated or o [candidate]
version or v
broadcast or b
help or h
offline <enable|disable>
selfupdate [force]
flush <candidates|broadcast|archives|temp>
candidate : the SDK to install: groovy, scala, grails, akka, etc.
use list command for comprehensive list of candidates
eg: $ sdk list
version : where optional, defaults to latest stable if not provided
eg: $ sdk install groovy
$
无论怎样,既然可以使用SDK命令,就尝试安装SDK。
$ sdk install springboot
Downloading: springboot 1.3.0.RELEASE
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 9094k 100 9094k 0 0 748k 0 0:00:12 0:00:12 --:--:-- 1088k
Installing: springboot 1.3.0.RELEASE
Done installing!
Do you want springboot 1.3.0.RELEASE to be set as default? (Y/n): y
Setting springboot 1.3.0.RELEASE as default.
$
看起来已经完成了设置。
$ spring
usage: spring [--help] [--version]
<command> [<args>]
Available commands are:
run [options] <files> [--] [args]
Run a spring groovy script
test [options] <files> [--] [args]
Run a spring groovy script test
grab
Download a spring groovy script's dependencies to ./repository
jar [options] <jar-name> <files>
Create a self-contained executable jar file from a Spring Groovy script
war [options] <war-name> <files>
Create a self-contained executable war file from a Spring Groovy script
install [options] <coordinates>
Install dependencies to the lib directory
uninstall [options] <coordinates>
Uninstall dependencies from the lib directory
init [options] [location]
Initialize a new project using Spring Initialzr (start.spring.io)
shell
Start a nested shell
Common options:
-d, --debug Verbose mode
Print additional status information for the command you are running
See 'spring help <command>' for more information on a specific command.
顺便说一下,我注意到了 sdkman 的 BROADCAST 通知栏上写着:”Gradle和Vert.x已经发布了!”,但是当我在 sdk list 上查看列表时,发现还有其他一些选项,具体如下:
================================================================================
Available Candidates
================================================================================
q-quit /-search down
j-down ?-search up
k-up h-help
--------------------------------------------------------------------------------
AsciidoctorJ (1.5.2) http://asciidoctor.org/
AsciidoctorJ is the official library for running Asciidoctor on the JVM. Using
AsciidoctorJ, you can convert AsciiDoc content or analyze the structure of a
parsed AsciiDoc document from Java and other JVM languages.
$ sdk install asciidoctorj
--------------------------------------------------------------------------------
Ceylon (1.2.0) http://ceylon-lang.org/
Ceylon is a modern, modular, statically typed programming language for the Java
and JavaScript virtual machines. The language features a flexible and very
readable syntax, a unique and uncommonly elegant static type system, a powerful
module architecture, and excellent tooling.
$ sdk install ceylon
--------------------------------------------------------------------------------
CRaSH (1.3.0) http://www.crashub.org/
The Common Reusable SHell (CRaSH) deploys in a Java runtime and provides
interactions with the JVM. Commands are written in Groovy or Java and can be
developed at runtime making the extension of the shell very easy with fast
development cycle.
$ sdk install crash
--------------------------------------------------------------------------------
Gaiden (1.0) http://kobo.github.io/gaiden/
Gaiden is a tool that makes it easy to create documentation with Markdown.
$ sdk install gaiden
--------------------------------------------------------------------------------
Glide (0.3.3) http://glide-gae.appspot.com/
Glide makes it incredibly easy to develop apps that harness the power of Google
App Engine for Java using expressiveness of Groovy and sweetness of Gaelyk's
syntactic sugar.
$ sdk install glide
--------------------------------------------------------------------------------
Gradle (2.9) http://gradle.org/
Gradle is a build automation tool that builds upon the concepts of Apache Ant
and Apache Maven and introduces a Groovy-based domain-specific language (DSL)
instead of the more traditional XML form of declaring the project
configuration. Gradle uses a directed acyclic graph (DAG) to determine the
order in which tasks can be run.
$ sdk install gradle
--------------------------------------------------------------------------------
Grails (3.0.9) https://grails.org/
Grails is a powerful web framework, for the Java platform aimed at multiplying
developers productivity thanks to a Convention-over-Configuration, sensible
defaults and opinionated APIs. It integrates smoothly with the JVM, allowing
you to be immediately productive whilst providing powerful features, including
integrated ORM, Domain-Specific Languages, runtime and compile-time
meta-programming and Asynchronous programming.
$ sdk install grails
--------------------------------------------------------------------------------
Griffon (1.5.0) http://griffon-framework.org/
Griffon is desktop application development platform for the JVM.Inspired by
Grails, Griffon leverages the use of the Groovy language and concepts like
Convention over Configuration. The Swing toolkit is the default UI toolkit of
choice however others may be used, for example JavaFX.
$ sdk install griffon
--------------------------------------------------------------------------------
Groovy (2.4.5) http://www.groovy-lang.org/
Groovy is a powerful, optionally typed and dynamic language, with static-typing
and static compilation capabilities, for the Java platform aimed at multiplying
developers' productivity thanks to a concise, familiar and easy to learn
syntax. It integrates smoothly with any Java program, and immediately delivers
to your application powerful features, including scripting capabilities,
Domain-Specific Language authoring, runtime and compile-time meta-programming
and functional programming.
$ sdk install groovy
--------------------------------------------------------------------------------
GroovyServ (1.0.0) https://kobo.github.io/groovyserv/
GroovyServ reduces startup time of the JVM for runnning Groovy significantly.
It depends on your environments, but in most cases, it’s 10 to 20 times faster
than regular Groovy.
$ sdk install groovyserv
--------------------------------------------------------------------------------
JBake (2.4.0) http://jbake.org/
JBake is a Java based, open source, static site/blog generator for developers
and designers.
$ sdk install jbake
--------------------------------------------------------------------------------
JBoss Forge (2.17.0.Final) http://forge.jboss.org/
JBoss Forge is the Fastest way to build Maven-based Java EE projects, and
anything else you fancy.
$ sdk install jbossforge
--------------------------------------------------------------------------------
Lazybones (0.8.1) https://github.com/pledbrook/lazybones/
Lazybones allows you to create a new project structure for any framework or
library for which the tool has a template.
$ sdk install lazybones
--------------------------------------------------------------------------------
Maven (3.3.3) https://maven.apache.org/
Apache Maven is a software project management and comprehension tool. Based on
the concept of a project object model (POM), Maven can manage a project's
build, reporting and documentation from a central piece of information.
$ sdk install maven
--------------------------------------------------------------------------------
sbt (0.13.9) http://www.scala-sbt.org/
SBT is an open source build tool for Scala and Java projects, similar to Java's
Maven or Ant. Its main features are: native support for compiling Scala code
and integrating with many Scala test frameworks; build descriptions written in
Scala using a DSL; dependency management using Ivy (which supports Maven-format
repositories); continuous compilation, testing, and deployment; integration
with the Scala interpreter for rapid iteration and debugging; support for mixed
Java/Scala projects
$ sdk install sbt
--------------------------------------------------------------------------------
Scala (2.11.7) http://www.scala-lang.org/
Scala is a programming language for general software applications. Scala has
full support for functional programming and a very strong static type system.
This allows programs written in Scala to be very concise and thus smaller in
size than other general-purpose programming languages. Scala source code is
intended to be compiled to Java bytecode, so that the resulting executable code
runs on a Java virtual machine. Java libraries may be used directly in Scala
code and vice versa. Scala is object-oriented, and uses a curly-brace syntax.
Scala has many features of functional programming languages, including
currying, type inference, immutability, lazy evaluation, and pattern matching.
It also has an advanced type system supporting algebraic data types, covariance
and contravariance, higher-order types, and anonymous types. Other features of
Scala include operator overloading, optional parameters, named parameters, raw
strings, and no checked exceptions.
$ sdk install scala
--------------------------------------------------------------------------------
Spring Boot (1.3.0.RELEASE) http://projects.spring.io/spring-boot/
Spring Boot takes an opinionated view of building production-ready Spring
applications. It favors convention over configuration and is designed to get
you up and running as quickly as possible.
$ sdk install springboot
--------------------------------------------------------------------------------
Vert.x (3.1.0) http://vertx.io/
Vert.x is a tool-kit for building reactive applications on the JVM.
$ sdk install vertx
--------------------------------------------------------------------------------
在这个配置中,我们使用的工具(Maven、Gradle、sbt、scala)基本上都可以在 Homebrew 中找到,所以我觉得只是为了这些工具而安装 sdkman 可能有些微妙。然而,在接下来的「10.2.3 OSX Homebrew installation」部分介绍了如何在 Homebrew 中进行安装。
为了在 Homebrew 上安装,首先需要卸载通过 sdkman 安装的内容。
$ sdk uninstall springboot 1.3.0.RELEASE
Unselecting springboot 1.3.0.RELEASE...
Uninstalling springboot 1.3.0.RELEASE...
然后通过Homebrew重新安装。在Homebrew的官方库中找不到此软件,似乎需要通过Pivotal的GitHub仓库来使用brew tap命令安装。
$ brew tap pivotal/tap
$ brew install springboot
Spring Boot CLI的安装就到这里。
运行Spring Boot的Web应用程序
看了「10.2.6 快速入门 Spring CLI 示例」
@RestController
class ThisWillActuallyRun {
@RequestMapping("/")
String home() {
"Hello World!"
}
}
听说保存下这段 Groovy 代码为 app.groovy,然后运行 spring run app.groovy 就可以正常运行…真的吗?这意味着不仅仅可以用 Grape 来解决最低限度的依赖库,还默认解决了一定程度的导入问题。
$ spring run app.groovy
Resolving dependencies...........................
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.3.0.RELEASE)
2015-11-23 16:06:26.616 INFO 53470 --- [ runner-0] o.s.boot.SpringApplication : Starting application on seratchs-MacBook-Pro.local with PID 53470 (/Users/seratch/.m2/repository/org/springframework/boot/spring-boot/1.3.0.RELEASE/spring-boot-1.3.0.RELEASE.jar started by seratch in /Users/seratch/Documents/github/spring-boot-example)
2015-11-23 16:06:26.619 INFO 53470 --- [ runner-0] o.s.boot.SpringApplication : No profiles are active
2015-11-23 16:06:27.004 INFO 53470 --- [ runner-0] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@517a4e29: startup date [Mon Nov 23 16:06:27 JST 2015]; root of context hierarchy
2015-11-23 16:06:28.414 INFO 53470 --- [ runner-0] o.s.b.f.s.DefaultListableBeanFactory : Overriding bean definition for bean 'beanNameViewResolver' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class]]
2015-11-23 16:06:29.166 INFO 53470 --- [ runner-0] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http)
2015-11-23 16:06:29.181 INFO 53470 --- [ runner-0] o.apache.catalina.core.StandardService : Starting service Tomcat
2015-11-23 16:06:29.183 INFO 53470 --- [ runner-0] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.0.28
2015-11-23 16:06:29.267 INFO 53470 --- [ost-startStop-1] org.apache.catalina.loader.WebappLoader : Unknown loader org.springframework.boot.cli.compiler.ExtendedGroovyClassLoader$DefaultScopeParentClassLoader@6598a08d class org.springframework.boot.cli.compiler.ExtendedGroovyClassLoader$DefaultScopeParentClassLoader
2015-11-23 16:06:29.288 INFO 53470 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2015-11-23 16:06:29.288 INFO 53470 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 2284 ms
2015-11-23 16:06:29.754 INFO 53470 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/]
2015-11-23 16:06:29.763 INFO 53470 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*]
2015-11-23 16:06:29.763 INFO 53470 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2015-11-23 16:06:29.764 INFO 53470 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2015-11-23 16:06:29.764 INFO 53470 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*]
2015-11-23 16:06:30.114 INFO 53470 --- [ runner-0] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@517a4e29: startup date [Mon Nov 23 16:06:27 JST 2015]; root of context hierarchy
2015-11-23 16:06:30.200 INFO 53470 --- [ runner-0] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/]}" onto public java.lang.String ThisWillActuallyRun.home()
2015-11-23 16:06:30.203 INFO 53470 --- [ runner-0] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2015-11-23 16:06:30.203 INFO 53470 --- [ runner-0] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest)
2015-11-23 16:06:30.246 INFO 53470 --- [ runner-0] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2015-11-23 16:06:30.246 INFO 53470 --- [ runner-0] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2015-11-23 16:06:30.300 INFO 53470 --- [ runner-0] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2015-11-23 16:06:30.816 INFO 53470 --- [ runner-0] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2015-11-23 16:06:30.921 INFO 53470 --- [ runner-0] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2015-11-23 16:06:30.926 INFO 53470 --- [ runner-0] o.s.boot.SpringApplication : Started application in 4.858 seconds (JVM running for 36.749)
确实启动了。默认情况下,Tomcat 8 启动。当访问 localhost:8080 时,将返回一个带有“Hello World!”内容的响应体。
$ curl -v http://localhost:8080/
* Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Content-Type: text/plain;charset=UTF-8
< Content-Length: 12
< Date: Mon, 23 Nov 2015 07:08:10 GMT
<
* Connection #0 to host localhost left intact
Hello World!$
由于暂时没有特别需要动手的地方,所以跳过一小段,接下来试着运行「11.3 编写代码」中的Java示例。
mkdir -p src/main/java/
echo 'import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.stereotype.*;
import org.springframework.web.bind.annotation.*;
@RestController
@EnableAutoConfiguration
public class Example {
@RequestMapping("/")
String home() {
return "Hello World!";
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Example.class, args);
}
}' > src/main/java/Example.java
最初我已经使用Gradle设置了一个最小的Spring Boot项目,所以只需放置源代码即可使用Gradle任务bootRun来启动。而Gradle的任务列表可以通过tasks命令来确认。
$ ./gradlew tasks
:tasks
------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------
Application tasks
-----------------
bootRun - Run the project with support for auto-detecting main class and reloading static resources
(以下略)
看起来,bootRun支持检测主类和静态文件的热加载。
./gradlew bootRun
这个也完全以同样的方式运作。
$ curl -v localhost:8080
* Rebuilt URL to: localhost:8080/
* Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Content-Type: text/plain;charset=UTF-8
< Content-Length: 12
< Date: Mon, 23 Nov 2015 07:15:28 GMT
<
* Connection #0 to host localhost left intact
Hello World!$
从这里开始的文档不仅包括 Gradle,还有关于 Maven、Ant 的构建方法以及上面粘贴的 build.gradle 的说明等等,因此跳过这部分,进入到 “III. 使用 Spring Boot”,并尝试 “14.2 定位主应用程序类” 的示例。
将 src/main/java/Example.java 删除,添加 src/main/java/myproject/Application.java。暂时可以将 Example.java 中的内容直接复制到新的文件中以确保其正常运行。
package myproject;
import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.stereotype.*;
import org.springframework.context.annotation.*;
import org.springframework.web.bind.annotation.*;
@Configuration
@EnableAutoConfiguration
@ComponentScan
@RestController // TODO: move
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@RequestMapping("/") String home() { return "Hello World!"; } // TODO: move
}
重新运行 ./gradlew bootRun,并确认它能够正常工作。
下一步是将 RestController 分离出来。myproject.Application 只负责主要的初始化和整个 Spring 的配置。
// src/main/java/myproject/Application.java
package myproject;
import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.stereotype.*;
import org.springframework.context.annotation.*;
@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
将路由和处理方法都移动到 myproject.web.HomeController 中。如果在 myproject.Application 中指定了 ComponentScan 注解,将 myproject 作为根包进行自动组件扫描,那么只需在类上添加 RestController 注解,就可以自动识别为已设置路由信息的组件。
// src/main/java/myproject/web/HomeController.java
package myproject.web;
import org.springframework.web.bind.annotation.*;
@RestController
public class HomeController {
@RequestMapping("/") String home() { return "Hello World!"; }
}
重新启动./gradlew bootRun 并进行操作确认。
迄今为止每次更改Java代码时,都需要重新启动Gradle,不过好像有一种可以进行热重载的解决方案,就是Spring Loaded。
链接:https://github.com/spring-projects/spring-loaded
通常在涉及Spring的项目中,我们经常使用JUnit进行单元测试来进行验证,因此并不需要将Servlet容器保持自动开启并自动重新加载类,因此我从未使用过Spring Loaded(尽管实际上使用它确实会有一些不便)。
看了这篇文章后,发现可以轻松地进行协作,因此决定试一试。
http://qiita.com/Sa2/items/c3150e3d43698cd67ff1
此外,我觉得应该到了要使用IDE的时候了,所以我决定像往常一样使用IntelliJ IDEA。
IntelliJ IDEA + Spring Loaded = IntelliJ IDEA 加 Spring Loaded
首先添加 idea 插件。idea 块是为了使 IDEA 将 class 文件输出到与 Gradle 的输出目录相匹配,因此直接复制粘贴。
apply plugin: 'idea'
idea {
module {
inheritOutputDirs = false
outputDir = file("$buildDir/classes/main/")
}
}
想法被添加了一个任务。
$ ./gradlew tasks
(中略)
IDE tasks
---------
cleanIdea - Cleans IDEA project files (IML, IPR)
idea - Generates IDEA project files (IML, IPR, IWS)
(以下略)
立即运行并输出 IDEA 的配置文件。
$ ./gradlew idea
Starting a new Gradle Daemon for this build (subsequent builds will be faster).
:ideaModule
Download https://jcenter.bintray.com/org/springframework/boot/spring-boot-starter-test/1.3.0.RELEASE/spring-boot-starter-test-1.3.0.RELEASE.pom
Download https://jcenter.bintray.com/org/mockito/mockito-core/1.10.19/mockito-core-1.10.19.pom
Download https://jcenter.bintray.com/org/hamcrest/hamcrest-library/1.3/hamcrest-library-1.3.pom
Download https://jcenter.bintray.com/org/springframework/spring-test/4.2.3.RELEASE/spring-test-4.2.3.RELEASE.pom
Download https://jcenter.bintray.com/org/objenesis/objenesis/2.1/objenesis-2.1.pom
Download https://jcenter.bintray.com/org/objenesis/objenesis-parent/2.1/objenesis-parent-2.1.pom
Download https://jcenter.bintray.com/org/springframework/boot/spring-boot-starter-test/1.3.0.RELEASE/spring-boot-starter-test-1.3.0.RELEASE.jar
Download https://jcenter.bintray.com/org/mockito/mockito-core/1.10.19/mockito-core-1.10.19.jar
Download https://jcenter.bintray.com/org/hamcrest/hamcrest-library/1.3/hamcrest-library-1.3.jar
Download https://jcenter.bintray.com/org/springframework/spring-test/4.2.3.RELEASE/spring-test-4.2.3.RELEASE.jar
Download https://jcenter.bintray.com/org/objenesis/objenesis/2.1/objenesis-2.1.jar
Download https://jcenter.bintray.com/org/springframework/boot/spring-boot-starter-web/1.3.0.RELEASE/spring-boot-starter-web-1.3.0.RELEASE-sources.jar
Download https://jcenter.bintray.com/org/springframework/boot/spring-boot-devtools/1.3.0.RELEASE/spring-boot-devtools-1.3.0.RELEASE-sources.jar
Download https://jcenter.bintray.com/org/springframework/boot/spring-boot-starter-test/1.3.0.RELEASE/spring-boot-starter-test-1.3.0.RELEASE-sources.jar
Download https://jcenter.bintray.com/org/springframework/boot/spring-boot-starter/1.3.0.RELEASE/spring-boot-starter-1.3.0.RELEASE-sources.jar
Download https://jcenter.bintray.com/org/springframework/boot/spring-boot-starter-tomcat/1.3.0.RELEASE/spring-boot-starter-tomcat-1.3.0.RELEASE-sources.jar
Download https://jcenter.bintray.com/org/springframework/boot/spring-boot-starter-validation/1.3.0.RELEASE/spring-boot-starter-validation-1.3.0.RELEASE-sources.jar
Download https://jcenter.bintray.com/com/fasterxml/jackson/core/jackson-databind/2.6.3/jackson-databind-2.6.3-sources.jar
Download https://jcenter.bintray.com/org/springframework/spring-web/4.2.3.RELEASE/spring-web-4.2.3.RELEASE-sources.jar
Download https://jcenter.bintray.com/org/springframework/spring-webmvc/4.2.3.RELEASE/spring-webmvc-4.2.3.RELEASE-sources.jar
Download https://jcenter.bintray.com/org/springframework/boot/spring-boot/1.3.0.RELEASE/spring-boot-1.3.0.RELEASE-sources.jar
Download https://jcenter.bintray.com/org/springframework/boot/spring-boot-autoconfigure/1.3.0.RELEASE/spring-boot-autoconfigure-1.3.0.RELEASE-sources.jar
Download https://jcenter.bintray.com/junit/junit/4.12/junit-4.12-sources.jar
Download https://jcenter.bintray.com/org/mockito/mockito-core/1.10.19/mockito-core-1.10.19-sources.jar
Download https://jcenter.bintray.com/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-sources.jar
Download https://jcenter.bintray.com/org/hamcrest/hamcrest-library/1.3/hamcrest-library-1.3-sources.jar
Download https://jcenter.bintray.com/org/springframework/spring-core/4.2.3.RELEASE/spring-core-4.2.3.RELEASE-sources.jar
Download https://jcenter.bintray.com/org/springframework/spring-test/4.2.3.RELEASE/spring-test-4.2.3.RELEASE-sources.jar
Download https://jcenter.bintray.com/org/springframework/boot/spring-boot-starter-logging/1.3.0.RELEASE/spring-boot-starter-logging-1.3.0.RELEASE-sources.jar
Download https://jcenter.bintray.com/org/yaml/snakeyaml/1.16/snakeyaml-1.16-sources.jar
Download https://jcenter.bintray.com/org/apache/tomcat/embed/tomcat-embed-core/8.0.28/tomcat-embed-core-8.0.28-sources.jar
Download https://jcenter.bintray.com/org/apache/tomcat/embed/tomcat-embed-el/8.0.28/tomcat-embed-el-8.0.28-sources.jar
Download https://jcenter.bintray.com/org/apache/tomcat/embed/tomcat-embed-logging-juli/8.0.28/tomcat-embed-logging-juli-8.0.28-sources.jar
Download https://jcenter.bintray.com/org/apache/tomcat/embed/tomcat-embed-websocket/8.0.28/tomcat-embed-websocket-8.0.28-sources.jar
Download https://jcenter.bintray.com/org/hibernate/hibernate-validator/5.2.2.Final/hibernate-validator-5.2.2.Final-sources.jar
Download https://jcenter.bintray.com/com/fasterxml/jackson/core/jackson-annotations/2.6.3/jackson-annotations-2.6.3-sources.jar
Download https://jcenter.bintray.com/com/fasterxml/jackson/core/jackson-core/2.6.3/jackson-core-2.6.3-sources.jar
Download https://jcenter.bintray.com/org/springframework/spring-aop/4.2.3.RELEASE/spring-aop-4.2.3.RELEASE-sources.jar
Download https://jcenter.bintray.com/org/springframework/spring-beans/4.2.3.RELEASE/spring-beans-4.2.3.RELEASE-sources.jar
Download https://jcenter.bintray.com/org/springframework/spring-context/4.2.3.RELEASE/spring-context-4.2.3.RELEASE-sources.jar
Download https://jcenter.bintray.com/org/springframework/spring-expression/4.2.3.RELEASE/spring-expression-4.2.3.RELEASE-sources.jar
Download https://jcenter.bintray.com/org/objenesis/objenesis/2.1/objenesis-2.1-sources.jar
Download https://jcenter.bintray.com/ch/qos/logback/logback-classic/1.1.3/logback-classic-1.1.3-sources.jar
Download https://jcenter.bintray.com/org/slf4j/jcl-over-slf4j/1.7.13/jcl-over-slf4j-1.7.13-sources.jar
Download https://jcenter.bintray.com/org/slf4j/jul-to-slf4j/1.7.13/jul-to-slf4j-1.7.13-sources.jar
Download https://jcenter.bintray.com/org/slf4j/log4j-over-slf4j/1.7.13/log4j-over-slf4j-1.7.13-sources.jar
Download https://jcenter.bintray.com/javax/validation/validation-api/1.1.0.Final/validation-api-1.1.0.Final-sources.jar
Download https://jcenter.bintray.com/org/jboss/logging/jboss-logging/3.3.0.Final/jboss-logging-3.3.0.Final-sources.jar
Download https://jcenter.bintray.com/com/fasterxml/classmate/1.1.0/classmate-1.1.0-sources.jar
Download https://jcenter.bintray.com/aopalliance/aopalliance/1.0/aopalliance-1.0-sources.jar
Download https://jcenter.bintray.com/ch/qos/logback/logback-core/1.1.3/logback-core-1.1.3-sources.jar
Download https://jcenter.bintray.com/org/slf4j/slf4j-api/1.7.13/slf4j-api-1.7.13-sources.jar
:ideaProject
:ideaWorkspace
:idea
BUILD SUCCESSFUL
Total time: 58.284 secs
这个地方是对之前的 Qiita 文章的引用,有关 IDEA 的设置可以在「Build, Execution, Deployment」>「Compiler」的「自动构建项目」选项上勾选,然后再次运行命令 ./gradlew bootRun。
2015-11-23 19:49:40.575 INFO 56854 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
2015-11-23 19:49:40.706 INFO 56854 --- [ restartedMain] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2015-11-23 19:49:40.714 INFO 56854 --- [ restartedMain] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2015-11-23 19:49:40.716 INFO 56854 --- [ restartedMain] myproject.Application : Started Application in 1.015 seconds (JVM running for 54.864)
2015-11-23 19:49:40.801 INFO 56854 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet 'dispatcherServlet'
2015-11-23 19:49:40.801 INFO 56854 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started
2015-11-23 19:49:40.803 INFO 56854 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 2 ms
> Building 80% > :bootRun
在这种情况下,如果更改 src/main/java/**.java,会重新启动 Tomcat,表现出正在重新启动的状态…
2015-11-23 19:50:15.605 INFO 56854 --- [ Thread-23] ationConfigEmbeddedWebApplicationContext : Closing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@3e05e4a6: startup date [Mon Nov 23 19:49:39 JST 2015]; root of context hierarchy
2015-11-23 19:50:15.606 INFO 56854 --- [ Thread-23] o.s.j.e.a.AnnotationMBeanExporter : Unregistering JMX-exposed beans on shutdown
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.3.0.RELEASE)
2015-11-23 19:50:15.875 INFO 56854 --- [ restartedMain] myproject.Application : Starting Application on seratchs-MacBook-Pro.local with PID 56854 (/Users/seratch/Documents/github/spring-boot-example/build/classes/main started by seratch in /Users/seratch/Documents/github/spring-boot-example)
2015-11-23 19:50:15.875 INFO 56854 --- [ restartedMain] myproject.Application : No profiles are active
2015-11-23 19:50:15.878 INFO 56854 --- [ restartedMain] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@160bf3cd: startup date [Mon Nov 23 19:50:15 JST 2015]; root of context hierarchy
2015-11-23 19:50:16.372 INFO 56854 --- [ restartedMain] o.s.b.f.s.DefaultListableBeanFactory : Overriding bean definition for bean 'beanNameViewResolver' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class]]
2015-11-23 19:50:16.524 INFO 56854 --- [ restartedMain] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http)
2015-11-23 19:50:16.527 INFO 56854 --- [ restartedMain] o.apache.catalina.core.StandardService : Starting service Tomcat
2015-11-23 19:50:16.527 INFO 56854 --- [ restartedMain] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.0.28
2015-11-23 19:50:16.534 INFO 56854 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2015-11-23 19:50:16.535 INFO 56854 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 657 ms
2015-11-23 19:50:16.615 INFO 56854 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/]
2015-11-23 19:50:16.617 INFO 56854 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*]
2015-11-23 19:50:16.624 INFO 56854 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2015-11-23 19:50:16.624 INFO 56854 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2015-11-23 19:50:16.624 INFO 56854 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*]
2015-11-23 19:50:16.682 INFO 56854 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@160bf3cd: startup date [Mon Nov 23 19:50:15 JST 2015]; root of context hierarchy
2015-11-23 19:50:16.694 INFO 56854 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/]}" onto java.lang.String myproject.web.HomeController.home()
2015-11-23 19:50:16.696 INFO 56854 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2015-11-23 19:50:16.697 INFO 56854 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest)
2015-11-23 19:50:16.704 INFO 56854 --- [ restartedMain] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2015-11-23 19:50:16.704 INFO 56854 --- [ restartedMain] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2015-11-23 19:50:16.722 INFO 56854 --- [ restartedMain] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2015-11-23 19:50:16.738 INFO 56854 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
2015-11-23 19:50:16.794 INFO 56854 --- [ restartedMain] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2015-11-23 19:50:16.808 INFO 56854 --- [ restartedMain] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2015-11-23 19:50:16.809 INFO 56854 --- [ restartedMain] myproject.Application : Started Application in 1.0 seconds (JVM running for 90.958)
2015-11-23 19:50:17.098 INFO 56854 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet 'dispatcherServlet'
2015-11-23 19:50:17.098 INFO 56854 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started
2015-11-23 19:50:17.101 INFO 56854 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 3 ms
在Twitter上得到的信息告诉我,这不是Spring Loaded,而是由spring-boot-devtools导致的行为。
@seratch_ja @megascus 这是使用开发工具的热加载功能,而非Spring Loaded,对吗?— Toshiaki Maki (@making) 2015年11月23日
原因只是因为Spring Loaded没有被添加进去导致的疏忽。非常抱歉给您带来困扰(& 谢谢您)。
因此,在build.gradle的buildscript.dependencies中添加”classpath(”org.springframework:springloaded:1.2.4.RELEASE”)”。
buildscript {
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.0.RELEASE")
classpath("org.springframework:springloaded:1.2.4.RELEASE")
}
}
禁用在依赖项中的 spring-boot-devtools。
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
//compile("org.springframework.boot:spring-boot-devtools")
testCompile("org.springframework.boot:spring-boot-starter-test")
}
然后使用 “./gradlew bootRun” 命令重新启动 Gradle。
用这种方式,你可以修改 Java 代码、添加或移动类等等,并且稍微有些延迟,但可以实现热加载而无需重新启动。非常好。
然而,似乎RequestMapping和Spring注册的Bean信息不会进行热重载,确实在我试过的情况下是这样的。这一点确实有点不方便。
@seratch_ja 这里指的是控制器的URL映射和bean定义之类的东西呢。— Σ(・ω・ノ)ノ! (@megascus) 2015年11月23日
之后,我也参考了这些网址:
我在想,当Spring Loaded进行热部署时,是否会输出任何日志?你可以参考此链接获取更多关于Spring Loaded的基本使用信息:https://github.com/spring-projects/spring-loaded/wiki/Basic-usage-information。
在 build.gradle 文件中进行以下设置后,日志开始大量输出。
bootRun {
systemProperty("springloaded", "verbose;explain")
}
当检测到文件被更改并编译结果被输出时,以下类型的日志将显示在标准输出中。
2015-11-24 12:56:48.262 INFO 40741 --- [Loader@14dad5dc] org.springsource.loaded.agent.Watcher : Observed last modification time change for /Users/k-sera/Documents/github/spring-boot-example/build/classes/main/myproject/web/HomeController.class (lastScanTime=1448337407162)
2015-11-24 12:56:48.262 INFO 40741 --- [Loader@14dad5dc] org.springsource.loaded.agent.Watcher : Firing file changed event /Users/k-sera/Documents/github/spring-boot-example/build/classes/main/myproject/web/HomeController.class
2015-11-24 12:56:48.263 INFO 40741 --- [Loader@14dad5dc] org.springsource.loaded.ReloadableType : Loading new version of myproject/web/HomeController, identifying suffix PUvM9u4, new data length is 593bytes
2015-11-24 12:56:48.264 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=org/springsource/loaded/TypeDiffComputer classloader=Launcher$AppClassLoader typeRegistry=TypeRegistry(id=455659002,loader=sun.misc.Launcher$AppClassLoader)
2015-11-24 12:56:48.264 INFO 40741 --- [Loader@14dad5dc] org.springsource.loaded.TypeRegistry : WhyNotReloadable? The type org/springsource/loaded/TypeDiffComputer is using a package name 'org/springsource/loaded/' which is considered infrastructure and types within it are not made reloadable
2015-11-24 12:56:48.265 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=sl/org/objectweb/asm/tree/ClassNode classloader=Launcher$AppClassLoader typeRegistry=TypeRegistry(id=455659002,loader=sun.misc.Launcher$AppClassLoader)
2015-11-24 12:56:48.266 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=sl/org/objectweb/asm/tree/AnnotationNode classloader=Launcher$AppClassLoader typeRegistry=TypeRegistry(id=455659002,loader=sun.misc.Launcher$AppClassLoader)
2015-11-24 12:56:48.267 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=sl/org/objectweb/asm/tree/MethodNode classloader=Launcher$AppClassLoader typeRegistry=TypeRegistry(id=455659002,loader=sun.misc.Launcher$AppClassLoader)
2015-11-24 12:56:48.269 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=sl/org/objectweb/asm/tree/InsnList classloader=Launcher$AppClassLoader typeRegistry=TypeRegistry(id=455659002,loader=sun.misc.Launcher$AppClassLoader)
2015-11-24 12:56:48.270 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=sl/org/objectweb/asm/tree/LabelNode classloader=Launcher$AppClassLoader typeRegistry=TypeRegistry(id=455659002,loader=sun.misc.Launcher$AppClassLoader)
2015-11-24 12:56:48.270 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=sl/org/objectweb/asm/tree/AbstractInsnNode classloader=Launcher$AppClassLoader typeRegistry=TypeRegistry(id=455659002,loader=sun.misc.Launcher$AppClassLoader)
2015-11-24 12:56:48.271 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=sl/org/objectweb/asm/tree/LineNumberNode classloader=Launcher$AppClassLoader typeRegistry=TypeRegistry(id=455659002,loader=sun.misc.Launcher$AppClassLoader)
2015-11-24 12:56:48.271 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=sl/org/objectweb/asm/tree/VarInsnNode classloader=Launcher$AppClassLoader typeRegistry=TypeRegistry(id=455659002,loader=sun.misc.Launcher$AppClassLoader)
2015-11-24 12:56:48.272 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=sl/org/objectweb/asm/tree/MethodInsnNode classloader=Launcher$AppClassLoader typeRegistry=TypeRegistry(id=455659002,loader=sun.misc.Launcher$AppClassLoader)
2015-11-24 12:56:48.273 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=sl/org/objectweb/asm/tree/InsnNode classloader=Launcher$AppClassLoader typeRegistry=TypeRegistry(id=455659002,loader=sun.misc.Launcher$AppClassLoader)
2015-11-24 12:56:48.273 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=sl/org/objectweb/asm/tree/LocalVariableNode classloader=Launcher$AppClassLoader typeRegistry=TypeRegistry(id=455659002,loader=sun.misc.Launcher$AppClassLoader)
2015-11-24 12:56:48.274 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=sl/org/objectweb/asm/tree/LdcInsnNode classloader=Launcher$AppClassLoader typeRegistry=TypeRegistry(id=455659002,loader=sun.misc.Launcher$AppClassLoader)
2015-11-24 12:56:48.275 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=org/springsource/loaded/TypeDelta classloader=Launcher$AppClassLoader typeRegistry=TypeRegistry(id=455659002,loader=sun.misc.Launcher$AppClassLoader)
2015-11-24 12:56:48.275 INFO 40741 --- [Loader@14dad5dc] org.springsource.loaded.TypeRegistry : WhyNotReloadable? The type org/springsource/loaded/TypeDelta is using a package name 'org/springsource/loaded/' which is considered infrastructure and types within it are not made reloadable
2015-11-24 12:56:48.276 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=org/springsource/loaded/MethodDelta classloader=Launcher$AppClassLoader typeRegistry=TypeRegistry(id=455659002,loader=sun.misc.Launcher$AppClassLoader)
2015-11-24 12:56:48.276 INFO 40741 --- [Loader@14dad5dc] org.springsource.loaded.TypeRegistry : WhyNotReloadable? The type org/springsource/loaded/MethodDelta is using a package name 'org/springsource/loaded/' which is considered infrastructure and types within it are not made reloadable
Reloading: Loading new version of myproject.web.HomeController [PUvM9u4]
2015-11-24 12:56:48.277 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=org/springsource/loaded/CurrentLiveVersion classloader=Launcher$AppClassLoader typeRegistry=TypeRegistry(id=455659002,loader=sun.misc.Launcher$AppClassLoader)
2015-11-24 12:56:48.277 INFO 40741 --- [Loader@14dad5dc] org.springsource.loaded.TypeRegistry : WhyNotReloadable? The type org/springsource/loaded/CurrentLiveVersion is using a package name 'org/springsource/loaded/' which is considered infrastructure and types within it are not made reloadable
2015-11-24 12:56:48.278 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=org/springsource/loaded/IncrementalTypeDescriptor classloader=Launcher$AppClassLoader typeRegistry=TypeRegistry(id=455659002,loader=sun.misc.Launcher$AppClassLoader)
2015-11-24 12:56:48.278 INFO 40741 --- [Loader@14dad5dc] org.springsource.loaded.TypeRegistry : WhyNotReloadable? The type org/springsource/loaded/IncrementalTypeDescriptor is using a package name 'org/springsource/loaded/' which is considered infrastructure and types within it are not made reloadable
2015-11-24 12:56:48.279 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=org/springsource/loaded/ExecutorBuilder$ExecutorBuilderVisitor classloader=Launcher$AppClassLoader typeRegistry=TypeRegistry(id=455659002,loader=sun.misc.Launcher$AppClassLoader)
2015-11-24 12:56:48.279 INFO 40741 --- [Loader@14dad5dc] org.springsource.loaded.TypeRegistry : WhyNotReloadable? The type org/springsource/loaded/ExecutorBuilder$ExecutorBuilderVisitor is using a package name 'org/springsource/loaded/' which is considered infrastructure and types within it are not made reloadable
2015-11-24 12:56:48.280 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=org/springsource/loaded/ExecutorBuilder$ExecutorBuilderVisitor$CopyingAnnotationVisitor classloader=Launcher$AppClassLoader typeRegistry=TypeRegistry(id=455659002,loader=sun.misc.Launcher$AppClassLoader)
2015-11-24 12:56:48.280 INFO 40741 --- [Loader@14dad5dc] org.springsource.loaded.TypeRegistry : WhyNotReloadable? The type org/springsource/loaded/ExecutorBuilder$ExecutorBuilderVisitor$CopyingAnnotationVisitor is using a package name 'org/springsource/loaded/' which is considered infrastructure and types within it are not made reloadable
2015-11-24 12:56:48.281 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=org/springsource/loaded/ConstructorCopier classloader=Launcher$AppClassLoader typeRegistry=TypeRegistry(id=455659002,loader=sun.misc.Launcher$AppClassLoader)
2015-11-24 12:56:48.281 INFO 40741 --- [Loader@14dad5dc] org.springsource.loaded.TypeRegistry : WhyNotReloadable? The type org/springsource/loaded/ConstructorCopier is using a package name 'org/springsource/loaded/' which is considered infrastructure and types within it are not made reloadable
2015-11-24 12:56:48.282 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=org/springsource/loaded/MethodCopier classloader=Launcher$AppClassLoader typeRegistry=TypeRegistry(id=455659002,loader=sun.misc.Launcher$AppClassLoader)
2015-11-24 12:56:48.282 INFO 40741 --- [Loader@14dad5dc] org.springsource.loaded.TypeRegistry : WhyNotReloadable? The type org/springsource/loaded/MethodCopier is using a package name 'org/springsource/loaded/' which is considered infrastructure and types within it are not made reloadable
2015-11-24 12:56:48.283 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=org/springsource/loaded/DispatcherBuilder classloader=Launcher$AppClassLoader typeRegistry=TypeRegistry(id=455659002,loader=sun.misc.Launcher$AppClassLoader)
2015-11-24 12:56:48.283 INFO 40741 --- [Loader@14dad5dc] org.springsource.loaded.TypeRegistry : WhyNotReloadable? The type org/springsource/loaded/DispatcherBuilder is using a package name 'org/springsource/loaded/' which is considered infrastructure and types within it are not made reloadable
2015-11-24 12:56:48.284 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=org/springsource/loaded/DispatcherBuilder$DispatcherBuilderVisitor classloader=Launcher$AppClassLoader typeRegistry=TypeRegistry(id=455659002,loader=sun.misc.Launcher$AppClassLoader)
2015-11-24 12:56:48.284 INFO 40741 --- [Loader@14dad5dc] org.springsource.loaded.TypeRegistry : WhyNotReloadable? The type org/springsource/loaded/DispatcherBuilder$DispatcherBuilderVisitor is using a package name 'org/springsource/loaded/' which is considered infrastructure and types within it are not made reloadable
2015-11-24 12:56:48.285 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=myproject/web/HomeController$$DPUvM9u4 classloader=ChildClassLoader typeRegistry=null
2015-11-24 12:56:48.286 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=org/springsource/loaded/__DynamicallyDispatchable classloader=Launcher$AppClassLoader typeRegistry=TypeRegistry(id=455659002,loader=sun.misc.Launcher$AppClassLoader)
2015-11-24 12:56:48.286 INFO 40741 --- [Loader@14dad5dc] org.springsource.loaded.TypeRegistry : WhyNotReloadable? The type org/springsource/loaded/__DynamicallyDispatchable is using a package name 'org/springsource/loaded/' which is considered infrastructure and types within it are not made reloadable
2015-11-24 12:56:48.286 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=myproject/web/HomeController$$EPUvM9u4 classloader=ChildClassLoader typeRegistry=null
2015-11-24 12:56:48.287 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=java/io/ObjectStreamClass$Caches classloader=null typeRegistry=null
2015-11-24 12:56:48.287 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=com/sun/beans/finder/PropertyEditorFinder classloader=null typeRegistry=null
2015-11-24 12:56:48.288 INFO 40741 --- [Loader@14dad5dc] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=org/springframework/util/ConcurrentReferenceHashMap$2 classloader=Launcher$AppClassLoader typeRegistry=TypeRegistry(id=455659002,loader=sun.misc.Launcher$AppClassLoader)
2015-11-24 12:56:48.288 INFO 40741 --- [Loader@14dad5dc] org.springsource.loaded.TypeRegistry : WhyNotReloadable? The type org/springframework/util/ConcurrentReferenceHashMap$2 is using a package name 'org/springframework/' which is considered infrastructure and types within it are not made reloadable
2015-11-24 12:56:48.288 INFO 40741 --- [Loader@14dad5dc] org.springsource.loaded.TypeRegistry : WhyNotReloadable? The type org/springframework/util/ConcurrentReferenceHashMap$2 is using a package name 'org/springframework/' which is considered infrastructure and types within it are not made reloadable
2015-11-24 12:56:48.289 INFO 40741 --- [Loader@14dad5dc] org.springsource.loaded.TypeRegistry : WhyNotReloadable? The type org/springframework/util/ConcurrentReferenceHashMap$Task is using a package name 'org/springframework/' which is considered infrastructure and types within it are not made reloadable
2015-11-24 12:56:48.289 INFO 40741 --- [Loader@14dad5dc] org.springsource.loaded.TypeRegistry : WhyNotReloadable? The type org/springframework/util/ConcurrentReferenceHashMap$Reference is using a package name 'org/springframework/' which is considered infrastructure and types within it are not made reloadable
2015-11-24 12:56:48.289 INFO 40741 --- [Loader@14dad5dc] org.springsource.loaded.TypeRegistry : WhyNotReloadable? The type org/springframework/util/ConcurrentReferenceHashMap$Entry is using a package name 'org/springframework/' which is considered infrastructure and types within it are not made reloadable
> Building 80% > :bootRun
然而,当设置此选项时,不知何故往往会有较高的概率以 exit 1 异常退出。
015-11-24 12:57:48.662 INFO 40758 --- [ DestroyJavaVM] o.s.l.agent.SpringLoadedPreProcessor : SpringLoaded preprocessing: classname=java/util/IdentityHashMap$KeyIterator classloader=null typeRegistry=null
:bootRun FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':bootRun'.
> Process 'command '/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home/bin/java'' finished with non-zero exit value 1
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
Total time: 10.923 secs
顺便说一下,如果使用./graldew bootRun –stacktrace命令运行,会出现如下日志,但仅凭此无法确定原因。
* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':bootRun'.
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:69)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64)
at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:52)
at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:203)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:185)
at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:66)
at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:50)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:25)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:110)
at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
at org.gradle.execution.DefaultBuildExecuter.access$000(DefaultBuildExecuter.java:23)
at org.gradle.execution.DefaultBuildExecuter$1.proceed(DefaultBuildExecuter.java:43)
at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:30)
at org.gradle.initialization.DefaultGradleLauncher$4.run(DefaultGradleLauncher.java:154)
at org.gradle.internal.Factories$1.create(Factories.java:22)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:52)
at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:151)
at org.gradle.initialization.DefaultGradleLauncher.access$200(DefaultGradleLauncher.java:32)
at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:99)
at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:93)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:62)
at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:93)
at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:82)
at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:94)
at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28)
at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:43)
at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:28)
at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:77)
at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:47)
at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:52)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:37)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
at org.gradle.util.Swapper.swap(Swapper.java:38)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.health.DaemonHealthTracker.execute(DaemonHealthTracker.java:47)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:66)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:72)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.health.HintGCAfterBuild.execute(HintGCAfterBuild.java:41)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:246)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
Caused by: org.gradle.process.internal.ExecException: Process 'command '/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home/bin/java'' finished with non-zero exit value 1
at org.gradle.process.internal.DefaultExecHandle$ExecResultImpl.assertNormalExitValue(DefaultExecHandle.java:367)
at org.gradle.process.internal.DefaultJavaExecAction.execute(DefaultJavaExecAction.java:31)
at org.gradle.api.tasks.JavaExec.exec(JavaExec.java:75)
at org.springframework.boot.gradle.run.BootRunTask.exec(BootRunTask.java:63)
at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:75)
at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.doExecute(AnnotationProcessingTaskFactory.java:227)
at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:220)
at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:209)
at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:585)
at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:568)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
... 68 more
可能已经有人提出了这个问题作为一个已知的事件,但总之,Spring Loaded现在可以使用了。
开发工具的自动重启
刚才重启Tomcat是由于spring-boot-devtools的操作。以前在从文档粘贴的build.gradle中有点不明确地启用了它,但是不知道它到底是什么。更进一步的说明在「20. 开发工具」中提供。
根据「20.2 自动重启」中所述,如果类路径上的文件发生更改,devtools似乎会重新启动Tomcat。默认情况下,它会检测类路径上所有资源的更改并进行重新启动。可以通过配置来更改这个更改检测目标。
devtools的重新启动机制并不仅仅是简单地重新启动。它使用了两个类加载器,分别是base和restart。对于那些不会改变的类,比如存在于jar文件中的类,会使用base加载器来加载,而对于经常发生变化的类,比如在src/main/java下的类,会使用restart加载器来加载。当重新启动时,只需要重新创建名为restart的类加载器,就能比简单地重新启动更快地启动。
如果你认为重启不如重新加载好的话,那么除了Spring Loaded,建议你也考虑一下ZeroTurnaround公司的JRebel(这个我其实还没用过,所以想找机会试试看)。
暫時在這附近停下來
因此,由於文章變得很長,我們可以考慮在這裡結束這篇文章。
我认为Spring Boot的好处在于可以轻松地进行试验。如果你有使用过Spring的经验,就可以想象出注释是做什么的,而且不需要费力地进行初始设置,这真是非常顺畅和好。
目前,我对测试相关、Swagger合作和OAuth2有兴趣,所以首先想尝试一下这些方面。另外,我也想尝试一下用Scala来做一些项目,虽然我用Gradle用的是Groovy,但也考虑过用Groovy尝试一下。