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.给前端封装数据
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; }
保存redis相关笔记