likes
comments
collection
share

Spring-Rest- url 请求风格和SpringMVC 映射请求数据

作者站长头像
站长
· 阅读数 19

目录

Rest- url 请求风格

Rest-基本介绍

● 说明

实例

说明:

● REST 的核心过滤器

代码说明Rest 风格的 url-完成增删改

需求说明

​编辑修改 web.xml 添加   HiddenHttpMethodFilter

修改 springDispatcherServlet-servlet.xml

 作用

创建rest.jsp

解读

创建BookHandler.java , 处 理 rest 风格的请求

注意事项和细节说明

SpringMVC 映射请求数据

说明

创建VoteHandler类

创建request_parameter.jsp类

Postman 完成测试

 获取 http 请求消息头

● 说明:

修改 VoteHandler.java增加方法

2. 修改 request_paramete.jsp, 增加代码

Postman 测试

获取 javabean 形式的数据

使用场景说明

 创建Pet.java类

创建Master类

修改 VoteHandler.java增加方法

修改 request_parameter.jsp, 增加演示代码

完成测试(Postman 方式)

 使用注意事项

获取 servlet api

● 说明

修改 VoteHandler.java, 增加方法

修改 request_parameter.jsp

完成测试(Postman 方式)

使用注意事项

修改 VoteHandler.java, 增加方法


Spring-Rest- url 请求风格

Rest-基本介绍

● 说明

1. REST:即 Representational State Transfer。(资源)表现层状态转化。是目前流行的请求方式。它结构清晰, 很多网站采用

2. HTTP 协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源

实例

传统的请求方法:

getBook?id=1 GET

delete?id=1 GET

update POST

add POST

说明:

传统的 url 是通过参数来说明 crud 的类型,rest 是通过 get/post/put/delete 来说明 crud 的类型

● REST 的核心过滤器

1. 当前的浏览器只支持 post/get 请求,因此为了得到 put/delete 的请求方式需要使用 Spring提供的 HiddenHttpMethodFilter 过滤器进行转换.

2. HiddenHttpMethodFilter:浏览器 form 表单只支持 GET 与 POST 请求,而 DELETE、PUT等 method 并不支持,Spring 添加了一个过滤器,可以将这些请求转换为标准的 http 方法,使得支持 GET、POST、PUT 与 DELETE 请求

3. HiddenHttpMethodFilter 能对 post 请求方式进行转换,因此我们需要特别的注意这一点

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

代码说明Rest 风格的 url-完成增删改

需求说明

Spring-Rest- url 请求风格和SpringMVC 映射请求数据修改 web.xml 添加   HiddenHttpMethodFilter

1. 作用是 把 以post方式提交的delete和put请求进行转换

2. 配置url-pattern 是 /* 表示请求都经过 hiddenHttpMethodFilter过滤

3. 后面通过debug源码,就看的很清楚

 <!--配置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>

修改 springDispatcherServlet-servlet.xml

 作用

加入两个常规配置

支持SpringMVC的高级功能,比如JSR303校验, 映射动态请求

将springmvc不能处理的请求,交给tomcat处理,比如css, js

<!--加入两个常规配置-->
    <!--支持SpringMVC的高级功能,比如JSR303校验, 映射动态请求-->
    <mvc:annotation-driven></mvc:annotation-driven>
    <!--将springmvc不能处理的请求,交给tomcat处理,比如css, js-->

创建rest.jsp

注意

需要引入 jquery, 测试的时 候查询/添加/删除/修改一个一个的来


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>rest </title>
<%--    引入jquery--%>
    <script type="text/javascript" src="script/jquery-3.6.0.min.js"></script>
    <script type="text/javascript">
        $(function () { //当页面加载完成后,就执行=> 如果你完全忘记,去回顾我们讲过的jquery
            //给删除超链接绑定一个点击事件
            $("#deleteBook").click(function (){
                //alert("点击。。。。");
                //我们自己定义给提交的行为
                $("#hiddenForm").attr("action", this.href);
                $(":hidden").val("DELETE");
                $("#hiddenForm").submit();
                return false; //改变点击超链接的行为, 不在提交
            })
        })
    </script>
</head>
<body>
<h3>Rest风格的crud操作案例</h3>
<br><hr>
<h3>rest风格的url 查询书籍[get]</h3>
<a href="user/book/200">点击查询书籍</a>
<br><hr>
<h3>rest风格的url 添加书籍[post]</h3>
<form action="user/book" method="post">
    name:<input name="bookName" type="text"><br>
    <input type="submit" value="添加书籍">
</form>
<br><hr>
<h3>rest风格的url, 删除一本书</h3>

<a href="user/book/600" id="deleteBook">删除指定id的书</a>
<form action="" method="post" id="hiddenForm">
    <input type="hidden" name="_method"/>
</form>
<br><hr>
<h3>rest风格的url 修改书籍[put]~</h3>
<form action="user/book/666" method="post">
    <input type="hidden" name="_method" value="PUT">
    <input type="submit" value="修改书籍~">
</form>
</body>
</html>

解读

删除为什么要这么弄

1. 默认情况下 <a href="user/book/600">删除指定id的书</a> 是get 2. 怎么样将 get 请求转成 springmvc 可以识别的 delete 就要考虑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()));
  ---------------------------------------------------
   if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {
            String paramValue = request.getParameter(this.methodParam);
            if (StringUtils.hasLength(paramValue)) {
                String method = paramValue.toUpperCase(Locale.ENGLISH);
                if (ALLOWED_METHODS.contains(method)) {
                    requestToUse = new HttpMethodRequestWrapper(request, method);
                }
            }
        }

3. 上面代码可以看到 HiddenHttpMethodFilter 过滤器

可以对以Post方式提交的delete,put,patch进行转换,

成springmvc识别的 RequestMethod.DELETE / RequestMethod.PUT /...

4. 我们需要将

get <a href="user/book/600">删除指定id的书</a> 以post方式提交给后端handler,

这样过滤器还会生效

5. 我们可以同jquery来处理-引入jquery

创建BookHandler.java , 处 理 rest 风格的请求

1. redirect:/user/success重定向 2. 会被解析成 /springmvc/user/success 

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

/**
 * BookHandler处理rest风格的请求-增删改查
 */
