月度记录-7月

91 阅读9分钟

每月都会把遇到的一些坑记录下来,一方面是写一次加深自己的印象,以后遇到也能尽快检索到,另一方面就是分享。

1. windows系统把项目放到Tomcat,然后注册成服务

进入bin目录,cmd打开dos窗口。输入service install 服务名,即可将项目注册成windows服务。

注册成服务之后再设置为自动启动,可以实现开机就启动项目。

2. windows删除服务

1)关闭服务 2)sc delete 服务名

3. tomcat最重要的三个端口都有什么作用?

shutdown:关闭tomcat的监听接口

:http走8080;https走8443

AJP/1.3 这个用于支持AJP协议(注掉也没事)以后用到在学(这个东西比较冷门,估计这辈子也用不到)

4. 复制tomcat

复制一个tomcat文件出来,打开webapp,删除原来的项目文件,将新的放进去。

修改conf的service配置文件service.xml,改三个端口,分别是shutdown、HTTP1.1、AJP1.3(可有可无)

5. executor="tomcatThreadPool",指定使用共享线程池

tomcat中每个用户请求,都是一个线程。web容器一般都有线程池的实现,这样当用户请求过来的时候就不需要再去临时创建线程。容器会分配线程池中的线程,提高访问速度。

todo:学习tomcat线程池

6. mybatis返回值 Map和Map

value返回String,如果返回值都是char,那就相安无事。否则取值会出问题

根本原因是:java里的泛型是类型擦除,虚拟机并不认识泛型,是编译器实现的,java泛型只在程序源码中存在,在编译后的字节码文件中,全部都被替换成原来的裸类型(详见深入理解JAVA虚拟机-泛型)

7. SimpleDateFormat线程不安全,DateTimeFormatter不但是不变对象,它还是线程安全的。

SimpleDateFormat不是线程安全的,使用的时候,只能在方法内部创建新的局部变量。而DateTimeFormatter可以只创建一个实例,到处引用。

原因:在多线程环境下,当多个线程同时使用相同的SimpleDateFormat对象,如果调用format方法,多个线程会同时调用calender.setTime()方法。time可能会被别的线程修改,所以线程不安全。

final DateTimeFormatter formatter = new DateTimeFormatterBuilder()
        .appendPattern("yyyy-MM-dd")
        .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
        .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
        .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
        .parseDefaulting(ChronoField.MILLI_OF_SECOND, 0)
        .toFormatter();
LocalDateTime localDateTime = LocalDateTime.parse("2018-12-11", formatter);

8. idea断开和svn的连接,然后换个目录重新上传

1) idea下载插件:SVN Disconnect

2) VCS->SVN Disconnect

3) 打开settings -》 version control,点击加号选择要上传的项目,选择完毕项目就会变色

4) 整个项目文件,右键选择subversion,选中share directory。然后选择要上传到的svn文件夹,点确定

5) share完成之后,项目变色了。这个时候提交一下要上传的文件就行,和开发中上传一样

上面的方法太慢了。。。用idea做这个事儿不行,有两种办法:1.myeclipse 2.小乌龟

9. Java多文件上传,postman怎么发?

后端接收:MultipartFile[] files

postman:body - form-data key写一样的,value选择文件类型,发出去就是文件数组了

10. mysql my.ini ,windows其实只显示my

my.ini怎么也搜不到,急死个人

11. mysql my.ini ,注意编码格式ANSI

在windows服务器,用记事本修改了my.ini文件,可是怎么也启动不了mysql。最后发现竟然是配置文件的锅,果断下载notepad++

12. 导入sql出现MYSQl server has gone away这个错误,原因可能是base64图片数据太大导致,设置max_allowed_packet即可

这个据说可以通过配置文件设置,然后重启mysql完成修改,但是我没成功

最后通过命令行set global max_allowed_packet=1024*1024*16,解决sql执行失败的问题。如果还报错,就设置的更大点

13. 容易忽略的小问题:集合即使是isNotEmpty,里面也可能有null,对拿出的元素别忘了判空

14. 一个windows自带的功能:windows任务,可以定时执行一些任务,或者说开机启动一些程序(比如idea开机自启)

15. java包装类,不要用 == 比较大小,应该用equals(虽然很简单,但是工作中确实看到有人犯这个错误,写下来自己警戒下)

整型、char类型所对应的包装类,在自动装箱时,对于-128~127之间的值会进行缓存处理。当然其目的就是提高效率。

缓存处理的原理为:如果数据在-128~127这个区间,那么在类加载时就已经为该区间的每个数值创建了对象,并将这256个对象存放到一个名为cache的数组中。每当自动装箱过程发生时(或者手动调用valueOf()时),就会先判断数据是否在该区间,如果在则直接获取数组中对应的包装类对象的引用,如果不在该区间,则会通过new调用包装类的构造方法来创建对象。

此处以Integer类为例,源码参考:

