使用form表单提交PUT请求


form表单的提交方式只支持GET或者POST,为了实现restful风格,需要使用form表单实现PUT和DELETE方式的提交,对于这种情况,spring提供了过滤器 HiddenHttpMethodFilter ,可以将POST方式提交的表单转换成PUT或者DELETE。

案例环境:

  • springboot 2.4.3
  • IntelliJ IDEA 2021.1 (Ultimate Edition)
  • Google Chrome版本 89.0.4389.114(正式版本)

过滤器 HiddenHttpMethodFilter 在springboot中配置在自动配置类WebMvcAutoConfiguration中:

	@Bean
	@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
	@ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", 
                           name = "enabled", matchIfMissing = false)
	public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
		return new OrderedHiddenHttpMethodFilter();
	}

OrderedHiddenHttpMethodFilter继承自HiddenHttpMethodFilter,然后看HiddenHttpMethodFilter的源码:

	public static final String DEFAULT_METHOD_PARAM = "_method";
	private String methodParam = DEFAULT_METHOD_PARAM;

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

		HttpServletRequest requestToUse = request;

		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);
				}
			}
		}

		filterChain.doFilter(requestToUse, response);
	}

14行, String paramValue = request.getParameter(this.methodParam); 在request请求中获取_method参数:

  1. 转换成大写,所以这个_method参数大小写都行;
  2. 检查传入的_method是否在ALLOWED_METHODS中,ALLOWED_METHODS包含 PUTDELETEPATCH
  3. 调用HttpMethodRequestWrapper()方法,将POST请求包装成其他HTTP请求

HttpMethodRequestWrapper() 源码:

	private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper {

		private final String method;

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

		@Override
		public String getMethod() {
			return this.method;
		}
	}

至此,POST请求被转换成其他的HTTP请求了。

写个例子,验证一下:

@RestController
public class RestfulController {

    @PostMapping("rest")
    public String post() {
        return "post";
    }

    @GetMapping("rest")
    public String get() {
        return "get";
    }

    @DeleteMapping("rest")
    public String delete() {
        return "delete";
    }

    @PutMapping("rest")
    public String put() {
        return "put";
    }

}

image-20210412113838148

该版本的springboot默认没有向容器中注入这个过滤器,所以需要在配置文件application.yml中开启:

  # 开启过滤器
  spring:
    mvc:
      hiddenmethod:
        filter:
          enabled: true

写一个表单测试:

<form method="post" action="rest">
    <input type="hidden" name="_method" value="PUT">
    <input type="submit" value="PUT">
</form>

浏览器验证结果:

image-20210412114342204

image-20210412114427128


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM