Restful风格的编程

news2024/11/26 9:52:41

Restful风格的编程

  • 1、 Restful简介
  • 2、查询用户以及用户详情
    • 2.1常用注解
    • 2.2查询用户详情
  • 3、处理创建请求
    • 3.1@RequestBody注解
      • 3.1.1用途
      • 3.1.2语法规范
    • 3.2日期类型的处理
    • 3.3BindingResult
  • 4、用户信息修改与删除
    • 4.1用户信息修改
    • 4.2案例
      • 前端界面
      • 后端控制器

1、 Restful简介

Restful比较热门,,Spring的微服务是基于Restful风格搭建的框架。
Restful有一下几个特点:

  1. 使用URL描述资源。
  2. 使用HTTP方法描述行为,使用HTTP状态码来表示不同的结果。
  3. 使用JSON交互数据。
  4. Restful只是一种风格,不是强制标准。

2、查询用户以及用户详情

最简单的,最常用的GET请求,用于查询全部数据或者其中一条数据的详情。

2.1常用注解

常用注解作用
@RestController表明此tController 提供的是Restful服务
@RequestMapping将URL映射到Java
@RequestParam映射请求参数到Java上的参数
@PageableDefault指定分页参数的默认值

2.2查询用户详情

@RequestMapping(value="/manage", method= {RequestMethod.GET})
	public String list(String userId,Map<String,Object> map) {
		if(userId==""||userId==null) {
			map.put("userList", userService.getUserList());
		}else {
			map.put("userList",userService.getUserById(Integer.parseInt(userId)));
		}
		return "user/list";
	}

3、处理创建请求

3.1@RequestBody注解

3.1.1用途

用于接收前端传递给后端的json字符串中的数据。(处理json格式的数据)
@RequestBody用来接收前端传递给后端的json字符串中的数据,GET方式的请求一般通过URL中携带key-value参数,而@RequestBody接收的是请求体中的数据(json格式的数据,只有请求体中能保存json),所以使用@RequestBody接收数据的时候必须是POST方式等方式。
@RequestBody与@RequestParam()可以同时使用,但@RequestBody最多只能有一个,而@RequestParam()可以多个。

3.1.2语法规范

(@RequestBody Map map)
(@RequestBody Object object)

(@RequestBody Map map)先对简单,将json解析成Map形式的key-value对,直接通过map.get(“KeyName”)就能拿到值了
(@RequestBody Object object) 通过json字符串中的key来匹配对应实体类的属性如果匹配一致且json中的该key对应的值符合实体类的对应属性的类型要求时,会调用实体类的setter方法将值注入到该属性。
例如

public Result deleteBookById(@RequestBody HashMap<String, String> map) {
        this.bookService.deleteBookById(Long.parseLong(map.get("id")));
        return Result.createWithSuccessMessage();
    }

public Result updateBookById(@RequestBody Book book){
        Book record = this.bookService.updateBookById(book);
        return Result.createWithModel(record);
    }

注意:

在(@RequestBody Object object)中,前端POST过来的数据会通过反序列数据到实体类中,并且在反序列的过程中会进行类型的转换。
在json中应该用null来代表空值,如果是"“(空字符串)会判断为空串,如果实体类属性是String类型的,那么接受到的就是”",如果实现类属性类型是Integer、Double等类型,那么接收到的就是null。

{
	name:"",
	age:null
}

(@RequestBody Object object)内部是通过传递过来的数据中的Key寻找setter方法,有则调用,无则不作任何操作(其实可以设计)。
如果通过Key匹配到setter方法,但是Value无法转换为对应的实例类属性的类型时,抛出异常。

3.2日期类型的处理

前端传入日期格式: yyyy-MM-dd HH:mm:ss,例如:2018-07-09 12:55:12(不使用时间戳,前后双方联调时查看起来更加友好)

后端返回日期格式: yyyy-MM-dd HH:mm:ss,例如:2018-07-09 12:55:12(不使用时间戳,前后双方联调时查看起来更加友好)

后端json序列化、反序列化框架: 定义任何一种高效的json工具都行,例如:Fastjson、Gson、Jackson lib

序列化、反序列化日期格式规范: pattern=”yyyy-MM-dd HH:mm:ss”,timezone = “GMT+8”,除特出场景可以使用pattern=”yyyy-MM-dd”,timezone = “GMT+8”

不要随意自定义convert处理日期格式以及其他特殊格式转换,应该交由基础框架组或架构组统一在框架层面解决,对业务开发透明,或者在有些小公司由Leader或高开来担当。

