java中的总结
1、GC垃圾回收
1、GC是负责回收所有无任何引用对象的内存空间。 注意:垃圾回收回收的是无任何引用的对象占据的内存空间而不是对象本身
2、GC回收机制的两种算法,a、引用计数法 b、可达性分析算法
2、HashMap的存储原理
HashMap是由数组+链表的一个结构组成;
3、事务
Spring可以使用编程式实现事务,声明式实现事务以及注解式实现事务;
注解实现事务@Transanctional:
该注解只能放在public方法上,且该方法里不能捕获异常,只能抛出异常;
4、多线程
如果一个任务可能会耗时,为了不影响走后边的流程,则需要将该任务放在新开的线程里(下边是jdk8的新建线程的语法)
new Thread(()->{
if(StringUtils.isBlank(sendValue)){
System.out.println("调用发短信接口去发送短信;用户下单失败,请马上处理;");
//此时调用发短信接口去发送短信,略过
/**
* 在Redis里放入数据,防止一直不停的发短信
* 间隔时间20秒(正常比这个数据久,这里为了测试先设置20秒)
*/
redisTemplate.opsForValue().set(saveOrderKey,"save-order-fail",20, TimeUnit.SECONDS);
}else{
System.out.println("已经发生过短信了,20秒内不要发了");
}
}).start();
5、反射
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;
这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
通俗地说,反射机制就是可以把一个类,类的成员(函数,属性),当成一个对象来操作,也就是说,类,类的成员,我们在运行的时候还可以动态地去操作他们.
java的反射机制就是增加程序的灵活性,避免将程序写死到代码里,例如:实例化一个person()对象,不使用反射,new person();如果想变成实例化其他类,那么必须修改源代码,并重新编译。使用反射:class.forName("person").newInstance();而且这个类描述可以写到配置文件中,如**.xml,这样如果想实例化其他类,只要修改配置文件的"类描述"就可以了,不需要重新修改代码并编译。
反射缺点
1、反射包括了一些动态类型,所以JVM无法对这些代码进行优化。因此,反射操作的效率要比那些非反射操作低得多。我们应该避免在经常被执行的代码或对性能要求很高的程序中使用反射。
2、由于反射允许代码执行一些在正常情况下不被允许的操作(比如访问私有的属性和方法),所以使用反射可能会导致意料之外的副作用;
6、AOP面向切面编程
面向切面编程:是指在程序运行期间将某段代码,动态的切入到某个类的指定方法的指定位置的这种编程思想叫做面向切面编程
实现AOP的程序:https://blog.csdn.net/liangshilin/article/details/81408916
优点:
1、每个事物逻辑位于一个位置,代码不分散,便于维护和升级;
2、业务模块更简洁,只包含核心业务代码;
7、IOC
Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。
在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。
传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对象的创建;
谁控制谁?当然是IoC 容器控制了对象;
控制什么?那就是主要控制了外部资源获取(不只是对象,还有文件等)。
8、tomcat部署web项目内存溢出
首先打开tomcat目录下bin目录里的catalina.bat文件,在最上边添加如下内容:
set CATALINA_OPTS=-Xmx300M -Xms256M
然后在在 echo Using CATALINA_BASE: “%CATALINA_BASE%” 前加入如下代码:
set JAVA_OPTS=-Xms64m -Xmx256m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m
idea设置tomcat内存:
-server
-XX:PermSize=512M
-XX:MaxPermSize=1024m
9、token
seesion简介:
浏览器第一次访问服务器,服务器会创建一个session,然后同时为该session生成一个唯一的会话的key,也就是sessionid,然后,将sessionid及对应的session分别作为key和value保存到缓存中,也可以持久化到数据库中,然后服务器再把sessionid,以cookie的形式发送给客户端。这样浏览器下次再访问时,会直接带着cookie中的sessionid。然后服务器根据sessionid找到对应的session进行匹配;
还有一种是浏览器禁用了cookie或不支持cookie,这种情况可以通过URL重写的方式发到服务器;
简单来讲,用户访问的时候说他自己是李四,他骗你怎么办? 那就当他第一次访问时在服务器端保存李四的信息,给他一个sessionid,让他下次访问时带上sessionid值,然后进行判断即可。
为什么出现了token:
首先,session的存储是需要空间的;其次,session的传递一般都是通过cookie来传递的,或者url重写的方式;而token在服务器是可以不需要存储用户的信息的,且token的传递方式也不限于cookie传递,当然,token也是可以保存起来的;
token的生成方式:
浏览器第一次访问服务器,根据传过来的唯一标识userId,服务端会通过一些算法(如常用的HMAC-SHA256算法),
然后加一个密钥,生成一个token,然后通过BASE64编码一下之后将这个token发送给客户端;
客户端将token保存起来,下次请求时,带着token,服务器收到请求后,然后会用相同的算法和密钥去验证token,如果通过,执行业务操作,不通过,返回不通过信息;
token和session的区别:
token和session其实都是为了身份验证,session一般翻译为会话,而token更多的时候是翻译为令牌;
session服务器会保存一份,可能保存到缓存,文件,数据库;token是可以不保存的;
同样,session和token都是有过期时间一说,都需要去管理过期时间;
虽然确实都是“客户端记录,每次访问携带”,但 token 很容易设计为自包含的,也就是说,
后端不需要记录什么东西,每次一个无状态请求,每次解密验证,每次当场得出合法 /非法的结论。这一切判断依据,
除了固化在 CS 两端的一些逻辑之外,整个信息是自包含的。这才是真正的无状态。
而 sessionid ,一般都是一段随机字符串,需要到后端去检索 id 的有效性。万一服务器重启导致内存里的 session 没了呢?万一 redis 服务器挂了呢?
10、Rest接口与RestFul风格:
简介:
在设计web接口的时候,REST主要是用于定义接口名,接口名一般是用名词写,不用动词,那怎么
表达“获取”或者“删除”或者“更新”这样的操作呢——用请求类型来区分。
比如,我们有一个friends接口,对于“朋友”我们有增删改查四种操作,怎么定义REST接口?
增加一个朋友,uri: generalcode.cn/va/friends 接口类型:POST
删除一个朋友,uri: generalcode.cn/va/friends 接口类型:DELETE
修改一个朋友,uri: generalcode.cn/va/friends 接口类型:PUT
查找朋友, uri: generalcode.cn/va/friends 接口类型:GET
举个反例:generalcode.cn/va/deleteFriends 该接口用来表示删除朋友,这就是不符
合REST协议的接口。
符合下边5条约束的系统就可以说是restFul风格的系统:
1、使用客户/服务器模型。客户和服务器之间通过一个统一的接口来互相通讯。
2、层次化的系统。在一个REST系统中,客户端并不会固定地与一个服务器打交道。
3、无状态。在一个REST系统中,服务端并不会保存有关客户的任何状态。也就是说,客户端自身负责用户状态的维持,并在每次发送请求时都需要提供足够的信息。
4、可缓存。REST系统需要能够恰当地缓存请求,以尽量减少服务端和客户端之间的信息传输,以提高性能。
5、统一的接口。一个REST系统需要使用一个统一的接口来完成子系统之间以及服务与用户之间的交互。这使得REST系统中的各个子系统可以独自完成演化。
11、JVM总结
JVM介绍
JVM初始分配的堆内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的堆内存由-Xmx指定,默认是物理内存的1/4。默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;
空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。因此服务器一般设置-Xms、-Xmx 相等以避免在每次GC 后调整堆的大小。
说明:如果-Xmx 不指定或者指定偏小,应用可能会导致java.lang.OutOfMemory错误,此错误来自JVM,不是Throwable的,无法用try...catch捕捉。
设置JVM
set JAVA_OPTS=-Xms512m -Xmx1024m -XX:PermSize=1024M -XX:MaxNewSize=2048m -XX:MaxPermSize=2048m
12、模拟当前线程睡眠
//TimeUnit包:import java.util.concurrent.TimeUnit;
TimeUnit.SECONDS.sleep(10);
13、String.format拼接字符串
//拼接地址,instance.getHost()放在第一个%s上,instance.getPort()放在第二个%s上
String url=String.format("http://%s:%s/api/v1/product/find?id="+product_id,instance.getHost(),instance.getPort());
14、for循环括号里不要写list.letgth
将list.letgth这个值提前拿出去,写在for循环里会每次查数据库,影响效率;
15、处理Double数据
①、四舍五入,且保留两位小数
double d = 987.125;
String.format("%.2f", d);
②、直接去掉后边的小数,保留两位小数,不进行四舍五入
double d = 123.125;
DecimalFormat df = new DecimalFormat("#.00");
String str = df.format(d);
System.out.println(str);
③、 BigDecimal.ROUND_HALF_UP表示四舍五入,BigDecimal.ROUND_HALF_DOWN也是五舍六入,BigDecimal.ROUND_UP表示进位处理(就是直接加1),BigDecimal.ROUND_DOWN表示直接去掉尾数:
double d = 131.125;
BigDecimal b = new BigDecimal(d);
d = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
System.out.println(d);
16、List转Page
int start = (int)page.getOffset();
// 当前页最后一条数据在List中的位置
int end = (start + page.getPageSize()) > itemAdditions.size() ? itemAdditions.size() : ( start + page.getPageSize());
// 配置分页数据
Page<ItemAddition> lastPage = new PageImpl<ItemAddition>(itemAdditions.subList(start, end), page, itemAdditions.size());
数据库总结
1、当数据表中A、B字段做了组合索引,那么单独使用A或单独使用B会有索引效果吗?(使用like查询如何有索引效果)
看A、B两字段做组合索引的时候,谁在前面,谁在后面,如果A在前,那么单独使用A会有索引效果,单独使用B则没有,反之亦然。
同理,使用like模糊查询时,如果只是使用前面%,那么有索引效果,如果使用双%号匹配,那么则无索引效果