【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.mzph.cn/news/239467.shtml

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

相关文章

Linux下编写zlg7290驱动(3)-键盘驱动编写

2.3. 数据处理实现 执行上述代码后系统中就注册了我们的input设备&#xff0c;接下来我们要做的是活得键盘的键值&#xff0c;zlg7290多可以支持64个按键&#xff0c;每个按键按下后都会产生一个中断&#xff0c;我们写驱动是可以使用轮询不断检测是否有按键也可以触发中断来判…

云原生之深入解析基于FunctionGraph在Serverless领域的FinOps的探索和实践

一、背景 Serverless 精确到毫秒级的按用付费模式使得用户不再需要为资源的空闲时间付费。然而&#xff0c;对于给定的某个应用函数&#xff0c;由于影响其计费成本的因素并不唯一&#xff0c;使得用户对函数运行期间的总计费进行精确的事先估计变成了一项困难的工作。以传统云…

git分支解析

1、概述和优点 在版本控制过程中&#xff0c;同时会推进多个任务&#xff0c;为此&#xff0c;就可以为每个任务创建单独的分支。开发人员可以把自己的任务和主线任务分离开来&#xff0c;在开发自己的分支的时候不会影响主分支。 分支的好处&#xff1a; 同时推进多个功能开发…

CSS自适应分辨率 amfe-flexible 和 postcss-pxtorem:Webpack5 升级后相关插件和配置更新说明

前言 项目对应的 webpack5 版本如下&#xff1a; npm i webpack5.89.0 -D npm i webpack-cli5.1.4 -D升级插件 说明一下&#xff0c;我更喜欢固定版本号&#xff0c;这样随机bug会少很多&#xff0c;更可控~ npm i postcss-loader6.1.1 -D npm i postcss-pxtorem6.0.0 -D配…

Postman创建及删除workspace工作空间

文章目录 一、Postman创建workspace工作空间二、Postman删除workspace工作空间 一、Postman创建workspace工作空间 打开Postman 点击 Workspaces → Create Workspaces 如图所示操作 工作空间创建完成 二、Postman删除workspace工作空间 点击 Workspaces → 选择要删除…

Milvus数据一致性介绍及选择方法

1、Milvus 时钟机制 Milvus 通过时间戳水印来保障读链路的一致性&#xff0c;如下图所示&#xff0c;在往消息队列插入数据时&#xff0c; Milvus 不光会为这些插入记录打上时间戳&#xff0c;还会不间断地插入同步时间戳&#xff0c;以图中同步时间戳 syncTs1 为例&#xff0…

uniapp使用colorUI

colorUI 微动画 | ColorUI 使用文档 1&#xff1a;把colorui里三个文件复制到自己项目中去 App.vue </script> <style> import url(colorui/icon.css); import url(colorui/main.css); import url("colorui/animation.css");-webkit-keyframes show {…

Struts2 S2-061 远程命令执行漏洞(CVE-2020-17530)复现

漏洞简介 Struts2框架是一个用于开发Java EE网络应用程序的开放源代码网页应用程序架构。它利用并延伸了Java Servlet API&#xff0c;鼓励开发者采用MVC架构。Struts2以WebWork优秀的设计思想为核心&#xff0c;吸收了Struts框架的部分优点&#xff0c;提供了一个更加整洁的MV…

心有暖阳,笃定前行,2024考研加油

2024考研学子&#xff0c;所有的付出终有收获&#xff0c;阳光终将穿透阴霾&#xff0c;终将上岸。 当曙光破晓的时候&#xff0c;你可曾记得那些星月为伴&#xff0c;孤独为友&#xff0c;理想为灯来指引前行之路的日子&#xff0c;那些默默扎根的日子终将化作星星在未来闪闪发…

Java项目-瑞吉外卖项目优化Day3

前后端分离开发 Yapi 是一个接口结合了接口测试、接口管理的管理平台&#xff0c;需要配置比较麻烦。看弹幕说用apifox更好用。可以将接口文档导出导入。 Swagger 注意下面的地址前面要有/。 效果&#xff1a; 可以在这里实现接口的测试&#xff0c;也可以导出文档等等。一般…

