从本章开始,我将一步步地带领读者学习Spring Boot到Spring Cloud的基础知识,并在此基础上,完成实际项目的开发。
Spring Boot简介
Spring Boot是由 Pivotal团队提供的基于Spring的全新框架,其设计目的是简化Spring应用的搭建和开发过程。该框架遵循“约定大于配置”原则,采用特定的方式进行配置,从而使开发者无须进行大量的XML配置。Spring Boot致力于成为蓬勃发展的快速应用开发领域的领导者。
Spring Boot并不重复“造轮子”,而是在原有Spring框架的基础上进行封装,并且它集成了一些类库,用于简化开发。换句话说,Spring Boot就是一个大容器。
关于 Spring Boot,其官网是这样描述的:
Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can “just run”. We take an opinionated view of the Spring platform and third-party libraries so you can get started with minimum fuss. Most Spring Boot applications need very little Spring configuration.
从上面的描述中,我们可以了解到,Spring Boot带给了我们全新的应用部署方案,通过它可以很方便地创建独立的、生产级的基于Spring的应用程序。同时,通过 Spring平台和第三方库可以轻松创建视图。
其实,Spring Boot默认集成了 Tomcat,因此我们可以只编译成jar包,通过 Java命令启动应用, 大多数Spring Boot应用程序只需要很少的Spring配置。
你好!世界
我们学习任何一门语言、一种框架,第一件事就是编写"Hello,World"程序,本专题也不例外,本节,我们就来编写入门Spring Boot的第一个程序。
打开IDEA,依次点击File->New->Project,如图1-1所示。
图1-1 IDEA项目创建图
然后选择Maven,并点击下一步,如图1-2所示。
图1-2 IDEA项目创建图
在GroupId后输入com.lynn.demo,ArtifactId后输入demo,依次点击Next->Finish,即可创建好一个空的Maven工程,如图1-3所示。
图1-3 项目示例图
接下来,我们就来编写第一Spring Boot应用。
首先,在pom.xml中加入Spring Boot相关依赖。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.60</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.0</version>
</dependency>
</dependencies>
由于Spring Boot基于Spring MVC,它是一个Web工程,因此我们需要依赖spring-boot-starter-web,使其集成Spring MVC,否则工程无法正确启动;在导读篇我已提到,为了简化代码,本专题的示例中均依赖lombok框架,因此在pom.xml中,也加入了该框架。
然后,编写应用的启动类,代码如下:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
上述代码中,我们只编写了一个main方法,通过SpringBoot内置的SpringApplication来启动应用程序,这就是Spring Boot的强大之处,因为它集成了Tomcat容器,因此我们无需安装Tomcat即可启动它。
需要注意的是,启动类必须添加@SpringBootApplication注解,否则启动会报错,该注解表明Application类是SpringBoot启动类,而启动时的很多操作都是需要通过该注解完成的配置,读者通过查看SpringBootApplicaiton源码可明白一二。
@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 {
@AliasFor(annotation = EnableAutoConfiguration.class)
Class<?>[] exclude() default {};
@AliasFor(annotation = EnableAutoConfiguration.class)
String[] excludeName() default {};
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};
@AliasFor(annotation = Configuration.class)
boolean proxyBeanMethods() default true;
}
由于本专题为入门专题,故对Spring Boot源码不做详细分析。
最后,启动Application类,在控制台可以看到如图1-4所示信息。
这样,我们就完成了Spring Boot应用程序的启动。但是,上述代码无任何功能,本节最开始,我提到了要编写"Hello,Word"程序,我们需要在浏览器中显示出来。
Spring Boot已经集成了Spring MVC,因此我们接下来的操作和Spring MVC大同小异,编写一个Controller,并提供HTTP地址即可。代码如下:
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("hello")
public class HelloController {
@RequestMapping("index")
public String index(){
return "你好!世界!";
}
}
然后重启Application,浏览器访问:http://localhost:8080/hello/index,可看到如图1-5所示界面。
图1-5 运行效果
配置文件
在上一节的示例中,读者可以发现,我们没有编写一个XML配置,甚至没有一个配置文件就可以启动一个Web应用程序。那是因为,Spring Boot对于每种配置都有自己的默认值。
例如:端口默认为8080,上下文路径默认为“/”。
整个Spring Boot应用程序,我们可以只需要一个配置文件即可,Spring Boot应用启动时,会将该配置文件内容加载到Spring容器中。Spring Boot支持两种格式的配置文件,它们分别是propertes和yml。Spring Boot官方默认properties格式的配置文件,但笔者认为,yml文件结构更加明了,可读性更好,因此笔者推荐读者也采用yml格式的配置文件。本专题的配置也全采用yml格式。
接下来,就跟随我一起来探究yml格式吧!
yml文件的基本格式如下:
key1:
key2:
key3: value
key4:
key5: value1
我们将它替换成properties格式,即key1.key2.key3=value和key1.key4.key5=value1。可以看到,yml的层次结构较为清晰。当然,key的个数不是固定的。这里需要说明的是,yml格式非常严格,如果当前的key后面需要跟value,则冒号后面必须至少有一个空格,否则启动会报错;其次,每个子属性之间需要通过空格或制表符(即按下Tab键)分隔,否则可能无法获取到正确的属性。
在后面的讲解中,如果代码形式,将采用yml格式展示,为了便于解释,如果代码解释则采用properties格式加以说明。
在src/main/resources下创建名为application.yml的文件,并编写下述代码:
server:
port: 8081
servlet:
context-path: /api
上述代码中,server.port表示应用端口,本示例改为8081,server.servlet.context-path为上下文路径,本示例改为/api。启动应用程序,访问http://localhost:8081/api/hello/index,可以看到图1-5相同的运行效果。
本节主要对yml格式进行一定的说明,并做了简单的效果展示,在后面的学习中,Spring Boot应用的大部分配置说明都将一一呈现。
配置类
不知道读者是否还有印象,在Spring MVC中,我们定义一个Bean或者一个Component都是在XML里面设置,譬如下述代码:
<bean class="com.lynn.demo.Bean">
<property value="id">1</property>
<property value="name">2</property>
</bean>
Spring Boot定义一个Bean,就非常简单,只需要一个注解就行。
首先创建一个普通类Person,编写下述代码:
import lombok.Builder;
import lombok.Data;
import lombok.ToString;
@Data
@Builder
@ToString
public class Person {
private Long id;
private String name;
}
然后编写配置类,我们取名为WebConfig,并编写下述代码:
@SpringBootConfiguration
public class WebConfig{
@Bean
public Person person(){
return Person.builder().id(1L).name("lynn").build();
}
}
上述代码中,我们首先添加@SpringBootConfiguration注解,凡是添加了该注解的类都可以是SpringMVC的配置类,都可以在里面定义Bean;然后,将Person实例化并初始化一些值,并添加@Bean注解,应用启动时,Spring就可以将Person类加入到Spring容器中,我们就可以在任何Spring的容器类中注入他。
本节暂不做演示,在后面读者将看到Person类的输出。
自定义Json转换器
我们在Controller输出结果时,Spring Boot默认用Jackjson框架解析结果并返回,如果读者不喜欢该框架,Spring Boot也支持改变Json转换器,下面以Fastjson为例,来演示如何改变为Fastjson。
首先修改WebConfig类,使其继承WebMvcConfigurationSupport类,并重写configureMessageConverters,添加代码如下:
@SpringBootConfiguration
public class WebConfig extends WebMvcConfigurationSupport {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
super.configureMessageConverters(converters);
FastJsonHttpMessageConverter fastConverter=new FastJsonHttpMessageConverter();
FastJsonConfig fastJsonConfig=new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(
SerializerFeature.PrettyFormat
);
List<MediaType> mediaTypeList = new ArrayList<>();
mediaTypeList.add(MediaType.APPLICATION_JSON);
fastConverter.setSupportedMediaTypes(mediaTypeList);
fastConverter.setFastJsonConfig(fastJsonConfig);
converters.add(fastConverter);
}
}
重启Application,浏览器访问应用,可以看到图1-6所示界面。
图1-6 运行效果
读者可以发现,返回的界面样式和图1-5有所区别,说明Json转换器改变成功了。
拦截器
在一个大型应用中,会涉及到许多安全性要求较高的接口,因此需要一些安全策略来保证接口传输的安全性。我们在编写代码时,不可能对所有接口都写一遍安全性校验,这时就需要用到拦截器了。
拦截器会将所有HTTP请求地址进行拦截,我们可以在拦截器里做相应的安全性处理,如果合法请求则通过,否则拦截。
Spring Boot创建拦截器很简单。首先创建名为ApiInterceptor的类,并实现HandlerInterceptor接口,并编写下述代码:
@Slf4j
public class ApiInterceptor implements HandlerInterceptor {
@Autowired
private Person person;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
log.info("调用接口前" + person);
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
log.info("调用接口时");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
log.info("调用接口后");
}
}
上述代码中,我们注入了前面编写的Person类,并在拦截器里打印出来。该拦截器共有三个方法,其中,preHandle为接口调用前执行,postHandle为接口调用时执行,afterCompletion为接口调用完成后执行。我们进行安全策略一般在preHandle方法编写,该方法返回boolean值,为false则被拦截,即不会再调用指定的接口了,为true则允许继续调用指定接口。
我们启动Application类,并访问HTTP地址,控制台可以看到图1-7所示信息。
图1-7 IDEA控制台日志