slf4j

redis系列之——分布式锁

独自空忆成欢 提交于 2020-07-27 15:13:11
端午节最后一天了,三天假期过得太快了,更坏的消息是,下周还要上六天班呢! 趁着假期的尾巴,和大家再叨逼叨redis是如何实现分布式锁的。这期也是为了填之前《redis系列之——缓存穿透、缓存击穿、缓存雪崩》留下的坑。 这一期不是专门聊分布式锁的,所以不会涉及到各种分布式锁实现及相关的比较,只是聊一下如何使用redis实现分布式锁。感觉上一个坑还没填完,这里又挖了一个大坑,各种分布式锁实现及相关的比较后面有时间我会跪着填上的,请大家给我多一点点时间,多一点点温柔。 本期是硬核输出,也是面试高频,更是实战必会。 什么是分布式锁 先说一个场景,消费者在购物网站上下单或收银员在POS机上下单,由于网络等问题,在连续点击了两下,后端网站如何处理,如何响应?对于这个问题,前端需要处理,后端也需要处理。这里主要说后端,后端不光要处理重复订单问题,还有处理幂等问题。幂等问题简单来说就是相同的请求,要有相同的响应结果,这里就不展开了。重复订单该如何处理? 对于一个小的访问量不大的网站,部署了一个tomcat,这个问题可以简单的通过JVM提供的同步锁synchronized实现。但是当网站访问量越来越大时,需要扩展机器,synchronized就不能起作用了。相同的下单参数连续两次请求后端服务器,可能会被分发到两个tomcat上,就会出现synchronized失效问题。

Springboot 系列(四)Spring Boot 日志框架

你。 提交于 2020-07-27 14:52:03
文章已经收录在 Github.com/niumoo/JavaNotes ,更有 Java 程序员所需要掌握的核心知识,欢迎Star和指教。 欢迎关注我的 公众号 ,文章每周更新。 注意:本 Spring Boot 系列文章基于 Spring Boot 版本 v2.1.1.RELEASE 进行学习分析,版本不同可能会有细微差别。 前言 Spring 框架选择使用了 JCL 作为默认日志输出。而 Spring Boot 默认选择了 SLF4J 结合 LogBack。那我们在项目中该使用哪种日志框架呢?在对于不同的第三方 jar 使用了不同的日志框架的时候,我们该怎么处理呢? <!-- more --> 1. 日志框架介绍 日志对于应用程序的重要性不言而喻,不管是记录运行情况还是追踪线上问题,都离不开对日志的分析,在 Java 领域里存在着多种日志框架,如 JUL, Log4j, Log4j2, Commons Loggin, Slf4j, Logback 等。关于 Log4j, Log4j2 和 Slf4j 直接的故事这里不做介绍,有兴趣可以自行百度。 2. SLF4 的使用 在开发的时候不应该直接使用日志实现类,应该使用日志的抽象层。具体参考 SLF4J 官方 。 下图是 SLF4J 结合各种日志框架的官方示例,从图中可以清晰的看出 SLF4J API 永远作为日志的门面

Java实现大批量数据导入导出(100W以上) -(一)导入

别说谁变了你拦得住时间么 提交于 2020-07-27 09:52:18
最近业务方有一个需求,需要一次导入超过100万数据到系统数据库。可能大家首先会想,这么大的数据,干嘛通过程序去实现导入,为什么不直接通过SQL导入到数据库。 大数据量报表导出请参考: Java实现大批量数据导入导出(100W以上) -(二)导出 一、为什么一定要在代码实现 说说为什么不能通过SQL直接导入到数据库,而是通过程序实现: 1. 首先,这个导入功能开始提供页面导入,只是开始业务方保证的一次只有<3W的数据导入; 2. 其次,业务方导入的内容需要做校验,比如门店号,商品号等是否系统存在,需要程序校验; 3. 最后,业务方导入的都是编码,数据库中还要存入对应名称,方便后期查询,SQL导入也是无法实现的。 基于以上上三点,就无法直接通过SQL语句导入数据库。那就只能老老实实的想办法通过程序实现。 二、程序实现有以下技术难点 1. 一次读取这么大的数据量,肯定会导致服务器内存溢出; 2. 调用接口保存一次传输数据量太大,网络传输压力会很大; 3. 最终通过SQL一次批量插入,对数据库压力也比较大,如果业务同时操作这个表数据,很容易造成死锁。 三、解决思路 根据列举的技术难点我的解决思路是: 1. 既然一次读取整个导入文件,那就先将文件流上传到服务器磁盘,然后分批从磁盘读取(支持多线程读取),这样就防止内存溢出; 2. 调用插入数据库接口也是根据分批读取的内容进行调用; 3.

