springBoot 过滤器去除请求参数前后空格实例详解

目录
  • 背景
  • 一、实现代码
    • 1、注册过滤器
    • 2、自定义过滤器TrimFilter
    • 3、自定义TrimRequestWrapper类
  • 二、测试
    • 1、Get请求测试首尾去空格
    • 2、Post方法测试首尾去空格
    • 3、post方法 json参数测试首尾去空格

背景

用户在前端页面中不小心输入的前后空格,为了防止因为前后空格原因引起业务异常,所以我们需要去除参数的前后空格!

如果我们手动去除参数前后空格,我们可以这样做

    @GetMapping(value = "/manualTrim")
    public void helloGet(String userName) {
        //手动去空格
        userName = userName == null ? null : userName.trim();
        //或者通过谷歌工具类手动去空格
         String trim = StringUtils.trim(userName);
    }

这种方式需要每个接口参数都进行手动的去除首尾空格,显然会让代码冗余,并不友好!所以我们应该从项目整体思考,这里通过过滤器的方式去除请求参数前后空格。

我们来看下大致实现的流程

在SpringBoot中有两种方式实现自定义Filter:

第一种是使用 @WebFilter 和 @ServletComponentScan 组合注解。

第二种是通过配置类注入 FilterRegistrationBean对象。

通过FilterRegistrationBean对象可以通过Order属性改变顺序,使用@WebFilter注解的方式只能根据过滤器名的类名顺序执行,添加@Order注解是无效的。

既然是通过过滤器获取请求参数去除参数的首尾空格,那我们应该考虑几种情况的请求参数

  • Get请求,请求参数放到url后面
  • Post请求 请求参数放到url后面
  • Post请求 请求参数放到body里面

第一种和第二种其实可以通过一种方式实现就是request.getParameter()方法。

Post中body请求参数我们可以通过使用流的方式,调用request.getInputStream()获取流,然后从流中读取参数。

一、实现代码

1、注册过滤器

/**
 *  通过FilterRegistrationBean注册自定义过滤器TrimFilter
 */
@Configuration
public class FilterConfig {
    /**
     * 注册去除参数头尾空格过滤器
     */
    @Bean
    public FilterRegistrationBean trimFilterRegistration() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setDispatcherTypes(DispatcherType.REQUEST);
        //注册自定义过滤器
        registration.setFilter(new TrimFilter());
        //过滤所有路径
        registration.addUrlPatterns("/*");
        //过滤器名称
        registration.setName("trimFilter");
        //优先级越低越优先,这里说明最低优先级
        registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE);
        return registration;
    }
}

2、自定义过滤器TrimFilter

/**
 *  自定义过滤器  通过继承OncePerRequestFilter实现每次请求该过滤器只被执行一次
 */
public class TrimFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain)
            throws ServletException, IOException {
        //自定义TrimRequestWrapper,在这里实现参数去空
        TrimRequestWrapper requestWrapper = new TrimRequestWrapper(httpServletRequest);
        filterChain.doFilter(requestWrapper, httpServletResponse);
    }
}

3、自定义TrimRequestWrapper类

TrimRequestWrapper类,其实也是最重要的一个类,继承HttpServletRequestWrapper重写getParameter,getParameterValues方法,getInputStream方法,前面的重写

可以解决非json的参数首尾去空格,但如果是json请求的参数那就必须重写getInputStream方法,从流中获取参数进行处理。

注意: request的输入流只能读取一次

/**
 * 自定义TrimRequestWrapper类
 */
