1.1Java基础
1.集合有哪些?数据结构?初始长度?扩容机制?哪些是线程安全的? hashmap的底层原理?
集合类型主要有3种:set(集)、list(列表)和map(映射)。
1、List(有序、可重复)
List里存放的对象是有序的,同时也是可以重复的,List关注的是索引,拥有一系列和索引相关的方法,查询速度快。因为往list集合里插入或删除数据时,会伴随着后面数据的移动,所有插入删除数据速度慢。
2、Set(无序、不能重复)
Set里存放的对象是无序,不能重复的,集合中的对象不按特定的方式排序,只是简单地把对象加入集合中。
3、Map(键值对、键唯一、值不唯一)
Map集合中存储的是键值对,键不能重复,值可以重复。根据键得到值,对map集合遍历时先得到键的set集合,对set集合进行遍历,得到相应的值。
Set接口数据结构
哈希表存储结构
List
有序可重复
ArrayList
ArrayList数据结构是数组。查询快,增删慢。ArrayList是线程不安全的,允许元素为null 。
Vector
线程安全的数组,效率较差,已经过时不用。
LinkedList
LinkedList 数据结构是双向链表,插入删除比较方便。LinkedList 是线程不安全的,允许元素为null 。
Map
Map遍历
map遍历的方式有4种,分别是:1、使用for循环遍历map;2、使用迭代遍历map;3、使用keySet迭代遍历map;4、使用entrySet遍历map
HashMap :
jdk1.8中HashMap底层是哈希表数据结构,数组+链表+红黑树,HashMap是线程不安全的,允许使用null键和null值,
HashMap根据键的HashCode值存储数据,具有很快的访问速度。
HashMap存入的键值对在遍历时的顺序是随机的。
HashMap不支持并发
HashTable:
线程安全,使用synchronized锁住全部数据,效率较低。
LinkedHashMap:
LinkedHashMap 是HashMap的一个子类,默认LinkedHashMap遍历时输出的顺序和put输入的顺序是相同的。
LinkedHashMap有两种排序方式:插入排序和访问排序(修改或访问一个元素后,将该元素移到队列末尾),默认是插入排序。使用accessOrder来标记使用哪种排序方式,accessOrder==true时,表示使用访问排序,默认为false;
LinkedHashMap使用了双向链表来保证了顺序性。
TreeMap:
TreeMap底层是红黑树数据结构,线程不安全,可以用于给Map集合中的键进行排序
TreeMap遍历出来的是排序后的键值对。
ConcurrentHashMap
ConcurrentHashMap是线程安全的,jdk1.8使用CAS和volatile实现。而jdk1.8以前通过锁分段技术、可重入锁实现。
支持并发,可以一边更新一边遍历
初始长度 扩容机制
默认初始容量 加载因子 一次扩容后的容量
Arraylist 10 1.5n+1
Vector 10 1 2n
HashSet 16 0.75 2n
HashMap 16 0.75 2n
线程安全和线程不安全的集合
Vector、HashTable、Properties是线程安全的;
ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap等都是线程不安全的。
值得注意的是:为了保证集合是线程安全的,相应的效率也比较低;线程不安全的集合效率相对会高一些。
HashMap 的实现原理?
HashMap的put()和get()的实现
map.put:
1.调用hashcode方法得出hash值 2.通过哈希算法转化成下标 3.下标位置上如果没有任何元素,就把Node添加到这个位置上 4.如果对应位置有链表 用key和链表上的key进行equals 5.如果map.put返回值都为false则添加到末尾 如果有为true的 覆盖value
map.get:
哈希冲突的产生原因
哈希是通过对数据进行再压缩,提高效率的一种解决方法。但由于通过哈希函数产生的哈希值是有限的,而数据可能比较多,导致经过哈希函数处理后仍然有不同的数据对应相同的值。这时候就产生了哈希冲突。
产生哈希冲突的影响因素
装填因子(装填因子=数据总数 / 哈希表长)、哈希函数、处理冲突的方法
解决哈希冲突的四种方法
1.开放地址方法
(1)线性探测
按顺序决定值时,如果某数据的值已经存在,则在原来值的基础上往后加一个单位,直至不发生哈希冲突。
(2)再平方探测
按顺序决定值时,如果某数据的值已经存在,则在原来值的基础上先加1的平方个单位,若仍然存在则减1的平方个单位。随之是2的平方,3的平方等等。直至不发生哈希冲突。
(3)伪随机探测
按顺序决定值时,如果某数据已经存在,通过随机函数随机生成一个数,在原来值的基础上加上随机数,直至不发生哈希冲突。
2.链式地址法(HashMap的哈希冲突解决方法)
对于相同的值,使用链表进行连接。使用数组存储每一个链表。
优点:
(1)拉链法处理冲突简单,且无堆积现象,即非同义词决不会发生冲突,因此平均查找长度较短;
(2)由于拉链法中各链表上的结点空间是动态申请的,故它更适合于造表前无法确定表长的情况;
(3)开放定址法为减少冲突,要求装填因子α较小,故当结点规模较大时会浪费很多空间。而拉链法中可取α≥1,且结点较大时,拉链法中增加的指针域可忽略不计,因此节省空间;
(4)在用拉链法构造的散列表中,删除结点的操作易于实现。只要简单地删去链表上相应的结点即可。
缺点:
指针占用较大空间时,会造成空间浪费,若空间用于增大散列表规模进而提高开放地址法的效率。
3.建立公共溢出区
建立公共溢出区存储所有哈希冲突的数据。
4.再哈希法
对于冲突的哈希值再次进行哈希处理,直至没有哈希冲突。
2.jvm内存模型的理解?
JVM 内存共分为虚拟机栈,堆,方法区,程序计数器,本地方法栈五个部分。
(1)程序计数器(Program Counter Register):当前线程所执行的字节码的行号指示器,字节码解析器的工作是通过改变这个计数器的值,来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能,都需要依赖这个计数器来完成;
(2)Java 虚拟机栈(Java Virtual Machine Stacks):用于存储局部变量表、操作数栈、动态链接、方法出口等信息;
(3)本地方法栈(Native Method Stack):与虚拟机栈的作用是一样的,只不过虚拟机栈是服务 Java 方法的,而本地方法栈是为虚拟机调用 Native 方法服务的;
(4)Java 堆(Java Heap):Java 虚拟机中内存最大的一块,是被所有线程共享的,几乎所有的对象实例都在这里分配内存;
(5)方法区(Methed Area):用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。
3.jvm垃圾回收机制和jvm调优?
将堆和方法区按照对象不同年龄进行分代:
新生代:
1. 所有新对象创建发生在Eden区,Eden区满后触发新生代上的minor GC,将Eden区和非空闲Survivor区存活对象复制到另一个空闲的Survivor区中。
2. 永远保证一个Survivor是空的,新生代minor GC就是在两个Survivor区之间相互复制存活对象,直到Survivor区满为止。
旧生代:
1. Eden区满后触发minor GC将存活对象复制到Survivor区,Survivor区满后触发minor GC将存活对象复制到旧生代。
2. 经过新生代的两个Survivor之间多次复制,仍然存活下来的对象就是年龄相对比较老的,就可以放入到旧生代了,随着时间推移,如果旧生代也满了,将触发Full GC,针对整个堆(包括新生代、旧生代和持久代)进行垃圾回收。
要执行gc关键在于两点,一是检测出垃圾对象,二是释放垃圾对象所占用的空间。
检测出垃圾对象一般有两种算法:
为每一个创建的对象分配一个引用计数器,用来存储该对象被引用的个数。当该个数为零,意味着没有人再使用这个对象,可以认为“对象死亡”。但是,这种方案存在严重的问题,就是无法检测“循环引用”:当两个对象互相引用,即时它俩都不被外界任何东西引用,它俩的计数都不为零,因此永远不会被回收。而实际上对于开发者而言,这两个对象已经完全没有用处了。
因此,Java 里没有采用这样的方案来判定对象的“存活性”。
2、 可达性分析
基本思路是把所有引用的对象想象成一棵树,从树的根结点 GC Roots 出发,持续遍历找出所有连接的树枝对象,这些对象则被称为“可达”对象,或称“存活”对象。其余的对象则被视为“死亡”的“不可达”对象,或称“垃圾”。
1、垃圾回收算法
复制(Copying)
标记-清除(Mark-Sweep)
标记-整理(Mark-Compact)
减少minor gc的频率、以及full gc的次数
2.2 性能调优的手段
1.使用JDK提供的内存查看工具,如JConsole和Java VisualVM
2.控制堆内存各个部分所占的比例
3.采用合适的垃圾收集器
4.线程的创建? 开启?状态? sleep 和wait的区别?线程池?死锁?如何保证线程安全?
创建
1)继承Thread类创建线程
2)实现Runnable接口创建线程
3)使用Callable创建线程
相同点:
1、两者都是接口
2、两者都需要调用Thread.start启动线程
不同点:
1、如上面代码所示,callable的核心是call方法,允许返回值,runnable的核心是run方法,没有返回值
2、call方法可以抛出异常,但是run方法不行
3、因为runnable是java1.1就有了,所以他不存在返回值,后期在java1.5进行了优化,就出现了callable,就有了返回值和抛异常
4、callable和runnable都可以应用于executors。而thread类只支持runnable
开启
状态:创建、就绪、运行、阻塞和死亡。
共同点:
都是使线程暂停一段时间的方法。
不同点:
①原理不同-sleep()是属于Thread类中的,而wait()方法,则是属于Object类中的。
②锁处理机制不同-sleep()最主要作用使线程暂停执行一段时间,时间一到自动恢复,不涉及线程通讯,因此,调用sleep()方法并不会释放锁。而当调用wait()方法的时候,线程会释放它所占的锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。
③使用区域不同-wait()方法必须放在同步代码块或者同步方法中使用,sleep()可以用在任何地方
线程池
降低资源消耗。通过重复利用已创建的线程,降低线程创建和销毁造成的消耗。
提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
增加线程的可管理型。线程是稀缺资源,使用线程池可以进行统一分配,调优和监控。
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者进程在运行过程中,请求和释放资源的顺序不当而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
保证线程安全
1、使用线程安全的类;
2、使用synchronized同步代码块,或者用Lock锁;
1)Lock 是一个接口;synchronized 是 Java 中的关键字,synchronized 是内置的语言实现;
2)Lock 在发生异常时,如果没有主动通过 unLock() 去释放锁,很可能会造成死锁现象,因此使用 Lock 时需要在 finally 块中释放锁;synchronized 不需要手动获取锁和释放锁,在发生异常时,会自动释放锁,因此不会导致死锁现象发生;
3)Lock 的使用更加灵活,可以有响应中断、有超时时间等;而 synchronized 却不行,使用 synchronized 时,等待的线程会一直等待下去,直到获取到锁;
4)在性能上,随着近些年 synchronized 的不断优化,Lock 和 synchronized 在性能上已经没有很明显的差距了,所以性能不应该成为我们选择两者的主要原因。官方推荐尽量使用 synchronized,除非 synchronized 无法满足需求时,则可以使用 Lock。
3、多线程并发情况下,线程共享的变量改为方法局部级变量;
volatile关键字会触发lock前缀指令,进而触发缓存一致性协议以及想配套的锁,从而保障了线程可见。
synchronized 关键字底层原理
Synchronized进过编译,通过内部对象Monitor(监视器锁)实现,会在同步块的前后分别形成monitorenter和monitorexit这个两个字节码指令。在执行monitorenter指令时,首先要尝试获取对象锁。如果这个对象没被锁定,或者当前线程已经拥有了那个对象锁,把锁的计算器加1,相应的,在执行monitorexit指令时会将锁计算器就减1,当计算器为0时,锁就被释放了。如果获取对象锁失败,那当前线程就要阻塞,直到对象锁被另一个线程释放为止。
5. 重写与重载的区别?
重载:一个类中有多个同名的方法,但是具有有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)。
重写:发生在子类与父类之间,子类对父类的方法进行重写,参数都不能改变,返回值类型可以不相同,但是必须是父类返回值的派生类。
6.java中字符串的方法有哪些? string stringbuilder stringbuffer 的区别?
indexOf():返回指定字符的索引。
charAt():返回指定索引处的字符。
replace():字符串替换。
trim():去除字符串两端空白。
split():分割字符串,返回一个分割后的字符串数组。
getBytes():返回字符串的 byte 类型数组。
length():返回字符串长度。
toLowerCase():将字符串转成小写字母。
toUpperCase():将字符串转成大写字符。
substring():截取字符串。
equals():字符串比较。
String:String 的值被创建后不能修改,任何对 String 的修改都会引发新的 String 对象的生成。
StringBuffer:跟 String 类似,但是值可以被修改,使用 synchronized 来保证线程安全。
StringBuilder:StringBuffer 的非线程安全版本,没有使用 synchronized,具有更高的性能,推荐优先使用。
7. == 和equals的区别?
==:运算符,用于比较基础类型变量和引用类型变量。
对于基础类型变量,比较的变量保存的值是否相同,类型不一定要相同。
对于引用类型变量,比较的是两个对象的地址是否相同。
equals 在 Object 方法中其实等同于 ==,但是在实际的使用中,equals 通常被重写用于比较两个对象的值是否相同。
8. 对反射的理解?获取Class对象的方式有哪些?如何用反射取私有属性Filed?
反射是指在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法;并且对于任意一个对象,都能够调用它的任意一个方法;这种动态获取信息以及动态调用对象方法的功能称为反射机制。
1、new Object().getClass 2、Object.class 3、 Class.forName(“java.util.String”)
利用反射,首先是Class字节码对象的获取,
// 获得指定类的属性
Field field = clazz.getDeclaredField("name");
// 值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问检查。
field.setAccessible(true);取消 Java 语言访问检查
9.常用设计模式有哪些? 在项目中哪里有用到?单例中懒汉饿汉优缺点?
工厂设计模式 : Spring使用工厂模式通过 BeanFactory、ApplicationContext 创建 bean 对象。
代理设计模式 : Spring AOP 功能的实现。
单例设计模式 : Spring 中的 Bean 默认都是单例的。
1、时间和空间
懒汉式是典型的时间换空间,也就是每次获取实例都会进行判断,看是否需要创建实例,浪费判断的时间。
饿汉式是典型的空间换时间,当类装载的时候就会创建类实例,不管你用不用,先创建出来,然后每次调用的时候,就不需要再判断了,节省了运行时间。
2、线程安全
从线程安全性上讲,不加同步的懒汉式是线程不安全的,饿汉式是线程安全的,因为虚拟机保证只会装载一次,在装载类的时候是不会发生并发的。
代理模式
Java中实现代理模式主要有三种方式:
静态代理
动态代理
cglib代理
作用
1.Proxy类的代码量被固定下来,不会因为业务的逐渐庞大而庞大;
2.可以实现AOP编程,实际上静态代理也可以实现,总的来说,AOP可以算作是代理模式的一个典型应用;
3.解耦,通过参数就可以判断真实类,不需要事先实例化,更加灵活多变。
10. jdk1. 8的新特性有哪些?
Lambda表达式
函数式接口
*方法引用和构造器调用
Stream API
接口中的默认方法和静态方法
新时间日期API
11.泛型的理解?什么是类型擦除?
泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?
顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),
然后在使用/调用时传入具体的类型(类型实参)。
泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,
操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。
擦除是将泛型类型以其父类代替,如String 变成了Object等。其实在使用的时候还是进行带强制类型的转化,只不过这是比较安全的转换,因为在编译阶段已经确保了数据的一致性。
12. error和exception的区别?常见的异常及异常处理的方式有哪些?
Error类一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢等。
Exception类表示程序可以处理的异常,可以捕获且可能恢复。
ArrayIndexOutOfBoundsException 数组下标越界异常,
ArithmaticException 算数异常 如除数为零
NullPointerException 空指针异常
IllegalArgumentException 不合法参数异常
13. 类加载机制?代码块的执行顺序?
首先执行静态代码块,接着执行构造代码块,最后指向构造方法
14. cookie 和session的区别? session 的实现原理?session的生命周期? session 如何存储数据?
cookie保存在客户端,session保存在服务器端,
cookie目的可以跟踪会话,也可以保存用户喜好或者保存用户名密码
session用来跟踪会话
session 的实现原理
当用户访问到一个服务器,如果服务器启用Session,服务器就要为该用户创建一个SESSION,在创建这个SESSION的时候,服务器首先检查这个用户发来的请求里是否包含了一个SESSION ID,如果包含了一个SESSION ID则说明之前该用户已经登陆过并为此用户创建过SESSION,那服务器就按照这个SESSION ID把这个SESSION在服务器的内存中查找出来,如果客户端请求里不包含有SESSION ID,则为该客户端创建一个SESSION并生成一个与此SESSION相关的SESSION ID。
Session的生命周期
Session存储在服务器的内存中(为了高速存取)。
Session何时生效
Sessinon在用户访问第一次访问服务器时创建,需要注意只有访问JSP、Servlet等程序时才会创建Session,只访问HTML、IMAGE等静态资源并不会创建Session,可调用request.getSession(true)强制生成Session。
Session何时失效
服务器会把长时间没有活动的Session从服务器内存中清除,此时Session便失效。Tomcat中Session的默认失效时间为20分钟。
Session的存储方式
sessionid是一个会话的key,浏览器第一次访问服务器会在服务器端生成一个session,有一个sessionid和它对应。tomcat生成的sessionid叫做jsessionid。
session在访问tomcat服务器HttpServletRequest的getSession(true)的时候创建,tomcat的ManagerBase类提供创建sessionid的方法:随机数+时间+jvmid。
存储在服务器的内存中,tomcat的StandardManager类将session存储在内存中,也可以持久化到file,数据库,memcache,redis等。客户端只保存sessionid到cookie中,而不会保存session,session销毁只能通过invalidate或超时,关掉浏览器并不会关闭session。
Cookie和session的联系
Cookies是属于Session对象的一种。但有不同,Cookies不会占服务器资源,是存在客服端内存或者一个cookie的文本文件中;而“Session”则会占用服务器资源。
SessionId的保存方法
使用Cookie来保存
使用URL附加信息的方式
第三种方式是在页面表单里面增加隐藏域
15.java中锁的种类和基本原理?
乐观锁/悲观锁
乐观锁:顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。
悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改自己的数据,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。
独享锁/共享锁
独享锁是指该锁一次只能被一个线程所持有,Java ReentrantLock就是独享锁,Synchronized也是独享锁。
共享锁是指该锁可被多个线程所持有,Java ReadWriteLock其读锁是共享锁,其写锁是独享锁,读锁的共享锁可保证并发读是非常高效的,读写,写读,写写的过程是互斥的。
互斥锁/读写锁
互斥锁/读写锁是具体的实现。
互斥锁在Java中的具体实现就是ReentrantLock,读写锁在Java中的具体实现就是ReadWriteLock。
可重入锁
可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁,ReetrantLock和Synchronized都是可重入锁。
公平锁/非公平锁
公平锁是指多个线程按照申请锁的顺序来获取锁。
非公平锁是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁。
偏向锁/轻量级锁/重量级锁
偏向锁是指一段同步代码一直被一个线程所访问,那么该线程会自动获取锁,降低获取锁的代价。
轻量级锁是指当锁是偏向锁的时候,被另一个线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,提高性能。
重量级锁是指当锁为轻量级锁的时候,另一个线程虽然是自旋,但自旋不会一直持续下去,当自旋一定次数的时候,还没有获取到锁,就会进入阻塞,该锁膨胀为重量级,重量级锁会让他申请的线程进入阻塞,性能降低。
自旋锁
在Java中,自旋锁是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗CPU。
16. collection 和collections的区别?
1. java.util.Collection
java.util.Collection 是一个集合接口(集合类的一个顶级接口)。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式,其直接继承接口有List与Set。
Collection
├List
│├LinkedList
│├ArrayList
│└Vector
│ └Stack
└Set
常用方法
2. java.util.Collections
java.util.Collections 是一个包装类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等各种操作。
排序(Sort) 混排(Shuffling) 反转(Reverse) 替换所以的元素(Fill) 拷贝(Copy) 返回Collections中最小元素(min) 返回Collections中最大元素(max)
17.java如何跳出循环?
18.排序有哪些?原理是什么?
冒泡排序
重复访问要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。访问数列的工作是重复地进行直到没有再需要交换的数据,也就是说该数列已经排序完成。
快速排序
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
直接插入排序
将数组中的所有元素依次跟前面已经排好的元素相比较,如果选择的元素比已排序的元素小,则交换,直到全部元素都比较过为止。
选择排序
在未排序序列中找到最小(大)元素,存放到未排序序列的起始位置。
19.什么是堆栈?什么是内存溢出?有垃圾回收机制为什么还会出现内存溢出的情况?
堆栈就是只能在一端插入和删除数据的链表,这个端就叫做栈顶(top),最后一个添加的数据第一个被删除。因此,这也叫后进先出(LAST IN FIRST OUT)链表或是先进后出链表(FIRST IN LAST OUT)。
内存溢出(Out Of Memory,简称OOM)是指应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用到的内存大于能提供的最大内存。此时程序就运行不了,系统会提示内存溢出
有垃圾回收机制为什么还会出现内存溢出的情况?
内存资源是有限的,垃圾回收只回收垃圾,对于你的程序运行有用的对象不会被回收。
内存溢出分两种情况一种是栈溢出,比如调用了一个无限递归。还有一种是堆溢出,即new出来的对象没有即使销毁,比如一直new。
20. java的基本类型有哪些,int 占几个字节? byte占几个字节?
byte1、short2、int4、long8、float4、 double8、char2、boolean1
21. 枚举的了解?
枚举是列出某些有穷序列集的所有成员的程序,一个类里定义几个静态变量,每个变量都是这个类的实例。
22. final、finally、 finalize关键字的区别? volatile关键字的了解?
Final:修饰类:该类不能再派生出新的子类,不能作为父类被继承。因此,一个类不能同时被声明为abstract 和 final。
修饰方法:该方法不能被子类重写。
修饰变量:该变量必须在声明时给定初值,而在以后只能读取,不可修改。 如果变量是对象,则指的是引用不可修改,但是对象的属性还是可以修改的。
finally:finally 是对 Java 异常处理机制的最佳补充,通常配合 try、catch 使用,用于存放那些无论是否出现异常都一定会执行的代码。在实际使用中,通常用于释放锁、数据库连接等资源,把资源释放方法放到 finally 中,可以大大降低程序出错的几率。
finalize:Object 中的方法,在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。finalize()方法仅作为了解即可,在 Java 9 中该方法已经被标记为废弃,并添加新的 java.lang.ref.Cleaner,提供了更灵活和有效的方法来释放资源。这也侧面说明了,这个方法的设计是失败的,因此更加不能去使用它。
volatile通常被比喻成"轻量级的synchronized",也是Java并发编程中比较重要的一个关键字。和synchronized不同,volatile是一个变量修饰符,只能用来修饰变量,无法修饰方法及代码块等。
1.遍历集合for(String s:list)
2.判断遍历的对象中是否含有“王”if(s.indexOf(“王”)!=-1)
3.执行删除list.remove(s)
24. String a=“123”; String b=“123”;a+=b; 生成几个对象?
一个
25.如何序列化和反序列化?序列化的目的?
序列化是指将Java对象转换为字节序列的过程,而反序列化则是将字节序列转换为Java对象的过程。
实现序列化:实现Serializable、Externalizable接口
实现反序列化:用ObjectInputStream(对象输入流)类包含一个readObject()方法用来“反序列化”一个对象
目的:
1)Java序列化就是把对象转换成字节序列,而Java反序列化就是把字节序列还原成Java对象。
2)采用Java序列化与反序列化技术,一是可以实现数据的持久化;二是可以对象数据的远程通信
26. 什么是多态?多态的使用场景?
1.多态概述
多态是继封装、继承之后,面向对象的第三大特性。
多态现实意义理解:
现实事物经常会体现出多种形态,如学生,学生是人的一种,则一个具体的同学张三既是学生也是人,即出现两种形态。
Java作为面向对象的语言,同样可以描述一个事物的多种形态。如Student类继承了Person类,一个Student的对象便既是Student,又是Person。
3.多态体现为父类引用变量可以指向子类对象。
4.前提条件:必须有子父类关系。
注意:在使用多态后的父类引用变量调用方法时,会调用子类重写后的方法。
5.多态的定义与使用格式
定义格式:父类类型 变量名=new 子类类型();
6.理解:
多态是同一个行为具有多个不同表现形式或形态的能力。
多态就是同一个接口,使用不同的实例而执行不同操作。
1.2数据库
1.sql优化有哪些?
1、在表中建立索引,优先考虑where、group by使用到的字段(较频繁地作为查询条件且唯一性不太差),不会在where中用到的字段不建立索引,因为建立索引也需要系统的开销。
2、减少使用 * ,用列名代替
select * from user;
要写成 select userID, userName, userSalary from user;
因为在使用 * 的时候,数据库还得查询数据字典,进而解析得到列名,而直接写出列名效率会更高些。
3、避免在开头使用模糊查询(%),该查询数据库引擎会放弃索引进行全表扫描。
4、需要删除所有记录的时候,用truncate而不用detele
因为delete删除表的时候,会扫描整个表再一条一条删除;
而truncate会一次性删除整个表的所有内容,不进行扫描,效率高。
5、避免使用in和not in,会导致全表扫描
优化方式:如果是连续数值,用between代替;如果是子查询,用exists代替。
6、如果表名或列名过长,就使用别名,因为长的表名和列名也会消耗扫描时间。
2.索引的种类?如何创建索引?创建索引的原则是什么?索引的优缺点?索引什么情况下会失效?
什么是索引?
索引(Index)是帮助 MySQL 高效获取数据的数据结构。
索引的数据结构
B+tree
B Tree指的是平衡树,并且所有叶子节点位于同一层。
B+Tree是基于B Tree和叶子节点顺序访问指针进行实现,它具有B Tree 的平衡性,并且通过顺序访问指针来提高区间查询的性能。
与红黑树比较
红黑树等平衡树也可以用来实现索引,但是文件系统及数据库系统普遍采用B+Tree作为索引结构,因为:
1.查找次数更少
2.利用磁盘预读特性
普通索引、唯一索引、主键索引和聚集索引
建表时创建:
CREATE TABLE 表名(
字段名 数据类型 [完整性约束条件],
……,
[UNIQUE | FULLTEXT | SPATIAL] INDEX | KEY
[索引名](字段名1 [(长度)] [ASC | DESC]) [USING 索引方法]
);
建表后创建:
ALTER TABLE 表名 ADD [UNIQUE | FULLTEXT | SPATIAL] INDEX | KEY [索引名] (字段名1 [(长度)] [ASC | DESC]) [USING 索引方法];
或
CREATE [UNIQUE | FULLTEXT | SPATIAL] INDEX 索引名 ON 表名(字段名) [USING 索引方法];
在mysql中使用索引的原则有以下几点:
1、 对于查询频率高的字段创建索引;
2、 索引的数目不宜太多
3. 对于经常存取的列避免建立索引;
优点:
加快数据的查询速度
缺点:
创建索引会耗费时间和占用磁盘空间,并且随着数据量的增加所耗费的时间也会增加
索引失效的情况有:1、对列进行计算或者使用函数时;2、使用了反向操作或者link操作时;3、在where语句中使用or时,如果有一个列没索引,那么其他列就会失效。
如何判断索引是否失效
explan查看索引是否失效
3.内连接和外连接的区别及使用场景?
内连接:指连接结果仅包含符合连接条件的行,参与连接的两个表都应该符合连接条件。
外连接:连接结果不仅包含符合连接条件的行同时也包含自身不符合条件的行。包括左外连接、右外连接和全外连接。
左外连接:左边表数据行全部保留,右边表保留符合连接条件的行。
右外连接:右边表数据行全部保留,左边表保留符合连接条件的行。
4.如何查看sql的执行计划及查看执行计划的目的?
可以通过(explain+执行sql)查看sql的执行计划
目的
看看扫描了多少张表 每个表扫了多少数据 避免全表扫描 没建索引的建索引 索引失效的看sql写的问题
5.数据库中常用的函数有哪些?
一、字符串函数二、聚合函数三、数学函数四、日期和时间函数
6.oracle和mysql的区别?
分页
Mysql:limit oracle:rownum
一、并发性
并发性是oltp数据库最重要的特性,但并发涉及到资源的获取、共享与锁定。
mysql:
mysql以表级锁为主,对资源锁定的粒度很大,如果一个session对一个表加锁时间过长,会让其他session无法更新此表中的数据。
虽然InnoDB引擎的表可以用行级锁,但这个行级锁的机制依赖于表的索引,如果表没有索引,或者sql语句没有使用索引,那么仍然使用表级锁。
oracle:
oracle使用行级锁,对资源锁定的粒度要小很多,只是锁定sql需要的资源,并且加锁是在数据库中的数据行上,不依赖与索引。所以oracle对并发性的支持要好很多。
二、一致性
oracle:
oracle支持serializable的隔离级别,可以实现最高级别的读一致性。每个session提交后其他session才能看到提交的更改。oracle通过在undo表空间中构造多版本数据块来实现读一致性,
每个session查询时,如果对应的数据块发生变化,oracle会在undo表空间中为这个session构造它查询时的旧的数据块。
mysql:
mysql没有类似oracle的构造多版本数据块的机制,只支持read commited的隔离级别。一个session读取数据时,其他session不能更改数据,但可以在表最后插入数据。
session更新数据时,要加上排它锁,其他session无法访问数据。
三、事务
oracle很早就完全支持事务。
mysql在innodb存储引擎的行级锁的情况下才支持事务。
四、数据持久性
oracle
保证提交的数据均可恢复,因为oracle把提交的sql操作线写入了在线联机日志文件中,保持到了磁盘上,
如果出现数据库或主机异常重启,重启后oracle可以考联机在线日志恢复客户提交的数据。
mysql:
默认提交sql语句,但如果更新过程中出现db或主机重启的问题,也许会丢失数据。
五、提交方式
oracle默认不自动提交,需要用户手动提交。
mysql默认是自动提交。
六、逻辑备份
oracle逻辑备份时不锁定数据,且备份的数据是一致的。
mysql逻辑备份时要锁定数据,才能保证备份的数据是一致的,影响业务正常的dml使用。
七、热备份
oracle有成熟的热备工具rman,热备时,不影响用户使用数据库。即使备份的数据库不一致,也可以在恢复时通过归档日志和联机重做日志进行一致的回复。
mysql:
myisam的引擎,用mysql自带的mysqlhostcopy热备时,需要给表加读锁,影响dml操作。
innodb的引擎,它会备份innodb的表和索引,但是不会备份.frm文件。用ibbackup备份时,会有一个日志文件记录备份期间的数据变化,因此可以不用锁表,不影响其他用户使用数据库。但此工具是收费的。
innobackup是结合ibbackup使用的一个脚本,他会协助对.frm文件的备份。
八、sql语句的扩展和灵活性
mysql对sql语句有很多非常实用而方便的扩展,比如limit功能,insert可以一次插入多行数据,select某些管理数据可以不加from。
oracle在这方面感觉更加稳重传统一些。
九、复制
oracle:既有推或拉式的传统数据复制,也有dataguard的双机或多机容灾机制,主库出现问题是,可以自动切换备库到主库,但配置管理较复杂。
mysql:复制服务器配置简单,但主库出问题时,丛库有可能丢失一定的数据。且需要手工切换丛库到主库。
十、性能诊断
oracle有各种成熟的性能诊断调优工具,能实现很多自动分析、诊断功能。比如awr、addm、sqltrace、tkproof等
mysql的诊断调优方法较少,主要有慢查询日志。
十一、权限与安全
mysql的用户与主机有关,感觉没有什么意义,另外更容易被仿冒主机及ip有可乘之机。
oracle的权限与安全概念比较传统,中规中矩。
十二、分区表和分区索引
oracle的分区表和分区索引功能很成熟,可以提高用户访问db的体验。
mysql的分区表还不太成熟稳定。
十三、管理工具
oracle有多种成熟的命令行、图形界面、web管理工具,还有很多第三方的管理工具,管理极其方便高效。
mysql管理工具较少,在linux下的管理工具的安装有时要安装额外的包(phpmyadmin, etc),有一定复杂性。
1.在pom.xml引入redis依赖包
2.在application.properties中配置redis
##redis settings##本地连接spring.redis.host=127.0.0.1##使用默认端口spring.redis.port=6379##未设密码,默认pwd为空spring.redis.password=
配置RestTemplate 的序列化方式
redis 支持的数据类型及数据类型的使用场景
string
此类型和memcache相似,作为常规的key-value缓存应用。
例如微博数、粉丝数等
注:一个键最大能存储512MB
Hash
存储部分变更数据,如用户信息
存储、读取、修改用户属性
list
list列表是简单的字符串列表,按照插入顺序排序(内部实现为LinkedList),可以选择将一个链表插入到头部或尾部
常用命令 :lpush(添加左边元素),rpush,lpop(移除左边第一个元素),rpop,lrange(获取列表片段,LRANGE key start stop)等。
应用场景:Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表,粉丝列表等都可以用Redis的list结构来实现。1、最新消息排行等功能(比如朋友圈的时间线) 2、消息队列
Set
1、共同好友 2、利用唯一性,统计访问网站的所有独立ip 3、好友推荐时,根据tag求交集,大于某个阈值就可以推荐
Sorted Set(有序集合)
1、排行榜 2、带权重的消息队列
redis的持久化机制和过期机制
在 Redis 中,是可以设置过期数据的,Redis 提供了两种的方式,用于删除过期的数据!
定期删除
惰性删除
1、定期删除
Redis 默认 100ms 随即抽取部分设置过期时间的 key,过期了就删除。优点是避免长时间的在扫描过期 key,缺点是有些过期 key 无法被删除。
不扫描全部 key 的原因是,当设置了过期时间的 key 太多的情况下,会很耗时间,O(n) 的时间复杂度。
2、惰性删除
如果查询了某个过期 key,但定期删除没有删除掉,那就将其删除了。key 没过期就正常返回
如何持久化到硬盘
redis提供两种方式进行持久化,一种是RDB持久化
RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘
AOF持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。
垂直平分 水平平分
存储过程的概念
存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集。经编译后存储在数据库中。
存储过程是数据库中的一个重要对象,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。
可由应用程序通过一个调用来执行,而且允许用户声明变量。
存储过程的使用
1、创建一个存储过程
create procedure GetUsers()
begin
select * from user;
end;12345
2、调用存储过程
call GetUsers();12
3、删除存储过程
drop procedure if exists GetUsers;
存储过程与函数的区别
本质上没区别,执行的本质都一样。
只是函数有如:只能返回一个变量的限制。而存储过程可以返回多个。
函数是可以嵌入在sql中使用的,可以在select中调用,而存储过程要让sql的query 可以执行, 需要把 mysql_real_connect 的最后一个参数设置为CLIENT_MULTI_STATEMENTS。
函数限制比较多,比如不能用临时表,只能用表变量.还有一些函数都不可用等等.而存储过程的限制相对就比较少。
特性区别如下:
1)一般来说,存储过程实现的功能要复杂一点,而函数的实现的功能针对性比较强。存储过程,功能强大,可以执行包括修改表等一系列数据库操作;用户定义函数不能用于执行一组修改全局数据库状态的操作。
2)对于存储过程来说可以返回参数,如记录集,而函数只能返回值或者表对象。函数只能返回一个变量;而存储过程可以返回多个。存储过程的参数可以有IN,OUT,INOUT三种类型,而函数只能有IN类~~存储过程声明时不需要返回类型,而函数声明时需要描述返回类型,且函数体中必须包含一个有效的RETURN语句。
3)存储过程,可以使用非确定函数,不允许在用户定义函数主体中内置非确定函数。
4)存储过程一般是作为一个独立的部分来执行( EXECUTE 语句执行),而函数可以作为查询语句的一个部分来调用(SELECT调用),由于函数可以返回一个表对象,因此它可以在查询语句中位于FROM关键字的后面。 SQL语句中不可用存储过程,而可以使用函数。
10. 数据库的乐观锁和悲观锁的理解和实现?
乐观锁:每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在提交更新的时候会判断一下在此期间别人有没有去更新这个数据。
悲观锁:每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻止,直到这个锁被释放。
数据库的乐观锁需要自己实现,在表里面添加一个 version 字段,每次修改成功值加 1,这样每次修改的时候先对比一下,自己拥有的 version 和数据库现在的 version 是否一致,如果不一致就不修改,这样就实现了乐观锁
使用悲观锁来实现:
在上面的场景中,商品信息从查询出来到修改,中间有一个处理订单的过程,使用悲观锁的原理就是,当我们在查询出goods信息后就把当前的数据锁定,直到我们修改完毕后再解锁。那么在这个过程中,因为goods被锁定了,就不会出现有第三者来对其进行修改了。
注:要使用悲观锁,我们必须关闭mysql数据库的自动提交属性,因为MySQL默认使用autocommit模式,也就是说,当你执行一个更新操作后,MySQL会立刻将结果进行提交。
我们可以使用命令设置MySQL为非autocommit模式:
set autocommit=0;
11.树形结构的表怎么设计的?
左右值算法
12.union和union all的区别?
Union:对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序;
Union All:对两个结果集进行并集操作,包括重复行,不进行排序;
13. mysql 的存储引擎的了解?
MyISAM和InnoDB
两者的对比:
是否支持行级锁 : MyISAM 只有表级锁(table-level locking),而InnoDB 支持行级锁(row-level locking)和表级锁,默认为行级锁。
是否支持事务和崩溃后的安全恢复: MyISAM 强调的是性能,每次查询具有原子性,其执行速度比InnoDB类型更快,但是不提供事务支持。但是InnoDB 提供事务支持事务,外部键等高级数据库功能。 具有事务(commit)、回滚(rollback)和崩溃修复能力(crash recovery capabilities)的事务安全(transaction-safe (ACID compliant))型表。
是否支持外键: MyISAM不支持,而InnoDB支持。
是否支持MVCC :仅 InnoDB 支持。应对高并发事务, MVCC比单纯的加锁更高效;MVCC只在 READ COMMITTED 和 REPEATABLE READ 两个隔离级别下工作;MVCC可以使用 乐观(optimistic)锁 和 悲观(pessimistic)锁来实现;各数据库中MVCC实现并不统一。
为什么MyISAM查询更快?
InnoDB要缓存数据块,MyISAM只缓存索引,加载索引可能更快
InnoDB寻址先到块再到行,MyISAM直接寻址到文件offset
InnoDB要维护MVCC一致
(1)read uncommitted 未提交读
所有事务都可以看到没有提交事务的数据。
(2)read committed 提交读
事务成功提交后才可以被查询到。
(3)repeatable 重复读
同一个事务多个实例读取数据时,可能将未提交的记录查询出来,而出现幻读。
mysql默认的事务处理级别是'REPEATABLE-READ',也就是可重复读
Oracle默认系统事务隔离级别是READ COMMITTED,也就是读已提交
15. sql如何去重?
mysql去除重复查询的方法:1、使用distinct,代码为【select distinct name from a where statesign=0】;2、使用group by,代码为【statesign=0 group by .】。
16. sql 如何行转列和列转行?
行转列:
1.使用case...when....then 进行行转列
CASE <单值表达式>
WHEN <表达式值> THEN
列转行:
本质是将一列数据分散成一条记录显示出来
用UNION ALL将结果集加起来
17.oracle中常用的分析函数有哪些?
聚合函数
SUM :该函数计算组中表达式的累积和
MIN :在一个组中的数据窗口中查找表达式的最小值
MAX :在一个组中的数据窗口中查找表达式的最大值
AVG :用于计算一个组和数据窗口内表达式的平均值。
COUNT :对一组内发生的事情进行累积计数
18. sql 中drop、truncate、 delete 的区别?
drop:drop table 表名
删除内容和定义,并释放空间。执行drop语句,将使此表的结构一起删除。
truncate (清空表中的数据):truncate table 表名
删除内容、释放空间但不删除定义(也就是保留表的数据结构)。与drop不同的是,只是清空表数据而已。
truncate不能删除行数据,虽然只删除数据,但是比delete彻底,它只删除表数据。
delete:delete from 表名 (where 列名 = 值)
与truncate类似,delete也只删除内容、释放空间但不删除定义;但是delete即可以对行数据进行删除,也可以对整表数据进行删除。
都删除整张表的话
TRUNCATE TABLE 速度更快,占用的日志更少,这是因为 TRUNCATE TABLE 直接释放数据页并且在事务日志中也只记录数据页的释放,而 DELETE 是一行一行地删除,在事务日志中要记录每一条记录的删除
19. mysql 如何忽略表名的大小写?
找到你mysql的配置文件my.ini(linux下是my.cnf),打开后找到“[mysqld]”节点,在下面加上一句话:
lower_case_table_names=1
having是在分组后对数据进行过滤
where是在分组前对数据进行过滤
having后面可以使用聚合函数
where后面不可以使用聚合
在查询过程中执行顺序:from>where>group(含聚合)>having>order>select
21.如何使用数据库中的定时器、触发器、定时任务和游标?
如何使用数据库中的定时器
create一个event on schedule 后跟时间
整体流程简介:
1.开启mysql数据库的event功能
2.创建一个类似于要执行的代码块。
3.创建一个事件,这个事件中有诸多属性,可以设置执行时间间隔以及指定执行的代码块
4.因为创建的事件的执行属性默认是关闭的,所以我们要去修改这个事件的属性为开启。
触发器
CREATE TRIGGER trigger_name trigger_time trigger_event
ON tbl_name FOR EACH ROW trigger_stmt
其中trigger_name标识触发器名称,用户自行指定;
trigger_time标识触发时机,用before和after替换;
trigger_event标识触发事件,用insert,update和delete替换;
tbl_name标识建立触发器的表名,即在哪张表上建立触发器;
trigger_stmt是触发器程序体;触发器程序可以使用begin和end作为开始和结束,中间包含多条语句;
定时任务
#创建计划任务
CREATE EVENT IF NOT EXISTS testInsert
ON SCHEDULE EVERY 3 SECOND
ON COMPLETION PRESERVE
DO INSERT INTO aa(`name`,sex) VALUES('aa',2),('bb',1);
#开启计划任务
ALTER EVENT testInsert ENABLE;
#关闭计划任务
ALTER EVENT testInsert DISABLE;
游标
游标实际上是一种能从包括多条数据记录的结果集中每次提取一条记录的机制。游标充当指针的作用。尽管游标能遍历结果中的所有行,但他一次只指向一行。
游标可以被看作是一个查询结果集和结果集中指向特定记录的游标位置组成的一个临时文件,提供了在查询结果集中向前或向后浏览数据、处理结果集中数据的能力
1 作用: 用来存储查询结果集的
2 使用: 遍历游标中的数据, 相当于有一个指针指向游标中的第一行数据,每获取一行记录,指针向下移一行
3 语法格式
1 声明游标
1 格式
declare cursor_name cursor for select_statement
2 格式介绍
1 cursor_name:游标名称,存储sql语句执行的结果
2 select_statement:sql语句
2 打开游标
1 格式
open cursor_name;
3 遍历游标中的数据
1 介绍
1 相当于有一个指针指向游标中的第一行数据,每获取一行记录,指针向下移一行
2 格式
fetch cursor_name into var_name [, var_name] ...
3 格式介绍
1 一行fetch只能获取游标中的一行记录,并把记录中每一列的值赋值给var_name
2 一个var_name保存一行记录中一个列的值,若有多个列,需要多个变量
3 要输出游标中的所有数据,需要使用循环语句
4 关闭游标
1 格式
close cursor_name;
22. oracle 中如何实现递归查询?
在oracle中使用 start with 条件一
connect by prior 条件二
where 条件三
23.高并发下如何保证修改数据安全?
乐观锁 悲观锁 Synchronized Lock
24. delete 误删数据没有备份怎么恢复?
可以使用数据库闪回
--得到一个当前序列号.
select dbms_flashback.get_system_change_number scn from dual;
--7827319是序列号
select * from table as of scn 7827319;
你可以慢慢减序列号,直到你能查询到数据.
例如, 我删除数据提交, Oracle会给这个操作一个序列号. 然后每一次操作都会生成序列号.
你用 as of scn 序列 查询时, 查询当时那个操作的数据情况.
25.oracle死锁如何处理?
--1.查看数据库中那些用户产生了锁
--2.杀掉ORACLE进程:
--3.查找并杀死死锁的进程
1.3框架
1. springcloud 常用组件有哪些?作用是什么?使用步骤是什么?
eureka (提供服务注册与发现功能)
ribbon(提供负载均衡功能)
Feign(整合了ribbon和Hystrix,具有负载均衡和熔断限流等功能)
Ribbon 和 Feign 的区别
Ribbon基于http和tcp的客户端负载均衡工具,通过restTemplate模拟http请求 步骤相当繁琐
Feign在ribbon的基础上进行过改进,使用起来更加方便 并且他默认集成了ribbon的负载均衡机制
Hystrix (提供了熔断限流,合并请求等功能)
Zuul (提供了智能路由的功能)
Hystrix Dashboard (提供了服务监控的功能,提供了数据监控和友好的图形化界面)
Hystrix Turbine (Hystrix Turbine将每个服务Hystrix Dashboard数据进行了整合。也是监控系统的功能)
spring cloud config (提供了统一配置的功能)
Spring Cloud Bus (提供了配置实时更新的功能)
2springboot常用注解及作用?
1、@Controller
在SpringMVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,使用@Controller 标记一个类是Controller ,然后使用@RequestMapping 和@RequestParam 等一些注解用以定义URL 请求和Controller 方法之间的映射,这样的Controller 就能被外界访问到。
2、@RequestMapping
RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
3、@Resource和@Autowired
@Resource和@Autowired都是做bean的注入时使用,其实@Resource并不是Spring的注解,它的包是javax.annotation.Resource,需要导入,但是Spring支持该注解的注入。
4、@PathVariable
用于将请求URL中的模板变量映射到功能处理方法的参数上,即取出uri模板中的变量作为参数。如:
7、@ResponseBody
作用:将方法的返回值,以特定的格式写入到response的body区域,进而将数据返回给客户端。
如果返回值是字符串,那么直接将字符串写到客户端;如果是一个对象,会将对象转化为json串,然后写到客户端。
3springmvc的工作流程是什么?哪些是需要我们手动写的?
SpringMVC流程
1、 用户向服务端发送一次请求,这个请求会先到前端控制器DispatcherServlet(也叫中央控制器)。
2、DispatcherServlet接收到请求后会调用HandlerMapping处理器映射器。由此得知,该请求该由哪个Controller来处理(并未调用Controller,只是得知)
3、DispatcherServlet调用HandlerAdapter处理器适配器,告诉处理器适配器应该要去执行哪个Controller
4、HandlerAdapter处理器适配器去执行Controller并得到ModelAndView(数据和视图),并层层返回给DispatcherServlet
5、DispatcherServlet将ModelAndView交给ViewReslover视图解析器解析,然后返回真正的视图。
6、DispatcherServlet将模型数据填充到视图中
7、DispatcherServlet将结果响应给用户
4. mybatis 的xml映射文件中常用标签及作用?如何进行sql引用?
一、顶级标签
sql – 可被其他语句引用的可重用语句块。
insert – 映射插入语句
update – 映射更新语句
delete – 映射删除语句
select – 映射查询语句
动态sql标签
If choose (when, otherwise) trim (where, set) foreach bind
方式一:将简单的sql语句写在注释中,mapper.xml文件中不需要做任何处理。
方式二:将相对复杂的sql语句写到一个类中
方式三:正常的mybatis在mapper.xml文件中写sql语句
5dubbo和springcloud的区别?
1.spring cloud 有注册中心eureka Dubbo 无 用第三方的zookeeper
2.Dubbo 使用 RPC 通讯协议,Spring Cloud 使用 HTTP 协议的 REST API。
3.Dubbo由于是二进制的传输,占用带宽会更少;Spring Cloud是http协议传输,带宽会比较多。
4.Dubbo的开发难度较大,原因是dubbo的jar包依赖问题很多大型工程无法解决;
Spring Cloud的接口协议约定比较自由且松散,需要有强有力的行政措施来限制接口无序升级
5.Dubbo的注册中心可以选择zk,redis等多种,Spring Cloud:的注册中心只能用Eureka或者自研Eureka
6.dubbo:如果我们使用配置中心、分布式跟踪这些内容都需要自己去集成,无形中增加了使用难度。
Spring Cloud:提供了微服务的一整套解决方案
7.Dubbo只是实现了服务治理;
Spring Cloud下面有17个子项目(可能还会新增)分别覆盖了微服务架构下的方方面面,服务治理只是其中的一个方面;
6. springboot 自动装配原 理是什么? springboot配置文件中常用配置有哪些?
SpringBoot启动的时候加载主配置类,开启了自动配置功能@EnableAutoConfiguration
将类路径下META-INF/spring.factories里面配置的所有EnableAutoConfiguration的值加入到了容器中
properties文件和yml文件
7springboot项目如何打包、部署、运行?
用idea开发工具右侧的maven projects intall package 然后就会出来我们需要的jar
8.spring是如何控制事务的?
使用注解配置
使用@Transactional注解 需要在配置文件中开启对这个注解的扫描:
然后就可以使用@Transactional注解,此注解可以使用在类上,也可以使用在方法上,使用在类上即对此类的所有方法都起作用,使用在方法上则表示对单个方法起作用
9.myhatis中的>和<怎么处理?
1、转义
小于号 大于号 小于等于 大于等于 和 单引号 双引号
2、用进行声明
10. mybatis的工作原理是什么? mybatis的缓存的理解?
Mybatis工作原理
1.通过SqlSessionFactoryBuilder从mybatis-config.xml配置文件中构建出SqlSessionFactory。
2.SqlSessionFactory的实例开启一个SqlSession
3.SqlSession实例获得Mapper对象并运行Mapper映射的SQL语句,完成对数据库的CRUD和事务提交以及事务失败的回滚,之后关闭Session。
mybatis的缓存的理解?
当一个查询发生的时候,Mybatis 会在当前会话中查找是否已经有过相同的查询,有的话就直接拿缓存,不去数据库查了,线程执行完毕,缓存就被清掉了。二级缓存是进程级别的,通过在 mapper 文件中增加节点来启用,一个mapper可以含有多个会话。
11. mybatis 中#{}和${}的区别?
#{}是预编译处理,${}是字符串替换;
Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
Mybatis在处理${}时,就是把${}替换成变量的值;
使用#{}可以有效的防止SQL注入,提高系统安全性。
12. springboot 的异常处理?
SpringBoot中有一个ControllerAdvice的注解,使用该注解表示开启了全局异常的捕获,我们只需在自定义一个方法使用ExceptionHandler注解然后定义捕获异常的类型即可对这些捕获的异常进行统一的处理。
13. spring 中如何配置拦截器、过滤器?
创建一个拦截器,实现HandlerInterceptor接口,重写此接口的三个方法,preHandle、postHandle、afterCompletion,只有第一个方法返回true时,才会进入Controller,否则不会处理Controller内容,也不会执行后边两个方法。
然后在xml文件里配置拦截路径
过滤器:定义一个类实现Filter接口
这一接口含有三个过滤器必须执行的方法:
doFilter(ServletRequest, ServletResponse, FilterChain):这是一个完成过滤行为的方法。这同样是上游过滤器调用的方法。引入的FilterChain对象提供了后续过滤器所要调用的信息。如果该过滤器是过滤器链中的最后一个过滤器,则将请求交给被请求资源。也可以直接给客户端返回响应信息。
init(FilterConfig):由Web容器来调用完成的初始化工作。它保证了在第一次doFilter()调用前由容器调用。您能获取在 web.xml 文件中指定的初始化参数。
destroy():由Web容器来调用来释放资源,doFilter()中的所有活动都被该实例终止后,调用该方法。
配置过滤器:在web.xml配置文件里配置filter和filter-mapping的
区别
1 、拦截器是基于java的反射机制的,而过滤器是基于函数回调。
2 、拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
3 、拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
4 、拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
5 、在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
拦截器与过滤器使用场景:
spring Web MVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。
1、日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)等。
2、权限检查:如登录检测,进入处理器检测检测是否登录,如果没有直接返回到登录页面;
3、性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间(如果有反向代理,如apache可以自动记录);
4、通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个处理器都需要的即可使用拦截器实现。
5、OpenSessionInView:如hibernate,在进入处理器打开Session,在完成后关闭Session。
14. springsession 的原理是什么?
Spring Session是为了解决多进程session共享的问题
原理:拦截请求,将之前在服务器内存中进行 Session 创建销毁的动作,改成在 Redis 中创建。
15. gateway 的动态路由如何实现?
16.鉴权框架的 了解和使用? springsecurity 的授权方式有哪些?
一般有shiro和spring-security
第一步:
构建一个spring boot工程,这个利用idea的Spring Initializr很容易就构建了
第二步:
引入spring boot为spring security的包装的起步依赖,也就是上面提到的spring-boot-starter-security
spring security和shiro的异同
相同点
1、认证功能2、授权功能3、加密功能4、会话管理5、缓存支持
6、rememberMe功能
不同点
1、Spring Security 基于Spring 开发,项目若使用 Spring 作为基础,配合 Spring Security 做权限更加方便,而 Shiro 需要和 Spring 进行整合开发;
2、Spring Security 功能比 Shiro 更加丰富些,例如安全维护方面;
3、Spring Security 社区资源相对比 Shiro 更加丰富;
Spring Security对Oauth、OpenID也有支持,Shiro则需要自己手动实现。而且Spring Security的权限细粒度更高
spring security 接口 RequestMatcher 用于匹配路径,对路径做特殊的请求,类似于shiro的
抽象类 PathMatchingFilter,但是 RequestMatcher 作用粒度更细
4、Shiro 的配置和使用比较简单,Spring Security 上手复杂些;
5、Shiro 依赖性低,不需要任何框架和容器,可以独立运行.Spring Security 依赖Spring容器;
6、shiro 不仅仅可以使用在web中,还支持非web项目它可以工作在任何应用环境中。在集群
会话时Shiro最重要的一个好处或许就是它的会话是独立于容器的。
apache shiro的话,简单,易用,功能也强大,spring官网就是用的shiro,可见shiro的强大
授权码模式
客户端模式
密码模式刷新令牌
简化模式
17. mybatis 同时操作同一条数据该怎么解决并发问题?
乐观锁机制在一定程度上解决了这个问题。乐观锁,大多是基于数据版本(Version)记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来实现。
读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。
18. mybatis 中传递参数有哪些方式?
方式一、顺序传递参数
mapper.java文件:
publicUserselectUser(String name,intdeptId);
mapper.xml文件:
注意:里面的数字代表你传入参数的顺序,不是特别建议使用这种方法传递参数,特别是参数个数多的时候
方式二、注解@Param传递参数
mapper.java文件:
publicUserselectUser(@Param("userName")String name,int@Param("deptId")id);
mapper.xml文件:
注意:在xml文件中就只能以在@Param注解中声明的参数名称获取参数
方式三、使用Map集合传递参数
mapper.java文件:
publicUserselectUser(Map
mapper.xml文件:
方式四、使用JavaBean实体类传递参数
mapper.java文件:
publicUserselectUser(User user);
mapper.xml文件:
实例化 属性赋值 初始化 销毁
singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例
prototype:原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例
request:对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不同的Bean实例。只有在Web应用中使用Spring时,该作用域才有效
session:对于每次HTTP Session,使用session定义的Bean豆浆产生一个新实例。同样只有在Web应用中使用Spring时,该作用域才有效
globalsession:每个全局的HTTP Session,使用session定义的Bean都将产生一个新实例。典型情况下,仅在使用portlet context的时候有效。
20.怎么实现mbatis批量插入?
通过insert标签加上foreach标签,可以实现Mybatis批量插入的功能。
21. restful 风格的接口是什么?
Restful风格的API是一种软件架构风格,设计风格而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
在Restful风格中,用户请求的url使用同一个url而用请求方式:get,post,delete,put…等方式对请求的处理方法进行区分,这样可以在前后台分离式的开发中使得前端开发人员不会对请求的资源地址产生混淆和大量的检查方法名的麻烦,形成一个统一的接口。
22. springboot 是如何对线程进行封装的?
配置类上加上@EnableAsync注解,就可以在想多线程支持的方法上加上@Async该方法就可以自持多线程了
spring-boot-starter-tomcat
spring-boot-starter-jdbc
spring-boot-starter-data-elasticsearch
spring-boot-starter-data-mongodb
spring-boot-starter-data-redis
如果你想要自己创建一个starter,那么基本上包含以下几步
创建一个starter项目,关于项目的命名你可以参考这里
创建一个ConfigurationProperties用于保存你的配置信息(如果你的项目不使用配置信息则可以跳过这一步,不过这种情况非常少见)
创建一个AutoConfiguration,引用定义好的配置信息;在AutoConfiguration中实现所有starter应该完成的操作,并且把这个类加入spring.factories配置文件中进行声明
打包项目,之后在一个SpringBoot项目中引入该项目依赖,然后就可以使用该starter了
1.签名
根据用户名或者用户id,结合用户的ip或者设备号,生成一个token。在请求后台,后台获取http的head中的token,校验是否合法(和数据库或者redis中记录的是否一致,在登录或者初始化的时候,存入数据库/redis)
2.加密
客户端和服务器都保存一个秘钥,每次传输都加密,服务端根据秘钥解密。
1.4实用技术
1. linux 常用命令有哪些? linux 下部署项目怎么做?
1.1 pwd命令该命令的英文解释为print working directory(打印工作目录)。输入pwd命令,Linux会输出当前目录。
1.2 cd命令cd命令用来改变所在目录。
cd / 转到根目录中
cd ~ 转到/home/user用户目录下
1.3 ls命令
ls命令用来查看目录的内容。
1.4 cat命令
cat命令可以用来合并文件,也可以用来在屏幕上显示整个文件的内容。
ps 静态查看系统进程
ps -aux 使用BSD语法查看所有进程
ps -ef 标准语法查看所有进程
UID 程序被该 UID 所拥有
PID 就是这个程序的 ID
PPID 则是其上级父程序的ID
C CPU 使用的资源百分比
STIME 系统启动时间
TTY 登入者的终端机位置
TIME 使用掉的 CPU 时间。
CMD 所下达的指令为何
ps -aux --sort -pcpu,-pmem
根据CPU占用情况和内存占用情况来显示进程
watch -n 1 'ps -aux --sort -pcpu,-pmem'
每隔1秒监控一次进程情况
top 动态查看系统的状态
lsof -Pti :8000
通过端口号获得进程pid
lsof -i:端口号
查看端口占用
kill -9 pid
杀死指定pid的进程,强行杀死。
history
查看历史命令
2.对消息队列的使用场景? 消息发送失败如何处理?如何防止消息的重复消费?
解耦、异步、削峰
ActiveMQ介绍 MQ是消息中间件,是一种在分布式系统中应用程序借以传递消息的媒介,常用的有ActiveMQ,RabbitMQ,kafka。ActiveMQ是Apache下的开源项目,完全支持JMS1.1和J2EE1.4规范的JMS Provider实现。 特点: 1、支持多种语言编写客户端 2、对spring的支持,很容易和spring整合 3、支持多种传输协议:TCP,SSL,NIO,UDP等 4、支持AJAX 消息形式: 1、点对点(queue) 2、一对多(topic)
RabbitMQ是由erlang语言开发,基于AMQP(Advanced Message Queue 高级消息队列协议)协议实现的消息队列,它是一种应用程序之间的通信方法,消息队列在分布式系统开发中应用非常广泛。
Kafka是分布式发布-订阅消息系统,它最初是由LinkedIn公司开发的,之后成为Apache项目的一部分,Kafka是一个分布式,可划分的,冗余备份的持久性的日志服务,它主要用于处理流式数据。
消息发送失败如何处理
就回滚,捕捉异常,把预处理的这条数据给删除了,数据库就没有数据了,消费方就不会有消息执行。双方数据一致。
如何防止消息的重复消费?
1、对于需要保存到数据库的数据,我们可以设置某条数据的某个值,比如订单号之类的,设置一个唯一索引,这样的话即使重复消费也不会生效数据
2、乐观锁,也就是我们每次插入一条数据或者更新的时候判断某个版本号是不是与预期一样,如果不是,那么就不进行操作
3、使用redis进行存储,每次操作数据的时候先去redis进行判断,如果存在的话,那么这条数据就是重复消费的,然后我们可以丢弃或者做其他处理。
死信消息产生的来源
消息被拒绝(basic.reject或basic.nack)并且requeue=false
消息TTL过期
队列达到最大长度(队列满了,无法再添加数据到mq中)
死信队列处理的方式
丢弃,如果不是很重要,可以选择丢弃
记录死信入库,然后做后续的业务分析或处理
通过死信队列,由负责监听死信的应用程序进行处理
3. 事务的特性和事务的传播行为是什么?分布式如何保证数据-致性?
特性:原子性,一致性,隔离性,持续性。
原子性:事物是数据库的逻辑工作单位,事物中包括的操作要么都做,要么都不做。
一致性:事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。
隔离性:一个事务的执行不能被其它事物干扰。即一个事物内部的操作及使用的数据对其它并发事物是隔离的,并发执行的各个事物之间不能互相烦扰。
持续性:也称永久性,只一个事物一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其它操作或故障不应该对其执行结果有任何影响
分布式如何保证数据一致性
当更新操作完成之后,任何多个后续进程或者线程的访问都会返回最新的更新过的值。这种是对用户最友好的,就是用户上一次写什么,下一次就保证能读到什么。
事务传播行为用来描述由某一个事务传播行为修饰的方法被嵌套进另一个方法的时事务如何传播。
强一致
当更新操作完成之后,任何多个后续进程或者线程的访问都会返回最新的更新过的值。这种是对用户最友好的,就是用户上一次写什么,下一次就保证能读到什么。根据 CAP 理论,这种实现需要牺牲可用性。
弱一致性
系统并不保证续进程或者线程的访问都会返回最新的更新过的值。系统在数据写入成功之后,不承诺立即可以读到最新写入的值,也不会具体的承诺多久之后可以读到。
最终一致性
弱一致性的特定形式。系统保证在没有后续更新的前提下,系统最终返回上一次更新操作的值。在没有故障发生的前提下,不一致窗口的时间主要受通信延迟,系统负载和复制副本的个数影响。DNS 是一个典型的最终一致性系统。
4. Elasticsearch 的了解及使用?
是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。
特点:
分布式,无需人工搭建集群(solr就需要人为配置,使用Zookeeper作为注册中心)
Restful风格,一切API都遵循Rest原则,容易上手
近实时搜索,数据更新在Elasticsearch中几乎是完全同步的。
5对工作流的了解及使用?
常见的工作流框架
Activity5.1.3、JBPM4.4、OSWorkFlow、WorkFlow
在Java领域,JBPM和Activity是两个主流的工作流系统,而Activity的出现无疑将会取代JBPM(Activity的开发者就是从Jbpm开发者出来的)。
avtivity的基本操作:
设计流程图(各种组件,如连线、用户任务、网关)
流程定义增删改查
流程变量增删改查
启动流程定义
任务增删改查
完成任务
历史信息查询
java工作流怎么用activity
常用的是:activiti-engine-5.91.jar,activiti-spring-5.9.jar;
解释:以上两个只是activiti工作流的常用包,通常会配置如spring开发的java包,还有数据库jar包等进行使用,但具体要用到什么包,这个和业务开发的逻辑有关系,也没办法进行详细说明
的,所以只需要先下载常用的两个,其余的辅助包如:日志包、spring包、数据库包、hibernate包、struts包、mybatis包等根据实际需要添加即可。
6. svn 和git中冲突如何解决?
pull一下,更新程序 同步 查看冲突代码 人工修改 保持本地最新版 提交修改 再pull一下 更新 人工合并 更新到最新版 commit提交 push
7docker的常用命令有哪些?用docker怎么部署项目?
基础操作:
1.docker images查看镜像信息列表 镜像是静态的
2.docker ps -a查看运行中的所有容器
3.docker pull [images]:[version]从dockerhub拉取指定镜像
4.docker rm [containerID]删除容器
5.docker rmi [imageID]删除镜像
8. 如何导入导出excel、word. pdf?
Poi
9. nginx 的使用场景?如何配置?
Nginx的主要应用场景
1.静态网站
2.负载均衡(可以减轻单台服务器的压力)
3.动态代理
4.动静分离
5.虚拟主机
6.解决ddos攻击
7.解决ajax跨域问题
nginx配置文件介绍
位置:nginx安装目录的conf文件夹下,nginx.conf
全局块
主要包括配置运行Nginx服务器的用户、允许生成的worker process数、日志存放路径、配置文件引入等;worker process值越大,支持的并发量越高。
events块
设置每个work process最大连接数等,该部分主要影响Nginx性能。
http块
http全局块:包含日志定义、超时时间等
server块:每个server块相当于一个虚拟主机
server全局块:配置本虚拟机监听配置
location块:基于Nginx接收到的请求,对其进行匹配处理、地址定向、数据缓存等
10. 文件上传和下载如何实现?
文件上传
文件上传的本质是IO流的从操作;客户端:
1.必须使用post,post才能携带大数据
2.必须设置type=“file” name="file"必须要有名字
3.必须要设置enctype="multipart/form-data"服务器端:通过request.getInputStream()获取字节输入流,读取请求正文内容;将上传内容得到,保存在服务器端,就完成了文件上传;实际使用直接用框架中的api就可以,commons-fileupload是apache提供的一套文件上传工具;
文件下载有两种方法:
1.超链接下载:如果文件能被浏览器解析,点击就会打开文件,如果要下载,需要使用右键另存为,不能被浏览器解析的文件,点击就下载;
2.通过服务器流回写到浏览器下载;要设置MIME,即设置setcontentType(String mimeType);浏览器能解析的直接显示,不能解析的直接下载;
获取文件的mimeType类型:String mimeType=this.getServletContext().getMimeType(filename);
如果设置响应头response.setHeader("content-disposition","attachment;filename=下载的文件名称");不管浏览器能不能解析,
都是下载操作;
SpringBoot-RestTemplate
public User doGetWith2(String url){
User user = restTemplate.getForObject(url, User.class);
return user;
}
两种常用协议方式:
1、基于不同协议:HTTPService基于http协议,而WebService基于soap协议;
2、处理数据效率不同:HTTPService效率较高,WebService能处理较复杂的数据类型。
http协议支持客户/服务器模式,简单快速,客户向服务器请求服务时,只需传送请求方法和路径灵活,http允许传输任意类型的数据对象。无连接,即限制每次连接只处理一个请求,可以节省传输时间。
3、跨域的处理:HttpService方式不能处理跨域,如果调用一个其它应用的服务就要用webService 简单说
httpservice通过post和get得到你想要的东西
webservice就是使用soap协议得到你想要的东西,相比httpservice能处理些更加复杂的数据类型。
12. 模板引擎的了解和使用?
模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档。
使用
1、导入文件
2、定义模板
3、准备对象(需要填充的数据)
4、将数据填充到模板
template(模板ID,填坑的数据)
13. 定时任务如何实现?
目前主要有以下几种实现方式:
- JDK自带 :JDK自带的Timer以及JDK1.5+ 新增的ScheduledExecutorService;
- Quartz :简单却强大的JAVA作业调度框架
- Spring3.0以后自带的task :可以将它看成一个轻量级的Quartz,而且使用起来比Quartz简单许多;
14. maven如何解决jar包冲突?
1.可以借助Maven Helper插件中的Dependency Analyzer分析冲突的jar包,然后在对应标红版本的jar包上面点击execlude,就可以将该jar包排除出去
2.手动排除 在pom.xml中使用标签去排除冲突的jar包
版本锁定原则:一般用在继承项目的父项目中
15. 开发程序需要哪些文档?
可行性研究报告、需求规格说明书、项目计划、软件测试计划、概要设计说明书、详细设计说明书、编程规范、软件测试用例、软件测试报告、用户手册、安装手册、项目总结报告
16.如何防止短信验证码被恶意消费?
短信发送间隔设置——设置同一号码重复发送的时间间隔,一般设置为60-120秒
IP限定——根据自己的业务特点,设置每个IP每天的最大发送量
手机号码限定——根据业务特点,设置每个手机号码每天的最大发送量
流程限定——将手机短信验证和用户名密码设置分成两个步骤,用户在设置成功用户名密码后,下一步才进行手机短信验证,并且需要在获取第一步成功的回执之后才可进行校验。
绑定图型校验码——将图形校验码和手机验证码进行绑定,这样能比较有效的防止软件恶意注册。
1.5前端
Vue 的生命周期总共分为8个阶段:创建前/后,载入前/后,更新前/后,销毁前/后。
vue的指令:
v-text
v-text主要用来更新textContent,可以等同于JS的text属性。
v-if
v-if可以实现条件渲染,Vue会根据表达式的值的真假条件来渲染元素。
v-for
用v-for指令根据遍历数组来进行渲染
v-bind
v-bind用来动态的绑定一个或者多个特性。
3 vue的双向绑定如何实现?
数据双向绑定(v-model)配合vue中的data
vue如何实现请求
axios
vue的路由跳转方式
router-link标签
2. vue 页面中如何引用另一个vue页面?
ifream
3. var let const区别?
var 声明的变量属于函数作用域,let 和 const 声明的变量属于块级作用域;
var 存在变量提升现象,而 let 和 const 没有此类现象;
var 变量可以重复声明,而在同一个块级作用域,let 变量不能重新声明,const 变量不能修改。
4. get和post有什么区别?
1. Get是不安全的,因为在传输过程,数据被放在请求的URL中;Post的所有操作对用户来说都是不可见的。
2. Get传送的数据量较小,这主要是因为受URL长度限制;Post传送的数据量较大,一般被默认为不受限制。
3. Get限制Form表单的数据集的值必须为ASCII字符;而Post支持整个ISO10646字符集。
4. Get执行效率却比Post方法好。Get是form提交的默认方法。
5. jquery常用的选择器?
类选择器 id选择器 元素选择器
6. 如何改变this指向?
改变this指向的三种方法:
call()
apply()
bind()
call apply bind 总结
相同点: 都可以改变函数内部的this指向
不同点 :
1.call和apply会调用函数,并且改变函数内部this的指向
2.call和apply传递的参数不一样,call传递参数aru1,aru2…形式 , apply必须数组形式
3.bind 不会调用函数,可以改变函数内部this指向
主要应用场景
1.call经常做继承
2.apply经常跟数组有关系,比如借助于数学对象实现数组最大值最小值
3.bind不调用函数,但是还想改变this指向,比如改变定时器内部的this指向
7.如何向后台发送数据? 如何接收后台返回的数据?
1.第一种:ajax
传给后台的数据通过json封装起来,再用ajax将json传到后台
2、通过form表单的action传值
一般情况下数值在传给后台之前需要校验,可以在form中的onsubmit调用js方法进行校验,当js方法返回值为true时,触发action,当js方法返回值为false时,action不触发。这样处理的好处在于当用户输入不正确时,不会刷新页面,表单仍然会保留用户之前的输入
8.如何解决跨域问题?
前端
利用反向代理实现跨域
反向代理需要用到nginx
后台
使用cors
把form表单的值序列化成一个Json对象,如{username:admin,password:123}
将字符串转换为Json对象
利用Session防止表单重复提交(推荐)
实现原理:
服务器返回表单页面时,会先生成一个subToken保存于session,并把该subToenk传给表单页面。当表单提交时会带上subToken,服务器拦截器Interceptor会拦截该请求,拦截器判断session保存的subToken和表单提交subToken是否一致。若不一致或session的subToken为空或表单未携带subToken则不通过。
首次提交表单时session的subToken与表单携带的subToken一致走正常流程,然后拦截器内会删除session保存的subToken。当再次提交表单时由于session的subToken为空则不通过。从而实现了防止表单重复提交。
10. ajax请求方式、参数类型、状态码?
Get post url date type
11. 如何获取当前日期?
var myDate = new Date();
var year=myDate.getFullYear(); //获取当前年
var month=myDate.getMonth()+1; //获取当前月
var date=myDate.getDate(); //获取当前日
var h=myDate.getHours(); //获取当前小时数(0-23)
var m=myDate.getMinutes(); //获取当前分钟数(0-59)
var s=myDate.getSeconds(); //获取当前秒
var now=year+'-'+getNow(month)+"-"+getNow(date)+" "+getNow(h)+':'+getNow(m)+":"+getNow(s);
12. 怎么打开一个模态窗口?
SimpleModal是一个轻量级的jQuery插件,它提供了一个强大的界面模态对话框发展。
SimpleModal提供2个简单的方法来调用一个模式对话框。
(1)作为一个串连的jQuery函数,你可以调用一个jQuery元素modal()函数使用该元素的内容将显示一个模式对话框。
$("#element-id").modal();
(2)作为一个独立的功能,可以通过一个jQuery对象,一个DOM元素,或者一个普通的字符串(可以包含HTML)创建一个模态对话框。
$("#element-id").modal({options});
$.modal("SimpleModal
13. 表单验证是如何实现的?
用document获取输入框的value可以判断是否为空或者是否为数字
其他类型的校验 比如手机号 邮箱之类的可以用正则表达式校验
Promise:
是一种异步编程的解决方案,有三种状态,pending(进行中)、resolved(已完成)、rejected(已失败),特点是只有异步操作的结果,可以决定当前是哪一种状态,状态一旦改变,就无法再次改变状态;
Promise的作用:
1,主要是用来解决回调嵌套(执行完后再去执行某一些操作,这时候容易形成嵌套再嵌套的问题)的问题,也就是常见的"回调地狱"; 2,执行多并发请求获取数据;
Promise的使用:
1,创建 Promise 实例,var pr = new Promise();
2,实例创建以后可以用 .then 方法来指定 resolved状态 和 reject状态 的回调函数;
3,用常见的两种异常机制来捕获异常;
15. 如何画 一个表格?如何合井单元格?
在的标签内只要有几行就要写几个
,而 内又包含着
在th或者td中设置rowspan属性,用于合并两行的同一列单元格
16.如何延时调用一个函数?
WindowsetTimeout()方法
jQuerydelay()方法
17. 如何 处理后端返回过来的树形结构数据?
首先先遍历所有的节点数据,生成id 和parent_id的关系,然后遍历id 和parent_id的关系,因此将子节点数据放入children 这个集合当中。
通过js遍历数据对象,拼接成dom字符串,插入到html中
18.如何实时刷新页面?
页面自动刷新:把如下代码加入区域中
19什么是http协议无状态协议?怎么解决http协议无状态协议?
HTTP无状态协议是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
1.通过Cookies保存状态信息
2.通过Session保存状态信息
Tomcat调优?
线程池参数详解
corePoolSize 线程池核心线程大小
maximumPoolSize 线程池最大线程数量
keepAliveTime 空闲线程存活时间
unit 空闲线程存活时间单位
workQueue 工作队列
threadFactory 线程工厂
handler 拒绝策略
springboot中yml、yaml、properties加载顺序
加载顺序:
yml --> yaml --> properties
MyBatis 中 标签 ,来设置别名?SpringBoot别名
什么是双亲委派模型?
如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。
63、线程池有哪些拒绝策略?
AbortPolicy:中止策略。默认的拒绝策略,直接抛出 RejectedExecutionException。调用者可以捕获这个异常,然后根据需求编写自己的处理代码。
DiscardPolicy:抛弃策略。什么都不做,直接抛弃被拒绝的任务。
DiscardOldestPolicy:抛弃最老策略。抛弃阻塞队列中最老的任务,相当于就是队列中下一个将要被执行的任务,然后重新提交被拒绝的任务。如果阻塞队列是一个优先队列,那么“抛弃最旧的”策略将导致抛弃优先级最高的任务,因此最好不要将该策略和优先级队列放在一起使用。
CallerRunsPolicy:调用者运行策略。在调用者线程中执行该任务。该策略实现了一种调节机制,该策略既不会抛弃任务,也不会抛出异常,而是将任务回退到调用者(调用线程池执行任务的主线程),由于执行任务需要一定时间,因此主线程至少在一段时间内不能提交任务,从而使得线程池有时间来处理完正在执行的任务。
死锁的四个必要条件:
1)互斥条件:进程对所分配到的资源进行排他性控制,即在一段时间内某资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。
2)请求和保持条件:进程已经获得了至少一个资源,但又对其他资源发出请求,而该资源已被其他进程占有,此时该进程的请求被阻塞,但又对自己获得的资源保持不放。
3)不可剥夺条件:进程已获得的资源在未使用完毕之前,不可被其他进程强行剥夺,只能由自己释放。
4)环路等待条件:存在一种进程资源的循环等待链,链中每一个进程已获得的资源同时被 链中下一个进程所请求。
启动类加载器(Bootstrap ClassLoader):
这个类加载器负责将存放在
扩展类加载器(Extension ClassLoader):
这个加载器由sun.misc.Launcher$ExtClassLoader实现,它负责加载
应用程序类加载器(Application ClassLoader):
这个类加载器由sun.misc.Launcher$AppClassLoader实现。由于这个类加载器是ClassLoader中的getSystemClassLoader()方法的返回值,所以一般也称它为系统类加载器。它负责加载用户类路径(ClassPath)上所指定的类库,开发者可以直接使用这个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。
自定义类加载器:
用户自定义的类加载器。
为什么能够提高查询速度?
索引就是通过事先排好序,从而在查找时可以应用二分查找等高效率的算法。
索引有什么副作用吗?
1)索引是有大量数据的时候才建立的,没有大量数据反而会浪费时间,因为索引是使用二叉树建立.
2)当一个系统查询比较频繁,而新建,修改等操作比较少时,可以创建索引,这样查询的速度会比以前快很多,同时也带来弊端,就是新建或修改等操作时,比没有索引或没有建立覆盖索引时的要慢。
3)索引并不是越多越好,太多索引会占用很多的索引表空间,甚至比存储一条记录更多。
对于需要频繁新增记录的表,最好不要创建索引,没有索引的表,执行insert、append都很快,有了索引以后,会多一个维护索引的操作,一些大表可能导致insert 速度非常慢。
一.删除和更新之间引起的死锁
造成死锁的原因就是多个线程或进程对同一个资源的争抢或相互依赖。
二.在外键上没有加索引引起的死锁
客户的10.2.0.4 RAC for AIX环境频繁出现ORA-60死锁问题,导致应用程序无法顺利执行。
经过一系列的诊断,发现最终问题是由于外键上没有建立索引所致,由于程序在主子表上删除数据,缺少索引导致行级锁升级为表级锁,最终导致大量的锁等待和死锁。
线程池创建的四种方法是什么
方法:newCachedThreadPool创建可缓存线程池、newFixedThreadPool创建定长线程池、newScheduledThreadPool创建定长线程池、newSingleThreadExecutor创建单线程化线程池。
缓存击穿,就是说某个 key 非常热点,访问非常频繁,处于集中式高并发访问的情况,当这个 key 在失效的瞬间,大量的请求就击穿了缓存,直接请求数据库,就像是在一道屏障上凿开了一个洞。
解决方式也很简单,可以将热点数据设置为永远不过期;或者基于 redis or zookeeper 实现互斥锁,等待第一个请求构建完缓存之后,再释放锁,进而其它请求才能通过该 key 访问数据。
2 雪崩
雪崩指的是多个key查询并且出现高并发,缓存中失效或者查不到,然后都去db查询,从而导致db压力突然飙升,从而崩溃。
出现原因: 1 key同时失效
2 redis本身崩溃了
事前:redis 高可用,主从+哨兵,redis cluster,避免全盘崩溃。
事中:本地 ehcache 缓存 + hystrix 限流&降级,避免 MySQL 被打死。
事后:redis 持久化,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据。
3 击透
一般是出现这种情况是因为恶意频繁查询才会对系统造成很大的问题: key缓存并且数据库不存在,所以每次查询都会查询数据库从而导致数据库崩溃。
解决方案:
1) 使用布隆过滤器: 热点数据等场景(具体看使用场景)
内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。
内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。
什么是SpringBoot?
1、用来简化spring初始搭建和开发过程使用特定的方式进行配置(properties或者yml文件)
2、创建独立的spring引用程序main方法运行
3、嵌入Tomcat无需部署war包,直接打成jar包nohup java -jar – & 启动就好
4、简化了maven的配置
4、自动配置spring添加对应的starter自动化配置
SpringBoot常用的starter:
1、spring-boot-starter-web(嵌入Tomcat和web开发需要的servlet和jsp支持)
2、spring-boot-starter-data-jpa(数据库支持)
3、spring-boot-starter-data-Redis(Redis支持)
4、spring-boot-starter-data-solr(solr搜索应用框架支持)
5、mybatis-spring-boot-starter(第三方mybatis集成starter)
SpringBoot自动配置原理:
1、@EnableAutoConfiguration这个注解会"猜"你将如何配置spring,前提是你已经添加了jar依赖项,如果spring-boot-starter-web已经添加Tomcat和SpringMVC,这个注释就会自动假设您在开发一个web应用程序并添加相应的spring配置,会自动去maven中读取每个starter中的spring.factories文件,该文件里配置了所有需要被创建spring容器中bean
2、在main方法中加上@SpringBootApplication和@EnableAutoConfiguration
SpringBoot starter工作原理:
1、SpringBoot在启动时扫描项目依赖的jar包,寻找包含spring.factories文件的jar
2、根据spring.factories配置加载AutoConfigure
3、根据@Conditional注解的条件,进行自动配置并将bean注入到Spring Context
SpringBoot的优点:
1、减少开发、测试时间和努力
2、使用JavaConfig有助于避免使用XML
3、避免大量的maven导入和各种版本冲突
4、提供意见发展方法
5、通过提供默认值快速开始开发
6、没有单独的web服务器需要,这就意味着不再需要启动Tomcat、Glassfish或其他任何东西
7、需要更少的配置,因为没有web.xml文件。只需添加用@Configuration注释的类,然后添加用@Bean注释的方法,Spring将自动加载对象并像以前一样对其进行管理。甚至可以将@Autowired添加到bean方法中,以使用Spring自动装入需要的依赖关系中
Springboot注解总结
@SpringBootApplication:申明让spring boot自动给程序进行必要的配置,这个配置等同于:
@Configuration ,@EnableAutoConfiguration 和 @ComponentScan 三个配置。
@ResponseBody:表示该方法的返回结果直接写入HTTP response body中,一般在异步获取数据时使用,用于构建RESTful的api。在使用@RequestMapping后,返回值通常解析为跳转路径,加上@esponsebody后返回结果不会被解析为跳转路径,而是直接写入HTTP response body中。比如异步获取json数据,加上@Responsebody后,会直接返回json数据。该注解一般会配合@RequestMapping一起使用。
@Controller:用于定义控制器类,在spring项目中由控制器负责将用户发来的URL请求转发到对应的服务接口(service层),一般这个注解在类中,通常方法需要配合注解@RequestMapping。
@RestController:用于标注控制层组件(如struts中的action),@ResponseBody和@Controller的合集。
@RequestMapping:提供路由信息,负责URL到Controller中的具体函数的映射。
@EnableAutoConfiguration:SpringBoot自动配置(auto-configuration):尝试根据你添加的jar依赖自动配置你的Spring应用。例如,如果你的classpath下存在HSQLDB,并且你没有手动配置任何数据库连接beans,那么我们将自动配置一个内存型(in-memory)数据库”。你可以将@EnableAutoConfiguration或者@SpringBootApplication注解添加到一个@Configuration类上来选择自动配置。如果发现应用了你不想要的特定自动配置类,你可以使用@EnableAutoConfiguration注解的排除属性来禁用它们。
@ComponentScan:表示将该类自动发现扫描组件。个人理解相当于,如果扫描到有@Component、@Controller、@Service等这些注解的类,并注册为Bean,可以自动收集所有的Spring组件,包括@Configuration类。我们经常使用@ComponentScan注解搜索beans,并结合@Autowired注解导入。可以自动收集所有的Spring组件,包括@Configuration类。我们经常使用@ComponentScan注解搜索beans,并结合@Autowired注解导入。如果没有配置的话,Spring Boot会扫描启动类所在包下以及子包下的使用了@Service,@Repository等注解的类。
@Configuration:相当于传统的xml配置文件,如果有些第三方库需要用到xml文件,建议仍然通过@Configuration类作为项目的配置主类——可以使用@ImportResource注解加载xml配置文件。
@Import:用来导入其他配置类。
@ImportResource:用来加载xml配置文件。
@Autowired:自动导入依赖的bean
@Service:一般用于修饰service层的组件
@Repository:使用@Repository注解可以确保DAO或者repositories提供异常转译,这个注解修饰的DAO或者repositories类会被ComponetScan发现并配置,同时也不需要为它们提供XML配置项。
@Bean:用@Bean标注方法等价于XML中配置的bean。
@Value:注入Spring boot application.properties配置的属性的值。示例代码:
@Inject:等价于默认的@Autowired,只是没有required属性;
@Component:泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
@Bean:相当于XML中的,放在方法的上面,而不是类,意思是产生一个bean,并交给spring管理。
@AutoWired:自动导入依赖的bean。byType方式。把配置好的Bean拿来用,完成属性、方法的组装,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。当加上(required=false)时,就算找不到bean也不报错。
@Qualifier:当有多个同一类型的Bean时,可以用@Qualifier(“name”)来指定。与@Autowired配合使用。@Qualifier限定描述符除了能根据名字进行注入,但能进行更细粒度的控制如何选择候选者,具体使用方式如下:
@Resource(name=”name”,type=”type”):没有括号内内容的话,默认byName。与@Autowired干类似的事。
雪崩效应:
分布式系统中的服务通信依赖于网络,网络不好,必然会对分布式系统带来很大的影响。在分布式系统中,服务之间相互依赖,如果一个服务之间出现了故障或者网络延迟,在高并发的情况下,会导致线程阻塞,在很短的时间内该服务的线程资源会消耗殆尽,最终使得该服务不可用。由于服务的相互依赖,可能会导致整个系统的不可用,这就是“雪崩效应”。为了防止此类事件的发生,分布式系统必然要采取相应的措施,如熔断机制(Springcloud采用的是Hystrix)
熔断机制:
1、当一个服务出现故障时,请求失败次数超过设定的阀值(默认50)之后,该服务就会开启熔断器,之后该服务就不进行任何业务逻辑操作,执行快速失败,直接返回请求失败的信息。其他依赖于该服务的服务就不会因为得不到响应而造成线程阻塞,这是除了该服务和依赖于该服务的部分功能不可用外,其他功能正常。
2、熔断器还有一个自我修复机制,当一个服务熔断后,经过一段时间(5s)半打开熔断器。半打开的熔断器会检查一部分请求(只能有一个请求)是否正常,其他请求执行快速失败,检查的请求如果响应成功,则可判断该服务正常了,就可关闭该服务的熔断器,反之则继续打开熔断器。这种自我熔断机制和自我修复机制可以使程序更加健壮、也可以为开发和运维减少很多不必要的工作。
3、熔断组件往往会提供一系列的监控,如:服务可用与否、熔断器是否被打开、目前的吞吐量、网络延迟状态的监控等,从而可以让开发人员和运维人员的了解服务的状况。
Eureka和zookeeper都可以提供服务注册与发现的功能,两者的区别:
Zookeeper保证了CP(C:一致性,P:分区容错性),Eureka保证了AP(A:高可用,P:分区容错)
Ribbon和Nginx的区别:
Nginx性能好,但Ribbon可以剔除不健康节点,Nginx剔除比较麻烦,Ribbon是客户端负载均衡,Nginx是服务端负载均衡
微服务架构概念
微服务是一种架构风格,是以开发一组小型服务的方式来作为一个独立的应用系统,每个服务都运行在自已
的进程中,服务之间采用轻量级的HTTP通信机制 ( 通常是采用HTTP的RESTful API )进行通信。这些服务都
是围绕具体业务进行构建的,并且可以独立部署到生产环境上。这些服务可以用不同的编程语言编写,并且
可以使用不同的数据存储技术。对这些微服务我们只需要使用一个非常轻量级的集中式管理来进行协调。
微服务架构的优缺点
优点
1. 易于开发和维护:一个微服务只会关注一个特定的业务功能,所以业务清晰、代码量较少。开发和
维护单个微服务相对简单。
2. 单个微服务启动较快
3. 局部修改容易部署:单一应用只要有修改,就得重新部署整个应用。微服务解决了这样的问题。一
般来说,对某个微服务进行修改,只需要重新部署这个服务即可。
4. 技术栈不受限制:在微服务架构中,可以结合项目业务及团队的特点,合理的选择技术栈。5. 按需伸缩:可根据需求,实现细粒度的扩展。
缺点
1. 运维要求高:更多的服务意味着要投入更多的运维。
2. 分布式固有的复杂性:使用微服务构建的是分布式系统。对于一个分布式系统,系统容错、网络延
迟、分布式事务等都会带来巨大的问题。
3. 接口调整成本高:微服务之间通过接口进行通信。如果修改某一个微服务的API,可能所有用到这
个接口的微服务都需要进行调整。
什么是 Spring Cloud
Spring Cloud,基于 Spring Boot 提供了一套微服务解决方案,包括服务注册与发现,配置中心,全链路监
控,服务网关,负载均衡,熔断器等组件,除了基于NetFlix的开源组件做高度抽象封装之外,还有一些选型
中立的开源组件。
SpringBoot和SpringCloud的关系
Spring Boot 可以离开 Spring Cloud 单独使用开发项目,但是Spring Cloud离不开SpringBoot,属于依赖的
关系.
Spring Boot 专注于快速方便的开发单个个体微服务,Spring Cloud 关注全局的服务治理框架。
Spring Cloud 是关注全局的微服务协调整理治理框架,它将 Spring Boot 开发的一个个单体微服务整合并管
理起来,为各个微服务之间提供,配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策
竞选、分布式会话等等集成服务。
系统会根据业务被拆分成了很多的微服务,微服务的信息如何管理?
Spring Cloud中提供服务注册中心来管理微服务信息。
为什么要用注册中心?
1. 微服务数量众多,要进行远程调用就需要知道服务端的ip地址和端口,注册中心帮助我们管理这些服务
的ip和端口。
2. 微服务会实时上报自己的状态,注册中心统一管理这些微服务的状态,将存在问题的服务踢出服务列
表,客户端获取到可用的服务进行调用。
Eureka Server 与 Eureka Client 的关系
1. Eureka Server 是服务端,负责管理各个微服务注册和发现。
2. 在微服务上添加 Eureka Client 代码,就会访问到 Eureka Server 将此微服务注册在Eureka Server中,从而
使服务消费方能够找到。
3. 微服务(服务消费者)需要调用另一个微服务(服务提供者)时,从 Eureka Server 中获取服务调用地址,
进行远程调用。
Eureka自我保护现象
如长时间没有访问、检测不到心跳,或者修改实例名称,eureka启动自我保护机制
在某时刻某一个微服务不可用了,Eureka不会立刻删除,依旧会对该微服务的信息进行保存
注解和xml优先级
xml的优先级会高于注解的优先级。
SpringCloud常用注解总结:
@Controller 控制层,里面有多个连接
@Service 业务层,一般对于接口和实现
@Qualifier 如果一个接口有多个实现,那么注入时候加上唯一标示
@Repository 一般的dao层
@Autowired 自动注入依赖
@Resource bean的注入,同Autowired 有相同的功能。
说明:
共同点:@Resource和@Autowired都可以作为注入属性的修饰,在接口仅有单一实现类时,两个注解的修饰效果相同,可以互相替换,不影响使用。
不同点:
@Resource是Java自己的注解,@Resource有两个属性是比较重要的,分别是name和type;Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。
@Autowired是spring的注解,是spring2.5版本引入的,Autowired只根据type进行注入,不会去匹配name。如果涉及到type无法辨别注入对象时,那需要依赖@Qualifier或@Primary注解一起来修饰。
@Component定义其它组件(比如访问外部服务的组件)
@RequestMapping (value=’’,method={RequestMethod。GET或者POSt})绑定url
@RequestParam (value=’’ required=false)绑定参数,将客户端请求中的参数值映射到相应方法的参数上;
@ModelAttribute 一般用于controller层,被注解的方法会在所以mapping执行之前执行,并且可以绑定参数到Model model里面。
@Transactional (readOnly=true)注解式事务
@TransactionalEventListener用于配置事务的回调方法,可以在事务提交前、提交后、完成后以及回滚后几个阶段接受回调事件。
@Value(“${}”)可以注入properties里面的配置项
@ControllerAdvice 是spring3提供的新注解
@ExceptionHandler 如果在controller方法遇到异常,就会调用含有此注解的方法。
@InitBinder 一般用于controller 可以将所以form 讲所有传递进来的string 进行html编码,防止xss攻击,比如可以将字符串类型的日期转换成date类型
@EnableCaching 注解自动化配置合适的缓存管理器。
@EnableWebSecurity 注解开启spring security的功能,集成websercrityconfigureadapter。
@SringBootApplication相当于@configuration,@EnableAutoConfiguation @ComponentScan三个注解合用。
@EnableDiscoveryclient 注册应用为Eureka客户端应用,以获得服务发现的能力
@EnableAdminServer 使用admin监控应用。
@EnableEurekaClient配置本应用将使用服务注册和服务发现,注意:注册和发现用这个注解。
@EnableEurekaServer 启动一个服务注册中心
@EnableHystrix表示启动断路器,断路器依赖于服务注册和发现。
@HystrixCommand注解方法失败后,系统将西东切换到fallbackMethod方法执行。指定回调方法
@EnableAutoConfiguration spring boot自动配置,尝试根据你添加的jar依赖自动配置你的spring应用。
@ComponentScan 表示将该类自动发现并注册bean 可以自动收集所有的spring组件
@Comfiguration 相当于传统的xml配置文件
@Import 导入其他配置类
@ImportResource用来 加载xml配置文件
@FeignClient注解中的fallbank属性指定回调类
@RestController 返回json字符串的数据,直接可以编写RESTFul的接口;
@CrossOrigin 可以处理跨域请求,让你能访问不是一个域的文件;
@ApiOperation 首先@ApiOperation注解不是Spring自带的,它是是swagger里的注解@ApiOperation是用来构建Api文档的@ApiOperation(value = “接口说明”, httpMethod = “接口请求方式”, response = “接口返回参数类型”, notes = “接口发布说明”;
@SpringBootApplication 申明让spring boot自动给程序进行必要的配置,等价于以默认属性使用@Configuration,@EnableAutoConfiguration和@ComponentScan;
@RefreshScope 如果代码中需要动态刷新配置,在需要的类上加上该注解就行。但某些复杂的注入场景下,这个注解使用不当,配置可能仍然不动态刷新;
@FeignClient springboot调用外部接口:声明接口之后,在代码中通过@Resource注入之后即可使用。@FeignClient标签的常用属性如下:name:指定FeignClient的名称,如果项目使用了Ribbon,name属性会作为微服务的名称,用于服务发现
url: url一般用于调试,可以手动指定@FeignClient调用的地址decode404:当发生http 404错误时,如果该字段位true,会调用decoder进行解码,否则抛出FeignException
configuration: Feign配置类,可以自定义Feign的Encoder、Decoder、LogLevel、Contractfallback: 定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback指定的类必须实现@FeignClient标记的接口
fallbackFactory: 工厂类,用于生成fallback类示例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复的代码path: 定义当前FeignClient的统一前缀
@EnableFeignClients 开启Spring Cloud Feign的支持
@EnableCircuitBreaker 开启断路器功能
@LoadBalanced 开启客户端负载均衡
@WebAppConfiguration 开启Web 应用的配置,用于模拟ServletContext
@RibbonClient,这个注解用来为负载均衡客户端做一些自定义的配置,可以进一步配置或自定义从哪里获取服务端列表、负载均衡策略、Ping也就是服务鉴活策略等等
@PathVariable 获取参数。
@JsonBackReference 解决嵌套外链问题。
@RepositoryRestResourcepublic 配合spring-boot-starter-data-rest使用
Redis 应用场景
Rambbitmq 根据削峰异步解耦 说一下项目中哪里用到
Linux 查看日志 tail 查看进程 PS 杀死进程 kill 项目部署 java -jar
Sql优化
1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:
select id from t where num is null
可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:
select id from t where num=0
3.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
4.应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:
select id from t where num=10 or num=20
可以这样查询:
select id from t where num=10
union all
select id from t where num=20
5.in 和 not in 也要慎用,否则会导致全表扫描,如:
select id from t where num in(1,2,3)
对于连续的数值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3
6.下面的查询也将导致全表扫描:
select id from t where name like '%abc%'
7.应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:
select id from t where num/2=100
应改为:
select id from t where num=100*2
8.应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如:
select id from t where substring(name,1,3)='abc'--name以abc开头的id
应改为:
select id from t where name like 'abc%'
9.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
10.在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。
11.不要写一些没有意义的查询,如需要生成一个空表结构:
select col1,col2 into #t from t where 1=0
这类代码不会返回任何结果集,但是会消耗系统资源的,应改成这样:
create table #t(...)
12.很多时候用 exists 代替 in 是一个好的选择:
select num from a where num in(select num from b)
用下面的语句替换:
select num from a where exists(select 1 from b where num=a.num)
13.并不是所有索引对查询都有效,SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,如一表中有字段sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。
14.索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,
因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。
一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。
15.尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。
这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。
16.尽可能的使用 varchar 代替 char ,因为首先变长字段存储空间小,可以节省存储空间,
其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。
17.任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。
18.避免频繁创建和删除临时表,以减少系统表资源的消耗。
19.临时表并不是不可使用,适当地使用它们可以使某些例程更有效,例如,当需要重复引用大型表或常用表中的某个数据集时。但是,对于一次性事件,最好使用导出表。
20.在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,
以提高速度;如果数据量不大,为了缓和系统表的资源,应先create table,然后insert。
21.如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先 truncate table ,然后 drop table ,这样可以避免系统表的较长时间锁定。
22.尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。
23.使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题,基于集的方法通常更有效。
24.与临时表一样,游标并不是不可使用。对小型数据集使用 FAST_FORWARD 游标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。
在结果集中包括“合计”的例程通常要比使用游标执行的速度快。如果开发时间允许,基于游标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好。
25.尽量避免大事务操作,提高系统并发能力。
26.尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。
分布式事务
可以看出 2PC 和 3PC 是一种强一致性事务,不过还是有数据不一致,阻塞等风险,而且只能用在数据库层面。
而 TCC 是一种补偿性事务思想,适用的范围更广,在业务层面实现,因此对业务的侵入性较大,每一个操作都需要实现对应的三个方法。
本地消息、事务消息和最大努力通知其实都是最终一致性事务,因此适用于一些对时间不敏感的业务。
事务传播机制
1.REQUIRED
PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的默认设置。
2.SUPPORTS
PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。
3.MANDATORY
PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
4.REQUIRES_NEW
PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。
5.NOT_SUPPORTED
PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
6.NEVER
PROPAGATION_NEVER:以非事务方式执行操作,如果当前存在事务,则抛出异常。
7. NESTED
PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED属性执行。
如何一次性删除百万数据
完整备份;
保存索引DDL,删除索引,删除速率与索引量成正比;保存索引DDL,删除索引,删除速率与索引量成正比;
关闭日志记录;
删除后重建索引
MySQL的慢查询
MySQL的慢查询,全名是慢查询日志,是MySQL提供的一种日志记录,用来记录在MySQL中响应时间超过阀值的语句。
具体环境中,运行时间超过long_query_time值的SQL语句,则会被记录到慢查询日志中。
long_query_time的默认值为10,意思是记录运行10秒以上的语句。
默认情况下,MySQL数据库并不启动慢查询日志,需要手动来设置这个参数。