SLF4J: Class path contains multiple SLF4J bindings.

谁说我不能喝 提交于 2020-07-27 06:06:53
SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [jar:file:/C:/Users/86186/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [jar:file:/C:/Users/86186/.m2/repository/org/slf4j/slf4j-log4j12/1.7.30/slf4j-log4j12-1.7.30.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation. SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder] java编译执行报SLF4J的重复绑定,虽不影响执行;但是红色的错误提示还是不能忍;

Spring枚举传参转换

岁酱吖の 提交于 2020-07-26 21:51:24
Spring boot枚举传参转换 在实际web开发项目中会用到枚举,本文章主要分析SpringBoot传参转换枚举, 主要包括SpringBoot传参转换枚举使用实例、应用技巧、基本知识点总结和需要注意事项,该技术对于Spring MVC同样适用。具体来讲可以归纳两种实现方式 可以基于Jackson自带枚举序列化方式进行转换; 基于Spring类型转换器方式来实现枚举传参转换; 以上两种方式都可以实现,只是方法一对于简单处理是可行,但是对于复杂或者全局处理就有局限性,推荐方法二, 本文主要解剖第二种实现方式 有时候,我们传参的时候,希望使用枚举类来当作参数,如下: e.g : public enum VipEnum { YELLOW(1, "黄钻"), RED(2, "红钻"); private Integer index; private String value; VipEnum(Integer index, String value) { this.index = index; this.value = value; } public Integer getIndex() { return index; } public String getValue() { return value; } } 我们期望的是这样,参数中传一个1 后台就自动转换为枚举类的VipEnum

java 线程中使用lamba表达式

心已入冬 提交于 2020-07-24 22:05:28
举例 import lombok.extern.slf4j.Slf4j; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @Slf4j public class SynchronizedExample2 { // 修饰一个类 public static void test1( int j) { synchronized (SynchronizedExample2. class ) { for ( int i = 0; i < 3; i++ ) { log.info( "test1 {} - {}" , j, i); } } } // 修饰一个静态方法 public static synchronized void test2( int j) { for ( int i = 0; i < 3; i++ ) { log.info( "test2 {} - {}" , j, i); } } public static void main(String[] args) { SynchronizedExample2 example1 = new SynchronizedExample2(); SynchronizedExample2 example2 = new

springboot 通过类名称获取bean

巧了我就是萌 提交于 2020-07-24 00:52:23
IOC容器有beanFactory 和ApplicationContext.通常建议使用后者,因为它包含了前者的功能。Spring的核心是ApplicationContext.它负责管理 beans 的完整生命周期。我们可以从applicationContext里通过bean名称获取安装的bean.进行某种操作。不能直接使用applicationContext.而需要借助applicationContextAware.具体方法如下: @Component public class ApplicationContextGetBeanHelper implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this .applicationContext = applicationContext; } public static Object getBean(String className) throws BeansException

Override Logback error output

六眼飞鱼酱① 提交于 2020-07-17 10:17:48
问题 In my custom exception class I've overridden toString() : @Override public String toString() { final String msg = getLocalizedMessage(); // base String str = getClass().getName() + ": [" + code + "]"; // message if (msg != null) str += " " + msg; // extra if (extra != null) { str += '\n' + extra.toString(); } return str; } (yes, I'm aware I should use StringBuilder there) However, when I log such an exception (via org.slf4j.Logger.warn(String msg, Throwable err) ) the output is as for vanilla

Override Logback error output

家住魔仙堡 提交于 2020-07-17 10:17:07
问题 In my custom exception class I've overridden toString() : @Override public String toString() { final String msg = getLocalizedMessage(); // base String str = getClass().getName() + ": [" + code + "]"; // message if (msg != null) str += " " + msg; // extra if (extra != null) { str += '\n' + extra.toString(); } return str; } (yes, I'm aware I should use StringBuilder there) However, when I log such an exception (via org.slf4j.Logger.warn(String msg, Throwable err) ) the output is as for vanilla

How to verify (with unit test) that error stack is printed in the log file?

故事扮演 提交于 2020-06-29 03:32:55
问题 In continuing to this answer I wrote a unit test to verify that in case of error, the stack will be printed in the log file. The tested method: import org.slf4j.Logger; import org.slf4j.LoggerFactory; private final Logger logger = LoggerFactory.getLogger(getClass()); public long getFq(String fi) { try { return calcSomeThing(fi.toLowerCase()); } catch (Exception e) { logger.error("unable to calculate SomeThing. Error: " , e); return -1; } } The unit test: import ch.qos.logback.classic.Level;