Spring Boot 入门例子和说明
- 刚接触Spring Boot,记录一些简单入门的知识点;
Spring Boot能让我们以最简单的方式创建独立的、产品级别的基于Spring的应用。
本文大部分内容来自spring boot的官方文档,以及Youtube的入门讲解.
总的来说,你可以用很少的配置,并且以很简单优雅的方式启动你的Spring Boot应用。
- Spring Boot设计者所想要解决的主要问题:
1、 为Spring应用的部署提供更为快捷的多途径的方式;
2、开箱即用,同样也可以快速修改默认设置;
3、为大项目提供一系列能共用的不需要编程支持的特性(例如嵌入式web容器、安全、度量、健康检查、外部配置);
4、不需要生成XML文件,也不需要配置XML文件
快速生成Demo项目
Spring提供在线生成项目的方式:start.spring.io
同样,访问在命令行访问该网站,可以获得命令行生成项目的方式;
此处不以这种方式创建Demo项目。
手动创建Spring Boot项目
使用Maven来创建Spring Boot项目
- 创建POM文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>myproject</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.7.RELEASE</version>
</parent>
<!-- Additional lines to be added here... -->
</project>
添加spring-boot-starter-parent
的父引用,为了方便地添加依赖,Spring Boot 提供了很多 Starters
。上面配置的starter-parent
提供了很多Maven默认依赖,它还提供了dependencyManagement
,这样,那些默认的依赖,可以不用version
设置就继承过来了。
回顾一下以前的开发,如果需要开发Spring MVC 项目,需要引用很多的依赖,并且每个都需要自己引用(当然你也可以复制粘贴),有了Spring Boot的Starter之后,就能以简单的方式添加一个新的功能,比如
Spring MVC
,JPA
,test
等等很多,Spring Boot提供了很多的Starter,具体可以访问:这里
Demo中将添加一个Spring MVC的服务,所以还需要在POM文件中添加web的支持,所以添加上如下的配置:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
- 添加业务代码
@RestController
@EnableAutoConfiguration
public class Example {
@RequestMapping("/")
@ResponseBody
String home(){
return "Hello World\n";
}
public static void main(String[] args) {
SpringApplication.run(Example.class,args);
}
}
熟悉Spring MVC的人应该很容易就辨别出,Example类是一个Controller,它提供了一个访问路径为/
的服务,该服务返回一个字符串
Hello World
。至于@EnableAutoConfiguration
注解,该注解是告诉Spring Boot怎样去解析这个类,由于我们之前配置了spring-boot-starter-web
,这个配置将引入Spring MVC
和Tomcat
,该注解将会假定我们需要创建一个Web项目。(好吧,它猜对了)
关于Starters和AutoConfiguration
AutoConfiguration和Starters结合起来能很好地发挥作用,但是这两者没有直接捆绑在一起,
Spring Boot允许开发者在Starter外部配置Jar依赖,这种情况下,它也能尽量满足配置需要。
此外还有一个main方法,这是SpringBoot项目和传统的Web项目不同的地方,SpringApplication.run
方法创建了一个SpringApplication
的代理,SpringApplication
负责启动Spring Boot项目。同样,@EnableAutoConfiguration
也会负责启动Spring环境和tomcat服务。
很好奇@EnableAutoConfiguration做了些什么事情,通过注释可以有一些发现:
它会尝试着去查找classpath下定义的Bean,这些Bean定义在spring.factories中
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\
…
很多,也就是说,在启动过程中,会去过一遍这些Configuration,看看是否符合被加载的条件,如果符合,就加载对应的上下文环境。
当然,这里只是做了简单的描述。
启动SpringBoot项目也只需要运行这个main方法即可。
同样也可以在项目目录下运行:mvn spring-boot:run
启动完成之后,访问本地8080端口,将返回如下的结果:
Hello World
停止服务,只需要按下Ctrl—C
- 生成Jar包(不是war包)
很明显,如果要生成可以单独运行的jar包,jar包中就需要包含运行项目所有的依赖包。
一般情况下,按照依赖生成出来的jar包都会比较大,这样带来的好处是很简洁,不需要依赖其他的jar包就能执行。
但是这样也会带来jar包重名冲突,也不能很清晰地看到到底哪些jar包是被真正使用到的。
Spring Boot提供了一种新的方式来兼容这两方面的问题,它提供了
spring-boot-maven-plugin
插件,在build
阶段,它会添加依赖的jar包。
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
如果需要去除添加的jar依赖,运行jar vtf xxxx.jar
就会得到最原始的没有依赖的jar包。
- 运行jar
java jar xxx.jar
同样也可以启动Spring Boot项目。
如果需要更换tomcat端口,需要在项目的
application.properties
中添加配置server.port=8000
- 监控
之前提到,Spring Boot提供了一套监控机制,可以在服务运行期间,完整监控服务的运行状态以及宿主机的情况;
添加上监控的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-remote-shell</artifactId>
</dependency>
重新运行服务,可以在Console中发现如下日志:
2017-10-05 23:33:50.823 INFO 31462 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[ /metrics/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint.value(java.lang.String)
2017-10-05 23:33:50.823 INFO 31462 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[ /metrics || /metrics.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2017-10-05 23:33:50.824 INFO 31462 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[ /trace || /trace.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2017-10-05 23:33:50.825 INFO 31462 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[ /mappings || /mappings.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2017-10-05 23:33:50.827 INFO 31462 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[ /beans || /beans.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2017-10-05 23:33:50.828 INFO 31462 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[ /configprops || /configprops.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2017-10-05 23:33:50.832 INFO 31462 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[ /env/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EnvironmentMvcEndpoint.value(java.lang.String)
2017-10-05 23:33:50.835 INFO 31462 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[ /env || /env.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2017-10-05 23:33:50.838 INFO 31462 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[ /loggers/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint.get(java.lang.String)
2017-10-05 23:33:50.838 INFO 31462 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[ /loggers/{name:.*}],methods=[POST],consumes=[application/vnd.spring-boot.actuator.v1+json || application/json],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint.set(java.lang.String,java.util.Map<java.lang.String, java.lang.String>)
2017-10-05 23:33:50.839 INFO 31462 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[ /loggers || /loggers.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2017-10-05 23:33:50.839 INFO 31462 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[ /dump || /dump.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2017-10-05 23:33:50.841 INFO 31462 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[ /health || /health.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke(javax.servlet.http.HttpServletRequest,java.security.Principal)
2017-10-05 23:33:50.842 INFO 31462 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[ /info || /info.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2017-10-05 23:33:50.845 INFO 31462 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[ /heapdump || /heapdump.json],methods=[GET],produces=[application/octet-stream]}" onto public void org.springframework.boot.actuate.endpoint.mvc.HeapdumpMvcEndpoint.invoke(boolean,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.io.IOException,javax.servlet.ServletException
访问 /metrics
,将得到类似的结果:
{
"mem": 337766,
"mem.free": 120221,
"processors": 4,
"instance.uptime": 436478,
"uptime": 495497,
"systemload.average": 2.94091796875,
"heap.committed": 282112,
"heap.init": 131072,
"heap.used": 161890,
"heap": 1864192,
"nonheap.committed": 57048,
"nonheap.init": 2496,
"nonheap.used": 55653,
"nonheap": 0,
"threads.peak": 44,
"threads.daemon": 36,
"threads.totalStarted": 56,
"threads": 41,
"classes": 7135,
"classes.loaded": 7135,
"classes.unloaded": 0,
"gc.ps_scavenge.count": 9,
"gc.ps_scavenge.time": 164,
"gc.ps_marksweep.count": 2,
"gc.ps_marksweep.time": 177,
"httpsessions.max": -1,
"httpsessions.active": 0
}
支持以JMX的形式查看和管理内部对象;
运行JConsole
,连接我们运行的项目对应的Java进程;
除此之外,Spring Boot还支持以SSH的方式登录Manager后台:
在服务启动的时候,输出了类似这样的日志:
Using default password for shell access: e509d8bd-308b-447c-892d-90118ab11f28
利用这个口令,我们可以使用SSH命令,访问本地的manager命令行界面:
可以通过help查看支持的操作,例如:
> endpoint invoke healthEndpoint
endpoint invoke healthEndpoint
{status=UP, diskSpace={status=UP, total=249821663232, free=189794660352, threshold=10485760}}
这些都是同样信息的不同展现形式。
- 自定义监控
Spring Boot支持自定义的监控展示,例如,开发者可以加入自己定义的HealthIndicator;
@Bean
HealthIndicator healthIndicator(){
return new HealthIndicator() {
@Override
public Health health() {
return Health.status("Hello, I am a health indicator.").build();
}
};
}
结果如下:
{
"status": "UP",
"healthIndicator": {
"status": "Hello, I am a health indicator."
},
"diskSpace": {
"status": "UP",
"total": 249821663232,
"free": 189796761600,
"threshold": 10485760
}
}
- 关于web容器
Spring Boot的目标是,Use it as a jar
。
-EOF-