• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

SpringBoot学习笔记part09Web开发——rest使用和原理

武飞扬头像
Parker7
帮助1

SpringBoot 学习笔记 Part09

1. 请求映射

从@RequestMapping标注处理什么请求,到控制器方法的方法体返回值,这个过程就叫做请求映射,如下:

    @RequestMapping("hello")
    public String hello(){
        return "Hello SpringBoot 2 !";
    }

2. Rest映射

Rest风格支持,即使用HTTP请求方式动词来表示对资源的操作。

  • 以前:/getUser 获取用户 /deleteUser 删除用户 /editUser 修改用户 /saveUser 保存用户
  • 现在: /user GET-获取用户 DELETE-删除用户 PUT-修改用户 POST-保存用户

Rest风格的请求映射,它们映射到的地址都是同一个,再根据请求方式的不同来区分不同的处理。代码如下:

	@RequestMapping(value = "user",method = RequestMethod.GET)
    public String getUser(){
        return "GET-张三";
    }

    @RequestMapping(value = "user",method = RequestMethod.POST)
    public String saveUser(){
        return "POST-张三";
    }


    @RequestMapping(value = "user",method = RequestMethod.PUT)
    public String putUser(){
        return "PUT-张三";
    }

    @RequestMapping(value = "user",method = RequestMethod.DELETE)
    public String deleteUser(){
        return "DELETE-张三";
    }
学新通

使用Rest风格进行映射,我们需要使用到一个核心Filter:HiddenHttpMethodFilter,我们进入这个Filter的底层可以发现,这个过滤器对于请求方式的处理过程。

学新通

那么SpringMVC有为我们自动配置这个Filter吗,前往底层源码可以发现,并没有。因此,必须手动配置。

学新通

使用方法总结

  1. 将表单的 method 设置为 post ,并将隐藏域 _method 设置为 put/delete/get (即 _method 里设置真正的请求方式)

    <form action="user" method="post">
      <input type="hidden" name="_method" value="put">
      <input type="submit" value="REST-PUT提交">
    </form>
    
    <form action="user" method="post">
      <input type="hidden" name="_method" value="delete">
      <input type="submit" value="REST-DELETE提交">
    </form>
    
  2. SpringBoot中 手动开启

    spring:
      mvc:
        hiddenmethod:
          filter:
            enabled: true
    

3. Rest的派生注解

@GetMapping、@PostMapping、@PutMapping、@DeleteMapping、@PatchMapping:它们就是@RequestMapping派生出来的注解,默认携带某个提交方式属性,源码如下:

@RequestMapping(method = {RequestMethod.GET})
public @interface GetMapping{}

将上面的示例全都改写为用派生注解,代码如下:

	@GetMapping("user")
    public String getUser(){
        return "GET-张三";
    }

    @PostMapping("user")
    public String saveUser(){
        return "POST-张三";
    }


    @PutMapping("user")
    public String putUser(){
        return "PUT-张三";
    }

    @DeleteMapping("user")
    public String deleteUser(){
        return "DELETE-张三";
    }
学新通

4. Rest映射的原理

springmvc底层源码:

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    HttpServletRequest requestToUse = request;
    if ("POST".equals(request.getMethod()) && request.getAttribute("javax.servlet.error.exception") == null) {
        String paramValue = request.getParameter(this.methodParam);
        if (StringUtils.hasLength(paramValue)) {
            String method = paramValue.toUpperCase(Locale.ENGLISH);
            if (ALLOWED_METHODS.contains(method)) {
                requestToUse = new HiddenHttpMethodFilter.HttpMethodRequestWrapper(request, method);
            }
        }
    }

    filterChain.doFilter((ServletRequest)requestToUse, response);
}

分析基于表单提交时使用的Rest映射过程:(下面以 DELETE 请求方式为例)

  1. 表单提交时会带上隐藏域 _method=DELETE
  2. 请求过来时会被 HiddenHttpMethodFilter拦截
  3. 判断请求是否有异常,并且要求请求方式是 POST
  4. 获取 _method 的值并转成大写(这一步说明我们在编写html时,请求方式大小写可以随意)
  5. 判断允许的请求方式中包不包含 _method的值(这里可以发现除了HTTP传统的 GET、POST外,还兼容PUT、DELETE、PATCH)
  6. 调用HttpMethodRequestWrapper方法。(原生request的请求是post,包装模式requestWrapper重写了原生request的getMethod方法,返回的就变成了_method的值)
  7. 过滤器链放行时放行的是Wrapper,以后的方法调用getMethod都会调用到包装模式requestWrapper重写过的,所以以后获取到的都是_method的值了。

注意:Http只兼容两种原生请求方式,才需要过滤器的支持。Rest使用客户端工具时,如安卓或Postman模拟,就可以直接发送PUT、DELETE请求,无需Filter。

在此我们也能够意识到为什么springboot默认没有把HiddenHttpMethodFilter开启。因为如果不做页面开发,springboot就是用于微服务的开发,微服务开发简单来说就是给别人提供接口,别人发给我们请求,我们提供JSON数据。不会经常交互页面,且前后端分离,页面也可能是别人写的。

5. 更换隐藏域的属性名

由于 SpringMVC 的自动配置时加载 HiddenHttpMethodFilter 组件是根据 @ConditionalOnMissingBean 按需加载的,因此我们可以自己给容器中放一个 HiddenHttpMethodFilter,并且隐藏域的属性名自己喜欢取什么就取什么。

@Configuration(proxyBeanMethods = false) //没有什么依赖,所以弄成多例可以减少开销
public class WebConfig {

    @Bean
    public HiddenHttpMethodFilter hiddenHttpMethodFilter(){
        HiddenHttpMethodFilter methodFilter = new HiddenHttpMethodFilter();
        methodFilter.setMethodParam("_m"); // HiddenHttpMethodFilter有一个set方法可以更改隐藏域属性
        return methodFilter;
    }

}

用 HiddenHttpMethodFilter 里的一个set方法 setMethodParam( ) 可以更改隐藏域属性。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhhaeejc
系列文章
更多 icon
同类精品
更多 icon
继续加载