Spring是什么?干什么的?怎么用?
Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架。
spring是一个万能的框架,方便解耦,开发,配置事务等等
Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。
Spring的核心机制是管理Bean
SpringMVC是什么?干什么的?怎么用?
SpringMVC是Spring框架的一个模块,使用Spring进行WEB开发时,可以使用Spring MVC框架。
web.xml中配置DisapatcherServlet,编写配置文件xxx-servlet.xml
mybatis是什么?干什么的?怎么用?
MyBatis 是一个持久层框架,用于 SQL查询、存储过程以及高级映射。两种使用方式:xml和注解。
Springboot是什么?干什么的/优点?
Spring Boot是用来简化Spring应用初始搭建以及开发过程的全新框架,自动配置spring,maven管理,无需部署,快速构建spring项目。
Spring secuity是什么?干什么的?
spring secuity是一个安全框架,用于授权和认证。
Redis 是一个开源的,高性能的 key-value 数据库。数据缓存在内存中,但是可以持久化到磁盘。
Redis能干什么?
内存存储、持久化,内存是断电即失的,所以需要持久化(RDB、AOF)高效率、用于高速缓冲发布订阅系统地图信息分析计时器、计数器(eg:浏览量)等等Redis特性
多样的数据类型持久化集群事务HTML、css、JavaScript
HTML 定义网页的内容CSS 规定网页的布局JavaScript 是基于浏览器的客户端脚本,对网页行为进行编程ajax
AJAX 是一种可以局部刷新网页的技术。通过 HTTP 请求加载远程数据。即可发送异步的ajax请求等。(客户端进行ajax操作,服务器返回json数据)
ajax三要素:异步交互、XMLHttpRequest对象、回调函数。
Web service 是什么?如何使用?
基于 Web 的服务:服务器端整出一些资源让客户端应用访问。比如天气预报数据。
编写服务端和客户端,进行发布访问 WebService Client–>(访问) WebServiceServer
webservice的优缺点?
==优:==1.采用xml支持跨平台远程调用.;2、基于http的soap协议,可跨越防火墙;3.支持面向对象开发;4.有利于软件和数据的重用,实现松耦合。
==缺:==1、数据传输的效率不高;2、单机应用程序;3、局域网的同构应用程序。
实现webservice的框架?
目前开发Web Service的几个框架,分别为Axis,axis2,Xfire,CXF以及JWS。
客户端调用WebService的方式: 1.通过wximport生成代码 2.通过客户端编程方式 3.通过ajax调用方式 4.通过 URL Connection 方式调用
服务端使用cfx+spring和注解实现服务端发布
NIO API
什么是Java NIO,它的工作原理是什么?
NIO是非阻塞式I/O模式,采用了通道和缓冲区的形式来进行处理数据。
专门的线程来处理 IO 事件,并负责分发。 事件驱动机制为:事件到的时候触发,而不是同步的去监视事件。
1、简单易学、有丰富的类库 2、面向对象(Java最重要的特性,让程序耦合度更低,内聚性更高) 3、与平台无关性(JVM是Java跨平台使用的根本) 4、可靠安全 5、支持多线程
面向过程:面向过程性能比面向对象高。
面向对象:面向对象易维护,易复用,易扩展。
GET就是获取资源,POST就是创建资源,PUT就是更新资源,DELETE就是删除资源。
静态变量、静态方法、静态块、静态内部类、静态导包。
访问权限 类 包 子类 其他包
public ∨ ∨ ∨ ∨ (对任何人都是可用的)
protect ∨ ∨ ∨ × (继承的类可以访问以及和private一样的权限)
default ∨ ∨ × × (包访问权限,即在整个包内均可被访问)
private ∨ × × × (作用于当前类)
即:类的成员不写访问修饰符时默认为default。默认对于同一个包中的其他类相当于公开(public),对于不是同一个包中的其他类相当于私有(private)。
Java中,外部类的修饰符只能是public或默认,类的成员(包括内部类)的修饰符可以是以上四种。
4种:
new创建新对象通过反射机制采用clone机制通过序列化机制Map:key-value key不可以重复,value可以重复
HashMap:无序,key不可以重复(hashCode和equals),key允许为空
TreeMap:按照key进行升序排序,key不可重复(与compareTo方法有关)
HashTable:与HashMap相近,区别在于HashTable中的方法基本都是同步方法,key不允许null,直接会抛出NullPointException
遍历map的方式:
public class Example02 { public static void main(String[] args) { Map map = new HashMap(); map.put("1", "老大"); map.put("2", "老二"); map.put("3", "老三"); Set keySet = map.keySet(); //获取键的集合 Iterator it = keySet.iterator(); //迭代键的集合 while(it.hasNext()) { Object key = it.next(); Object value = map.get(key); //获取每个键所对应的值 System.out.println(key+" : "+value); } } }相同点: 实现原理相同,功能相同,底层都是哈希表结构,查询速度快,在很多情况下可以互用 不同点: 1、Hashtable是早期提供的接口,HashMap是新版JDK提供的接口。 2、Hashtable继承Dictionary类,HashMap实现Map接口。 3、Hashtable线程安全,HashMap线程非安全。 4、Hashtable不允许null值,HashMap允许null值。
Hashtable: 线程安全、效率低。(内部有上锁的控制synchronized)
HashMap:线程不安全、效率高。(多个线程同时操作这一个HashMap,可能出现线程不安全的情况,甚至出现死锁)
ConcurrentHashMap:分段锁,将锁的力度变小,兼顾两者,保证线程安全和性能
(老版本升级,兼容新版本时)
hashCode相等,equals也不一定相等, 两个类也不一定相等
equals相同, 说明是同一个对象, 那么hashCode一定相同
ArrayList底层的实现是Array, 数组扩容实现,搜索和读取数据是很快。
LinkList是一个双链表,在添加和删除元素时性能高.但在get与set方面弱于ArrayList。
Vector 和ArrayList类似,但属于强同步类。但ArrayList是线程不安全的,Vector是线程安全的(Vector的关键方法都使用了synchronized修饰)。扩容时候ArrayList扩0.5倍,Vector扩1倍
区别:
执行速度不同:string最慢。
线程安全不同:StringBuffer是线程安全的,StringBuilder是线程不安全的
==本质区别:==String类是不可变类,值不可变的,StringBuffer、StringBuilder是可变类。
联系:StringBuffer、StringBuilder和String一样,也用来代表字符串。
String类的场景:在字符串不经常变化的场景中
StringBuffer类的场景:在频繁进行字符串运算,并且运行在多线程环境中。
StringBuilder类的场景:在频繁进行字符串运算,并且运行在单线程的环境中。
继承Thread类来创建线程:
a.首先创建一个任务类extends Thread类,因为Thread类实现了Runnable接口,所以自定义的任务类也实现了Runnable接口,重写run()方法,其中定义具体的任务代码或处理逻辑。
b.创建一个任务类对象,可以用Thread或者Runnable作为自定义的变量类型。
c.调用自定义对象的start()方法,启动一个线程。
示例代码:
//每个任务都是Runable接口的一个实例,任务是可运行对象,线程即可运行对象。必须创建任务类,重写run方法定义任务 public class EFT extends Thread { private int a = 10; @Override //重写run方法,定义任务 public void run() { while(a>=0) { System.out.println("$" + this.getName() + "(" + a + ")"); } } //调用start方法会启动一个线程,导致任务中的run方法被调用,run方法执行完毕则线程终止 public static void main(String[] args) { EFT thread1 = new EFT(); EFT thread2 = new EFT(); thread1.start(); thread2.start(); System.out.println("火箭发射倒计时:"); } }java创建线程的三种方式:
继承Thread类创建线程类
通过Runable接口创建线程类
实现Callable接口
应用程序可以使用Executor [ɪɡˈzekjətə®] 框架来创建线程池
Runnable接口有如下好处: ①避免单继承的局限,一个类可以实现多个接口。 ②适合于资源的共享
②同时线程池的效率也非常高,很容易实现和使用。
//继承Thread类 public class MyThread extends Thread { @Override public void run() { System.out.println(getName()); } public static void main(String[] args) { for(int i=0;i<10;i++){ new MyThread().start(); } // 内部类 方式 new Thread(){ @Override public void run() { for (int x = 0; x < 10; x++) { System.out.println(Thread.currentThread().getName() + ":" + x); } } }.start(); } } // 实现runnable接口 public class RunnableThreadTest implements Runnable { public void run() { System.out.println("run:" + Thread.currentThread().getName()); } public static void main(String[] args) { System.out.println("main:"+ Thread.currentThread().getName()); RunnableThreadTest rt = new RunnableThreadTest(); new Thread(rt, "线程1").start(); // 用内部类的方式创建线程,实现runnable接口 new Thread(new Runnable() { @Override public void run() { for (int x = 0; x < 10; x++) { System.out.println(Thread.currentThread().getName() + ":" + x); } } }).start(); } }专业描述:当多个线程访问一个对象时,如果不用进行额外的同步控制或其他的协调操作,调用这个对象的行为都可以获得正确的结果,我们就说这个对象是线程安全的。
那么我们如何做到线程安全?
一般采用synchronized关键字给代码块或方法加锁
在开发中,如果需要拼接字符串,使用StringBuilder还是StringBuffer?
场景一:
如果是多个线程访问同一个资源,那么就需要上锁,才能保证数据的安全性。
这个时候如果使用的是非线程安全的对象,比如StringBuilder,那么就需要借助外力,给他加synchronized关键字。或者直接使用线程安全的对象StringBuffer。
场景二:
如果每个线程访问的是各自的资源,那么就不需要考虑线程安全的问题,所以这个时候,我们可以放心使用非线程安全的对象,比如StringBuilder。
在方法中,创建对象,来实现字符串的拼接使用哪个好?
建议创建StringBuilder,这时候相当是每个线程独立占有一个StringBuilder对象,不存在多线程共享一个资源的情况,所以我们可以安心使用,虽然StringBuilder本身不是线程安全的。
什么时候需要考虑线程安全?
1,多个线程访问同一个资源
2,资源是有状态的,比如我们上述讲的字符串拼接,这个时候数据是会有变化的
因为java有个重要的特性,叫垃圾自动回收机制,所以答案是多线程,这里面有两部分,主线程(用户线程),垃圾回收线程GC(守护线程)同时存在。
线程与进程相似,但线程是一个比进程更小的执行单位。线程也被称为轻量级进程。
程序是含有指令和数据的文件,被存储在磁盘或其他的数据存储设备中,也就是说程序是静态的代码。
进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。
关系:系统运行一个程序即是一个进程从创建,运行到消亡的过程。一个进程在其执行的过程中可以产生多个线程。
初始状态、运行状态、阻塞状态、等待状态、超时等待状态、终止状态
new、runnable、blocked、waiting、time_waiting、terminated。
序列化:将 Java 对象转换成字节流的过程。
反序列化:将字节流转换成 Java 对象的过程。
当 Java 对象需要在网络上传输 或者 持久化存储到文件中时,就需要对 Java 对象进行序列化处理。
如何实现对象的序列化?
1、新建一个实体对象,实现Serializable接口,这个实体对象就可以进行序列化了
2、另一个类中序列化这个实体类,并且将序列化之后的字节序列存在磁盘上。
public class SerializableDemo { public static void main(String[] args) throws Exception { //序列化一个对象 ObjectOutputStream objOutputStream = new ObjectOutputStream(new FileOutputStream("D:\\obj.txt")); Person person = new Person(); person.setName("Tom"); person.setAge(24); //写入字面值常量 objOutputStream.writeObject("将对象序列化"); //写入匿名对象 objOutputStream.writeObject(new Date()); //写入对象 objOutputStream.writeObject(person); //反序列化一个对象 ObjectInputStream objInputStream = new ObjectInputStream(new FileInputStream("D:\\obj.txt")); System.out.println("读取的字面值常量:"+(String)objInputStream.readObject()); System.out.println("读取的匿名对象"+(Date)objInputStream.readObject()); System.out.println("读取person对象"+((Person)objInputStream.readObject()).toString()); } }对于不想进行序列化的变量,使用 transient 关键字修饰。transient 只能修饰变量,不能修饰类和方法。
通过异常体系保证程序的健壮性。
error: 一般指jvm错误,
栈内存异常堆内存异常runtimeexception (运行时异常):LogicException 逻辑异常,代码写得不严谨,数组越界,空指针异常。
Java可抛出(Throwable)的结构分为三种类型:被检查的异常(CheckedException),运行时异常 (RuntimeException),错误(Error)。
执行,并且finally的执行早于try里面的return 结论: 1、不管有木有出现异常,finally块中代码都会执行;
Java 中 IO 流分为几种?
按照流的流向分,可以分为输入流和输出流;按照操作单元划分,可以划分为字节流和字符流;按照流的角色划分为节点流和处理流。InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。 OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。
25、java反射的作用于原理
1、定义:
这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。
2、哪里会用到反射机制?
jdbc、hibernate,struts等框架使用反射实现的
3、反射的实现方式:
获取Class对象
单例设计模式:即某个类在整个系统中只能有一个实例对象可被获取和使用的代码模式。
例如:代表JVM运行环境的Runtime类。
要点:
一是某个类只能有一个实例 构造器私有化 二是他必须自行创建这个实例 含有一个该类的静态变量来保存这个唯一的实例; 三是它必须自行向整个系统提供这个实例; 对外提供获取该实例对象的方式: 直接报露用静态变量的get方法获取。几种常见形式:
饿汉式:直接创建对象,不存在线程安全问题
直接实例化饿汉式(简洁直观) * 1、构造器私有化 * 2、自行创建,并且用静态变量保存 * 3、向外提供这个实例 * 4、强调这是一个单例,我们可以用final修改 public class Singleton1 { public static final Singleton1 INSTANCE =new Singleton1(); private Singleton1(){ } } 枚举式(最简洁) * 枚举类型--最简洁:表示该类型的对象是有限的几个 * 我们限定为一个,就成了单例 public enum Singleton2 { INSTANCE; } 静态代码块饿汉式(适合复杂实例化—读一堆初始化数据) public class Singleton3 { public static final Singleton3 INSTANCE; static { INSTANCE= new Singleton3(); } private Singleton3(){ } }测试类:获取这个对象
public class TestSingleton1 { public static void main(String[] args) { Singleton1 s = Singleton1.INSTANCE; System.out.println(s); } }懒汉式:延迟创建这个实例对象。
线程不安全(适用于单线程)
* 1、构造器私有化 * 2、用一个静态变量保存这个唯一的实例 * 3、提供一个静态方法,获取这个实例对象 public class Singleton4 { private static Singleton4 instance; private Singleton4(){ } public static Singleton4 getInstance(){ if(instance==null){ instance = new Singleton4(); } return instance; } }线程安全(适用于多线程)
静态内部类形式(适用于多线程)小结:
单例、工厂模式:SpringIOC就是使用了工厂模式。代理模式:SpringAOP就是使用的动态代理。
技术的角度:
JSP本质就是一个Servlet JSP的工作原理:JSP->翻译->Servlet(java)->编译->Class(最终跑的文件)
应用的角度:
JSP=HTML+Java Servlet=Java+HTML 各取所长,JSP的特点在于实现视图,Servlet的特点在于实现控制逻辑
Servlet是单实例的。
生命周期的流程:
创建对象–>初始化–>service()–>doXXX()–>销毁
创建对象的时机:
1,默认是第一次访问该Servlet的时候创建 2,也可以通过配置web.xml,来改变创建时机,比如在容器启动的时候去创建,DispatcherServlet(SpringMVC前端控制器)就是一个例子 1
执行的次数
对象的创建只有一次,单例 初始化一次 销毁一次
关于线程安全
构成线程不安全三个因素: 1,多线程的环境(有多个客户端,同时访问Servlet) 2,多个线程共享资源,比如一个单例对象(Servlet是单例的) 3,这个单例对象是有状态的(比如在Servlet方法中采用全局变量,并且以该变量的运算结果作为下一步操作的判断依据)
Cookie实际上是一小段的文本信息,Session在服务端开辟一块内存来保存session标识。
存储的位置不同
Session:服务端 Cookie:客户端
存储的数据格式不同
Session:value为对象,Object类型 Cookie:value为字符串,如果我们存储一个对象,这个时候,就需要将对象转换为JSON
存储的数据大小
Session:受服务器内存控制 Cookie:一般来说,最大为4k
生命周期不同
Session:服务器端控制,默认是30分钟,注意,当用户关闭了浏览器,session并不会消失
Cookie:客户端控制,其实是客户端的一个文件,分两种情况 1,默认的是会话级的cookie,这种随着浏览器的关闭而消失,比如保存sessionId的cookie 2,非会话级cookie,可通过设置有效期来控制,比如这种“7天免登录”这种功能, 就需要设置有效期,setMaxAge
Session机制背后的原理是,服务器会自动生成会话级的cookie来保存session的标识。
xml:可扩展标记语言,是一种用于标记电子文件使其具有结构性的标记语言。
json:(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。
二者区别:
它们都是一种数据交换格式。
1,xml是重量级的,json是轻量级的。
2,xml在传输过程中比较占带宽,json占带宽少,易于压缩。
3,xml和json都用在项目交互下,xml多用于做配置文件,json用于数据交互。
4,json可用jackson,gson等方法解析,xml可用dom,sax,demo4j等方式解析。
转发:
发生在服务器内部的跳转,所以,对于客户端来说,至始至终就是一次请求,所以这期间,保存在request对象中的数据可以传递
重定向:
发生在客户端的跳转,所以,是多次请求,这个时候,如果需要在多次请求之间传递数据,就需要用session对象
面试官的问题:
在后台程序,想跳转到百度,应该用转发还是重定向? 答案:重定向,因为转发的范围限制在服务器内部
1,JavaEE将企业级软件架构分为三个层次:
Web层:负责与用户交互并对外提供服务接口 业务逻辑层:实现业务逻辑模块 数据存取层:将业务逻辑层处理的结果持久化,方便后续查询
2,看图:
3,每个层都有各自的框架
WEB层:SpringMVC,Struts2,Struts1 业务逻辑层:Spring 数据持久层:Hibernate,MyBatis,SpringDataJPA,SpringJDBC
MVC是对Web层做了进一步的划分,更加细化
Model(模型) - 模型代表一个存取数据的对象或 JAVA POJO。 View(视图) - 视图代表模型包含的数据的可视化,比如HTML,JSP,Thymeleaf,FreeMarker等等 Controller(控制器) - 控制器作用于模型和视图上。它控制数据流向模型对象,并在数据变化时更新视图。它使视图与模型分离开,目前的技术代表是Servlet,Controller。
SpringMVC分为两个控制器
DispatchServlet:前端控制器,由它来接收客户端的请求,再根据客户端请求的URL的特点,分发到对应的业务控制器,比如UserController。
记得多少回答多少即可。
内置对象名 类型 request (HttpServletRequest) response (HttpServletResponse) config (ServletConfig) application (ServletContext) session (HttpSession) exception (Throwable) page (Object(this)) out (JspWriter) pageContext (PageContext)
page域: 只能在当前jsp页面使用 (当前页面) request域: 只能在同一个请求中使用 (转发才有效,重定向无效) session域: 只能在同一个会话(session对象)中使用 (私有的,多个请求和响应之间) context域: 只能在同一个web应用中使用 (全局的)
并发:同一个CPU执行多个任务,按细分的时间片交替执行
并行:在多个CPU上同时处理多个任务
增:
1.1【插入单行】 insert [into] <表名> (列名) values (列值) 例:insert into Strdents (姓名,性别,出生日期) values (‘开心朋朋’,‘男’,‘1980/6/15’)
删:
2.1【删除<满足条件的>行】 delete from <表名> [where <删除条件>] 例:delete from a where name=‘开心朋朋’(删除表a中列值为开心朋朋的行)
改:
update <表名> set <列名=更新值> [where <更新条件>] 例:update tongxunlu set 年龄=18 where 姓名=‘蓝色小名’
查:
4.1、精确(条件)查询 select <列名> from <表名> [where <查询条件表达试>] [order by <排序的列名>[asc或desc]]
查询所有:select * from 表名;
4.1.2【查询部分行列–条件查询】 例:select i,j,k from a where f=5 说明:查询表a中f=5的所有行,并显示i,j,k3列
4.1.3【在查询中使用AS更改列名】 例:select name as 姓名 from a where xingbie=‘男’ 说明:查询a表中性别为男的所有行,显示name列,并将name列改名为(姓名)显示
4.1.4 模糊查询
例:select * from a where name like ‘赵%’
4.2.2【使用between在某个范围内进行查询】 例:select * from a where age between 18 and 20
4.2.3【使用in在列举值内进行查询】 例:select name from a where address in (‘北京’,‘上海’,‘唐山’)
4.3.1【使用group by进行分组查询】 例:select studentID ,AVG(score) from student group by studentID (score)指的是列名
4.3.2【使用having子句进行分组筛选】 例:select studentID ,AVG(score) from student group by studentID having count(score)>1
注:由于where只能在没有分组时使用,分组后只能使用having来限制条件。
4.4.1内联接(只列出两张表关联查询符合条件的记录**) 例:select a.name,b.chengji from a,b **where a.name=b.name或者
select a.name,b.chengji from a inner join b on a.name=b.name
4.4.2.1【左外联接查询】 例:select s.id sid, s.name sname,c.id cid, from strdent s left join score c on s.id=c.sid 以左表为主
右外连接改为right 以左表为主
(1)求出员工总人数。 SELECT COUNT(*) FROM emp; – SELECT count(rowid) FROM emp; (2)求出公司每月要支付的工资总数。 SELECT COUNT(sal) FROM emp; (3)求出最高月薪、最低月薪。 SELECT MAX(sal), MIN(sal) FROM emp; (4)求出公司的平均月薪。 SELECT AVG(sal) FROM emp;
SQL1999标准中多表连接的语法: SELECT [DISTINCT] *|[列名 别名,…] FROM 主表名 [别名] JOIN_TYPE 从表名 [别名] ON 连接条件 WHERE 查询条件1 GROUPBY 分组表达式 HAVING 组过滤条件 ORDERY BY 排序表达式;
(5)显示每个部门的员工数量。 SELECT COUNT(rowid) FROM emp GROUP BY deptno; (6)显示每种职位的名及平均月薪。SELECT job,AVG(sal) FROM emp GROUP BY job;
(7)显示平均月薪大于2000的部门编号及平均月薪。SELECT deptno,AVG(sal) FROM emp GROUP BY deptno HAVING AVG(sal) > 2000;
(注:聚合函数不能出现在WHERE子句中。)
(8)显示不是总裁(PRESIDENT)的职位名以及该职位的员工月薪总和,还要满足同职位的员工的月薪总和大于4500。输出结果按月薪的总和降序排列。
1、职位不是总裁的职位名:SELECT job FROM emp WHERE job!=‘PRESIDENT’; 2、按职位分组,求出月薪总和:SELECT job,SUM(sal) FROM emp WHERE job!=‘PRESIDENT’ GROUP BY job; 3、分组后过滤月薪总和大于4500:SELECT job,SUM(sal) FROM emp WHERE job!=‘PRESIDENT’ GROUP BY job HAVING SUM(sal) > 4500; 4、结果按月薪的总计降序排列:SELECT job,SUM(sal) FROM emp WHERE job!=‘PRESIDENT’ GROUP BY job HAVING SUM(sal) > 4 4500 ORDER BY SUM(sal) DESC; select job,sum(sal) from emp group by job having sum(sal) >4500 and job!=‘PRESIDENT’ order by sum(sal) desc;
(9)求出部门平均月薪的最高值。 SELECT MAX(AVG(sal)) FROM emp GROUP BY deptno;
(10)求出部门平均月薪最高的部门编号和平均月薪。
SELECT deptno,AVG(sal) FROM emp GROUP BY deptno HAVING avg(sal)=(SELECT MAX(AVG(sal)) FROM emp GROUP BY deptno);
(11)查询出月薪大于2000的员工姓名、月薪、受雇日期及其所在的部门名,输出结果按受雇日期排序。
SELECT ename,sal,hiredate,dname FROM emp INNER JOIN dept ON emp.deptno=dept.deptno WHERE emp.sal>2000 ORDER BY hiredate;
(12)查询出月薪比“SMITH”高的员工信息。 Select * from emp where sal>(select sal from emp where ename=‘SCOTT’) (13)查询出月薪最高的员工姓名和月薪。 Select ename,sal from emp where sal=(select max(sal) from emp)
(inodb /i nou db/、myisam/misam/ 、memory 、merge、archive )
事务是访问数据库的一个操作序列,数据库应用系统通过事务集来完成对数据库的存取。
注:事务必须服从ISO/IEC所制定的ACID原则。ACID是原子性(atomicity)、一致性(consistency)、隔离性(isolation)和持久性(durability)
原子性是基础,隔离性是手段,一致性 是约束条件,而持久性是我们的目的。
l READ UNCOMMITTED 读未提交,脏读、不可重复读、幻读有可能发生。 l READ COMMITTED 读已提交,可避免脏读的发生,但不可重复读、幻读有可能发生。 l REPEATABLE READ 可重复读,可避免脏读、不可重复读的发生,但幻读有可能发生。 l SERIALIZABLE 串行化,可避免脏读、不可重复读、幻读的发生,但性能会影响比较大。
特别说明:
幻读,是指在本地事务查询数据时只能看到3条,但是当执行更新时,却会更新4条,所以称为幻读
第一范式:列不可分 第二范式:要有主键 第三范式:不可存在传递依赖
JDBC对事务的操作是基于Connection来进行控制的,具体代码如下:
try { //开启事务 connection.setAutoCommit(false); //做业务操作 //doSomething(); //提交事务 connection.commit(); }catch(Exception e){ //回滚事务 try { connection.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } }但,注意,事务的边界我们是放在业务层进行控制,因为业务层通常包含多个dao层D的操作。
1,作用的位置不同
synchronized [ˈsɪŋkrənaɪzd] 可以给方法,代码块加锁
lock只能给代码块加锁
2,锁的获取锁和释放机制不同
**synchronized无需手动获取锁和释放锁,**发生异常会自动解锁,不会出现死锁。
lock需要自己加锁和释放锁,如lock()和unlock(),如果忘记使用unlock(),则会出现死锁,
所以,一般我们会在finally里面使用unlock().
synchronized修饰成员方法时,默认的锁对象,就是当前对象
synchronized修饰静态方法时,默认的锁对象,当前类的class对象,比如User.class
1、线程A和线程B相互持有对方需要的锁,从而发生阻塞,最终变为死锁。
2,如何防止死锁?(重点)
减少同步代码块嵌套操作
降低锁的使用粒度,不要几个功能共用一把锁
尽量采用tryLock(timeout)的方法,可以设置超时时间,这样超时之后,就可以主动退出,防止死锁(关键)
分别是普通索引、唯一索引、聚集索引、主键索引、全文索引几种。
使用索引的优点:
提高数据的搜索速度加快表与表之间的连接速度在信息检索过程中,若使用分组及排序子句进行时,通过建立索引能有效的减少检索过程中所需的分组及排序时间,提高检索效率。使用索引的缺点:
在我们建立数据库的时候,需要花费的时间去建立和维护索引,而且随着数据量的增加,需要维护它的时间也会增加。在创建索引的时候会占用存储空间。在我们需要修改表中的数据时,索引还需要进行动态的维护,所以对数据库的维护带来了一定的麻烦。唯一索引:在创建唯一索引时要不能给具有相同的索引值。 主键索引:在我们给一个字段设置主键的时候,它就会自动创建主键索引,用来确保每一个值都是唯一的。 聚集索引:我们在表中添加数据的顺序,与我们创建的索引键值相同,而且一个表中只能有一个聚集索引。 普通索引:它的结构主要以B+树和哈希索引为主,主要是对数据表中的数据进行精确查找。 全文索引:它的作用是搜索数据表中的字段是不是包含我们搜索的关键字,就像搜索引擎中的模糊查询。
第一种方式:在执行CREATE TABLE时创建索引
第二种方式:使用ALTER TABLE命令去增加索引
第三种方式:使用CREATE INDEX命令创建
删除索引:根据索引名删除普通索引、唯一索引、全文索引: alter table 表名 drop KEY 索引名
关系型数据库和菲关系型数据库
关系型:mysql、oracle、sqlserver等
菲关系型:redis、memcache、mogodb、hadoop等
14、mysql数据库默认的最大连接数?
100,可设置。
反射是一种在程序运行时,动态获取当前类对象的所有属性和方法的能力,可以动态执行方法,给属性赋值等操作的能力。
在java中,Class类就是关键API,在我们的许多框架的背后实现上,都采用了反射的机制来实现动态效果。
IOC:“控制反转”。可以自动管理依赖的对象,重点是解耦!
AOP:面向切面编程。方便我们将一些非核心业务逻辑抽离,从而实现核心业务和非核心业务的解耦,即关注业务逻辑的开发。
其他:声明式事物的支持、方便程序测试、方便集成各种优秀框架、降低Java EE API的使用难度。
Spring AOP ,面向切面编程。原理:JDK动态代理
IOC,即控制反转,是一种设计思想,就是容器控制应用程序所需要外部资源的创建和管理,然后将其反转给应用程序
DI,即依赖注入,一种实现手段,在系统运行过程中,动态的向某个对象注入它所依赖的对象。
1,默认是singleton,即单例模式(常用)
2,prototype,每次从容器调用bean时都会创建一个新的对象,比如整合Struts2框架的时候,spring管理action对象则需要这么设置。
3,request,每次http请求都会创建一个对象
4,session,同一个session共享一个对象
5,global-session
大家可以回顾下线程不安全构成的三要素:
1,多线程环境
2,访问同一个资源
3,资源具有状态性
那么Spring的bean模式是单例,而且后端的程序,天然就处于一个多线程的工作环境。
那么是安全的吗?
关键看第3点,我们的bean基本是无状态的,所以从这个点来说,是安全的。
所谓无状态就是没有存储数据,即没有通过数据的状态来作为下一步操作的判断依据
propagation_required:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
这个配置项的意思是说当我调用service层的方法的时候,开启一个事务,那么在调用这个service层里面的其他的方法的时候,如果当前方法产生了事务就用当前方法产生的事务,否则就创建一个新的事务。这个工作是由Spring来帮助我们完成的。
1,首先,将请求分给前端控制器DispatcherServlet
2,DispatcherServlet查询HandlerMapping(映射控制器),从而找到处理请求的Controller(处理器)
3,Controller执行业务逻辑处理后,返回一个ModelAndView(模型和视图)
4,DispatcherServlet查询一个或多个ViewResolver(视图解析器),找到ModelAndView对应的视图对象,视图对象负责渲染返回给客户端
快速记忆技巧:
核心控制器捕获请求、
查找Handler、
执行Handler、
选择ViewResolver、
通过ViewResolver渲染视图并返回。
SpringMVC容器管理,controller,Handlermapping,ViewResolver
Spring容器管理,service,datasource,mapper,dao
Spring容器是父容器,SpringMVC容器是子容器子容器可以访问父容器上面的资源,所以我们会在看Controller可以注入Service@RequestMapping:做请求的URL,跟我们controller或者方法的映射关系
@RequestParam:做请求参数的匹配,当请求参数名称跟我们方法的参数名不一致的时候,可以做匹配
@GetMapping: 请求方式为GET
@PostMapping:请求方式为POST
@PathVariable:获取URL中携带的参数值,处理RESTful风格的路径参数
@CookieValue:获取浏览器传递cookie值
@RequestBody:接收请求中的参数信息,一般来说,接收一个集合或数组,或者以post方式提交的数据
@ResponseBody: 改变返回逻辑视图的默认行为,返回具体的数据,比如json
@Controller:Spring定义的,作用就是标明这是一个controller类
@RestController:@Controller+@ResponseBody的组合
(1)工厂模式:SpringIOC就是使用了工厂模式 (2)单例模式:Bean默认为单例模式。 (3)代理模式:Spring的AOP功能用到了JDK的动态代理; (4)模板模式:Spring中jdbcTemplate、hibernateTemplate等以Template结尾的对数据库操作的类,就是用到了模板模式。 (5)观察者模式:Spring事件驱动模型就是观察者模式很经典的一个应用。
(6)适配器模式:Spring AOP的增强或通知使用到了适配器模式。
(7)策略模式:Spring中资源访问接口Resource的设计是一种典型的策略模式。
(8)装饰器模式:Spring 中配置 DataSource 的时候。
Spring AOP的底层都是通过代理来实现的
一种是基于JDK的动态代理(实现类接口,使用JDK动态代理完成AOP)一种是基于CgLIB的动态代理(没有实现接口,采用CGLIB动态代理完成AOP)1,悲观锁是利用数据库本身的锁机制来实现,会锁记录。安全
2,乐观锁是一种不锁记录的实现方式,采用CAS模式,建议采用version字段来作为判断依据。
优点:
SQL写在XML里,解除sql与程序代码的耦合,便于统一管理;消除了JDBC大量冗余的代码;很好的与各种数据库兼容;能够与Spring很好的集成;提供映射标签。缺点:
SQL语句的编写工作量较大SQL语句依赖于数据库,导致数据库移植性差。一级缓存总结:
1,一级缓存模式是开启状态 2,一级缓存作用域在于SqlSession 3,如果中间有对数据的更新操作,则将清空一级缓存。
要使用二级缓存,需要经历两个步骤 1,开启二级缓存(默认处于开启状态) 2,在Mapper.xml中,配置二级缓存(也支持在接口配置) 在标签下面添加标签即可
二级缓存作用域在于SqlSessionFactory。MyBatis的二级缓存默认采用的是Map的实现。二级缓存优先于一级缓冲。
第一种是使用标签,逐一定义数据库列名和对象属性名之间的映射关系。 第二种是使用sql列的别名功能,将列的别名书写为对象属性名。
有了列名与属性名的映射关系后,Mybatis通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。
Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页。
分为逻辑分页和物理分页(正常人,一般使用)。
首先,在MyBatis内部定义了一个拦截器接口
所有的插件都要实现该接口,来,我们看看这个接口的定义
public interface Interceptor { Object intercept(Invocation invocation) throws Throwable; Object plugin(Object target); void setProperties(Properties properties); }那么其中一个关键的方法就是intercept,从而实现拦截
分页插件的原理:就是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。
所以原理还是基于拦截器。
MySQL使用limit分页(计算参数为 开始序号(startNum),要查的总条数 (totalNum))
select * from stu limit m, n; //m = (startPage-1)*pageSize,n = pageSizeOracle使用rownum分页,三层嵌套查询(计算参数为 开始序号(startNum) , 结束序号 (endNum))
select * from ( select rownum rn,a.* from table_name a where rownum <= x //结束行,x = startPage*pageSize ) where rn >= y; //起始行,y = (startPage-1)*pageSize+11、#是将传入的值当做字符串的形式,eg:select id,name,age from student where id =#{id},当前端把id值1,传入到后台的时候,就相当于 select id,name,age from student where id =‘1’. #{} 占位符 采用#可以解决SQL注入的问题。
2 、== 是 将 传 入 的 数 据 直 接 显 示 生 成 s q l 语 句 = = , e g : s e l e c t i d , n a m e , a g e f r o m s t u d e n t w h e r e i d = 是将传入的数据直接显示生成sql语句==,eg:select id,name,age from student where id = 是将传入的数据直接显示生成sql语句==,eg:selectid,name,agefromstudentwhereid={id},当前端把id值1,传入到后台的时候,就相当于 select id,name,age from student where id = 1. ${} 拼接符
1,基本的CRUD标签,select|insert|updae|delete
2,、、、、
3,动态SQL标签:trim | where | set | foreach | if | choose | when | otherwise | bind等,其中为sql片段标签,通过标签引入sql片段
启动类上面的注解是@SpringBootApplication,主要组合包含了以下3 个注解:
@SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。 @EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项。
@ComponentScan:Spring组件扫描。
SpringCloud是基于Springboot的、微服务系统架构的一站式解决方案。
SpringCloud是一系列主流框架的集合,以SpringBoot的方式对外提供服务。
区别:
SpringBoot可以离开SpringCloud独立使用,开发项目,但SpringCloud离不开SpringBoot,属于依赖关系;SpringBoot专注于快速、方便的开发单个个体微服务,SpringCloud关注全局的服务治理框架;联系:
Sprigboot为SprigCloud提供了代码实现环境,使用SprigBoot将其它组件有机融合到了SprigCloud的体系架构中了。
CAP是做分布式开发一个非常关键性的原则
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m2jzV7uK-1603932851241)(java基础笔试题总结.assets/image-20201011194822096.png)]
key–value
原因:
如何回收:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QRpIi7tX-1603932851245)(java基础笔试题总结.assets/image-20201011201604872.png)]
意义:
具体有什么样的机制?
首先,需要经过DNS(域名解析服务)将URL转换为对应的ip地址,实际上域名只是方便我们记忆,在网络上的每台主机交互的地址都是IP。
其次,我们需要通过这个ip地址跟服务器建立TCP网络连接,随后向我们的服务器发出http请求。注意,http协议是tcp的上层协议
最后,服务器接收到我们的请求,处理完毕之后,将响应数据放入到http的响应信息中,然后返回给客户端。
客户端浏览器完成对服务器响应信息的渲染,将信息展现在用户面前。
示意图:
传输层协议:TCP协议、UDP协议
应用层协议:FTP、HTTP、SMTP
网络层协议:IP协议
首先,两者都是传输层的协议。
其次,
tcp提供可靠的传输协议,传输前需要建立连接,面向字节流,传输慢
udp无法保证传输的可靠性,无需创建连接,以报文的方式传输,效率高
经过3次握手,4次挥手。
3次挥手
为什么要四次挥手?原因是TCP连接是一种双工的通信模式
可用天眼查企业相关信息。
a、实力!实力!实力! 关注高频问题
b、主动权思维。
给面试官传递的信号是确定感.自我介绍,展示自己的优点,引导面试官询问已准备好的问题。可以铺开来说。c、着重查看应聘岗位所需的技术,了解产品、业务范围。
面试过程中相关:
面试后:
罗列面试中遇到的问题,重新组织好答案,变成自己的语言。 脱稿
技术复习优先级:
乐学网-在线教育是一个基于springboot工程的多模块项目,分为前台用户系统和后台运营平台。项目采用前后端分离技术开发,前端部分,使用主流的前端框架Vue,使用Es6的开发规范,采用模块化的开发模式。后端部分,使用的是SpringBoot+SpringCloud进行微服务架构开发。
一、我参与了讲师、课程管理模块、服务预约模块、banner模块的动态展示。
在讲师、课程管理模块的开发接口整合了mybatisplus,用到了代码生成器策略,(增删改查配置相关mp插件,)并整合swagger进行接口测试(生成在线接口文档,方便接口测试),模块开发进行统一的返回结果,统一异常,统一日志处理。
(MyBatis-Plus是一个 MyBatis 的增强工具,封装许多方法、也有强大的特性,内置Mapper、条件构造器 Wrapper、支持主键自动生成、内置代码生成器、内置分页插件等等:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询)
首页显示的banner数据(轮播图),使用到了redis缓冲。使用mp实现crud操作。(redis使用的是redisTemplate模板并结合springdataredis,调用redis接口方法)
预约模块,在前台可以预约名师,后台接受数据,讲师可进行是否同意匹配以及查看匹配记录,之后回传数据到前端,学生查看预约结果。前端是vue+element-ui组件实现,后端是相似的开发接口。
对于用户登录使用了spring security安全框架进行授权和认证,参考官方文档在SecurityConfig类中进行配置,可额外增加权限控制及注销,需结合thymeleaf。可定制登录页,以Cookie作为凭证媒介可实现rememberMe功能 。
用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程(数据从数据库读取)。
auth.inMemoryAuthentication()
用户授权指的是验证某个用户是否有权限执行某个操作。
在用户认证方面,Spring Security 框架支持主流的认证方式,包括 HTTP 基本认证、HTTP 表单验证、HTTP 摘要认证等。
在用户授权方面,Spring Security 提供了基于角色的访问控制和访问控制列表。
在讲师管理模块做文件上传使用到了阿里云oss存储服务。
如何实现?
传统的文件上传是存储到Tomcat中或者储存到本地路径中。弊端:别人的电脑就无法访问到我硬盘中的文件了。
于是采用了阿里云oss存储,在线联网可以使所有人都访问,(众所周知,阿里云技术在国内是顶级的,在实际项目开发中很多人也都会用到阿里云oss存储,因为他是很好的云存储解决方案。)
没有达到一定的存储量,它是免费。即使收费也是比较优惠的。
具体如何使用:
1、开通“对象存储OSS”服务(需要注册阿里云账号、实名认证)
2、在管理控制台中创建Bucket(相当于包或文件夹)
3、通过java代码操作实现上传文件到阿里云oss(官方api文档有详细的使用说明)
导入依赖固定的代码结构,id、秘钥等(需创建),new对象,调用方法等在添加课程分类功能中,(是先把信息添加到execl表格中,)使用到了一个技术叫EasyExcel,用它来读取execl内容,然后添加到数据库中。
相对传统的表单数据添加使用EasyExcel可以实现分类信息的批量添加,减轻录入工作量,便于统计信息的归档。EasyExcel是阿里巴巴提供的一个针对excel简单、高效的开源处理框架,实现读和写操作。
具体如何使用:
引入easyexcel相关依赖。编写具体的后台开发接口代码—>(获取上传过来的文件,读取文件内容,添加到数据库)其中实体类要和execl数据对应,读取关键点创建监听器。
课程分类列表使用树形结构显示等等
在服务注册、调用、熔断器、网关、配置中心如何操作?
在服务模块引入依赖。添加服务配置信息添加注解@Enablexxx,开启功能 。二、Alice电子商城是一个基于SSM轻量级java开发框架搭建的平台,我参与了商品展示模块,注册登录模块,评论留言模块等。代码采用的分层方式,并进行了统一异常处理,配置了拦截器等。
商品展示模块中,有商品分类、排序、搜索、分页显示利用了PageHelper插件,
(在SqlSessionFactoryBean中配置PageHelper的分页插件,业务层设置分页所必须的参数,在Controller层将分页展示的数据传入PageHelper所提供的分页对象中,由于分页对象存储到request域中,视图层通过el表达式即可完成分页。)
注册使用了邮件验证激活账号(首先在数据库添加激活码和验证状态两个字段,注册时使用javamail发送邮箱验证链接,点击验证);
登录配置了拦截器。
订单结算通过更改商品状态。
乐学网-在线教育
1.影响比较深的一个问题是:跨域请求,在线教育项目是基于前后分离的一个项目,前后端采用不同端口访问,比如说9528端口访问8001端口,出现服务器错误,通过思考查询相关资料后,得到两种解决方式
在后端接口controller添加注解@CrossOrigin使用网关解决2.多路由跳转同一页面问题,讲师的添加和修改的表单提及放在同一页面,修改再进行添加,数据没有清空(eduTeacher.clear()):使用vue的监听机制实现表单清空
当然还有细节问题,在controller层参数的传递,接受,返回的数据格式问题
逻辑删除问题,使用乐观锁,根据乐观锁的版本号状态值的变化等
Alice电子商城
没有太多复杂的问题,最常遇见状态500问题,没有加载上下文路径。
权限访问控制问题,使用过滤器只能拦截相关页面,不能拦截请求路径,配置拦截器可以完成对全部的请求路径完成拦截。
一些具体问题记得不太清,但是在实际使用中遇到这类问题能够解决。
乐学网-在线教育
讲师、课程管理模块的开发接口整合了mybatisplus,用到代码生成器策略,(增删改查配置相关mp插件,)并整合swagger进行接口测试(生成在线接口文档,方便接口测试),模块开发进行统一的返回结果,统一异常,统一日志处理。首页显示的banner数据(轮播图),使用到了redis缓冲。使用mp实现crud操作。对于用户登录使用了spring security安全框架进行授权和认证,在做文件上传使用到了阿里云oss存储服务,比如讲师头像上传在添加课程分类功能中,(是先把信息添加到execl表格中,)使用到了一个技术叫EasyExcel,用它来读取execl内容,然后添加到数据库中。课程分类列表使用树形结构显示概念图: ajax操作/异步请求操作(前端定义接口地址和参数、请求方式等)
axios 前端得到数据用vue指令进行遍历显示。
什么是node.js?简单的说 Node.js 就是运行在服务端的 JavaScript,是 JavaScript的运行环境。
什么是NPM?Node.js的包管理工具,相当于后端的Maven
Es6:是一套标准,一套规范。
Nginx相关概念:
动静分离:不同服务器放置不同的资源,比如java代码放在tomcat中,一些静态资源(html、图片等)放在静态服务器中。然后根据不同的请求访问不同的服务器。