3.3BindingResult

	/*
     * 添加用户,使用@RequestBody将请求体映射到Action方法参数中
     * 使用@Valid注解验证请求参数的合法性
     * 使用BindingResult处理校验结果
     * @param user
     * @param result
     * @return
     */
      @PostMapping("/user")
      public User create(@Valid @RequestBody User user, BindingResult result){
         if(result.hasErrors()){
             result.getAllErrors().stream().forEach(error -> {
                 FieldError fieldError = (FieldError)error;
                 String message = fieldError.getField() + " " + error.getDefaultMessage();
                 System.out.println(message);
             });
             return null;
         }
         System.out.println(user.toString());
         user.setId(5l);
         return user;
     }

4、用户信息修改与删除

PUT和DELETE并不复杂,大家也熟悉,用于对后台数据的更新和删除。

4.1用户信息修改

对资源更新的请求方法通常是是PUT,但有时候也可能是POST。那么问题来了,都是更新资源区别在哪里?

PUTPOST
在HTTP中PUT被定义为幂等的请求方法而POST则不是
操作是作用于一个具体资源之上作用于一个集合资源之上
URL在客户端确定使用PUTURL在服务端确定使用POST

比较直观的是资源URL的不同
——

4.2案例

前端界面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../js/jquery.min.js"></script>
    <script>
        $(function () {
            // 查询所有
            $('#btn1').click(function () {
                $.get('/employees', function (data) {
                    console.log(data);
                });
            });

            // 查询一个
            $('#btn2').click(function () {
                $.get('/employees/10', function (data) {
                    console.log(data);
                });
            });

            // 添加
            $('#btn3').click(function () {
                $.post('/employees', "id=11", function (data) {
                    console.log(data);
                });
            });

            // 修改
            $('#btn4').click(function () {
                $.ajax({
                    url: "/employees",
                    type: "PUT",
                    data: {id: 1, name: "小肥羊", age: 10},
                    success: function (data) {
                        console.log(data);
                    }
                });
            });

            // 删除
            $('#btn5').click(function () {
                $.ajax({
                    url: "/employees/13",
                    type: "DELETE",
                    data: {id: 1},
                    success: function (data) {
                        console.log(data);
                    }
                });
            });

        });
    </script>
</head>
<body>
<button id="btn1">查询所有</button>
<button id="btn2">查询一个</button>
<button id="btn3">添加</button>
<button id="btn4">修改</button>
<button id="btn5">删除</button>
</body>
</html>

后端控制器

package com.yy.web.controller;

import com.yy.domain.Employee;
import com.yy.util.JsonResult;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.web.bind.annotation.*;

import java.util.Arrays;
import java.util.List;

/**
 * @program: restful-demo
 * @ClassName: EmployeeController
 * @description:
 * @author: YanYang
 * @create: 2021-06-23 15:04
 **/
@RestController
@RequestMapping("employees")
public class EmployeeController {
    /**
     * 2个接口设计都是用相同资源,相同请求方法,此时 SpringMVC 无法识别,
     * 认为是同一方法,报错:Ambiguous mapping. [模糊映射]
     *
     * RESTful 解决方案:使用 参数路径 方式
     *      具体实现:将参数作为请求映射路径一部分,[参与映射路径区分]
     *      比如:查询指定 id 的员工信息接口设计
     *      @RequestMapping(value = "/employees/{id}", method = RequestMethod.GET)
     *      其中 "/employees/{id}" 参数路径,{id} 就是路径参数
     *
     *      访问该接口时:http:localhost:8080/employees/1  其中 1 是 id 参数
     *      接口接收路径参数:使用 @PathVariable,表示将参数路径上的参数解析,并赋值给指定变量
     *      如果路径参数与变量名不一致,使用 @PathVariable("eid")明确指定
     *
     */
    // 查询所有(数据是模拟的)
//    @RequestMapping(value = "/employees", method = RequestMethod.GET)
    @GetMapping
    public List<Employee> list() {
        return Arrays.asList(new Employee(1L,"小肥羊", 10), new Employee(2L, "熊大", 11));
    }

    // 查询单个(数据是模拟的)
//    @RequestMapping(value = "/employees/{id}", method = RequestMethod.GET)
    @GetMapping("/{eid}")
    public Employee queryById(@PathVariable("eid") Long id) {
        System.out.println("查询单个 = " + id);
        return new Employee(3L, "熊二", 8);
    }

    // 添加(数据是模拟的)
//    @RequestMapping(value = "/employees", method = RequestMethod.POST)
    @PostMapping
    public Employee add(@ModelAttribute("employee") Employee employee) {
        System.out.println("添加 = " + employee.getId());
        return employee;
    }

