在做一个小程序项目的时候,由于小程序发过来的json数据比较多,在进入到controller层之前需要拦截下判断openid表示是否合法,并且把判断是查询到的user对象(openid唯一表示)放到request中,把json转成map放到request中,再有controller接收,这里就用到了HttpServletRequestWrapper对象,拦截器拦截到请求后,拿到request的请求体,代码如下:
首先一个request封装器:
package com.wxccase.utils;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
* MyRequestWrapper.
*
* @author havery
*/
public class JsonRequestWrapper extends HttpServletRequestWrapper {
private final String body;
public JsonRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
StringBuffer stringBuilder = new StringBuffer();
byte[] b = new byte[1024];
int len = 0;
InputStream inputStream = null;
try {
inputStream = request.getInputStream();
if (inputStream != null) {
//我真的要哭了 终于找到核心所在了 我操了草 这里给拿到body默认给搞成gbk了,我还需要转成utf8就麻烦的受不了的,在这里就要直接拿到utf8格式的
while ((len = inputStream.read(b)) != -1){
stringBuilder.append(new String(b, 0, len, "utf-8"));
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
throw ex;
} finally {
if( inputStream != null){
inputStream.close();
}
}
body = stringBuilder.toString();
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
ServletInputStream servletInputStream = new ServletInputStream() {
public int read() throws IOException {
return byteArrayInputStream.read();
}
@Override
public boolean isFinished() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isReady() {
// TODO Auto-generated method stub
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
// TODO Auto-generated method stub
}
};
return servletInputStream;
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
public String getBody() {
return this.body;
}
}
这里一定要使用utf-8编码进行读取request的字节输入流。这样在读取中文时才不会出现乱码(Springmvc在web.xml的utf-8强制转码在这里无效,因为直接拿到的request的字节输入流)
然后springmvc拦截器:
package com.wxccase.interceptor.unit;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import com.wxccase.exception.GlobalErrorInfoException;
import com.wxccase.exception.code.FormatErrorInfoEnum;
import com.wxccase.utils.JsonRequestWrapper;
import com.wxccase.utils.JsonToMap;
public class FormatInterceptor extends HandlerInterceptorAdapter{
@Resource
private JsonToMap jsonToMap;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
JsonRequestWrapper myJsonRequestWrapper = new JsonRequestWrapper(request);
Map info = null;
try{
info = jsonToMap.jsonToMapUtil(myJsonRequestWrapper.getBody());
}catch(Exception e){
throw new GlobalErrorInfoException(FormatErrorInfoEnum.FORMAT_ERROR);
}
myJsonRequestWrapper.setAttribute("info", info);
return true;
}
}
在xml中做如下配置::
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/extra/**"/>
<mvc:exclude-mapping path="/onlogin"/>
<bean class="com.wxccase.interceptor.unit.TokenidIntercepter"></bean>
</mvc:interceptor>
</mvc:interceptors>
这样就可以按照装饰器的思路重新封装一个request.(request只能读取一次)
使用到的jsonToMap如下:
package com.wxccase.utils;
import java.util.Map;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSON;
@Component
public class JsonToMap {
public Map jsonToMapUtil(String str) throws Exception{
System.out.println(str);
Map map = JSON.parseObject(str, Map.class);
return map;
}
}