必备基础知识面向对象的特征
继承:从当前类继承另外一个类,当前类为子类,继承的类为父类,本质是对程序的扩展和延伸(extends)封装:编写一个类就是对数据的一种封装,封装为隐藏一切可隐藏的东西,只对外部提供简单的接口多态:多态性是指允许不同子类型的对象对同一消息作出不同的响应,父类引用指向子类,根据实际需求调用实际对象的实际方法,(简称动态绑定)抽象:抽象是将一类对象的共同特征总结出来构造类的过程,抽象只关注对
象有哪些属性和行为,不关心具体细节(abstract)
访问权限修饰符:public > protected > default > private
Java中没有goto语句(属于保留字段)throw 和 throws 的区别
throw表示抛出异常,由方法体内的语句处理
throws声明这个方法抛出某种类型的异常,让使用者来捕获异常的类型。final、finally、finalize 的区别?
final:属性表示不可变,方法不可覆盖,类不可继承
Finally:异常处理语句结构的一部分,表示总是执行
finalize :Object 类的一个方法---垃圾回收器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收JavaSE常用API
Math.round(11.5)等于多少?Math.round(- 11.5) 又等于多少?
Math.round(11.5)的返回值是 12
Math.round(-11.5)的返回值是-11
Java5 以前 switch()中,expr 只能是 byte、short、char、int。
Java 5开始expr 也可以是枚举类型数组有length属性,string有length方法String 、StringBuilder 、StringBuffer 的区别?
String 引用的字符串内容不可变
StringBuffer/StringBuilder 表示字符串对象可以修改。
String:对象定义后不可变,线程安全。
StringBuffer:是线程安全的(对调用方法加入同步锁),执行效率较慢
StringBuilder:是线程不安全的,适用于单线程下操作字符串缓冲区大量
StringBuilder 与 StringBuffer 有公共父类 AbstractStringBuilder(抽象类)
String s1 = "Programming";
4. String s2 = new String("Programming");
5. String s3 = "Program";
6. String s4 = "ming";
7. String s5 = "Program" + "ming";
8. String s6 = s3 + s4;
9. System.out.println(s1 == s2); //false
10. System.out.println(s1 == s5); //true
11. System.out.println(s1 == s6); //false
12. System.out.println(s1 == s6.intern()); //true
13. System.out.println(s2 == s2.intern()); //false
String 对象的 intern()方法会得到字符串对象在常量池中对应的版本的引用八种基本数据类型的字节数量
Byte 1字节 -128---127
Short 2字节
Int 4字节
Long 8字节
Float 4字节
Double 8字节
Char 2字节
Boolean 1字节int 和 和 Integer 有什么区
Java 为每一个基本数据类型都引入了对应的包装类型Java 中有几种类型的流
输入流inputStream (字节流)
输出流outputStream(字节流)
字节流继承于 InputStream 和 OutputStream
节点流可以从或向一个特定的地方(节点)读写数据。如 FileReader
字符流继承于 InputStreamReader 和 OutputStreamWriter字节流如何转为字符流
字节输入流转字符输入流通过 InputStreamReader 实现,该类的构造函数可以传入 InputStream 对象。
字节输出流转字符输出流通过 OutputStreamWriter 实现,该类的构造函数可以传入 OutputStream 对象。如何将一个 java 对象序列化到文件里
在 java 中能够被序列化的类必须先实现 Serializable 接口,该接口没有任何抽象方法只是起到一个标记作用字节流和字符流的区别
字节流读取的时候,读到一个字节就返回一个字节
字符流使用了字节流读到一个或多个字节
字符流处理的单元为 2 个字节的 Unicode 字符如何实现对象克隆?
1). 实现 Cloneable 接口并重写 Object 类中的 clone()方法;
2). 实现 Serializable 接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆,java 序列化,如何实现 java 序列化
序列化是一种处理对象流的机制,对象流是将对象的内容进行流化。对流化后的对象进行读
写操作,序列化是解决在对象流进行读写操作时所引发的问题。
序列化的实现--将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法Java 中实现多态的机制是什么?
父类引用指向子类,根据实际需求调用实际对象的实际方法,(简称动态绑定)五大常见异常
1)java.lang.NullPointerException 空指针异常
2)java.lang.ClassNotFoundException 指定的类找不到
3)java.lang.NumberFormatException 字符串转换为数字异常
4)java.lang.IndexOutOfBoundsException 数组角标越界异常
5)java.lang.IllegalArgumentException 方法传递参数错误
6)java.lang.ClassCastException 数据类型转换异常ArrayList、HashSet、HashMap 是线程安全的吗?
在集合中 Vector 和 HashTable 倒是线程安全的。打开源码会发现各自核心方法添加上了
synchronized 关键字--加上了 synchronized 关键字可以让上面那 3 个不安全的集合变为安全的ArrayList 内部用什么实现的?
ArrayList 内部是用 Object[](数组)实现的。并发集合和普通集合如何区别?
普通集合通常性能最高,但是不保证多线程的安全性和并发的可靠性。
线程安全集合仅仅是给集合添加了 synchronized 同步锁,严重牺牲了性能List 的三个子类的特点
ArrayList 底层结构是数组,底层查询快,增删慢。
LinkedList 底层结构是链表型的,增删快,查询慢。
voctor 底层结构是数组 线程安全的,增删慢,查询慢。List 和 Map、Set 的区别
List 和 Set 是存储单列数据的集合
List 中存储的数据是有顺序,并且允许重复
Map 是存储键和值这样的双列数据的集合
Map 中存储的数据是没有顺序的,其键是不能重复的它的值是可以有重复的
Set 中存储的数据是无序的,且不允许有重复实现类:List 和 Map、Set
List 接口有三个实现类(LinkedList:;ArrayList:;Vector)
Map 接口有三个实现类((HashMap:;HashTable:;LinkedHashMap:)
Set 接口有两个实现类((HashSet:LinkedHashSet:继承与 HashSet,)HashMap 是线程不安全的
HashMap是Map的一个子接口,将键映射到值得对象,不允许键值重复
允许空键和空值HashMap 的效率要较 HashTable 的效率高一些HashTable 是线程安全的一个集合,不允许 null 值作为一个 key 值或者 Value 值;
HashTable 是 sychronize多个线程访问时不需要自己为它的方法实现同步
而 HashMap 在被多个线程访问的时候需要自己为它的方法实现同步;ArrayList 和 Linkedlist 区别?
ArrayList 和 Vector 使用了数组的实现,可以认为 ArrayList 或者 Vector 封装了对内部数组的操作,比如向数组中添加,删除,插入新的元素或者数据的扩展和重定向。LinkedList使用了循环双向链表数据结构。与基于数组的 ArrayList 相比,这是两种截然不同的实现技术,这也决定了它们将适用于完全不同的工作场景。Map 中的 key 和 value 可以为 null 么?
HashMap 对象的 key、value 值均可为 null。
HahTable 对象的 key、value 值均不可为 null且两者的的 key 值均不能重复,若添加 key 相同的键值对,后面的 value 会自动覆盖前面的 value,但不会报错。多线程基础知识
继承Thread类创建线程
public class MyThread extends Thread {  public void run() {  System.out.println("MyThread.run()");  }
}
MyThread myThread1 = new MyThread();
MyThread myThread2 = new MyThread();
myThread1.start();
myThread2.start();
实现Runnable接口创建线程
自己的类已经extends另一个类,无法extends Thread,此时,可以实现一个Runnable接口
public class MyThread extends OtherClass implements Runnable {  public void run() {  System.out.println("MyThread.run()");  }
}
为了启动MyThread,需要首先实例化一个Thread,并传入自己的MyThread实例:
MyThread myThread = new MyThread();
Thread thread = new Thread(myThread);
thread.start();
当传入一个Runnable target参数给Thread后,Thread的run()方法就会调用target.run()
(参考jdk源码)
public void run() {  if (target != null) {  target.run();  }
}  线程互斥与同步
多个线程急用同一台打印机,会使打印结果交织在一起,难于区分。可能会导致处理出错
因此线程同步的主要任务是使并发执行的各线程之间能够有效的共享资源和相互合作多线程的创建方式
继承 Thread 类:但 Thread 本质上也是实现了 Runnable 接口的一个实例,它代表一个线程的实例,并且,启动线程的唯一方法就是通过 Thread 类的 start()实例方法。start()方法是一个 native 方法,它将启动一个新线程,并执行 run()方法。这种方式实现多线程很简单,通过自己的类直接 extend Thread,并复写 run()方法,就可以,启动新线程并执行自己定义的 run()方法。例如:继承 Thread 类实现多线程,并在合适的地方启动线程wait 和 sleep 方法的不同?
最大的不同是在等待时wait会释放锁
而slee一直持有锁wait通常用于线程间交互,sleep通常用于暂停执行。synchronized 和 volatile 关键字的作用
一旦一个共享变量(类的成员变量、类的静态成员变量)被 volatile 修饰之后,一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的
synchronized 则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住
volatile 仅能实现变量的修改可见性,并不能保证原子性;
synchronized 则可以保证变量的修改可见性和原子性
volatile 不会造成线程的阻塞;线程池
线程池就是事先将多个线程对象放到一个容器中,当使用的时候就不用 new 线程而是直接去池中拿线程即可,节省了开辟子线程的时间,提高的代码执行效率。遇到线程死锁该怎么解决死锁的定义:所谓死锁是指多个线程因竞争资源而造成的一种僵局(互相等待)线程阻塞:线程阻塞通常是指一个线程在执行过程中暂停,以等待某个条件的触发。线程和进程的区别
进程:具有一定独立功能的程序关于某个数据集合上的一次运行活动,
线程:是进程的一个实体,是 cpu 调度和分派的基本单位
特点:
线程的划分尺度小于进程,这使多线程程序拥有高并发性
进程在运行时各自内存单元相互独立,线程之间内存共享,使多线程编程有更好用户体验
wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁;
sleep():使一个正在运行的线程处于睡眠状态
notify():唤醒一个处于等待状态的线程启动一个线程是调用 run()方法还是 start()方法?
start()方法Java高级
Java 中反射的理解
Java中的反射是能够获取到Java中要反射类的字节码
获取字节码有以下三种方式:
1.Class.forName(className)
2.类名.class
3.this.getClass()。Java 中的设计模式&回收机制
Java 中一般认为有 23 种设计模式
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式单例设计
饿汉式:1. public class Singleton {
2.// 直接创建对象
3.public static Singleton instance = new Singleton();
4.
5.// 私有化构造函数
6.private Singleton() {
7.}
8.// 返回对象实例
9.
10.public static Singleton getInstance() {
11.return instance;
12.}
13.}懒汉式:
1. public class Singleton {
2. // 声明变量
3. private static volatile Singleton singleton = null;
4.
5. // 私有构造函数
6. private Singleton() {
7. }
8.
9. // 提供对外方法
10. public static Singleton getInstance() {
11. if (singleton == null) {
12. synchronized (Singleton.class) {
13. if (singleton == null) {
14. singleton = new Singleton();
15. }
16. }
17. }
18. return singleton;
19. }
20. }Java 中引用类型都有哪些?
强引用(StrongReference)
如果一个对象被被人拥有强引用,那么垃圾回收器绝不会回收它软引用(SoftReference)
如果一个对象只具有软引用,那么如果内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存。弱引用(WeakReference)
如果一个对象只具有弱引用,那该类就是可有可无的对象,因为只要该对象被 gc 扫描到了随时都会把它干掉虚引用(PhantomReference)
那么它就和没有任何引用一样,在任何时候都可能被垃圾回收Heap(堆) 和 stack(栈) 有什么区别
stack:由系统自动分配。
heap:需要程序员自己申请类什么时候被初始化?
创建类的实例,也就是 new 一个对象
访问某个类或接口的静态变量,或者对该静态变量赋值
调用类的静态方法
反射(Class.forName("com.lyj.load")
初始化一个类的子类(会首先初始化子类的父Java 类加载体系之 ClassLoader 双亲委托机制--
java 是安全的语言,它有四类称为安全沙箱机制的安全性,这四类安全沙箱分别是:
类加载体系
.class 文件检验器
内置于 Java 虚拟机(及语言)的安全
安全管理器及 Java Api在开发中遇到过内存溢出么?原因有哪些?解决方法有哪些?
1.内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
2.集合类中有对对象的引用,使用完后未清空,使得 JVM 不能回收;
3.代码中存在死循环或循环产生过多重复的对象实体
4.使用的第三方软件中的 BUG;
5.启动参数内存值设定的过Java在什么情况下会内存溢出
1 被生命周期极长的集合类不当持有,号称是Java内存泄漏的首因
2 Scope定义不对,这个很简单了,方法的局部变量定义成类的变量,类的静态变量等。
3 异常时没有加finally{}来释放某些资源,JDBC时代也是很普遍的事情。
4 另外一些我了解不深的原因,如:Swing里的Listener没有显式remove;内部类持有外部对象的隐式引用;Finalizers造成关联对象没有被及时清空等。
内存溢出的解决方案:
第一步,修改 JVM 启动参数,直接增加内存。(-Xms,-Xmx 参数一定不要忘记加。
第二步,检查错误日志,查看“OutOfMemory”错误前是否有其它异常或错误
第三步,对代码进行走查和分析,找出可能发生内存溢出的位置。AJAX
通过异步模式,提升了用户体验(异步刷新不用对整个页面刷新,降低了服务器的压力)jsonp 原理
JavaScript 是一种在 Web 开发中经常使用的前端动态脚本技术
jsonp 的最基本的原理是:动态添加一个<script>标签,使用 script 标签的 src 属性没有跨域的限制的特点实现跨域。首先在客户端注册一个 callback, 然后把 callback 的名字传给服务器。此时,服务器先生成 json 数
据。 然后以 javascript 语法的方式,生成一个 function , function 名字就是传递上来的参数 jsonp。最后将json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。什么是 jsp,什么是Servlet?jsp 和Servlet 有什么区别
jsp 本质上就是一个 Servlet
jsp 是 html 页面中内嵌的 Java 代码,侧重页面显示(显示层)
Servlet 是 html 代码和 Java 代码分离,侧重逻辑控制(控制层)Jsp(九大)内置对象及他们的作用?
Page 代表js本身(this)
Session 存储用户会话所需信息
request 用于接受通过 HTTP 协议传送到服务器的数据
response 表示服务器端对客户端的回应
application 用于存储和访问所有用户分享一个Application对象
out 用在web浏览器上输出信息
config 取得服务器的配置信
exception 显示异常信息
Pagecontext 用于存取其他隐含对象什么是 xml,使用 xml 的优缺点
优点:用于配置文件,格式统一,符合标准,在互不兼容的系统间交互数据,共享数据方便
缺点:xml 文件格式复杂,数据传输占流量,服务和客户端解析 xml 占用资源且不易维护
Xml 常用解析器有 2 种,分别是:DOM 和 SAX;常用的 Linux 命令
Ll           查看目录
mkdir 文件名 创建文件
tar -xvf       打包
tar -zcvf      打包并且压缩
tar -zxvf      解压
rm -rf        删除
Vi 文件名    编辑Linux 中如何查看日志
tail –f 日志文件Linux 怎么关闭进程
ps -ef | grep java  //查看进程(grep是搜索是否有java信息)
kill -9 [PID]       //终止线程前端框架有哪些
EasyUI:一种基于jQuery用户界面插件集合
使用 easyui 你不需要写很多代码,你只需要通过编写一些HTML 标记,就可以定义界面
easyui 为创建现代化,互动,JavaScript 应用程序,提供必要的功能MiniUI(优点)
基于 jquery 的框架,快速开发 WebUI它能缩短开发时间,减少代码量
使开发者更专注于业务和服务端,轻松实现界面开发,带来绝佳的用户体验
使用 MiniUI,开发者可以快速创建 Ajax 无刷新、 B/S 快速录入数据缺点:收费,没有源码,基于这个开发如果想对功能做扩展就
需要找他们的团队进行升级!Vue.js
是一套构建用户界面的渐进式框架,Vue 的核心库只关注视图层,
Vue.js 的核心是一个允许采用简洁的模板语法来声明式的将数据渲染进 DOM 的系统:AngularJS
google 开发者设计的一个前端开发框架
它是由是由 JavaScript 编写的一个 JS 框架
通常它是用来在静态网页构建动态应用不足而设计的。AngularJS 特点
1、 数据绑定: AngularJS 是数据双向绑定。
2、 MVVM(Model-View-ViewModel)模式: Model 简单数据对象,View 视图wModel 是用来提供数据和方法,和 View 进行交互。这种设计模式使得代码解耦3、依赖注入:AngularJS 支持注入方式把需要的对象,方法等注入到指定的对象中。
4、 指令: AngularJS 内部自带各种常用指令,同时也支持开发者自定义指令。
5、HTML 模板和扩展 HTML: AngularJS 可以定义与 HTML 兼容的自定义模板SQL 之连接查询(左连接和右连接的区别)
左连接(左外连接):以左表作为基准进行查询,左表数据会全部显示出来,右表如果和左表匹配的,数据则显示相应字段的数据,如果不匹配则显示为 null右连接(右外连接):以右表作为基准进行查询,右表数据会全部显示出来,左表如果和右表匹配的,数据则显示相应字段的数据,如果不匹配则显示为 null全连接:先以左表进行左外连接,再以右表进行右外连接。SQL 之 sql 注入
当执行的 sql 为 select * from user where username = “admin” or “a”=“a”时,sql 语句恒成立参数 admin 毫无意义2. Mybatis 框架中的mapper方式中的 # 也能很大程度的防止 sql 注入($无法防止sql 注入)Mysql 性能优化
1、当只要一行数据时使用 limit 1查询时如果已知会得到一条数据
2、这种情况下加上limit 1会增加性能。因为 mysql 数据库引擎会在找到一条结果停止搜索
3、而不是继续查询下一条是否符合标准直到所有记录查询完毕Mysql 中有两个引擎 MyISAM 和 InnoDB,每个引擎有利有弊
MyISAM 适用于一些大量查询的应用
InnoDB 的趋势会是一个非常复杂的存储引擎,对于一些小的应用会比 MyISAM 还慢,但是支持“行锁”,MyISAM 是 MySQL 官方提供默认的存储引擎,其特点是不支持事务、表锁和全文索引,
InnoDB 存储引擎支持事务,行锁设置、支持外键,支持非锁定读,默认情况下读不产生锁Mysql 架构器中各个模块都是什么
(1)、连接管理与安全验证是什么?
每个客户端都会建立一个与服务器连接的线程,服务器会有一个线程池来管理这些 连接;如果客户端需要连接到 MYSQL 数据库还需要进行验证,包括用户名、密码、主机信息等。
(2)、解析器是什么?
解析器的作用主要是分析查询语句,最终生成解析树;首先解析器会对查询语句的语法进行分析,分析语法是否,有问题。还有解析器会查询缓存,如果在缓存中有对应的语句,就返回查询结果不进行接下来的优化执行操作。前提是缓存中的数据没有被修改,当然如果被修改了也会被清出缓存。
(3)、优化器怎么用?
优化器的作用主要是对查询语句进行优化操作,包括选择合适的索引,数据的读取方式,包括获取查询的开销信息,统计信息等,
(4)、执行器是什么?
执行器包括执行查询语句,返回查询结果,生成执行计划包括与存储引擎的一些处理操作。事务的四大特征是
(1)原子性:事物所执行逻辑不可分割的特性(要么执行成功/要么失败/回滚)
(2)一致性:事物执行前后数据的完整性
(3)隔离性:事物执行前后不受其他事物所干扰
(4)持久性:事务执行成功后,数据永久保存到数据库中Mysql 中四种隔离级
读已提交(不可重复读,幻读)
读未提交(脏读,不可重复读,幻读)
可重复读(幻读)
可串行化(串行读)
脏读(事务可以读取其它事务未提交的数据)
Spring的常用注解
@requestmapping//用于请求url映射
@requestbody接收http请求的json数据/将json数据转化为对象
@responsebody将对象转化为json数据如何开启注解处理器和适配器?
springmvc.xml 中通过开启 <mvc:annotation-driven>来实现注解处理器和适配器的开启解决 get 和 post 乱码问题?
post请求乱码:在web.xml 里边配置一个CharacterEncodingFilter 过滤器,设置为 utf-8
get 请求的乱码修改 tomcat 配置文件添加编码与工程编码一致谈谈你对 Spring 的理解
Spring 是一个开源框架,是一个 IOC 和 AOP 容器框架。
Spring 容器的主要核心是控制反转(IOC)
传统java开发模式需要一个对象时,会使用new创建一个对象。
在spring 开发模式中,spring 容器使用了工厂模式为我们创建了所需要的对象,不需要我们自己创建了,直接调用 spring 提供的对象就可以了,这是控制反转的思想。依赖注入(DI)
spring 使用 javaBean 对象的 set 方法或带参数的构造方法
我们在创建所需对象时将属性自动设置为所需要的值,就是依赖注入的思想面向切面编程(AOP)
在面向对象编程(oop)思想中,我们将事物纵向抽成一个个的对象。而在面向切面编程
中,我们将一个个的对象某些类似的方面横向抽成一个切面,对这个切面进行一些如权限控制、事物管理,记录日志等Spring 的常用注解
@Required:设值方法
@Autowired:可以对类成员变量方法及构造函数进行标注,完成自动装配的工作@Qualifier:该注解和@Autowired 搭配使用,用于消除特定 bean 自动装配的歧义。Spring bean 的生命周期
bean 定义:在配置文件里面用<bean></bean>来进行定义
bean 初始化:有两种方式初始化:
1.在配置文件中通过指定 init-method 属性来完成
2.实现 org.springframwork.beans.factory.InitializingBean 接口
bean 销毁:使用配置文件指定的 destro-method Spring 能帮我们做什么?
Spring 根据配置文件进行创建及组装对象间依赖关系,只需要改配置文件即可
Spring 面向切面编程能帮助我们无耦合的实现日志记录,性能统计,安全控制
Spring 能非常简单的帮我们管理数据库事务
Spring 还能与第三方数据库访问框架(如 Hibernate、JPA)无缝集成,而且自己也提供了一套 JDBC访问模板,来方便数据库访问
Spring 还能与第三方 Web(如 Struts、JSF)框架无缝集成,而且自己也提供了一套 Spring MVC框架,来方便 web 层搭建。Spring 的事务
声明式事务管理的定义:
用在 Spring 配置文件中声明式的处理事务来代替代码式的处理事务。这样的好
处是,事务管理不侵入开发的组件,具体来说,业务逻辑对象就不会意识到正在事务管理之中,事实上也应该如此,因为事务管理是属于系统层面的服务,而不是业务逻辑的一部分,如果想要改变事务管理策划的话,也只需要在定义文件中重新配置即可,这样维护起来极其方便。解释 Spring JDBC、Spring DAO 和 Spring ORM
Spring-DAO实际上是指示你写 DAO 操作、写好 DAO 操作的一些规范
Spring-JDBC 提供了 Jdbc 模板类,它移除了连接代码以帮你专注于 SQL 查询和相关参数
Spring-ORM 是一个囊括了很多持久层技术(JPA,JDO,Hibernate,iBatis)的总括模块Spring WEB 模块
WEB 模块是构建在 application context 模块基础之上,提供一个适合 web 应用的上下文Spring 配置文件有什么作用?
Spring 配置文件是个 XML 文件,这个文件包含了类信息,描述了如何配置它们,以及如何相互调用。什么是 Spring IOC 容器?
IOC 控制反转:Spring IOC 负责创建对象,管理对象。装配对象,配置对象,并且管理这些对象的整个生命周期IOC 的优点
依赖注入把应用的代码量降到最低,它使应用容易测试,单元测试不再需要单例和 JNDI 查找机制ApplicationContext 的实现类有哪些?
1.FileSystemXmlApplicationContext :此容器从一个 XML 文件中加载 beans 的定义,XML Bean 配置文件的全路径名必须提供给它的构造函数2.ClassPathXmlApplicationContext:此容器也从一个 XML 文件中加载 beans 的定义,这里,你需要正确设置classpath 因为这个容器将在 classpath 里找 bean 配置3.WebXmlApplicationContext:此容器加载一个 XML 文件,此文件定义了一个 WEB 应用的所有 bean什么是 Spring 的依赖注入?
平常java 开发中,某个类中需要依赖其它类的方法,通常是 new 一个依赖类再调用类实例的方法,这种开发存在的问题是 new 的类实例不好统一管理spring 提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过 spring 容器帮我们 new 指定实例并且将实例注入到需要该对象的类中。依赖注入的另一种说法是“控制反转”,通俗的理解是:平常我们 new 一个实例,这个实例的控制权是我们程序员,而控制反转是指 new 实例工作不由我们程序员来做而是交给 spring 容器来做。Shiro
pache Shiro 是 Java 的一个安全框架,使用 shiro 可以非常容易的开发出足够好的应用,其不仅可以用在 JavaSE环境,也可以用在 JavaEE 环境。Shiro 可以帮助我们完成:
认证、授权、加密、会话管理、与 Web 集成、缓存等Shiro 的四种权限控制方式
1)url 级别权限控制
2)方法注解权限控制
3)代码级别权限Mybatis 中#和$的区别?
#相当于对数据 加上 双引号,$相当于直接显示数据
order by "111"   ,   order by $user_id$
#方式能够很大程度防止 sql 注入
$方式无法防止 Sql 注入
$方式一般用于传入数据库对象,例如传入表名
一般能用#的就别用$Mybatis 的编程步骤
1、创建 SqlSessionFactory
2、通过 SqlSessionFactory 创建 SqlSession
3、通过 sqlsession 执行数据库操作
4、调用 session.commit()提交事务
5、调用 session.close()关闭会话
介绍一下 Struts2
Struts2 框架是一个按照 MVC 设计模式设计的 WEB 层框架,struts2 在处理客户端请求时, 会先读取 web.xml 配置文件,根据前端控制器将符合条件的请求 分给各个不同的 Action 处理当 Action 执行完后要返回一个结果视图,这个结果视图可以跟据 struts2 的配置文件中 配置,选择转发或者重定向。
Struts2 中 Action 配置的注意事项有哪些?
1.name 包名称,在 struts2 的配置文件中,包名不能重复,name 并不是真正包名,只是为 了管理 Action
2.namespace 和 的 name 属性,决定 Action 的访问路径 (以/开始 )
3.extends 继承哪个包,通常开发中继承 struts-default 包 (struts-default 包 在 struts-default.xml 中定 义 )拦截器和过滤器有哪些区别?
拦截器是基于 java 的反射机制的
过滤器是基于函数回调
拦截器不依赖与 servlet 容器
过滤器依赖与 servlet 容器
拦截器只能对 action 请求起作用
过滤器则可以对几乎所有的请求起作用
拦截器可以访问 action 上下文、值栈里的对象
过滤器不能在 action 的生命周期中
拦截器可以多次被调用
过滤器只能在容器初始化时被调用一次Struts2 中的 # 和 % 分别是做什么的?
(1)使用#获取 context 里面数据
(2)向 request 域放值(#context 的 key 名称.域对象名称)
(3)在页面中使用 ognl 获取
(4)%在 struts2 标签中表单标签 在 struts2 标签里面使用 ognl 表达式,如果直接在 struts2 表单标签里面使用 ognl 表达式不识别,只有%之后才 会识别。Hibernate
第一步:加载 hibernate 的配置文件,读取配置文件的参数(jdbc 连接参数,数据 库方言,hbm 表与对象关 系映射文件)
第二步:创建 SessionFactory 会话工厂(内部有连接池)
第三步:打开 session 获取连接,构造 session 对象(一次会话维持一个数据连接, 也是一级缓存)
第四步:开启事务
第五步:进行操作
第六步:提交事务
第七步:关闭 session(会话)将连接释放
第八步:关闭连接池hibernate 中对象的三种状态
瞬时态(临时态、自由态):不存在持久化标识 OID,尚未关联对象
持久态:存在持久化标识 OID,与当前session有关联
脱管态(离线态、游离态):存在持久化标识 OID,但没有与当前 session 关联Hibernate 的查询方式有哪些?
HQL, QBC(命名查询), 以及使用原生 SQL 查询(SqlQuery)Hibernate 和 Mybatis 的区别?
Mybatis 优势:
1)MyBatis 可以进行更为细致的 SQL 优化,可以减少查询字段。
2)MyBatis 容易掌握,而 Hibernate 门槛较高。 Hibernate 优势:
1)Hibernate 的 DAO 层开发比 MyBatis 简单,Mybatis 需要维护 SQL 和结果映射。
2)Hibernate 对对象的维护和缓存要比 MyBatis 好,对增删改查的对象的维护要方便。
3)Hibernate 数据库移植性很好,MyBatis 的数据库移植性不好,不同的数据库需要写不同 SQL。
4)Hibernate 有更好的二级缓存机制,可以使用第三方缓存。MyBatis 本身提供的缓存机制不佳。get 和 load 的区别
(1)get 是立即加载,load 是延时加载。
(2)get 会先查一级缓存,再查二级缓存,然后查数据库;load 会先查一级缓存,如果没有找到,就创建代理对 象
(3)get 如果没有找到会返回 null,load 如果没有找到会抛出异常。如何进行 Hibernate 的优化?
(1)数据库设计调整。
(2)HQL 优化。
(3)API 的正确使用(如根据不同的业务类型选用不同的集合及查询 API)。
(4)主配置参数(日志,查询缓存,fetch_size, batch_size 等)。
(5)映射文件优化(ID 生成策略,二级缓存,延迟加载,关联优化)。
(6)一级缓存的管理。
(7)针对二级缓存,还有许多特有的策略。
(8)事务控制策略。Hibernate 延迟加载?
延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要 数据的时候,才真正执行数据加载操作。Redis 的特点?(非关系型数据库)
该软件使用 C 语言编写
本质上是一个 Key-Value 类型的内存数据库
性能非常出色,每秒可以处理超过10万次读写操作,是已知性能最快的 Key-Value DB为什么 redis 需要把所有数据放到内存中?
Redis 为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘。所以 redis 具有快速和 数据持久化的特征。如果不将数据放在内存中,磁盘 I/O 速度为严重影响 redis 的性能Redis 最适合的场景有哪些?
(1)、会话缓存(Session Cache)
(2)、全页缓存(FPC)
(3)、队列
(4)、排行榜/计数器
(5)、发布/订阅Redis 的数据结构有五种,分别是:
String——字符串
Hash——字典
List——列表
Set——集合
Sorted Set——有序集合Redis 的优缺点
a)性能极高 – Redis 能支持超过 100K+ 每秒的读写频率。
b)丰富的数据类型 – Redis 支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
c)原子 – Redis 的所有操作都是原子性的,同时 Redis 还支持对几个操作全并后的原子性执行。
d)丰富的特性 – Redis 还支持 publish/subscribe, 通知, key 过期等等特性。消息队列?
ActiveMQ、RabbitMQ、kafka。
ActiveMQ: ActiveMQ 是 Apache 下的一个子项目。 类似于 ZeroMQ,它能够以代理人和点对点的技术实现队列。同时类似 于 RabbitMQ,它少量代码就可以高效地实现高级应用场景。ActiveMQ 如果消息发送失败怎么办?
Activemq 有两种通信方式,点到点形式和发布订阅模式。 如果是点到点模式的话,如果消息发送不成功此 消息默认会保存到 activemq 服务端知道有消费者将其消费,所以此时消息是不会丢失的。Dubbo
Dubbo 的容错机制有哪些
1)Failover Cluster 模式 失败自动切换,当出现失败,重试其它服务器。(默认)
2)Failfast Cluster 快速失败,只发起一次调用,失败立即报错。 通常用于非幂等性的写操作,比如新增记录。
3)Failsafe Cluster 失败安全,出现异常时,直接忽略。 通常用于写入审计日志等操作。
4)Failback Cluster 失败自动恢复,后台记录失败请求,定时重发。 通常用于消息通知操作。
5)Forking Cluster 并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。 可通过 forks=”2”来设置最大并行数。Dubbo 的连接方式有哪些?
Dubbo 的客户端和服务端有三种连接方式,分别是:广播,直连和使用 zookeeper 注册中心。zookeeper 以及 zookeeper 的原理
ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 Google 的 Chubby 一个开源的实现, 是 Hadoop 和 Hbase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域 名服务、分布式同步、组服务等。 ZooKeeper 的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、 功能稳定的系统提供给 用户。solr
Solr 是一个独立的企业级搜索应用服务器Solr 是一个高性能,采用 Java5 开发,基于 Lucene 的全文搜索服务器。同时对其进行了扩展,提供了比 Lucene 更为丰富的查询语言,同时实现了可配置、可扩展并对查询性能 进行了优化,并且提供了一个完善的功能管理界面,是一款非常优秀的全文搜索引擎。solr 怎么设置搜索结果排名靠前?
可以设置文档中域的 boost 值,boost 值越高,计算出来的相关度得分就越高,排名也就越靠前。此方法可以把 热点商品或者推广商品的排名提高webService
WebService 是一种跨编程语言和跨操作系统平台的远程调用技术。所谓跨编程语言和跨操作平台,就是说服务端程序采用 java 编写,客户端程序则可以采用其他编程语言编写,反之亦然!跨操作系统平台则是指服务端程序和客户端程序可以在不同的操作系统上。Sql优化
1、查询语句中不要使用 *
2、尽量减少子查询,使用关联查询(left join,right join,inner  join)替代
3、or 的查询尽量用 union或者union all 代替
4、那些可以过滤掉最大数量记录的条件必须写在WHERE子句的最末尾
5.关键词%yue%,yue前面用到了“%”,查询会走全表扫描,非必要,不要在关键词前加%,
where 子句中可以对字段进行 null 值判断吗? (可以)
关于数据库查询:连接查询
内连查询和外连查询(左连接 右连接 全连接)(on代表关联条件)
select * from Name;
ID Name
1    张三
2    李四
3    王五select * from Company;
ID Name
1     银行
2     软件
4     房地产左联
select a.*, b.* from Name as a left join Company as b on a.ID=b.ID;
ID Name ID Company
1   张三    1   银行
2   李四    2   软件
3   王五    空   空右联
select a.*, b.* from Name as a right join Company as b on a.ID=b.ID;
ID Name ID Company
1   张三    1   银行
2   李四    2   软件
空  空       4   房地产全联
select a.*, b.* from Name as a full join Company as b on a.ID=b.ID;
ID Name ID Company
1   张三    1   银行
2   李四    2   软件
3   王五    空   空
空  空       4   房地产Sql优化
1、查询语句中不要使用 *
2、尽量减少子查询,使用关联查询(left join,right join,inner  join)替代
3、or 的查询尽量用 union或者union all 代替
4、那些可以过滤掉最大数量记录的条件必须写在WHERE子句的最末尾
5.关键词%yue%,yue前面用到了“%”,查询会走全表扫描,非必要,不要在关键词前加%Sql查询语句
CREATE TABLE emp(empno INT,ename VARCHAR(50),job   VARCHAR(50),mgr    INT,hiredate DATE,sal      DECIMAL(7,2),comm     DECIMAL(7,2),deptno   INT
) ;
CREATE TABLE dept(deptno        INT,dname       VARCHAR(14),loc         VARCHAR(13)
);INSERT INTO emp VALUES(7369,'SMITH','CLERK',7902,'1980-12-17',800,NULL,20);
INSERT INTO emp VALUES(7499,'ALLEN','SALESMAN',7698,'1981-02-20',1600,300,30);INSERT INTO dept VALUES(10, 'ACCOUNTING', 'NEW YORK');
INSERT INTO dept VALUES(20, 'RESEARCH', 'DALLAS');-- 单行子查询(> < >= <= = <>)-- 查询出高于10号部门的平均工资的员工信息1.查询出10号部门的平均工资SELECT AVG(sal) FROM emp WHERE deptno = 10;2.查询出高于10号部门平均工资的员工信息SELECT * FROM emp WHERE sal > (SELECT AVG(sal) FROM emp WHERE deptno = 10);
-- 多行子查询(in  not in any all)    >any  >all-- 查询出比10号部门任何员工薪资高的员工信息1. 查询出10号部门的所有工资信息SELECT sal FROM emp WHERE deptno=10;2.得出结果SELECT * FROM emp WHERE sal >ALL(SELECT sal FROM emp WHERE deptno=10); -- 多列子查询(实际使用较少)   in-- 和10号部门同名同工作的员工信息1.查出10号部门员工名字和工作信息SELECT ename,job FROM emp WHERE deptno=10;2. 得出结果:SELECT * FROM emp WHERE (ename,job) IN
(SELECT ename,job FROM emp WHERE deptno=10) AND deptno!=10;
-- Select接子查询-- 获取员工的名字和部门的名字1.查出员工的名字和部门编号信息SELECT ename,deptno FROM emp;2.得出结果SELECT ename,(SELECT dname FROM dept WHERE dept.deptno=emp.deptno) FROM emp;
-- from后面接子查询-- 查询emp表中经理信息1.查询出所有经理的IDSELECT DISTINCT mgr FROM emp;2. 查出经理的信息,只要id在第一步的查询结果中就可以了SELECT * FROM emp,(SELECT DISTINCT mgr FROM emp) mgrs
WHERE emp.empno = mgrs.mgr;
-- where 接子查询-- 薪资高于10号部门平均工资的所有员工信息1.查询出10号部门的平均工资SELECT AVG(sal) FROM emp WHERE deptno=10;2.得出结果:SELECT * FROM emp WHERE sal > (SELECT AVG(sal) FROM emp WHERE deptno=10);
-- having后面接子查询-- 有哪些部门的平均工资高于30号部门的平均工资1.30号部门的平均工资SELECT AVG(sal) FROM emp WHERE deptno=30;2. 统计所有部门的平均工资SELECT deptno,AVG(sal) FROM emp GROUP BY deptno ;3. 得出最终的结果SELECT deptno,AVG(sal) FROM emp GROUP BY deptno HAVING AVG(sal) >
(SELECT AVG(sal) FROM emp WHERE deptno=30);-- 工资>JONES工资的员工信息1.查处JONES的工资信息SELECT sal FROM emp WHERE ename='JONES';2.得出结果SELECT * FROM emp WHERE sal > (SELECT sal FROM emp WHERE ename='JONES');
-- 查询与SCOTT同一个部门的员工1.查处SCOTT的部门编号SELECT deptno FROM emp WHERE ename = 'SCOTT';2.得出结果SELECT * FROM emp WHERE deptno =
(SELECT deptno FROM emp WHERE ename = 'SCOTT');
-- 工资高于30号部门所有人的员工信息1.得出30号部门的最大工资SELECT MAX(sal) FROM emp WHERE deptno = 30;2.得出结果SELECT * FROM emp WHERE sal > (SELECT MAX(sal) FROM emp WHERE deptno = 30);
-- 查询工作和工资与MARTIN完全相同的员工信息1.查处MARTIN的工作和工资SELECT job,sal FROM emp WHERE ename='MARTIN';2.得出结果SELECT * FROM emp WHERE (job,sal) IN
(SELECT job,sal FROM emp WHERE ename='MARTIN');
-- 有两个以上直接下属的员工信息1.查出emp表中mgr信息SELECT mgr FROM emp;2.分组统计mgr的信息SELECT mgr,COUNT(*) FROM emp GROUP BY mgr HAVING COUNT(*)>2;3.得出结果SELECT * FROM emp e1 WHERE e1.empno
IN (SELECT e2.mgr FROM emp e2 GROUP BY e2.mgr HAVING COUNT(*)>2);
-- 查询员工编号为7788的员工名称,员工工资,部门名称,部门地址1.将员工表和部门表链接起来SELECT * FROM emp ,dept WHERE emp.deptno = dept.deptno;2.得出ID为7788的所有信息SELECT * FROM emp ,dept WHERE emp.deptno = dept.deptno AND empno=7788;3.只显示其中的需要的信息SELECT ename,sal ,dname, loc FROM emp ,dept
WHERE emp.deptno = dept.deptno AND empno=7788;-- 1. 查询出高于本部门平均工资的员工信息1. 分组统计每个部门的平均工资SELECT deptno,AVG(sal) FROM emp GROUP BY deptno;2. 得出相应的结果SELECT * FROM emp e1 WHERE e1.sal > (SELECT AVG(e2.sal)
FROM emp e2 WHERE e1.deptno=e2.deptno  GROUP BY e2.deptno);-- 1. 列出达拉斯加工作的人中,比纽约平均工资高的人0. 查处DALLAS 的部门编号SELECT deptno FROM dept WHERE loc='DALLAS';1.查处达拉斯工作的人的信息SELECT * FROM emp WHERE deptno = (SELECT deptno FROM dept WHERE loc='DALLAS');2. 查处纽约的部门编号SELECT deptno FROM dept WHERE loc='NEW YORK';3. 查村纽约平均工资SELECT AVG(sal) FROM emp WHERE deptno =
(SELECT deptno FROM dept WHERE loc='NEW YORK');4.得出结果:SELECT * FROM emp WHERE deptno = (SELECT deptno FROM dept WHERE loc='DALLAS')AND sal > (SELECT AVG(sal) FROM emp WHERE deptno =
(SELECT deptno FROM dept WHERE loc='NEW YORK'));-- 2. 查询7369员工编号,姓名,经理编号和经理姓名SELECT e1.empno,e1.ename,e1.mgr,mgrtable.ename
FROM emp e1,emp mgrtable WHERE e1.mgr = mgrtable.empno; -- 3. 查询出各个部门薪水最高的员工所有信息1.分组统计每个部门员工最高的薪资是多少SELECT MAX(sal),deptno FROM emp GROUP BY deptno;2.算出结果SELECT * FROM emp e1 WHERE e1.sal =
(SELECT MAX(sal) FROM emp e2 WHERE e1.deptno = e2.deptno GROUP BY deptno);Select  ut  from user limit(0,3);  //索引从0开始查3条//索引按数据库显示
Select  ut  from user limit(3,3);  //索引从3开始查3条//索引按数据库显示
面试被问到的问题关于单例模式
单例模式,是一种常用的软件设计模式。在它的核心结构只包含一个被称为单例的特殊类。单例模式可以保证系统中,一个类只有一个对象实例。提供了对唯一实例的受控访问(优)
防止其它对象对自己的实例化确保所有的对象都访问一个实例(优)
单例模式,不是抽象的所以可扩展性比较差(缺)
使用场景: 1、统计当前在线人数(网站计数器):用一个全局对象来记录。
1.需要频繁实例化然后销毁的对象。
2.创建对象时耗时过多或者耗资源过多,但又经常用到的对象。
3.有状态的工具类对象。
4.频繁访问数据库或文件的对象。 工厂模式
它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过一个共同的接口来指向新创建的对象。
优点:
1、一个调用者想创建一个对象,只要知道其名称就可以了。
2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
3、屏蔽产品的具体实现,调用者只关心产品的接口。
缺点:
每次增加产品,需要增加一个具体类和对象实现工厂,使系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
使用场景:
1、日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。
2、数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。
3、设计一个连接服务器的框架,需要三个协议,"POP3"、"IMAP"、"HTTP",可以把这三个作为产品类,共同实现一个接口。线程的状态
1. 新建(NEW):新创建了一个线程对象。
2. 可运行(RUNNABLE):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权 。
3. 运行(RUNNING):可运行状态(runnable)的线程获得了cpu 时间片(timeslice) ,执行程序代码。
4. 阻塞(BLOCKED):阻塞状态是指线程因为某种原因放弃了cpu 使用权,也即让出了cpu timeslice,暂时停止运行。直到线程进入可运行(runnable)状态,才有机会再次获得cpu timeslice 转到运行(running)状态。阻塞的情况分三种:
(一). 等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue)中。
(二). 同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。
(三). 其他阻塞:运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。
5. 死亡(DEAD):线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。mysql存储引擎
InnoDB
是事务型数据库的首选引擎,支持事务安全表(ACID),支持行锁定和外键,InnoDB 是默认的 MySQL引擎
MyISAM 存储引擎
MyISAM 基于 ISAM 存储引擎,并对其进行扩展。它是在 Web、数据仓储和其他应用环境下最常使用的存储引擎之一。MyISAM 拥有较高的插入、查询速度,但不支持事物垃圾回收机制
理论上 Java 有垃圾回收机制不会存在内存泄露问题
在实际开发中,可能会存在无用但可达的对象,这些对象不能被 GC 回收,因此也会导致内存泄露的发生Springmvc
(1)控制反转(IOC):传统的 java 开发模式中,当需要一个对象时,我们会自己创建一个对象,而在 Spring 开发模式中,Spring 容器使用工厂模式创建了所需要对象,直接调用提供的对象即可,这就是控制反转的思想。
(2)实例化一个 java 对象有三种方式:使用类构造器,使用静态工厂方法,使用实例工厂方法。当使用 spring 时我们不需要关心通过何种方式实例化一个对象,spring 通过控制反转机制自动为我们实例化一个对象。(2)依赖注入(DI):Spring 使用 Java Bean 对象的 Set 方法和带参数的构造方法为我们在创建所需对象时将其属性自动设置所需要的值的过程就是依赖注入的基本思想。(3)面向切面编程(AOP):在面向对象编程(OOP)思想中,我们将事物纵向抽象成一个个的对象。而在面向切面编程中,我们将一个个对象某些类似的方面横向抽象成一个切面,对这个切面进行一些如权限验证,事物管理,记录日志等公用操作处理的过程就是面向切面编程的思想。Sql注入
采用预编译语句集,它内置了处理SQL注入的能力,只要使用它的setXXX方法传值即可。
使用正则表达式过滤传入的参数
private String CHECKSQL = “^(.+)\\sand\\s(.+)|(.+)\\sor(.+)\\s$”;
字符串过滤
String inj_str = "'|and|exec|insert|select|delete|update|
jsp中调用该函数检查是否包函非法字符
JSP页面判断代码:
使用javascript在客户端进行不安全字符屏蔽基本数据类型的字节
byte     1字节
short    2字节
int      4字节
long     8字节
char     2字节(C语言中是1字节)可以存储一个汉字
float    4字节
double   8字节
boolean  false/true(理论上占用1bit,1/8字节,实际处理按1byte处理)       Redis 的存储类型
String
Hash
List
Set
有序set集合SpringMVC流程(手写)
1、  用户发送请求至前端控制器DispatcherServlet。
2、  DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、  处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、  DispatcherServlet调用HandlerAdapter处理器适配器。
5、  HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6、  Controller执行完成返回ModelAndView。
7、  HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
8、  DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
9、  ViewReslover解析后返回具体View。
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、 DispatcherServlet响应用户。Thread类中有哪些方法
Start
run
sleep
yield
join
interrupt
Interrupted
Stop
DestroyServle生命周期
1.加载和实例化
2.初始化(init)
3.请求处理
4.服务终止数据库索引
因为数据中的记录很多,为了方便我们查找,提高查询的效率
索引的原理:对要查询的字段建立索引就是把该字段按照一定的方式排序
一、为什么要创建索引呢(优点)?
这是因为,创建索引可以大大提高系统的性能。
创建唯一性索引可以保证数据库表中每一行数据的唯一性。
可以加快数据的检索速度
可以加速表和表之间的连接,实现数据的完整性方面特别有意义。
使用分组和排序子句进行数据检索时,可以显著减少查询中分组和排序的时间。
通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。二、建立方向索引的不利因素(缺点)
表中的每一个列都增加索引,创建索引和维护索引要耗费时间
索引需要占物理空间,如果要建立聚簇索引,那么需要的空间就会更大
对表中数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护索引种类
普通索引:仅加速查询(MySQL中基本索引类型,没有什么限制,允许在定义索引的列中插入重复值和空值,纯粹为了查询数据更快一点。)
唯一索引:加速查询 + 列值唯一(可以有null)
主键索引:加速查询 + 列值唯一(不可以有null)+ 表中只有一个。
组合索引:多列值组成一个索引,专门用于组合搜索,其效率什么是存储过程,使用存储过程的好处?(2017-11-25-wzz)
存储过程(Stored Procedure )是一组为了完成特定功能的 SQL 语句集,经编译后存储在数据库中。
用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据库中的一个重要对
象,任何一个设计良好的数据库应用程序都应该用到存储过程。
优点:
(1)允许模块化程序设计,就是说只需要创建一次过程,以后在程序中就可以调用该过程任意次。
(2)允许更快执行,如果某操作需要执行大量 SQL 语句或重复执行,存储过程比 SQL 语句执行的要快。
(3)减少网络流量,例如一个需要数百行的 SQL 代码的操作有一条执行语句完成,不需要在网络中发
送数百行代码。
(3)更好的安全机制,对于没有权限执行存储过程的用户,也可授权他们执行存储过程拦截器和过滤器有哪些区别?
拦截器是基于 java 的反射机制的
过滤器是基于函数回调
拦截器不依赖与 servlet 容器
过滤器依赖与 servlet 容器
拦截器只能对 action 请求起作用
过滤器则可以对几乎所有的请求起作用
拦截器可以访问 action 上下文、值栈里的对象
过滤器不能在 action 的生命周期中
拦截器可以多次被调用
过滤器只能在容器初始化时被调用一次Jdk和jre的区别
JRE是java运行时环境,包含了java虚拟机,java基础类库
JDK是java开发工具包,是程序员使用java语言编写java程序的开发工具包Spring事物的隔离级别
脏读:一个事务读到了另一个事务未提交的数据
不可重复读:一个事务读到了另一个事务已提交的数据,造成前后两次查询结果不一致
幻读:一个事务读到了另一个事务insert的数据 ,造成前后查询结果不一致 。
写:丢失更新。####隔离级别
读未提交
> 引发问题: 脏读
读已提交
> 解决: 脏读 , 引发: 不可重复读
可重复读
> 解决: 脏读 、 不可重复读 , 未解决: 幻读
可串行化
> 解决: 脏读、 不可重复读 、 幻读。
mySql 默认的隔离级别是  可重复读
Oracle 默认的隔离级别是  读已提交两个HashMap里面的内容是否相等?
重写hashcode和equals方法来判断对象是否相等。
Map<String, Integer> map1 = new HashMap<String, Integer>();
Map<String, Integer> map2 = new HashMap<String, Integer>();
比较方法一:map1.equals(map2))
比较方法二:Iterator<Entry<String, Integer>> it1 = map1.entrySet().iterator();while(it1.hasNext()){Entry<String, Integer> entry1 = it1.next();Integer integer2 = tempMap.get(entry1.getKey());if(integer2 == null||(!integer2.equals(entry1.getValue()))){b = false;break;}}Hashmap的数据结构
HashMap采取数组加链表的存储方式来实现spring的controller默认是单例还是多例
曾经面试的时候有面试官问我spring的controller是单例还是多例,结果我傻逼的回答当然是多例,要不然controller类中的非静态变量如何保证是线程安全的,这样想起似乎是对的,但是不知道(主要是我没看过spring的源码,不知道真正的内在意图)为什么spring的controller是单例的。
先看看spring的bean作用域有几种,分别有啥不同。
spring bean作用域有以下5个:
singleton:单例模式,当spring创建applicationContext容器的时候,spring会欲初始化所有的该作用域实例,加上lazy-init就可以避免预处理;
prototype:原型模式,每次通过getBean获取该bean就会新产生一个实例,创建后spring将不再对其管理;
====下面是在web项目下才用到的===
request:搞web的大家都应该明白request的域了吧,就是每次请求都新产生一个实例,和prototype不同就是创建后,接下来的管理,spring依然在监听
session:每次会话,同上
global session:全局的web域,类似于servlet中的application
好了,上面都说了spring的controller默认是单例,那很自然就是singleton了。
再看一个例子,看看单例会不会有我说的那种问题(就是类中定义的非静态变量线程安全问题),当然下面这个例子我是实验过的, 要不然也不敢发出来
为什么spring要默认是单例呢?原因有二:
1、为了性能。
2、不需要多例。
1、这个不用废话了,单例不用每次都new,当然快了。
2、不需要实例会让很多人迷惑,因为spring mvc官方也没明确说不可以多例。
我这里说不需要的原因是看开发者怎么用了,如果你给controller中定义很多的属性,那么单例肯定会出现竞争访问了。
因此,只要controller中不定义属性,那么单例完全是安全的。下面给个例子说明下:消息中间件(activatemq)
用来提升系统性能:
简单理解就是应用不用关心处理结果的部分,可通过消息中间件异步通知消息。然后其他应用服务器接收到消息后,慢慢处理。业务场景说明:(activatemq)
消息队列在大型电子商务类网站,如京东、淘宝、去哪儿等网站有着深入的应用,
队列的主要作用是消除高并发访问高峰,加快网站的响应速度。
在不使用消息队列的情况下,用户的请求数据直接写入数据库,在高并发的情况下,会对数据库造成巨大的压力,同时也使得系统响应延迟加剧。
在使用队列后,用户的请求发给队列后立即返回,
例如: 当然不能直接给用户提示订单提交成功,京东上提示:您“您提交了订单,请等待系统确认”),
再由消息队列的消费者进程从消息队列中获取数据,异步写入数据库。
由于消息队列的服务处理速度远快于数据库,因此用户的响应延迟可得到有效改善。
1.异步处理
场景说明:用户注册后,需要发注册邮件和注册短信。
传统的做法有两种1.串行的方式;2.并行方式。
(1)串行方式:将注册信息写入数据库成功后,发送注册邮件,再发送注册短信。以上三个任务全部完成后,返回给客户端。
(2)并行方式:将注册信息写入数据库成功后,发送注册邮件的同时,发送注册短信。以上三个任务完成后,返回给客户端。与串行的差别是,并行的方式可以提高处理的时间。
假设三个业务节点每个使用50毫秒钟,不考虑网络等其他开销,则串行方式的时间是150毫秒,并行的时间可能是100毫秒。
2.2.    应用解耦
场景说明:用户下单后,订单系统需要通知库存系统。传统的做法是,订单系统调用库存系统的接口。如下图:传统模式的缺点:
1)  假如库存系统无法访问,则订单减库存将失败,从而导致订单失败;
2)  订单系统与库存系统耦合;
如何解决以上问题呢?引入应用消息队列后的方案,如下图:1:订单系统:用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功,请等待物流配送。
2:库存系统:订阅下单的消息,采用拉/推的方式,获取下单信息,库存系统根据下单信息,进行库存操作。
3:假如:在下单时库存系统不能正常使用。也不影响正常下单,
因为下单后,订单系统写入消息队列就不再关心其他的后续操作了。实现订单系统与库存系统的应用解耦。
2.3.    流量削锋
流量削锋也是消息队列中的常用场景,一般在秒杀或团抢活动中使用广泛。
应用场景:秒杀活动,一般会因为流量过大,导致流量暴增,应用容易挂掉。为解决这个问题,一般需要在应用前端加入消息队列。可以控制活动的人数.
可以缓解短时间内高流量压垮应用;
用户的请求,服务器接收后,首先写入消息队列。假如消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面;
秒杀业务根据消息队列中的请求信息,再做后续处理。
2.4.    消息通讯
消息通讯是指,消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯。比如实现点对点消息队列,或者聊天室等。
点对点通讯:客户端A和客户端B使用同一队列,进行消息通讯。
聊天室通讯:客户端A,客户端B,客户端N订阅同一主题,进行消息发布和接收。实现类似聊天室效果。以上实际是消息队列的两种消息模式,点对点或发布订阅模式。什么是Docker?
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。Docker的应用场景
Web 应用的自动化打包和发布。
自动化测试和持续集成、发布。
在服务型环境中部署和调整数据库或其他的后台应用。
从头编译或者扩展现有的OpenShift或Cloud Foundry平台来搭建自己的PaaS环境。为什么要使用Docker
容器除了运行其中应用外,基本不消耗额外的系统资源,使得应用的性能很高,同时系统的开销尽量小。传统虚拟机方式运行 10 个不同的应用就要起 10 个虚拟机,而Docker 只需要启动 10 个隔离的应用即可。
具体说来,Docker 在如下几个方面具有较大的优势。
1、更快速的交付和部署
对开发和运维人员来说,最希望的就是一次创建或配置,可以在任意地方正常运行。
开发者可以使用一个标准的镜像来构建一套开发容器,开发完成之后,运维人员可以直接使用这个容器来部署代码。 Docker 可以快速创建容器,快速迭代应用程序,并让整个过程全程可见,使团队中的其他成员更容易理解应用程序是如何创建和工作的。 Docker 容器很轻很快!容器的启动时间是秒级的,大量地节约开发、测试、部署的时间。
2、更高效的虚拟化
Docker 容器的运行不需要额外的 hypervisor 支持,它是内核级的虚拟化,因此可以实现更高的性能和效率。
3、更轻松的迁移和扩展
Docker 容器几乎可以在任意的平台上运行,包括物理机、虚拟机、公有云、私有云、个人电脑、服务器等。 这种兼容性可以让用户把一个应用程序从一个平台直接迁移到另外一个。
4、更简单的管理
使用 Docker,只需要小小的修改,就可以替代以往大量的更新工作。所有的修改都以增量的方式被分发和更新,从而实现自动化并且高效的管理。Xml的解析方式有哪些
1.DOM生成和解析XML文档
为 XML 文档的已解析版本定义了一组接口。解析器读入整个文档,然后构建一个驻留内存的树结构,然后代码就可以使用 DOM 接口来操作这个树结构。
优点:整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能;
缺点:将整个文档调入内存(包括无用的节点),浪费时间和空间;
场景:一旦解析了文档还需多次访问这些数据;硬件资源充足(内存、CPU)。2.SAX生成和解析XML文档
为解决DOM的问题,出现了SAX事件驱动。当解析器发现元素开始、元素结束、文本、文档的开始或结束等时,发送事件,程序员编写响应这些事件的代码,保存数据。
优点:不用事先调入整个文档,占用资源少;SAX解析器代码比DOM解析器代码小,适于Applet,下载。
缺点:不是持久的;事件过后,若没保存数据,那么数据就丢了;无状态性;从事件中只能得到文本,但不知该文本属于哪个元素;
场景:Applet;只需XML文档的少量内容,很少回头访问;机器内存少;转发和重定向的区别
重定向:以前的request中存放的变量全部失效,并进入一个新的request作用域。
转发:以前的request中存放的变量不会失效,就像把两个页面拼到了一起。什么是跨域为什么会引起跨域?
跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制。
解决办法:
1,第一种解决方法
后台代码在被请求的Servlet中添加Header设置:
response.setHeader("Access-Control-Allow-Origin", "*");
PrintWriter out =null;
try
{
out = response.getWriter();
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
out.print("{'status':'ok'}");
out.flush();
out.close();
Access-Control-Allow-Origin这个Header在W3C标准里用来检查该跨域请求是否可以被通过,如果值为*则表明当前页面可以跨域访问。默认的情况下是不允许的。
在前端JS中需要向Servlet发出请求,请求代码如下所示:$.ajax({url: "your url",type:"get or post",dataType:"json",data:{....},success:function(data){...}
第二种解决方法
通过jsonp跨域请求的方式。JSONP和JSON虽然只有一个字母的区别,但是他们完全就是两回事,很多人很容易把他们搞混。JSON是一种数据交换的格式,而JSONP则是一种非官方跨域数据交互协议。
首先来说一下前端JS是怎么发送请求。代码如下所示:$.ajax({url:"your url",type:"get or post",async:false,dataType : "jsonp",//服务端用于接收callback调用的function名的参数jsonp:"callbackparam",//callback的function名称jsonpCallback:"success_jsonpCallback",success:function(data){console.log(data);},error:function(data){console.log(data);}});
这里的callbackparam和success_jsonpCallback可以理解为发送的data数据的键值对,可以自定义,但是callbackparam需要和后台约定好参数名称,因为后台需要获取到这个参数里面的值(即success_jsonpCallback)。
4,下面,最重要的来了,后台怎么样获取和返回数据呢。代码如下所示:
PrintWriter out =null;
String callback=req.getParameter("callbackparam");
String json=callback+"({'status':'ok'})";
try
{
out = resp.getWriter();
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
out.print(json);
out.flush();
out.close();
首先需要获取参数名为callbackparam的值,这里获取到的值就是“success_jsonpCallback”。然后将这个值加上一对小括号。小括号里放入你需要返回的数据内容,比如这里我返回一个JSON对象。当然你也可以返回其他对象,比如只返回一个字符串类型数据也可以。最后前端JS返回的数据就是这样的:
success_jsonpCallback({'status':'ok'})
浏览器会自动解析为json对象,这时候你只需要在success回调函数中直接用data.status就可以了。springboot
Spring 诞生时是 Java 企业版(也称之为J2EE)属于轻量级代替品
spring开发为企业提供了一种相对简单的办法通过依赖注入和面向切面编程利用简单的java对象实现了EJB功能
虽然 Spring 的组件代码是轻量级的,但它的配置却是重量级的
一开始,Spring 用 XML 配置,而且是很多 XML 配置Spring 2.5 引入了基于注解的组件扫描,这消除了大量针对应用程序自身组件的显式 XML 配置。Spring 3.0 引入了基于 Java 的配置,这是一种类型安全的可重构配置方式,可以代替 XML。这些配置都代表了开发时的损耗。因为在思考 Spring 特性配置和解决业务问题之间需要进行思维切换,所以写配置挤占了写应用程序逻辑的时间。和所有框架一样,Spring 实用,但与此同时它要求的回报也不少。Spring Boot 是 Spring 社区较新的一个项目。该项目的目的是帮助开发者更容易的创建基于 Spring 的应用程序和服务,让更多人的人更快的对 Spring 进行入门体验,为 Spring 生态系统提供了一种固定的、约定优于配置风格的框架。
Spring Boot 具有如下特性:
(1)为基于 Spring 的开发提供更快的入门体验
(2)开箱即用,没有代码生成,也无需 XML 配置。同时也可以修改默认值来满足特定的需求。
(3)提供了一些大型项目中常见的非功能性特性,如嵌入式服务器、安全、指标,健康检测、外部配置等。
(4)Spring Boot 并不是不对 Spring 功能上的增强,而是提供了一种快速使用 Spring 的方式。JMS(ActiveMQ)
1.2.1什么是JMS
JMS(Java Messaging Service)是Java平台上有关面向消息中间件的技术规范,
它便于消息系统中的Java应用程序进行消息交换,并且通过提供标准的产生、发送、
接收消息的接口简化企业应用的开发。
JMS 定义了五种不同的消息正文格式,以及调用的消息类型,允许你发送并接收以一
些不同形式的数据,提供现有消息格式的一些级别的兼容性。
· TextMessage--一个字符串对象
· MapMessage--一套名称-值对
· ObjectMessage--一个序列化的 Java 对象
· BytesMessage--一个字节的数据流
· StreamMessage -- Java 原始值的数据流1.2.2 JMS消息传递类型
对于消息的传递有两种类型:
一种是点对点的,即一个生产者和一个消费者一一对应;
另一种是发布/ 订阅模式,即一个生产者产生消息并进行发送后,可以由多个消费者进
行接收。Freemark
网页静态化技术和缓存技术的共同点都是为了减轻数据库的访问压力,
但是具体的应用场景不同,缓存比较适合小规模的数据,而网页静态
化比较适合大规模且相对变化不太频繁的数据。如果将网页以纯静态化的形式展现,就可以使用Nginx这样的高性能的web服务器来部署。
Nginx可以承载5万的并发,而Tomcat只有几百1.2什么是 Freemarker
FreeMarker 是一个用 Java 语言编写的模板引擎,它基于模板来生成文本输出。FreeMarker与 Web
容器无关,即在 Web 运行时,它并不知道 Servlet 或 HTTP。它不仅可以用作表现层的实现技术,而且还可以用于生成 XML,JSP 或 Java 等Solr(比较优秀的一款全文搜索引擎)
独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口。用户可以通过http请求,向搜索引擎服务器提交一定格式的XML文件,生成索引;也可以通过Http Get操作提出查找请求,并得到XML格式的返回结果。
(配置信息)
name:指定域的名称
type:指定域的类型
indexed:是否索引
stored:是否存储
required:是否必须
multiValued:是否多值
特点:
Solr是一个高性能,采用Java5开发,
Solr基于Lucene的全文搜索服务器。同时对其进行了扩展,提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展并对查询性能进行了优化,并且提供了一个完善的功能管理界面,是一款非常优秀的全文搜索引擎。原理:
文档通过Http利用XML 加到一个搜索集合中。
Solr查询该集合也是通过http收到一个XML/JSON响应来实现。它的主要特性包括:高效、灵活的缓存功能,垂直搜索功能,高亮显示搜索结果,通过索引复制来提高可用性,提供一套强大Data Schema来定义字段,类型和设置文本分析,提供基于Web的管理界面等。SpringSecurity
我们用这个主要是用于安全认证服
1.修改 spring 配置文件spring-security.xml
2.可以通过security="none"  设置此资源不被拦截.
3.如果你没有设置登录页security="none",就会出现无法访问页面等问题
intercept-url 表示拦截页面
/*  表示的是该目录下的资源,只包括本级目录不包括下级目录
/** 表示的是该目录以及该目录下所有级别子目录的资源
form-login  为开启表单登陆Dubbo
Dubbox简介
远程服务调用的分布式框架
节点角色说明:
 Provider: 暴露服务的服务提供方。
 Consumer: 调用远程服务的服务消费方。
 Registry: 服务注册与发现的注册中心。
 Monitor: 统计服务的调用次调和调用时间的监控中心。
 Container: 服务运行容器。
调用关系说明:
 0. 服务容器负责启动,加载,运行服务提供者。
 1. 服务提供者在启动时,向注册中心注册自己提供的服务。
 2. 服务消费者在启动时,向注册中心订阅自己所需的服务。
 3. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推
送变更数据给消费者。
 4. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,
如果调用失败,再选另一台调用。
 5. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计
数据到监控中心。Zookeeper
zookeeper 注册中心。注册中心负责服务地址的注册与查找,相当于目录服务,
服务提供者和消费者只在启动时与注册中心交互,注册中心不转发请求,压力较小。

java面试所问到的问题和资料整理相关推荐

  1. Java面试常问计算机网络问题

    转载自   Java面试常问计算机网络问题 一.GET 和 POST 的区别 GET请注意,查询字符串(名称/值对)是在 GET 请求的 URL 中发送的:/test/demo_form.asp?na ...

  2. 指南Java面试常问问题及答案

    Java 面试常问问题及答案(非常详细) 一:java 基础 1.简述 string 对象,StringBuffer.StringBuilder 区分 string 是 final 的,内部用一个 f ...

  3. Java 面试必问题目,Java 后端校招面试题

    字节跳动一面: 自我介绍,主要讲讲做了什么和擅长什么 看你项目做 Spring 比较多, 问一下 Spring 相关的东西, IoC 是什么概念? Bean 的默认作用范围是什么?其他的作用范围? 索 ...

  4. 面试必问的 Linux 命令帮你整理好啦 (下)

    如果我说 Linux 操作系统和命令是面试必问的,你相信么?不信,我们来看看企业招聘需求: 随便在某招聘网站上搜了一下测试工程师的技能要求,基本都有 Linux 操作系统和命令的要求.说明,这个技能确 ...

  5. Java面试手册V2.0+突击V3.0知识点整理(一) 附封面图片

    虚静出内功 1. Java语言三大特性 1. 封装: 属性用来描述同一类事物的特征,方法可描述一类事物可做的操作 封装就是把属于同一类事物的共性(包括属性和方法)归到一个类中,以方便使用 概念: 封装 ...

  6. Java面试常问基础知识(持续更新)

    欢迎关注我的知乎专栏[数据池塘],专注于分享机器学习,数据挖掘相关内容:HTTPS://zhuanlan.zhihu.com/datapool 本文中的知识都是我自己或同学在面试过程中常被问到的,在此 ...

  7. java面试会问到的问题吗_[转载]java面试中经常会被问到的一些算法的问题

    Java面试中经常会被问到的一些算法的问题,而大部分算法的理论及思想,我们曾经都能倒背如流,并且也能用开发语言来实现过, 可是很多由于可能在项目开发中应用的比较少,久而久之就很容易被忘记了,在此我分享 ...

  8. java面试常问问题及答案,附源代码

    找大厂面试题,看套路!Java面试题及答案及面试解析请阅读严宏博士的Java模式或设计模式解释中的桥梁模式). 封装:一般认为封装是将数据和操作数据的方法绑定起来,数据的访问只能通过定义的界面进行.面 ...

  9. Java面试必问!javasocket服务端持久化

    前言 最近刷到了一句耐人寻味的话,"解决雪崩问题的最好办法是不发生雪崩". 不论是在硅谷互联网公司里还是在国内的互联网平台上,曾多次遇到过海量规模的交易瞬间吞噬平台的悲惨故事. 核 ...

最新文章

  1. 多角度回顾因果推断的模型方法
  2. 手把手教你发布自己的CocoaPods开源库
  3. linux python复制安装,复制一个Python全部环境到另一个环境,python另一个,导出此环境下安装的包...
  4. web前端技术亮点_Web前端开发职业技术要求规划
  5. 上传文件插件uploadify应用简单说明
  6. mysql字符集设置lampp_xampp下mariaDB数据库设置默认字符集utf8(Windows)
  7. samba服务设置与访问共享文件夹
  8. hp打印机装不上服务器系统,winxp系统无法安装HP打印机驱动程序如何解决
  9. 阿里云 centos7.2 安装openstack报错
  10. PowerDesigner下载安装破解
  11. html5读取加速度传感器,一文读懂加速度传感器
  12. excel文档插入新列报错:为了防止数据丢失,excel不能从表中移走非空单元格。
  13. 笔记本光驱位固态硬盘重装系统
  14. 读书笔记-反省使人成长
  15. 多人协同在线编辑文档软件使用体验
  16. 添加视频字幕后期制作Premiere Pro 2022中文
  17. swiper(轮播图)基本使用
  18. 使用FTP进行主机与Linux的文件传输
  19. Python中的可变对象和不可变对象
  20. 纳秒脉冲等离子体放电

热门文章

  1. KUKA机器人 - 从开机到自动运行
  2. 魔兽世界怀旧服 八区最新服务器推荐,魔兽世界怀旧服选择哪一个服务器好[多图]...
  3. 李宏毅机器学习—读书笔记
  4. 哪里有模板建站配云服务器销售,模板建站配云服务器费用
  5. Oracle Executable Binary Mismatch Detected
  6. 欧拉图简述---(一笔画问题)
  7. 汽车matlab小论文,基于matlab汽车道路模型研究论文
  8. springboot如何在接收和返回json时下划线转驼峰以及驼峰转下划线
  9. SpringMVC条件查询+分页时下一页丢失查询条件
  10. STM32SPI通信原理