最近在做一个APP时,服务端需要在记录日志,记录所有请求过来的URL、IP以及参数,说道参数,那么问题来了,我是用过滤器来记录日志的,来看我在过滤器里面是怎么写的:
public void doFilter(ServletRequest arg0, ServletResponse arg1,
FilterChain arg2) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) arg0;
// 获取URL
String url = request.getRequestURL().toString();
// 获取参数
/*StringBuffer info=new java.lang.StringBuffer();
InputStream in=request.getInputStream();
BufferedInputStream buf=new BufferedInputStream(in);
BufferedInputStream bufBak=buf;
byte[] buffer=new byte[1024];
int iRead;
while((iRead=buf.read(buffer))!=-1)
{
info.append(new String(buffer,0,iRead,"UTF-8"));
}
logger.info(info.toString()+"------xxxxx------");*/
/* Collection<Part> ps= request.getParts();
for(Part p:ps){
Collection<String> cs=p.getHeaderNames();
for(String s:cs){
logger.info("------Collection----"+s);
}
}*/
String name=request.getParameter("userId");
logger.info("--------name------------"+name);
Map<String,String[]> map = request.getParameterMap();
String queryString = "";
for (String key : map.keySet()) {
String[] values = map.get(key);
for (int i = 0; i < values.length; i++) {
String value = values[i];
queryString += key + "=" + value + "&";
}
}
logger.info("--------------------"+queryString);
String userId=null;
//获取用户ID
String[] userIds = (String[]) map.get("userId");
if(null!=userIds&&0<userIds.length){
userId=userIds[0];
}
//活动区IP
String ip = this.getClientIp(request);
logger.info(url + " " + gson.toJson(map) + " " + ip + " " +userId);
//logger.info(arg0.hashCode()+"-------hashCode-------------"+req.hashCode());
arg2.doFilter(arg0, arg1);
}
可是运行后发现request.getParameterMap() 获取不到数据,怎么回事呢?
后来,我找Andriod客户端开放人员看了一下他们的客户端的请求代码,发现他们是用HttpURLConnection来进行请求的,大概的代码如下:
URL url = new URL(u);
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
// 设置是否向httpUrlConnection输出,因为这个是post请求,参数要放在
// http正文内,因此需要设为true, 默认情况下是false;
urlConn.setDoOutput(true);
// 设置是否从httpUrlConnection读入,默认情况下是true;
urlConn.setDoInput(true);
// Post 请求不能使用缓存
urlConn.setUseCaches(false);
// 设定传送的内容类型是可序列化的java对象
// (如果不设此项,在传送序列化对象时,当WEB服务默认的不是这种类型时可能抛java.io.EOFException)
urlConn.setRequestProperty("Content-Type","multipart/form-data; boundary="+"00content0boundary00\r\n");
//application/x-java-serialized-object
//urlConn.setRequestProperty("Content-type","application/x-www-form-urlencoded");
// 设定请求的方法为"POST",默认是GET
urlConn.setRequestMethod("POST");
// 连接,上面对urlConn的所有配置必须要在connect之前完成,
urlConn.connect();
/*
* Post传参的方法
*/
OutputStream os = urlConn.getOutputStream();
String param = new String(p);//参数以逗号分隔的字符串eg.name=xiaoming,age=23,sex=0
os.write(param.getBytes());
// 调用HttpURLConnection连接对象的getInputStream()函数,
// 将内存缓冲区中封装好的完整的HTTP请求电文发送到服务端。
StringBuffer info=new java.lang.StringBuffer();
InputStream inStrm = urlConn.getInputStream(); // <===注意,实际发送请求的代码段就在这里
BufferedInputStream buf=new BufferedInputStream(inStrm);
byte[] buffer=new byte[1024];
int iRead;
while((iRead=buf.read(buffer))!=-1)
{
info.append(new String(buffer,0,iRead,"UTF-8"));
}
System.out.println(info.toString()+"------xxxxx------");
return info.toString();
客户端的请求Content-Type设置成了
multipart/form-data; boundary="+"00content0boundary00\r\n"
这是一种对媒体MIME的格式,一般用来传输大文本或二进制文件上载。所以在request.getParameterMap()里面不能获取到客户端请求上来的参数
如果Content-Type设置成
application/x-www-form-urlencoded
就可以通过request.getParameterMap()获取到参数了,但是在向服务器发送大量的文本、包含非ASCII字符的文本或二进制数据时这种编码方式效率很低