springBoot-如何修改请求和返回参数

一、 需求      

       有时候做项目,我们希望在请求未到达controller层,修改请求参数,为什么有这种需求,比如:参数需要验签和加解密之后赋值使用,如果没有进行验签和解密显然请求会异常。ServletRequest和HttpServletRequest中的请求参数是不能进行修改的,因此有了ServletRequestWrapper和HttpServletRequestWrapper可以进行修改请求参数,controller中的请求参数,都是通过getParameter(String name) 或者 getParameterValues(String name)这两个方法类赋值转换的,因此重新定义类来修改请求参数,我们继承HttpServletRequestWrapper,然后重写getParameter(String name)、getParameterValues(String name)。(这里用到了装饰者模式)

       同样通过自定义类来修改返回参数,可以保护重要信息,比如对返回参数加密或者脱敏处理等

二、 实现

1、pom文件



	4.0.0
	
		org.springframework.boot
		spring-boot-starter-parent
		2.1.1.RELEASE
		 
	
	com.cn.dl
	springbootfilterdemo
	0.0.1-SNAPSHOT
	springbootfilterdemo
	Demo project for Spring Boot

	
		1.8
	

	
		
			org.springframework.boot
			spring-boot-starter-web
		

		
			org.springframework.boot
			spring-boot-starter-test
			test
		

		
			com.alibaba
			fastjson
			1.2.47
		

		
			org.projectlombok
			lombok
		
		
			com.google.inject
			guice
			4.1.0
			test
		
		
			javax.validation
			validation-api
		
        
            commons-io
            commons-io
            2.6
        
	

	
		
			
				org.springframework.boot
				spring-boot-maven-plugin
			
		
	


2、ParameterServletRequestWrapper:处理请求参数

package com.cn.dl.config;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class ParameterServletRequestWrapper extends HttpServletRequestWrapper {

    private Map params = new HashMap();
    
    public ParameterServletRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        this.params.putAll(request.getParameterMap());
    }

    /**
     * 重载一个构造方法
     * @param request
     * @param extendParams
     */
    public ParameterServletRequestWrapper(HttpServletRequest request , Map extendParams) throws IOException {
        this(request);
        addAllParameters(extendParams);
    }

    @Override
    public String getParameter(String name) {
        String[]values = params.get(name);
        if(values == null || values.length == 0) {
            return null;
        }
        return values[0];
    }

    @Override
    public String[] getParameterValues(String name) {
        return params.get(name);
    }

    public void addAllParameters(MapotherParams) {
        for(Map.Entryentry : otherParams.entrySet()) {
            addParameter(entry.getKey() , entry.getValue());
        }
    }


    public void addParameter(String name , Object value) {
        if(value != null) {
            if(value instanceof String[]) {
                params.put(name , (String[])value);
            }else if(value instanceof String) {
                params.put(name , new String[] {(String)value});
            }else {
                params.put(name , new String[] {String.valueOf(value)});
            }
        }
    }
}

3、ParameterServletResponseWrapper :处理返回参数

package com.cn.dl.config;

import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.*;

public class ParameterServletResponseWrapper extends HttpServletResponseWrapper {

    private ByteArrayOutputStream buffer;
    private ServletOutputStream out;
    private PrintWriter writer;

    public ParameterServletResponseWrapper(HttpServletResponse resp) throws IOException {
        super(resp);
        buffer = new ByteArrayOutputStream();
        out = new WapperedOutputStream(buffer);
        writer = new PrintWriter(new OutputStreamWriter(buffer,
                this.getCharacterEncoding()));
    }

    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        return out;
    }

    @Override
    public PrintWriter getWriter() throws UnsupportedEncodingException {
        return writer;
    }

    @Override
    public void flushBuffer() throws IOException {
        if (out != null) {
            out.flush();
        }
        if (writer != null) {
            writer.flush();
        }
    }

    @Override
    public void reset() {
        buffer.reset();
    }

    public byte[] getResponseData() throws IOException {
        flushBuffer();
        return buffer.toByteArray();
    }

    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 void setWriteListener(WriteListener writeListener) {

        }

        @Override
        public boolean isReady() {
            return false;
        }
    }

}

4、RequestParam

