SpringMVC(三)【REST 风格】

1、REST 风格

1.1、REST 简介

  • REST(Representational State Transfer),表现形式状态转换

        在开发中,它其实指的就是访问网络资源的格式

1.1.1、传统风格资源描述形式

  • http://localhost/user/getById?id=1
  • http://localhost/user/saveUser

1.1.2、REST 风格描述形式

在 REST 风格中,一般用 模块名 + s 的格式描述资源,表示这是一类资源,而不是单个资源。

4 个常用的 REST 风格请求行为

  • http://localhost/users        查询所有用户信息        GET (查询)
  • http://localhost/users/1        查询指定用户信息        GET (查询)
  • http://localhost/users        添加用户信息        POST (新增)
  • http://localhost/users        修改用户信息        PUT (更新)
  • http://localhost/users/1        删除用户信息        DELETE (删除)

        REST 风格下,对于同一个路径,不同的请求代表对资源不同的操作。也就是说,我们只需要一个路径和一个请求方式就可以确定一个访问行为

        根据 REST 风格对资源进行访问称为 RESTful 。

优点

  1. 最大在优点就是隐藏资源的访问行为,无法通过地址得到对资源是如何操作的

注意:REST 风格只是一种风格,并不是一种规范,可以打破。也就是说我们想怎么写就怎么写,但是我们只是希望大家都遵守这种风格,方便开发。

1.2、RESTful 入门案例

        RESTful 就是指使用 REST 风格开发项目。

1.2.1、设定 http 请求动作

        REST 风格下,我们对资源的不同操作由路径请求动作决定,这里的路径我们统一为 模块名 + s,所以我们需要把 Controller 类上面的 @RequsetMapping 中指定的该模块资源的统一前缀去掉。

        添加请求动作只需要先把原本 Controller 类的方法上 RequsetMapping 注解的参数改为 模块名 + s  ,然后通过 method 属性来给方法添加请求动作。

        查询都是 GET、新增是 POST 、修改是 PUT、删除是 DELETE

    @RequestMapping(value = "/users",method = RequestMethod.POST)@ResponseBodypublic String save(@RequestBody User user){System.out.println("user save,  name = " + user.getName() + " , age = " + user.getAge());return "{'module':'user save'}";}

         这里的新增用户请求需要传递用户参数,这里我们通过 @RequestBody 注解来表示从请求体中获取参数,也就是通过 json 来传递

1.2.2、设定请求路径参数

        也就是我们控制器类方法上面的注解 @RequsetMapping 中的 value 参数,这里需要根据需求决定需不需要带参数(比如删除 name 为 'zs' 的用户,那就需要指定 value="/users/name" 而不只是模块名+s)。

        此外,对于带有路径变量的请求参数需要给形参前面添加注解 @PathVariable ,表示从请求路径中解析出该变量当做形参的值。

    @RequestMapping(value = "/users/{id}",method = RequestMethod.DELETE)@ResponseBodypublic String delete(@PathVariable Integer id){System.out.println("user deleted ... user id => " + id);return "{'module': 'user delete'}";}

 完整代码:

@Controller
public class UserController {@RequestMapping(value = "/users",method = RequestMethod.POST)@ResponseBodypublic String save(@RequestBody User user){System.out.println("user save,  name = " + user.getName() + " , age = " + user.getAge());return "{'module':'user save'}";}@RequestMapping(value = "/users/{id}",method = RequestMethod.DELETE)@ResponseBodypublic String delete(@PathVariable Integer id){System.out.println("user deleted ... user id => " + id);return "{'module': 'user delete'}";}@RequestMapping(value = "/users",method = RequestMethod.PUT)@ResponseBodypublic String update(@RequestBody User user){System.out.println("user deleted ... user => " + user.toString());return "{'module': 'user update'}";}@RequestMapping(value = "/users/{id}",method = RequestMethod.GET)@ResponseBodypublic String getById(@PathVariable Integer id){System.out.println("user get ... user id => " + id);return "{'module': 'user get'}";}@RequestMapping(value = "/users",method = RequestMethod.GET)@ResponseBodypublic String getAll(){System.out.println("user get all ...");return "{'module': 'user get all'}";}
}

测试结果:

查询所有用户:

查询 id 为 1 的用户:

新增用户:

 

注意新增用户时我们需要给控制器方法传递一个 User 类型创参数,因为需要使用 jackson 把我们的 json 转为 java 对象,这里要求该对象必须要有无参构造器,不然会报错!

删除用户:

修改用户:
 

1.2.3、请求参数总结

到现在我们共学习了三种请求参数的传递方法:

  1. @RequestBody
  2. @RequestParam(用的比较少)
  3. @PathVariable

