1. 需求分析
需求: 对百度网盘分享链接输入密码时尾部多输入的空格做兼容处理。
问题描述:
-
点击链接,会提示,请输入提取码,如下图所示
-
当我们从别人发给我们的内容中复制提取码的时候,有时候会多复制到一些空格,直接粘贴到百度的提取码输入框
-
但是百度那边记录的提取码是没有空格的
-
这个时候如果不做处理,直接对比的话,就会引发提取码不一致,导致无法访问百度盘上的内容
-
所以多输入一个空格可能会导致项目的功能无法正常使用。
-
此时我们就想能不能将输入的参数先帮用户去掉空格再操作呢?
答案是可以的,我们只需要在业务方法执行之前对所有的输入参数进行格式处理——trim()
- 是对所有的参数都需要去除空格么?
也没有必要,一般只需要针对字符串处理即可。
- 以后涉及到需要去除前后空格的业务可能会有很多,这个去空格的代码是每个业务都写么?
可以考虑使用AOP来统一处理。
- AOP有五种通知类型,该使用哪种呢?
我们的需求是将原始方法的参数处理后在参与原始方法的调用,能做这件事的就只有环绕通知。
综上所述,我们需要考虑两件事:
①:在业务方法执行之前对所有的输入参数进行格式处理——trim()
②:使用处理后的参数调用原始方法——环绕通知中存在对原始方法的调用
2. 环境准备
-
创建一个Maven项目
-
pom.xml添加Spring依赖
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.10.RELEASE</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency> </dependencies>
-
添加ResourcesDao和ResourcesDaoImpl类
public interface ResourcesDao { boolean readResources(String url, String password); } @Repository public class ResourcesDaoImpl implements ResourcesDao { public boolean readResources(String url, String password) { //模拟校验 return password.equals("1234"); } }
-
添加ResourcesService和ResourcesServiceImpl类
public interface ResourcesService { public boolean openURL(String url ,String password); } @Service public class ResourcesServiceImpl implements ResourcesService { @Autowired private ResourcesDao resourcesDao; public boolean openURL(String url, String password) { return resourcesDao.readResources(url,password); } }
-
创建Spring的配置类
@Configuration @ComponentScan("com.dcxuexi") public class SpringConfig { }
-
编写SpringAop运行类
public class SpringAop { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); ResourcesService resourcesService = context.getBean(ResourcesService.class); boolean b = resourcesService.openURL("https://pan.baidu.com/s/1AA14syG9sE4VAdTJMvgzzw", "1234 "); System.out.println(b); } }
最终创建好的项目结构如下:
现在项目的效果是,当输入密码为"1234"控制台打印为true,如果密码改为"1234 "控制台打印的是false
需求是使用AOP将参数进行统一处理,不管输入的密码1234
前后包含多少个空格,最终控制台打印的都是true。
3. 具体实现
步骤1:开启SpringAOP的注解功能
@Configuration
@ComponentScan("com.dcxuexi")
@EnableAspectJAutoProxy
public class SpringConfig {
}
步骤2:编写通知类
@Component
@Aspect
public class ResourcesAdvice {
@Pointcut("execution(* com.dcxuexi.service.*Service.*(*,*))")
public void ptService(){}
}
步骤3:添加环绕通知
@Component
@Aspect
public class ResourcesAdvice {
@Pointcut("execution(* com.dcxuexi.service.*Service.*(*,*))")
public void ptService(){}
//@Around("ptService()") 这两种写法都对
@Around("ResourcesAdvice.ptService()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Object proceed = proceedingJoinPoint.proceed();
return proceed;
}
}
步骤4:完成核心业务,处理参数中的空格
@Component
@Aspect
public class ResourcesAdvice {
@Pointcut("execution(* com.dcxuexi.service.*Service.*(*,*))")
public void ptService(){}
//@Around("ptService()") 这两种写法都对
@Around("ResourcesAdvice.ptService()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//获取原始方法的参数
Object[] args = proceedingJoinPoint.getArgs();
for (int i = 0; i < args.length; i++) {
//判断参数是不是字符串
if (args[i].getClass().equals(String.class)){
args[i] = args[i].toString().trim(); // 去重空格
}
}
// 将修改后的值传到原始方法的执行中
Object proceed = proceedingJoinPoint.proceed(args);
return proceed;
}
}
步骤5:运行程序
不管密码1234
前后是否加空格,最终控制台打印的都是true
步骤6:优化测试
为了能更好的看出AOP已经生效,我们可以修改ResourcesImpl类,在方法中将密码的长度进行打印
@Repository
public class ResourcesDaoImpl implements ResourcesDao {
public boolean readResources(String url, String password) {
System.out.println("密码长度 :"+password.length());
//模拟校验
return password.equals("1234");
}
}
再次运行成功,就可以根据最终打印的长度来看看,字符串的空格有没有被去除掉。
注意: