SpringMVC(07) -- RESTful

2023-10-30

SpringMVC学习笔记

源码地址

7.1)RESTful简介

REST:Representational State Transfer,表现层资源状态转移。

7.1.1)资源

资源是一种看待服务器的方式,即,将服务器看作是由很多离散的资源组成。每个资源是服务器上一个可命名的抽象概念。因为资源是一个抽象的概念,所以它不仅仅能代表服务器文件系统中的一个文件、数据库中的一张表等等具体的东西,可以将资源设计的要多抽象有多抽象,只要想象力允许而且客户端应用开发者能够理解。与面向对象设计类似,资源是以名词为核心来组织的,首先关注的是名词。一个资源可以由一个或多个URI来标识。URI既是资源的名称,也是资源在Web上的地址。对某个资源感兴趣的客户端应用,可以通过资源的URI与其进行交互。

7.1.2)资源的表述

资源的表述是一段对于资源在某个特定时刻的状态的描述。可以在客户端-服务器端之间转移(交换)。资源的表述可以有多种格式,例如HTML/XML/JSON/纯文本/图片/视频/音频等等。资源的表述格式可以通过协商机制来确定。请求-响应方向的表述通常使用不同的格式。

7.1.3)状态转移

状态转移说的是:在客户端和服务器端之间转移(transfer)代表资源状态的表述。通过转移和操作资源的表述,来间接实现操作资源的目的。

7.2)RESTful的实现

具体说,就是 HTTP 协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。

它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源。

REST 风格提倡 URL 地址使用统一的风格设计,从前到后各个单词使用斜杠分开,不使用问号键值对方式携带请求参数,而是将要发送给服务器的数据作为 URL 地址的一部分,以保证整体风格的一致性。

操作 传统方式 REST风格
查询操作 getUserById?id=1 user/1-->get请求方式
保存操作 saveUser user-->post请求方式
删除操作 deleteUser?id=1 deleteUser?id=1
更新操作 updateUser user-->put请求方式

7.2.1)RESTful的查询操作实现

在源码的工程 SpringMvcDemo3中,修改视图解析器springMVC.xml,代码如下:

    <!--3)配置视图控制器-->
    <!-- path:设置处理的请求地址  view-name:设置请求地址所对应的视图名称 -->
    <mvc:view-controller path="/" view-name="index"></mvc:view-controller>
    <mvc:view-controller path="/test_view" view-name="test_view"></mvc:view-controller>
    <mvc:view-controller path="/test_rest" view-name="test_rest"></mvc:view-controller>
    <!--开启mvc的注解驱动-->
    <mvc:annotation-driven />
</beans>

新建用户控制器UserController.java,代码如下:

@Controller
public class UserController {
    /**
     * 使用RESTFul模拟用户资源的增删改查
     * /user    GET     查询所有用户信息
     * /user/1    GET     根据用户id查询用户信息
     */
    @RequestMapping(value = "/user", method = RequestMethod.GET)
    public String getAllUser(){
        System.out.println("查询所有用户信息");
        return "success";
    }
​
    @RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
    public String getUserById(){
        System.out.println("根据id查询用户信息");
        return "success";
    }
}

新建页面test_rest.html,代码如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>RESTful示例</h1>
<a th:href="@{/user}">查询所有用户信息</a><br>
<a th:href="@{/user/1}">根据id查询用户信息</a><br>
</body>
</html>

测试:【配置Tomacat后启动工程,浏览器访问:http://localhost:8080/SpringMvcDemo3/test_rest】,点击超链接“查询所有用户信息”,页面跳转至:http://localhost:8080/SpringMvcDemo3/user,页面如下:

 控制台输出:

11:16:43.746 [http-nio-8080-exec-10] DEBUG org.springframework.web.servlet.DispatcherServlet - GET "/SpringMvcDemo3/user", parameters={}
11:16:43.756 [http-nio-8080-exec-10] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to com.study.mvc.controller.UserController#getAllUser()
查询所有用户信息
11:16:43.917 [http-nio-8080-exec-10] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 200 OK

点击超链接“根据id查询用户信息”,页面跳转至:http://localhost:8080/SpringMvcDemo3/user/1,页面如下:

 控制台输出:

11:18:33.397 [http-nio-8080-exec-6] DEBUG org.springframework.web.servlet.DispatcherServlet - GET "/SpringMvcDemo3/user/1", parameters={}
11:18:33.398 [http-nio-8080-exec-6] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to com.study.mvc.controller.UserController#getUserById()
根据id查询用户信息
11:18:33.401 [http-nio-8080-exec-6] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 200 OK

