springMvc统一异常处理
先配置处理异常的类,然后在分析源码
mvc统一处理异常的实现常见的异常如下,基本都是参数校验的异常。参数校验需要配合jsr303的注解校验哦。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167@Slf4j@RestControllerAdvice@Conditi ...
spring-spi
java有java的spidubbo有dubbo的spispring也有自己的spi
spring spi 入口类为org.springframework.core.io.support.SpringFactoriesLoader
springBoot main启动时就用到了
1234567891011121314151617181920212223public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { ... // Context initialize 监听器 setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); // 所有的ApplicationListener setListeners((Collection) getSpringFactoriesInstances(Ap ...
MybatisPlus语法糖的校验
mybatisPlus大大的提高了我们开发的速度。因为不需要关心sql。建立好的对象通过mybatisPlus语法糖来拼接sql。但是坏处是语法糖不好统一维护。到处都是语法糖。
所以我们规定建立一层Dao,dao层负责统一管理sql。因为要去除xml里面的sql。写sql容易出问题(字符串容易写错,不同数据库还需要关心不同的特性)建议Dao统一继承此BaseDao
一个表对应一个实体、一个mapper,一个DaoDao继承BaseDao,需要实体继承BaseDomain,mapper继承CustomBaseMapper如果实体不继承baseDomain,mapper不继承CustomBaseMapper,则dao也无法继承BaseDao
如何有效(强制)的避免以下相同拼接的sql出现在多处?例如以下的sql拼接语法糖
123456789101112131415161718192021222324252627public DemoService { @Autowired DemoDao demoDao; public void ...
基于Spring的代码分层校验
常见的代码分层图
分层很明确,先说缺点
service层可以依赖多个dao层一个表肯定对应一个dao。如果一个service直接操作多张表(dao)也没问题,但是有可能所有表的操作都封闭在一个service中。
如果后期维护某一张表的时候你就得需要屡下所有调用此表的service,花费时间不说,还有可能漏掉。
如果对其中一个表进行别的业务复用的话,则需要把代码抽离出来,并且有可能开发人员不抽离,而是直接copy粘贴,导致代码原来越乱。
所以建议一个表对应一个dao和一个service,其中service只能操作自己的表(dao)。要是操作其他的表只能依赖其对应的service
上图没有明确表明哪些是可以互相依赖(service依赖其他service,dao可以依赖其他dao...),哪些不可以互相依赖。所以我们认为都是可以相互依赖的。互相依赖比较混乱。
dao专门负责管理sql,如果对一个实体的curd还涉及到另外其他的实体curd。那么这就显然属于业务范畴了,应该放在service。所以在dao这一层。我们不能让他操作多张表(不能有互相依赖)
没有强制的依赖校验。如果 ...
springBoot容器启动流程
main方法启动时,springBoot启动流程的各个生命周期会以事件通知的方式,把事件告知其他程序前期通过spring-spi获取所有监听事件的类
spring启动的大体流程为以下的几个方法 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475public class EventPublishingRunListener implements SpringApplicationRunListener { ... private final SimpleApplicationEventMulticaster initialMulticaster = new SimpleApplicationEventMulticaster(); public EventPublishingRunListener(SpringAppli ...
获取spring启动环境的工具类
必须用到的枚举工具类
参考通用枚举的---使用例子一 通用枚举
定义ENV枚举1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859@Slf4jpublic enum ENV implements IEnums<String> { RELEASE("正式", "release", "prod"), PRE("预发", "pre"), TEST("测试", "test", "test1", "test2", "test3"), DEV("dev", "dev"), LOCAL("本地", "local&q ...
分析spring的Environment(配置文件)的加载
项目立项->开发->测试->维护->上线->维护,这几个过程中分为不同的环境。不同的环境不同业务有着不同的逻辑。spring完美支持启动的时候加载不同的配置文件。我们通过指定不同的spring.profiles.active即可实现加载不同的配置文件。不管怎么样默认会加载如下几个配置文件
1234567891011121314151617181920212223public class ConfigFileApplicationListener implements EnvironmentPostProcessor, SmartApplicationListener, Ordered { ... // Note the order is from least to most specific (last one wins) private static final String DEFAULT_SEARCH_LOCATIONS = "classpath:/,classpath:/config/,file:./,f ...
java如何优雅的打印log
1 用sl4j(采用门面模式,不提供实现,且提供占位符打印的方式)2 过长的内容没有意义,集合最多打印几十个3 如果有字符串拼接或者toJSON的情况,打印log之前判断该级别是否开启,不然会白白浪费cpu4 对于第3点可优化的地方,用下面的util,配合着sl4j,这样就不用写判断日志级别是否开启的代码了
12345678910111213public abstract class LogUtils { public static LogUtils lazyJson(Object object) { return new LogUtils() { String json = null; @Override // 只有在输出的时候在toJSON,并且如果是集合的类型限制最多输出100个 public String toString() { return json != null ? json : (json ...
重新加装MybatisPlus
1.字段填充器注意重写了strictFill方法统一规范,字段填充的值和类型所有的表都一样。所以不作类型判断。
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253@Componentpublic class FieldAutoFillHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { User user = CurrentUser.getCurrentUser(); this.strictInsertFill(metaObject, "deleteFlag", null, DeleteFlag.N); this.strictInsertFill(metaObject, "isDelete", ...
MybatisPlus针对Saas系统的动态多租户插件
多租户就是用额外的一个字段代表当前表中的数据的归属。在sql curd时根据上下文的用户(租户) 自动拼接此条件动态就是有些表是公用的,没有多租户的概念。那么操作此表的时候需要排除,亦或者多个字段,每个字段的值都不一样等
前期工作1.首先定义一个多租户字段的枚举,为提取数据库多租户字段的字段做准备IEnums参考通用枚举
1234567891011121314151617181920212223242526272829303132@Getterpublic enum TenantField implements IEnums<String> { // mid 为我们系统的租户字段 // CurrentTenant 是业务系统的上下文,比如说当前的登录用户信息,可以自由改造 MID("商户id", "mid", () -> CurrentTenant.getCurrentTenant().getMid()), ; private final String[] dbFieldNames; ...