filter修改request参数
2017-11-16 20:20
253 查看
前言:根据项目要求,需要将request中的请求参数进行修改
转化为
所以在网上查看了很多资料发现可以用HttpServletRequestWrapper来实现,具体实现如下:
PS:在粘贴代码前先来知道一个从request中获取请求参数的方法
我们一般在时候springmvc的时候会用如下3中方法来回去数据(3和2是一样的调用getParameterValues(name)方法)
现在我们知道了怎么来获取参数就好办了。
其实我们在调用1、2方法的时候是在调用ServletRequest的getParameter(name)和getParameterValues(name)方法,所以要想修改请求参数只要在传递参数的时候用不同的实现类即可,恰好HttpServletRequestWrapper给了我们这个机会,查看一下HttpServletRequestWrapper 的源码可以发现其实内部的所有重写的方法都是调用ServletRequestWrapper的方法,而ServletRequestWrapper类中正好有一个ServletRequest属性,所以我们只需要重写HttpServletRequestWrapper中的getParameter(name)和getParameterValues(name)即可。
妈的,说了一堆废话直接上代码:
filter中的方法连同修改response一起搞出来[b]*********[/b]
我擦现在项目又有需求了,要将controller中返回的明文数据进行加密(我们总不能封装一个加密方法之后再所有的接口上都加上加密方法在输出吧,这样太虎了,冗余还显得不高端,不利于后续维护),所以我的想法是在filter中将返回的response进行拦截。于是顺着上面的例子我找到了
发现一个问题我们在使用response的时候可以有两种方式进行输出
然而在我们在controller层直接返回对象的时候,实际上调用的是ServletResponse.getOutputStream().write(int b)方法;
所以我们只需要继承HttpServletResponseWrapper重写HttpServletResponseWrapper中个getOutputStream方法(因为返回的是ServletOutputStream是一个抽象类没有实现write(int b)方法所以要创建一个类来实现此方法),墨迹这么多代码如下:
值得注意的是如下:
1。因为我们重写了write(int b)方法所以我们要指定一个字节数组的输出流往其内部进行书写
2。要有一个获取字节数字的方法(方法前一定要flush防止数据缺失)
现在要写filter方法
当我们完成了这次操作的时候会发现一个问题,比如说我们在controlle返回的是”123456789”(UTF-8)
我们在out.write(“我爱你亲爱的姑娘”);的时候会发现前台只返回了”我爱你”;
这里注意response.setContentLength(-1);
body: { //adsfasdfasdf为加密后的json串(如加密前{name:'张三','age':'18'}) 'data':'adsfasdfasdf'加密后的数据 }
转化为
body: { name : 张三, age : 18 }
所以在网上查看了很多资料发现可以用HttpServletRequestWrapper来实现,具体实现如下:
PS:在粘贴代码前先来知道一个从request中获取请求参数的方法
1、request.getParameter(name);
2、request.getParameterValues(name);
3、 @RequestMapping("/getRequestParameter") @ResponseBody public int getRequestParameter(String name, Integer age){ return 1; }
我们一般在时候springmvc的时候会用如下3中方法来回去数据(3和2是一样的调用getParameterValues(name)方法)
现在我们知道了怎么来获取参数就好办了。
HttpServletRequestWrapper extends ServletRequestWrapper implements HttpServletRequest extends ServletRequest ServletRequestWrapper implements ServletRequest
其实我们在调用1、2方法的时候是在调用ServletRequest的getParameter(name)和getParameterValues(name)方法,所以要想修改请求参数只要在传递参数的时候用不同的实现类即可,恰好HttpServletRequestWrapper给了我们这个机会,查看一下HttpServletRequestWrapper 的源码可以发现其实内部的所有重写的方法都是调用ServletRequestWrapper的方法,而ServletRequestWrapper类中正好有一个ServletRequest属性,所以我们只需要重写HttpServletRequestWrapper中的getParameter(name)和getParameterValues(name)即可。
妈的,说了一堆废话直接上代码:
package com.example.demo; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.Vector; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; public class RequestWrapper extends HttpServletRequestWrapper { //注意这里我们要创建一个map,让后续getParameter和getParameterValues方法直接从map中获取即可 private Hash 4000 Map<String, String> parameter; public RequestWrapper(HttpServletRequest request, HashMap<String, String> parameters) { super(request); parameter = new HashMap<String, String>(); for(Map.Entry<String, String> entry : parameters.entrySet()) { parameter.put(entry.getKey(), entry.getValue()); } } @Override public String getParameter(String name) { return parameter.get(name); } @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public Map getParameterMap() { return parameter; } @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public Enumeration getParameterNames() { return new Vector(parameter.keySet()).elements(); } @Override public String[] getParameterValues(String name) { String[] result = null; Object v = parameter.get(name); if (v == null) { result = null; } else if (v instanceof String[]) { result = (String[]) v; } else if (v instanceof String) { result = new String[] { (String) v }; } else { result = new String[] { v.toString() }; } return result; } }
上面代码中有几个刚才没有说过的代码,当我们在controller中调用request的什么方法,在RequestWrapper 中就要重写这个方法。
———————————————————————————filter中的方法连同修改response一起搞出来[b]*********[/b]
我擦现在项目又有需求了,要将controller中返回的明文数据进行加密(我们总不能封装一个加密方法之后再所有的接口上都加上加密方法在输出吧,这样太虎了,冗余还显得不高端,不利于后续维护),所以我的想法是在filter中将返回的response进行拦截。于是顺着上面的例子我找到了
HttpServletResponseWrapper extends ServletResponseWrapper implements HttpServletResponse extends ServletResponse ServletResponseWrapper implements ServletResponse
发现一个问题我们在使用response的时候可以有两种方式进行输出
httpServletResponse.getOutputStream().write("".getBytes()); httpServletResponse.getWriter().write("");
然而在我们在controller层直接返回对象的时候,实际上调用的是ServletResponse.getOutputStream().write(int b)方法;
所以我们只需要继承HttpServletResponseWrapper重写HttpServletResponseWrapper中个getOutputStream方法(因为返回的是ServletOutputStream是一个抽象类没有实现write(int b)方法所以要创建一个类来实现此方法),墨迹这么多代码如下:
package com.example.demo; import java.io.ByteArrayOutputStream; import java.io.IOException; import javax.servlet.ServletOutputStream; import javax.servlet.WriteListener; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; public class ResponseWrapper extends HttpServletResponseWrapper{ private ByteArrayOutputStream buffer = null; private ServletOutputStream out = null; public ResponseWrapper(HttpServletResponse resp) throws IOException { super(resp); buffer = new ByteArrayOutputStream(); out = new WapperedOutputStream(buffer); } @Override public ServletOutputStream getOutputStream() throws IOException { return out; } @Override public void flushBuffer() throws IOException { if (out != null) { out.flush(); } } @Override public void reset() { buffer.reset(); } /** 将out、writer中的数据强制输出到WapperedResponse的buffer里面,否则取不到数据 */ public String getResponseContent() throws IOException { flushBuffer(); return new String(buffer.toByteArray(), this.getCharacterEncoding()); } /** 内部类,对ServletOutputStream进行包装 */ private class WapperedOutputStream extends ServletOutputStream { private ByteArrayOutputStream bos = null; public WapperedOutputStream(ByteArrayOutputStream stream)throws IOException { bos = stream; } @Override public void write(int b) throws IOException { bos.write(b); } @Override public void write(byte[] b) throws IOException { bos.write(b, 0, b.length); } @Override public boolean isReady() { return false; } @Override public void setWriteListener(WriteListener listener) { } } }
值得注意的是如下:
1。因为我们重写了write(int b)方法所以我们要指定一个字节数组的输出流往其内部进行书写
2。要有一个获取字节数字的方法(方法前一定要flush防止数据缺失)
现在要写filter方法
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest)request; HttpServletResponse httpServletResponse = (HttpServletResponse)response; RequestWrapper requestWrapper = new RequestWrapper(httpServletRequest, bodyParameters); ResponseWrapper responseWrapper = new ResponseWrapper(httpServletResponse); chain.doFilter(requestWrapper, responseWrapper); String responseContent= responseWrapper.getResponseContent(); //response.setContentLength(-1); PrintWriter out = response.getWriter(); String string = "原內容:" + responseContent + "加密后的内容" + "1234567890asdfghjkl"; out.write(string); out.flush(); out.close(); }
当我们完成了这次操作的时候会发现一个问题,比如说我们在controlle返回的是”123456789”(UTF-8)
我们在out.write(“我爱你亲爱的姑娘”);的时候会发现前台只返回了”我爱你”;
这里注意response.setContentLength(-1);
相关文章推荐
- 继承HttpServletRequestWrapper以实现在Filter中修改HttpServletRequest的参数
- 在filter中修改request参数
- filter对request请求拦截,对请求参数进行修改
- 继承HttpServletRequestWrapper以实现在Filter中修改HttpServletRequest的参数
- 如何使用wrapper在filter修改request参数
- 使用HttpServletRequestWrapper在filter修改request参数
- 继承HttpServletRequestWrapper以实现在Filter中修改HttpServletRequest的参数
- 在filter中使用包装类包装request、response分别修改请求参数和修改响应结果
- 继承HttpServletRequestWrapper以实现在Filter中修改HttpServletRequest的参数
- 自定义类封装request配合filter解决参数乱码
- springMvc 完美解决 multipart/form-data 方式提交请求 在 Filter 中 ServletRequest.getParameter方法 获取不到参数的问题
- 修改HttpServletRequest的参数【转】
- 修改HttpServletRequest的参数【转】
- springmvc中修改request的参数以及实现去空格功能
- Fiddler:如何读取本地文件修改Request参数
- HttpServletRequest修改header参数
- 软键盘实例 request参数修改
- 解决在Filter中读取Request中的流后, 然后在Controller中@RequestBody的参数无法注入而导致 400 错误
- springMvc 完美解决 multipart/form-data 方式提交请求 在 Filter 中 ServletRequest.getParameter方法 获取不到参数的问题
- struts2 拦截器修改request的parameters参数失败的问题