7.2.2)RESTful的保存操作实现

修改用户控制器UserController.java,代码如下:

    @RequestMapping(value = "/user", method = RequestMethod.POST)
    public String insertUser(String username, String password){
        System.out.println("添加用户信息:"+username+","+password);
        return "success";
    }

修改页面test_rest.html,代码如下:

<form th:action="@{/user}" method="post">
    用户名:<input type="text" name="username"><br>
    密码:<input type="password" name="password"><br>
    <input type="submit" value="添加"><br>
</form>

测试:【配置Tomacat后启动工程,浏览器访问:http://localhost:8080/SpringMvcDemo3/test_rest】,输入表单信息点击“添加”按钮,页面跳转至:http://localhost:8080/SpringMvcDemo3/user,页面如下:

 控制台输出:

11:28:17.061 [http-nio-8080-exec-10] DEBUG org.springframework.web.servlet.DispatcherServlet - POST "/SpringMvcDemo3/user", parameters={masked}
11:28:17.073 [http-nio-8080-exec-10] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to com.study.mvc.controller.UserController#insertUser(String, String)
添加用户信息:admin,3457675
11:28:17.217 [http-nio-8080-exec-10] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 200 OK

7.2.3)RESTful的更新操作实现

修改用户控制器UserController.java,代码如下:

    @RequestMapping(value = "/user", method = RequestMethod.PUT)
    public String updateUser(String username, String password) {
        System.out.println("修改用户信息:" + username + "," + password);
        return "success";
    }

修改页面test_rest.html,代码如下:

<form th:action="@{/user}" method="put">
    用户名:<input type="text" name="username"><br>
    密码:<input type="password" name="password"><br>
    <input type="submit" value="修改"><br>
</form>

测试:【配置Tomacat后启动工程,浏览器访问:http://localhost:8080/SpringMvcDemo3/test_rest】,输入表单信息点击“修改”按钮,页面跳转至:http://localhost:8080/SpringMvcDemo3/user?username=admin1&password=21353432,页面如下:

 控制台输出:【虽然页面执行更新方法put,但实际执行是查询方法get】

12:44:59.379 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.DispatcherServlet - GET "/SpringMvcDemo3/user?username=admin1&password=21353432", parameters={masked}
12:44:59.379 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to com.study.mvc.controller.UserController#getAllUser()
查询所有用户信息
12:44:59.382 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 200 OK

由于浏览器只支持发送get和post方式的请求,发送put和delete请求会默认执行get请求,为执行put和delete请求SpringMVC 提供了 HiddenHttpMethodFilter

7.2.3.1)HiddenHttpMethodFilter

SpringMVC 提供了 HiddenHttpMethodFilter将 POST 请求转换为 DELETE 或 PUT 请求;

HiddenHttpMethodFilter处理put和delete请求的条件:

  1. 当前请求的请求方式必须为post

  2. 当前请求必须传输请求参数_method

满足以上条件,HiddenHttpMethodFilter 过滤器就会将当前请求的请求方式转换为请求参数_method的值,因此请求参数_method的值才是最终的请求方式,在web.xml中注册HiddenHttpMethodFilter,代码如下:

    <!--1)配置编码过滤器-->
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
​
    <!--2)配置请求方式过滤器HiddenHttpMethodFilter-->
    <filter>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

目前为止,SpringMVC中提供了两个过滤器:CharacterEncodingFilter和HiddenHttpMethodFilter

在web.xml中注册时,必须先注册CharacterEncodingFilter,再注册HiddenHttpMethodFilter

原因:

  • 在 CharacterEncodingFilter 中通过 request.setCharacterEncoding(encoding) 方法设置字符集的

    request.setCharacterEncoding(encoding) 方法要求前面不能有任何获取请求参数的操作;

  • 而 HiddenHttpMethodFilter 恰恰有一个获取请求方式的操作:

String paramValue = request.getParameter(this.methodParam);

修改页面test_rest.html,代码如下:

<form th:action="@{/user}" method="post">
    <input type="hidden" name="_method" value="PUT">
    用户名:<input type="text" name="username"><br>
    密码:<input type="password" name="password"><br>
    <input type="submit" value="修改"><br>
</form>

