【SpringMVC】REST(Representation State Transfer)ful开发

REST全称Representation State Transfer,表现形式状态转换

文章目录

  • 1. 为什么提出了REST?
  • 2. RESTful入门案例
    • 案例代码
    • 修改请求方式
      • 修改成RESTful风格,并以POST方式提交
    • RESTful格式下传参
    • RESTful入门案例总结
    • @RequestBody,@RequestParam,@PathVariable总结
  • 3. RESTful快速开发
    • 第一次修改
    • 第二次修改
    • 快速开发注解总结
  • 4. RESTful案例开发
    • 案例代码(一些config的设定和domain等)
    • 后台Controller的开发

1. 为什么提出了REST?

传统风格资源描述形式:

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

REST风格描述形式:

  • http://localhost/user/1
  • http://localhost/user

REST风格优点:

  • 隐藏资源的访问行为,无法通过地址得知对资源是何种操作(REST风格描述的第二项既可以描述一个saveUser操作,也可以描述一个updateUser操作)
  • 书写简化

按照REST风格访问资源时使用行为动作区分对资源进行了何种操作,根据REST风格对资源进行访问称为RESTful

地址作用行为动作
http://localhost/users查询全部用户信息GET (查询)
http://localhost/user/1查询指定用户信息GET (查询)
http://localhost/users添加用户信息POST (新增/保存)
http://localhost/users修改用户信息PUT (修改/更新)
http://localhost/users/1删除用户信息DELETE (删除)

注: 上述行为是约定方式,约定不是规范,可以打破,所以称REST风格,而不是REST规范
描述模块的名称通常使用复数,也就是加s的格式描述,表示此类资源,而非单个资源,例如:users、books、accounts

2. RESTful入门案例

案例代码

config/ServletContainerInitConfig.java

package com.demo.config;import org.apache.ibatis.jdbc.Null;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;import javax.servlet.Filter;public class ServletContainerInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {@Overrideprotected Class<?>[] getRootConfigClasses() {return new Class[0];}@Overrideprotected Class<?>[] getServletConfigClasses() {return new Class[]{SpringMvcConfig.class};}@Overrideprotected String[] getServletMappings() {return new String[]{"/"};}@Overrideprotected Filter[] getServletFilters() {CharacterEncodingFilter filter = new CharacterEncodingFilter();filter.setEncoding("UTF-8");return new Filter[]{filter};}
}

config/SpringMvcConfig.java

package com.demo.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;@Configuration
@ComponentScan("com.demo.controller")
@EnableWebMvc
public class SpringMvcConfig {
}

controller/BookController.java

package com.demo.controller;import com.demo.domain.Book;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;@Controller
public class BookController {@RequestMapping(value = "/books", method = RequestMethod.POST)@ResponseBodypublic String save(@RequestBody Book book){System.out.println("book save ...");return "{'module': 'book save'}";}@RequestMapping(value = "/books", method = RequestMethod.DELETE)@ResponseBodypublic String delete(@PathVariable Integer id){System.out.println("book delete ..." + id);return "{'module': 'book delete'}";}@RequestMapping(value = "/books", method = RequestMethod.PUT)@ResponseBodypublic String update(@RequestBody Book book){System.out.println("book update ..." + book);return "{'module': 'book update'}";}@RequestMapping(value = "/books/{id}", method = RequestMethod.GET)@ResponseBodypublic String getById(@PathVariable Integer id){System.out.println("book getById ..." + id);return "{'module': 'book getById'}";}@RequestMapping(value = "/books", method = RequestMethod.GET)@ResponseBodypublic String getAll(){System.out.println("book getAll ...");return "{'module': 'book update'}";}
}

controller/UserController.java

package com.demo.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;@Controller
public class UserController {@RequestMapping("/save")@ResponseBodypublic String save(){System.out.println("User save...");return "{'module': 'springmvc'}";}@RequestMapping("/delete")@ResponseBodypublic String delete(Integer id){System.out.println("User delete..." + id);return "{'module': 'springmvc'}";}@RequestMapping("/update")@ResponseBodypublic String update(@RequestBody User user){System.out.println("User update... => " + user);return "{'module': 'springmvc'}";}
}

