6.2 构建 RESTful 应用接口

本文介绍了如何使用 Spring Boot 构建 RESTful 应用接口,包括 Spring Boot 对 RESTful 的支持,如 @GetMapping、@PostMapping 等注解,以及如何设计和实现用户管理接口,并进行验证测试。示例中展示了用户管理模块的接口定义和状态码说明。
摘要由CSDN通过智能技术生成

第6章 构建 RESTful 服务

6.1 RESTful 简介
6.2 构建 RESTful 应用接口
6.3 使用 Swagger 生成 Web API 文档
6.4 实战:实现 Web API 版本控制

6.2 构建 RESTful 应用接口

6.2.1 Spring Boot 对 RESTful 的支持

Spring Boot 提供的spring-boot-starter-web组件完全支持开发 RESTful API,提供了与 REST 操作方式(GET、POST、PUT、DELETE)对应的注解:

  1. @GetMapping:处理 GET 请求,获取资源。
  2. @PostMapping:处理 POST 请求,新增资源。
  3. @PutMapping:处理 PUT 请求,更新资源。
  4. @DeleteMapping:处理 DELETE 请求,删除资源。
  5. @PatchMapping:处理 PATCH 请求,用于部分更新资源。

通过这些注解就可以在 Spring Boot 项目中轻松构建 RESTful 接口。其中比较常用的是 @GetMapping、@PostMapping、@PutMapping、@DeleteMapping 四个注解。

使用 Spring Boot 开发 RESTful 接口非常简单,通过 @RestController 定义控制器,然后使用 @GetMapping 和 @PostMapping 等注解定义地址映射,实现相应的资源操作方法即可。

示例:

RESTfulController.java

package com.example.restfulproject.controller;

import com.example.restfulproject.model.User;
import org.springframework.web.bind.annotation.*;

/**
 * RESTful 接口简单案例(增删改查)
 */
@RestController
public class RESTfulController {

    @GetMapping(value = "/user/{id}")
    public String getUserById(@PathVariable String id) {
        return "getUserById:" + id;
    }

    @PostMapping(value = "/user")
    public String save(@RequestBody User user) {
        String name = user.getName();
        return "save successed";
    }

    @PutMapping(value = "/user")
    public String update(@RequestBody User user) {
        return "update successed";
    }

    @DeleteMapping(value = "/user/{id}")
    public String delete(@PathVariable String id) {
        return "delete id:" + id;
    }


/*
    // 上面的注解是 @RequestMapping 注解的简化:

    @RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
    public String getUserById(@PathVariable String id) {
        return "getUserById:" + id;
    }

    @RequestMapping(value = "/user", method = RequestMethod.POST)
    public String save(User user) {
        return "save successed";
    }

    @RequestMapping(value = "/user", method = RequestMethod.PUT)
    public String update(User user) {
        return "update successed";
    }

    @RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)
    public String delete(@PathVariable String id) {
        return "delete id:" + id;
    }
*/
}

6.2.2 Spring Boot 实现 RESTful API

1. 设计API

在 RESTful 架构中,每个网址代表一种资源,所以 URI 中建议不要包含动词,只包含名词即可,而且所用的名词往往与数据库的表名对应。

(1)接口定义

下表是用户管理模块的接口定义,实际项目的 RESTful API 文档要更详细,还会定义全部请求的数据结构体。

用户管理模块API说明

HTTP Method接口地址接口说明
POST/user创建用户
GET/user/id根据id获取用户信息
PUT/user更新用户
DELETE/user/id根据id删除对应的用户

上表中定义了用户管理模块的接口,根据 REST 的定义,我们将用户定义为一种资源,通过 POST、DELETE、PUT、GET 等 HTTP Method 实现对用户的增、删、改、查。

(2)状态码和提示信息定义

除了设计 URL 接口之外,还需要定义服务端向客户端返回的状态码和提示信息。详细状态码说明见下表。

用户管理模块状态码说明:

状态码状态说明
200Ok,请求成功
201Created,新增成功
203Updated,修改成功
204Deleted,删除成功

除了定义用户管理相关的业务状态码之外,还需要定义通用的错误码,如 400 对应数据校验错误、401 对应数据无权限等。

用户管理模块错误码说明:

错误码错误说明
400数据验证错误
401无权限
404资源不存在
500服务端错误
2. 实现用户管理接口

UserManagementController.java

package com.example.restfulproject.controller;

import com.example.restfulproject.comm.utils.JSONResult;
import com.example.restfulproject.model.User;
import org.springframework.web.bind.annotation.*;

/**
 * Spring Boot 实现 RESTful API
 */
@RestController
@RequestMapping("/userManagement")
public class UserManagementController {
    /**
     * 用户新增
     */
    @PostMapping(value = "/user")
    public JSONResult save(@RequestBody User user) {
        System.out.println("用户创建成功:" + user.getName());
        return JSONResult.ok(201, "用户创建成功");
    }

    /**
     * 用户修改
     */
    @PutMapping(value = "/user")
    public JSONResult update(@RequestBody User user) {
        System.out.println("用户修改成功:" + user.getName());
        return JSONResult.ok(203, "用户修改成功");
    }

