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

1 Rest****基本介绍

1.1 基本说明

  • REST:即 Representational State Transfer。(资源)表现层状态转化。是目前流行的请求方 式。它结构清晰, 很多网站采用
  • HTTP 协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作: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 请求,而 DELETE、PUT 等 method 并不支持,Spring 添加了一个过滤器,可以将这些请求转换为标准的 http 方法,使得支持 GET、POST、PUT 与 DELETE 请求

  • HiddenHttpMethodFilter 能对 post 请求方式进行转换

  • 这个过滤器需要在 web.xml 中配置

    <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 只允许 GET、POST 或 HEAD。

  • 解决方式 1: 使用 Tomcat7

  • 解决方式 2: 将请求转发(forward)改为请求重定向(redirect):重定向到一个 Handler, 由 Handler 转发到页面。一般使用解决方式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() 获取,效果一样,推 荐使用参数形式传入,更加简单明了
相关推荐
to be a question2 小时前
【物联网工程导论期末复习完整知识点】第二章RFID与物联网应用
笔记·嵌入式硬件·物联网·期末复习
吉拉尔3 小时前
昇思25天学习打卡营第06天 | 网络构建
学习
Java追光着3 小时前
谷粒商城学习-07-虚拟机网络设置
服务器·网络·学习·谷粒商城
github_zwl3 小时前
昇思25天学习打卡营第6天|linchenfengxue
人工智能·学习·目标跟踪
chushiyunen3 小时前
搏击与防卫笔记
笔记
杂鱼Tong3 小时前
11. Revit API UI 补充
笔记
2301_795167204 小时前
昇思25天学习打卡营第8天|MindSpore保存与加载(保存和加载MindIR)
学习
鸽鸽程序猿4 小时前
【C语言】分支(选择)和循环语句
c语言·开发语言·学习·程序人生·学习方法·visual studio
盐焗星球4 小时前
HCIA4.26-5.10
网络·笔记·智能路由器
Spcarrydoinb5 小时前
嵌入式学习——硬件(Linux内核驱动编程LED、蜂鸣器、按键)——day59
linux·驱动开发·学习