domain/User.java

package com.demo.domain;public class User {private String name;private int age;Address address;@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +", address=" + address +'}';}public Address getAddress() {return address;}public void setAddress(Address address) {this.address = address;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}

domain/Book.java

package com.demo.domain;public class Book {String bookName;String issn;@Overridepublic String toString() {return "Book{" +"bookName='" + bookName + '\'' +", issn='" + issn + '\'' +'}';}public String getBookName() {return bookName;}public void setBookName(String bookName) {this.bookName = bookName;}public String getIssn() {return issn;}public void setIssn(String issn) {this.issn = issn;}
}

修改请求方式

测试一下UserController中的三个方法:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

修改成RESTful风格,并以POST方式提交

将两个方法上的@RequestMapping注解,均新增一个method属性,并修改value属性,如下:

@RequestMapping(value = "/users", method = RequestMethod.POST)
@RequestMapping(value = "/users", method = RequestMethod.DELETE)
@RequestMapping(value = "/users", method = RequestMethod.PUT)

再运行,发现可以运行(注意,Postman中请求的模式要记得修改):
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

RESTful格式下传参

我们的delete方法中是有参数的,那在RESTful风格下,我们的路径是localhost/delete/1,那这个1怎么传到方法中的id里呢?
应该在路径后面接上{variable name}来表示我们想要传递的参数,这里variable name填写的应该是方法中的参数名;并在方法的参数前面使用@PathVariable注解声明该变量来自路径。例如:

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

但对于像Update方法中这种传User这种POJO数据(注意 Integer不算POJO数据)的,则不需要做改动
修改后请求delete方法如下
在这里插入图片描述
请求update方法仍然是将JSON数据转换为POJO,
在这里插入图片描述

RESTful入门案例总结

想要使用RESTful风格,步骤如下:

  1. 设定http请求动作(动词),如Request.POST, Request.PUT, Request.GET, Request.Delete等
  2. 设定请求参数(路径变量),在请求路径中使用{variable name}添加请求参数,方法中的参数前使用@PathVariable进行注解

@RequestBody,@RequestParam,@PathVariable总结

区别:

  • @RequestBody用于接收JSON数据
  • @RequestParam用于接收url地址或表单传参
  • @PathVariable用于接收路径参数,使用{参数名称}描述路径参数

应用:

  • 后期开发中,发送请求参数超过1个时,以JSON格式为主,@RequestBody应用较广
  • 发送非JSON格式数据,选用@RequestParam接收请求参数
  • 采用RESTful开发,当参数量较少时,例如1个,可以采用@PathVariable接收请求路径变量,通常用于传递id值。当然也可以通过@PathVariable注解接收多个请求路径变量,但多个变量主要还是用JSON

3. RESTful快速开发

入门案例中存在一个问题,如下(下边以BookController为例讲解),红框中内容重复,应该简化掉:
在这里插入图片描述

第一次修改

针对于这个问题,我们首先可以将@RequestMapping作为类注解写在类上,@ResponseBody也可以作为类注解写在类上。但有一个更简便的办法:@RestController注解包含了@Controller@ResponseBody,最终修改如下:

package com.demo.controller;import com.demo.domain.Book;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;@RequestMapping("books")
@RestController
public class BookController {@RequestMapping(method = RequestMethod.POST)public String save(@RequestBody Book book){System.out.println("book save ...");return "{'module': 'book save'}";}@RequestMapping(method = RequestMethod.DELETE)public String delete(@PathVariable Integer id){System.out.println("book delete ..." + id);return "{'module': 'book delete'}";}@RequestMapping(method = RequestMethod.PUT)public String update(@RequestBody Book book){System.out.println("book update ..." + book);return "{'module': 'book update'}";}@RequestMapping(method = RequestMethod.GET)public String getById(@PathVariable Integer id){System.out.println("book getById ..." + id);return "{'module': 'book getById'}";}@RequestMapping(method = RequestMethod.GET)public String getAll(){System.out.println("book getAll ...");return "{'module': 'book update'}";}
}

