AOP是怎么实现事务处理的:
更深入一些是借助了ThreadLocal类实现的,在spring 从数据连接池获取connection 时,把 connection 放进ThreadLocal中,也就和线程绑定了,事务的提交和回滚 直接从 ThreadLocal 中拿 connection 进行操作。我们也可以用ThreadLocal获取用户信息
——————————————————————————————————————————
1、提供全局UserBo副本
package com.xx.openapi.purf.s.utils;
import com.e.cc.common.pojo.bo.UserBo;
/**
* <p>
* 提供全局UserBo副本
* </p>
*
* @author DELL
* @since 2023/6/15 15:30
*/
public class SingletonThreadLocal {
private UserBo user;
private SingletonThreadLocal() {
}
private static final ThreadLocal<SingletonThreadLocal> threadLocalHandler = ThreadLocal.withInitial(SingletonThreadLocal::new);
public static SingletonThreadLocal getInstance() {
return threadLocalHandler.get();
}
public void removeUser() {
threadLocalHandler.remove();
}
public UserBo getUser() {
return user;
}
public void setUser(UserBo user) {
this.user = user;
}
}
2、客户端调用工具类
package com.xxopenapi.purf.indirect.utils;
import com.ho.UserBo;
/**
* <p>
* 客户端调用工具类
* </p>
*
* @author DELL
* @since 2023/6/15 15:32
*/
public class UserContext {
/**
* 获取当前用户
*
* @return
*/
public static UserBo getCurrentUser() {
return SingletonThreadLocal.getInstance().getUser();
}
/**
* 获得当前用户唯一ID
*
* @return
*/
public static String getCurrentUserWxUniqueId() {
UserBo user = SingletonThreadLocal.getInstance().getUser();
return null != user ? user.getJobNo() : null;
}
/**
* 获得当前用户ID
*
* @return
*/
public static String getCurrentUserHikUserId() {
UserBo user = SingletonThreadLocal.getInstance().getUser();
return null != user ? user.getJobNo() : null;
}
}
3、aop切面入口
package com.xx.ss.openapi.c.c.utils;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
/**
* 切面入口
*/
@Aspect
public class AopPointCut {
@Pointcut("execution(public * com.ss.cc.openapi.purf.c.controller.*.*(..))")
public void pointCut4Controller() {
}
}
4、用户切面,写入ThreadLocal
package com.ss.cc.openapi.purf.c.utils;
import com.alibaba.fastjson.JSON;
import com.ss.hdsyctbj.common.pojo.bo.UserBo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
/**
* 用户切面,写入ThreadLocal
*
* @author DELL
* @since 2023/6/15 15:32
*/
@Aspect
@Component
@Order(0)
@Slf4j
public class UserAspect {
@Around("com..utils.AopPointCut.pointCut4Controller()")
public Object initUserInfo(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
// 过滤掉健康检查接口
HttpServletRequest request = null;
if (null != servletRequestAttributes) {
request = servletRequestAttributes.getRequest();
String uri = request.getRequestURI();
if (StringUtils.isNotBlank(uri) && "/status".equals(uri)) {
return proceedingJoinPoint.proceed();
}
}
if (null == request) {
return proceedingJoinPoint.proceed();
}
try {
UserBo userBo = new UserBo();
userBo.setJobNo(request.getHeader("x-user-id"));
String username = request.getHeader("x-user-name");
if (StringUtils.isNotBlank(username)) {
userBo.setUserName(URLDecoder.decode(username, StandardCharsets.UTF_8.name()));
}
log.info("当前用户信息:{}", JSON.toJSONString(userBo));
SingletonThreadLocal.getInstance().setUser(userBo);
return proceedingJoinPoint.proceed();
} finally {
SingletonThreadLocal.getInstance().removeUser();
}
}
}