package com.cn.dl.bean;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
 * Created by yanshao on 2019/2/12.
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class RequestParam implements Serializable {

    private static final long serialVersionUID = 8608875806674149703L;

    private String data1;
    private String data2;
    private String data3;
    private int data4;

    @Override
    public String toString() {
        //将bean转换成bean string
        return JSON.toJSONString(this);
    }
}

5、WebFilterParam:对请求和返回进行过滤处理

在项目中我们一般都是继承servlet中的Filter来实现过滤,而现在推荐使用OncePerRequestFilter,OncePerRequestFilter能够确保一次请求只过滤一次,不会重复执行,我们经常用的servlet Filter,servlet版本不一样,过滤请求的情况都不一样,而OncePerRequestFilter能够兼容不同的servlet版本和运行环境。

package com.cn.dl.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cn.dl.bean.RequestParam;
import com.cn.dl.config.ParameterServletRequestWrapper;
import com.cn.dl.config.ParameterServletResponseWrapper;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by yanshao on 2019/2/12.
 */
public class WebFilterParam extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        PrintWriter out = response.getWriter();

        Map parameterMap = new HashMap<>(request.getParameterMap());
        //修改请求参数
        parameterMap.put("data1",new String[]{"data1"});
        parameterMap.put("data2",new String[]{"data2"});
        parameterMap.put("data3",new String[]{"data3"});
        parameterMap.put("data4",new String[]{"44"});
        ParameterServletRequestWrapper req = new ParameterServletRequestWrapper(request, parameterMap);
        ParameterServletResponseWrapper resp = new ParameterServletResponseWrapper(response);

        //调用对应的controller
        super.doFilter(req,resp,filterChain);

        //对返回参数进行处理
        resp.setContentLength(-1);
        RequestParam requestParam = JSONObject.toJavaObject(JSON.parseObject(new String(resp.getResponseData())), RequestParam.class);
        requestParam.setData1("****");
        requestParam.setData2("****");
        out.print(requestParam.toString());
        out.flush();
        out.close();
    }
}

6、WebConfig:配置过滤器

package com.cn.dl.config;

import com.cn.dl.filter.WebFilterParam;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


/**
 * Created by yanshao on 2018/12/26.
 */
@Configuration
public class WebConfig{

//    @Bean
//    public FilterRegistrationBean WebFilterDemo(){
//         TODO: 2018/12/26 配置了过滤器
//        FilterRegistrationBean frBean = new FilterRegistrationBean();
//        frBean.setFilter(new WebFilterDemo());
//        frBean.addUrlPatterns("/*");
//        frBean.setName("webFilterDemo");
//        return frBean;
//    }
    @Bean
    public FilterRegistrationBean WebFilterDemo(){
        //配置过滤器
        FilterRegistrationBean frBean = new FilterRegistrationBean();
        frBean.setFilter(new WebFilterParam());
        frBean.addUrlPatterns("/*");
        frBean.setName("webFilterDemo");
        //springBoot会按照order值的大小,从小到大的顺序来依次过滤。
        frBean.setOrder(0);
        return frBean;
    }
}

7、WebFilterParamControllerDemo:controller测试类

package com.cn.dl.controller;

import com.cn.dl.bean.RequestParam;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created by yanshao on 2019/2/12.
 */
@RestController
@RequestMapping(value = {"/web_request"})
public class WebFilterParamControllerDemo {


    @PostMapping(value = "test1")
    public String webReqestParamTest(RequestParam requestParam){
        System.out.println("webReqestParamTest>>>>>>>>>>>>");
        System.out.println(requestParam.toString());
        return requestParam.toString();

    }

    @GetMapping (value = "test2")
    public String webReqestParamTest2(RequestParam requestParam){
        System.out.println("webReqestParamTest>>>>>>>>>>>>");
        System.out.println(requestParam.toString());
        return requestParam.toString();
    }

}

三、测试

1、data1至data3的值在到达controller层之前被修改为value1、value2、value3,data4被修改为44,返回时,data1和data2值为*****,最后请求和返回实际输出结果与预期一致

 

springBoot-如何修改请求和返回参数_第1张图片

2、data1至data3的值在到达controller层之前被修改为value1、value2、value3,data4未赋值,data4的值应该为0,返回时,data1和data2值为*****,最后请求和返回实际输出结果与预期一致

 

springBoot-如何修改请求和返回参数_第2张图片

 

 

 

 

 

 

 

 

你可能感兴趣的:(springboot)