Spring Boot 的 RESTful API 设计与实现
myzbx 2025-01-01 21:43 72 浏览
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
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
如上图新建 application-dev.yml、application-test.yml、application-uat.yml、application-prod.yml 四套配置文件环境,我们在四套配置文件中将设置服务端口号分别设置为 8091/8092/8093/8094。
然后启动服务,可以看到服务的端口号会和 application.yml 中激活的环境配置信息一致。
[更多技术文章](https://qrcode.ceba.ceshiren.com/link?name=article&project_id=qrcode&from=toutiao×tamp=1662397200&author=Muller)
- 上一篇:百度地图API基本使用(三)
- 下一篇:API接口安全性测试及优化方案
相关推荐
- 如何设计一个优秀的电子商务产品详情页
- 
        加入人人都是产品经理【起点学院】产品经理实战训练营,BAT产品总监手把手带你学产品电子商务网站的产品详情页面无疑是设计师和开发人员关注的最重要的网页之一。产品详情页面是客户作出“加入购物车”决定的页面... 
- 怎么在JS中使用Ajax进行异步请求?
- 
        大家好,今天我来分享一项JavaScript的实战技巧,即如何在JS中使用Ajax进行异步请求,让你的网页速度瞬间提升。Ajax是一种在不刷新整个网页的情况下与服务器进行数据交互的技术,可以实现异步加... 
- 中小企业如何组建,管理团队_中小企业应当如何开展组织结构设计变革
- 
        前言写了太多关于产品的东西觉得应该换换口味.从码农到架构师,从前端到平面再到UI、UE,最后走向了产品这条不归路,其实以前一直再给你们讲.产品经理跟项目经理区别没有特别大,两个岗位之间有很... 
- 前端监控 SDK 开发分享_前端监控系统 开源
- 
        一、前言随着前端的发展和被重视,慢慢的行业内对于前端监控系统的重视程度也在增加。这里不对为什么需要监控再做解释。那我们先直接说说需求。对于中小型公司来说,可以直接使用三方的监控,比如自己搭建一套免费的... 
- Ajax 会被 fetch 取代吗?Axios 怎么办?
- 
        大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!今天给大家带来的主题是ajax、fetch... 
- 前端面试题《AJAX》_前端面试ajax考点汇总
- 
        1.什么是ajax?ajax作用是什么?AJAX=异步JavaScript和XML。AJAX是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,AJAX可以使网页实... 
- Ajax 详细介绍_ajax
- 
        1、ajax是什么?asynchronousjavascriptandxml:异步的javascript和xml。ajax是用来改善用户体验的一种技术,其本质是利用浏览器内置的一个特殊的... 
- 6款可替代dreamweaver的工具_替代powerdesigner的工具
- 
        dreamweaver对一个web前端工作者来说,再熟悉不过了,像我07年接触web前端开发就是用的dreamweaver,一直用到现在,身边的朋友有跟我推荐过各种更好用的可替代dreamweaver... 
- 我敢保证,全网没有再比这更详细的Java知识点总结了,送你啊
- 
        接下来你看到的将是全网最详细的Java知识点总结,全文分为三大部分:Java基础、Java框架、Java+云数据小编将为大家仔细讲解每大部分里面的详细知识点,别眨眼,从小白到大佬、零基础到精通,你绝... 
- 福斯《死侍》发布新剧照 "小贱贱"韦德被改造前造型曝光
- 
        时光网讯福斯出品的科幻片《死侍》今天发布新剧照,其中一张是较为罕见的死侍在被改造之前的剧照,其余两张剧照都是死侍在执行任务中的状态。据外媒推测,片方此时发布剧照,预计是为了给不久之后影片发布首款正式预... 
- 2021年超详细的java学习路线总结—纯干货分享
- 
        本文整理了java开发的学习路线和相关的学习资源,非常适合零基础入门java的同学,希望大家在学习的时候,能够节省时间。纯干货,良心推荐!第一阶段:Java基础重点知识点:数据类型、核心语法、面向对象... 
- 不用海淘,真黑五来到你身边:亚马逊15件热卖爆款推荐!
- 
        Fujifilm富士instaxMini8小黄人拍立得相机(黄色/蓝色)扫二维码进入购物页面黑五是入手一个轻巧可爱的拍立得相机的好时机,此款是mini8的小黄人特别版,除了颜色涂装成小黄人... 
- 2025 年 Python 爬虫四大前沿技术:从异步到 AI
- 
        作为互联网大厂的后端Python爬虫开发,你是否也曾遇到过这些痛点:面对海量目标URL,单线程爬虫爬取一周还没完成任务;动态渲染的SPA页面,requests库返回的全是空白代码;好不容易... 
- 最贱超级英雄《死侍》来了!_死侍超燃
- 
        死侍Deadpool(2016)导演:蒂姆·米勒编剧:略特·里斯/保罗·沃尼克主演:瑞恩·雷诺兹/莫蕾娜·巴卡林/吉娜·卡拉诺/艾德·斯克林/T·J·米勒类型:动作/... 
- 停止javascript的ajax请求,取消axios请求,取消reactfetch请求
- 
        一、Ajax原生里可以通过XMLHttpRequest对象上的abort方法来中断ajax。注意abort方法不能阻止向服务器发送请求,只能停止当前ajax请求。停止javascript的ajax请求... 
- 一周热门
- 最近发表
- 标签列表
- 
- HTML 简介 (30)
- HTML 响应式设计 (31)
- HTML URL 编码 (32)
- HTML Web 服务器 (31)
- HTML 表单属性 (32)
- HTML 音频 (31)
- HTML5 支持 (33)
- HTML API (36)
- HTML 总结 (32)
- HTML 全局属性 (32)
- HTML 事件 (31)
- HTML 画布 (32)
- HTTP 方法 (30)
- 键盘快捷键 (30)
- CSS 语法 (35)
- CSS 轮廓宽度 (31)
- CSS 谷歌字体 (33)
- CSS 链接 (31)
- CSS 定位 (31)
- CSS 图片库 (32)
- CSS 图像精灵 (31)
- SVG 文本 (32)
- 时钟启动 (33)
- HTML 游戏 (34)
- JS Loop For (32)
 