@RequestMapping("/user")
@Controller
public class BookHandler {

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

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

    //删除[DELETE]
    @RequestMapping(value = "/book/{id}", method = RequestMethod.DELETE)
    public String delBook(@PathVariable("id") String id) {
        System.out.println("删除书籍 id= " + id);
        //return "success"; //[如果这样返回会报错 JSPs only permit GET POST or HEAD]
        //解读
        //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页面
    }

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

注意事项和细节说明

1、HiddenHttpMethodFilter,在将 post 转成 delete / put 请求时,是按_method 参数名 来读取的

2、如果 web 项目是运行在 Tomcat 8 及以上,会发现被过滤成 DELETE 和 PUT 请求,到达控制器时能顺利执行,但是返回时(forward)会报 HTTP 405 的错误提示:消息 JSP 只允许 GET、POST 或 HEAD。

1) 解决方式 1: 使用 Tomcat7

2) 解决方式 2: 将请求转发(forward)改为请求重定向(redirect):重定向到一个 Handler,由 Handler转发到页面

Spring-Rest- url 请求风格和SpringMVC 映射请求数据

3、页面测试时, 如果出现点击修改书籍,仍然走的是删除 url ,是因为浏览器原因(缓存等原 因), 换成 chrome 即可


SpringMVC 映射请求数据

说明

开发中,如何获取到 http://xxx/url?参数名=参数值&参数名=参数值

Spring-Rest- url 请求风格和SpringMVC 映射请求数据

创建VoteHandler类

解读 @RequestParam(value="name", required=false) 1. 获取到超链接传递的数据 请求 http://localhost:8080/springmvc/vote/vote01?name=xx 2. @RequestParam 表示会接收提交的参数 3. value="name" 表示提交的参数名是name 4. required=false 表示该参数可以没有, 默认是true,表示必须有这个参数 5. 当我们使用了@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";
    }

创建request_parameter.jsp类

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>测试 request parameter</title>
</head>
<body>
<h2>获取到超链接参数值</h2>
<hr/>
<a href="vote/vote01?name=112">获取超链接的参数</a>
</body>
</html>

Postman 完成测试

Spring-Rest- url 请求风格和SpringMVC 映射请求数据

 获取 http 请求消息头

● 说明:

1. 开发中,如何获取到 http 请求的消息头信息 2. 使用较少

修改 VoteHandler.java增加方法

需求: 获取http请求头信息, 获取到Accept-Encoding 和 Host

1. 这里涉及到前面讲过的http协议,小伙伴可以进行回顾 @RequestHeader("Http请求头字段")

@RequestMapping("/vote")
@Controller
public class VoteHandler {

    @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. 修改 request_paramete.jsp, 增加代码

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

Postman 测试

Spring-Rest- url 请求风格和SpringMVC 映射请求数据

获取 javabean 形式的数据

使用场景说明

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

Spring-Rest- url 请求风格和SpringMVC 映射请求数据

 创建Pet.java类

package com.hspedu.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 + '\'' +
                '}';
    }
}

创建Master类

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 +
                '}';
    }
}

修改 VoteHandler.java增加方法

@RequestMapping("/vote")
@Controller
public class VoteHandler {
// 演示如果获取到提交数据->封装成java对象
    @RequestMapping(value = "/vote03")
    public String test03(Master master) {

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

1. 方法的形参用对应的类型来指定即可, SpringMVC会自动的进行封装

2. 如果自动的完成封装, 要求提交的数据,参数名和对象的字段名保持一致

3. 如果属性是对象,这里就是仍然是通过 字段名.字段名 比如Master [pet], 即提交的数据 参数名 是 pet.id pet.name, 这就是级联操作

4. 如果提交的数据 的参数名和对象的字段名不匹配,则对象的属性值就是null

5. 怎么就封装成功[底层仍然是反射+注解..]

修改 request_parameter.jsp, 增加演示代码

1. 这是一个表单,表单的数据对应Master对象

2. 提交的数据参数名和对象的字段名一致即可

<h1>添加主人信息</h1>

<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 方式)

Spring-Rest- url 请求风格和SpringMVC 映射请求数据

 使用注意事项

1. 支持级联数据获取

2. 表单的控件名称 name 需要和 javabean 对象字段对应, 否则就是null


获取 servlet api

● 说明

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

2. 使用 servlet api , 需要引入 tomcat/lib 下的 servlet-api.jar

修改 VoteHandler.java, 增加方法

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


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

修改 request_parameter.jsp

<hr>
<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>

完成测试(Postman 方式)

Spring-Rest- url 请求风格和SpringMVC 映射请求数据

使用注意事项

1. 除了 HttpServletRequest, HttpServletResponse 还可以其它对象也可以这样的形式获取

2. HttpSession、     java.security.Principal,    InputStream,OutputStream,        Reader,Writer

3. 其中一些对象也可以通过 HttpServletRequest / HttpServletResponse 对象获取,比如

Session 对象 ,既可以通过参数传入,也以通过 request.getSession() 获取,效果一样,推荐使用参数形式传入,更加简单明了

修改 VoteHandler.java, 增加方法

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

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

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