SpringBoot学习笔记【part09】rest使用与原理

SpringBoot学习笔记【part09】rest使用与原理,第1张

SpringBoot学习笔记【part09】rest使用与原理 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吗,前往底层源码可以发现,并没有。因此,必须手动配置。



使用方法总结:

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

    
    
    

    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 请求方式为例)

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

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5717216.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-18
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存