python+django教学质量评价系统o8x1z

本基于web的在线教学质量评价系统的设计与实现有管理员&#xff0c;教师&#xff0c;督导&#xff0c;学生一共四个角色。管理员功能有个人中心&#xff0c;学生管理&#xff0c;教师管理&#xff0c;督导管理&#xff0c;学生评价管理&#xff0c;课程信息管理&#xff0c;学生…

生产者和消费者模式

在一个系统中&#xff0c;存在生产者和消费者两种角色&#xff0c;他们通过内存缓冲区进行通信&#xff0c;生产者生产消费者需要的资料&#xff0c;消费者把资料做成产品。 最关键就是内存缓冲区为空的时候消费者必须等待&#xff0c;而内存缓冲区满的时候&#xff0c;生产者…

编译原理----算符优先级的分析(自底向上)

自底向上分析的分类如下所示&#xff1a; 算符优先分析 算符优先分析只规定算符之间的优先关系&#xff0c;也就是只考虑终结符之间的优先关系。 &#xff08;一&#xff09;若有文法G&#xff0c;如果G没有形如A->..BC..的产生式&#xff0c;其中B和C为非终结符&#xff…

springMVC-与spring整合

一、基本介绍 在项目开发中&#xff0c;spring管理的 Service和 Respository&#xff0c;SrpingMVC管理 Controller和ControllerAdvice,分工明确 当我们同时配置application.xml, springDispatcherServlet-servlet.xml , 那么注解的对象会被创建两次&#xff0c; 故…

freeswitch on debian docker

概述 freeswitch是一款简单好用的VOIP开源软交换平台。 因为centos系统期限的原因&#xff0c;尝试在debian的docker上使用fs。 环境 docker engine&#xff1a;Version 24.0.6 debian docker&#xff1a;bullseye 11.8 freeswitch&#xff1a;v1.10.7 Debian准备 目前…

Pycharm报的一些Python语法错误

Pycharm报的一些Python语法错误 1、PEP8:Expected 2 blank less:found 1 意思是&#xff1a;类和上面的行要间隔两行&#xff0c;现在只有一行 解决办法&#xff1a; 间隔2行 2、Remove redundant parentheses 意思是&#xff1a;删除多余的括号 解决&#xff1a;删掉外面括…

LSTM和GRU vs 普通的循环神经网络RNN

1、考虑下列三种情况下&#xff0c;对比一下普通RNN的表现和LSTM和GRU表现&#xff1a; &#xff08;1&#xff09;早期观测值对预测未来观测者具有非常重要的意义。 考虑一个极端情况&#xff0c;其中第一个观测值包含一个校验和&#xff0c; 目标是在序列的末尾辨别校验和是…

应用案例 | 汽车行业基于3D机器视觉引导机器人上下料解决方案

Part.1 背景 近年来&#xff0c;汽车行业蓬勃发展&#xff0c;一度出现供不应求的现象。在汽车零配件、整车大规模制造的过程中&#xff0c;为了降本增效&#xff0c;提升产品质量&#xff0c;工厂急需完成自动化升级。随着人工智能的发展&#xff0c;越来越多的生产环节引入机…

C++(多态)

目录 前言&#xff1a; 1.多态的概念 2.多态的定义及实现 2.1多态的构成条件 2.2析构函数的重写&#xff08;基类与派生类析构函数名字不同&#xff09; 2.3虚函数重写 2.4C override 和final 2.5 重载、覆盖&#xff08;重写&#xff09;隐藏&#xff08;重定义&#…

css 设备背景图片 宽高总是不能平铺

宽高总是宽大了 高就挤出去了&#xff1b;高设置了 宽度就变小了&#xff1b;疯掉的节奏。。。。。。 .center-bottom{background: url(/img/newpic/leftbg.png);background-repeat: no-repeat;width: 98%;height: 60%;background-position: center center;background-size: 1…