public static Integer valueOf(int i) {  
if (i >= IntegerCache.low && i <= IntegerCache.high)   
 return IntegerCache.cache[i + (-IntegerCache.low)]; 
 return new Integer(i);  
 // 超过范围就是newInteger对象
}

==,比较地址值

16. redis dump.rdb

默认情况下 每隔一段时间redis服务器程序会自动对数据库做一次遍历,把内存快照写在一个叫做“dump.rdb”的文件里,这个持久化机制叫做SNAPSHOT。有了SNAPSHOT后,重新启动redis服务器程序时redis会自动加载dump.rdb,将数据库状态恢复到上一次做SNAPSHOT时的状态。

17. 往数据库存图片是真下水道

永远不要采用这种方式保存用户附件,数据迁移就是天坑,数据量稍微大点,半天都执行不完sql

再说,大文件保存在数据库,一旦加载到缓存,会把很多原来在缓存里的数据挤出去,导致缓存命中率降低,性能肯定拉跨

18. 将redis注册为服务(总是忘记,只好记录一下)

进入到redis安装目录下:执行:

redis-server.exe --service-install redis.windows.conf --service-name redis_6380 --port 6380

19. Multiparthttpservletrequest

文件上传可以用这个,能设置参数

20. ConCurrentHashMap.newKeySet

HashSet 是从hashmap实现的,所以线程不安全。上面的方法可以获取线程安全的Set

21. mybatis批量更新,&allowMultiQueries=true打开,separator=“;”,一定记得要用分号

22. Runtime.getRuntime().availableProcessors()

返回的是可用的计算资源,而不是CPU物理核心数

多线程情况下:cpu密集型任务,推荐设置为N,和可用计算资源保持一致,尽量减少cpu上下文切换

io密集型推荐设置为可用计算资源2N

23. Mysql使用本地IP无法连接,使用localhost或127.0.0.1可以正常连接

Mysql默认不会开启本地IP连接的权限,需要手动开启

关键的不是记住多少东西,而是要掌握解决问题的方法。遇到这个问题,一开始无谓的改密码,重建数据库,都没能如愿,因为懒得思考.....,后来还是仔细思考了一下解决了。

24. 多层循环的时候,尽量外层循环小,内层循环大

因为cpu有分支预测功能,我们要尽量让CPU少预测错误几次

比方循环a,循环100次;b,循环10000次

a放外面,预测错100次。b放外面,会预测错10000次(真实情况可能不是这样,没学过硬件,先按照这样理解),差距越大,内外差越明显。

25. 2022-08-0900:00:00

这种日和时不带空格,会出bug。他可以parse但是日期是错的,如果不注意很可能会出bug。(项目中遇到这个问题是因为工具类有问题,一个用trim,另一个竟然用replace去空格,不知道哪个人才写的,导致一个正常有空格,另一个没有,坑死我辣!)

26. replace和replaceAll都是替换所有。

  1. replace的参数是字符或字符串,可以支持字符的替换,也支持字符串的替换;
  2. replaceAll的参数是正则表达式,即基于规则表达式的替换;

若是replaceAll()所用的参数据不是正则表达式,则与replace()替换字符串的效果是同样的

replaceFirst(),这个⽅法也是基于正则表达式的替换,但与replaceAll()不同的是,只替换第⼀次出现的字符串

27. WARN!不要在finally块中使用return

try块中return执行成果之后,并不马上返回,而是等到finally块语句执行完毕,如果此处存在return语句,就会丢弃try中的返回。

28. MySQL表可以选择不同的存储引擎,而不是一个库只能用一种

以前一直以为存储引擎是和库绑定的,今天忽然发现是和表绑定的,误解了两年。

另外这也牵出了一个知识点:Mysql服务层部不管理事务,事务是由下层的存储引擎实现的。所以在同一个事务中使用多种存储引擎是不可靠的。如果在事务中混用了事务和非事务的表,一旦需要回滚,非事务型的表就会变得无法撤销。

更致命的是,在非事务的表上执行事务相关操作时,MySQL通常不会提醒也不报错。只有在回滚的时候才会给个警报:某些非事务型的表上的变更不能回滚。

29. leftjoin where和and

on后加and,都作为on条件。

on后用where,where是筛选条件。(有次sql写迷糊了就用错了,导致结果不对)

30. try can use automic resource management

从 Java 7 build 105版本开始,Java 7的编译器和运行环境支持新的try-with-resources语句,称为ARM 块(Automatic Resource Management) ,自动资源管理。新的语句支持包括流以及任何可关闭的资源。

数据流会在try执行完毕之后自动关闭,前提是可关闭的资源必须实现java.lang.AutoCloseable接口。

try(资源) { }

31. String.ValueOf(null),会得到“null”,小心。

return (obj == null) ? "null" : obj.toString();

32. HashedMap,虽然写错了但是歪打正着,真有这个方法!

33. 注意:使用BigDecimal来计算时需要将它计算出的结果进行保存,若不进行操作,则原始值还是不变的。

平时用的比较少,每次用都要看文档~