使用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