spring 接收_header 作为get请求的httpheader

今天项目遇到一个问题,我们项目用户验证和权限验证的信息(licence)是在http头中设置的,百度了一下,只有ajax才能设置头信息,form表单是无法设置的,但是我突然想起springMVC关于form表单解决put、delete提交方式的问题,我灵机一动,于是模仿springMVC实现了设置自定义header的功能。  

起源

项目使用的是SSM框架,废话不多说,我们先看springMVC对于form表单提交put、delete请求问题的解决方案,springMVC是使用了一个过滤器,使之用用户只需在form表单增加一个隐藏域_method即可,比如下面这样:

  1. <form id="fm" method="post" >  
  2.         <input type="hidden" name="_method" value="put"/>  
  3.         <input type="hidden" name="_header" value="${licence }"/>  
  4.         <div class="fitem">  
  5.             <label>uNum:</label>  
  6.             <input name="uNum" class="easyui-validatebox" required="true">  
  7.         </div>  
  8.         <div class="fitem">  
  9.             <label>uPass:</label>  
  10.             <input name="uPass" class="easyui-validatebox" required="true">  
  11.         </div>  
  12.         <div class="fitem">  
  13.             <label>uName:</label>  
  14.             <input name="uName" class="easyui-validatebox" required="true">  
  15.         </div>  
  16.         <div class="fitem">  
  17.             <label>csId:</label>  
  18.             <input name="csId" class="easyui-validatebox" required="true">  
  19.         </div>  
  20.         <div class="fitem">  
  21.             <label>uJob:</label>  
  22.             <input name="uJob" class="easyui-validatebox" required="true">  
  23.         </div>  
  24.         <div class="fitem">  
  25.             <label>uStartTime:</label>  
  26.             <input name="uStartTime" class="easyui-validatebox" required="true">  
  27.         </div>  
  28.         <div class="fitem">  
  29.             <label>rId:</label>  
  30.             <input name="rId" class="easyui-validatebox" required="true">  
  31.         </div>  
  32.         <div class="fitem">  
  33.             <label>uMail:</label>  
  34.             <input name="uMail" class="easyui-validatebox" validType="email" required="true">  
  35.         </div>  
  36.         <div class="fitem">  
  37.             <label>uState:</label>  
  38.             <input name="uState" class="easyui-validatebox" required="true">  
  39.         </div>  
  40.     </form>  

_method里的值就是你要提交方式,具体情况大家自己百度我就细说了。

实现

springmvc在web.xml中配置是这样的

  1. <filter>  
  2.         <filter-name>httpMethodFilter</filter-name>  
  3.         <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>  
  4.     </filter>  
  5.     <filter-mapping>  
  6.         <filter-name>httpMethodFilter</filter-name>  
  7.         <servlet-name>SpringMVC</servlet-name>  
  8.     </filter-mapping>  

然后我们来看springMVC的源码:

  1. /* 
  2.  * Copyright 2002-2012 the original author or authors. 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16.   
  17. package org.springframework.web.filter;  
  18.   
  19. import java.io.IOException;  
  20. import java.util.Locale;  
  21. import javax.servlet.FilterChain;  
  22. import javax.servlet.ServletException;  
  23. import javax.servlet.http.HttpServletRequest;  
  24. import javax.servlet.http.HttpServletRequestWrapper;  
  25. import javax.servlet.http.HttpServletResponse;  
  26.   
  27. import org.springframework.util.Assert;  
  28. import org.springframework.util.StringUtils;  
  29.   
  30. /** 
  31.  * {@link javax.servlet.Filter} that converts posted method parameters into HTTP methods, 
  32.  * retrievable via {@link HttpServletRequest#getMethod()}. Since browsers currently only 
  33.  * support GET and POST, a common technique - used by the Prototype library, for instance - 
  34.  * is to use a normal POST with an additional hidden form field ({@code _method}) 
  35.  * to pass the "real" HTTP method along. This filter reads that parameter and changes 
  36.  * the {@link HttpServletRequestWrapper#getMethod()} return value accordingly. 
  37.  * 
  38.  * <p>The name of the request parameter defaults to {@code _method}, but can be 
  39.  * adapted via the {@link #setMethodParam(String) methodParam} property. 
  40.  * 
  41.  * <p><b>NOTE: This filter needs to run after multipart processing in case of a multipart 
  42.  * POST request, due to its inherent need for checking a POST body parameter.</b> 
  43.  * So typically, put a Spring {@link org.springframework.web.multipart.support.MultipartFilter} 
  44.  * <i>before</i> this HiddenHttpMethodFilter in your {@code web.xml} filter chain. 
  45.  * 
  46.  * @author Arjen Poutsma 
  47.  * @since 3.0 
  48.  */  
  49. public class HiddenHttpMethodFilter extends OncePerRequestFilter {  
  50.   
  51.     /** Default method parameter: {@code _method} */  
  52.     public static final String DEFAULT_METHOD_PARAM = "_method";  
  53.   
  54.     private String methodParam = DEFAULT_METHOD_PARAM;  
  55.   
  56.   
  57.     /** 
  58.      * Set the parameter name to look for HTTP methods. 
  59.      * @see #DEFAULT_METHOD_PARAM 
  60.      */  
  61.     public void setMethodParam(String methodParam) {  
  62.         Assert.hasText(methodParam, "'methodParam' must not be empty");  
  63.         this.methodParam = methodParam;  
  64.     }  
  65.   
  66.     @Override  
  67.     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)  
  68.             throws ServletException, IOException {  
  69.   
  70.         String paramValue = request.getParameter(this.methodParam);  
  71.         if ("POST".equals(request.getMethod()) && StringUtils.hasLength(paramValue)) {  
  72.             String method = paramValue.toUpperCase(Locale.ENGLISH);  
  73.             HttpServletRequest wrapper = new HttpMethodRequestWrapper(request, method);  
  74.             filterChain.doFilter(wrapper, response);  
  75.         }  
  76.         else {  
  77.             filterChain.doFilter(request, response);  
  78.         }  
  79.     }  
  80.   
  81.   
  82.     /** 
  83.      * Simple {@link HttpServletRequest} wrapper that returns the supplied method for 
  84.      * {@link HttpServletRequest#getMethod()}. 
  85.      */  
  86.     private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper {  
  87.   
  88.         private final String method;  
  89.   
  90.         public HttpMethodRequestWrapper(HttpServletRequest request, String method) {  
  91.             super(request);  
  92.             this.method = method;  
  93.         }  
  94.   
  95.         @Override  
  96.         public String getMethod() {  
  97.             return this.method;  
  98.         }  
  99.     }  
  100.   
  101. }  