测试:页面再次执行上述更新操作,控制台输出:【页面执行更新方法put,实际执行也为更新方法put】

12:53:26.668 [http-nio-8080-exec-9] DEBUG org.springframework.web.servlet.DispatcherServlet - PUT "/SpringMvcDemo3/user", parameters={masked}
12:53:26.674 [http-nio-8080-exec-9] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to com.study.mvc.controller.UserController#updateUser(String, String)
修改用户信息:admin1,21353432
12:53:26.849 [http-nio-8080-exec-9] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 200 OK

7.2.4)RESTful的删除操作实现

修改用户控制器UserController.java,代码如下:

    @RequestMapping(value = "/user", method = RequestMethod.DELETE)
    public String deleteUser(String username, String password) {
        System.out.println("删除用户信息:" + username + "," + password);
        return "success";
    }

修改页面test_rest.html,代码如下:

<form th:action="@{/user}" method="post">
    <input type="hidden" name="_method" value="DELETE">
    用户名:<input type="text" name="username"><br>
    密码:<input type="password" name="password"><br>
    <input type="submit" value="删除"><br>
</form>

测试:【配置Tomacat后启动工程,浏览器访问:http://localhost:8080/SpringMvcDemo3/test_rest】,输入表单信息点击“删除”按钮,页面跳转至:http://localhost:8080/SpringMvcDemo3/user,页面如下:

 控制台输出:【页面执行删除方法delete,实际执行也为删除方法delete】

