SSM攔截器校驗JSON數據(3) -- 解決攔截器獲取json後,controller參數爲空

本篇爲系列文,不以目的爲目的,以學習爲目的。旨在學習,重在研究。

上一篇:SSM攔截器校驗JSON數據(2) -- 從Request中獲取json格式數據

創建AccountWrapper繼承HttpServletRequestWrapper

HttpServletRequestWrapper介紹

package sinosoft.project.sso.utils.wrapper;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;

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

import org.springframework.util.StreamUtils;

/**
 * @Description:  Account--Request--請求包裝類,解決json只能接受一次的問題
 */
public class AccountWrapper extends HttpServletRequestWrapper{

	private byte[] requestBody;
	
	public AccountWrapper(HttpServletRequest request) throws IOException {
		super(request);
		requestBody = StreamUtils.copyToByteArray(request.getInputStream());
	}

	@Override
	public BufferedReader getReader() throws IOException {
		return new BufferedReader(new InputStreamReader(getInputStream(),StandardCharsets.UTF_8));
	}
	
	@Override
	public ServletInputStream getInputStream() throws IOException {
		if(requestBody == null){
			requestBody = new byte[0];
		}
		final ByteArrayInputStream  bais = new ByteArrayInputStream(requestBody);
		return new ServletInputStream() {
			
			@Override
			public int read() throws IOException {
				return bais.read();
			}
			
			@Override
			public void setReadListener(ReadListener readListener) {
				
			}
			
			@Override
			public boolean isReady() {
				return false;
			}
			
			@Override
			public boolean isFinished() {
				return false;
			}
		};
	}
}

修改preHandle的代碼

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
	try{
		AccountInfo accountInfo = ssoJsonUtil.getParam(request);
		//省略業務判斷邏輯代碼
	}catch (Exception e) {
		return false;
	}
}    

/**
*@Description: 解析request裏的AccountInfo
*/
public AccountInfo getParam(HttpServletRequest request) throws IOException, SSOException {
	String jsonString = null;
	String submitMethod = request.getMethod();
	if("GET".equals(submitMethod) || submitMethod.equals("get")){
		jsonString = getParamStringByGet(request);
	}else if(submitMethod.equals("POST") || submitMethod.equals("post")){
		jsonString = getParamJsonStringByPost(request);
	}else{
		logger.error("GetRequestJsonUtil解析Request參數錯誤--"+submitMethod);
	}
	logger.info("解析出來的參數--getParam:{}",jsonString);
	if(StringUtils.isBlank(jsonString)){
		throw new SSOException(new ReturnMsg(EC.RTF_FALSE,EC.ERR_PARAM_NULL_CODE,EC.ERR_PARAM_NULL_MSG));
	}
	AccountInfo parse = JSONObject.parseObject(jsonString, AccountInfo.class);
	return parse;
}

/**
*@Description: 解析post方式提交的json數據
*/
private String getParamJsonStringByPost(HttpServletRequest request) throws IOException {
    //這裏修改了
	AccountWrapper aWrapper = new AccountWrapper(request);
	int contentLength = aWrapper.getContentLength();
	if(contentLength<0){
		return null;
	}
	byte buffer[]  = new byte[contentLength];
	for (int i = 0; i < contentLength; i++) {
		int readlen = aWrapper.getInputStream().read(buffer,i,contentLength -i);
		if(readlen == -1){
			break;
		}
		i+=readlen;
	}
	return new String(buffer,"UTF-8");
}

/**
*@Description: 解析get方式提交的request參數
*/
private String getParamStringByGet(HttpServletRequest request) throws IOException {
    //這裏修改了
	AccountWrapper aWrapper = new AccountWrapper(request);
	return new String(aWrapper.getQueryString().getBytes("ios-8859-1"),"utf-8").replaceAll("%22", "\"");
}

這樣並沒有解決問題,因爲request中的數據在複製給AccountWrapper 時讀取過了(調用了request.getInputstream方法),所以要用AccountWrapper 代替request傳到controller中。

這樣就需要用過濾器配合

配置過濾器AccountFilter

package sinosoft.project.sso.utils.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;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import sinosoft.project.sso.utils.wrapper.AccountWrapper;

/**
 * @Description:  過濾器,用於controller可以獲取json
 */

public class AccountFilter implements Filter{

	Logger logger = LoggerFactory.getLogger(AccountFilter.class);
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		AccountWrapper accountWrapper = null;
		logger.info("AccountFilter--doFilter");
		if(request instanceof HttpServletRequest){
			accountWrapper = new AccountWrapper((HttpServletRequest)request);
		}
		if(accountWrapper == null){
			chain.doFilter(request, response);
		}else {
			chain.doFilter(accountWrapper, response);//在這裏將AccountWrapper代替request去了controller
		}
	}

	@Override
	public void destroy() {
		
	}

}

web.xml配置過濾器

<filter>
  	<filter-name>ssoAccountFilter</filter-name>
  	<filter-class>sinosoft.project.sso.utils.filter.AccountFilter</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>ssoAccountFilter</filter-name>
  	<url-pattern>/sso/account/*</url-pattern>
  </filter-mapping>

spring-mvc註冊攔截器 (如果在第一篇文章時配置了就不需要了)

<!-- 註冊攔截器 -->
<!--攔截器-->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/sso/account/**" /> <! --攔截路徑 -- >
        <bean class="sinosoft.project.sso.account.interceptor.AccountInterceptor"></bean>
    </mvc:interceptor>
</mvc:interceptors>

 

大功告成

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章