服务构造静态引用
构造静态引用我们有些静态工具类中如果需要使用到service,这个时候引入就会有问题,如下所示
1234567891011121314151617package com.tthk.inland.ticket.core.utils.statistic;import com.tthk.inland.ticket.core.utils.redis.RedisUtil;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;@Componentpublic class StaticRedisTemplateComponet { @Autowired private RedisUtil redisUtil; private static void test(){ redisUtil.get("test"); }}
有时候我们在静态方法里面 ...
实体类转MAP工具类
实体类转MAP工具类123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657package com.tthk.inland.ticket.core.utils.other;import java.lang.reflect.Field;import java.util.HashMap;import java.util.Map;public class EntityUtils { /** * * @description 实体类转Map */ public static Map<String, Object> entityToMap(Object object) { Map<String, Object> map = new HashMap<>(); for (Field field : object.getClass().getDeclaredFields()) ...
http工具类统一封装
http工具类统一封装
个人封装使用,仅供参考,用来捕获接口异常,并且通知到企业微信
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354package com.tthk.inland.ticket.core.utils.https;import cn.hutool.http.HttpRequest;import cn.hutool.http.HttpResponse;import com.alibaba.fastjson.JSONObject;import com.tthk.framework.base.api.dto.CommonResult;import com.tthk.inland.ticket.core.enums.result.ResulEnum;import com.tthk.inland.ticket.core.enums.wechat.WeChatEnums;import com.tthk.inland.ticket.c ...
limiter限流
limiter限流单机限流思路介绍采用 Google 的 Guava 中的 RateLimiter.create 来进行令牌桶的分发,但是我们需要动态控制限流的速率,所以在这上面利用单例模式的“ 双重检查锁 ”和 “懒汉式”来进行动态创建
12345<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>20.0</version></dependency>
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960package com.tthk.inland.ticket.core.utils.limiters;import com.google.common.util.concurrent.Rate ...
定义either类
定义either类
在我们日常开发中,stream流里面如果出现了异常是没法直接抛出的,需要进行try-catch进行捕获然后进行处理,或者干脆直接抛出异常停止
这个时候我们需要一个either工具类,区分成功和失败的执行结果,并且单独对失败的这些结果进行处理,以下是一些简单的实现
1234567891011121314151617181920212223242526272829303132333435package com.tthk.inland.ticket.core.utils.stream;import java.util.List;import java.util.Random;import java.util.stream.Collectors;import java.util.stream.Stream;/** * @Description either类 * @date 2023/4/20_15:05 * @author Foam */public class Either<L, R> { public static void main(S ...
规则枚举
规则枚举一些简单的猜想实现,用来去除ifelse或者switch,虽然在jdk17中已经引入了新的switch语法,但是还是想做一些尝试
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849package com.tthk.inland.ticket.core.enums.czloworder;import lombok.AllArgsConstructor;import lombok.Getter;import java.util.Arrays;/** * @author Foam * @Description 枚举 * @date 2023/5/4 17:12 */@Getter@AllArgsConstructorpublic enum LowOrderEnums { UNLIMITED("枚举1"){ @Override public boolean check(Integer i ...
控制xxl-job下次执行时间
项目场景:
目前项目引入了 xxl-job 来跑定时任务,但是存在一个问题,项目执行结束的时间不固定,有峰值,在高峰期的时候会出现长阻塞一直排队等待,如图:
问题描述需要做一种策略来解决长阻塞问题,精准控制下一次执行时间,尽量保证不空档
原因分析:1.上游接口的接口限流或者峰值压力导致返回超时2.高峰期数据量达到峰值处理不过来3.设置的执行间隔太短,执行不过来
解决方案:思路 编写一个cron表达式,时间一分钟一次,直接获取当前时间的下一次执行时间,并且更新到xxl-job的执行日志里面
注意 1.因为设置的1分钟59秒,所以在秒的位置设置了59,防止在59秒执行完更新超时,导致定时任务执行过时间
2.xxlJobInfo.setTriggerStatus(1); 设置这个,只需要点击立即执行就可以让它运行,但是后续可能需要加一个开关来控制需要执行的策略是一次或者多次
3.在xxl_job_info中schedule_conf是编写cron表达式,但是trigger_next_time才是下次执行时间,需要转为时间戳更新
实现方法12345678910111213 ...
秒杀架构
什么是秒杀(seckill)seckill是一个老生常谈的场景它一般出现在电商系统中,在某些特定的节日,限定特定商品数量以超低折扣进行促销引流按照秒杀的特性,特价商品一般在一两秒内被抢光,剩下的人只会出现售罄页面这一两秒会出现一个瞬间峰值,因为是短暂的活动,不能消耗太多服务器资源,所以需要达到最小代价做到最大的抗压,不直接冲垮服务器,还得保证不超卖,不丢单,不宕机等问题
seckill需要注意哪些问题幂等
多次调用方法或者接口不会改变业务状态,可以保证重复调用的结果和单次调用的结果一致
描述
前端重复提交:前端瞬间点击多次造成表单重复提交
接口超时重试:接口可能会因为某些原因而调用失败,处于容错性考虑会加上失败重试的机制。如果接口调用一半,再次调用就会因为脏数据的存在而产生异常
消息重复消费:在使用消息中间件来处理消息队列,且手动ack确认消息被正常消费时。如果消费者突然断开链接,那么已经执行了一半的消息会重新放回队列。被其他消费者重新消费时就会导致结果异常,如数据库重复数据, 数据库数据冲突,资源重复等
请求重发:网络抖动引发的nginx重发请求,造成重复调用解决方案
给前端点 ...
实体类设计
DDD领域驱动设计(Domain-driven design)介绍领域驱动设计:是一种通过将实现连接到持续进化的模型来满足复杂需求的软件开发方法(一种解决业务复杂性的设计思想,不是一种标准规则的解决方法)领域模型是对业务模型的抽象,DDD是把业务模型翻译成系统架构设计的一种方式
失血模型
模型仅仅包含对象属性的定义和操作对象的getter/setter方法其它所有的业务逻辑完全由业务逻辑层去实现,这种类叫POJO
优点:对象结构简单缺点:会导致业务逻辑层臃肿,难于理解和维护,无法良好的扩展复杂业务逻辑和场景
123456@Datapublic class person { private String name; private String sex; private Integer age;}
贫血模型
模型包含了对象属性的定义和操作对象的getter/setter方法并且包含了对象的行为【是完整的一个对象】属性:姓名,性别,年龄等行为:走路,吃饭,睡觉等不包括依赖持久层的业务逻辑,这部分持久层的数据还是在业务逻辑层去实现,组合逻辑也是服务类负 ...
Vector
什么是Vector类似于ArrayList,Vector也是由数组组成,默认的初始化大小是【10】但是Vector是线程安全的,在大多数的方法上面都存在synchronized关键字如果需要进行扩容,每次扩容大小默认为【2】,注意(capacityIncrement > 0)是双括号条件
Vector和ArrayList的区别1.vector默认构造还是饿汉式,而arrayList在1.8后改为了懒汉式2.Vector 是多线程安全的,线程安全就是说多线程访问同一代码,不会产生不确定的结果,而 ArrayList 不是,这个可以从源码中看出,Vector 类中的方法很多有 synchronized 进行修饰,这样就导致了 Vector 在效率上无法与 ArrayList 相比【第二张图能体现】3.vector可以设置增长因子【默认0】
以2倍的方式扩容,导致下一次申请的内存必然大于之前分配内存的总和,导致之前分配的内存不能再被使用,所以最好倍增长因子设置为(1,2)之间
4.因为考虑到线程安全的问题,效率比较低可以用什么代替VectorCopyOnWriteArrayList ...