1.3、RESTful 快速开发

        这一节我们来对上面的代码进行简化开发,比如所有的控制器方法的前缀都是 "/users" ,所有的控制器方法上面都有一个 @ResponseBody (因为我们不需要返回页面)。

1.3.1、统一路径前缀

        上一节使用 REST 风格后,我们发现所有的请求路径的前缀都是 "/users" + 路径变量,所以既然都有一个前缀 "/users" ,那么为什么不可以都踢出来呢:

@RequestMapping("/users")
public class UserController {// ...
}

        这样,对于那些在 REST 风格下路径本来就是 模块名+s("/users")的方法,直接就可以直接省去 @RequestMapping 中的 value 属性,对于请求路径包含路径变量的方法,可以省去前缀,就像这样:

    @RequestMapping(value = "/{id}",method = RequestMethod.DELETE)public String delete(@PathVariable Integer id){System.out.println("user deleted ... user id => " + id);return "{'module': 'user delete'}";}

1.3.2、@RestController

        从上一节我们的代码中可以发现,控制器类的方法都带有一个 @ResponseBody ,这是因为因为我们不需要返回页面。所以这里我们可以直接简化把它提到控制器类上面:

@Controller
@ResponseBody
@RequestMapping("/users")
public class UserController {// ...
}

        但是 SpringMVC 还是觉得不够简化,它又提供了一个注解 @RestController ,它就相当于同时包含了 @ResponseBody 和 @Controller 两个注解,毕竟控制器类上面肯定是由 @Controller 注解的。所以以后我们直接这么写就行了:

@RestController
@RequestMapping("/users")
public class UserController {// ...
}

1.3.2、标准请求动作注解

        经过上一步的简化,我们的 UserController 现在变成了这样:

@RestController
@RequestMapping("/users")
public class UserController {@RequestMapping(method = RequestMethod.POST)public String save(@RequestBody User user){System.out.println("user save,  name = " + user.getName() + " , age = " + user.getAge());return "{'module':'user save'}";}@RequestMapping(value = "/{id}",method = RequestMethod.DELETE)public String delete(@PathVariable Integer id){System.out.println("user deleted ... user id => " + id);return "{'module': 'user delete'}";}@RequestMapping(method = RequestMethod.PUT)public String update(@RequestBody User user){System.out.println("user deleted ... user => " + user.toString());return "{'module': 'user update'}";}@RequestMapping(value = "/{id}",method = RequestMethod.GET)public String getById(@PathVariable Integer id){System.out.println("user get ... user id => " + id);return "{'module': 'user get'}";}@RequestMapping(method = RequestMethod.GET)public String getAll(){System.out.println("user get all ...");return "{'module': 'user get all'}";}
}

        现在看起来还是很冗余,我们可以对这些方法的请求行为进行进一步简化,现在这么长的参数太扎眼了,现在我们的代码就变成了这样(把 value =  "/{param}" 和  method = RequestMethpd.X 合并到一个注解中):

@RestController
@RequestMapping("/users")
public class UserController {@PostMappingpublic String save(@RequestBody User user){System.out.println("user save,  name = " + user.getName() + " , age = " + user.getAge());return "{'module':'user save'}";}@DeleteMapping("/{id}")public String delete(@PathVariable Integer id){System.out.println("user deleted ... user id => " + id);return "{'module': 'user delete'}";}@PutMappingpublic String update(@RequestBody User user){System.out.println("user deleted ... user => " + user.toString());return "{'module': 'user update'}";}@GetMapping("/{id}")public String getById(@PathVariable Integer id){System.out.println("user get ... user id => " + id);return "{'module': 'user get'}";}@GetMappingpublic String getAll(){System.out.println("user get all ...");return "{'module': 'user get all'}";}
}

显然一下子变得清新脱俗!舒服多了。

1.4、基于 RESTful 页面数据交互

  实体类

package com.lyh.domain;public class Book {private Integer id;private String type;private String name;private String description;public Book(){}public Book(Integer id, String type, String name, String description) {this.id = id;this.type = type;this.name = name;this.description = description;}@Overridepublic String toString() {return "Book{" +"id=" + id +", type='" + type + '\'' +", name='" + name + '\'' +", description='" + description + '\'' +'}';}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getType() {return type;}public void setType(String type) {this.type = type;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}
}

SpringMVC 配置类

@Configuration
@ComponentScan("com.lyh.controller") // 扫描
@EnableWebMvc // 开启 json 转对象的功能等各种格式转换
public class SpringMvcConfig {}

Sevlet 容器配置类

public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {protected Class<?>[] getRootConfigClasses() {return new Class[0];}protected Class<?>[] getServletConfigClasses() {return new Class[]{SpringMvcConfig.class};}protected String[] getServletMappings() {return new String[]{"/"};}// 乱码处理@Overrideprotected Filter[] getServletFilters() {CharacterEncodingFilter filter = new CharacterEncodingFilter();filter.setEncoding("UTF-8");return new Filter[]{filter};}
}

