zoukankan      html  css  js  c++  java
  • 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请求类似数据封装层对象这一点操作。

  • 相关阅读:
    Flask 静态文件缓存问题
    Flask中current_app和g对象
    Flask-Login详解
    Flask-分开Models解决循环引用
    python包中__init__.py文件的作用
    Flask中路由参数
    Flask之加载静态资源
    Flask request 属性详解
    Django REST framework+Vue 打造生鲜超市(一)
    8.Vue基础
  • 原文地址:https://www.cnblogs.com/ad-zhou/p/9864802.html
Copyright © 2011-2022 走看看