Skip to content

Latest commit

 

History

History
103 lines (74 loc) · 3.69 KB

Spring-REST风格-源码解析.md

File metadata and controls

103 lines (74 loc) · 3.69 KB

Spring-REST风格-源码解析

文章已同步至GitHub开源项目: Java超神之路

SpringBoot支持的RESTful风格的请求方式,底层是如何实现的呢?

准备

  • html

    <form action="/user" method="POST">
        <input name="_method" hidden value="DELETE">
        <input type="submit" value="DELETE提交 删除用户信息">
    </form>
  • Controller

    @RequestMapping(value = "/user",method = RequestMethod.DELETE)
        public String deleteUser(){
            return "DELETE-删除用户";
        }

开始Debug

  • 表单提交会带上**_method=PUT**

    <form action="/user" method="POST">
        <input name="_method" hidden value="DELETE">
        <input type="submit" value="DELETE提交 删除用户信息">
    </form>
  • 通过Debug发现,请求过来被HiddenHttpMethodFilter拦截

    // 拦截所有请求
    @Override
    	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
    			throws ServletException, IOException {
    
    		HttpServletRequest requestToUse = request;
    
            //请求是否有错误,并且是POST
    		if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) { 
                //获取到名称为`this.methodParam`的参数
    			String paramValue = request.getParameter(this.methodParam); 
                //如果有这个参数
    			if (StringUtils.hasLength(paramValue)) {
                    //转化为英文大写 DELETE
    				String method = paramValue.toUpperCase(Locale.ENGLISH); //获取到_method的值。
    				if (ALLOWED_METHODS.contains(method)) { //如果是允许的值
                        //将之前的原生请求中的请求方式改为参数_method的请求方式
    					requestToUse = new HttpMethodRequestWrapper(request, method); //包装 
    				}
    			}
    		}
    
            //将包装好的请求放行。
    		filterChain.doFilter(requestToUse, response); 
    	}

    通过DeBug我们发现,首先请求进来,会if判断是否是POST请求,并且请求中没有错误。之后用request.getParameter方法获取到名称为this.methodParam的参数。我们发现,this.methodParam的值为_mothod

    image-20210726144142519

    所以获取到了请求中参数名称为_method的值。DELETE

    image-20210726143515937

    然后通过String method = paramValue.toUpperCase(Locale.ENGLISH);转换为大写。之后判断是包含在否是允许的请求中。通过Debug,允许的请求如下

    image-20210726144219958

    也就是说兼容以下请求;PUT.DELETE.PATCH

    之后会重新创建一个HttpMethodRequestWrapper请求。

    这个类支持了请求传参。将原生的请求方式改为传递过来的参数DELETE

    public HttpMethodRequestWrapper(HttpServletRequest request, String method) {
    			super(request);
    			this.method = method;
    		}

    image-20210726145110249

    将包装好的请求放行。

    filterChain.doFilter(requestToUse, response);

    此时,

    原生的请求由POST方法改为参数_method中指定的请求类型。然后由Controller层接收。

文章已同步至GitHub开源项目: Java超神之路 更多Java相关知识,欢迎访问!