4月7
(一)事务传播机制 7种
Required (默认):
如果当前没有事务,就新建一个事务,如果已存在一个事务中
加入到这个事务中,这是最常见的选择。
Supports :
支持当前事务,如果没有当前事务,就以非事务方法执行。
Mandatory :
中文翻译为强制,支持使用当前事务,如果当前事务不存在,则抛出Exception。
Requies_new :
创建一个新事务,如果当前事务存在,把当前事务挂起。
Not_Supported :
无事务执行,如果当前事务存在,把当前事务挂起。
Never :
无事务执行,如果当前有事务则抛出Exception。
Nested :
嵌套事务,如果当前事务存在,那么在嵌套的事务中执行。
如果当前事务不存在,则表现跟REQUIRED一样。
注解配置时如:@Transactional(propagation=Propagation.REQUIRED)
7种事务举例子可看此篇博客 感觉不错: https://www.cnblogs.com/myseries/p/10800430.html
(二)事务隔离级别
事务隔离级别 脏读 不可重复读 幻读
读未提交(Read-Uncommitted) 是 是 是
不可重复读(Read-Committed) 否 是 是
可重复读(Repeatable-Read) 否 否 是
串行化(Serializable) 否 否 否
注解配置时如:@Transactional(isolation = Isolation.READ_UNCOMMITTED)
Mysql 默认 可重复读 ---repeatable-read
事务的并发问题
1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,
对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。
3、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,
但是系统管理员B就在这个时候插入了一条具体分数的记录,
当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。
解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表
Required (默认):
如果当前没有事务,就新建一个事务,如果已存在一个事务中
加入到这个事务中,这是最常见的选择。
Supports :
支持当前事务,如果没有当前事务,就以非事务方法执行。
Mandatory :
中文翻译为强制,支持使用当前事务,如果当前事务不存在,则抛出Exception。
Requies_new :
创建一个新事务,如果当前事务存在,把当前事务挂起。
Not_Supported :
无事务执行,如果当前事务存在,把当前事务挂起。
Never :
无事务执行,如果当前有事务则抛出Exception。
Nested :
嵌套事务,如果当前事务存在,那么在嵌套的事务中执行。
如果当前事务不存在,则表现跟REQUIRED一样。
注解配置时如:@Transactional(propagation=Propagation.REQUIRED)
7种事务举例子可看此篇博客 感觉不错: https://www.cnblogs.com/myseries/p/10800430.html
(二)事务隔离级别
事务隔离级别 脏读 不可重复读 幻读
读未提交(Read-Uncommitted) 是 是 是
不可重复读(Read-Committed) 否 是 是
可重复读(Repeatable-Read) 否 否 是
串行化(Serializable) 否 否 否
注解配置时如:@Transactional(isolation = Isolation.READ_UNCOMMITTED)
Mysql 默认 可重复读 ---repeatable-read
事务的并发问题
1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,
对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。
3、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,
但是系统管理员B就在这个时候插入了一条具体分数的记录,
当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。
解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表
3月14
项目中的一些依赖由于需要手动添加,很多时候都会创建一个私服仓库,比如nexus,将第三方jar添加到私服中,然后在pom中引用。刚来公司接手一个3年前的一个项目,该项目之前下过依赖,这些依赖本地依旧存在,如今重新导入该项目,由于没了私服,于是删去私服地址后,执行mvn package后项目会重新到配置的仓库中找这些依赖下载。
此时会报错"was cached in the local repository..." 或者 " Could not resolve dependencies for project"
解决方法,找到该依赖本地资源库位置,删去_remote.repositories文件 和 xx.lastUpdated文件
此时会报错"was cached in the local repository..." 或者 " Could not resolve dependencies for project"
解决方法,找到该依赖本地资源库位置,删去_remote.repositories文件 和 xx.lastUpdated文件
1月6
使用场景,多个接口的某个或多个参数都是从登录态中获取的,如下的capCode,这里只设计修改入参。
@Order(1)
@Component
@Aspect
@Slf4j
public class CapCodeAspect {
@Autowired
private TokenService tokenService;
public CapCodeAspect() {
}
@Pointcut("@annotation(com.xx.oo.annotation.CapCode)")
private void parameterPointCut() {
}
@Around("parameterPointCut()")
public Object getCapCode(ProceedingJoinPoint joinPoint) {
try {
Object[] o = joinPoint.getArgs();
if (null != o) {
for (Object ob : o) {
changObjectValue(ob, "capCode", gatCapCode());
}
}
return joinPoint.proceed(o);
} catch (Throwable e) {
log.error("目标方法执行异常,目标类:" + joinPoint.getTarget() + "方法:" + joinPoint.getSignature().getName(), e);
throw new RuntimeException("系统繁忙,请稍后再试!");
}
}
/***
* 修改入参具体字段值
*/
private Object changObjectValue(Object obj, String filedName, Object afterValue) throws Exception {
Class<?> resultClz = obj.getClass();
//获取父类的字段,因为capCode放在在基类里面,这里就直接获取父类的Class了,
//参数只在当前类的可以添加当前类的逻辑
Field[] fieldInfo = resultClz.getSuperclass().getDeclaredFields();
for (Field field : fieldInfo) {
if (filedName.equals(field.getName())) {
field.setAccessible(true); //成员变量为private,故必须进行此操
Object fieldValue = field.get(obj);
field.set(obj, afterValue);
break;
}
}
return obj;
}
private String gatCapCode() {
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
SysUser user = loginUser.getUser();
String capCode = user.getProviderId();
log.info("资金编码:{}", capCode);
return capCode;
}
}
@Order(1)
@Component
@Aspect
@Slf4j
public class CapCodeAspect {
@Autowired
private TokenService tokenService;
public CapCodeAspect() {
}
@Pointcut("@annotation(com.xx.oo.annotation.CapCode)")
private void parameterPointCut() {
}
@Around("parameterPointCut()")
public Object getCapCode(ProceedingJoinPoint joinPoint) {
try {
Object[] o = joinPoint.getArgs();
if (null != o) {
for (Object ob : o) {
changObjectValue(ob, "capCode", gatCapCode());
}
}
return joinPoint.proceed(o);
} catch (Throwable e) {
log.error("目标方法执行异常,目标类:" + joinPoint.getTarget() + "方法:" + joinPoint.getSignature().getName(), e);
throw new RuntimeException("系统繁忙,请稍后再试!");
}
}
/***
* 修改入参具体字段值
*/
private Object changObjectValue(Object obj, String filedName, Object afterValue) throws Exception {
Class<?> resultClz = obj.getClass();
//获取父类的字段,因为capCode放在在基类里面,这里就直接获取父类的Class了,
//参数只在当前类的可以添加当前类的逻辑
Field[] fieldInfo = resultClz.getSuperclass().getDeclaredFields();
for (Field field : fieldInfo) {
if (filedName.equals(field.getName())) {
field.setAccessible(true); //成员变量为private,故必须进行此操
Object fieldValue = field.get(obj);
field.set(obj, afterValue);
break;
}
}
return obj;
}
private String gatCapCode() {
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
SysUser user = loginUser.getUser();
String capCode = user.getProviderId();
log.info("资金编码:{}", capCode);
return capCode;
}
}
10月20
remote: The project you were looking for could not be found.
在使用Git客户端克隆和pull远程仓库的时候报错:提示找不到上游仓库,但是地址是正确的!
问题原因解析:
因为自己的项目不止一个 又有自动保存git密码的功能,当clone第二个项目的时候和之前的git用户不是同一个就会报这个错误!
解决方案:
在自己的项目路径上加上自己的用户名,
例如:
Git clone http://10.1.100.1:0000/credit/code/heck.git (失败)
Git clone http://用户名@10.1.100.1:0000/credit/code/heck.git(成功)
或者clear掉之前拉的项目保存的用户名和密码认证的数据。
在使用Git客户端克隆和pull远程仓库的时候报错:提示找不到上游仓库,但是地址是正确的!
问题原因解析:
因为自己的项目不止一个 又有自动保存git密码的功能,当clone第二个项目的时候和之前的git用户不是同一个就会报这个错误!
解决方案:
在自己的项目路径上加上自己的用户名,
例如:
Git clone http://10.1.100.1:0000/credit/code/heck.git (失败)
Git clone http://用户名@10.1.100.1:0000/credit/code/heck.git(成功)
或者clear掉之前拉的项目保存的用户名和密码认证的数据。
10月8
mybatis 映射文件中,if标签判断字符串相等,两种方式:
因为mybatis映射文件,是使用的ognl表达式,所以在判断字符串sex变量是否是字符串Y的时候,
1.
<if test="signUpFlag=='Y'.toString()">
2.
<if test = 'signUpFlag== "Y"'>
注意:
不能使用
<if test="signUpFlag=='Y'">
and 1=1
</if>
因为mybatis会把'Y'解析为字符char类型,而不是String类型,不能做到判断的效果,java是强类型语言,所以不能这样写。
注意点:
mybatis中判断字符串为某一个值,必须+toString() 或者 flage=="xxx" (双引号),否则无法进入该判断
因为mybatis映射文件,是使用的ognl表达式,所以在判断字符串sex变量是否是字符串Y的时候,
1.
<if test="signUpFlag=='Y'.toString()">
2.
<if test = 'signUpFlag== "Y"'>
注意:
不能使用
<if test="signUpFlag=='Y'">
and 1=1
</if>
因为mybatis会把'Y'解析为字符char类型,而不是String类型,不能做到判断的效果,java是强类型语言,所以不能这样写。
注意点:
mybatis中判断字符串为某一个值,必须+toString() 或者 flage=="xxx" (双引号),否则无法进入该判断
9月24
解决方法
写入excel时使用 SXSSFWorkbook workbook = new SXSSFWorkbook(xssfWorkbook , 1000);只在内存中留1000行,不会占用过多的内存。下面只贴了部分代码。
public static void createExcelByTrade(List mergeCellConfigList , Map cellConfMap , List dataList ,String tempPath , String fileName ) {
try {
int excelRowNum = 0;
short fontSize = 12;
// 创建新的Excel 工作簿
XSSFWorkbook xssfWorkbook = new XSSFWorkbook();
SXSSFWorkbook workbook = new SXSSFWorkbook(xssfWorkbook , 1000);
Sheet sheet = workbook.createSheet(fileName);
// 设置合并表头
setMergeHeaderCellByTrade( workbook, sheet, mergeCellConfigList , excelRowNum, fontSize );
excelRowNum ++ ;
excelRowNum ++ ;
//设置表头
setHeaderCell( workbook, sheet, cellConfMap , excelRowNum, fontSize );
excelRowNum ++ ; //查询数据库中所有的数据
setCellData( workbook, sheet, cellConfMap, dataList, excelRowNum, fontSize);
// 新建一输出文件流
FileOutputStream fOut = new FileOutputStream(tempPath);
// 把相应的Excel 工作簿存盘
workbook.write(fOut);
//清空缓冲区数据
fOut.flush();
// 操作结束,关闭文件
fOut.close();
System.out.println("文件生成...");
} catch (Exception e) {
e.printStackTrace();
System.out.println("已运行 xlCreate() : " + e);
}
}
写入excel时使用 SXSSFWorkbook workbook = new SXSSFWorkbook(xssfWorkbook , 1000);只在内存中留1000行,不会占用过多的内存。下面只贴了部分代码。
public static void createExcelByTrade(List
try {
int excelRowNum = 0;
short fontSize = 12;
// 创建新的Excel 工作簿
XSSFWorkbook xssfWorkbook = new XSSFWorkbook();
SXSSFWorkbook workbook = new SXSSFWorkbook(xssfWorkbook , 1000);
Sheet sheet = workbook.createSheet(fileName);
// 设置合并表头
setMergeHeaderCellByTrade( workbook, sheet, mergeCellConfigList , excelRowNum, fontSize );
excelRowNum ++ ;
excelRowNum ++ ;
//设置表头
setHeaderCell( workbook, sheet, cellConfMap , excelRowNum, fontSize );
excelRowNum ++ ; //查询数据库中所有的数据
setCellData( workbook, sheet, cellConfMap, dataList, excelRowNum, fontSize);
// 新建一输出文件流
FileOutputStream fOut = new FileOutputStream(tempPath);
// 把相应的Excel 工作簿存盘
workbook.write(fOut);
//清空缓冲区数据
fOut.flush();
// 操作结束,关闭文件
fOut.close();
System.out.println("文件生成...");
} catch (Exception e) {
e.printStackTrace();
System.out.println("已运行 xlCreate() : " + e);
}
}
9月1
Word模板引擎,基于Microsoft Word模板和数据生成新的文档,并且支持用户自定义函数,函数可以在Word模板的任何位置执行。
poi-tl是一个完全的Java类库,你可以非常方便的加入到你的Java项目中,核心API只需要一行代码:
XWPFTemplate template = XWPFTemplate.compile("~/file.docx").render(datas);
所有的标签都是以 {{ 开始,以 }} 结束。
{{template}} 文本
{{@template}} 图片
{{#template}} 表格
{{*template}} 列表
{{+template}} Word文档合并
{{?template}}{{/template}} if和foreach功能
示例
从一个超级简单的例子开始:把{{title}}替换成"Poi-tl 模板引擎"。
新建文档template.docx,包含文本{{title}}
TDO模式:Template + data-model = output
//一行代码
XWPFTemplate template = XWPFTemplate.compile("~/template.docx").render(new HashMap(){{
put("title", "Poi-tl 模板引擎");
}});
template.writeToFile("out_template.docx");
操作手册:http://deepoove.com/poi-tl/
poi-tl是一个完全的Java类库,你可以非常方便的加入到你的Java项目中,核心API只需要一行代码:
XWPFTemplate template = XWPFTemplate.compile("~/file.docx").render(datas);
所有的标签都是以 {{ 开始,以 }} 结束。
{{template}} 文本
{{@template}} 图片
{{#template}} 表格
{{*template}} 列表
{{+template}} Word文档合并
{{?template}}{{/template}} if和foreach功能
示例
从一个超级简单的例子开始:把{{title}}替换成"Poi-tl 模板引擎"。
新建文档template.docx,包含文本{{title}}
TDO模式:Template + data-model = output
//一行代码
XWPFTemplate template = XWPFTemplate.compile("~/template.docx").render(new HashMap(){{
put("title", "Poi-tl 模板引擎");
}});
template.writeToFile("out_template.docx");
操作手册:http://deepoove.com/poi-tl/
8月19
最近公司的项目,配置nginx反向代理时遇到一个问题,当设置nginx监听80端口时转发请求没有问题。但一旦设置为监听其他端口,就一直跳转不正常;如访问欢迎页面时应该是重定向到登录页面,在这个重定向的过程中端口丢失了变默认变成80了,当然就访问不到了。
这里给出一个简短的解决方案,修改nginx的配置文件。
一、配置文件
server {
listen 42112;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host:$server_port; #这里是重点,这样配置才不会丢失端口
location / {
proxy_pass http://127.0.0.1:9001;
}
location = /50x.html {
root html;
}
}
二、产生原因
nginx没有正确的把端口信息传送到后端,没能正确的配置nginx,下面这行是关键
proxy_set_header Host $host:$server_port; 这一行是关键。
或者
proxy_set_header Host $http_host;
这里给出一个简短的解决方案,修改nginx的配置文件。
一、配置文件
server {
listen 42112;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host:$server_port; #这里是重点,这样配置才不会丢失端口
location / {
proxy_pass http://127.0.0.1:9001;
}
location = /50x.html {
root html;
}
}
二、产生原因
nginx没有正确的把端口信息传送到后端,没能正确的配置nginx,下面这行是关键
proxy_set_header Host $host:$server_port; 这一行是关键。
或者
proxy_set_header Host $http_host;
8月12
在使用idea的过程中,遇到其中一个maven模块变成灰色的故障如下所示:

点开查看项目结构发现,文件没有被正确识别。
解决方法:造成这个的原因可能是忽略了maven模块,可以尝试如下解决方法:在file->setting里,搜索maven,然后选择Ignored Filess,看右边的面板中变灰的maven模块是否处于勾选状态。勾选表示忽略了这个模块的pom文件。取消勾选即可解决。


取消勾选后依旧没有解决可以尝试点击,reimport重新加载依赖。
刚接触IntellijIDEA遇到的问题,我出现此问题的原因是因为以前创建过一个相同名字的模块,因为一些原因删掉了,重新创建同名模块的时候IntellijIDEA直接把我新模块的pom文件设置成了忽略状态。
点开查看项目结构发现,文件没有被正确识别。
解决方法:造成这个的原因可能是忽略了maven模块,可以尝试如下解决方法:在file->setting里,搜索maven,然后选择Ignored Filess,看右边的面板中变灰的maven模块是否处于勾选状态。勾选表示忽略了这个模块的pom文件。取消勾选即可解决。
取消勾选后依旧没有解决可以尝试点击,reimport重新加载依赖。
刚接触IntellijIDEA遇到的问题,我出现此问题的原因是因为以前创建过一个相同名字的模块,因为一些原因删掉了,重新创建同名模块的时候IntellijIDEA直接把我新模块的pom文件设置成了忽略状态。
8月6
今天有个同事说要我帮他看下怎么把这个定时任务的cron表达式放到配置文件里面去,
1、在类上加注解@Component,交给Spring管理
2、在@PropertySource指定配置文件名称,如下配置,指定放在src/main/resource目录下的application.yml文件
3、配置文件application.yml参考内容如下
application.yml
jobs:
customDictUpdateTime:
corn: "0/5 * * * * ?"
@Configuration
@Component
@Slf4j
@PropertySource(value = "classpath:application.yml")
public class QuartzTask {
@Autowired
private RedisUtil redisUtil;
private static boolean startTask = true;
@PostConstruct
public void startInit() {
excuteBusiness();
}
//定时任务初始化政务宝自定义词库
//如果获取不到, 取冒号后面的默认值
@Scheduled(cron = "${jobs.customDictUpdateTime.corn:0/5 * * * * ?}")
public void excuteTask() {
excuteBusiness();
}
}
上面说的是yml配置文件,有的同学就说了,那么我用的application.properties文件配置呢?
application.properties
jobs.customDictUpdateTime.corn=0/5 * * * *
import org.springframework.context.annotation.PropertySource;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Configuration
@Component
@Slf4j
@PropertySource(value = "classpath:application.properties")
public class QuartzTask {
@Autowired
private RedisUtil redisUtil;
private static boolean startTask = true;
@PostConstruct
public void startInit() {
excuteBusiness();
}
//定时任务初始化政务宝自定义词库
//如果获取不到, 取冒号后面的默认值
@Scheduled(cron = "${jobs.customDictUpdateTime.corn:0/5 * * * * ?}")
public void excuteTask() {
excuteBusiness();
}
}
1、在类上加注解@Component,交给Spring管理
2、在@PropertySource指定配置文件名称,如下配置,指定放在src/main/resource目录下的application.yml文件
3、配置文件application.yml参考内容如下
application.yml
jobs:
customDictUpdateTime:
corn: "0/5 * * * * ?"
@Configuration
@Component
@Slf4j
@PropertySource(value = "classpath:application.yml")
public class QuartzTask {
@Autowired
private RedisUtil redisUtil;
private static boolean startTask = true;
@PostConstruct
public void startInit() {
excuteBusiness();
}
//定时任务初始化政务宝自定义词库
//如果获取不到, 取冒号后面的默认值
@Scheduled(cron = "${jobs.customDictUpdateTime.corn:0/5 * * * * ?}")
public void excuteTask() {
excuteBusiness();
}
}
上面说的是yml配置文件,有的同学就说了,那么我用的application.properties文件配置呢?
application.properties
jobs.customDictUpdateTime.corn=0/5 * * * *
import org.springframework.context.annotation.PropertySource;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Configuration
@Component
@Slf4j
@PropertySource(value = "classpath:application.properties")
public class QuartzTask {
@Autowired
private RedisUtil redisUtil;
private static boolean startTask = true;
@PostConstruct
public void startInit() {
excuteBusiness();
}
//定时任务初始化政务宝自定义词库
//如果获取不到, 取冒号后面的默认值
@Scheduled(cron = "${jobs.customDictUpdateTime.corn:0/5 * * * * ?}")
public void excuteTask() {
excuteBusiness();
}
}







