SpringMVC框架学习笔记(三):url请求风格-Rest 以及 SpringMVC 映射获取到各种类型数据

news2024/11/23 15:04:43

Rest 基本介绍

1.1 基本说明

  • REST:即 Representational State Transfer(资源)表现层状态转化。是目前流行的请求方 式。它结构清晰, 很多网站采用
  • HTTP 协议里面,四个表示操作方式的动词:GETPOSTPUTDELETE。它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源。
  • 传统的 url 是通过参数来说明 crud 的类型,rest 是通过 get/post/put/delete 来说明 crud 的类型
传统的请求方法 :
GET:getBook?id=1
GET:delete?id=1
POS:Tupdate
POST:add

1.2 REST 的核心过滤器

  • 当前的浏览器只支持 post/get 请求,因此为了得到 put/delete 的请求方式需要使用 Spring 提供的 HiddenHttpMethodFilter 过滤器进行转换.
  • HiddenHttpMethodFilter:浏览器 form 表单只支持 GET POST 请求,而 DELETEPUT method 并不支持,Spring 添加了一个过滤器,可以将这些请求转换为标准的 http 法,使得支持 GETPOSTPUT DELETE 请求
  • HiddenHttpMethodFilter 能对 post 请求方式进行转换
  • 这个过滤器需要在 web.xml 中配置
<!--
    1. 配置 HiddenMethodFilter 过滤器,
    2. 可以将以 post 方式提交的 delete、put 和patch 请求进行转换
-->
<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>
  • HiddenHttpMethodFilter 核心代码解析:
public static final String DEFAULT_METHOD_PARAM = "_method";
---------------------------------------------------
private static final List<String> ALLOWED_METHODS =
        Collections.unmodifiableList(Arrays.asList(HttpMethod.PUT.name(),
                HttpMethod.DELETE.name(), HttpMethod.PATCH.name()));
---------------------------------------------------
// 如果请求方式为POST,过滤器就进行转换
if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {
        // 得到参数名为 "_method" 的参数值
        String paramValue = request.getParameter(this.methodParam);
        if (StringUtils.hasLength(paramValue)) {
            // 将参数值转为大写
            String method = paramValue.toUpperCase(Locale.ENGLISH);
            // 如果转换成大写的参数值包含在 ALLOWED_METHODS 中,就将该值作为请求方式传给后端
            if (ALLOWED_METHODS.contains(method)) {
                requestToUse = new HttpMethodRequestWrapper(request, method);
            }
        }
}

上面代码可以看到 HiddenHttpMethodFilter 过滤器可以对以Post方式提交的delete,put,patch进行转换,成 springmvc 识别的 RequestMethod.DELETE / RequestMethod.PUT /...

2 使用Rest 风格的 url 完成增删改查(实例)

1.1 查询(GET)

(1)前端发送请求

说明:在默认情况下,超链接的请求方式是get

<h3>rest风格的url 查询书籍[get]</h3>
<%--默认情况下,超链接的请求方式的get--%>
<a href="user/book/200">点击查询书籍</a>

(2)后端接收请求

//查询[GET]
@RequestMapping(value = "/book/{id}", method = RequestMethod.GET)
public String getBook(@PathVariable("id") String id) {
    System.out.println("查询书籍 id=" + id);
    return "success";
}

1.2 添加(POST)

(1)前端发送请求

<h3>rest风格的url 添加书籍[post]</h3>
<form action="user/book" method="post">
    name:<input name="bookName" type="text"><br>
    <input type="submit" value="添加书籍">
</form>

(2)后端接收请求

//添加[POST]
@PostMapping(value = "/book")
public String addBook(String bookName) {
    System.out.println("添加书籍 bookName== " + bookName);
    return "success";
}

1.3 删除(DELETE)

1.3.1 方式1

(1)前端请求

说明:由于在默认情况下,超链接的请求方式是get,且不能直接指定请求方式,这时需要使用jquery来修改提交方式

<head>
    <title>rest </title>
