网站做外链什么意思,如何在凡科建设网站,域名是什么?,到国外做网站网站是怎么回事策略工厂定义策略接口#xff0c;多个实现类#xff0c;定义策略工厂#xff0c;构造方法通过Spring 容器自动获取实现类List集合#xff0c;遍历List按照每个实现类策略类型逐个插入Mappublic interface PayHandler {void pay(PayCommand command);String getPayType(); …策略工厂定义策略接口多个实现类定义策略工厂构造方法通过Spring 容器自动获取实现类List集合遍历List按照每个实现类策略类型逐个插入Mappublic interface PayHandler { void pay(PayCommand command); String getPayType(); // 获取支付类型例如支付宝微信 } Service(ALI) public class AliPayHandler implements PayHandler { Override public void pay(PayCommand command) { // 支付宝支付逻辑 System.out.println(支付宝支付支付金额 command.getAmount()); } Override public String getPayType() { return ALI; // 支付宝支付类型 } } Service(WECHAT) public class WeChatPayHandler implements PayHandler { Override public void pay(PayCommand command) { // 微信支付逻辑 System.out.println(微信支付支付金额 command.getAmount()); } Override public String getPayType() { return WECHAT; // 微信支付类型 } } Component public class PayHandlerFactory { private final MapString, PayHandler handlerMap; Autowired public PayHandlerFactory(ListPayHandler handlerList) { handlerMap new HashMap(); // 遍历 handlerList将每个策略和支付类型关联起来 for (PayHandler handler : handlerList) { handlerMap.put(handler.getPayType(), handler); } } public PayHandler getHandler(String payType) { PayHandler handler handlerMap.get(payType); if (handler null) { throw new IllegalArgumentException(不支持的支付方式: payType); } return handler; } }动态代理代理类在运行期自动生成无需手动实现JDK动态代理基于接口public interface OrderService { void createOrder(); } public class OrderServiceImpl implements OrderService { Override public void createOrder() { System.out.println( 执行业务创建订单); } } import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class LogInvocationHandler implements InvocationHandler { private final Object target; public LogInvocationHandler(Object target) { this.target target; } Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 方法前增强 System.out.println( 方法前记录日志 / 幂等校验 / 事务开始); // 调用目标方法 Object result method.invoke(target, args); // 方法后增强 System.out.println( 方法后提交事务 / 记录日志); return result; } } import java.lang.reflect.Proxy; public class ProxyTest { public static void main(String[] args) { // 1️⃣ 目标对象 OrderService target new OrderServiceImpl(); // 2️⃣ 创建代理对象 OrderService proxy (OrderService) Proxy.newProxyInstance( target.getClass().getClassLoader(), // 类加载器 target.getClass().getInterfaces(), // 代理的接口 new LogInvocationHandler(target) // 方法拦截器 ); // 3️⃣ 调用代理方法 proxy.createOrder(); } }CGLIB动态代理基于继承二、目标类⚠️ 没有接口 public class OrderService { public void createOrder() { System.out.println( 执行业务创建订单); } } 三、MethodInterceptor核心拦截器 import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class LogMethodInterceptor implements MethodInterceptor { Override public Object intercept( Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { // 方法前增强 System.out.println( 方法前记录日志 / 事务开始); // ⚠️ 调用父类方法不是反射 Object result proxy.invokeSuper(obj, args); // 方法后增强 System.out.println( 方法后提交事务); return result; } } 重点 invokeSuper() → 调用父类方法 不是 method.invoke()性能更好 四、创建代理对象关键代码 import net.sf.cglib.proxy.Enhancer; public class CglibProxyTest { public static void main(String[] args) { Enhancer enhancer new Enhancer(); // 1️⃣ 设置父类目标类 enhancer.setSuperclass(OrderService.class); // 2️⃣ 设置方法拦截器 enhancer.setCallback(new LogMethodInterceptor()); // 3️⃣ 创建代理对象子类实例 OrderService proxy (OrderService) enhancer.create(); // 4️⃣ 调用方法 proxy.createOrder(); } } 五、运行时 JVM 实际生成的类核心理解 JVM 运行期生成的代理类类似 class OrderService$$EnhancerByCGLIB extends OrderService { Override public void createOrder() { interceptor.intercept(...); } } 这就是“基于继承”的直接体现 六、执行流程一定要理解 proxy.createOrder() ↓ 子类重写方法 ↓ MethodInterceptor.intercept() ↓ invokeSuper() 调用父类 ↓ OrderService.createOrder()Spring AOP底层技术实现动态代理上层通过切面思想和注解优化了实现二、定义一个【幂等注解】 Target(ElementType.METHOD) Retention(RetentionPolicy.RUNTIME) public interface Idempotent { /** * 幂等key的 SpEL 表达式 * 例如#msg.orderId */ String key(); /** * 幂等超时时间秒 */ long timeout() default 300; } 关键点 SpEL 表达式 → 不侵入业务 不绑定 MQ、HTTP、RPC → 通用 三、RocketMQ 消费者业务代码极简 RocketMQMessageListener( topic ORDER_PAY_SUCCESS, consumerGroup order-consumer-group ) Component public class OrderPaySuccessConsumer implements RocketMQListenerOrderPayMsg { Override Idempotent(key ORDER_PAY_ #msg.orderId) public void onMessage(OrderPayMsg msg) { // ✅ 这里不写任何幂等代码 orderService.handlePaySuccess(msg.getOrderId()); } } ✅ 你会发现 MQ 重试 重复投递 幂等控制 业务代码完全无感知 四、AOP 幂等切面核心 Aspect Component public class IdempotentAspect { Autowired private RedissonClient redissonClient; Around(annotation(idempotent)) public Object around(ProceedingJoinPoint pjp, Idempotent idempotent) throws Throwable { Method method ((MethodSignature) pjp.getSignature()).getMethod(); // 1️⃣ 解析 SpEL生成幂等 key String key parseKey(idempotent.key(), method, pjp.getArgs()); String redisKey IDEMPOTENT: key; // 2️⃣ Redis 原子占位 RBucketString bucket redissonClient.getBucket(redisKey); boolean success bucket.trySet( PROCESSING, idempotent.timeout(), TimeUnit.SECONDS ); if (!success) { // 幂等命中直接返回 return null; } try { // 3️⃣ 执行业务逻辑 Object result pjp.proceed(); // 4️⃣ 标记成功 bucket.set(SUCCESS, idempotent.timeout(), TimeUnit.SECONDS); return result; } catch (Exception e) { // ❗ 异常要删除 key允许 MQ 重试 bucket.delete(); throw e; } } }责任链模式当执行业务逻辑前有很多条校验时采取责任链模式提升代码复用性和扩展性定义一个责任链最高层接口多个责任链模式接口每个责任链模式接口多个实现类把每个责任链模式的实现类根据定义好的Order排序存到List再根据对应责任链模式存到Mappublic interface AbstractChainHandlerT extends Ordered { /** * 执行责任链逻辑 * * param requestParam 责任链执行入参 */ void handler(T requestParam); /** * return 责任链组件标识 */ String mark(); } public interface TrainPurchaseTicketChainFilterT extends PurchaseTicketReqDTO extends AbstractChainHandlerPurchaseTicketReqDTO { Override default String mark() { return TicketChainMarkEnum.TRAIN_PURCHASE_TICKET_FILTER.name(); } } Component RequiredArgsConstructor public class TrainPurchaseTicketParamNotNullChainHandler implements TrainPurchaseTicketChainFilterPurchaseTicketReqDTO { Override public void handler(PurchaseTicketReqDTO requestParam) { if (StrUtil.isBlank(requestParam.getTrainId())) { throw new ClientException(列车标识不能为空); } if (StrUtil.isBlank(requestParam.getDeparture())) { throw new ClientException(出发站点不能为空); } if (StrUtil.isBlank(requestParam.getArrival())) { throw new ClientException(到达站点不能为空); } if (CollUtil.isEmpty(requestParam.getPassengers())) { throw new ClientException(乘车人至少选择一位); } for (PurchaseTicketPassengerDetailDTO each : requestParam.getPassengers()) { if (StrUtil.isBlank(each.getPassengerId())) { throw new ClientException(乘车人不能为空); } if (Objects.isNull(each.getSeatType())) { throw new ClientException(座位类型不能为空); } } } Override public int getOrder() { return 0; } } Component RequiredArgsConstructor public class TrainPurchaseTicketParamVerifyChainHandler implements TrainPurchaseTicketChainFilterPurchaseTicketReqDTO { private final TrainMapper trainMapper; private final TrainStationMapper trainStationMapper; private final DistributedCache distributedCache; Override public void handler(PurchaseTicketReqDTO requestParam) { // 查询会员购票车次是否存在通过封装后安全的 Get 方法 TrainDO trainDO distributedCache.safeGet( TRAIN_INFO requestParam.getTrainId(), TrainDO.class, () - trainMapper.selectById(requestParam.getTrainId()), ADVANCE_TICKET_DAY, TimeUnit.DAYS); if (Objects.isNull(trainDO)) { // 如果按照严谨逻辑类似异常应该记录当前用户的 userid 并发送到风控中心 // 如果一段时间有过几次的异常直接封号处理。下述异常同理 throw new ClientException(请检查车次是否存在); } // TODO当前列车数据并没有通过定时任务每天生成最新的所以需要隔离这个拦截。后期定时生成数据后删除该判断 if (!EnvironmentUtil.isDevEnvironment()) { // 查询车次是否已经发售 if (new Date().before(trainDO.getSaleTime())) { throw new ClientException(列车车次暂未发售); } // 查询车次是否在有效期内 if (new Date().after(trainDO.getDepartureTime())) { throw new ClientException(列车车次已出发禁止购票); } } // 车站是否存在车次中以及车站的顺序是否正确 String trainStationStopoverDetailStr distributedCache.safeGet( TRAIN_STATION_STOPOVER_DETAIL requestParam.getTrainId(), String.class, () - { LambdaQueryWrapperTrainStationDO queryWrapper Wrappers.lambdaQuery(TrainStationDO.class) .eq(TrainStationDO::getTrainId, requestParam.getTrainId()) .select(TrainStationDO::getDeparture); ListTrainStationDO actualTrainStationList trainStationMapper.selectList(queryWrapper); return CollUtil.isNotEmpty(actualTrainStationList) ? JSON.toJSONString(actualTrainStationList) : null; }, Index12306Constant.ADVANCE_TICKET_DAY, TimeUnit.DAYS ); ListTrainStationDO trainDOList JSON.parseArray(trainStationStopoverDetailStr, TrainStationDO.class); boolean validateStation validateStation( trainDOList.stream().map(TrainStationDO::getDeparture).toList(), requestParam.getDeparture(), requestParam.getArrival() ); if (!validateStation) { throw new ClientException(列车车站数据错误); } } Override public int getOrder() { return 10; } public boolean validateStation(ListString stationList, String startStation, String endStation) { int index1 stationList.indexOf(startStation); int index2 stationList.indexOf(endStation); if (index1 -1 || index2 -1) { return false; } return index2 index1; } } Component RequiredArgsConstructor public class TrainPurchaseTicketParamStockChainHandler implements TrainPurchaseTicketChainFilterPurchaseTicketReqDTO { private final SeatMarginCacheLoader seatMarginCacheLoader; private final DistributedCache distributedCache; Override public void handler(PurchaseTicketReqDTO requestParam) { // 车次站点是否还有余票。如果用户提交多个乘车人非同一座位类型拆分验证 String keySuffix StrUtil.join(_, requestParam.getTrainId(), requestParam.getDeparture(), requestParam.getArrival()); StringRedisTemplate stringRedisTemplate (StringRedisTemplate) distributedCache.getInstance(); ListPurchaseTicketPassengerDetailDTO passengerDetails requestParam.getPassengers(); MapInteger, ListPurchaseTicketPassengerDetailDTO seatTypeMap passengerDetails.stream() .collect(Collectors.groupingBy(PurchaseTicketPassengerDetailDTO::getSeatType)); seatTypeMap.forEach((seatType, passengerSeatDetails) - { Object stockObj stringRedisTemplate.opsForHash().get(TRAIN_STATION_REMAINING_TICKET keySuffix, String.valueOf(seatType)); int stock Optional.ofNullable(stockObj).map(each - Integer.parseInt(each.toString())).orElseGet(() - { MapString, String seatMarginMap seatMarginCacheLoader.load(String.valueOf(requestParam.getTrainId()), String.valueOf(seatType), requestParam.getDeparture(), requestParam.getArrival()); return Optional.ofNullable(seatMarginMap.get(String.valueOf(seatType))).map(Integer::parseInt).orElse(0); }); if (stock passengerSeatDetails.size()) { return; } throw new ClientException(列车站点已无余票); }); } Override public int getOrder() { return 20; } } public final class AbstractChainContextT implements CommandLineRunner { private final MapString, ListAbstractChainHandler abstractChainHandlerContainer new HashMap(); /** * 责任链组件执行 * * param mark 责任链组件标识 * param requestParam 请求参数 */ public void handler(String mark, T requestParam) { ListAbstractChainHandler abstractChainHandlers abstractChainHandlerContainer.get(mark); if (CollectionUtils.isEmpty(abstractChainHandlers)) { throw new RuntimeException(String.format([%s] Chain of Responsibility ID is undefined., mark)); } abstractChainHandlers.forEach(each - each.handler(requestParam)); } Override public void run(String... args) throws Exception { MapString, AbstractChainHandler chainFilterMap ApplicationContextHolder .getBeansOfType(AbstractChainHandler.class); chainFilterMap.forEach((beanName, bean) - { ListAbstractChainHandler abstractChainHandlers abstractChainHandlerContainer.get(bean.mark()); if (CollectionUtils.isEmpty(abstractChainHandlers)) { abstractChainHandlers new ArrayList(); } abstractChainHandlers.add(bean); ListAbstractChainHandler actualAbstractChainHandlers abstractChainHandlers.stream() .sorted(Comparator.comparing(Ordered::getOrder)) .collect(Collectors.toList()); abstractChainHandlerContainer.put(bean.mark(), actualAbstractChainHandlers); }); } }