第二次修改

修改完以后,代码里又存在大量的@RequestMapping(method=...),也挺冗余的,可以做如下修改:
@RequestMapping(method = RequestMethod.xxx)替换成@xxxMapping
如果在@RequestMapping中还有表示参数的value,就在@xxxMapping后加上(参数路径),比如@xxxMapping("/{id}")
所有代码再次修改如下:

package com.demo.controller;import com.demo.domain.Book;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;@RequestMapping("books")
@RestController
public class BookController {@PostMappingpublic String save(@RequestBody Book book){System.out.println("book save ...");return "{'module': 'book save'}";}@DeleteMapping("/{id}")public String delete(@PathVariable Integer id){System.out.println("book delete ..." + id);return "{'module': 'book delete'}";}@PutMappingpublic String update(@RequestBody Book book){System.out.println("book update ..." + book);return "{'module': 'book update'}";}@GetMapping("/{id}")public String getById(@PathVariable Integer id){System.out.println("book getById ..." + id);return "{'module': 'book getById'}";}@GetMappingpublic String getAll(){System.out.println("book getAll ...");return "{'module': 'book update'}";}
}

逐项进行测试:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
控制台输出:
在这里插入图片描述

快速开发注解总结

  1. @RestController:类注解,在控制器类上方进行定义,设置当前控制器为RESTful风格,等同于@Controller@ResponseBody两个注解组合功能
  2. @GetMapping,@PostMapping,@PutMapping,@DeleteMapping:方法注解,注解在SpringMVC的RESTful开发控制器方法上方,其作用是设置当前控制器方法访问路径与请求动作,每种对应一个请求动作

4. RESTful案例开发

我们在这个案例下的目标是通过RESTful实现案例交互:发送RESTful请求,获取数据后在页面中展示结果

案例代码(一些config的设定和domain等)

config/SevletContainerInitConfig.java

package com.demo.config;import org.apache.ibatis.jdbc.Null;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;import javax.servlet.Filter;public class ServletContainerInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {@Overrideprotected Class<?>[] getRootConfigClasses() {return new Class[0];}@Overrideprotected Class<?>[] getServletConfigClasses() {return new Class[]{SpringMvcConfig.class};}@Overrideprotected String[] getServletMappings() {return new String[]{"/"};}@Overrideprotected Filter[] getServletFilters() {CharacterEncodingFilter filter = new CharacterEncodingFilter();filter.setEncoding("UTF-8");return new Filter[]{filter};}
}

config/SpringMvcConfig.java

package com.demo.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;@Configuration
@ComponentScan("com.demo.controller")
@EnableWebMvc
public class SpringMvcConfig {
}

domain/Book.java

package com.demo.domain;public class Book {private Integer id;private String type;private String name;private String 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;}
}

后台Controller的开发

写一个save方法和一个getAll方法

package com.demo.controller;import com.demo.domain.Book;
import org.springframework.web.bind.annotation.*;import java.util.ArrayList;
import java.util.List;@RestController
@RequestMapping("/books")
public class BookController {@PostMappingpublic String save(@RequestBody Book book){System.out.println("book save ==> " + book);return "{'module':'book save success'}";}@GetMappingpublic List<Book> getAll(){Book book1 = new Book();book1.setType("计算机");book1.setName("SpringMVC1111");book1.setDescription("小试牛刀");Book book2 = new Book();book2.setType("计算机");book2.setName("SpringMvc2222");book2.setDescription("一代宗师");List<Book> bookList = new ArrayList<>();bookList.add(book1);bookList.add(book2);return bookList;}}

启动Tomcat容器进行测试
在这里插入图片描述
在这里插入图片描述
前端使用了ElementUI+Vue,但是我目前不太记得这个东西了(等我弄清楚了再来这里补充),可以先转去视频,里边有很详细的介绍完整的案例开发:Bilibili-基于RESTful的页面数据交互

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

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

