Spring Boot 入门指南
Spring Boot 快速入门
相信小伙伴们在使用 Spring 或 SpringMVC 的过程中,或多或少会被各种配置问题所牵绊,这些配置不仅徒增工作量,而且在跨平台部署时容易出现问题。
因此,Spring Boot 应运而生,它集成了大量常用的第三方库配置(例如 Jackson、JDBC、MongoDB、Redis、Mail 等等),这些第三方库几乎都可以零配置的开箱即用,可以帮助我们快速搭建一个项目,从而让开发者能够更加专注于业务逻辑。
Spring Boot 的优点及特性,就不再逐一罗列了,本场 Chat 针对 Spring Boot 的初学者,让我们先快速学会怎么用,至于更深入的探讨,留待后续 Chat 进行。
版本列表
快速构建项目
关于 Spring Boot 项目的构建,IDEA 为我们提供了良好的支持,在 IDEA 中 New→Project→Spring Initializr→Next→Next(可自己填写相关信息)→选中 Web 栏目的 Web 依赖→Next→Finish(可自己填写相关信息),一个简单 Spring Boot 项目搭建好了。
接下来我们看看 IDEA 自动生成目录结构(以读者填写的具体信息为准)。
-
main
-
java
-
xin.chung.springboot
-
SpringbootApplication.java(项目入口文件)
-
resources
-
static(静态资源包)
-
templates(页面模板包)
-
application.properties(项目属性配置文件)
-
test
-
java
-
xin.chung.springboot
-
SpringbootApplicationTests.java(测试文件)
IDEA 自动为我们生成了几个文件,其中 application.properties 文件为项目属性配置文件,一般包含服务器、数据库、日志等方面的配置,以及一些自定义的属性。
SpringbootApplicationTests.java 是 JUnit 测试类,用来进行开发过程中的单元测试。这两类文件,留待后面详细介绍。
至于这个 SpringbootApplication.java 文件,它其实是项目的入口文件,内容也非常简单,如下:
@SpringBootApplicationpublic class SpringbootApplication {public static void main(String[] args) { SpringApplication.run(SpringbootApplication.class, args); } }
当我们运行这个类或主方法时,框架就会自动为我们开启服务。若见日志打印如下,说明启动成功,从日志可以看到,我们的 Tomcat 8080 端口已经准备就绪。
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v1.5.9.RELEASE) ······ Tomcat started on port(s): 8080 (http) Started SpringbootApplication in 4.694 seconds (JVM running for 7.789)
关于项目构建途径或项目启动的其他方式,大家可在读者圈一起交流。
项目属性配置
单元测试
在后续话题开始之前,我们有必要先探讨下单元测试。以往我们写一段测试代码,有一个前置步骤:用ClassPathXmlApplicationContext
装载上下文,然后用ApplicationContext
对象获取 Bean 实例。
接下来,才能进行我们的测试代码编写。
而在 Spring Boot 中,极大简化了测试代码,它为我们提供了@RunWith
注解和@SpringBootTest
注解分别用来指定测试运行类和运行 Spring Boot 基础测试环境。
此时,你可以直接使用@Resource
或@Autowired
注入所需 Bean 并使用,示例如下:
@RunWith(SpringRunner.class)@SpringBootTestpublic class PropertiesTests {@Resourceprivate DemoService demoService;// 仅作展示,还未编写@Testpublic void test() { System.out.println(demoService.getDemo().toString()); } }
由于单元测试贯穿本场 Chat,所以每个章节都会在相应的地方讨论 Spring Boot 中 JUnit 的具体使用方法,此处只写出最简单的使用示例。
属性配置
在前面提到过的 application.properties 文件中,我们可以进行一些项目的配置,也可以自定义一些项目所需要的属性参数然后用@Value
注解在 Java 文件中引用。
例如:
# Server 服务相关 server.port=8080 server.context-path=/demo # Log 日志相关 logging.path=/var/logs logging.file=demo.log # Other 自定义 author=chung addr=http://gitbook.cn/gitchat/activity/5a444c451f6ee91a25846ac1
我们可以编写如下测试代码,验证.properties
文件中的值是否能被我们在 Java 文件中所使用,至于打印结果我就不贴出来了。
@RunWith(SpringRunner.class)@SpringBootTestpublic class PropertiesTests {@Value("${author}")private String author;@Value("${addr}")private String addr;@Testpublic void test() { System.out.println("author:" + author + "--addr:" + addr); } }
实际上,我们也可以使用 YAML 作为项目的配置文件,这种语言更加简洁明了。以上.properties
文件,可等价如下.yml
文件( 切记:
后面的空格不能少,同时注意每行的缩进 ):
# Server 服务相关 server: port: 8080 context-path: /demo # Log 日志相关 logging: path: /var/logs file: demo.log # Other 自定义 author: chung addr: http://gitbook.cn/gitchat/activity/5a444c451f6ee91a25846ac1
但是以上两种写法都有同一个弊端:项目里面自定义配置项往往会有很多,频繁使用@Value
注入将给项目的后期维护带来极大不便。
这时,我们就可以建立一个属性对象,利用@ConfigurationProperties
注解来绑定属性,有效简化繁杂的注入操作。例如:
# Other gitchat: author: chung addr: http://gitbook.cn/gitchat/activity/5a444c451f6ee91a25846ac1
@Component// prefix 对应配置文件中的前缀@ConfigurationProperties(prefix = "gitchat")public class GitChat {private String author;private String addr;/*** 省略 Getter Setter***/}
同理,我们可以编写如下测试代码,验证这种属性对象的方式能否正常使用。
@Resourceprivate GitChat gitChat;@Testpublic void test() { System.out.println("author:" + gitChat.getAuthor() + " addr:" + gitChat.getAddr()); }
可以看到,当属性越来越多,我们利用对象的方式优势也就越大,而至于.properties
和.yml
选哪种,就看个人喜好了。
控制器基本用法
关于 Controller
讨论完了项目的属性配置,让我们探讨一下在 Spring Boot 中如何使用控制器。在 Spring Boot Controller 的编码中,我们常用到的注解如下:
-
标注控制层组件的注解
@Controller
、@RestController
-
配置 URL 映射的注解
@RequestMapping
-
获取参数的注解
@PathVariable
(URL 中)、@RequestParam
(HTTP 请求中) -
校验参数的注解
@Valid
相信以上那些,大家或多或少有点熟悉,其实还有一些简洁的组合注解,这些注解在配合使用RESTful API
时,会非常优雅非常有逼格:
-
@GetMapping("")
-
@PostMapping("")
-
@PutMapping("")
-
@DeleteMapping("")
而实际上,XXXMapping("YYY")
和 @RequestMapping(value = "YYY",method = RequestMethod.XXX)
没有区别,点进源码一切你就会恍然大悟。
看完这些注解,接下来我们瞧瞧怎么把它们用进控制器。
先拿@Controller
和@RestController
来说,如果使用@Controller
注解,表示控制器返回的是模板,而使用@RestController
注解,则表示返回的可能是 JSON 或文本等等。
见如下代码,编写完成后启动项目,浏览器访问 http://localhost:8080/demo/say,你会看到 Hello World!就是这么简单粗暴,什么 Jackson 配置之类的,让框架替你解决就好了。
@RestControllerpublic class DemoController {@RequestMapping("/say")public String sayHello() {return "Hello World!"; } }
注意 :
项目配置文件选择 application.properties 与 application.yml 之一即可(删掉其中一个)
若上一章中没有配置 server.context-path=/demo 或者 context-path: /demo,则应访问 http://localhost:8080/say
添加完依赖后,右键 pom.xml→Maven→ Reimport,重新导入
至于@Controller
注解,我们常用来和模板引擎Thymeleaf
一起使用,这里我们不讨论模板引擎,简单看看@Controller
的使用:
-
在 pom 文件中导入
Thymeleaf
依赖(IDEA 的提示功能很强大,好好利用); -
编写 Controller 代码,返回 hello 页面模板;
-
编写页面模板 hello.html。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency>
@Controllerpublic class DemoController {@RequestMapping("/say")public String sayHello() {return "hello"; } }
<html><head><title>Hello</title></head><body><p>Hello World!</p></body></html>
同样,启动项目,访问 http://localhost:8080/demo/say,我们发现,Hello World! 还是那个 Hello World!,但是它们背后的故事可就大不相同了。
实际上,我们点进源码就会发现,
@RestController
其实就是@ResponseBody
+@Controller
,玩到后来还是被套路了 …
再来看看控制器中其它注解的使用,就拿那几个代表性的传说中和RESTful
完美搭配的那几个家伙为例,我们在@RestController
注解标识的控制器中,编写如下方法:
@GetMapping("/getGitChat/{id}")public GitChat getGitChat(@PathVariable String id) { GitChat gitChat = new GitChat(null, "chung", new Date(), "http://gitbook.cn/gitchat/activity/" + id);return gitChat; }
其中@GetMapping
表示此方法仅响应 GET 请求,其请求路径也附在括号内。而@PathVariable
则获取了路径中的一个参数,这个参数在路径中用大括号标注。
还要再编写实体类 GitChat 如下:
public class GitChat {private Integer id;private String author;private Date date;private String url;/*** 省略 NoArgsConstructor AllArgsConstructor***//*** 省略 Getter Setter***/}
此时重启项目,再访问 http://localhost:8080/demo/getGitChat/5a444c451f6ee91a25846ac1,就可以看到框架已经自动帮我们把对象转换为 JSON 显示在了浏览器,如下:
{ "id": null, "author": "chung", "date": 1514896266452, "url": "http://gitbook.cn/gitchat/activity/5a444c451f6ee91a25846ac1"}
在上面的例子中,我们用到了@PathVariable
注解,它可以帮助我们从路径中获取参数。而与其不同的@RequestParam
注解,它可以帮助我们从请求中获取参数,例如:
@GetMapping("/getGitChat")public GitChat getGitChatByRequestParam(@RequestParam(defaultValue = "5a444c451f6ee91a25846ac1") String id) { GitChat gitChat = new GitChat(null, "chung", new Date(), "http://gitbook.cn/gitchat/activity/" + id);return gitChat; }
此时重启项目,访问 http://localhost:8080/demo/getGitChat?id=5a444c451f6ee91a25846ac1 也将得到同样的结果。
注意 :如果缺少
?id=*
这段,访问时将会报错,为避免这样的问题,我们可以设置默认值@RequestParam(defaultValue = "5a444c451f6ee91a25846ac1")
。
单元测试
在上一章我们讨论了 Spring Boot 中 JUnit 的简单写法,其实,我们可以使用 IDEA 插入单元测试,这样更加便捷,省去了我们新建包、新建文件、新建类的时间,步骤如下:
-
在代码中选中
DemoController
右键→Go To→Test→Create New Test→勾选需要测试的方法→OK; -
这时 IDEA 已经在 test 目录下相应的包内为我们创建好了
DemoControllerTest
文件; -
我们使用 Spring 提供的
MockMvc
类来完成测试,用@AutoConfigureMockMvc
注解让框架自动配置,并使用@Resource
注入 MockMvc; -
编写接口测试代码并打印,测试代码及结果如下两段:
@RunWith(SpringRunner.class)@aaa@qq.com class DemoControllerTest {@Resourceprivate MockMvc mockMvc;@Testpublic void getGitChatByRequestParam() throws Exception { mockMvc.perform( MockMvcRequestBuilders .get("/getGitChat") .param("id", "5a444c451f6ee91a25846ac1") ) .andDo(print()) .andReturn(); } }
MockHttpServletResponse: Status = 200 Error message = null Headers = {Content-Type=[application/json;charset=UTF-8]} Content type = application/json;charset=UTF-8 Body = {"author":"chung","date":1514893447007,"url":"http://gitbook.cn/gitchat/activity/5a444c451f6ee91a25846ac1"} Forwarded URL = null Redirected URL = null Cookies = []
测试结果限于篇幅,我只贴出了一小部分,在真实测试日志中我们可以看到各种详细的数据,包括返回页面 Body 体的具体内容也打印了出来。这样的测试代码简单优雅而又霸气十足有木有?
下一篇: 上海=北京+武汉