第21章 Spring Boot新手指南:一文学会RESTful API开发

任务描述

任务要求

使用IDEA开发工具构建一个项目多模块工程。study-springboot-chapter17学习关于Springboot开发前端控制层,方便实现前后端分离

  1. 基于study-springboot工程,复制study-springboot-chapter17标准项目,坐标groupId(com.cbitedu)、artifactId(study-springboot-chapter17),其他默认
  2. 继承study-springboot工程依赖
  3. 构建Restful API

任务收获

  1. Spring Boot开发Restful API服务
  2. 学会使用JUnit完成单元测试
  3. 掌握web开发原理
  4. 熟悉SpringMVC的基础配置

任务准备

环境要求

  1. JDK1.8+
  2. MySQL8.0.27+
  3. Maven 3.6.1+
  4. IDEA/VSCode

数据库准备

sql 复制代码
-- ----------------------------
-- Table structure for tb_user
-- ----------------------------
DROP TABLE IF EXISTS `tb_user`;
CREATE TABLE `tb_user`  (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `username` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户名',
  `password` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '密码,加密存储',
  `phone` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '注册手机号',
  `created` datetime NOT NULL COMMENT '创建时间',
  `salt` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '密码加密的salt值',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE INDEX `username`(`username` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户表' ROW_FORMAT = DYNAMIC;

-- ----------------------------
-- Records of tb_user
-- ----------------------------
INSERT INTO `tb_user` VALUES (1, 'tosea', '44f871f0a390c5ca0731ebb0f5a17e73', '13037889034', '2019-04-11 11:36:45', '802ae2cb978b4cc2b5705e9e525f3c7d');
INSERT INTO `tb_user` VALUES (2, 'tellsea', 'a11a53405c18b7bd9793396a5ada044c', '18386474459', '2019-04-17 23:02:43', 'aabaf92f1d10459d84d2b0f076fb3fdd');

工程目录要求

study-springboot-chapter17

任务实施

前端控制层常用的@Controller、@RestController、@RequestMapping注解。

  1. @Controller:修饰class,用来创建处理http请求的对象
  2. @RestController:Spring4之后加入的注解,原来在@Controller中返回json需要@ResponseBody来配合,如果直接用@RestController替代@Controller就不需要再配置@ResponseBody,默认返回json格式
  3. @RequestMapping:配置url映射。现在更多的也会直接用以Http Method直接关联的映射注解来定义,比如:GetMapping、PostMapping、DeleteMapping、PutMapping等

下面我们通过使用Spring MVC来实现一组对User对象操作的RESTful API,配合注释详细说明在Spring MVC中如何映射HTTP请求、如何传参、如何编写单元测试。

RESTful API具体设计如下:

Method 介绍 幂等
GET 数据的查询操作 Yes
HEAD GET相同, 区别是响应中不包含响应体. 可以用来获取资源的元数据, 如 header 等 Yes
POST 信息的创建:创建成功应该返回响应码 201 No
PATCH 用于局部更新 从 POST 请求分出来的, POST 全量更新, PATCH 局部更新. No
PUT 信息的更新 Yes
DELETE 数据删除 Yes
OPTIONS API 相关信息 如探测服务支持的所有Method, 或者检测服务通不通. Yes
CONNECTED 与服务器建立链接, 通过服务器代理客户端请求 说白了就是一个 HTTP 代理 Yes
TRACE 对请求路径的环回测试 Yes

幂等, 上面表格中幂等的意思就是, 接口调2次和调1次结果一样, 既可以重复调用.

GET(SELECT):从服务器取出资源(一项或多项)。

POST(CREATE):在服务器新建一个资源。

PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。

PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。

DELETE(DELETE):从服务器删除资源。

例如:

响应码 介绍
1xx 请求已收到, 需要继续操作
2xx 请求成功处理
3xx 重定向, 需要进一步请求
4xx 客户端错误
5xx 服务器错误

定义User实体

kotlin 复制代码
package com.cbitedu.springboot.entity;

import lombok.Data;

@Data
public class User {

    private Long id;
    private String username;
    private String password;
    private Integer age;

}

定义状态响应辅助类

kotlin 复制代码
package com.cbitedu.springboot.utils;


import lombok.Builder;
import lombok.Data;

@Data
@Builder  // 作用:调用时使用链式写法
public class ResultResponse {
    private String code;
    private String message;
    private Object data;
}

@Data注解可以实现在编译器自动添加set和get函数的效果。该注解是lombok提供的,只需要在pom中引入加入下面的依赖就可以支持:

xml 复制代码
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

实现对User对象的操作接口

typescript 复制代码
package com.cbitedu.springboot.controller;

import com.cbitedu.springboot.entity.User;
import com.cbitedu.springboot.utils.ResultResponse;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@Slf4j
@RequestMapping(value = "demo")  // 类中所有接口地址的前缀
public class UserController {
    // @RequestMapping(value="loginGet", method= RequestMethod.GET)
    @GetMapping("loginGet")
    public String loginGet() {
        return "登录成功";
    }

    // @RequestMapping(value="loginPost", method= RequestMethod.POST)
    @PostMapping("loginPost")  // 简便写法
    public String loginPost(@RequestBody User user) {  // 如果没用 @RequestBody,则获取结果为 null
        log.info("username : " + user.getUsername());
        log.info("password : " + user.getPassword());
        return "登录成功:" + user.getUsername();
    }

    // 访问:http://localhost:8080/demo/userId/1/2
    // @RequestMapping(value="userId/{userId}/{id}", method=RequestMethod.GET)
    @GetMapping("getUser/{userid}/{id}")
    public String loginUser1(@PathVariable("userid") Integer userid, @PathVariable("id") Integer id) {
        log.info("userid : " + userid);
        log.info("id : " + id);
        return "userid: " + userid + "  id: " + id;
    }

    // 访问:http://localhost:8080/demo/getUser?userid=1&id=2
    // 访问:http://localhost:8080/demo/getUser?user=1&id=2,则 userid 值为 null
    @GetMapping("getUser")
    public String loginUser2(@RequestParam(value = "userid", required = false) Integer userid,  // required=false:参数非必须传
                             @RequestParam("id") Integer id) {
        log.info("userid : " + userid);
        log.info("id : " + id);
        return "userid: " + userid + "  id: " + id;
    }

    @GetMapping("loginSuccess")
    public ResponseEntity loginSuccess() {
        User user = new User();
        user.setUsername("creatorblue");
        user.setPassword("admin123");
        ResultResponse resultResponse = ResultResponse.builder().code("00").message("登录成功").data(user).build();
        return ResponseEntity.status(HttpStatus.OK).body(resultResponse);
    }

    @GetMapping("loginFail")
    public ResponseEntity loginFail() {
        User user = new User();
        user.setUsername("creatorblue");
        user.setPassword("admin123");
        ResultResponse resultResponse = ResultResponse.builder().code("02").message("登录失败").data(user).build();
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(resultResponse);
    }
}

用更细化的@GetMapping、@PostMapping等系列注解替换了以前的@RequestMaping注解;另外,还使用@RequestBody替换了@ModelAttribute的参数绑定。

测试

http://localhost:8080/demo/loginSuccess

小结

至此,我们通过引入web模块(没有做其他的任何配置),就可以轻松利用Spring MVC的功能,以非常简洁的代码完成了对User对象的RESTful API的创建以及单元测试的编写。其中同时介绍了Spring MVC中最为常用的几个核心注解:@RestController,RequestMapping以及一些参数绑定的注解:@PathVariable,@RequestBody等。

后端接收前端数据的三种注解方式:

第一种:@RequestParam注解

  • 作用: 将指定的请求参数赋值给方法中的形参。
  • 接收形式: Get传参请求。
  • 属性:
    (1)value :绑定请求的参数名,默认绑定为同名的形参;
    (2)required:是否必须,默认是true,表示请求中一定要有相应的参数,否则将报错;
    (3)defaultValue:默认值,表示如果请求中没有接收到值时的默认值。
  • 用法示例:
less 复制代码
@GetMapping("/test")
public void test(@RequestParam(required = true)String name,@RequestParam(defaultValue = "20")Integer age) {
System.out.println("name:"+name+",age:"+age);
}

第二种:@PathVariable注解

  • 作用: 接收请求路径中占位符的值。
  • 接收形式: Get路径请求。
  • 属性: value:String类型,绑定请求的参数名,默认绑定为同名的形参。
  • 用法示例:
less 复制代码
@GetMapping("/selectOne/{id}")
public void test(@PathVariable Integer id) {
System.out.println("id:"+id);
}

第三种:@RequestBody注解

  • 作用: 接收前端传递的Json对象的字符串。
  • 接收形式: Post请求。
  • 用法示例:
less 复制代码
@PostMapping("/test")
public void test(@RequestBody User user){
System.out.println("user:"+user);
}

实验实训

1、重点学习Spring MVC前端注解

2、重点复习RestFul接口命名规范

附录

SpringBoot 核心注解

注解 说明
Component 声明为 SpringBoot 的 bean
Repository 用于 dao 层的 bean
Autowired 用于向一个 bean 中注入其他 bean
Service 用于 service 层的 bean
Configuration 用于声明 SpringBoot 的配置文件类
Value("${key)") 获取 SpringBoot 配置文件中的值
Bean 声明其为 bean 实例,常和 Configuration 配合使用

SpringBoot Restful 接口实现

注解 说明
SpringBootApplication SpringBoot 主类,用来加载 SpringBoot 各种特性
RestController SpringBoot 会转换返回值并自动将其写入 HTTP 响应
RequestMapping 用于类和方法,在方法级别时,用于处理 HTTP 的各种方法
RequestBody 将请求 Body 中的 json/xml 对象解析成该参数类型的 JavaBean 对象
PathVariable 处理动态 URI,即 URI 的值可以作为控制器中处理方法的入参
Post/Put/Get/DeleteMapping 在方法的级别上使用,在方法级别时,用于处理 HTTP 的各种方法
RequestParam 处理 get 请求的参数
相关推荐
苹果醋332 分钟前
2020重新出发,MySql基础,MySql表数据操作
java·运维·spring boot·mysql·nginx
小蜗牛慢慢爬行33 分钟前
如何在 Spring Boot 微服务中设置和管理多个数据库
java·数据库·spring boot·后端·微服务·架构·hibernate
azhou的代码园36 分钟前
基于JAVA+SpringBoot+Vue的制造装备物联及生产管理ERP系统
java·spring boot·制造
wm10431 小时前
java web springboot
java·spring boot·后端
小扳3 小时前
微服务篇-深入了解 MinIO 文件服务器(你还在使用阿里云 0SS 对象存储图片服务?教你使用 MinIO 文件服务器:实现从部署到具体使用)
java·服务器·分布式·微服务·云原生·架构
龙少95433 小时前
【深入理解@EnableCaching】
java·后端·spring
溟洵5 小时前
Linux下学【MySQL】表中插入和查询的进阶操作(配实操图和SQL语句通俗易懂)
linux·运维·数据库·后端·sql·mysql
SomeB1oody7 小时前
【Rust自学】6.1. 定义枚举
开发语言·后端·rust
SomeB1oody7 小时前
【Rust自学】5.3. struct的方法(Method)
开发语言·后端·rust
路在脚下@9 小时前
spring boot的配置文件属性注入到类的静态属性
java·spring boot·sql