程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> SpringMVC無法獲取請求中的參數的問題的調查與解決(2),springmvc參數

SpringMVC無法獲取請求中的參數的問題的調查與解決(2),springmvc參數

編輯:JAVA綜合教程

SpringMVC無法獲取請求中的參數的問題的調查與解決(2),springmvc參數


由於Request的getInputSteam()一旦獲取一次後,就再也無法獲取了

在實際項目中導致下面的問題:

1,多個攔截器,Filter都需要從InputStream中拿數據的情況無法處理;

2,InputStream被攔截器,Filter拿走了,Controller層無法getParameter(),也無法使用@RequestParam 注解來自動匹配設置參數。

 

 

參考了多篇處理getInputStream()相關的博文後,采取了下面的解決方案。

 

1,通過繼承HttpServletRequestWrapper創建自定義的Request對象,

在這個對象中,以字節數組形式長期保持Request的Stream內容,可以在攔截器,Filter,Controller中任意多次復用;

同時,重寫getParameter()相關的各個方法,確保從保持的Stream數據中,可以正常解析所有參數,並且在解析過程中,可以進行自定義的解碼操作。

package org.jiagoushi.mobile.rule.filter;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import com.mtime.mobile.utils.Encodes;

public class MAPIHttpServletRequestWrapper extends HttpServletRequestWrapper {
    private Map<String, String[]> paramsMap;

    @Override
    public Map getParameterMap() {
        return paramsMap;
    }

    @Override
    public String getParameter(String name) {// 重寫getParameter,代表參數從當前類中的map獲取
        String[] values = paramsMap.get(name);
        if (values == null || values.length == 0) {
            return null;
        }
        return values[0];
    }

    @Override
    public String[] getParameterValues(String name) {// 同上
        return paramsMap.get(name);
    }

    @Override
    public Enumeration getParameterNames() {
        return Collections.enumeration(paramsMap.keySet());
    }

    private String getRequestBody(InputStream stream) {
        String line = "";
        StringBuilder body = new StringBuilder();
        int counter = 0;

        // 讀取POST提交的數據內容
        BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
        try {
            while ((line = reader.readLine()) != null) {
                if (counter > 0) {
                    body.append("\r\n");
                }
                body.append(line);
                counter++;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return body.toString();
    }

    private HashMap<String, String[]> getParamMapFromPost(HttpServletRequest request) {

        String body = "";
        try {
            body = getRequestBody(request.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
        HashMap<String, String[]> result = new HashMap<String, String[]>();

        if (null == body || 0 == body.length()) {
            return result;
        }

        return parseQueryString(body);
    }

    // 自定義解碼函數
    private String decodeValue(String value) {
        if (value.contains("%u")) {
            return Encodes.decodeUnicode(value);
        } else {
            try {
                return URLDecoder.decode(value, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                return "";// 非UTF-8編碼
            }
        }
    }

    public HashMap<String, String[]> parseQueryString(String s) {
        String valArray[] = null;
        if (s == null) {
            throw new IllegalArgumentException();
        }
        HashMap<String, String[]> ht = new HashMap<String, String[]>();
        StringTokenizer st = new StringTokenizer(s, "&");
        while (st.hasMoreTokens()) {
            String pair = (String) st.nextToken();
            int pos = pair.indexOf('=');
            if (pos == -1) {
                continue;
            }
            String key = pair.substring(0, pos);
            String val = pair.substring(pos + 1, pair.length());
            if (ht.containsKey(key)) {
                String oldVals[] = (String[]) ht.get(key);
                valArray = new String[oldVals.length + 1];
                for (int i = 0; i < oldVals.length; i++) {
                    valArray[i] = oldVals[i];
                }
                valArray[oldVals.length] = decodeValue(val);
            } else {
                valArray = new String[1];
                valArray[0] = decodeValue(val);
            }
            ht.put(key, valArray);
        }
        return ht;
    }

    private Map<String, String[]> getParamMapFromGet(HttpServletRequest request) {
        return parseQueryString(request.getQueryString());
    }

    private final byte[] body; // 報文

    public MAPIHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        body = readBytes(request.getInputStream());

        // 首先從POST中獲取數據
        if ("POST".equals(request.getMethod().toUpperCase())) {
            paramsMap = getParamMapFromPost(this);
        } else {
            paramsMap = getParamMapFromGet(this);
        }

    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
        return new ServletInputStream() {

            @Override
            public int read() throws IOException {
                return bais.read();
            }
        };
    }

    private static byte[] readBytes(InputStream in) throws IOException {
        BufferedInputStream bufin = new BufferedInputStream(in);
        int buffSize = 1024;
        ByteArrayOutputStream out = new ByteArrayOutputStream(buffSize);

        byte[] temp = new byte[buffSize];
        int size = 0;
        while ((size = bufin.read(temp)) != -1) {
            out.write(temp, 0, size);
        }
        bufin.close();

        byte[] content = out.toByteArray();
        return content;
    }
}

 

2,自定義一個Filter(這個Filter的配置位置放在最靠前的位置),替換掉原始的Request對象:

web.xml中最靠前的位置增加Filter

...

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/api-spring.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
    <!-- 下面的Filter以自定義的Request對象替換掉原有的Request,進行POST數據的保持和自定義解碼 -->  
    <!-- 可以解決下面兩個問題:
         1,CheckUrl攔截器讀取InputStream導致getParameter()方法失效;
         2,POST數據由於有自定義Unicode編碼,解碼時也需要讀取InputSteam
     -->  
    <filter>  
        <filter-name>requestFilter</filter-name>  
        <filter-class>org.jiagoushi.mobile.rule.filter.HttpServletRequestReplacedFilter</filter-class>  
    </filter>  
    <filter-mapping>  
        <filter-name>requestFilter</filter-name>  
        <url-pattern>/*</url-pattern>  
    </filter-mapping>  


...

 

Filter類的代碼

package org.jiagoushi.mobile.rule.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

public class HttpServletRequestReplacedFilter implements Filter  {
    @Override  
    public void destroy() {  
          
    }  
  
    @Override  
    public void doFilter(ServletRequest request, ServletResponse response,  
            FilterChain chain) throws IOException, ServletException {  
        
        ServletRequest requestWrapper = null;    
        if(request instanceof HttpServletRequest) {  
            HttpServletRequest httpServletRequest = (HttpServletRequest) request;
            if("POST".equals(httpServletRequest.getMethod().toUpperCase())){
                requestWrapper = new MAPIHttpServletRequestWrapper((HttpServletRequest) request); 
            } 
        }

        if(requestWrapper == null) {    
            chain.doFilter(request, response);    
        } else {    
            chain.doFilter(requestWrapper, response);    //替換!
        }    
    }  
  
    @Override  
    public void init(FilterConfig arg0) throws ServletException {  
          
    }

}

 

 

---

參考資料:

http://ayaoxinchao.iteye.com/blog/2110902

http://my.oschina.net/tmallMoney/blog/127225

http://www.xuebuyuan.com/809435.html

http://hw1287789687.iteye.com/blog/1923085

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved