SpringAOP详解(下)

小项目

1.对权限控制进行优化 (配合注解使用)

2.事务的开启

3.给前端封装数据 (配合注解使用)

1.对权限控制进行优化

ThreadLocal:上游的数据可以直接被下游获取到

      为每一个线程创建一个单独的变量副本,故而每个线程都可以独立地改变自己所拥有的变量副本,而不会影响其他线程所对应的副本

 

相关方法:

  • get():返回此线程局部变量的当前线程副本中的值。
  • initialValue():返回此线程局部变量的当前线程的“初始值”。
  • remove():移除此线程局部变量当前线程的值。
  • set(T value):将此线程局部变量的当前线程副本中的值设置为指定值。
com.wiscom.anno.PrivAnno:代表权限的注解
package com.wiscom.anno;
​
@Target(ElementType.METHOD) //注解使用在方法上
@Retention(RetentionPolicy.RUNTIME)//保证注解保留在运行阶段
public @interface PrivAnno {
    // 代表权限的数组
    PrivEnum[] value() default PrivEnum.CUST;
}
PrivEnum:枚举出权限的类别
package com.wiscom.enums;
​
public enum PrivEnum {
    CUST,USER,ADMIN
}
com.wiscom.service.UserServiceImpl
com.wiscom.test.TestDemo
package com.wiscom.test;
​
public class TestDemo {
    // 本地线程变量
    public static ThreadLocal<PrivEnum> local = new ThreadLocal<PrivEnum>();
    @Test
    public void test01(){
        // 加载spring容器
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 获取控制器
        final UserController controller = context.getBean(UserController.class);
        // 创建用户
        User user = new User(11,"zbj","456","zbj@qq.com");
        // 注册
        controller.registUser(user);
//      // 更新
//      controller.updateUser(user);
//      // 删除
//      controller.deleteUser(22);
//      // 查询
//      User user1 = controller.queryUser(111);
//      System.out.println(user1);
        // 开辟不同的线程
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                // 设置当前线程的权限
                local.set(PrivEnum.CUST);
                controller.deleteUser(11);
            }
        }).start();
        
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                // 设置当前线程的权限
                local.set(PrivEnum.ADMIN);
                controller.deleteUser(22);
            }
        }).start();
    }
}
com.wiscom.aspect.PrivAspect
package com.wiscom.aspect;
​
@Component
@Aspect
public class PrivAspect {
    @Around("execution(* com.wiscom.service.*.*(..))")
    public Object privFunc(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println("===================");
        // 在环绕通知中根据注解的权限决定要不要执行目标方法
        Object obj;
        // 1.获取被拦截下来的方法
        MethodSignature ms = (MethodSignature) pjp.getSignature();
        Method method = ms.getMethod();// 获取的默认是接口的方法
        // 需要获取的是实际运行时调用的方法
        // 获取目标对象
        Object targetObj = pjp.getTarget();
        // 获取实际调用的方法
        Method instanceMethod = targetObj.getClass().getMethod(method.getName(), method.getParameterTypes());
        
        // 2.判断方法上面是否有PrivAnno注解
        if (instanceMethod.isAnnotationPresent(PrivAnno.class)){
            // 代码执行到这一行,代表方法上面有权限注解
            
            // 3.获取被拦截方法上面的注解的权限
            PrivAnno anno = instanceMethod.getAnnotation(PrivAnno.class);
            PrivEnum[] privs = anno.value(); // [admin,user]
            
            // 4.获取当前用户的权限
            PrivEnum role = TestDemo.local.get();
            
            // 5.判断注解上面的权限是否包含当前用户的权限
            if (Arrays.asList(privs).contains(role)){
                // 6.包含权限,执行目标方法
                obj = pjp.proceed();
                return obj;
            }else{
                // 7.如果权限不足,那么抛出异常
                throw new RuntimeException("权限不足");
            }
            
        }else{// 没有权限对应的注解
            // 直接执行
            obj = pjp.proceed();
            return obj;
        }
        
    }
}

 

 

2.1事务的开启(待优化)

可以添加注解进行控制是否需要开启事务

com.wiscom.util.TranManager
package com.wiscom.util;
​
public class TranManager {
    
    // 需要连接
    public static Connection conn;
    