    /**
     * 用户删除
     */
    @DeleteMapping(value = "/user/{userId}")
    public JSONResult delete(@PathVariable String userId) {
        System.out.println("用户删除成功:" + userId);
        return JSONResult.ok(204, "用户删除成功");
    }

    /**
     * 获取用户
     */
    @GetMapping(value = "/user/{userId}")
    public JSONResult queryUserById(@PathVariable String userId) {
        User user = new User();
        user.setId(userId);
        user.setName("zhangsan");
        user.setAge(20);
        System.out.println("获取用户成功:" + userId);
        return JSONResult.ok(200, "获取用户成功", user);
    }
    
}

JSONResult.java

package com.example.restfulproject.comm.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.List;

/**
 * 定义数据处理类
 *
 * @Title:: JSONResult.java
 * @Package com.example.webproject.comm.utils
 * @Description: 自定义响应数据结构
 *          200: 表示成功
 *          500: 表示错误,错误信息在 msg 字段中
 *          501: bean 验证错误,无论多少个错误都以 map 形式返回
 *          502: 拦截器拦截到用户 token 出错
 *          555: 异常抛出信息
 * Copyright: Copyright (c) 2023
 *
 * @create: 2023-02-05 17:35:54
 * @Modify: 2023-02-17 19:41:30
 * @version V1.1
 */
public class JSONResult {
    // 定义 jackson 对象 (关于jackson的使用详解请参考:https://juejin.cn/post/6844904166809157639)
    private static final ObjectMapper MAPPER = new ObjectMapper();
    // 响应业务状态
    private Integer code;
    // 响应消息
    private String msg;
    // 响应中的数据
    private Object data;

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public JSONResult() {
    }

    public JSONResult(Integer code, String msg, Object data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public JSONResult(Object data) {
        this.code = 200;
        this.msg = "OK";
        this.data = data;
    }

//    // 是否成功
//    public Boolean isSuccess() {
//        return this.code == 200;
//    }

    // 构建返回的数据
    public static JSONResult build(Integer status, String msg, Object data) {
        return new JSONResult(status, msg, data);
    }

    // 200:成功,有返回值
    public static JSONResult ok(Object data) {
        return new JSONResult(data);
    }

    // 200:成功,没有返回值
    public static JSONResult ok() {
        return new JSONResult(null);
    }

    //200:成功,没有返回值
    public static JSONResult ok(Integer code, String msg) {
        return new JSONResult(code, msg, null);
    }

    // 200: 成功
    public static JSONResult ok(Integer code, String msg, Object data) {
        return new JSONResult(code, msg, data);
    }

    //500:错误,错误信息在 msg 字段中
    public static JSONResult errorMsg(String msg) {
        return new JSONResult(500, msg, null);
    }

    //501:bean 验证错误,无论多少个错误都以 map 形式返回
    public static JSONResult errorMap(Object data) {
        return new JSONResult(501, "error", data);
    }

    //502:拦截器拦截到用户 token 出错
    public static JSONResult errorTokenMsg(String msg) {
        return new JSONResult(502, msg, null);
    }

    //555:异常抛出信息
    public static JSONResult errorException(String msg) {
        return new JSONResult(555, msg, null);
    }

    /**
     * @Description: 将 json 结果集转化为 JSONResult 对象,需要转换的对象是一个类
     *
     * @param jsonData
     * @param clazz
     * @return
     */
    public static JSONResult formatToPojo(String jsonData, Class<?> clazz) {
        try {
            if (clazz == null) {
                return MAPPER.readValue(jsonData, JSONResult.class);
            }

            JsonNode jsonNode = MAPPER.readTree(jsonData);
            JsonNode data = jsonNode.get("data");
            Object obj = null;
            if (clazz != null) {
                if (data.isObject()) {
                    obj = MAPPER.readValue(data.traverse(), clazz);
                } else if (data.isTextual()) {
                    obj = MAPPER.readValue(data.asText(), clazz);
                }
            }
            return build(jsonNode.get("code").intValue(), jsonNode.get("msg").asText(), obj);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * @Description: 没有 object 对象的转化
     *
     * @param json
     * @return
     */
    public static JSONResult format(String json) {
        try {
            return MAPPER.readValue(json, JSONResult.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @Description: Object 是集合转化,需要转换的对象是一个list
     *
     * @param jsonData
     * @param clazz
     * @return
     */
    public static JSONResult formatToList(String jsonData, Class<?> clazz) {
        try {
            JsonNode jsonNode = MAPPER.readTree(jsonData);
            JsonNode data = jsonNode.get("data");
            Object obj = null;
            if(data.isArray() && data.size() > 0) {
                obj = MAPPER.readValue(data.traverse(), MAPPER.getTypeFactory().constructCollectionType(List.class,clazz));
            }
            return build(jsonNode.get("code").intValue(), jsonNode.get("msg").asText(), obj);
        } catch (Exception e) {
            return null;
        }
    }

}

3. 验证测试

(1)获取用户:http://localhost:8080/userManagement/user/2001
获取用户.png

(2)用户新增:http://localhost:8080/userManagement/user
用户新增.png

(3)用户修改:http://localhost:8080/userManagement/user
用户修改.png

(4)用户删除:http://localhost:8080/userManagement/user/2001
用户删除.png

来源:《Spring Boot 从入门到实战》学习笔记

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值