环境:Spring 4.2.5.RELEASE ,tomcat:8.5.37
在做微信小程序的时候,前端用的是mpvue+flyio来发送请求,但是后台用request.getParam…获取不到参数值,后来经测试发现,无论前端发送请求的头部Content-Type设置成什么,结果发送的参数都会封装至body中以json字符串的格式发送到后台,后台只能以流的方式接受,但是涉及到登录验证时需要拦截器来验证是否包含登录信息时,需要在此时取出数据验证,但是问题来了,再拦截器中取得了参数信息,到真正执行的业务类中参数全部为空,下面是解决办法!
最后会有问题这种方案产生的问题,请看完!
新增过滤器 HttpServletFilter
package com.......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 com.....RequestWrapper;
public class HttpServletFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// System.out.println("过滤器");
ServletRequest requestWrapper = null;
if(request instanceof HttpServletRequest) {
requestWrapper = new RequestWrapper((HttpServletRequest) request);
}
if(requestWrapper == null) {
chain.doFilter(request, response);
} else {
chain.doFilter(requestWrapper, response);
}
}
public void destroy() {
}
}
新增工具类 RequestWrapper
package com....util;
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;
public class RequestWrapper extends HttpServletRequestWrapper {
private final String body;
public RequestWrapper(HttpServletRequest request) throws IOException {
super(request);
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
throw ex;
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
throw ex;
}
}
}
body = stringBuilder.toString();
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
ServletInputStream servletInputStream = new ServletInputStream() {
public boolean isFinished() {
return false;
}
public boolean isReady() {
return false;
}
public void setReadListener(ReadListener readListener) {}
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
return servletInputStream;
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream(),"UTF-8"));
}
public String getBody() {
return this.body;
}
}
新增拦截器 SessionInterceptor
package com.....interceptor;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSONObject;
import com.njpp.wxxcx.core.common.ErrCode;
import com.njpp.wxxcx.core.common.Tool;
import com.njpp.wxxcx.util.RequestWrapper;
public class SessionInterceptor implements HandlerInterceptor {
@Override
public void afterCompletion(HttpServletRequest arg0,
HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
// TODO Auto-generated method stub
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2, ModelAndView arg3) throws Exception {
// TODO Auto-generated method stub
}
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object arg2) throws Exception {
// System.out.println("拦截器");
// RequestWrapper myRequestWrapper = new RequestWrapper((HttpServletRequest) request);
String body = ((RequestWrapper)request).getBody();
// System.out.println(body);
JSONObject requestJson = JSONObject.parseObject(body);
JSONObject res = new JSONObject();
PrintWriter out = null;
try {
if (!Tool.existInRedis(requestJson)) {
res.put(ErrCode.STATE, ErrCode.INVALID);
out = response.getWriter();
out.append(res.toString());
return false;
} else {
return true;
}
} catch (Exception e) {
e.printStackTrace();
response.sendError(500);
return false;
}
}
}
在service层使用 获取参数
Map paramMap = (Map) JSONObject.parse(((RequestWrapper)request).getBody());
还需要在spring-mvc.xml中添加配置
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/user/**" />
<mvc:mapping path="/notice/**" />
<bean class="com.....SessionInterceptor">bean>
mvc:interceptor>
mvc:interceptors>
在web.xml中添加配置
<filter>
<filter-name>requestFilterfilter-name>
<filter-class>com.njpp.wxxcx.core.filter.HttpServletFilterfilter-class>
filter>
<filter-mapping>
<filter-name>requestFilterfilter-name>
<url-pattern>/notice/*url-pattern>
<url-pattern>/user/*url-pattern>
filter-mapping>
注意,这两个配置的拦截配置需要相同,不然会报错,,请求必须为POST,还有会有人问为什么不写/*,因为这个方法会影响上传文件,需要把上传文件独立出来不被拦截才行,不拦截的方法需要用如下的POST方式取参:
/**
* 从request中获得参数Map,并返回可读的Map code专用
*
* @param request
* @return
* @throws Exception
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static Map getParameterMapCode(HttpServletRequest request)
throws Exception {
// 获取提交方式(GET/POST)
String submitMehtod = request.getMethod();
Map<String, Object> paramMap = null;
Map properties = request.getParameterMap();
if (submitMehtod.equals("GET")) {
paramMap = getMethod(request);
// POST
} else {
paramMap = postMethod(request);
}
if (paramMap == null) {
paramMap = new HashMap<String, Object>();
}
return paramMap;
}
// get请求获取参数
private static Map getMethod(HttpServletRequest request) {
// 返回值Map
Map returnMap = new HashMap();
// 参数Map
Map properties = request.getParameterMap();
Iterator entries = properties.entrySet().iterator();
Map.Entry entry;
String name = "";
String value = "";
while (entries.hasNext()) {
entry = (Map.Entry) entries.next();
name = (String) entry.getKey();
Object valueObj = entry.getValue();
if (null == valueObj) {
value = "";
} else if (valueObj instanceof String[]) {
String[] values = (String[]) valueObj;
for (int i = 0; i < values.length; i++) {
value = values[i] + ",";
}
value = value.substring(0, value.length() - 1);
} else {
value = valueObj.toString();
}
returnMap.put(name, value);
}
return returnMap;
}
// 处理POST请求参数
private static Map postMethod(HttpServletRequest request)
throws IOException {
byte buffer[] = getRequestPostBytes(request);
String charEncoding = request.getCharacterEncoding();
if (charEncoding == null) {
charEncoding = "UTF-8";
}
String param = new String(buffer, charEncoding);
if(Tool.isEmpty(param)){
return null;
}
return (Map) JSONObject.parse(param);
}
/**
* 描述:获取 post 请求的 byte[] 数组
*
*
* 举例:
*
*
* @param request
* @return
* @throws IOException
*/
private 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;
}