    static{
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql:///sdb","root","root");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    /// 开启事务  --关闭自动提交
    public static void startTran(){
        System.out.println("开启事务");
        try {
            // 关闭自动提交
            conn.setAutoCommit(false);
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    // 提交事务
    public static void commitTran(){
        System.out.println("提交事务");
        try {
            conn.commit();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    // 回滚事务
    public static void rollbackTran(){
        System.out.println("回滚事务");
        try {
            conn.rollback();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    // 关闭连接
    public static void closeConn(){
        try {
            conn.close();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    // 返回连接
    public static Connection getConnection(){
        return conn;
    }
    
}
com.wiscom.aspect.TransactionAspect
package com.wiscom.aspect;
​
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
​
import com.wiscom.util.TranManager;
​
@Component
@Aspect
public class TransactionAspect {
    
    // 环绕通知
    @Around("execution(* com.wiscom.service.*.*(..))")
    public Object transactionAdvice(ProceedingJoinPoint pjp)throws Throwable{
        try {
            // 开启事务
            TranManager.startTran();
            // 执行目标方法
            Object obj = pjp.proceed();
            // 提交事务
            TranManager.commitTran();
            return obj;
        } catch (Exception e) {
            
            // 回滚事务
            TranManager.rollbackTran();
            throw e;
        }
    }
}

 

 

2.2事务的开启(优化版本)

可以通过注解进行控制

com.wiscom.service.UserServiceImpl
package com.wiscom.service;
​
@Service
public class UserServiceImpl implements  UserService{
    @Autowired
    private UserDao dao;
    @Override  //游客  用户 管理员都可以调用
    @Tran
    public void registUser(User user) {
            dao.addUser(user);
    }
​
    @Override  // 用户和管理员可以调用
    @Tran
    public void updateUser(User user) {
            dao.updateUser(user);       
    }
    
    @Override  //只有管理员可以删除
    public void deleteUser(int id) {
            // 删除用户
            dao.deleteUser(id);
    }
​
    @Override  //用户和管理员可以查询
    @Tran
    public User queryUser(int id) {
            // 可以执行权限
            User user = dao.queryUser(id);
            return user;            
    }
​
}
​
com.wiscom.util.TranManager
package com.wiscom.util;
​
public class TranManager {
    
    // 需要连接
    public static Connection conn;
    
    static{
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql:///sdb","root","root");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    /// 开启事务  --关闭自动提交
    public static void startTran(){
        System.out.println("开启事务");
        try {
            // 关闭自动提交
            conn.setAutoCommit(false);
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    // 提交事务
    public static void commitTran(){
        System.out.println("提交事务");
        try {
            conn.commit();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    // 回滚事务
    public static void rollbackTran(){
        System.out.println("回滚事务");
        try {
            conn.rollback();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    // 关闭连接
    public static void closeConn(){
        try {
            conn.close();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    // 返回连接
    public static Connection getConnection(){
        return conn;
    }
    
}
com.wiscom.aspect.TransactionAspect
package com.wiscom.aspect;
​
@Component
@Aspect
public class TransactionAspect {
    
    // 环绕通知
    @Around("execution(* com.wiscom.service.*.*(..))")
    public Object transactionAdvice(ProceedingJoinPoint pjp)throws Throwable{
        // 0.获取接口的方法
        MethodSignature ms = (MethodSignature) pjp.getSignature();
        Method method = ms.getMethod();
        // 1.获取真正执行的方法
        // 1.1获取目标对象
        Object targetObj = pjp.getTarget();
        // 1.2获取目标对象的字节码文件对象
        Class clz = targetObj.getClass();
        // 1.3获取目标对象的方法  参数1:方法名  参数2:参数列表
        Method instanceM = clz.getMethod(method.getName(), method.getParameterTypes());
    
        // 2.判断方法上面是否有对应的Tran注解 --> 如果有那么添加事务 如果没有直接执行方法
        if (instanceM.isAnnotationPresent(Tran.class)){
            // 有对应的Tran注解,需要添加事务
            try {
                // 开启事务
                TranManager.startTran();
                // 执行目标方法
                Object obj = pjp.proceed();
                // 提交事务
                TranManager.commitTran();
                return obj;
            } catch (Exception e) {
                // 回滚事务
                TranManager.rollbackTran();
                throw e;
            }
        }else{
            // 没有对应的Tran注解,直接执行目标方法
            return pjp.proceed();
        }
    }
}
com.wiscom.test.TestDemo
package com.wiscom.test;
​
public class TestDemo {
    // 本地线程变量
    @Test
    public void test01(){
        // 加载spring容器
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 获取控制器
        final UserController controller = context.getBean(UserController.class);
        // 创建用户
        User user = new User(11,"zbj","456","zbj@qq.com");
        // 注册
        controller.registUser(user);
//      // 更新
        controller.updateUser(user);
//      // 删除
        controller.deleteUser(22);
        // 查询
        User user1 = controller.queryUser(111);
        System.out.println(user1);
    }
}

 

 

 

 

3.给前端封装数据

ExceptionAnnotation.java
package com.wiscom.web.annotation;
​
import com.wiscom.commonEnum.ResultState;
​
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
​
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExceptionAnnotation {
    public String SuccessMsg() default "操作成功";
    public ResultState SuccessState() default ResultState.SUCCESS;
    public String FailMsg() default "操作失败";
    public ResultState FailState() default ResultState.ERROR;
}
ResultState.java
package com.wiscom.commonEnum;

public enum ResultState {
    //构造函数传入参数
    FAIL(0),
    SUCCESS(1),
    ERROR(2);
​
    private int _code;
​
    private ResultState(int code) {
        this._code = code;
    }
​
    @Override
    public String toString() {
        return String.valueOf(this._code);
    }
}
​
CommonResult.java
package com.wiscom.common;
​
import com.wiscom.commonEnum.ResultState;
​
/**
 * 统一返回结果类库
 * Created by wuhang on 2017/1/12.
 */
public class CommonResult {
    private ResultState state;
    private Object rows;
    private String msg;
    private long total = 0;
    private String error;
    private Integer[] errorkeys;
}
ExceptionAspect.java
package com.wiscom.web.annotation;
​
import com.wiscom.common.CommonResult;
import com.wiscom.commonEnum.ResultState;
import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import wiscom.psp.common.miniserver.StringUtils;
import org.aspectj.lang.reflect.MethodSignature;
import java.lang.reflect.Method;
​
@Aspect
@Component
public class ExceptionAspect {
​
    private static Logger logger = Logger.getLogger(ExceptionAspect.class);
​
    @Pointcut("@annotation(com.wiscom.web.annotation.ExceptionAnnotation)")
    public void ExceptionAspect(){
​
    }
​
    @Around("ExceptionAspect()")
    public CommonResult doAround(ProceedingJoinPoint joinPoint){
        CommonResult result = new CommonResult();
        String successMsg = "";
        ResultState successState = null;
        String failMsg = "";
        ResultState failState = null;
        try {
            //String targetName = joinPoint.getTarget().getClass().getName();
            // 拦截的方法名称。当前正在执行的方法
            String methodName = joinPoint.getSignature().getName();
            //Object[] arguments = joinPoint.getArgs();
            // 拦截的方法参数类型
            Signature sig = joinPoint.getSignature();
            MethodSignature msig = null;
            if (!(sig instanceof MethodSignature)) {
                throw new IllegalArgumentException("该注解只能用于方法");
            }
            msig = (MethodSignature) sig;
            // 拦截的方法参数数组
            Class[] parameterTypes = msig.getMethod().getParameterTypes();
            // 拦截的实体类,就是当前正在执行的controller
            Object target = joinPoint.getTarget();
            //拦截的方法,就是当前调用的方法
            Method method = target.getClass().getMethod(methodName, parameterTypes);
            if (null != method) {
                successMsg = method.getAnnotation(ExceptionAnnotation.class).SuccessMsg();
                successState = method.getAnnotation(ExceptionAnnotation.class).SuccessState();
                failMsg = method.getAnnotation(ExceptionAnnotation.class).FailMsg();
                failState = method.getAnnotation(ExceptionAnnotation.class).FailState();
            }
            /*Class targetClass = Class.forName(targetName);
            Method[] methods = targetClass.getMethods();
            for (Method method : methods) {
                if (method.getName().equals(methodName)) {
                    Class[] clazzs = method.getParameterTypes();
                    if (clazzs.length == arguments.length) {
                        successMsg = method.getAnnotation(ExceptionAnnotation.class).SuccessMsg();
                        successState = method.getAnnotation(ExceptionAnnotation.class).SuccessState();
                        failMsg = method.getAnnotation(ExceptionAnnotation.class).FailMsg();
                        failState = method.getAnnotation(ExceptionAnnotation.class).FailState();
                        break;
                    }
                }
            }*/
            result = (CommonResult) joinPoint.proceed();
            if(StringUtils.isEmpty(result.getMsg())){
                result.setMsg(successMsg);
            }
            if(result.getState() == null){
                result.setState(successState);
            }
            return result;
        }catch (Throwable e){
            logger.info(e.getMessage());
            result.setMsg(e.getMessage());
            result.setState(failState);
        }
        return result;
    }
}
​
使用方法:
    @RequestMapping(value = "/getIconList")
    @ResponseBody
    @ExceptionAnnotation
    public CommonResult getIconList() {
        CommonResult result = new CommonResult(ResultState.SUCCESS);
        result.setRows(iIntersectionDiagramEditService.getIconList());
        return result;
    }

 

 

posted @ 2020-08-19 15:15  minnersun  阅读(111)  评论(0编辑  收藏  举报