使用springAOP实现权限控制
说明:
- 这里使用的配置方式是:注解+xml文件的方式
- 三个角色:的权限设置
- const:只能注册
- user:注册+查询+修改
- admin:注册+查询+修改+删除
1、搭建基本环境
-
导入依赖
<dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.24</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.11</version> </dependency> <!-- spring-aspects会帮我们传递过来aspectjweaver --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>5.3.1</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>5.3.29</version> </dependency> </dependencies>
-
实体类User
@Data @AllArgsConstructor @NoArgsConstructor public class User { private int id; private String username; private String address; }
-
controller层添加UserController的注解,
@Controller public class UserController { @Autowired private UserService userService; public void registUser(User user){ userService.registUser(user); } public void updateUser(User user){ userService.updateUser(user); } public void deleteUserById(int id){ userService.deleteUserById(id); } public User queryUserById(int id){ return userService.queryUserById(id); } }
-
service层添加UserService与实现类
public interface UserService { void registUser(User user); void updateUser(User user); void deleteUserById(int id); User queryUserById(int id); }
@Service public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Override public void registUser(User user) { userDao.registUser(user); } @Override public void updateUser(User user) { userDao.updateUser(user); } @Override public void deleteUserById(int id) { userDao.deleteUserById(id); } @Override public User queryUserById(int id) { return userDao.queryUserById(id); } }
-
dao层添加UserDao接口与UserDaoImpl实现类
public interface UserDao { void registUser(User user); void updateUser(User user); void deleteUserById(int id); User queryUserById(int id); }
@Repository public class UserDaoImpl implements UserDao { @Override public void registUser(User user) { System.out.println("注册用户成功" + user); } @Override public void updateUser(User user) { System.out.println("更新用户成功" + user); } @Override public void deleteUserById(int id) { System.out.println("删除用户成功" + id); } @Override public User queryUserById(int id) { if (id == 1) return new User(1,"孙悟空","花果山"); return null; } }
-
添加applicationContext.xml文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <!--开启包扫描--> <context:component-scan base-package="cn.javasm"></context:component-scan> </beans>
-
加载配置类,注册IOC容器
public class TestDemo { // cust user admin public static String role = "admin"; public static void main(String[] args) { // 加载核心配置文件 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); // 获取对象 UserController userController = applicationContext.getBean(UserController.class); User user = new User(2, "猪八戒", "高老庄"); userController.registUser(user); userController.updateUser(user); System.out.println(userController.queryUserById(1)); userController.deleteUserById(2); } }
-
测试成功
2、思路说明:
使用自定义注解在service层中的实现方法上标记用户,如果一个方法上拥有该用户的名字则拥有该权限
准备工作:
- 创建一个自定义注解 目的:为了做标记
- 创建一个枚举类存放这三个用户 目的:为了后期扩展,方便维护
- 创建切面类 目的:使用spring的AOP框架来简化动态代理技术
3、创建工作
-
创建枚举类,定义三个用户权限
public enum PrivEnum { CUST,USER,ADMIN; }
-
自定义枚举
@Target(ElementType.METHOD) //作用范围为方法 @Retention(RetentionPolicy.RUNTIME) //运行时,起作用 public @interface PrivAnnotation { PrivEnum [] value() default PrivEnum.CUST; //使用枚举来 }
-
在servic层中给操作方法添加注解作为标记
注意:对于注册方法registUser都有该权限,我们可以使用不做标记的方式作为判断,在切面类内放行
@Service public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Override public void registUser(User user) { userDao.registUser(user); } @Override @PrivAnnotation(value = {PrivEnum.USER,PrivEnum.ADMIN}) public void updateUser(User user) { userDao.updateUser(user); } @Override @PrivAnnotation(value = {PrivEnum.ADMIN}) public void deleteUserById(int id) { userDao.deleteUserById(id); } @Override @PrivAnnotation(value = {PrivEnum.USER,PrivEnum.ADMIN}) public User queryUserById(int id) { return userDao.queryUserById(id); } }
-
切面类:
@Component @Aspect //添加该注解说明该类是一个切面类 public class MyAspect { @Around(value = "execution(* cn.javasm.service..*.*(..))") public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { //获取接口中的方法 MethodSignature methodSnippet = (MethodSignature) proceedingJoinPoint.getSignature(); Method method1 = methodSnippet.getMethod(); //1.获取目标对象 Object target = proceedingJoinPoint.getTarget(); System.out.println(target); //2.利用反射,根据目标对象获取目标方法 Method method = target.getClass().getMethod(method1.getName(), method1.getParameterTypes()); //3. 如果方法上标记有注解则判断 if(method.isAnnotationPresent(PrivAnnotation.class)){ //3.1根据目标方法获取方法上面的注解 PrivAnnotation annotation = method.getAnnotation(PrivAnnotation.class); PrivEnum[] value = annotation.value(); //3.1.1如果注解中的值包含用户的角色值,则执行 if(Arrays.asList(value).contains(TestDemo.role)){ return proceedingJoinPoint.proceed(); }else{ //3.1.2如果不包含则抛出异常 throw new RuntimeException("没有权限"); } }else { //如果不包含注解,则放行 return proceedingJoinPoint.proceed(); } } }
-
测试:使用枚举类作为用户测试
public class TestDemo { // cust user admin public static PrivEnum role = PrivEnum.ADMIN; public static void main(String[] args) { // 加载核心配置文件 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); // 获取对象 UserController userController = applicationContext.getBean(UserController.class); User user = new User(2, "猪八戒", "高老庄"); userController.registUser(user); userController.updateUser(user); System.out.println(userController.queryUserById(1)); userController.deleteUserById(2); } }
-
效果图