本系列文章旨在使用最小依赖、最简单配置,帮助初学者快速掌握Spring Boot各组件使用,达到快速入门的目的。全部文章所使用示例代码均同步Github仓库和Gitee仓库。
Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。
讲的通俗一点就是Spring Boot并不是一个新的框架,它只是整合和默认实现了很多框架的配置方式。
最大的好处就是简单、快捷、方便,在Spring Boot之前,我们如果要搭建一个框架需要做什么?
笔者手边正好有一个很久之前的项目,当时还是使用的Spring3.x,可以给各位看一下当时一个项目的配置文件有多少:
而我如果需要新建一个项目,这里面大量的配置文件都要copy过去,并且重新调试,非常的不方便且浪费时间,当Spring Boot横空出世的时候,这些噩梦都结束了。
Spring Boot的优势:
目标设定:构建一个简单的RESTful API并实现对应的单元测试
Spring Boot提供两种工程构建方式:
关于创建springcloud项目,目前有两种比较方便的方案,核心都是一样的,大家自行选择自己使用方便的。
打开spring的官方链接:
https://start.spring.io/
在 Group 中填入自己的组织,一般填写公司的域名的到写,例如 com.jd 或者 com
.baidu ,这里我直接写 com.springboot
在 Artifact 中填写工程的名称,这里我直接写 spring-boot-quick-start 。
package 选择 jar ,java 选择11(目前最新的LTS版本),至此,基础选择已经全都选完,接下来要开始选择我们使用的 Spring Boot 的组件了。
在 Dependencies 中找到 Spring Web ,选择 Spring Web ,结果如下图:
最后点击下方的绿色长条按钮 Generate the project 进行下载,等待下载完成后,直接将压缩包解压导入我们的编辑工具idea里即可。
基于 idea 创建,打开 idea ,首先 file->new->project ,选中 Spring Initializr ,这时可以看到右侧让我们选择一个初始化的服务url,默认的就是上面的官方链接, https://start.spring.io/
点击 next 下一步,填写和上面一样的 Group 、 Artifact 、 java 版本、 package 方式等信息,继续 next 下一步,选择依赖,和前面的方法的一样,在 Dependencies 中找到 Spring Web ,选择 Spring Web ,点击 next ,选择项目名称和存储路径,点击 finish ,静静等一会,第一个项目 spring-boot-quick-start 就新鲜出炉了~~~
我一般选择第一种方式创建 Spring Boot 项目,这种方式不依赖IDE工具。
首先先看一下我们创建的工程结构,如下图:
这里我们重点关注 <dependencies>
标签,这里写明了我们引入的组件
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
spring-boot-starter-web spring-boot-starter-test
RESTful API 设计如下:
请求类型 | URL | 功能 |
---|---|---|
GET | / | 查询用户列表 |
POST | / | 创建User |
GET | /{id} | 根据 url 中的 id 获取 user 信息 |
PUT | /{id} | 根据 id 更新用户信息 |
DELETE | /{id} | 根据 id 删除用户信息 |
注意:RESTful接口在设计的时候应该遵循标准的方法以及语义,这些语义包含了安全性和幂等性等方面的考量,例如GET和HEAD请求都是安全的, 无论请求多少次,都不会改变服务器状态。而GET、HEAD、PUT和DELETE请求都是幂等的,无论对资源操作多少次, 结果总是一样的,后面的请求并不会产生比第一次更多的影响。
下面列出了GET,DELETE,PUT和POST的典型用法:
用户Model类如下:
public class UserModel { private Long id; private String name; private int age; // 省略 getter 和 setter }
REST API 实现类如下:
@RestController public class UserController { // 创建线程安全的Map,用作数据存储 static Map<Long, UserModel> users = new ConcurrentHashMap<>(); /** * 查询用户列表 * @return */ @GetMapping("/") public List<UserModel> getUserList() { List<UserModel> list = new ArrayList<UserModel>(users.values()); return list; } /** * 创建User * @param userModel * @return */ @PostMapping("/") public UserModel postUser(@ModelAttribute UserModel userModel) { users.put(userModel.getId(), userModel); return users.get(userModel.getId()); } /** * {id} 根据 url 中的 id 获取 user 信息 * url中的id可通过@PathVariable绑定到函数的参数中 * @param id * @return */ @GetMapping("/{id}") public UserModel getUser(@PathVariable Long id) { return users.get(id); } /** * 根据 id 更新用户信息 * @param id * @param userModel * @return */ @PutMapping("/{id}") public UserModel putUser(@PathVariable Long id, @ModelAttribute UserModel userModel) { UserModel u = users.get(id); u.setName(userModel.getName()); u.setAge(userModel.getAge()); users.put(id, u); return users.get(userModel.getId()); } /** * 根据 id 删除用户信息 * @param id * @return */ @DeleteMapping("/{id}") public String deleteUser(@PathVariable Long id) { users.remove(id); return "success"; } }
可以看一下 @RestController
,可以看到 @RestController
本身就是由 @ResponseBody
和 @Controller
组成的,源码如下:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Controller @ResponseBody public @interface RestController { /** * The value may indicate a suggestion for a logical component name, * to be turned into a Spring bean in case of an autodetected component. * @return the suggested component name, if any (or empty String otherwise) * @since 4.0.1 */ @AliasFor(annotation = Controller.class) String value() default ""; }
单元测试类如下:
@RunWith(SpringRunner.class) @SpringBootTest public class SpringBootQuickStartApplicationTests { private MockMvc mvc; @Before public void setUp() throws Exception { mvc = MockMvcBuilders.standaloneSetup(new UserController()).build(); } @Test public void contextLoads() throws Exception { RequestBuilder request = null; // 1、get查一下user列表,应该为空 request = MockMvcRequestBuilders.get("/") .contentType(MediaType.APPLICATION_JSON); mvc.perform(request) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcResultHandlers.print()) .andReturn(); // 2、post提交一个user request = MockMvcRequestBuilders.post("/") .param("id", "1") .param("name", "Spring Boot") .param("age", "18") .contentType(MediaType.APPLICATION_JSON); mvc.perform(request) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcResultHandlers.print()) .andReturn(); // 3、get获取user列表,应该有刚才插入的数据 request = MockMvcRequestBuilders.get("/") .contentType(MediaType.APPLICATION_JSON); mvc.perform(request) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcResultHandlers.print()) .andReturn(); // 4、put修改id为1的user request = MockMvcRequestBuilders.put("/1") .param("name", "Spring Boot Test") .contentType(MediaType.APPLICATION_JSON); mvc.perform(request) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcResultHandlers.print()) .andReturn(); // 5、get一个id为1的user request = MockMvcRequestBuilders.get("/1") .contentType(MediaType.APPLICATION_JSON); mvc.perform(request) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcResultHandlers.print()) .andReturn(); // 6、del删除id为1的user request = MockMvcRequestBuilders.delete("/1") .contentType(MediaType.APPLICATION_JSON); mvc.perform(request) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcResultHandlers.print()) .andReturn(); // 7、get查一下user列表,应该为空 request = MockMvcRequestBuilders.get("/") .contentType(MediaType.APPLICATION_JSON); mvc.perform(request) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcResultHandlers.print()) .andReturn(); } }
启动测试类,控制台打印如下,这里仅截取一段内容做展示:
MockHttpServletRequest: HTTP Method = POST Request URI = / Parameters = {id=[1], name=[Spring Boot], age=[18]} Headers = [Content-Type:"application/json"] Body = <no character encoding set> Session Attrs = {} Handler: Type = com.springboot.springbootquickstart.controller.UserController Method = public com.springboot.springbootquickstart.model.UserModel com.springboot.springbootquickstart.controller.UserController.postUser(com.springboot.springbootquickstart.model.UserModel) Async: Async started = false Async result = null Resolved Exception: Type = null ModelAndView: View name = null View = null Model = null FlashMap: Attributes = null MockHttpServletResponse: Status = 200 Error message = null Headers = [Content-Type:"application/json;charset=UTF-8"] Content type = application/json;charset=UTF-8 Body = {"id":1,"name":"Spring Boot","age":18} Forwarded URL = null Redirected URL = null Cookies = []
从控制台打印中可以完整的看到整个模拟请求的过程以及参数。