<%--    引入jquery,该文件在文章顶部可获取--%>
    <script type="text/javascript" src="script/jquery-3.6.0.min.js"></script>
    <script type="text/javascript">
        $(function () { //当页面加载完成后,就执行
            // alert("点击。。。。");
<%--            //给删除超链接绑定一个点击事件--%>
            $("#deleteBook").click(function (){
                //自己定义要提交的行为
                //将id为deleteBook的超链接的href属性值,赋给id为hiddenForm的表单的action属性
                $("#hiddenForm").attr("action", this.href);
                //将参数类型为hidden的参数值改为DELETE
                $(":hidden").val("DELETE");
                //提交该表单
                $("#hiddenForm").submit();
                return false; //改变点击超链接的行为, 不再提交
            })
        })
    </script>
</head>
<body>
<a href="user/book/600" id="deleteBook">删除指定id的书</a>
<%--隐藏表单--%>
<form action="" method="post" id="hiddenForm">
    <input type="hidden" name="_method"/>
</form>
</body>

(2)后端请求

说明:

  • 如果 web 项目是运行在 Tomcat 8 及以上,会发现被过滤成 DELETE PUT 的请求,到达 控制器时能顺利执行,但是返回时(forward)会报 HTTP 405 的错误提示:消息 JSP 只允GETPOST HEAD
  •  解决方式 1: 使用 Tomcat7
  • 解决方式 2: 将请求转发(forward)改为请求重定向(redirect:重定向到一个 HandlerHandler 转发到页面。一般使用解决方式2
//删除[DELETE]
@RequestMapping(value = "/book/{id}", method = RequestMethod.DELETE)
public String delBook(@PathVariable("id") String id) {
    System.out.println("删除书籍 id= " + id);
    //如果这样返回会报错 JSPs only permit GET POST or HEAD]
    //因为消息 JSP 只允许 GET、POST 或 HEAD。
    //return "success";
    //1. redirect:/user/success重定向
    //2. 会被解析成 /springmvc/user/success
    return "redirect:/user/success";
}

//该方法的作用是如果请求是 /user/success , 就转发到 success.jsp
//successGenecal对应的url http://ip:port/springmvc/user/success
@RequestMapping(value = "/success")
public String successGenecal() {
    return "success";  //由该方法 转发到success.jsp页面
}

 1.3.2 方式2

(1)前端发送请求

说明:HiddenHttpMethodFilter,在将 post 转成 delete / put 请求时,是按_method 参数名 来 读取的,参数值大小写均可

<form action="user/book/600" method="post">
    //value的值大小写均可
    <input type="hidden" name="_method" value="delete"/>
    <input type="submit" value="删除书籍~">
</form>

(2)后端接收请求

同方式1

1.4 修改(PUT)

(1)前端发送请求

<h3>rest风格的url 修改书籍[put]~</h3>
<form action="user/book/666" method="post">
    <input type="hidden" name="_method" value="PUT">
    <input type="submit" value="修改书籍~">
</form>

(2)后端接收请求

//修改[PUT]
@PutMapping(value = "/book/{id}")
public String updateBook(@PathVariable("id") String id) {
    System.out.println("修改书籍 id=" + id);
    return "redirect:/user/success";
}

3 SpringMVC 映射请求数据

3.1 获取参数值

3.1.1 说明

开发中,可通过 @RequestParam 获取到形如 http://xxx/url?参数名=参数值&参数名=参数值 的参数值

3.1.2 应用实例

(1)前端发送请求

<h2>获取到超链接参数值</h2>
<hr/>
<a href="vote/vote01?name=yss">获取超链接的参数</a>

(2)后端接收请求

解读 @RequestParam(value="name", required=false):

  •  获取到超链接传递的数据 请求 http://localhost:8080/springmvc/vote/vote01?name=xx
  • @RequestParam 表示会接收提交的参数
  • value="name" 表示提交的参数名是name
  • required=false 表示该参数可以没有, 默认是true,表示必须有这个参数
  • 当我们使用了@RequestParam(value="name", required=false)后,请求的参数名和方法的形参名可以不一致
@RequestMapping("/vote")
@Controller
public class VoteHandler {
    @RequestMapping(value = "/vote01")
    public String test01(@RequestParam(value = "name", required = false) String username) {
        System.out.println("得到的username= " + username);
        //返回到一个结果
        return "success";
    }
}

3.2 获取http请求消息头

3.2.1 说明

演示在开发中,使用@RequestHeader获取到 http 请求的消息头信息(在实际开发中使用较少)

3.2.2 应用实例

(1)修改 VoteHandler.java, 增加方法

/**
 * 获取http请求头信息, 这里只演示获取 Accept-Encoding 和 Host
 * 形式:@RequestHeader("Http请求头字段")
 */
@RequestMapping(value = "/vote02")
public String test02(@RequestHeader("Accept-Encoding") String ae,
                     @RequestHeader("Host") String host) {
    System.out.println("Accept-Encoding= " + ae);
    System.out.println("Host= " + host);
    //返回到一个结果
    return "success";
}

(2)前端发送请求

<h1>获取到消息头</h1>
<hr>
<a href="vote/vote02">获取http消息头信息</a>

3.3 获取javabean形式的数据

3.3.1 说明

如何获取到 javaben 的数据,就是以前的 entity/pojo 对象数据

3.3.2 应用实例

(1)创建 Pet.java

package com.web.requestparam.entity;

public class Pet {
    private Integer id;
    private String name;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Pet{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

(2)创建 Master.java

package com.web.requestparam.entity;

public class Master {
    private Integer id;
    private String name;
    private Pet pet;//对象的属性是另外一个对象[涉及级联]

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Pet getPet() {
        return pet;
    }

    public void setPet(Pet pet) {
        this.pet = pet;
    }

    @Override
    public String toString() {
        return "Master{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", pet=" + pet +
                '}';
    }
}

(3)修改 VoteHandler.java, 增加方法

说明:

  • 方法的形参用对应bean的类型来指定即可, SpringMVC会自动的进行封装
  • 如果自动的完成封装, 要求提交的数据,参数名和对象的字段名保持一致
  • 如果属性是对象,需要通过 字段名.字段名 来完成封装。
  • 比如Master [pet],提交的数据 参数名 是 pet.id pet.name, 这就是级联操作
  • 如果提交的数据 的参数名和对象的字段名不匹配,则对象的属性值就是null
  • 底层是反射+注解
@RequestMapping(value = "/vote03")
public String test03(Master master) {

    System.out.println("master=" + master);
    //返回结果
    return "success";
}

(4)前端发送请求

<h1>添加主人信息</h1>
<!--
1. 这是一个表单,表单的数据对应Master对象
2. 提交的数据参数名和对象的字段名一致即可
-->
<form action="vote/vote03" method="post">
    主人号:<input type="text" name="id"><br>
    主人名:<input type="text" name="name"><br>
    宠物号:<input type="text" name="pet.id"><br>
    宠物名:<input type="text" name="pet.name"><br>
    <input type="submit" value="添加主人和宠物">
</form>

如果使用postman进行测试,可按下图操作 

3.3.3 使用注意事项

  • 支持级联数据获取
  • 表单的控件名称 name 需要和 javabean 对象字段对应, 否则就是 null

3.4 获取 servlet api

3.4.1 说明

(1)开发中, 我们可能需要使用到原生的 servlet api ,看看如何获取

(2)使用 servlet api , 需要引入 servlet-api.jar,该包在文章顶部可获取

3.4.2 应用实例

(1)修改 VoteHandler.java, 增加方法

/**
 * 使用servlet api, 来获取提交的数据
 */
@RequestMapping(value = "/vote04")
public String test04(HttpServletRequest request,
                     HttpServletResponse response,
                     HttpSession hs) {

    //获取到session
    //servlet原生的方式
    HttpSession session = request.getSession();
    System.out.println("session=" + session);
    //注意:通过参数传入的 hs 和 通request.getSession() 得到的对象是同一个
    System.out.println("hs= " + hs);

    String username = request.getParameter("username");
    String pwd = request.getParameter("pwd");
    System.out.println("username= " + username);
    System.out.println("pwd= " + pwd);
    //返回结果
    return "success";
}

(2)前端发送请求

<h1>演示 servlet api的使用 </h1>
<form action="vote/vote04" method="post">
    用户名:<input type="text" name="username"><br>
    密 码:<input type="password" name="pwd"><br>
    <input type="submit" value="添加用户">
</form>

 (3)控制台输出结果

3.4.3 使用注意事项

  • 除了 HttpServletRequest, HttpServletResponse ,sevlet的其它对象也可以以这样的形式获取
  • 例如 HttpSession、java.security.Principal,InputStream,OutputStream,Reader,Writer
  • 其中一些对象也可以通过 HttpServletRequest / HttpServletResponse 对象获取,比如 Session 对象 ,既可以通过参数传入,也以通过 request.getSession() 获取,效果一样,推 荐使用参数形式传入,更加简单明了

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

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

相关文章

音视频开发14 FFmpeg 视频 相关格式分析 -- H264 NALU格式分析

H264简介-也叫做 AVC H.264&#xff0c;在MPEG的标准⾥是MPEG-4的⼀个组成部分–MPEG-4 Part 10&#xff0c;⼜叫Advanced Video Codec&#xff0c;因此常常称为MPEG-4 AVC或直接叫AVC。 原始数据YUV,RGB为什么要压缩-知道就行 在⾳视频传输过程中&#xff0c;视频⽂件的传输…

flume-ng-sql | 支持JDK8+ | 支持Flume 1.11.0 | 使用 Kotlin 编写

文章目录 简介用法 简介 flume-ng-sql-source 作者已经停止维护了&#xff0c;并且已经不支持新版Flume&#xff0c;我们决定开启这一项目 flume-ng-sql。 用法 像 flume-ng-sql-source 一样将 flume-ng-sql 发行的 Jar 包导入lib下&#xff0c;必要时需要添加自己 MySQL 版本…

Mybatis 查询TypeHandler使用,转译查询数据(逗号分隔转List)

创建自定义的Hanndler /*** Package: com.datalyg.common.core.handler* ClassName: CommaSeparatedStringTypeHandler* Author: dujiayu* Description: 用于mybatis 解析逗号拼接字符串* Date: 2024/5/29 10:03* Version: 1.0*/ public class CommaSeparatedStringTypeHandle…

在PostGIS中检查孤线(Find isolated lines in PostGIS)

场景 在PostGIS中有一张线要素表,需要检查该表中的孤线,并且进行自动纠正的计算。 其中孤线定义为两端端点都不在任何其他线的顶点上。 本文介绍在PostGIS中的线要素点,通过函数计算指定线要素表中的孤线,并计算最接近的纠偏位置。 In PostGIS, there is a table of line …

MMrotate报错AttributeError: ‘NoneType‘ object has no attribute ‘shape‘

使用MMrotate训练自定义数据集报错&#xff1a; AttributeError: ‘NoneType’ object has no attribute ‘shape’ 2024-05-31 17:48:06,121 - mmrotate - INFO - workflow: [(train, 1)], max: 12 epochs 2024-05-31 17:48:06,121 - mmrotate - INFO - Checkpoints will be …

nacos连接异常did not find the Leader node;

目录 问题描述解决过程持久化节点真的是存在数据库吗&#xff1f; 问题描述 我搭建的是nacos伪集群&#xff0c;然后主要想着看看集群情况下&#xff0c;临时节点和持久节点的区别。 如果使用临时节点项目能够正常起来&#xff0c;一旦添加ephemeral: false项目就起不来了。 …

【linux】自定义快捷命令/脚本

linux自定义快捷命令 场景自定义命令自定义脚本 场景 深度学习经常要切换到自己环境&#xff0c;conda activate mmagic&#xff0c;但是又不想每次重复打这么多字&#xff0c;想使用快捷命令直接切换。 自定义命令 使用别名&#xff08;alias&#xff09;或自定义脚本来创建…

打造你的首个QT 5计算器应用

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言&#xff1a;QT 5的力量与我们的计算器 二、QT 5基础&#xff1a;理解UI设计与文件…

Go微服务: 基于Docker搭建Kong网关环境

概述 在当今的微服务架构中&#xff0c;API网关扮演着至关重要的角色&#xff0c;它作为系统的统一入口负责处理所有内外部请求&#xff0c;实现路由转发、负载均衡、安全控制、限流熔断等多种功能Kong&#xff0c;作为一个开源、高性能、可扩展的API网关&#xff0c;凭借其强…

vscode 远程连接出现问题

终端太小了&#xff0c; 因为终端中有换行符&#xff0c;如果 终端太小会出现问题

【AI+知识库问答】沉浸式体验了解 AI知识库问答fastGPT

之前写过一篇文章 【AI本地知识库】个人整理的几种常见本地知识库技术方案 &#xff0c; 由于当时主要是针对AI本地知识库&#xff0c; 所以没列fastGPT。 最近经常刷到fastGPT&#xff0c;这里单独水一篇。 FastGPT 是一个基于 LLM 大语言模型的知识库问答系统&#xff0c;…

基于Cloudflare/CloudDNS/GitHub使用免费域名部署NewBing的AI服务

部署前准备&#xff1a; Cloudflare 账号 https://dash.cloudflare.com/login CloudDNS 账号 https://www.cloudns.net/ GitHub 账号 https://github.com/Harry-zklcdc/go-proxy-bingai Cloudflare 部署 Worker CloudDNS 获取免费二级域名 GitHub New Bing Ai 项目 https://git…

C++ 快排算法

今天看到一种清爽的快速算法&#xff0c;复习一下~ 快速排序算法的平均时间复杂度是O(n log n)&#xff0c;最坏情况下的时间复杂度是O(n^2)。 快速排序的最佳情况是每次分割都平均分配元素&#xff0c;这种情况下时间复杂度可降至O(n log n)。 快速排序的基本步骤如下&#…

qwen-moe

一、定义 qwen-moe 代码讲解&#xff0c; 代码qwen-moe与Mixtral-moe 一样&#xff0c; 专家模块qwen-moe 开源教程Mixture of Experts (MoE) 模型在Transformer结构中如何实现&#xff0c;Gate的实现一般采用什么函数&#xff1f; Sparse MoE的优势有哪些&#xff1f;MoE是如…

【智能算法】三角拓扑聚合优化算法(TTAO)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献5.代码获取 1.背景 2024年&#xff0c;S Zhao受到数学相似三角形拓扑结构启发&#xff0c;提出了三角拓扑聚合优化算法&#xff08;Triangulation Topology Aggregation Optimizer, TTAO&#xff09;。 2.算…

Unity中的MVC框架

基本概念 MVC全名是Model View Controller 是模型(model)-视图(view)-控制器(controller)的缩写 是一种软件设计规范&#xff0c;用一种业务逻辑、数据、界面显示 分离的方法组织代码 将业务逻辑聚集到一个部件里面&#xff0c;在改进和个性化定制界面及用户交互的同时&#x…

ch4网络层---计算机网络期末复习(持续更新中)

网络层概述 将分组从发送方主机传送到接收方主机 发送方将运输层数据段封装成分组 接收方将分组解封装后将数据段递交给运输层网络层协议存在于每台主机和路由器上 路由器检查所有经过它的IP分组的分组头 注意路由器只有3层(网络层、链路层、物理层) 网络层提供的服务 一…

无人售货机零售业务成功指南:从市场分析到创新策略

在科技驱动的零售新时代&#xff0c;无人售货机作为一种便捷购物解决方案&#xff0c;正逐步兴起&#xff0c;它不仅优化了消费者体验&#xff0c;还显著降低了人力成本&#xff0c;提升了运营效能。开展这项业务前&#xff0c;深入的市场剖析不可或缺&#xff0c;需聚焦消费者…

命令模式(行为型)

目录 一、前言 二、命令模式 三、总结 一、前言 命令模式&#xff08;Command Pattern&#xff09;是一种行为型设计模式&#xff0c;命令模式将一个请求封装为一个对象&#xff0c;从而可以用不同的请求对客户进行参数化&#xff1b;对请求排队或记录请求日志&#xff0c;以…

【C++】C++入门2.0

各位读者老爷好&#xff0c;本鼠最近浅学了一点C的入门知识&#xff01;利用本博客作为笔记的同时也希望得到各位大佬的垂阅&#xff01; 目录 1. 引用 1.1.引用的概念 1.2.引用的特性 1.3.引用的使用场景 1.4.引用的易错点 1.5.引用的优势 1.6.引用和指针 2.内联函数 …