重点我们来看他写的HttpMethodRequestWrapper这个内部类,这个类继承HttpServletRequestWrapper,而HttpServletRequestWrapper我进去看了下都是调用更上层的方法自己并没有做什么事情,再往上我就没去看了。我理解的他的原理是:request在得到method时时使用getMethod方法的,所以他重写了getMethod方法,从而可以把_method的值当做method。

那么既然这样,我也可以把_header的值当做header啊,而request获取header的方法是public String getHeader(String name),所以我就写了下面这样的过滤器:

  1. package com.zs.tools;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import javax.servlet.FilterChain;  
  6. import javax.servlet.ServletException;  
  7. import javax.servlet.http.HttpServletRequest;  
  8. import javax.servlet.http.HttpServletRequestWrapper;  
  9. import javax.servlet.http.HttpServletResponse;  
  10. import org.springframework.web.filter.HiddenHttpMethodFilter;  
  11.   
  12.   
  13. /** 
  14.  * 张顺,2017-2-28 
  15.  * 处理form表单头的过滤器, 
  16.  * 如果表单有_header字段,可以自动将该字段转为request的header头信息(增加一条头) 
  17.  * @author it023 
  18.  */  
  19. public class MyHiddenHttpMethodFilter extends HiddenHttpMethodFilter{  
  20.   
  21.       
  22.     @Override  
  23.     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)  
  24.             throws ServletException, IOException {  
  25.         String header=request.getParameter("_header");  
  26.         if (header!=null && !header.trim().equals("")) {  
  27.             HttpServletRequest wrapper = new HttpHeaderRequestWrapper(request,header);  
  28.             super.doFilterInternal(wrapper, response, filterChain);  
  29.         }else {  
  30.             super.doFilterInternal(request, response, filterChain);  
  31.         }  
  32.     }  
  33.       
  34.     private static class HttpHeaderRequestWrapper extends HttpServletRequestWrapper{  
  35.   
  36.         private final String header;  
  37.           
  38.         public HttpHeaderRequestWrapper(HttpServletRequest request,String licence) {  
  39.             super(request);  
  40.             this.header=licence;  
  41.         }  
  42.   
  43.         @Override  
  44.         public String getHeader(String name) {  
  45.             if (name!=null &&   
  46.                     name.equals("licence") &&   
  47.                     super.getHeader("licence")==null) {  
  48.                 return header;  
  49.             }else {  
  50.                 return super.getHeader(name);  
  51.             }  
  52.         }  
  53.           
  54.     }  
  55.       
  56.       
  57. }  

然后,在web.xml中配置一下,我是放在HiddenHttpMethodFilter前面的。

  1. <filter>  
  2.         <filter-name>httpHeaderFilter</filter-name>  
  3.         <filter-class>com.zs.tools.MyHiddenHttpMethodFilter</filter-class>  
  4.     </filter>  
  5.     <filter-mapping>  
  6.         <filter-name>httpHeaderFilter</filter-name>  
  7.         <servlet-name>SpringMVC</servlet-name>  
  8.     </filter-mapping>  

结果

结果很成功,具体的代码我不想贴了,请看日志,这一条表示获取到http头的licence(不要在意licence为什么这么简单,那是因为这是测试数据)。

转自http://blog.csdn.net/fe123rarwa14235pp/article/details/58607296

原文地址:https://www.cnblogs.com/tiancai/p/8080372.html