ajax發送PUT請求,使用HttpPutFormContentFilter過濾器接受辦法


相信在使用ajax發送put請求時候,肯定遇到過后端數據無法被接受到的405錯誤。

為什么會遇到這個問題?

1.首先查看Tomcat源碼 關於如何將數據封裝到Request

public class Request
implements HttpServletRequest {}
//可以看出就像書中所說一樣 Request實現了HttpServletRequest接口

/**
     * Parse request parameters.
     */
    protected void parseParameters() {

    if( !getConnector().isParseBodyMethod(getMethod()) ) {
                success = true;
                return;
            }
}
//受保護的parseParameters()方法
//將數據封裝到parameters中去  

然后查看isParseBodyMethod()方法

public class Connector extends LifecycleMBeanBase  {
    protected String parseBodyMethods = "POST";
    protected HashSet<String> parseBodyMethodsSet;

@Override
    protected void initInternal() throws LifecycleException {

        super.initInternal();

        // Initialize adapter
        adapter = new CoyoteAdapter(this);
        protocolHandler.setAdapter(adapter);

        // Make sure parseBodyMethodsSet has a default
        if( null == parseBodyMethodsSet ) {
            setParseBodyMethods(getParseBodyMethods());
        }

        if (protocolHandler.isAprRequired() &&
                !AprLifecycleListener.isAprAvailable()) {
            throw new LifecycleException(
                    sm.getString("coyoteConnector.protocolHandlerNoApr",
                            getProtocolHandlerClassName()));
        }

        try {
            protocolHandler.init();
        } catch (Exception e) {
            throw new LifecycleException
            (sm.getString
                    ("coyoteConnector.protocolHandlerInitializationFailed"), e);
        }

        // Initialize mapper listener
        mapperListener.init();
    }

    public void setParseBodyMethods(String methods) {

        HashSet<String> methodSet = new HashSet<String>();

        if( null != methods ) {
            methodSet.addAll(Arrays.asList(methods.split("\\s*,\\s*")));
        }

        if( methodSet.contains("TRACE") ) {
            throw new IllegalArgumentException(sm.getString("coyoteConnector.parseBodyMethodNoTrace"));
        }

        this.parseBodyMethods = methods;
        this.parseBodyMethodsSet = methodSet;

    }
    
   protected boolean isParseBodyMethod(String method) {

        return parseBodyMethodsSet.contains(method);

    }  
        
}public String getParseBodyMethods() {

        return this.parseBodyMethods;

    }

上面源碼的內容就是Connector的默認方法是POST,然后其中的如果不是“Post”,數據將無法封裝到Parameter中去

那么解決辦法是:

可以使用HttpPutFormContentFilter過濾器,將PUT請求的表單內容傳輸通過過濾器封裝到Request對象中去

具體步驟如下

1.通過web.xml配置一個過濾器,將PUT請求中的數據進行封裝

        <filter>
		<filter-name>HttpPutFormContentFilter</filter-name>
		<filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>
	</filter>
	
	<filter-mapping>
		<filter-name>HttpPutFormContentFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>    

2.HttpPutFormContentFilter的基本原理是

public class HttpPutFormContentFilter extends OncePerRequestFilter{

		if (("PUT".equals(request.getMethod()) || "PATCH".equals(request.getMethod())) && isFormContentType(request)) {
			HttpInputMessage inputMessage = new ServletServerHttpRequest(request) {
				@Override
				public InputStream getBody() throws IOException {
					return request.getInputStream();
				}
			};
			MultiValueMap<String, String> formParameters = formConverter.read(null, inputMessage);
			HttpServletRequest wrapper = new HttpPutFormContentRequestWrapper(request, formParameters);
			filterChain.doFilter(wrapper, response);
		}
		else {
			filterChain.doFilter(request, response);
		}
}

 基本思路是從request中獲取request,getInputStream()的流 inputMessage

然后將流中的數據封裝到Map中 MultiValueMap 最后將數據重新封裝到request對象中去,完成put數據的封裝

實現Toncat的Request不滿足的PUT請求類似數據封裝層對象這一點操作。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM