首先, 回顾并详细说明一下在快速入门中使用的 @Controller,@RestController,@RequestMapping 注解. 如果您对 Spring MVC 不熟悉并且还没有尝试过快速入门案例, 建议先看一下快速入门的内容.
@Controller: 修饰 class, 用来创建处理 http 请求的对象
@RestController:Spring4 之后加入的注解, 原来在 @Controller 中返回 JSON 需要 @ResponseBody 来配合, 如果直接用 @RestController 替代 @Controller 就不需要再配置 @ResponseBody, 默认返回 JSON 格式
@RequestMapping: 配置 url 映射. 现在更多的也会直接用以 Http Method 直接关联的映射注解来定义, 比如: GetMapping,PostMapping,DeleteMapping,PutMapping 等
下面我们通过使用 Spring MVC 来实现一组对 User 对象操作的 RESTful API, 配合注释详细说明在 Spring MVC 中如何映射 HTTP 请求, 如何传参, 如何编写单元测试.
** RESTful API 具体设计如下:**
定义 User 实体
- @Data
- public class User {
- private Long id;
- private String name;
- private Integer age;
- }
注意: 相比 1.x 版本教程 http://blog.didispace.com/springbootrestfulapi/ 中自定义 set 和 get 函数的方式, 这里使用 @Data 注解可以实现在编译器自动添加 set 和 get 函数的效果. 该注解是 lombok 提供的, 只需要在 pom 中引入加入下面的依赖就可以支持:
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- </dependency>
实现对 User 对象的操作接口
- @RestController
- @RequestMapping(value = "/users") // 通过这里配置使下面的映射都在 / users 下
- public class UserController {
- // 创建线程安全的 Map, 模拟 users 信息的存储
- static Map<Long, User> users = Collections.synchronizedMap(new HashMap<Long, User>());
- /**
- * 处理 "/users/" 的 GET 请求, 用来获取用户列表
- *
- * @return
- */
- @GetMapping("/")
- public List<User> getUserList() {
- // 还可以通过 @RequestParam 从页面中传递参数来进行查询条件或者翻页信息的传递
- List<User> r = new ArrayList<User>(users.values());
- return r;
- }
- /**
- * 处理 "/users/" 的 POST 请求, 用来创建 User
- *
- * @param user
- * @return
- */
- @PostMapping("/")
- public String postUser(@RequestBody User user) {
- // @RequestBody 注解用来绑定通过 http 请求中 application/JSON 类型上传的数据
- users.put(user.getId(), user);
- return "success";
- }
- /**
- * 处理 "/users/{id}" 的 GET 请求, 用来获取 url 中 id 值的 User 信息
- *
- * @param id
- * @return
- */
- @GetMapping("/{id}")
- public User getUser(@PathVariable Long id) {
- // url 中的 id 可通过 @PathVariable 绑定到函数的参数中
- return users.get(id);
- }
- /**
- * 处理 "/users/{id}" 的 PUT 请求, 用来更新 User 信息
- *
- * @param id
- * @param user
- * @return
- */
- @PutMapping("/{id}")
- public String putUser(@PathVariable Long id, @RequestBody User user) {
- User u = users.get(id);
- u.setName(user.getName());
- u.setAge(user.getAge());
- users.put(id, u);
- return "success";
- }
- /**
- * 处理 "/users/{id}" 的 DELETE 请求, 用来删除 User
- *
- * @param id
- * @return
- */
- @DeleteMapping("/{id}")
- public String deleteUser(@PathVariable Long id) {
- users.remove(id);
- return "success";
- }
- }
这里相较 1.x 版本教程 http://blog.didispace.com/springbootrestfulapi/ 中, 用更细化的 @GetMapping,@PostMapping 等系列注解替换了以前的 @RequestMaping 注解; 另外, 还使用 @RequestBody 替换了 @ModelAttribute 的参数绑定.
编写单元测试
下面针对该 Controller 编写测试用例验证正确性, 具体如下. 当然也可以通过浏览器插件等进行请求提交验证.
- @RunWith(SpringRunner.class)
- @SpringBootTest
- public class Chapter21ApplicationTests {
- private MockMvc mvc;
- @Before
- public void setUp() {
- mvc = MockMvcBuilders.standaloneSetup(new UserController()).build();
- }
- @Test
- public void testUserController() throws Exception {
- // 测试 UserController
- RequestBuilder request;
- // 1,get 查一下 user 列表, 应该为空
- request = get("/users/");
- mvc.perform(request)
- .andExpect(status().isOk())
- .andExpect(content().string(equalTo("[]")));
- // 2,post 提交一个 user
- request = post("/users/")
- .contentType(MediaType.APPLICATION_JSON)
- .content("{\"id\":1,\"name\":\" 测试大师 \",\"age\":20}");
- mvc.perform(request)
- .andExpect(content().string(equalTo("success")));
- // 3,get 获取 user 列表, 应该有刚才插入的数据
- request = get("/users/");
- mvc.perform(request)
- .andExpect(status().isOk())
- .andExpect(content().string(equalTo("[{\"id\":1,\"name\":\" 测试大师 \",\"age\":20}]")));
- // 4,put 修改 id 为 1 的 user
- request = put("/users/1")
- .contentType(MediaType.APPLICATION_JSON)
- .content("{\"name\":\" 测试终极大师 \",\"age\":30}");
- mvc.perform(request)
- .andExpect(content().string(equalTo("success")));
- // 5,get 一个 id 为 1 的 user
- request = get("/users/1");
- mvc.perform(request)
- .andExpect(content().string(equalTo("{\"id\":1,\"name\":\" 测试终极大师 \",\"age\":30}")));
- // 6,del 删除 id 为 1 的 user
- request = delete("/users/1");
- mvc.perform(request)
- .andExpect(content().string(equalTo("success")));
- // 7,get 查一下 user 列表, 应该为空
- request = get("/users/");
- mvc.perform(request)
- .andExpect(status().isOk())
- .andExpect(content().string(equalTo("[]")));
- }
- }
对 MockMvc 不熟悉的读者, 可能会碰到一些函数不存在而报错. 必须引入下面这些静态函数的引用:
- import static org.hamcrest.Matchers.equalTo;
- import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
- import static org.springframework.test.Web.servlet.result.MockMvcResultMatchers.content;
- import static org.springframework.test.Web.servlet.result.MockMvcResultMatchers.status;
这里相较 1.x 版本教程 http://blog.didispace.com/springbootrestfulapi/ 中, 主要有两个地方不同. 测试类采用 @RunWith(SpringRunner.class) 和 @SpringBootTest 修饰启动; 另外, 由于 POST 和 PUT 接口的参数采用 @RequestBody 注解, 所以提交的会是一个 JSON 字符串, 而不是之前的参数形式, 这里在定义请求的时候使用 contentType(MediaType.APPLICATION_JSON) 指定提交内容为 JSON 格式, 使用 content 传入要提交的 JSON 字符串. 如果用 @ModelAttribute 的话就得用 param 方法添加参数, 具体可以看 1.x 版本的教程 http://blog.didispace.com/springbootrestfulapi/ .
至此, 我们通过引入 Web 模块 (没有做其他的任何配置), 就可以轻松利用 Spring MVC 的功能, 以非常简洁的代码完成了对 User 对象的 RESTful API 的创建以及单元测试的编写. 其中同时介绍了 Spring MVC 中最为常用的几个核心注解:@RestController,RequestMapping 以及一些参数绑定的注解:@PathVariable,@RequestBody 等.
代码示例
本文的相关例子可以查看下面仓库中的 chapter2-1 目录:
GitHub:
Gitee:
如果您觉得本文不错, 欢迎 Star 支持, 您的关注是我坚持的动力!
来源: https://www.cnblogs.com/didispace/p/11606136.html