刘仁 Java后端开发

使用SpringBoot使用过滤器去除@RequestBody参数两端的空格


使用SpringBoot使用过滤器去除@RequestBody参数两端的空格

使用SpringBoot使用过滤器去除@RequestBody参数两端的空格;一般我们去普通的请求我们都会对请求参数进行验证。Java也提供了@notNull和@notBlank这种验证方式,但是对@RequestBody 这种只能验证是不是非空,对数据两端的空格未进行处理,同时大家也不想遍历一遍参数然后再处理再封装到对象中,正好项目中有这个需要,所以就参考别的做了Post请求中针对application/json格式的有@RequestBody注解的参数进行了去空格处理

协议:CC BY-SA 4.0 https://creativecommons.org/licenses/by-sa/4.0/

版权声明:本文为原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

第一步:编写一个配置信息

ParamsFilterConfig.java

package com.codepeople.framework.config;

import javax.servlet.DispatcherType;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.ruoyi.framework.filter.ParamsFilter;

/**
 * @ClassName: ParamsFilterConfig
 * @Description: SpringBoot中去除@RequestBody中前后端空格
 * @Author 刘 仁
 * @DateTime 2020-7-23 10:07:02
 */
@Configuration
public class ParamsFilterConfig {

	@Bean
	public FilterRegistrationBean paramsFilterRegistration() {
		FilterRegistrationBean registration = new FilterRegistrationBean();
		registration.setDispatcherTypes(DispatcherType.REQUEST);
        registration.setFilter(new ParamsFilter());
        registration.addUrlPatterns("/*");
        registration.setName("paramsFilter");
        registration.setOrder(Integer.MAX_VALUE-1);
        return registration;
	}
}

第二步:编写ParamsFilter过滤器

ParamsFilter.java

package com.kelan.framework.filter;

/**
 * @ClassName: ParamsFilter
 * @Description: 
 * @Author 刘 仁
 * @DateTime 2021-4-9 10:49:46 
 */

import java.io.IOException;

import javax.servlet.DispatcherType;
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.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;

import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@WebFilter(urlPatterns = "/**", filterName = "ParamsFilter", dispatcherTypes = DispatcherType.REQUEST)
@Order(value = 1)
public class ParamsFilter implements Filter {

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		ParameterRequestWrapper parmsRequest = new ParameterRequestWrapper((HttpServletRequest) request);
		chain.doFilter(parmsRequest, response);
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		
	}

	@Override
	public void destroy() {
		
	}

	
}

第三步:实现ParameterRequestWrapper

ParameterRequestWrapper.java

package com.codepeople.framework.filter;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;

import com.alibaba.fastjson.JSON;
import com.codepeople.framework.util.StringJsonUtils;

public class ParameterRequestWrapper extends HttpServletRequestWrapper {

	private Map<String , String[]> params = new HashMap<>();
	
	public ParameterRequestWrapper(HttpServletRequest request) {
		// 将request交给父类,以便于调用对应方法的时候,将其输出,其实父亲类的实现方式和第一种new的方式类似
        super(request);
        //将参数表,赋予给当前的Map以便于持有request中的参数
        Map<String, String[]> requestMap=request.getParameterMap();
        this.params.putAll(requestMap);
        this.modifyParameterValues();
	}

	/**
	 * 重写getInputStream方法  post类型的请求参数必须通过流才能获取到值 
	 */
	@Override
    public ServletInputStream getInputStream() throws IOException {
		/** 非json类型,直接返回 */
		if(!super.getHeader(HttpHeaders.CONTENT_TYPE).equalsIgnoreCase(MediaType.APPLICATION_JSON_VALUE)){
            return super.getInputStream();
        }
        //为空,直接返回
        String json = IOUtils.toString(super.getInputStream(), "utf-8");
        if (StringUtils.isEmpty(json)) {
            return super.getInputStream();
        }
        System.out.println("去除POST请求数据两端的空格前参数:"+json);
        Map<String,Object> map= StringJsonUtils.jsonStringToMap(json);
        System.out.println("去除POST请求数据两端的空格后参数:"+JSON.toJSONString(map));
        ByteArrayInputStream bis = new ByteArrayInputStream(JSON.toJSONString(map).getBytes("utf-8"));
        return new MyServletInputStream(bis);
    }

