素材巴巴 > 程序开发 >

后端自动去除字符串前后空格

程序开发 2023-09-09 07:07:09

关于Post请求查询,前端传来的字符串前后有空格的处理

1. 问题起因:

最近办公室在对项目系统进行统一的测试,测试出了一些查询的问题,我们这写的index页面的分页查询接口,如果是index页面展示的字段单表可以满足,就直接用mybatis plus的分页查询,但是呢,凡是都有例外,因为做的是公司用的oa系统,关联的地方很多,比如组织机构啊,项目啊,合同啊,单位啊,之类的……总之有很是单表查询满足不了的,因此,就产生了今天的问题,前端的入参,不标准怎么办?冷不丁的给你冒出个前后空格,导致查询结果不对,用户就反馈,为什么这个查不出来啊,我都是复制的,想想就头疼。

2. 初步想法

因为最开始对这个系统功能不熟悉,加之比较急,就没有考虑这个问题,具体是前端做,还是后端做,其实:我感觉,必须是前端自己做,哈哈哈!一开始呢,第一时间肯定就是想到trim方法嘛。

就是用下面这种改法:

这是控制器方法,一个例子而已。

	@PostMapping("/getIndexPageData")public R getIndexPageData(@RequestBody SubProblemIndexReqDTO reqDTO,@RequestHeader String token) {log.info(LogConstant.CALL_INTERFACE,"/security/statistical/getIndexPageData");return securityCheckService.getIndexPageData(reqDTO,token);}
 

这是入参类的结构

/*** index页请求DTO* @author: 一位大帅哥* @date: 2022/10/12 10:32* @description: TODO*/
 @Data
 @EqualsAndHashCode(callSuper = true)
 @Trim // 就是我们今天要说的注解
 public class SubProblemIndexReqDTO extends PageReqDTO {/*** 区域*/private String area;/*** 流程编号*/private String flowCode;/*** 项目名称*/private String projectName;/*** 合同名称*/private String contractName;/*** 监理单位名称*/private String companyNameJl;/*** 施工单位名称*/private String companyNameSg;/*** 检查类型*/private String checkType;/*** 回复率起始值*/private Double responseRateBegin;/*** 回复率结束值*/private Double responseRateEnd;/*** 整改率起始值*/private Double rectificationRateBegin;/*** 整改率结束值*/private Double rectificationRateEnd;/*** 闭合率起始值*/private Double closingRateBegin;/*** 闭合率结束值*/private Double closingRateEnd;/*** 检查日期 --> 起始值*/private Date checkDateBegin;/*** 检查日期 --> 结束值*/private Date checkDateEnd;}
 

顺便给大家说一下利用Post请求做分页,把查询参数放到类中的,定义一个抽象的ReqDTO,把查询的公共参数放到里面,直接继承着用,感觉大家应该都能想到。下面是我用的ReqDTO

/*** 

请求公共属性抽象类

** @author gaoming* @Date 2022/9/6 11:43*/ @Data public abstract class PageReqDTO {/*** 页大小 , 默认值 10*/private Integer pageSize = 10;/*** 当前页 , 默认值 1*/private Integer pageNum = 1;/*** 流程状态*/private Integer processStatus;/*** 项目ids*/private List projectIds;/*** 项目组织结构id*/private String organizationId;}

一开始想的就是在service方法中,把要用到的String属性判断不为空,就进行trim操作

if (StrUtil.isNotBlank(reqDTO.getArea())) {reqDTO.setArea(reqDTO.getArea().trim());
 }
 

但是这样做就太多了,有的入参类String属性有一二十个,那要是这样改,人不得改崩了啊!所以果断放弃,因此,就要从别的方面入手,第一时间想到用注解形式,只要定义一个注解,放到类或者类的属性上面,不就可以了吗?

3. 正文开始

