Spring拦截器关于获取request body参数问题(request body miss)

我是个java小白,在近期的开发中,有这样一个任务,拦截请求,统一对请求进行token的验证,由于特殊原因,工程全部采用post请求。想到的就是拦截器、Filter、aop。

由于要求尽量使用spring组件,所以排除Filter,由于工程的URL没有统一规范,所以aop也排除,最后使用了拦截器,在使用的过程中会出现Required request body is missing错误,经过查找资料发现是request body中获取参数时使用流获取,但是request的流只能使用一次,给出的办法就是在获取流之前对流进行复制。具体实现见下面代码。

1:首先自定义一个类继承HttpServletRequestWrapper,用来备份流

public class BufferedServletRequestWrapper extends HttpServletRequestWrapper {

	private byte[] buffer;

	public BufferedServletRequestWrapper(HttpServletRequest request) throws IOException {
		super(request);
		InputStream is = request.getInputStream();
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		byte buff[] = new byte[1024];
		int read;
		while ((read = is.read(buff)) > 0) {
			baos.write(buff, 0, read);
		}
		this.buffer = baos.toByteArray();
	}

	@Override
	public ServletInputStream getInputStream() throws IOException {
		return new BufferedServletInputStream(this.buffer);
	}

	// 对外提供读取流的方法
	@Override
	public BufferedReader getReader() throws IOException {
		return new BufferedReader(new InputStreamReader(getInputStream()));
	}
}

2:在spring配置文件中自定义拦截器组件


		
		
			
			
				
					
						/doctorWebLoginAccount/doctorLogin/app
						/doctorWebLoginAccount/doctorLogin/web
						/ws
						/fileUpload/uploadPicture
						/fileUpload/uploadSignature
						/doctor/registe
						/hospitalAndDepartment/findHospital
						/hospitalAndDepartment/findDepartment
						/hospDoctorTreatment/usageSelect
						/chiefComplaint/symptom
						/initialDiagnose/list
						/doctor/patientInfo
						/doctor/updateAccountInfo
						/doctor/getMessageCode
						/doctor/storeBaseInfo
						/doctor/storeBaseGoods/list
						/doctor/checkPhoneNum
						/storeBaseGoods/pageList
					
				
			
		
	

3:定义拦截的实现类

public class ValidateTokenInterceptor implements HandlerInterceptor{
    
    //不拦截的请求
    private String[] excludeMapping;
	
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		//不需要过滤的请求
		for(String exclude : excludeMapping){
			if(request.getRequestURI().endsWith(exclude)){
				return true;
			}
		}
		BufferedServletRequestWrapper requestWrapper = new BufferedServletRequestWrapper(request);
    //在这边替换流,使用工具类GetRequestJsonUtils获取json参数
		JSONObject json = GetRequestJsonUtils.getRequestJsonObject(requestWrapper);
		return true;
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		logger.info("返回视图之前!");
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		logger.info("请求结束之后!");
	}

	public void setExcludeMapping(String[] excludeMapping) {
		this.excludeMapping = excludeMapping;
	}
	
	
}

4:最后自定义一个Filter(spring请求的链式执行顺序为Filter-->拦截器-->controller)用来备份流

public class TranslateRequestWrapper implements Filter{

	/**
	 * 销毁
	 */
	@Override
	public void destroy() {
		
	}

	/**
	 * 过滤
	 */
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		ServletRequest requestWrapepr = null;
		if(request instanceof HttpServletRequest){
			requestWrapepr = new BufferedServletRequestWrapper((HttpServletRequest)request);
		}
		if(requestWrapepr == null){
			chain.doFilter(request, response);
		}else{
			chain.doFilter(requestWrapepr, response);
		}
	}

	/**
	 * 初始化
	 */
	@Override
	public void init(FilterConfig arg0) throws ServletException {
		
	}

}

5:附上从流中读取参数的工具类

public class GetRequestJsonUtils {
	public static JSONObject getRequestJsonObject(HttpServletRequest request) throws IOException {
		String json = getRequestJsonString(request);
		return JSONObject.parseObject(json);
	}
	 /***
     * 获取 request 中 json 字符串的内容
     * 
     * @param request
     * @return : byte[]
     * @throws IOException
     */
    public static String getRequestJsonString(HttpServletRequest request)
            throws IOException {
        String submitMehtod = request.getMethod();
        // GET
        if (submitMehtod.equals("GET")) {
        	if(StringUtils.isNotEmpty(request.getQueryString())){
        		return new String(request.getQueryString().getBytes("iso-8859-1"),"utf-8").replaceAll("%22", "\"");
        	}else{
        		return new String("".getBytes("iso-8859-1"), "utf-8").replaceAll("%22", "\"");
        	}
        // POST
        } else {
            return getRequestPostStr(request);
        }
    }
 
    /**      
     * 描述:获取 post 请求的 byte[] 数组
     * 
     * 举例:
     * 
* @param request * @return * @throws IOException */ public static byte[] getRequestPostBytes(HttpServletRequest request) throws IOException { int contentLength = request.getContentLength(); if(contentLength<0){ return null; } byte buffer[] = new byte[contentLength]; for (int i = 0; i < contentLength;) { int readlen = request.getInputStream().read(buffer, i, contentLength - i); if (readlen == -1) { break; } i += readlen; } return buffer; } /** * 描述:获取 post 请求内容 *
     * 举例:
     * 
* @param request * @return * @throws IOException */ public static String getRequestPostStr(HttpServletRequest request) throws IOException { byte buffer[] = getRequestPostBytes(request); String charEncoding = request.getCharacterEncoding(); if (charEncoding == null) { charEncoding = "UTF-8"; } return new String(buffer, charEncoding); } }

这样就不会出现request body si missing

你可能感兴趣的:(Java,WEB,Spring)