filter修改request参数

前言:根据项目要求,需要将request中的请求参数进行修改

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 HashMap<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一起搞出来*********
我擦现在项目又有需求了,要将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);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值