@Slf4j
public class TrimRequestWrapper extends HttpServletRequestWrapper {
    /**
     * 保存处理后的参数
     */
    private Map<String, String[]> params = new HashMap<String, String[]>();
    public TrimRequestWrapper(HttpServletRequest request) {
        //将request交给父类,以便于调用对应方法的时候,将其输出
        super(request);
        //对于非json请求的参数进行处理
        if (super.getHeader(HttpHeaders.CONTENT_TYPE) == null ||
                (!super.getHeader(HttpHeaders.CONTENT_TYPE).equalsIgnoreCase(MediaType.APPLICATION_JSON_VALUE) &&
                        !super.getHeader(HttpHeaders.CONTENT_TYPE).equalsIgnoreCase(MediaType.APPLICATION_JSON_UTF8_VALUE))) {
            setParams(request);
        }
    }
    private void setParams(HttpServletRequest request) {
        //将请求的的参数转换为map集合
        Map<String, String[]> requestMap = request.getParameterMap();
        log.info("kv转化前参数:" + JSON.toJSONString(requestMap));
        this.params.putAll(requestMap);
        //去空操作
        this.modifyParameterValues();
        log.info("kv转化后参数:" + JSON.toJSONString(params));
    }
    /**
     * 将parameter的值去除空格后重写回去
     */
    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);
        }
    }
    /**
     * 重写getParameter 参数从当前类中的map获取
     */
    @Override
    public String getParameter(String name) {
        String[] values = params.get(name);
        if (values == null || values.length == 0) {
            return null;
        }
        return values[0];
    }
    /**
     * 重写getParameterValues
     */
    @Override
    public String[] getParameterValues(String name) {
        return params.get(name);
    }
    /**
     * 重写getInputStream方法  post类型的请求参数必须通过流才能获取到值
     * 这种获取的参数的方式针对于内容类型为文本类型,比如Content-Type:text/plain,application/json,text/html等
     * 在springmvc中可以使用@RequestBody 来获取 json数据类型
     * 其他文本类型不做处理,重点处理json数据格式
     * getInputStream() ,只有当方法为post请求,且参数为json格式是,会被默认调用
     */
    @Override
    public ServletInputStream getInputStream() throws IOException {
        //
        if (!super.getHeader(HttpHeaders.CONTENT_TYPE).equalsIgnoreCase(MediaType.APPLICATION_JSON_VALUE) &&
                !super.getHeader(HttpHeaders.CONTENT_TYPE).equalsIgnoreCase(MediaType.APPLICATION_JSON_UTF8_VALUE)) {
            //如果参数不是json格式则直接返回
            return super.getInputStream();
        }
        //为空,直接返回
        String json = IOUtils.toString(super.getInputStream(), "utf-8");
        if (StringUtils.isEmpty(json)) {
            return super.getInputStream();
        }
        log.info("json转化前参数:" + json);
        //json字符串首尾去空格
        JSONObject jsonObject = StringJsonUtils.JsonStrTrim(json);
        log.info("json转化后参数:" + jsonObject.toJSONString());
        ByteArrayInputStream bis = new ByteArrayInputStream(jsonObject.toJSONString().getBytes("utf-8"));
        return new MyServletInputStream(bis);
    }
}

二、测试

因为上面说了三种情况,所以这里提供了3个接口来进行测试

/**
 * 测试接口
 *
 * @author xub
 * @date 2022/10/24 下午5:06
 */
@Slf4j
@RestController
public class ParamController {
    /**
     * 1、Get请求测试首尾去空格
     */
    @GetMapping(value = "/getTrim")
    public String getTrim(@RequestParam String username, @RequestParam String phone) {
        return username + "&" + phone;
    }
    /**
     * 2、Post方法测试首尾去空格
     */
    @PostMapping(value = "/postTrim")
    public String postTrim(@RequestParam String username, @RequestParam String phone) {
        return username + "&" + phone;
    }
    /**
     * 3、post方法 json入参 测试首尾去空格
     */
    @PostMapping(value = "/postJsonTrim")
    public String helloUser(@RequestBody UserDO userDO) {
        return JSONObject.toJSONString(userDO);
    }
}

1、Get请求测试首尾去空格

请求url

http://localhost:8080/getTrim?username=张三 &phone= 18812345678

后台输出日志

