天天看點

spring 接收_header 作為get請求的httpheader

今天項目遇到一個問題,我們項目使用者驗證和權限驗證的資訊(licence)是在http頭中設定的,百度了一下,隻有ajax才能設定頭資訊,form表單是無法設定的,但是我突然想起springMVC關于form表單解決put、delete送出方式的問題,我靈機一動,于是模仿springMVC實作了設定自定義header的功能。  

起源

項目使用的是SSM架構,廢話不多說,我們先看springMVC對于form表單送出put、delete請求問題的解決方案,springMVC是使用了一個過濾器,使之用使用者隻需在form表單增加一個隐藏域_method即可,比如下面這樣:

[html] view plain copy

  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.             <label>uPass:</label>  
  9.             <input name="uPass" class="easyui-validatebox" required="true">  
  10.             <label>uName:</label>  
  11.             <input name="uName" class="easyui-validatebox" required="true">  
  12.             <label>csId:</label>  
  13.             <input name="csId" class="easyui-validatebox" required="true">  
  14.             <label>uJob:</label>  
  15.             <input name="uJob" class="easyui-validatebox" required="true">  
  16.             <label>uStartTime:</label>  
  17.             <input name="uStartTime" class="easyui-validatebox" required="true">  
  18.             <label>rId:</label>  
  19.             <input name="rId" class="easyui-validatebox" required="true">  
  20.             <label>uMail:</label>  
  21.             <input name="uMail" class="easyui-validatebox" validType="email" required="true">  
  22.             <label>uState:</label>  
  23.             <input name="uState" class="easyui-validatebox" required="true">  
  24.     </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.         <servlet-name>SpringMVC</servlet-name>  
  7.     </filter-mapping>  

然後我們來看springMVC的源碼:

[java] view plain copy

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

重點我們來看他寫的HttpMethodRequestWrapper這個内部類,這個類繼承HttpServletRequestWrapper,而HttpServletRequestWrapper我進去看了下都是調用更上層的方法自己并沒有做什麼事情,再往上我就沒去看了。我了解的他的原理是:request在得到method時時使用getMethod方法的,是以他重寫了getMethod方法,進而可以把_method的值當做method。

那麼既然這樣,我也可以把_header的值當做header啊,而request擷取header的方法是public String getHeader(String name),是以我就寫了下面這樣的過濾器:

  1. package com.zs.tools;  
  2. import org.springframework.web.filter.HiddenHttpMethodFilter;  
  3.  * 張順,2017-2-28 
  4.  * 處理form表單頭的過濾器, 
  5.  * 如果表單有_header字段,可以自動将該字段轉為request的header頭資訊(增加一條頭) 
  6.  * @author it023 
  7. public class MyHiddenHttpMethodFilter extends HiddenHttpMethodFilter{  
  8.         String header=request.getParameter("_header");  
  9.         if (header!=null && !header.trim().equals("")) {  
  10.             HttpServletRequest wrapper = new HttpHeaderRequestWrapper(request,header);  
  11.             super.doFilterInternal(wrapper, response, filterChain);  
  12.         }else {  
  13.             super.doFilterInternal(request, response, filterChain);  
  14.     private static class HttpHeaderRequestWrapper extends HttpServletRequestWrapper{  
  15.         private final String header;  
  16.         public HttpHeaderRequestWrapper(HttpServletRequest request,String licence) {  
  17.             this.header=licence;  
  18.         public String getHeader(String name) {  
  19.             if (name!=null &&   
  20.                     name.equals("licence") &&   
  21.                     super.getHeader("licence")==null) {  
  22.                 return header;  
  23.             }else {  
  24.                 return super.getHeader(name);  
  25.             }  

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

  1.         <filter-name>httpHeaderFilter</filter-name>  
  2.         <filter-class>com.zs.tools.MyHiddenHttpMethodFilter</filter-class>  

結果

結果很成功,具體的代碼我不想貼了,請看日志,這一條表示擷取到http頭的licence(不要在意licence為什麼這麼簡單,那是因為這是測試資料)。

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