BookController 控制器类

@RestController
@RequestMapping("/books")
public class BookController {@PostMappingpublic String save(@RequestBody Book book){System.out.println("book save ... book => " + book.toString());return "{'module':'book save'}";}@GetMappingpublic List<Book> getAll(){List<Book> list = new ArrayList<Book>();list.add(new Book(1,"编程","《图解Spark》","大数据技术"));list.add(new Book(2,"小说","《黄金时代》","王小波著作"));return list;}
}

测试

        导入静态资源后访问 localhost:85/pages/boos.html 发现报错找不到映射:No Mapping for GET /pages/books.html 这是因为我们现在的请求都被 SpringMVC 拦截走了,其实这些静态资源应该是由 Tomcat 处理的。

1.4.1、放行非 SpringMVC 请求

        上面的问题是对于静态资源的访问,本该是由 Tomcat 处理,但是前面我们在 Servlet 配置类中设置了所有请求都由 SpringMVC 来响应。所以,现在我们需要通过添加一个配置类来实现放行静态资源:

@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {@Overrideprotected void addResourceHandlers(ResourceHandlerRegistry registry) {// 当访问 /pages/下的资源时,走 /pages 目录下的内容registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");registry.addResourceHandler("/js/**").addResourceLocations("/js/");registry.addResourceHandler("/css/**").addResourceLocations("/css/");registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");}
}

        然后,我们需要让 SpringMVC 去加载这个新的配置类:

这样就可以访问到了:

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

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

相关文章

飞书API(4):筛选数据的三种思路

截止到上一篇&#xff0c;终于通过飞书 API 完整获取到飞书多维表的数据。但是&#xff0c;有些场景&#xff0c;比如数据源会出现脏数据&#xff0c;毕竟如果是运营过程多人协作维护的数据&#xff0c;要想保持数据完美简直是天方夜谭&#xff01;再比如我们不需要完整的数据&…

【JavaWeb】Day46.Mybatis——入门

JDBC介绍 通过Mybatis可以很方便的进行数据库的访问操作。其实java语言操作数据库&#xff0c;只能通过一种方式&#xff1a;使用sun公司提供的 JDBC 规范。Mybatis框架&#xff0c;就是对原始的JDBC程序的封装。 JDBC&#xff1a; ( Java DataBase Connectivity )&#xff0c…

开源了!自从用了这个远程控制工具,从此把 TeamViewer 扔一边了【文末领项目源码】

在工作中&#xff0c;咱们经常要使用向日葵、TeamViewer 等远程控制工具&#xff0c;来远程操控项目上的主机去解决一些部署在现场的系统问题&#xff0c;亦或是在家偶尔加班时用家里的电脑远程公司的电脑处理工作。但不爽的是&#xff0c;TeamViewer 用一用试用期就过了&#…

ES 大数据量按照日期分索引存储和查询

前言 ES 通常被用来存放各种日志数据或其他大批量数据&#xff0c;然后做统计。 对于请求量大的系统来说&#xff0c;日志或其他业务数据无比庞大&#xff0c;需要按日期来划分索引&#xff0c;便于做冷热数据的迁移管理。大批量的业务数据也要根据日期来区分&#xff0c;提高…

Java --- 类与对象

上篇内容给大家带来了Java的语句与数组的相关内容&#xff0c;那么本期内容比较重要&#xff0c;需要读者们掌握Java面向对象编程的根本&#xff0c;通过这篇博客来让读者浅入理解Java类的一些基本操作。 目录 一.特点&#xff1a; 二.成员变量&#xff1a; 三.访问修饰符&a…

【JavaSE】搞定String类

前言 本篇会细致讲解String类的常见用法&#xff0c;让小伙伴们搞定String类~ 欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 前言 常用的三种字符串构造 字符串长度length 字符串比较 比较 比较字符串的内容equals…

MySQL DDL 通用语法

&#x1f339;作者主页&#xff1a;青花锁 &#x1f339;简介&#xff1a;Java领域优质创作者&#x1f3c6;、Java微服务架构公号作者&#x1f604; &#x1f339;简历模板、学习资料、面试题库、技术互助 &#x1f339;文末获取联系方式 &#x1f4dd; 往期热门专栏回顾 专栏…

libftdi1学习笔记 4 - MPSSE SPI

目录 1. 初始化 2. SCK默认电平设置 3. GPIO控制 4. spi全双工通信 4.1 MSB/LSB 4.2 分配command缓存 4.3 spi0TransferBit 4.3 spi1TransferBit 4.4 spi2TransferBit 4.5 spi3TransferBit 4.6 写命令序列 4.7 读数据 4.8 组合实际数据 5. 验证 5.1 初始化FTDI设…

短视频底层逻辑分析

短视频底层逻辑 1.迭代模型_ev 2.Douyin的本质_ev 3.Douyin的审核机制_ev 4.平台趋势_ev 5.定位_ev 6.建立用户期待_ev 7.好内容的定义_ev 8怎么做好内容_ev 9.如何做好选题_ev 10.如何快速模仿_ev 11.账号拆解的底层逻辑_ev 12选人的重要性_ev 13.内容的包装_ev 14.打造大IP的…

【中间件】ElasticSearch简介和基本操作

一、简介 Elasticsearch 是一个分布式、RESTful 风格的搜索和数据分析引擎&#xff0c;支持各种数据类型&#xff0c;包括文本、数字、地理、结构化、非结构化 ,可以让你存储所有类型的数据&#xff0c;能够解决不断涌现出的各种用例。其构成如下&#xff1a; 说明&#xff1…

Python数学建模学习-PageRank算法

1-基本概念 PageRank算法是由Google创始人Larry Page在斯坦福大学时提出&#xff0c;又称PR&#xff0c;佩奇排名。主要针对网页进行排名&#xff0c;计算网站的重要性&#xff0c;优化搜索引擎的搜索结果。PR值是表示其重要性的因子。 中心思想&#xff1a; 数量假设&#…

创领“浆”来:三一重工特种砂浆站引领行业绿色高效新纪元

随着我国城市化进程不断加快&#xff0c;国家对城市建设高度关注&#xff0c;国务院办公厅针对城镇老旧小区基础设施匮乏、住房条件落后、环境污染严重等突出问题印发了《关于全面推进城镇老旧小区改造工作的指导意见》&#xff0c;各地积极响应&#xff0c;因此特种砂浆也迎来…

【微信取证篇】微信收藏图片存储记录思维导图

【微信取证篇】微信收藏图片存储记录思维导图 最近在测试微信收发图片和收藏的功能&#xff0c;发现许多有意思的地方&#xff0c;**微信收藏图片缓存的文件目前发现有三个地方&#xff0c;都是在Fav下&#xff0c;名称都一样&#xff0c;有直接原始图片&#xff0c;也有加密的…

2024年nodejs调用小红书最新关注(粉丝)follow接口,api接口分析2004-04-16

一、打开chrome按f12&#xff0c;点击右上角的“关注”按钮&#xff0c;抓包位置如下&#xff1a; (图1 follow接口) 二、follow接口分析 1、请求地址 https://edith.xiaohongshu.com/api/sns/web/v1/user/follow 2、请求方法: POST 3、请求头&#xff1a; :authority: edith…

telnet不是内部或外部命令也不是可运行的程序或批处理文件

出现问题 在Windows命令行运行telnet命令&#xff0c;出现&#xff1a; ‘telnet’ 不是内部或外部命令&#xff0c;也不是可运行的程序&#xff0c;或批处理文件。 问题原因 Windows系统中的telnet客户端是关闭状态。因为Win10默认没有安装telnet功能。 解决方式 将系统中…

FPGA - 以太网UDP通信(一)

一&#xff0c;简述以太网 以太网简介 ​以太网是一种计算机局域网技术。IEEE组织的IEEE 802.3标准制定了以太网的技术标准&#xff0c;它规定了包括物理层的连线、电子信号和介质访问层协议的内容。 ​ 以太网类型介绍 以太网是现实世界中最普遍的一种计算机网络。以太网有…

[C++][算法基础]二分图的最大匹配(匈牙利算法)

给定一个二分图&#xff0c;其中左半部包含 n1 个点&#xff08;编号 1∼n1&#xff09;&#xff0c;右半部包含 n2 个点&#xff08;编号 1∼n2&#xff09;&#xff0c;二分图共包含 m 条边。 数据保证任意一条边的两个端点都不可能在同一部分中。 请你求出二分图的最大匹配…

Intel显卡驱动导致Qt opengl 渲染YUV时拉伸窗口内存泄漏

最近在使用QOpenGLWidget做YUV视频渲染&#xff0c;发现在拉伸窗口的时候内存暴涨&#xff0c;如果窗口不动则内存不变。 可以得出结论一定是resizeGL出了问题&#xff0c;但是其实这里代码很简单 glViewport(0, 0, w, h); 还有就是变换矩阵计算&#xff0c;根本没资源建立与释…

Sublime Text下载,安装,安装插件管理器,下载汉化插件

SublimeTest官网 © Sublime Text中文网 下载安装 一路点击安装即可 安装插件管理器 管理器官网安装 - 包控制 (packagecontrol.io) 手动安装将3 位置点击网址下载 再打开SublimeTest 点击 选择第一个Browse Packages..... 将会跳转到文件夹中 进入上一个文件夹 在进入…