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

news2025/2/6 10:13:31

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 {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[0];
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    @Override
    protected 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)
    @ResponseBody
    public String save(@RequestBody Book book){
        System.out.println("book save ...");
        return "{'module': 'book save'}";
    }

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

    @RequestMapping(value = "/books", method = RequestMethod.PUT)
    @ResponseBody
    public String update(@RequestBody Book book){
        System.out.println("book update ..." + book);
        return "{'module': 'book update'}";
    }

    @RequestMapping(value = "/books/{id}", method = RequestMethod.GET)
    @ResponseBody
    public String getById(@PathVariable Integer id){
        System.out.println("book getById ..." + id);
        return "{'module': 'book getById'}";
    }

    @RequestMapping(value = "/books", method = RequestMethod.GET)
    @ResponseBody
    public 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")
    @ResponseBody
    public String save(){
        System.out.println("User save...");
        return "{'module': 'springmvc'}";
    }

    @RequestMapping("/delete")
    @ResponseBody
    public String delete(Integer id){
        System.out.println("User delete..." + id);
        return "{'module': 'springmvc'}";
    }

	@RequestMapping("/update")
    @ResponseBody
    public 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;

    @Override
    public 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;

    @Override
    public 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 {

    @PostMapping
    public 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'}";
    }

    @PutMapping
    public 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'}";
    }

    @GetMapping
    public 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 {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[0];
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    @Override
    protected 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;

    @Override
    public 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 {

    @PostMapping
    public String save(@RequestBody Book book){
        System.out.println("book save ==> " + book);
        return "{'module':'book save success'}";
    }

    @GetMapping
    public 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.coloradmin.cn/o/1327942.html

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

相关文章

【高效开发工具系列】eclipse部署web项目

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Go 随机密码

一.Go实现随机密码 随机密码 package mainimport ("fmt""math/rand""os""strconv""time" )func RandomPassword(num int) {length : numif len(os.Args) > 1 {arg : os.Args[1]i, err : strconv.ParseInt(arg, 10, 6…

LeetCode做题总结 1. 两数之和

1. 两数之和 暴力法哈希法重新分析Java语法 暴力法 2023.09.20 刚开始用暴力法破解&#xff08;C&#xff09; class Solution { public:vector<int> twoSum(vector<int>& nums, int target) {vector<int> a;for(int i0; i<nums.size()-1; i) {for(…

flink watermark 实例分析

WATERMARK 定义了表的事件时间属性&#xff0c;其形式为: WATERMARK FOR rowtime_column_name AS watermark_strategy_expression rowtime_column_name 把一个现有的列定义为一个为表标记事件时间的属性。该列的类型必须为 TIMESTAMP(3)/TIMESTAMP_LTZ(3)&#xff0c;且是 sche…

pdf 在线编辑

https://smallpdf.com/edit-pdf#rapp 参考 https://zh.wikihow.com/%E5%B0%86%E5%9B%BE%E5%83%8F%E6%8F%92%E5%85%A5PDF

网络基础篇【网线的制作,OSI七层模型,集线器和交换机的介绍,路由器的介绍与设置】

目录 一、网线制作 1.1 工具介绍 1.1.1网线 1.1.2 网线钳 1.1.3 水晶头 1.1.4 网线测试仪 二、OSI七层模型 2.1 简介 2.2 OSI模型层次介绍 2.2.1 结构图 2.2.2 数据传输过程 2.3 相关网站 二、集线器 2.1 介绍 2.2 适用场景 三、交换机 3.1 介绍 3.2 适用场景…

【Java】Mac下的Tomcat安装配置

&#x1f514;Tomcat是一个免费的开源web应用服务器&#xff0c;是开发和调试JSP 程序的首选&#x1f590;可利用它响应HTML页面的访问请求。 我们在进行网络编程时&#xff0c;其中重要的中间件就是Tomcat&#xff0c;下面我们将进行在Mac上配置Tomcat的讲解。&#x1f632; …

医院影像科PACS系统源码,医学影像系统,支持MPR、CPR、MIP、SSD、VR、VE三维图像处理

PACS系统是医院影像科室中应用的一种系统&#xff0c;主要用于获取、传输、存档和处理医学影像。它通过各种接口&#xff0c;如模拟、DICOM和网络&#xff0c;以数字化的方式将各种医学影像&#xff0c;如核磁共振、CT扫描、超声波等保存起来&#xff0c;并在需要时能够快速调取…

Redis-学习笔记

Remote Dictionary Server(Redis) 是一个开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存、分布式、可选持久性的键值对(Key-Value)存储数据库&#xff0c;并提供多种语言的 API&#xff0c;是跨平台的非关系型数据库。 Redis 通常被称为数据结构服务器&…

自媒体新手如何写出爆款公众号文章

今天跟大家分享一下&#xff0c;作为新手怎么样写出一篇阅读量过万的公众号的文章。 我的公众号是从2020年开始写的&#xff0c;写到今天差不多三年多一点。然后现在的粉丝数虽然不多&#xff0c;但也差不多近两千个了。 我这三年多差不多更新了150篇原创文章。刚开始的时候写的…

【谭浩强C程序设计精讲 2】整型数据

文章目录 3.3 整型数据3.3.1 整型常量的表示方法3.3.2 整型变量1. 整型数据在内存中的存放形式2. 整型变量的分类3. 整型变量的定义4. 整型数据的溢出 3.3.3 整型常量的类型 3.3 整型数据 3.3.1 整型常量的表示方法 整型常量即整常数。C 的整常数可以用以下三种形式表示&…

ISA95 及工业互联网平台

ISA95简称S95&#xff0c;是美国仪表、系统和自动化协会&#xff08;ISA&#xff09;在95年提出来的&#xff0c;也是这个协会启动编制的第95个标准项目。它定义了企业商业和控制系统之间的集成&#xff0c;主要可以分成三个层次&#xff1a; 第0&#xff0c;1&#xff0c;2层…

Ubuntu 常用命令之 fdisk 命令用法介绍

&#x1f4d1;Linux/Ubuntu 常用命令归类整理 fdisk 是一个用于处理磁盘分区的命令行工具&#xff0c;它在 Linux 系统中广泛使用。fdisk 命令可以创建、删除、更改、复制和显示硬盘分区&#xff0c;以及更改硬盘的分区 ID。 fdisk 命令的常用参数如下 -l&#xff1a;列出所…

jmx_exporter安装

下载 wget https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/0.13.0/jmx_prometheus_javaagent-0.13.0.jar 创建jmx_exporter.yml文件 文件内容为&#xff1a; rules: - pattern: ".*" 配置tomcatpinter/apache-tomcat-8.5.38/bin/ca…

模型评估方法

目录 数据集切分 交叉验证 交叉验证实例 混淆矩阵 实例 代码实现 阈值 全局阈值处理 自适应阈值处理 阈值对结果的影响 ROC曲线 数据集切分 数据集切分是指将一个数据集分割成训练集和测试集的过程。常用的方法是随机切分&#xff0c;即将数据集中的样本按照一定比…

计算机存储术语: 扇区,磁盘块,页

扇区(sector) 硬盘的读写以扇区为基本单位。磁盘上的每个磁道被等分为若干个弧段&#xff0c;这些弧段称之为扇区。硬盘的物理读写以扇区为基本单位。通常情况下每个扇区的大小是 512 字节。linux 下可以使用 fdisk -l 了解扇区大小&#xff1a; $ sudo /sbin/fdisk -l Disk …

B/S医院手术麻醉临床管理系统源码 手术申请、手术安排

手术麻醉系统概述 手术室是医院各个科室工作交叉汇集的一个重要中心&#xff0c;在时间、空间、设备、药物、材料、人员调配的科学管理、高效运作、安全质控、绩效考核&#xff0c;都十分重要。手术麻醉管理系统&#xff08;Operation Anesthesia Management System&#xff0…

vue 简单实现购物车:商品基础信息最终的 html 文件 + 商品计数器的组件处理,实现了购物车;

购物车实现过程&#xff1a; Ⅰ、商品购物车作业需求&#xff1a;1、商品购物车页面示例&#xff1a;2、具体需求&#xff1a; Ⅱ、html 文件的构建&#xff1a;商品购物车.html Ⅲ、组件文件的构建&#xff1a;商品购物车1.js Ⅳ、小结&#xff1a; Ⅰ、商品购物车作业需求&am…

百度侯震宇详解:大模型将如何重构云计算?

12月20日&#xff0c;在2023百度云智大会智算大会上&#xff0c;百度集团副总裁侯震宇以“大模型重构云计算”为主题发表演讲。他强调&#xff0c;AI原生时代&#xff0c;面向大模型的基础设施体系需要全面重构&#xff0c;为构建繁荣的AI原生生态筑牢底座。 侯震宇表示&…

.Net Core webapi RestFul 统一接口数据返回格式

在RestFul风格盛行的年代&#xff0c;大部分接口都需要一套统一的数据返回格式&#xff0c;那么我们怎么才能保证使用统一的json数据格式返回呢&#xff0c;下面给大家简单介绍一下&#xff1a; 假如我们需要接口统一返回一下数据格式&#xff1a; {"statusCode": …