	/**
	 * @Title: modifyParameterValues
	 * @Description:  将parameter的值去除空格后重写回去
	 * @DateTime 2020-7-23 10:31:12
	 */
    public void modifyParameterValues(){
        Set<String> set = params.keySet();
        Iterator<String> it = set.iterator();
        while(it.hasNext()){
            String key= it.next();
            String[] values = params.get(key);
            values[0] = values[0].trim();
            params.put(key, values);
        }
    }
    
    @Override
    public String getParameter(String name) {
        String[]values = params.get(name);
        if(values == null || values.length == 0) {
            return null;
        }
        return values[0];
    }
    /**
	 * @Title: getParameterValues
	 * @Description:  重写getParameterValues
	 * @DateTime 2020-7-23 10:31:12
	 */
    @Override
    public String[] getParameterValues(String name) {//同上
        return params.get(name);
    }
 
    class MyServletInputStream extends  ServletInputStream{
        private ByteArrayInputStream bis;
        public MyServletInputStream(ByteArrayInputStream bis){
            this.bis=bis;
        }
        @Override
        public boolean isFinished() {
            return true;
        }
 
        @Override
        public boolean isReady() {
            return true;
        }
 
        @Override
        public void setReadListener(ReadListener listener) {
 
        }
        @Override
        public int read(){
            return bis.read();
        }
    }

}

第四步:利用fastjson实现json字符串转map功能

package com.codepeople.framework.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
/**
 * @ClassName: StringJsonUtils
 * @Description: 
 * @Author 刘 仁
 * @DateTime 2020-7-23 10:26:28
 */
public class StringJsonUtils {
	
	/**
	 * @Title: jsonStringToMap
	 * @Description: 把jsonString转为Map
	 * @Author 刘 仁
	 * @DateTime 2020-7-23 10:27:11
	 * @param jsonString
	 * @return
	 */
	public static Map<String, Object> jsonStringToMap(String jsonString) {
        Map<String, Object> map = new HashMap<>();
        JSONObject jsonObject = JSONObject.parseObject(jsonString);
        for (Object k : jsonObject.keySet()) {
            Object o = jsonObject.get(k);
            if (o instanceof JSONArray) {
                List<Map<String, Object>> list = new ArrayList<>();
                Iterator<Object> it = ((JSONArray) o).iterator();
                while (it.hasNext()) {
                    Object obj = it.next();
                    list.add(jsonStringToMap(obj.toString()));
                }
                map.put(k.toString(), list);
            } else if (o instanceof JSONObject) {
                // 如果内层是json对象的话,继续解析
                map.put(k.toString(), jsonStringToMap(o.toString()));
            } else {
                // 如果内层是普通对象的话,直接放入map中
               // map.put(k.toString(), o.toString().trim()); 
                 if (o instanceof String) {
                   map.put(k.toString(), o.toString().trim());
                } else {
                    map.put(k.toString(), o);
                }   
            }
        }
        return map;
    }

}

主要引入的包

<!--常用工具类 -->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
		</dependency>
<!-- 阿里JSON解析器 -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
		</dependency>
<!-- io常用工具类 -->
		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
		</dependency>
<!-- servlet包 -->
        <dependency>
		    <groupId>javax.servlet</groupId>
		    <artifactId>javax.servlet-api</artifactId>
		</dependency>

测试日志

11:28:07.995 [http-nio-80-exec-17] INFO  c.r.f.f.ParameterRequestWrapper - [getInputStream,54] - 去除POST请求数据两端的空格前参数:{
	"idNumber": "110101201003073036",
	"password": " 123456 "
}
11:28:07.997 [http-nio-80-exec-17] INFO  c.r.f.f.ParameterRequestWrapper - [getInputStream,56] - 去除POST请求数据两端的空格后参数:{"password":"123456","idNumber":"110101201003073036"}

如果Filter未生效则可以直接在Springboot启动类上增加如下注解

@ServletComponentScan(basePackages = "full.package.path")
##例如
@ServletComponentScan(basePackages = "com.kelan.framework.filter")

博客地址:https://www.codepeople.cn

=====================================================================

微信公众号:


Similar Posts

Comments