13:01:10.693 [http-nio-8080-exec-7] DEBUG org.springframework.web.servlet.DispatcherServlet - DELETE "/SpringMvcDemo3/user", parameters={masked}
13:01:10.695 [http-nio-8080-exec-7] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to com.study.mvc.controller.UserController#deleteUser(String, String)
删除用户信息:admin3,2311241
13:01:10.841 [http-nio-8080-exec-7] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 200 OK

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SpringMVC(07) -- RESTful 的相关文章

  • 任务“:app:dexDebug”执行失败

    我目前正在处理我的项目 我决定将我的 Android Studio 更新到新版本 但在我导入项目后 它显示如下错误 Information Gradle tasks app assembleDebug app preBuild UP TO
  • Google 地图查询返回的 JSON 包含像 \x26 这样的编码字符(如何解码?)

    在 Java 应用程序中 我获取 JSON 来自 Google 地图 其中包含以下字符 x26我想将其转换为其原始字符 据我所知 这是一个 UTF 8 表示法 但我不完全确定 在源 JSON 中 可能会出现各种编码字符 例如 x3c div
  • 检查双精度值的等于和不等于条件

    我在比较两者时遇到困难double values using and 我创建了 6 个双变量并尝试进行比较If健康 状况 double a b c d e f if a b c d e f My code here in case of t
  • MI设备中即使应用程序被杀死,如何运行后台服务

    您好 我正在使用 alaram 管理器运行后台服务 它工作正常 但对于某些 mi 设备 后台服务无法工作 我使用了服务 但它无法工作 如何在 mi 中运行我的后台服务 MI UI有自己的安全选项 所以你需要的不仅仅是上面提到的粘性服务 你需
  • Java:从元素创建 DOM 元素,而不是文档

    如您所知 在 Java 中创建 Dom 元素的正确方法是执行以下操作 import org w3c dom Document import org w3c dom Element Document d Element e e d creat
  • JavaFX - setVisible 隐藏元素但不重新排列相邻节点

    在 JavaFX 中 如果我有一个场景有 2VBox元素和每个VBox有多个Label in it 如果我设置顶部VBox to 无形的 为什么底部VBox 不向上移动顶部的场景VBox was The VBox is 无形的但我希望其他物
  • spring - 强制 @Autowired 字段的 cglib 代理

    我有混合堆栈 EJB 和 Spring 为了将 Spring 自动装配到 EJB 我使用SpringBeanAutowiringInterceptor 不确定这是否会影响我遇到的问题 在尝试通过以下方式自动装配 bean 时 Scope p
  • 场景生成器删除 fxml 文件中的导入

    我使用场景构建器 Gluon Scene Builder JavaFX Scene Builder 8 1 1 来创建应用程序的 UI 并使用 Eclipse 开发 JavaFX 现在 每次我在场景生成器中保存某些内容时 它都会从 fxml
  • 如何将 XMP XML 块序列化为现有的 JPEG 图像?

    我有许多 JPEG 图像 其中包含损坏的 XMP XML 块 我可以轻松修复这些块 但我不确定如何将 固定 数据写回图像文件 我目前正在使用 JAVA 但我愿意接受任何能让这项任务变得容易的事情 这是目标关于 XMP XML 的另一个问题
  • 所有junit测试后的清理

    在我的项目中 我必须在所有测试之前进行一些存储库设置 这是使用一些棘手的静态规则来完成的 然而 在所有测试之后我不知道如何进行清理 我不想保留一些神奇的静态数字来引用所有测试方法的数量 我应该一直维护它 最受赞赏的方法是添加一些侦听器 该侦
  • 让JScrollPane控制多个组件

    对于我的应用程序 我正在设计一个脚本编辑器 目前我有一个JPanel其中包含另一个JPanel保存行号 位于左侧 以及JTextArea用于允许用户输入代码 位于右侧 目前 我已经实施了JScrollPane on the JTextAre
  • 不兼容的类型:在 java netbeans 中对象无法转换为 String

    我试图在我的项目中使用对象数组 但出现错误 incompatible types Object cannot be converted to String 在这一行 ST1 new String emt1 emt2 emt3 emt4 现在
  • OpenJDK 版本控制

    上下文 我想确保我们系统上安装的 Java 不受 CVE 2022 21449 的影响 java version 给出 openjdk version 11 0 7 2020 04 14 LTS OpenJDK Runtime Enviro
  • 如何在keycloak中动态编辑standalone.xml文件

    我正在尝试通过 docker 编辑standalone xml 并尝试添加 但 keycloak 正在使用它standalone xml 但我可以看到standalone xml 文件中的更改 我需要在standalone xml 文件中添
  • 在 Selenium WebDriver 上如何从 Span 标签获取文本

    在 Selenium Webdriver 上 如何从 span 标记检索文本并打印 我需要提取文本UPS Overnight Free HTML代码如下 div id customSelect 3 class select wrapper
  • ExceptionHandler 不适用于 Throwable

    我们的应用程序是基于 Spring MVC 的 REST 应用程序 我正在尝试使用 ExceptionHandler 注释来处理所有错误和异常 I have ExceptionHandler Throwable class public R
  • 阻止 OSX 变音符号为所有用户禁用 Java 中的 KeyBindings?

    注 我知道这个问题 https stackoverflow com questions 40335285 java keybinds stop working after holding down a key用户必须输入终端命令才能解决此问
  • Java 编码风格、局部变量与重复方法调用

    我更喜欢使用局部变量而不是多次调用同一方法 I prefer this Vehicle vehicle person getVehicle if vehicle instanceof Car Car car Car vehicle car
  • Java中有类似分支/跳转表的东西吗?

    Java有类似分支表或跳转表的东西吗 分支表或跳转表是 根据维基百科 http en wikipedia org wiki Branch table 用于描述使用分支指令表将程序控制 分支 转移到程序的另一部分 或可能已动态加载的不同程序
  • Java 推断泛型类型

    我正在寻找类似的推断捕获泛型类型的概念 类似于以下方法片段 但不是捕获泛型类型的类 public

