一、问题描述
需求:
对百度网盘分享链接输入密码时尾部多输入的空格做兼容处理。
分析:
① 在业务方法执行之前对所有的输入参数进行格式处理,trim() 方法用于删除字符串的头尾空白符;
② 使用处理后的参数调用原始方法,AOP 环绕通知中存在对原始方法的调用。
二、代码实现
1. 配置类
这里需要导入一些依赖,Spring 依赖、Junit 测试依赖、mybatis 依赖、Spring 整合 mybatis 依赖、MySQL 依赖、Spring 整合 jdbc 依赖、阿里的数据源依赖以及我们的 AOP 所需要的 aspectjweaver 依赖,如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>Spring_AOP</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.9</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
</dependencies>
</project>
2. 数据库配置
这里是数据库信息,jdbc.properties 文件:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ZXEdb?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=false
jdbc.username=root
jdbc.password=123456bb
3. config 配置类
① SpringConfig 类的出现是为了替代原先的配置文件。
package com.zxe.config;
import org.springframework.context.annotation.*;
@Configuration
@ComponentScan("com.zxe")
@PropertySource("jdbc.properties")
@Import({JdbcConfig.class, MybatisConfig.class})
@EnableAspectJAutoProxy
public class SpringConfig {
}
② JdbcConfig 类单独拿出来,配置数据库相关数据源信息。
package com.zxe.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import javax.sql.DataSource;
public class JdbcConfig {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String userName;
@Value("${jdbc.password}")
private String password;
@Bean
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driver);
dataSource.setUrl(url);
dataSource.setUsername(userName);
dataSource.setPassword(password);
return dataSource;
}
}
③ MybatisConfig 类是固定格式,一个是数据池,另一个是映射文件。
package com.zxe.config;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;
import javax.sql.DataSource;
public class MybatisConfig {
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setTypeAliasesPackage("com.zxe.domain");
sqlSessionFactoryBean.setDataSource(dataSource);
return sqlSessionFactoryBean;
}
@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
mapperScannerConfigurer.setBasePackage("com.zxe.dao");
return mapperScannerConfigurer;
}
}
4. AOP 通知类
该类用于定义切入点和通知,并绑定它们的关系,用环绕注解实现在执行 openURL 方法前先对传来的数据进行格式处理,这也是问题处理的关键。
package com.zxe.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class MyAdvice {
//定义切入点
@Pointcut("execution(boolean com.zxe.service.*Service.*(*,*))")
private void servicePt() {}
//绑定关系
@Around("MyAdvice.servicePt()")
public Object trimStr(ProceedingJoinPoint pjp) throws Throwable {
//在执行openURL方法前先对传来的数据进行格式处理
Object[] args = pjp.getArgs();
for (int i = 0; i < args.length; i++) {
//判断是不是字符串
if (args[i].getClass().equals(String.class)) {
args[i] = args[i].toString().trim();
}
}
//将修改后的参数传入原始方法中
Object ret = pjp.proceed(args);
return ret;
}
}
5. 数据层
这里用的是 Mybatis 的注解开发,自动代理出的实现类对象,所以不需要再写实现类。
package com.zxe.dao;
import org.apache.ibatis.annotations.Select;
public interface ResourcesDao {
@Select("select pwd from t_password where url = #{url}")
public String readPassword(String url);
}
6. 业务层
Service 层对从 Dao 层取过来的数据进行处理,密码校验,此时的数据已是环绕通知之后修改过的数据。
package com.zxe.service.impl;
import com.zxe.dao.ResourcesDao;
import com.zxe.service.ResourcesService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ResourcesServiceImpl implements ResourcesService {
@Autowired
private ResourcesDao resourcesDao;
@Override
public boolean openURL(String url, String password) {
String pwd = resourcesDao.readPassword(url);
boolean flag = pwd.equals(password);
return flag;
}
}
7. 实体类
用于数据映射。
package com.zxe.domain;
public class Admin {
private String url;
private String password;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
三、测试及结果
package com.zxe;
import com.zxe.config.SpringConfig;
import com.zxe.service.ResourcesService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
ResourcesService resourcesService = ac.getBean(ResourcesService.class);
boolean flag = resourcesService.openURL("http://pan.baidu.com.haha", "zhanlaoshi123");
System.out.println(flag);
}
}
有时候用户输入的密码是对的,但是会不小心在开头或者结尾多输入空格,我们利用 AOP 来解决这个问题,在业务方法执行之前对所有的输入参数进行格式处理,也就是自动去除掉多余的空格。