目录
什么是SpringBoot
Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。简单来说,就是 Spring Boot 其实不是什么新的框架,它默认配置了很多框架的使用方式,就像 Maven 整合了所有的 Jar 包,Spring Boot 整合了所有的框架。
使用 Spring Boot有什么好处
前面我们要搭建一个基于SSM的项目,我们需要进行如下的步骤
引入相关的依赖
添加对应的配置文件
配置日志框架
添加数据源
框架相互之间整合
…
总之步骤非常的繁琐,对于很多初学的小伙伴来说就非常的痛苦,不光步骤多而且容易遗忘,这时SpringBoot的作用就体现出来了,我仅仅只需要非常少的几个配置就可以迅速方便的搭建起来一套 Web 项目或者是构建一个微服务。一个字总结就是"爽"!
Spring Boot 特点
1).Spring Boot 设计目的是用来简化新 Spring 应用的初始搭建以及开发过程。
2).嵌入的 Tomcat,无需部署 WAR 文件
3).Spring Boot 并不是对 Spring 功能上的增强,而是提供了一种快速使用 Spring 的方式。
GA:General Availability,正式发布的版本,官方推荐使用此版本。在国外都是用GA来说明release版本的。
PRE: 预览版,内部测试版. 主要是给开发人员和测试人员测试和找BUG用的,不建议使用;
SNAPSHOT: 快照版,可以稳定使用,且仍在继续改进版本
SpringBoot的构建方式
其实构建SpringBoot项目的方式还是比较多的,但其本质都是一样的。
在线构建
Spring官方给我们提供一种在线创建SpringBoot项目的方式。其实我们后面通过开发工具创建有部分也是基于此创建的,首先打开此网站(https://start.spring.io/)
这里要配置的按顺序分别如下:
- 项目构建工具是 Maven 还是 Gradle ?Gradle 在 Android 中使用较多,Java 后端,目前来看还是 Maven 为主,因此这里选择第一项。
- 开发语言,当然选择 Java 了。
- Spring Boot 版本,可以看到,目前最新的稳定版是 2.1.4 ,这里我们就是用最新稳定版。
- 既然是 Maven 工程,当然要有项目坐标,项目描述等信息了,另外这里还让输入了包名,因为创建成功后会自动创建启动类。
- Packing 表示项目要打包成 jar 包还是 war 包,Spring Boot 的一大优势就是内嵌了 Servlet 容器,打成 jar 包后可以直接运行,所以这里建议打包成 jar 包,当然,开发者根据实际情况也可以选择 war 包。
- 然后选选择构建的 JDK 版本。
- 最后是选择所需要的依赖,输入关键字如 web ,会有相关的提示,这里我就先加入 web 依赖。
- 都设置完成后点击创建按钮,生成项目。然后将生成的项目导入到我们开发工具中即可。
如此,剩下的自行操作即可。
IntelliJ IDEA在线模板构建
这种方式其实和上面的是一样的,只是简化了我们的操作,也是我们最常用的构建方式。
IntelliJ IDEA 通maven项目构建
当然我们也可以不通过工具来直接构建出来,我们也可以通过一个maven项目来手动的构建,效率肯定没有前面的快,但是可以帮助我们更加清楚SpringBoot项目的结构。
然后点击 Next 完成项目的创建。
创建完成后,在 pom.xml 文件中,添加如下依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
添加成功后,再在 java 目录下创建包,包中创建一个名为 App 的启动类,如下:
启动即可
SpringBoot的常用配置
入口类和相关注解
SpringBoot项目通常都有一个名为*Application的入口类,入口类中有一个main方法,这个main方法就是一个标准的java应用的入口方法,方法中使用"SpringApplication.run(…)",启动SpringBoot应用项目。
在入口类中有一个注解"@SpringBootApplication",这是SpringBoot中的核心主键,它是一个组合组件,进入具体查看如下:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication
该组合注解中包括这三个:
@SpringBootConfiguration ,@EnableAutoConfiguration ,@ComponentScan如果我们不使用@SpringBootApplication注解的话,我们可以分别使用这三个注解来实现。
通过@SpringBootApplication的源码我们会发现SpringBoot会帮助我们完成很多的自动配置,但有些情况下我们并不需要SpringBoot帮助我们完成自动配置,这时我们可以通过@SpringBootApplication注解的exclude参数来设置,如下
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class SpringbootHelloApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootHelloApplication.class, args);
}
}
定制Banner
通过入口类启动的时候在控制台我们可以看到一个banner图案,处于兴趣原因们想要改下这个也是可以的,具体如下:
修改banner图标
默认的banner如下
在src/main/resources下新建一个banner.txt文件
通过访问http://patorjk.com/software/taag 网站生成字符,如"bobo",然后将生成的字符复制到banner.txt中,
关闭banner
这个banner其实并没有什么作用,一般情况下我们会关点它,我们来看看如何关掉banner。 main方法中修改如下
public static void main(String[] args) {
SpringApplication app = new SpringApplication(SpringbootHelloApplication.class);
// 关闭banner
app.setBannerMode(Banner.Mode.OFF);
app.run(args);
}
常规属性修改
SpringBoot使用一个全局的配置文件application.properties或application.yml,位于src/main/resources目录或者类路径/config下
tomcat端口号修改
tomcat的端口号默认是8080,我们需要将之修改为8082,并将默认访问路径"/" 修改为"/springboot"
server.port=8082
server.servlet.context-path=/springboot
启动后浏览器访问即可:
常规属性配置
前面介绍Spring的时候,我们想要注入properties中的值的时候我们需要通过@PropertySource指明properties文件的位置,然后通过@Value注入值,在SpringBoot中,我们只需要在application.properties定义属性,直接使用@Value注入即可。
application.properties增加属性
user.username=xx
user.age=18
user.address=bj
代码中获取
@RestController
public class HelloController {
@Value("${user.username}")
private String name;
@Value("${user.age}")
private int age;
@Value("${user.address}")
private String address;
@RequestMapping("/hello")
public String hello(){
return "Hello SpringBoot ... "+name+" "+age+" "+address;
}
}
访问测试
中文乱码处理
内容是取到了,但是中文乱码,如何解决呢,继续往下看
在application.properties中添加如下设置
server.tomcat.uri-encoding=UTF-8
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
spring.http.encoding.force=true
spring.messages.encoding=UTF-8
file – > setting – > Editor – > File Encodings – >然后按照如下图设置
再测试即可
类型安全的配置
上面将的属性配置在实际的开发过程中有点复杂,因为我们需要设置的属性太多了,这时我看可以使用类型安全的配置方式来实现,这样使用起来会更加方便,具体如下:
创建bean对象
@ConfigurationProperties注解需要加入如下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
@Component
@ConfigurationProperties(prefix = "users")
public class User {
private String name;
private String age;
private String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
业务代码
@RestController
public class HelloController {
@Autowired
private User user;
@RequestMapping("/hello")
public String hello(){
return "Hello SpringBoot ... "+user.getName()+" "+user.getAge()+" "+user.getAddress();
}
}
测试
日志
SpringBoot支持Java Util Logging、Log4J、Log4J2和Logback作为日志框架,无论使用哪种日志框架,SpringBoot已为当前使用的日志框架的控制台输出及文件输出做好了配置,默认情况下,SpringBoot使用Logback作为日志框架
配置日志级别:
# 日志配置
logging.file=c:/tools/log.log
logging.level.org.springframework.web=DEBUG
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="log.context.name" value="ibms"/>
<property name="log.charset" value="UTF-8"/>
<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS}[%p][%c][%M][%L] %msg%n "/>
<contextName>${log.context.name}</contextName>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder charset="${log.charset}">
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>./log/${log.context.name}%d{yyyyMMdd}.log</fileNamePattern>
<maxHistory>5</maxHistory>
</rollingPolicy>
<encoder charset="${log.charset}">
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<logger name="org.apache" level="ERROR" />
<logger name="org.apache.kafka" level="INFO" />
<logger name="org.springframework" level="ERROR" />
<logger name="org.springframework.data.elasticsearch.client.WIRE" level="trace"/>
<logger name="org.elasticsearch.client" level="ERROR"/>
<root>
<level value="info"/>
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE"/>
</root>
</configuration>
profile
profile我们在介绍Spring的时候就已经和大家介绍过了,profile的主要是用来针对不同的环境对不同的配置提供支持的,在Spring中使用的时候稍显得有点复杂,在SpringBoot中相对的要简单许多,全局Profile配置使用application-{profile}.properties(比如 application-prod.properties)举例实现如下:
在src/main/resources文件夹下定义不同环境下的Profile配置文件,文件名分别为application-prod.properties和application-dev.properties,这两个前者表示生产环境下的配置,后者表示开发环境下的配置,如下:
配置文件配置相关内容
application-dev.properties
server.port=8083 |
application-prod.properties
server.port=8082 |
application.properties
# 配置profile spring.profiles.active=dev |
表示使用的是开发环境
SpringBoot中静态资源的使用
springboot访问静态资源,默认有两个默认目录,
一个是 classpath/static 目录 (src/mian/resource)
一个是 ServletContext 根目录下( src/main/webapp )
static目录
在IDEA中默认创建的有此目录,如下:
在次目录下我们创建一个html文件和一张图片,并且创建了一个子目录images,其中存放了一张图片。
启动访问,启动之前最好install下
访问成功~
webapp目录
创建的项目默认是没有webapp目录的,我们需要手动创建该目录,如下:
然后对项目clean后install,我们查看install后的目录:
自定义目录
一般情况下,默认目录已经满足我们的需求了,但是在某些特殊的情况下我们可能需要将静态文件存放在特殊的文件夹下,我们可以在application.properties中如下配置
#表示所有的访问都经过静态资源路径
spring.mvc.static-path-pattern=/**
#覆盖默认配置,所以需要将默认的也加上否则static、public等这些路径将不能被当作静态资源路径
spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,classpath:/sfile/
然后启动程序,访问测试
自动装配原理
starter
名称 | 描述 |
spring-boot-starter-thymeleaf | 使MVC Web applications 支持Thymeleaf |
spring-boot-starter-data-couchbase | 使用Couchbase 文件存储数据库、Spring Data Couchbase |
spring-boot-starter-artemis | 为JMS messaging使用Apache Artemis |
spring-boot-starter-web-services | 使用Spring Web Services |
spring-boot-starter-mail | Java Mail、Spring email为邮件发送工具 |
spring-boot-starter-data-redis | 通过Spring Data Redis 、Jedis client使用Redis键值存储数据库 |
spring-boot-starter-web | 构建Web,包含RESTful风格框架SpringMVC和默认的嵌入式容器Tomcat |
spring-boot-starter-activemq | 为JMS使用Apache ActiveMQ |
spring-boot-starter-data-elasticsearch | 使用Elasticsearch、analytics engine、Spring Data Elasticsearch |
spring-boot-starter-integration | 使用Spring Integration |
spring-boot-starter-test | 测试 Spring Boot applications包含JUnit、 Hamcrest、Mockito |
spring-boot-starter-jdbc | 通过 Tomcat JDBC 连接池使用JDBC |
spring-boot-starter-mobile | 通过Spring Mobile构建Web应用 |
spring-boot-starter-validation | 通过Hibernate Validator使用 Java Bean Validation |
spring-boot-starter-hateoas | 使用Spring MVC、Spring HATEOAS构建 hypermedia-based RESTful Web 应用 |
spring-boot-starter-jersey | 通过 JAX-RS、Jersey构建 RESTful web applications;spring-boot-starter-web的另一替代方案 |
spring-boot-starter-data-neo4j | 使用Neo4j图形数据库、Spring Data Neo4j |
spring-boot-starter-websocket | 使用Spring WebSocket构建 WebSocket 应用 |
spring-boot-starter-aop | 通过Spring AOP、AspectJ面向切面编程 |
spring-boot-starter-amqp | 使用Spring AMQP、Rabbit MQ |
spring-boot-starter-data-cassandra | 使用Cassandra分布式数据库、Spring Data Cassandra |
spring-boot-starter-social-facebook | 使用 Spring Social Facebook |
spring-boot-starter-jta-atomikos | 为 JTA 使用 Atomikos |
spring-boot-starter-security | 使用 Spring Security |
spring-boot-starter-mustache | 使MVC Web applications 支持Mustache |
spring-boot-starter-data-jpa | 通过 Hibernate 使用 Spring Data JPA (Spring-data-jpa依赖于Hibernate) |
spring-boot-starter | Core starter,包括 自动配置支持、 logging and YAML |
spring-boot-starter-groovy-templates | 使MVC Web applications 支持Groovy Templates |
spring-boot-starter-freemarker | 使MVC Web applications 支持 FreeMarker |
spring-boot-starter-batch | 使用Spring Batch |
spring-boot-starter-social-linkedin | 使用Spring Social LinkedIn |
spring-boot-starter-cache | 使用 Spring caching 支持 |
spring-boot-starter-data-solr | 通过 Spring Data Solr 使用 Apache Solr |
spring-boot-starter-data-mongodb | 使用 MongoDB 文件存储数据库、Spring Data MongoDB |
spring-boot-starter-jooq | 使用JOOQ链接SQL数据库;spring-boot-starter-data-jpa、spring-boot-starter-jdbc的另一替代方案 |
spring-boot-starter-jta-narayana | Spring Boot Narayana JTA Starter |
spring-boot-starter-cloud-connectors | 用连接简化的 Spring Cloud 连接器进行云服务就像Cloud Foundry、Heroku那样 |
spring-boot-starter-jta-bitronix | 为JTA transactions 使用 Bitronix |
spring-boot-starter-social-twitter | 使用 Spring Social Twitter |
spring-boot-starter-data-rest | 使用Spring Data REST 以 REST 方式暴露 Spring Data repositories |
spring-boot-starter-actuator | 使用Spring Boot Actuator 的 production-ready 功能来帮助你监视和管理应用 |
spring-boot-starter-undertow | 使用 Undertow 作为嵌入式服务容器;spring-boot-starter-tomcat的另一替代方案 |
spring-boot-starter-jetty | 使用 Jetty 作为嵌入式服务容器;spring-boot-starter-tomcat的另一替代方案 |
spring-boot-starter-logging | 为 logging 使用Logback.默认 logging starter |
spring-boot-starter-tomcat | 使用 Tomcat 作为嵌入式服务容器;作为默认嵌入式服务容器被spring-boot-starter-web使用 |
spring-boot-starter-log4j2 | 使用Log4j2记录日志;spring-boot-starter-logging的另一替代方案 |
自动装配
@EnableAutoConfiguration
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
通过@EnableAutoConfiguration注解发现。其本身就是一个组合注解,有一个注解我们必须要弄清楚@Import注解
@Import
在Spring中我们将类型交给SpringIoC管理的方式有哪些?
1.基于xml配置文件<bean>
2.基于xml配置文件@Component
3.基于Java配置类【@Configuration】 @Bean
4.基于Java配置类+@ComponentScan+@Component
5.FactoryBean接口【getObject()】
6.@Import注解
第一种使用方式
静态使用方式
@Configuration
@Import(UserService.class)
public class JavaConfig {
/*@Bean
public UserService getUserSerivce(){
return new UserService();
}*/
}
在@Import注解中直接指定要添加的类型
缺点:直接在@Import中写死要注入的类型,不太灵活
第二种使用方式
ImportSelector接口
public class GpImportSelector implements ImportSelector {
/**
* 动态获取IoC要加载的类型
* @param annotationMetadata 注解的元数据
* @return
* IoC要加载的类型的数组
*/
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
// 根据不同的业务逻辑 实现动态添加IoC加载的类型
/*if (){
}*/
return new String[]{LoggerService.class.getName(),CacheService.class.getName()};
}
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(GpImportSelector.class)
public @interface EnableGpImport {
}
是将@Import注解中添加的 ImportSelector的实现类中的selectImports这个方法返回的字符串数组加载到IoC容器中
第三种实现方式
实现ImportBeanDefinitionRegistrar接口,其实和第二种方式很类似,都是在源码设计层面用的比较多。
public class GpImportBeanDefinition implements ImportBeanDefinitionRegistrar {
/**
* 提供了一个beanDefinition的注册器,我直接把需要IoC加载的类型注册到容器中去
* @param annotationMetadata
* @param beanDefinitionRegistry beanDefinition的注册器
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
// 将我们需要添加的类型统一封装为RootBeanDefinition对象
RootBeanDefinition cache = new RootBeanDefinition(CacheService.class);
beanDefinitionRegistry.registerBeanDefinition("cache",cache);
RootBeanDefinition logger = new RootBeanDefinition(LoggerService.class);
beanDefinitionRegistry.registerBeanDefinition("logger",logger);
}
}
原理分析
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
// 加载META-INF/spring-autoconfigure-metadata.properties
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
// 返回需要IoC加载的类型数组
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
} else {
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
// 获取候选的配置信息 META-INF/spring.factories 加载了很多的 类路径
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
// 去掉重复的
configurations = this.removeDuplicates(configurations);
// 去掉要排除掉的类型
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
this.checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 过滤器
configurations = this.filter(configurations, autoConfigurationMetadata);
// 广播
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
}
}
自动装配的原理:
1.在SpringBoot项目启动的时候,会加载SpringBootApplication这个注解
2.会解析@EnableAutoConfiguration注解
3.与之对应的解析@Import注解
4.执行ImportSelector接口的的实现
5.加载META-INF/spring-autoconfigure-metadata.properties中的注解元数据信息
6.加载META-INF/spring.factories各种类路径【第三方扩展也同样的会加载对应的文件 SPI扩展机制】