随机推荐

  • JAVA代码实现抖音转载视频无水印视频,亲测通过

    许多小伙伴想做抖音视频 无奈没有摄影器材 也没有取景材料 就想着去用别人人气视频来提高自己的粉丝量 可问题又来了 别人的视频通过分享 或者链接根本不是原创 上面还带着水印 视频一挂上去就被发现了 小则视频不通过 给出警告 大则封号 降低视频
  • Linux centos8安装docker

    1 下载docker ce的repo curl https download docker com linux centos docker ce repo o etc yum repos d docker ce repo 2 安装依赖 yu
  • vue3实现导航栏绑定内容锚点+滚动动画

    目前用的两种方法实现 第一种 原生js实现 注意 因为移动端可滚动区域可能会嵌套在其他架子下 所以需要用到ref获取滚动区域 正常获取scrollTop 前者基于html 后者基于body scrollTop document docume
  • 017-Java-008

    实例变量 实例变量声明在一个类中 但在方法 构造方法和语句块之外 当一个对象被实例化之后 每个实例变量的值就跟着确定 实例变量在对象创建的时候创建 在对象被销毁的时候销毁 实例变量的值应该至少被一个方法 构造方法或者语句块引用 使得外部能够
  • STM32移植lwip之建立web服务器

    本篇目标 在之前能ping通pc机的工程基础上搭建web服务器 借鉴官方web服务器的程序与网页 能够用pc机浏览器访问web服务器 并返回设置的网页 材料准备 基础工程 修改后能ping通pc机的工程 STM32官方移植lwip修改代码
  • Redis中使用Lua的一些优化和注意事项

    EVAL EVALSHA命令 Redis从2 6 0版本开始提供了eval命令 通过内置的Lua解释器 可以让用户执行一段Lua脚本并返回数据 因为Redis单线程模型的特点 可以保证多个命令的原子性 因为最近的项目才想到用Lua 详细的使
  • 火牛(STM32) 多路ADC采样数据经过RS485传输到另一块ARM板路虎(LPC1768)

    调试了好几天终于搞定ADC多路的数据采集 然后通过RS485传输到另一块ARM板上 上程序 火牛开发板基础实验 串口实验 在串口1中输出实验标题 并打印串口1输入的字符 串口中断接收 include stm32f10x h include
  • 嵌入式Linux webserver: Boa+CGI程序设计技术

    摘要 在详细介绍一种嵌入式Web服务器BOA的实现与配置方法的基础上 以一个Web在线远程监控GPIO 通用输入 输出 的程序为实例 介绍嵌入式Linux系统下CPU程序设计技术 关键词 嵌入式系统Linux BOA CGI GPIO 1
  • java中strictfp关键字,java strictfp关键字用法大全详解

    一 strictfp关键字简介 strictfp是Java中提供的一个保留关键字 该关键字是从这第java JDK2版本儿开始出现的一直沿用到现在 只不过很多情况下都不怎么使用 所以容易被大家遗忘 因此今天我们来介绍一下这个关键字的用法和使
  • 【深度学习环境-2】nvidia驱动、cuda安装配置

    一 ubuntu系统安装nvidia驱动 方法一 禁用nouveau驱动 1 打开文件 sudo vim etc modprobe d blacklist conf 2 在末尾添加 blacklist nouveau 3 更新设置 sudo
  • abap append 用法

    转自http blog chinaunix net uid 7982817 id 91999 html Append用法总结 2008 11 14 11 42 19 分类 Syntax APPEND wa INITIAL LINE LINE
  • molloc/free和new/delete的区别

    malloc free和new delete的区别 malloc free和new delete的共同点是 都是从堆上申请空间 并且需要用户手动释放 不同的地方是 malloc和free是函数 new和delete是操作符 malloc申请
  • CSP-S第二轮认证总结——提高组算法总结

    目录 0 前言 一 动态规划 必考必考必考 1 背包 1 01背包 2 完全背包 2 线性DP 3 多维DP 二 贪心 三 模拟 四 图论 很灵活 1 最短路 1 spfa 2 Dijkstra 堆优化 时间复杂度远快于spfa 2 最小生
  • 聚类算法dbscan

    k means k medians 初始化k个类的中心 计算样本点到k个类中心的距离 以此为根据 将这些样本点归类为k类中距离最近的那个类 重新计算k类的中心 直到k类的中心收敛 缺点 需提前知道类数量 优点 速度快 均值漂移 它的原理就是
  • openwrt 中调用json

    对于这种写法 json require json print json encode 1 2 fred first mars second venus third earth 还是这种写法 local json require json p
  • git 提交到某分支,如何将某些提交移动到git中的另一个分支?

    The situation master is at X quickfix1 is at X 2 commits Then I started working on quickfix2 but by accident took quickf
  • python调用搜狗OCR接口实现图片文字识别

    import requests multiple files pic 1111111 jpg open r QQ截图20180905172943 jpg rb image jpg resp requests post r http ocr
  • 自适应控制---自校正PID控制器

    PID算法 其中e 期望输出 实际输出 自校正PID控制器参数的确定 注 F q 1 中有 1 f1q 部分是为了提高分母的次数 便于实现 PID自校正控制算法 对于PI或者P控制 只要将对应的系数去掉即可
  • Android:开启一个服务循环ping服务器,记录ping 5次均失败触发某条件

    import android app Service import android content Intent import android os Handler import android os IBinder import andr
  • SpringMVC(07) -- RESTful

    SpringMVC学习笔记 源码地址 7 1 RESTful简介 REST Representational State Transfer 表现层资源状态转移 7 1 1 资源 资源是一种看待服务器的方式 即 将服务器看作是由很多离散的资源