1. 程式人生 > >springMVC列印請求資訊日誌,如請求頭,請求體,請求路徑等

springMVC列印請求資訊日誌,如請求頭,請求體,請求路徑等

處理類LoggingFilter :

package com.zqsign.app.privatearbitrate.interceptor;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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;

import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSONObject;


public class LoggingFilter implements Filter {
	Logger logger = Logger.getLogger(LoggingFilter.class);  
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		// TODO Auto-generated method stub
		javax.servlet.http.HttpServletRequest req = (javax.servlet.http.HttpServletRequest)request;
		Map<String, Object> map = new HashMap<String, Object>();
		HttpServletRequest requestWrapper = new RepeatedlyReadRequestWrapper(req);

		try {
			// Get request URL.
			map.put("URL", req.getRequestURL());
			map.put("Method", req.getMethod());
			map.put("Protocol",req.getProtocol());
			// 獲取header資訊
			
			List<Map<String,String>> headerList = new ArrayList<>();
			Map<String,String> headerMaps = new HashMap<String,String>();
			for(Enumeration<String> enu = req.getHeaderNames();enu.hasMoreElements();){
				String name = enu.nextElement();
				headerMaps.put(name,req.getHeader(name));
			}
			headerList.add(headerMaps);
			map.put("headers", headerList);
			//獲取parameters資訊
			
			List<Map<String,String>> parameterList = new ArrayList<>();
			Map<String,String> parameterMaps = new HashMap<String,String>();
			for(Enumeration<String> names = req.getParameterNames();names.hasMoreElements();){
				String name = names.nextElement();
				parameterMaps.put(name, req.getParameter(name));
			}
			parameterList.add(parameterMaps);
			map.put("parameters", parameterList);
			String line = "";
			// 獲取請求體資訊
			if (req.getMethod().equalsIgnoreCase("POST")) {
				int len = req.getContentLength();
				char[] buf = new char[len];
				int bufcount = requestWrapper.getReader().read(buf);
				if (len > 0 && bufcount <= len) {
					line = String.copyValueOf(buf).substring(0, bufcount);
				}
			} else if (req.getMethod().equalsIgnoreCase("GET")) {
				int idx = req.getRequestURL().indexOf("?");
				if (idx != -1) {
					line = req.getRequestURL().substring(idx + 1);
				} else {
					line = null;
				}
			}
			if (line != null) {
				map.put("Context", new String[] { line });
			}
			logger.info("接收請求報文:\n"+JSONObject.toJSONString(map));
			chain.doFilter(requestWrapper, response);
		} catch (IOException ex) {
			ex.printStackTrace();
		}
		
		
	}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}


}

RepeatedlyReadRequestWrapper類:

package com.zqsign.app.privatearbitrate.interceptor;

import org.apache.commons.lang3.StringUtils;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;

/**
 * @author lidanyang
 * @date 2018/7/4
 */
public class RepeatedlyReadRequestWrapper extends HttpServletRequestWrapper {
    private final byte[] body;

    public RepeatedlyReadRequestWrapper(HttpServletRequest request)
            throws IOException {
        super(request);
        body = readBytes(request.getReader(), "UTF-8");
    }

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

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

            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener listener) {

            }

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

    /**
     * 通過BufferedReader和字元編碼集轉換成byte陣列
     * @param br
     * @param encoding
     * @return
     * @throws IOException
     */
    private byte[] readBytes(BufferedReader br,String encoding) throws IOException{
        String str = null,retStr="";
        while ((str = br.readLine()) != null) {
            retStr += str;
        }
        if (StringUtils.isNotBlank(retStr)) {
            return retStr.getBytes(Charset.forName(encoding));
        }
        return null;
    }
}

web.xml配置:

<filter>
    <filter-name>requestCopyFilter</filter-name>
    <filter-class>com.zqsign.app.privatearbitrate.interceptor.RepeatedlyReadFilter</filter-class>
    <async-supported>true</async-supported>
  </filter>
  <filter-mapping>
    <filter-name>requestCopyFilter</filter-name>
    <url-pattern>/local/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>ERROR</dispatcher>
  </filter-mapping>

總結:輸出的請求日誌如下:

{
	"Context": ["{\t\"caseCategoryInfoViewModel\": {\t\t\"agentInfoEntity\": {\t\t\t\"address\": \"sdfas\",\t\t\t\"agentType\": \"律師代理\",\t\t\t\"caseCategoryCode\": \"1513\",\t\t\t\"company\": \"fasdfa\",\t\t\t\"email\": \"[email protected]\",\t\t\t\"identityNo\": \"362226198908241213\",\t\t\t\"identityType\": \"身份證\",\t\t\t\"litigantType\": \"申請人\",\t\t\t\"mobile\": \"18615412359\",\t\t\t\"name\": \"fsdfas\",\t\t\t\"power\": \"一般代理\",\t\t\t\"powerDetail\": \"\",\t\t\t\"principal\": \"fasdf\",\t\t\t\"sex\": \"男\",\t\t\t\"uuid\": \"402882d8662900c601662907e2dc0002\"\t\t},\t\t\"applicantInfoEntity\": {\t\t\t\"addresses\": \"dfasdfasd\",\t\t\t\"caseCategoryCode\": \"1513\",\t\t\t\"contact\": \"sdfasf\",\t\t\t\"email\": \"[email protected]\",\t\t\t\"identityNo\": \"123456789123456QWE\",\t\t\t\"identityType\": \"組織機構程式碼證\",\t\t\t\"legalRepresent\": \"fasdf\",\t\t\t\"mobile\": \"18615412359\",\t\t\t\"name\": \"fasdfa\",\t\t\t\"nature\": \"企業\",\t\t\t\"post\": \"行長\",\t\t\t\"uuid\": \"402882d8662900c601662907e2d80001\"\t\t},\t\t\"caseCategoryEvidenceEntityList\": [],\t\t\"caseCategoryInfoEntity\": {\t\t\t\"appealTemplate\": \"fsafsd\",\t\t\t\"appealType\": 1,\t\t\t\"businessCode\": \"sdfas\",\t\t\t\"businessName\": \"fasdfas\",\t\t\t\"caseCategoryCode\": \"1513\",\t\t\t\"caseCategoryName\": \"fsdfasdfad\",\t\t\t\"caseCategoryStatus\": -1,\t\t\t\"commissionCode\": \"gzac\",\t\t\t\"createTime\": 1538286674000,\t\t\t\"platformName\": \"sfa\",\t\t\t\"tenantName\": \"fasdfa\",\t\t\t\"uuid\": \"402882d8662900c601662907e2b50000\",\t\t\t\"zqid\": \"ZQf31ad1a694ab4105800d2aa90389f67f\"\t\t}\t}}"],
	"headers": [{
		"content-length": "1437",
		"cookie": "SESSION=e32500b2-c1e9-499e-a452-09a202ddd5ff",
		"postman-token": "6556ef77-7c56-4fc3-aaa1-917d3e4f0b17",
		"host": "localhost:8083",
		"content-type": "application/json",
		"connection": "keep-alive",
		"cache-control": "no-cache",
		"accept-encoding": "gzip, deflate",
		"user-agent": "PostmanRuntime/7.1.1",
		"accept": "*/*"
	}],
	"Method": "POST",
	"Protocol": "HTTP/1.1",
	"parameters": [{}],
	"URL": "http://localhost:8083/web/local/case-category-info/deployment"
} >

作用:用來排查前後端互動時因請求資訊不一致所引起的問題。