    // 修改(数据是模拟的)
//    @RequestMapping(value = "/employees", method = RequestMethod.PUT)
    @PutMapping
    public Employee update(@ModelAttribute("employee") Employee employee) {
        System.out.println("修改 = " + employee.getId());
        employee.setId(employee.getId());
        employee.setName(employee.getName());
        employee.setAge(employee.getAge());
        return employee;
    }

    // 删除(数据是模拟的)
//    @RequestMapping(value = "/employees/{id}", method = RequestMethod.DELETE)
    @DeleteMapping("/{id}")
    public String delete(@PathVariable Long id) {
        System.out.println("删除 = " + id);
        if (id != null && 1 == id) {
            return "删除成功";
        }
        return "删除失败";
    }
}

在这里插入图片描述
求三连!!!!!

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

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

相关文章

剑指offer(C++)-JZ69:跳台阶(算法-动态规划)

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 题目描述&#xff1a; 一只青蛙一次可以跳上1级台阶&#xff0c;也可以跳上2级。求该青蛙跳上一个 n 级的台阶总共有多少种跳法&…

【JavaSE】类与对象(上)类是什么?对象是什么?

文章目录面向过程与面向对象认识类和对象创建类类的实例化内存分布注意事项总结面向过程与面向对象 我们说C语言是面向过程的编程语言&#xff0c;而Java是面向对象的编程语言&#xff0c;那究竟什么才是面向过程与面向对象呢&#xff1f;我们举一个例子来帮助大家理解&#x…

PX4飞行测试

文章目录前言一、首次飞行指南飞行入门解锁飞机起飞降落飞行控制/命令辅助飞行任务飞行规划任务设置机体航向设置航点/转弯半径地理围栏故障保护地理围栏地理围栏规划安全点(集结点)创建/定义安全点地形跟随/保持地形跟随地形保持前言 本节包含有关飞行&#xff08;完全配置过…

虚拟主播也带货?直播电商的变与不变

5月6日晚&#xff0c;海外虚拟主播vox在B站开启了中国直播首秀。从最终数据来看&#xff0c;直播1.7小时&#xff0c;营收111万人民币&#xff0c;当晚还登上平台热门首位&#xff0c;这样的直播吸金能力&#xff0c;让不少明星都望尘莫及。 更值得关注的是&#xff0c;直播间…

Matlab:表达式

Matlab&#xff1a;表达式变量数字矩阵运算符数组运算符函数表达式示例变量 与大多数其他编程语言一样&#xff0c;MATLAB 语言提供数学表达式&#xff0c;但与大多数编程语言不同的是&#xff0c;这些表达式涉及整个矩阵。 MATLAB 不需要任何类型声明或维度说明。当 MATLAB …

PyCharm 这40个使用技巧真棒

大家好&#xff0c;今天分享 PyCharm 40个使用技巧&#xff0c;内容有点长&#xff0c;喜欢欢迎收藏、分享、点赞。 废话不多说。我们开始吧&#xff01; 文章目录技术提升第一章&#xff1a;运行调试篇1\. 通过指定参数&#xff0c;执行程序2\. 程序结束了&#xff0c;照样可…

Vue 3 属性绑定细节

在ButtonDemo中默认会把传给这个组件上的所有事件,都传递给Button中的最外层的元素 不管这个最外层的元素是什么!比如下图:在button外面还有一个div,那么传递给最外层的就应该是div,而不是button 最外层为div 想让组件的某一个部分,点击时被触发click事件 现在传递给最…

LeetCode-764. 最大加号标志【动态规划,二维数组】

LeetCode-764. 最大加号标志【动态规划&#xff0c;二维数组】题目描述&#xff1a;解题思路一&#xff1a;动态规划。用一个n*n的数组记录每个点上下左右方向上为1的最小值。最后ans返回数组中最大的加号。解题思路二&#xff1a;优化1。解题思路三&#xff1a;0题目描述&…

word制作多个单位联合发文的文件头

一、前言 word制作多个单位联合发文的文件头&#xff0c;好像不难。但是做起来&#xff0c;却发现&#xff0c;自己的只是储备还是不够&#xff0c;居然花费了1个多小时才搞定....哎 二、遇到问题 开始思路是想使用【分栏】来操作&#xff0c;但是不得其法&#xff0c;搞了一…

驱动开发基础知识

文章目录记录驱动开发前的知识储备工作一、驱动开发环境搭建二、驱动开发框架&#xff08;重点&#xff1a;WDF框架&#xff09;1、前世今生&#xff08;1&#xff09;Vista简介&#xff08;2&#xff09;发展历史2、基于框架的驱动程序的 WDM&#xff08;1&#xff09;驱动程序…

linux(1.nginx基础 2.使用Nginx负载均衡及动静分离)

一.nginx基础 目录 1. Nginx使用场景2. Nginx中的进程 2.1 Nginx中的多进程模型2.2 多进程模式的优点&#xff1a;2.3 缓存3. Ngnix的负载均衡策略 3.1 轮询法3.2 加权轮询3.3 原地址哈希3.4 最小连接数法3.5 Fair3.6 url_hash3. Nginx配置文件4. Nginxtomcat 集群示例 4.1 下…

c++学习-STL常用函数

第八部分-STL常用函数 5.1 常用遍历算法 5.1.1 for_each 5.1.2 transform 5.2 常用查找算法 5.2.1 find 5.2.2 find_if 5.2.3 adjacent_find 面试题中如果出现查找相邻重复元素&#xff0c;记得用stl中的adjacent_find算法 5.2.4 binary_search 5.2.5 count 5.2.6 count_if 5.…

【双十一特辑】爱心代码(程序员的浪漫)-李峋

前言 最近《点燃我温暖你》中李峋的爱心代码超级火&#xff0c;看着特别心动&#xff0c;这不&#xff0c;光棍节快到了&#xff0c;给兄弟们教学一波爱心代码&#xff0c;赶在双十一前表白&#xff0c;让这个双十一不在是孤单一个人&#xff01;目录 前言 C语言简易爱心代码…

final 关键字 —— 限制继承、限制虚函数重写

final 关键字有两个作用&#xff0c;一个是限制继承&#xff0c;一个是限制重写。 目录 1、限制继承 (1) 基类的构造函数设为私有 (2) 基类类名后面加上 final 关键字修饰 2、限制虚函数重写 1、限制继承 限制继承有两种方式&#xff0c;一种是将基类的构造函数设为私有&am…

谷粒商城-基础篇(详细流程梳理+代码)

文章目录前言一、项目环境搭建1.1、安装virtualbox以及vagrant1.2、Docker安装MySQL与Redis1.3、前后端开发工具统一配置1.4、Git工具安装与配置1.5、Gitee创建仓库与IDEA导入1.6、构建微服务模块1.7、编写.gitignore文件&#xff08;忽略上传gitee文件配置&#xff09;1.8、数…

【云原生之K8s】 K8s资源控制及探针检查

文章目录一、资源限制1.资源限制的使用2.request资源&#xff08;请求&#xff09;和limit资源&#xff08;约束&#xff09;3.Pod和容器的资源请求和限制4.官方文档示例5.资源限制实操5.1 编写yaml资源配置清单5.2 释放内存&#xff08;node节点&#xff0c;以node1为例&#…

昨晚,我用python帮学妹P证件照自拍,然后发现。。。

人生苦短&#xff0c;我用Python前因后果先上效果准备工作证件照尺寸调整证件照背景调整各种背景颜色图片完整代码结尾最后前因后果 事情是这样的 晚上我正在聚精会神写代码&#xff08;打游戏~&#xff09; 突然&#xff0c;收到学妹给我发来的消息 还有一张自拍照 而且是…

基于stm32单片机的超声波测距显示倒车雷达提醒报警系统Proteus仿真

资料编号&#xff1a;145 下面是相关功能视频演示&#xff1a; 145-基于stm32单片机的超声波测距显示倒车雷达提醒报警系统Proteus仿真&#xff08;源码原理图仿真论文&#xff09;设计内容 本次嵌入式课程设计综合实验的内容为倒车测距系统。以proteus keilU5为模拟硬件基础…

Android studio中控件TextView学习

1、TextView 基础属性 layout_ width; 组件的宽度layout. _height: 组件的高度id: 为TextView设置- -个组件idtext; 设置显示的文本内容textColor: 设置字体颜色textStyle: 设置字体风格&#xff0c;三个可选值: n normal(无效果)&#xff0c;bold(加粗)&#xff0c; italic(斜…

Springboot @Async 失效的坑

异步应用场景 为了提高接口的响应性能&#xff0c;当业务非常复杂的情况下&#xff0c;可以将一部分跟业务关联性不是特别强的逻辑进行异步处理。如日志记录、短信发送、增加积分等。通常而言会将此类业务逻辑通过异步的方式进行处理&#xff0c;从而加快接口的响应速度&#…