springBoot 过滤器去除请求参数前后空格(附源码)

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

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

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

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

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

springBoot 过滤器去除请求参数前后空格(附源码)

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

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

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

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

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

  1. Get请求,请求参数放到url后面
  2. Post请求 请求参数放到url后面
  3. 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 

请求参数和返回参数

springBoot 过滤器去除请求参数前后空格(附源码)

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

后台输出日志

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

说明首尾去空格成功!

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

声明: 公众号如需转载该篇文章,发表文章的头部一定要 告知是转至公众号: 后端元宇宙。同时也可以问本人要markdown原稿和原图片。其它情况一律禁止转载!

发表评论

评论已关闭。

相关文章