基于 Spring Boot 的 RESTful API 设计与实现

news2024/10/9 18:19:19

RESTful 是一种规范,符合 RESTful 的 Api 就是 RESTful Api。简单的说就是可联网设备利用 HTTP 协议通过 GET、POST、DELETE、PUT、PATCH 来操作具有 URI 标识的服务器资源,返回统一格式的资源信息,包括 JSON、XML、CSV、ProtoBuf、其他格式。
RESTful 的核心思想是,客户端发出的数据操作指令都是"动词 + 宾语"的结构。比如,GET /case 这个命令,GET 是动词,/case 是宾语。

RESTful API简介

  • RESTful 架构遵循统一接口原则,不论什么样的资源,都是通过使用相同的接口进行资源的访问。接口应该使用标准的 HTTP 方法如 GET ,PUT 和 POST ,并遵循这些方法的语义。

设计规范

常用的动词有以下 5 个


详情见 https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html 1

Spring Boot 实现 RESTful API

我们可以通过 Spring Boot 注解来实现 RESTful API 。

现在需要编写的是对一个用户的增删改查操作,如下表是一个非 RESTful 和 标准 RESTful 的对比表。

下面我们着重介绍下以下两对注解。

Controller 一般应用在有返回界面的应用场景下。例如,管理后台使用了模板技术如 thymeleaf 开发,需要从后台直接返回 Model 对象到前台,那么这时候就需要使用 Controller 来注解。

RestController 一般应用在只有接口的应用场景下. 例如开发前后端分离的项目时,通过 Ajax 请求服务端接口,那么接口就使用 RestController 统一注解。

需要注意的是 RestController 是 Controller 的子集。RestController 是 Spring4 后新加的注解,从 RestController 注解源码可以看出 RestController 是 Controller 和 ResponseBody 两个注解的结合体,即Controller=RestController+ResponseBody。

RestController 注解源码

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
    @AliasFor(
        annotation = Controller.class
    )
    String value() default "";
}

RequestMapping 和GetMapping/PostMapping/PutMapping/DeleteMapping 作用一样,其实可以相互替换,后者是前者的简化版本。

GetMapping 其实就等于将 RequestMapping 注解的 method 属性设置为 GET,PostMapping 其实就等于将 RequestMapping 注解的 method 属性设置为 POST,PutMapping、DeleteMapping 其实就等于将 RequestMapping 注解的 method 属性分别设置为 PUT、DELETE。

也就是说GetMapping、PostMapping、PutMapping、DeleteMapping 是 RequestMapping 的子集。

我们来看看 RequestMapping 的源码:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
    String name() default "";

    //请求URI
    @AliasFor("path")
    String[] value() default {};
    @AliasFor("value")
    String[] path() default {};
    //请求类型,如 GET、POST、PUT、DELETE 等
    RequestMethod[] method() default {};
    //请求参数中必须包含某些参数值,才让该方法处理。
    String[] params() default {};
    //请求参数中必须包含某些指定的header值,才能让该方法处理请求。
    String[] headers() default {};
    //请求的内容类型(Content-Type),例如application/json, text/html;
    String[] consumes() default {};
    //响应的内容类型,仅当 request 请求头中的( Accept )类型中包含该指定类型才返回;
    String[] produces() default {};
}

示例说明:
 

  • 新增 2 个文件:dto/UserDto.java 和 controller/HogwartsTestUserController.java ,其中 UserController 类中包括了对用户的 4 个操作增删改查。
public class UserDto {

    private String name;
    private String pwd;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }
}

/**
 * RESTful API 风格示例 对资源 user 进行操作
 * 本示例没有使用数据库,也没有使用 service 类来辅助完成,所有操作在本类中完成
 * */
@Api(tags = "霍格沃兹测试学院-用户管理模块", hidden = true)
@RestController
@RequestMapping("/api/user")
public class HogwartsTestUserController {

    /**
     * 查询用户列表,返回一个JSON数组
     * */
    @ApiOperation("查询用户列表")
    @GetMapping("/users")
    @ResponseStatus(HttpStatus.OK)
    public Object getUsers(){
        List<UserDto> list = getData();
        return list;
    }