看了这么久,终于等到正文了!

  1. 定义一个自定义注解Trim

    /*** @author GmDsg* @date 2023/5/15 9:29* @description 去除String字段前后空格*/
     @Target({ElementType.FIELD, ElementType.TYPE}) // 注解可作用在类或者类属性
     @Retention(RetentionPolicy.RUNTIME) // 运行时生效
     public @interface Trim {
     }
     
  2. 定义一个切面类

    /*** @author GmDsg* @date 2023/5/15 9:30* @description Trim切面*/
     @Aspect
     @Component
     @Slf4j
     public class TrimAop {/*** 切入点:任意包路径下controller包下的任意Controller类的公共方法* */@Pointcut("execution(public * *..controller.*Controller.*(..))")public void pointCut() {}/*** 前置操作* @param joinPoint 连接点* @throws Throwable 抛出异常*/@Before("pointCut()")public void before(JoinPoint joinPoint) throws Throwable {// 获取入参Object[] args = joinPoint.getArgs();for (int i = 0; i < args.length; i++) {Object arg = args[i];if (arg == null) {continue;}// 获取该入参类是否有Trim注解Class argClass = arg.getClass();Trim annotation = argClass.getAnnotation(Trim.class);// 获取该入参类所有属性Field[] fields = argClass.getDeclaredFields();if (annotation == null) {// 类上没有Trim注解for (Field field : fields) {// 获取类中属性是否有Trim注解Trim fieldAnnotation = field.getAnnotation(Trim.class);if (fieldAnnotation == null || !field.getType().equals(String.class)) {continue;}// 该属性有注解并且也是String类型// 设置私有属性可访问field.setAccessible(true);// 获取属性值Object value = field.get(arg);if (value != null) {// 执行trim操作,并重新为该属性赋值field.set(arg, ((String) value).trim());}}} else {// 入参类上存在Trim注解for (Field field : fields) {// 遍历所有属性值并筛选是String类型的字段if (!field.getType().equals(String.class)) {continue;}// 设置私有属性可访问field.setAccessible(true);// 获取属性值Object value = field.get(arg);if (value != null) {// 执行trim操作,并重新为该属性赋值field.set(arg, ((String) value).trim());}}}// 为当前类赋值处理完的类,实现去除空格效果args[i] = arg;}}
     }
     
  3. 浅浅的解释一下

    使用@Before注解获取前置操作的所有入参,也就是这一句

            // 获取入参Object[] args = joinPoint.getArgs();
     

    会获取控制器方法的所有入参:就会获取reqDTO,token

    @PostMapping("/getIndexPageData")
     public R getIndexPageData(@RequestBody SubProblemIndexReqDTO reqDTO,@RequestHeader String token) {log.info(LogConstant.CALL_INTERFACE,"/security/statistical/getIndexPageData");return securityCheckService.getIndexPageData(reqDTO,token);}
     

    遍历获取到的Object,反射获取Object的class,调用class的getAnnotation(Trim.class)方法

    // 获取类中属性是否有Trim注解
     Trim annotation = argClass.getAnnotation(Trim.class);
     

    如果这个annotation不为空,则说明该类上有Trim注解,对于类上面有Trim注解的,会对所有String类型并且不为null的属性进行去除

    前后空格操作。

    所以就要获取类中所有的属性

    // 获取该入参类所有属性
     Field[] fields = argClass.getDeclaredFields();
     

    遍历fields,挨个判断Field是否是String类型并且不为空,如果满足,则为该Field设置去除前后空格的值,具体操作如下。

    // 入参类上存在Trim注解
     for (Field field : fields) {// 遍历所有属性值并筛选是String类型的字段if (!field.getType().equals(String.class)) {continue;}// 设置私有属性可访问field.setAccessible(true);// 获取属性值Object value = field.get(arg);if (value != null) {// 执行trim操作,并重新为该属性赋值field.set(arg, ((String) value).trim());}
     }
     

    然后类上面没有Trim注解的呢,我们还要再对fields进行遍历,因为我们的注解当时定义是作用在类上或者属性上的,因此类上面没有还要对属性进行判断,这个属性有没有Trim注解,有这个注解它是不是String类型的,话不多说,上代码。

    // 类上没有Trim注解
     for (Field field : fields) {// 获取类中属性是否有Trim注解Trim fieldAnnotation = field.getAnnotation(Trim.class);if (fieldAnnotation == null || !field.getType().equals(String.class)) {continue;}// 该属性有注解并且也是String类型// 设置私有属性可访问field.setAccessible(true);// 获取属性值Object value = field.get(arg);if (value != null) {// 执行trim操作,并重新为该属性赋值field.set(arg, ((String) value).trim());}
     }
     

    其实这个没啥讲的,取属性上的注解,看属性上有没有这个注解,如果有,还要判断这个属性是不是String类型的,如果都满足,则对这个Field做trim操作

4. 测试

我们找到一个接口,随便测试一下

​ 这是入参,然后直接点查询

6

​ 后台日志:

​ 可以看到,projectName 和 companyNameSg都加了空格,因为projectName加了Trim注解,所以去掉了空格,反之,companyNameSg没加注解,没有去掉空格,导致查询为空!

7

​ 结果:

8

5. 最后

最后还是要说一下,利用切面类,是很好用,但是,启动项目时,spring也会加载切面,如果切面写的范围过大,会导致启动速度变慢,也可能导致方法查询不准确,所以大家用的时候,要写好这个切入点。以上就是我这次给大家分享的‘干货’,因为我也是小菜鸟一枚,写博客也只是记录一下,大家有什么好的建议或者文章中有一些写的不对不准确的地方,欢迎大家指正。最后祝在看文章的您,能在这卷到飞起的java大环境中,成长为一个超级大大大大大……神!


标签:

素材巴巴 Copyright © 2013-2021 http://www.sucaibaba.com/. Some Rights Reserved. 备案号:备案中。