JTA 深度历险 - 原理与实现
一、利用 JTA 处理事务
1.1 什么是事务处理
事务是计算机应用中不可或缺的组件模型,它保证了用户操作的原子性 ( Atomicity )、一致性 ( Consistency )、隔离性 ( Isolation ) 和持久性 ( Durabilily )。
关于事务最经典的示例莫过于信用卡转账:将用户 A 账户中的 500 元人民币转移到用户 B 的账户中,其操作流程如下:
将 A 账户中的金额减少 500
将 B 账户中的金额增加 500
这两个操作必须保正 ACID 的事务属性:即要么全部成功,要么全部失败。假若没有事务保障,用户的账号金额将可能发生问题:
假如第一步操作成功而第二步失败,那么用户 A 账户中的金额将就减少 500 元而用户 B 的账号却没有任何增加(不翼而飞)。
如果第一步出错,而第二步成功,那么用户 A 的账户金额不变而用户 B 的账号将增加 500 元(凭空而生)。
上述任何一种错误都会产生严重的数据不一致问题,事务的缺失对于一个稳定的生产系统是不可接受的。
1.2 J2EE 事务处理方式
1.2.1 本地事务
本地事务紧密依赖于底 ...
详解 Spring 声明式事务
一、引言
Spring的事务机制包括声明式事务和编程式事务。
编程式事务管理:Spring推荐使用 TransactionTemplate,实际开发中使用声明式事务较多。
声明式事务管理:将我们从复杂的事务处理中解脱出来,获取连接,关闭连接、事务提交、回滚、异常处理等这些操作都不用我们处理了,Spring都会帮我们处理。
声明式事务管理使用了 AOP 实现的,本质就是在目标方法执行前后进行拦截。在目标方法执行前加入或创建一个事务,在执行方法执行后,根据实际情况选择提交或是回滚事务。
声明式事务优点:不需要在业务逻辑代码中编写事务相关代码,只需要在配置文件配置或使用注解(@Transaction),这种方式没有侵入性。
声明式事务缺点:声明式事务的最细粒度作用于方法上,如果像代码块也有事务需求,只能变通下,将代码块变为方法。
事务属性包含以下五个方面:隔离级别、传播行为、回滚规则、事务超时、只读。
二、基本使用
首先在类中注入事务管理器,然后在需要实现事务的方法上添加 @Transactional 注解。通过调用 transactionManager 的 commit() ...
SpringBoot 远程调试
在配合 QA 进行代码测试,以及处理线上 BUG 时,代码往往已经被部署于服务器端,因此服务器端程序支持远程调试功能就尤为重要。
Java 原生支持调试功能,由于实际开发中使用 SpringBoot,因此本文探讨基于 jar 包的调试,远程调试的 IDE 为 IDEA。
注: war 包调试、Eclipse 远程调试功能请另行了解,这不在本文的探讨范围内。
一、调试命令
最为常见的远程调试命令,也是我正在使用的调试命令是:
1java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=6001 -jar xxx.jar
当然更多的你也可能见到这种:
1java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=6001 -jar xxx.jar
1.1 基础概念
JPDA(Java Platform Debugger Architecture),即 Java 平台调试体系,具体结构图如下图所示。
其中实现调试功能的主要协议是 J ...
理解 BigDecimal 的 RoundingMode
在金融等对数据精度计算要求较高的领域,传统 double 运算无法满足要求, BigDecimal 类应运而生。实际使用中,RoundingMode 这个枚举类控制着小数的舍位原则,本文对该枚举类进行介绍。
一、RoundingMode.DOWN
等价枚举: BigDecimal.ROUND_DOWN
舍位原则: 粗暴截断舍弃位,不考虑任何进位舍位操作
例: Scale = 2
1234Origin:3.33333333333333 OutPut:3.33Origin:1.976744186046512 OutPut:1.97Origin:-4.868913857677903 OutPut:-4.86Origin:-2.307692307692308 OutPut:-2.3
二、RoundingMode.UP
等价枚举: BigDecimal.ROUND_UP
舍位原则: 精度保留的最后一位,朝远离数轴的方向进位。正数+1,负数-1
例: Scale = 2
1234Origin:3.33333333333333 ...
探讨 Spring MVC 能否注入 Request 和 Response
一、引言
当我们第一次接触到 Java Web 开发,从最原生的 Servlet 方法开始,我们就知道在 doGet() 或者 doPost() 方法有两个形参,分别是 HttpServletRequest 和 HttpServletResponse,这两个参数代表了 web 容器为我们封装的 HTTP 请求和 HTTP 响应。
当 Java Web 进化到 SpringMVC 中,一系列的杂活脏活都交给了 DispatcherServlet 前端控制器来处理。
回到正文,传统情况下,我们访问一个接口,想要从中取得 request 对象,或者是 response 对象,亦或者是 httpSession 对象,都是直接作为形参传进来。举个例子,前端传递 token,先经过 filter 得到用户ID,并将它存入 request 中,那么在每个接口中取得用户ID,都要这样:
12345@GetMapping(/"test")public ResponseResult test(HttpServletRequest request, HttpServletRespons ...
从 Git 仓库的 Commit 历史中移除敏感文件
在很多情况,我们由于疏忽会将一些敏感信息误传到 Git 仓库上面去。 尽管我们可以使用 git rm 将包含敏感信息文件删除掉,然后重新提交上传,文件就不会在仓库文件列表显示。 但是这并不能完全将敏感信息文件从仓库中完全删除, commit history 仍然会有敏感信息的文件的残留,我们仍然可以从仓库中的 commit history 中访问到文件。
如果想要将敏感信息文件完全删除。不仅需要将文件从 github 中的文件列表中删除,同时还需要将文件从 github 的 commit history 中的 文件相关信息删除。删除 commit history 文件相关信息,主要有两种方法:
filter-branch
BFG
一、filter-branch
1.1 移除数据
filter-branch 是 git 自带的命令:
123git filter-branch --force --index-filter \'git rm --cached --ignore-unmatch PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA ...
Java Switch 是如何支持 String 的,为什么不支持 long
我们知道 Java Switch 支持byte、short、int 类型,在 JDK 1.5 时,支持了枚举类型,在 JDK 1.7 时,又支持了 String类型。那么它为什么就不能支持 long 类型呢,明明它跟 byte、short、int 一样都是数值型,它又是咋支持 String 类型的呢?
一、结论
不卖关子,先说结论:
switch 底层是使用 int 型 来进行判断的,即使是枚举、String类型,最终也是转变成 int 型。由于 long 型表示范围大于 int 型,因此不支持 long 类型。
下面详细介绍下各个类型是如何被转变成 int 类型的,使用的编译命令为 javac,反编译网站为:http://javare.cn
二、枚举类型是咋变成 int 类型的?
在没有实验之前,我想当然的认为它是不是根据枚举的 int 型字段来计算的(因为一般枚举都是一个int型,一个string型),但是转念一想,万一枚举没有 int 型字段呢,万一有多个 int 型字段呢,所以肯定不是这样的,下面看实验吧。
定义两个枚举类,一个枚举类有一个int型属性,一个string型 ...
String hashCode 方法为什么选择数字31作为乘子
一、背景
某天,我在写代码的时候,无意中点开了 String hashCode 方法。然后大致看了一下 hashCode 的实现,发现并不是很复杂。但是我从源码中发现了一个奇怪的数字,也就是本文的主角31。在接下来章节里,请大家带着好奇心和我揭开数字 31 的用途之谜。
二、选择数字31的原因
在详细说明 String hashCode 方法选择数字31的作为乘子的原因之前,我们先来看看 String hashCode 方法是怎样实现的,如下:
12345678910111213// java.lang.String#hashCodepublic int hashCode() { int h = hash; if (h == 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; } ...
详解 Guava Cache
一、Guava Cache
推荐大家改用 Caffine,性能更佳!
一般在项目中,本地缓存的实现为 ConcurrentHashMap,它具有线程安全、持久有效的特点。但是相较于传统缓存,它不具备缓存过期、缓存移除等特性,Google Guava 包内的 Cache 模块可能会给你一个新的选择。
Guava 目前托管于 GitHub,在项目中引入也是十分简单:
1234567<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>27.1-jre</version> <!-- or, for Android: --> <version>27.1-android</version></dependency>
二、初始化
2.1 CacheLoader
如果我们希望对缓存中所有的 key 值使用同一个 ...
Markdown 使用进阶教程
一、为什么要学习 Markdown?
语法简练,上手迅速
纯文本、轻量级
支持协作开发
所想即所得
跨平台、高兼容
使用广泛
二、Markdown 语法
2.1 标题
使用多个 # 的方式实现标题,Markdown 支持 1 ~ 6 级标题,6级标题以上将不会被识别。
123456# 一级标题## 二级标题### 三级标题#### 四级标题##### 五级标题###### 六级标题
2.2 粗体、斜体、删除、分割线、更改颜色
使用单个 * 号包裹文字,实现斜体的效果:
1*这是斜体效果*
使用两个 * 号包裹文字,实现粗体的效果:
1**这是粗体效果**
使用两个 ~ 号包裹文字,实现删除的效果:
1~~这是删除效果~~~
使用连续三个短横线 - 实现添加分割线:
1---
Markdown 不支持文字更改颜色,如需支持,请使用 HTML 标签,例如红色:
1<font color="red">红色</font>
2.3 有序列表、无序列表
使用数字加+ . 加空格实现有序列表:
1231. 水果2. 蔬菜3. 肉类
使用短横线 ...