相关文章

Redis-运维

转自 极客时间 Redis 亚风 原文视频&#xff1a;https://u.geekbang.org/lesson/535?article681062 Redis 同步 Redis主从数据同步,主从第⼀次同步是全量同步 replicaof 主机 端口 #当前这个机器做Master的备份master如何判断slave是不是第⼀次来同步数据&#xff1a; Repl…

第11章 GUI Page400~402 步骤二 画直线

运行效果&#xff1a; 源代码&#xff1a; /**************************************************************** Name: wxMyPainterApp.h* Purpose: Defines Application Class* Author: yanzhenxi (3065598272qq.com)* Created: 2023-12-21* Copyright: yanzhen…

谷歌推大语言模型VideoPoet:文本图片皆可生成视频和音频

Google Research最近发布了一款名为VideoPoet的大型语言模型&#xff08;LLM&#xff09;&#xff0c;旨在解决当前视频生成领域的挑战。该领域近年来涌现出许多视频生成模型&#xff0c;但在生成连贯的大运动时仍存在瓶颈。现有领先模型要么生成较小的运动&#xff0c;要么在生…

蓝桥杯 1223 第 2 场 小白入门赛

蓝桥小课堂-平方和 模拟 1 2 2 2 3 2 ⋯ n 2 n ⋅ ( n 1 ) ⋅ ( 2 n 1 ) 6 1^22^23^2\cdotsn^2\dfrac{n\;\cdot\;(n 1)\;\cdot\;(2n1)}{6} 122232⋯n26n⋅(n1)⋅(2n1)​。 write(n * (n 1) * (n * 2 1) / 6);房顶漏水啦 m a x ( 最大的行 − 最小的行 , 最大的列 −…

九:爬虫-MongoDB基础

MongoDB介绍 MongoDB是一个介于关系数据库和非关系数据库之间的产品&#xff0c;是非关系数据库当中功能最丰富&#xff0c;最像关系数据库的。它支持的数据结构非常松散&#xff0c;因此可以存储比较复杂的数据类型。Mongo最大的特点是它支持的查询语言非常强大&#xff0c;其…

Tomcat与Netty比较

Tomcat介绍Tomcat支持的协议Tomcat的优缺点Netty介绍Netty支持的协议Netty的优点和缺点Tomcat和Netty的区别Tomcat和Netty的应用场Tomcat和Netty来处理大规模并发连接的优化Tomcat与Netty的网络模型的区别Tomcat与Netty架构设计拓展 Tomcat介绍 Tomcat是一个免费的、开放源代码…

JavaOOP篇----第十五篇

系列文章目录 文章目录 系列文章目录前言一、有没有可能两个不相等的对象有相同的hashcode二、拷贝和浅拷贝的区别是什么?三、static都有哪些用法?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通…

RabbmitMQ基础

RabbmitMQ基础 1.1 什么是MQ MQ(Message Queue)&#xff0c;从字面意思看&#xff0c;本质是个队列&#xff0c;FIFO先入先出&#xff0c;队列中存放的是message。是一种跨进程的通信机制&#xff0c;用于上下游传递消息。在互联网架构中&#xff0c;MQ是一种非常常见的上下游…

10 NAT网络地址转换

广域网技术 上面聊的内容都是内网的一些配置&#xff0c;但内网终将要访问外网的&#xff0c;我们需要怎么处理呢&#xff1f;一般使用HDLC&#xff08;高级数据链路控制协议&#xff09;或者PPP&#xff08;点对点协议&#xff09;。 使用PPP安全接入Internet PPP&#xff0…

PHP函数定义和分类

函数的含义和定义格式 在PHP中&#xff0c;允许程序员将常用的流程或者变量等组件组织成一个固定的格式实现特定功能&#xff0c;也就是说函数是具有特定功能特定格式的代码段。 函数的定义格式如下&#xff1a; function 函数名(参数1&#xff0c;参数2&#xff0c;参数n) {…

基于SSM的双减后初小教育课外学习生活活动平台的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

ESP8266网络相框采用TFT_eSPI库TJpg_Decoder库mixly库UDP库实现图片传送

用ESP8266和TFT_ESPI模块来显示图片数据。具体来说&#xff0c;我们将使用ILI9431显示器作为显示设备&#xff0c;并通过UDP协议将图片数据从发送端传输到ESP8266。最后&#xff0c;我们将解析这些数据并在TFT屏幕上显示出来。在这个过程中&#xff0c;我们将面临一些编程挑战&…

STM32 支持IAP的bootloader开发,使用串口通过Ymodem协议传输固件

资料下载: https://download.csdn.net/download/vvoennvv/88658447 一、概述 关于IAP的原理和Ymodem协议&#xff0c;本文不做任何论述&#xff0c;本文只论述bootloader如何使用串口通过Ymodem协议接收升级程序并进行IAP升级&#xff0c;以及bootloader和主程序两个工程的配置…

最常见的SQL报错注入函数(floor、updatexml、extractvalue)及payload总结

SQL报错注入是一种常见的SQL注入攻击方式&#xff0c;攻击者通过注入恶意代码&#xff0c;触发数据库的错误响应&#xff0c;并从错误信息中获取有用的信息。 下面介绍最常见的三个报错注入函数用法及payload总结&#xff1a; 1、floor() 使用floor报错注入&#xff0c;需要…

Centos 7.9安装Oracle19c步骤亲测可用有视频

视频介绍了在虚拟机安装centos 7.9并安装数据库软件的全过程 视频链接&#xff1a;https://www.zhihu.com/zvideo/1721267375351996416 下面的文字描述是安装数据库的部分介绍 一.安装环境准备 链接&#xff1a;https://pan.baidu.com/s/1Ogn47UZQ2w7iiHAiVdWDSQ 提取码&am…

Java经典框架之Spring

Java经典框架之Spring Java 是第一大编程语言和开发平台。它有助于企业降低成本、缩短开发周期、推动创新以及改善应用服务。如今全球有数百万开发人员运行着超过 51 亿个 Java 虚拟机&#xff0c;Java 仍是企业和开发人员的首选开发平台。 课程内容的介绍 1. Spring简介 2.…

T-Dongle-S3开发笔记——相关配置

portTICK_PERIOD_MS设置 Flash配置 Flash SPI mode 默认是DIO&#xff0c;改为QIO (W25Q128支持QIO) DIO与QIO区别&#xff1a; esp8266&#xff0c;esp32中的SPI FLASH 访问模式&#xff08;QIO QOUT DIO DOUT&#xff09;_qio dio-CSDN博客 Dual SPI:MOSI 和 MISO 引脚…

等腰三角形两底角相等

等腰三角形定义: 是指至少有两边相等的三角形。相等的两个边称为这个三角形的腰 二.证明 有等腰△ABC,AB和AC是腰,p是BC的中点 证明等腰三角形两底角相等 即 ∠ A B P ∠ P C A ∠ABP∠PCA ∠ABP∠PCA ∴ ∴ ∴ 三角形内角和为180 ∵ { ∠ A B P ∠ A P B ∠ B A P 180 …

什么是视频号小店?怎么开通,上架产品,一篇详解!

大家好&#xff0c;我是电商糖果 一个做了七年电商的95后&#xff0c;现居河南郑州。 混迹互联网多年&#xff0c;电商圈的gai溜子&#xff0c;偶尔会抽抽风。 这篇文章分享的内容是糖果在2022年做的电商项目——视频号小店。 因为它是刚出来的&#xff0c;很多人对此不是很…

leetcode 1576. 替换所有的问号(easy)(优质解法)

链接&#xff1a;1576. 替换所有的问号 代码&#xff1a; class Solution {public String modifyString(String s) {char[] charSs.toCharArray();int lengthcharS.length;//遍历找到 &#xff1f;for(int i0;i<length;i){if(charS[i]?){//遍历 a ~ z 选择一个合适的字符来…