    /**
     * 查询用户信息,返回一个新建的JSON对象
     * */
    @ApiOperation("查询用户信息")
    @GetMapping("/users/{id}")
    @ResponseStatus(HttpStatus.OK)
    public Object getUser(@PathVariable("id") Long id){

        if(Objects.isNull(id)){
            return null;
        }

        List<UserDto> list= getData();
        UserDto userDto = getUserDto(id, list);

        return userDto;
    }

    /**
     * 新增用户
     * */
    @ApiOperation("新增用户")
    @PostMapping("/users")
    @ResponseStatus(HttpStatus.CREATED)
    public Object addUser(@RequestBody UserDto user){

        List<UserDto> list= getData();
        list.add(user);//模拟向列表中增加数据
        return user;
    }

    /**
     * 编辑用户
     * */
    @ApiOperation("编辑用户")
    @PutMapping("/users/{id}")
    @ResponseStatus(HttpStatus.CREATED)
    public Object editUser(@PathVariable("id") Long id,@RequestBody UserDto user){
        List<UserDto> list = getData();
        for (UserDto userDto:list) {
            if(id.equals(userDto.getId())){
                userDto = user;
                break;
            }
        }

        return user;
    }

    /**
     * 删除用户
     * */
    @ApiOperation("删除用户")
    @DeleteMapping("/users/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public Object deleteUser(@PathVariable("id") Long id){
        List<UserDto> list = getData();
        UserDto userDto = getUserDto(id, list);
        return  userDto;
    }

    /**
     * 模拟数据
     * */
    private List<UserDto> getData(){
        List<UserDto> list=new ArrayList<>();

        UserDto userDto = new UserDto();
        userDto.setId(1L);
        userDto.setName("admin");
        userDto.setPwd("admin");
        list.add(userDto);

        userDto = new UserDto();
        userDto.setId(2L);
        userDto.setName("HogwartsTest1");
        userDto.setPwd("HogwartsTest1");
        list.add(userDto);

        userDto = new UserDto();
        userDto.setId(3L);
        userDto.setName("HogwartsTest2");
        userDto.setPwd("HogwartsTest2");
        list.add(userDto);

        userDto = new UserDto();
        userDto.setId(4L);
        userDto.setName("HogwartsTest3");
        userDto.setPwd("HogwartsTest3");
        list.add(userDto);

        return  list;
    }

    /**
     *  模拟根据id查询列表中的数据
     * @param id
     * @param list
     * @return
     */
    private UserDto getUserDto( Long id, List<UserDto> list) {
        UserDto UserDto = null;
        for (UserDto user : list) {
            if (id.equals(user.getId())) {
                UserDto = user;
                break;
            }
        }
        return UserDto;
    }
}

获取全部资源 获取所有用户

GET http://127.0.0.1:8081/api/user/users/

响应参数

[
  {
    "id": 1,
    "name": "admin",
    "pwd": "admin"
  },
  {
    "id": 2,
    "name": "HogwartsTest1",
    "pwd": "HogwartsTest1"
  },
  {
    "id": 3,
    "name": "HogwartsTest2",
    "pwd": "HogwartsTest2"
  },
  {
    "id": 4,
    "name": "HogwartsTest3",
    "pwd": "HogwartsTest3"
  }
]

获取单个资源 获取用户

GET http://127.0.0.1:8081/api/user/users/3

新增一个资源 新增一个用户

POST http://127.0.0.1:8081/api/user/users

请求参数

{
  "id": 4,
  "name": "HogwartsTest5",
  "pwd": "HogwartsTest5"
}

编辑更新一个资源

PUT http://127.0.0.1:8081/api/user/users/3

请求参数

{
  "name": "HogwartsTest6",
  "pwd": "HogwartsTest6"
}

删除一个资源

DELETE http://127.0.0.1:8081/api/user/users/3

下面介绍一些 Spring Boot 常用配置项,通过这些常用配置项,我们可以修改 Spring Boot 的一些默认配置。
修改服务默认端口:

server:
  port: 8093

指定服务名称:

spring:
  application:
    name: aitest

多环境配置

spring:
  profiles:
    active: dev

895×292 15.6 KB


