第三章 HiddenHttpMethodFilter (REST)

REST风格是什么?

REST:即 Representational State Transfer。(资源)表现层状态转化。是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用

  • 资源(Resources):【万物皆资源】网络上的一个实体,或者说是网络上的一个具体信息。
    它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的存在。
    可以用一个URI(统一资源定位符)指向它,每种资源对应一个特定的 URI 。
    获取这个资源,访问它的URI就可以,因此 URI 即为每一个资源的独一无二的识别符。
  • 表现层(Representation):【每一种资源都有对应的表现形式】把资源具体呈现出来的形式,叫做它的表现层(Representation)。比如,文本可以用 txt 格式表现,也可以用 HTML 格式、XML 格式、JSON 格式表现,甚至可以采用二进制格式。
  • 状态转化(State Transfer):每发出一个请求,就代表了客户端和服务器的一次交互过程。HTTP协议,是一个无状态协议,即所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生“状态转化”(State Transfer)。
    而这种转化是建立在表现层之上的,所以就是 “表现层状态转化”。
  • 具体说,就是 HTTP 协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。
    它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源。

REST

系统希望以非常简洁的URL地址来发请求;怎么表示对一个资源的增删改查用请求方式来区分
旧方式

/getBook?id=1 :查询图书
/deleteBook?id=1 :删除1号图书
/updateBook?id=1 :更新1号图书
/addBook     :添加图书

REST推荐:简洁的URL提交请求,以请求方式区分

url地址这么起名; /资源名/资源标识符
/book/1 :GET 查询1号图书
/book/1  :PUT 更新1号图书
/book/1  :DELETE 删除1号图书
/book : POST 添加图书
系统的URL地址就这么来设计即可

REST风格增删改查环境搭建

问题:从页面上只能发送两种请求,GET 、POST 其他的请求方式没法使用 如果强制使用默认为get

package com.project.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class MyController {
    @RequestMapping(value="book/{bid}" , method = RequestMethod.GET)
    public String getBook(@PathVariable("bid") Integer id ) {
        System.out.println("get"+id);
        return "hello";
    }
    @RequestMapping(value="book/{bid}" , method = RequestMethod.PUT)
    public String updateBook(@PathVariable("bid") Integer id ) {
        System.out.println("update"+id);
        return "hello";
    }
    @RequestMapping(value="book/{bid}" , method = RequestMethod.DELETE)
    public String deleteBook(@PathVariable("bid") Integer id ) {
        System.out.println("delete"+id);
        return "hello";
    }
    @RequestMapping(value="book" , method = RequestMethod.POST)
    public String addBook( ) {
        System.out.println("add");
        return "hello";
    }
}

页面代码

《%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
《html>
《body>
《h2>Hello World!《/h2>
《/body>
《a href="book/1" >查询1号图书《/a>《!-- "book/1"不能写/ 写/要加项目名  默认是GET请求-->
《form action="book" method="post">《!-- post请求 -->
    《input type="submit" value="添加1号图书">
《/form>
《form action="book/1" method="delete">《!-- delete请求 -->
    《input type="submit" value="添加1号图书">
《/form>
《form action="book/1" method="put">《!-- put请求 -->
    《input type="submit" value="更新1号图书">
《/form>
《/html>

图片说明

从页面发起put、DELETE 形式的请求 利用过滤器HiddenHttpMethodFilter 来配置 Spring提供了对Rest风格的支持

  • SpringMVC中有一个Filter:它可以把普通的请求转化为规定形式的请求 POST->delete/put
    <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>
  • jsp的代码
    《%@ page language="java" contentType="text/html; charset=UTF-8"
      pageEncoding="UTF-8"%>
    《html>
    《body>
    《h2>Hello World!《/h2>
    《/body>
    《a href="book/1" >查询1号图书《/a>《!-- "book/1"不能写/ 写/要加项目名  默认是GET请求-->
    《form action="book" method="post">《!-- post请求 -->
      《input type="submit" value="添加1号图书">
    《/form>
    《form action="book/1" method="post">《!-- delete请求 -->
      《input name="_method" value="delete" />
      《input type="submit" value="添加1号图书">
    《/form>
    《form action="book/1" method="post">《!-- put请求 -->
      《input name="_method" value="put" />
      《input type="submit" value="更新1号图书">
    《/form>
    《/html>
    图片说明

因为Tomcat高版本问题 需要加isErrorPage="true"
瞒天过海原理

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        String paramValue = request.getParameter(this.methodParam);
//判断如果表单是一个post 且_method有值
        if ("POST".equals(request.getMethod()) && StringUtils.hasLength(paramValue)) {
            String method = paramValue.toUpperCase(Locale.ENGLISH);//delete put 都转为大写 
            HttpServletRequest wrapper = new HttpMethodRequestWrapper(request, method);//实现了HttpServletRequest 且复写了request.getMethod() ; 得到的值是_method的值  
            filterChain.doFilter(wrapper, response);
        }
        else {
//否则直接放行
            filterChain.doFilter(request, response);
        }
    }

高版本 Tomcat 8.0以上 Rest会405

图片说明

全部评论

相关推荐

点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务