: kv转化前参数:{"username":["张三 "],"phone":[" 18812345678"]}
: kv转化后参数:{"phone":["18812345678"],"username":["张三"]}

接口返回

张三&18812345678

说明首尾去空格成功!

2、Post方法测试首尾去空格

请求url

http://127.0.0.1:8080/postTrim?username=张三 &phone= 18812345678

后台输出日志

: kv转化前参数:{"username":["张三 "],"phone":[" 18812345678"]}
: kv转化后参数:{"phone":["18812345678"],"username":["张三"]}

接口返回

张三&18812345678

说明首尾去空格成功!

3、post方法 json参数测试首尾去空格

请求url

http://127.0.0.1:8080/postJsonTrim

请求参数和返回参数

注意 这个请求头为Content-Type:application/json

后台输出日志

json转化前参数:{"phone":"18812345678 " ,"username":" 张三 "}
json转化后参数:{"phone":"18812345678","username":"张三"}

说明首尾去空格成功!

项目示例源码: https://github.com/yudiandemingzi/spring-boot-study

以上就是springBoot 过滤器去除请求参数前后空格实例详解的详细内容,更多关于springBoot 过滤器去除空格的资料请关注我们其它相关文章!

(0)

相关推荐

  • Springboot详解如何实现SQL注入过滤器过程

    目录 1.过滤器SqlInjectFilter 2.请求装饰类CustomRequestWrapper 3.过滤器注册 4.测试辅助类 4.1 结果对象ResultObj 4.2 Restful的Controller类 5.测试 5.1 POST请求测试 5.2 GET请求测试1 5.3 GET请求测试2 场景:以过滤器(Filter)的方式,对所有http请求的入参拦截,使用正则表达式匹配入参中的字符串.存在SQL注入风险的参数,中断请求,并立即返回提示信息.不存在SQL注入风险的参数,校验通

  • SpringBoot之跨域过滤器配置允许跨域访问方式

    目录 SpringBoot跨域过滤器配置允许跨域访问 跨域请求 问题背景 跨域过滤器 跨域功能改进 SpringBoot跨域设置(CORS) 一.什么是跨域 二.跨域资源共享(CORS) 1. 简单请求 2. 非简单请求 三.SpringBoot设置CORS SpringBoot跨域过滤器配置允许跨域访问 跨域请求 当一个资源从与该资源本身所在的服务器不同的域或端口请求一个资源时,资源会发起一个跨域 HTTP 请求. 出于安全原因,浏览器限制从脚本内发起的跨源HTTP请求. 例如,XMLHttp

  • SpringBoot+Redis实现布隆过滤器的示例代码

    目录 简述 Redis安装BloomFilter 基本指令 结合SpingBoot 方式一 方式二 简述 关于布隆过滤器的详细介绍,我在这里就不再赘述一遍了 我们首先知道:BloomFilter使用长度为m bit的字节数组,使用k个hash函数,增加一个元素: 通过k次hash将元素映射到字节数组中k个位置中,并设置对应位置的字节为1.查询元素是否存在: 将元素k次hash得到k个位置,如果对应k个位置的bit是1则认为存在,反之则认为不存在. Guava 中已经有具体的实现,而在我们实际生产

  • SpringBoot详解shiro过滤器与权限控制

    目录 shiro过滤器 权限控制 动态配置权限 shiro过滤器 首先从客户端发来的所有请求都经过Shiro过滤器,如果用户没有认证的都打回去进行认证,认证成功的,再判断是否具有访问某类资源(公有资源,私有资源)的权限,如果没有权限,访问失败;如果有权限访问成功.注意:客户端传来的token要和realm中的认证信息进行相同规则的比较(加密算法要一致). 常见过滤器: 1.在shiro配置类中配置,使用 filterFactoryBean.setFilterChainDefinitionMa()

  • SpringBoot 过滤器 Filter使用实例详解

    目录 简介 用法 功能 实现 简介 过滤器是AOP(面向切面编程)思想的具体实现.可以过滤浏览器发出的请求,并且决定放行请求还是中断请求. 在浏览器对服务器发起请求或者服务器对浏览器响应,都会经过过滤器. 基于过滤器的机制,我们可以在过滤器中对请求和响应做一些处理,可以在过滤器中决定是否放行,例如:校验请求中有没有敏感字符串,校验有没有Session,实现URL级别的权限控制.压缩响应信息.编码格式等. 用法 在spring的应用中我们存在两种过滤的用法,一种是拦截器.另外一种当然是过滤器.我们

  • SpringBoot中shiro过滤器的重写与配置详解

    目录 问题 解决方案 实现代码 1.重写shiro 登录 过滤器 2.重写role权限 过滤器 3.配置过滤器 问题 遇到问题:在前后端分离跨域访问的项目中shiro进行权限拦截失效 (即使有正确权限的访问也会被拦截) 时造成302重定向错误等问题报错:Response for preflight is invalid (redirect) 1.302原因:使用ajax访问后端项目时无法识别重定向操作 2.shiro拦截失效原因:跨域访问时有一种带预检访问的跨域,即访问时先发出一条methods

  • SpringBoot实现过滤器拦截器的耗时对比

    目录 过滤器的方式 拦截器的方式 三种方式 下面为大家一一对应 过滤器的方式 拦截器的方式 过滤器的方式 这种方式简单点 但是可配置性不高 注意:一定得扫描到spring容器中 创建一个类 实现 filter接口 init:该方法是对filter对象进行初始化的方法,仅在容器初始化filter对象结束后被调用一次,参数FilterConfig可以获得filter的初始化参数: doFilter:可以对request和response进行<u>预处理</u>.其中FilterChai

  • 详解SpringBoot中如何使用布隆过滤器

    目录 前言 一.Guava 实现布隆过滤器 二.Hutool 布隆过滤器 三.Redission 布隆过滤器 四.小结 五.Guava 布隆过滤器结合 Redis 使用 昨天写了一篇Redis布隆过滤器相关的命令的文章,今天来说一说springboot中如何简单在代码中使用布隆过滤器吧. 目前市面上也有好几种实现方式,如果你需要高度定制化,可以完全从零实现,当然这不是一个简单的工程. 如果只是想快速开始的话,那么市面上现成的实现,无疑是最快的. 前言 今天说到的实现方式有以下几种: 引入 Gua

  • jQuery中通过ajax调用webservice传递数组参数的问题实例详解

    下面通过实例给大家说明比较直观些,更方便大家了解. 本人的项目中通过jquery.ajax调用webservice. 客户端代码如下: $.ajax({ url: "test/xxx.asmx", type: 'POST', dataType: 'xml', timeout: , data: { name: "zhangsan", tags: ["aa", "bb", "cc"] }, error: fun

  • Struts2之Action接收请求参数和拦截器详解

    技术分析之在Struts2框架中使用Servlet的API 1. 在Action类中也可以获取到Servlet一些常用的API 需求:提供JSP的表单页面的数据,在Action中使用Servlet的API接收到,然后保存到三个域对象中,最后再显示到JSP的页面上. 提供JSP注册的页面,演示下面这三种方式 <h3>注册页面</h3> <form action="${ pageContext.request.contextPath }/xxx.action"

  • springboot自动扫描添加的BeanDefinition源码实例详解

    1. springboot启动过程中,首先会收集需要加载的bean的定义,作为BeanDefinition对象,添加到BeanFactory中去. 由于BeanFactory中只有getBean之类获取bean对象的方法,所以将将BeanDefinition添加到BeanFactory中,是通过BeanDefinitionRegistry接口的void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) t

  • SpringMVC中参数绑定问题实例详解

    目录 前言 1. 参数绑定的过程 2. 默认支持的类型 3. 简单类型的绑定 4. pojo类型的绑定 4.1 普通pojo类型 4.2. 包装的pojo类型 5. 集合类型的绑定 5.1 数组的绑定 5.2 List的绑定 5.2 Map的绑定 总结 前言 众所周知,springmvc是用来处理页面的一些请求,然后将数据再通过视图返回给用户的,前面的几篇博文中使用的都是静态数据,为了能快速入门springmvc,在这一篇博文中,我将总结一下springmvc中如何接收前台页面的参数,即spri

  • SpringBoot多环境配置及配置文件分类实例详解

    目录 二.配置文件分类 2.1 代码演示 2.1.1 环境准备 2.1.2 验证1级和2级的优先级 2.1.3 验证2级和4级的优先级 一.多环境配置 在工作中,对于开发环境.测试环境.生产环境的配置肯定都不相同,比如我们开发阶段会在自己的电脑上安装 mysql ,连接自己电脑上的 mysql 即可,但是项目开发完毕后要上线就需要该配置,将环境的配置改为线上环境的. 来回的修改配置会很麻烦,而 SpringBoot 给开发者提供了多环境的快捷配置,需要切换环境时只需要改一个配置即可.不同类型的配

  • uni-app网络请求、数据缓存实例详解

    目录 一.网络请求 1.配置请求 1.1 发送get请求 1.2 发送POST请求 二.数据缓存 1.uni.setStorage(OBJECT) 2.uni.setStorageSync(KEY,DATA) 3.uni.getStorage(OBJECT) 4.uni.getStorageSync(KEY) 5.uni.removeStorage(OBJECT) 总结 一.网络请求 在uni中可以调用uni.request方法进行请求网络请求 需要注意的是:在小程序中网络相关的 API 在使用

  • SpringBoot/Spring AOP默认动态代理方式实例详解

    目录 1. springboot 2.x 及以上版本 2. Springboot 1.x 3.SpringBoot 2.x 为何默认使用 Cglib 总结: Spring 5.x中AOP默认依旧使用JDK动态代理 SpringBoot 2.x开始,AOP为了解决使用JDK动态代理可能导致的类型转换异常,而使用CGLIB. 在SpringBoot 2.x中,AOP如果需要替换使用JDK动态代理可以通过配置项spring.aop.proxy-target-class=false来进行修改,proxy

  • 将DataTable作为存储过程参数的用法实例详解

    最近工作中写了几个存储过程,需要向存储过程中传递字符串,因为SQL Server 2000中没有内置类似于 split 的函数,只好自己处理,将前台数据集中的一列用逗号拆分存到一个List<string>中,再转化为字符串传给存储过程,很是麻烦.今天看了下SQL Server 2008的新特性,发现有表变量的使用,及其将DataTable作为参数的用法,就尝试了一下,简单谈谈心得. 示例代码下载 一.测试环境 1.Windows Server 2008 R2 DataCenter 2.Visu

  • C语言字符串替换空格实例详解

    目录 一.题目描述 二.思路分析 三.整体代码 总结 一.题目描述 请实现一个函数,把字符串 s 中的每个空格替换成"%20". 示例: 输入:s = "We are happy." 输出:"We%20are%20happy." 限制:0 <= s 的长度 <= 10000 二.思路分析 思路 C语言的字符串无法改变大小,所以无法直接在原来的字符串上操作.于是我们先统计空格个数,算出替换后的字符串的大小,并申请一块新内存.(注意要多申

  • SpringBoot快速入门及起步依赖解析(实例详解)

    目录 一.SpringBoot简介 1.1 SpringBoot快速入门 1.1.1 开发步骤 1.1.2 对比 1.1.3 官网构建工程 1.1.4 SpringBoot工程快速启动 1.2 SpringBoot概述 1.2.1 起步依赖 1.2.2 程序启动 1.2.3 切换web服务器 一.SpringBoot简介 SpringBoot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化 Spring 应用的初始搭建以及开发过程. 使用了 Spring 框架后已经简化了我们的开

随机推荐