如上图新建 application-dev.yml、application-test.yml、application-uat.yml、application-prod.yml 四套配置文件环境,我们在四套配置文件中将设置服务端口号分别设置为 8091/8092/8093/8094。

然后启动服务,可以看到服务的端口号会和 application.yml 中激活的环境配置信息一致。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/135656.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OpenVINS 官方文档 第一部分

参考链接&#xff1a;OpenVINS https://docs.openvins.com/index.html 1. Getting Started 欢迎来到OpenVIINS项目&#xff01;以下指南将帮助新用户下载软件并在我们支持的数据集上运行。此外&#xff0c;我们还提供有关如何在我们的系统上运行您自己的传感器的信息&#xff0…

《500强高管谈VE价值工程》-对经营变革期下VE的期待

文章出处&#xff1a;日本VE协会杂志 文章翻译&#xff1a;泰泽项目部 关注泰泽&#xff1a;实现高利润企业 《500强高管谈VE价值工程》-对经营变革期下VE的期待 作者: 鹿岛建设常务董事小野馨喜 随着21世纪的到来&#xff0c;社会结构和经济环境正在发生重大转变&…

MobPush 创建推送

功能说明 MobPush提供遵循REST规范的HTTP接口&#xff0c;适用各开发语言环境调用。 IP绑定 工作台可以绑定服务器IP地址&#xff0c;未绑定之前所有IP均可进行REST API的调用&#xff0c;绑定后进仅绑定的IP才有调用权限。 调用地址 POSThttp://api.push.mob.com/v3/push/c…

东南亚开年大促必爆商品;2023Lazada家居家饰需求品类来袭

为持续提升商家体验&#xff0c;保障经营效率&#xff0c;2023年Lazada平台将调整Birthday sale生日大促的活动时间节奏 2023年6个国家站点&#xff08;印尼、马来西亚、菲律宾、新加坡、泰国、越南&#xff09;均会将生日大促提前至2023年3月3日开始。 家居家饰需求清单&…

什么是快速排序?

本文首发自「慕课网」&#xff0c;想了解更多IT干货内容&#xff0c;程序员圈内热闻&#xff0c;欢迎关注&#xff01; 作者| 慕课网精英讲师 JdreamZhang 快速排序&#xff08;Quick Sort&#xff09;&#xff0c;是计算机科学与技术领域中非常经典的一种排序算法&#xff0…

华为云工程师HCIA——桌面云解决方案概述

一、桌面云解决方案概述 瘦终端和胖终端 瘦终端&#xff1a;提供屏幕&#xff0c;和很小的计算能力胖终端&#xff1a;提供主要计算能力 桌面云架构VDI与IDV 华为桌面云解决方案逻辑架构 FusionCompute云平台架构 桌面云的优势 二、桌面云组件介绍 接入和访问控制层 WI&…

图像处理(2)——图像特征提取LBP

图像处理&#xff08;2&#xff09;——图像特征提取LBP 其实现在大家都说图像处理&#xff0c;其实计算机是不认识图片的&#xff0c;之所以可以处理图像&#xff0c;其实图像就是一个个矩阵&#xff0c;其实是数字&#xff0c;转而其实都是在处理数字。深度学习在图像上的建…

数字图像处理实验——数字图像处理初步

一、实验目的与要求 1.熟悉及掌握在MATLAB中能够处理哪些格式的图像&#xff1b; 2.熟练掌握在MATLAB中如何读取图像及图像的属性信息&#xff08;大小、颜色、亮度&#xff08;灰度&#xff09;、宽度、高度等&#xff09;&#xff1b; 3.掌握如何在MATLAB中按照指定要求存储一…

Windows 内核安全编程技术实践

《Windows 内核安全编程技术实践》&#xff0c;这是一本Windows 10内核安全开发系列丛书&#xff0c;探索 AntiRootKit 反内核工具核心原理与技术实现细节&#xff0c;揭开ARK工具的神秘面纱&#xff0c;本书以实战角度出发摒弃了大量无用的专业术语&#xff0c;欢迎阅读并提出…

在Qt中设置窗体背景颜色及透明度的方法介绍

本文主要介绍在 Qt 中设置窗体背景颜色及透明度的方法。 说明&#xff1a; 本文中的应用程序是面向 Windows 操作系统的&#xff1b;本文中使用的 Qt Creator 版本号为&#xff1a;7.0.0&#xff1b;本文中使用的 Qt 版本号为&#xff1a;5.14.2。 1 利用样式表&#xff08;S…

Github每日精选(第82期):还在用logging试试loguru

Loguru 如果你还在使用logging&#xff0c;不妨花点时间来看看Loguru&#xff0c;Loguru是一个Python日志记录的库。 您是否曾懒于配置记录器而使用print&#xff08;&#xff09;&#xff1f;。。。 我确实这样做了&#xff0c;但日志记录对于每个应用程序来说都是基本的&a…

Redis集群系列十二 —— 故障转移二

场景 模拟集群中有一个 master 宕机场景。 故障转移自动故障转移和手动故障转移。 自动故障转移 打开日志监控 为了更好折查看效果&#xff0c;通过 watch 命令实时查看集群的动态日志变化&#xff0c;如图&#xff1a; watch redis-cli -p 30001 cluster nodes 注意&#…

用SQL语句进行数据库查询(复杂查询)

前言 &#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;推荐专栏: &#x1f354;&#x1f35f;&#x1f32f; c语言初阶 &#x1f511;个人信条: &#x1f335;知行合一 &#x1f349;本篇简介:>:上一篇学习了如何使用SQL语句进行简单的数据查询,本篇…

C++ 简单工厂模式 与 工厂模式

简单工厂模式&#xff1a; 一个工厂&#xff0c;多个产品。产品需要有一个虚基类。通过传入参数&#xff0c;生成具体产品对象&#xff0c;并利用基类指针指向此对象。通过工厂获取此虚基类指针&#xff0c;通过运行时多态&#xff0c;调用子类实现。 注意&#xff1a;简单工厂…

S32K144—autoMBD是什么?

基于模型的设计&#xff08;Model-Based Design&#xff0c;MBD&#xff09;是一项非常具有发展潜力的技术&#xff0c;autoMBD 致力于分享和传播 MBD 相关技术&#xff0c;让更多人可以快速、高效地在项目开发中使用 MBD。 MBD能做什么&#xff1f; 从大的范围来说&#xff…

14 Python 办公自动化

目录 1、普通文件自动化管理 1.1 文件的复制 1.2 文件内容的复制 1.3 文件的裁剪 1.4 文件的删除 1.5 文件的压缩与解压缩 1.6 文件的查找 1.7 查找含有指定内容的文件 1.8 清理重复的文件 1.9 批量修改目录中的文件名称 2、文件夹的自动化管理 2.1 文件夹的复制 …

机器学习中的数学原理——线性可分问题

这个专栏主要是用来分享一下我在机器学习中的学习笔记及一些感悟&#xff0c;也希望对你的学习有帮助哦&#xff01;感兴趣的小伙伴欢迎私信或者评论区留言&#xff01;这一篇就更新一下《白话机器学习中的数学——线性可分问题》&#xff01; 一、什么是线性可分问题 线性可分…

kibana和elasticsearch-head安装手册

kibana和elasticsearch-head安装手册 0 安装包下载 组件安装包下载地址kibanakibana-8.5.2-linux-x86_64.tar.gzelastic官网&#xff1a;https://www.elastic.co/cn/downloads/past-releases#kibana elastic中文社区&#xff1a;https://elasticsearch.cn/download/nodenode-…

关键字:static

文章目录一、static关键字的使用static修饰属性实例变量静态变量&#xff08;类变量&#xff09;内存解析static修饰方法static注意点如何确定什么时候使用static&#xff1f;方法属性单例设计模式饿汉式懒汉式区分饿汉式和懒汉式一、static关键字的使用 1、可以用来修饰&…

回首满是自豪

写在前面hi朋友&#xff0c;我是几何心凉&#xff0c;感谢你能够点开这篇文章&#xff0c;看到这里我觉得我们是有缘分的&#xff0c;因着这份缘分&#xff0c;我希望你能够看完我的分享&#xff0c;因为下面的分享就是要汇报给你听的&#xff0c;这篇文章是在 2022 年 12 月 3…