一、Java
1、Java跨平台原理
详细说明:
由于各操作系统支持的指令集,不是一致的、会让我们的程序在不同的操作系统上执行不同的代码。而Java开发了适用于不同操作系统及位数的Java虚拟机来屏蔽个系统之间的差异、提供统一接口。对于Java开发者来说,只需在不同的系统上安装对应的不同Java虚拟机,这时我们的Java程序只需遵循Java规范即可在所有系统上运行。
简单说明:
Java通过不同的系统、版本、和位数的虚拟机来屏蔽不同的系统指令及差异而对外统一接口API、对于开发者来说,只需按照接口开发即可,如果系统部署到不同环境时,只需在系统上安装对应版本的虚拟机即可。
2、搭建Java开发环境的步骤
Java环境需要啥?
- 开发环境的JDK
- 开发工具
- Web服务器
一、下载组件
二、安装JDK,配置JAVA_HOME变量,因为开发工具和服务器需要依赖该变量。
3、int占几个字节?
Java中有几种数据类型? 8种
int占4位字节、二进制32位数;
4、面向对象的特征
四大特征:封装、继承、抽象、多态
封装:将类的信息封装到类内部、不允许外部程序访问、而是通过该类提供的get/set方法来实现对隐藏信息的操作和访问,通过private 来隐藏;
继承:将子类中共有的属性和方法提取到父类、通过extends继承父类、使用继承时必须符合is-a的关系,java只能单继承、Object类是java中的基类、所有类默认继承该类、子类不能继承到的有使用private修饰的属性和方法、父类构造、默认访问修饰符并不在同包中。
抽象:使用abstract修饰的类为抽象类,目的是限制该类实例化(不能new)。
多态:指同一个引用类型,使用不能的实例而执行不同的操作。
5、有了基本数据类型,为啥还需要包装类?
java提供了8种基本数据类型:byte、short、int、long、float、double、char、boolean
包装类:每个基本数据类型都会对应一个包装类、比如:int–>Integer。
装箱和拆箱
装箱:将基本的数据类型转换成对应的包装类。比如:
Integer i = 1; 自动装箱,在编译时会调用valueOf(值)方法来装箱;
拆箱:将包装类转换为对应的基本数据类型、比如:
基本数据类型 变量名 = 对应包装类;自动拆箱,在编译时调用intValue()
Integer i = 1; // 自动装箱
Integer.valueOf(2); // 手动装箱
int j = i; // 自动拆箱
int j = i.intValue(); // 手动拆箱
为什么需要?
Java是面向对象的语言、而基本数据类型、不具备面向对象的特征。
基本数据类型没有好的方法,不能判断是否为空或最大最小值、缓存值。
缓存值:
Integer i = 1;
Integer j = 1;
System.out.println(i==j);
// 结果为true
6、"=="和equals()的区别?
==
比较两个变量之间的值是否相等、但是变量分为基本数据类型和引用类型、
如果是基本数据类型的变量会比较变量值是否相等返回boolean类型。
如果是引用类型而会判断它的内存地址是否相等。
equals()
比较两个对象的某些特征是否一致。
7、String、StringBuilder的区别?StringBuffer和StringBuilder的区别?
java中提供的三个类String、StringBuilder、StringBuffer都表示操作字符串的。
-
String:是内容不可变的字符串。底层使用了不可变的字符数组(final char[])
-
StringBuilder、StringBuffer :是内容可变的字符串。底层使用了可变的字符数组(没有final修饰)。
拼接字符串的效率:
-
String:拼接 String str = “a” + “b”; 这是三个对象。效率低;
-
StringBuilder或StringBuffer。效率高;
StringBuilder sb = new StringBuilder().sb.append(“a”).append(“b”);
-
拼接字符串不能用String、要用StringBuilder、StringBuffer。
-
-
StringBuilder线程不安全、效率高。
-
StringBuffer线程安全,效率低。
8、Java中的集合
java中的集合分为value、key-value(Conllection、Map)两种。
存储值分为:List和Set。
List和Set的区别:
List:有序、可重复。
Set:无序、不可重复。根据equals和hashCode判断、如果一个对象要存储在Set中,必须重写equals和hashCode方法。
存储key-value的为Map。
9、ArrayList和LinkedList的区别?
List常用的有ArrayList和LinkedList。
先说数据底层实现原理、再说区别、场景。
- ArrayList底层使用数组。
- LinkedList底层使用链表。
- 数组和链表的区别:
- 数组:有索引查询快、插入和删除或修改比较慢。
- 原因:数组在内存中有一块专门的内存,如果插入或删除时需要移动内存。
- 链表:不要求地址内存是连续的,在当前元素中存放上一个或下一个元素的地址。
- 查询时要从头部开始,逐个查询,所以查询效率低。
- 插入时不用移动内存,只需改变引用指向即可,所以插入或删除效率高。
- 数组:有索引查询快、插入和删除或修改比较慢。
- ArrayList使用在查询比较多,插入和删除较少的情况。
- LinkedList使用在查询比较少,插入和删除较多的情况。
10、HashMap和HashTable的区别?HashTable和ConcurrentHashMap的区别?
HashMap和HashTable
-
相同点:都可用来存储key-value的数据。
区别:
-
HashMap可把null作为key或value的。HashTable是不可的。
-
HashMap是线程不安全的、效率高。HashTable是线程安全的,效率低。
想线程安全又想效率高?
通过把整个Map分为多个Segnent(类似HashTable)可提供相同的线程安全,效率提升N倍、默认提升16倍。
11、实现拷贝文件的工具类使用字节流还是字符流?
首先明白什么是字节流和字符流?
- 字符流:传递字符,字符最终会转换为字节
- 字节流:传递二进制位字节。
拷贝文件不确定只包含字符流,有可能有字节流(图片、音频等),为考虑通用性,使用字节流。
12、线程
实现线程的方式?
-
继承Thread类,重写run方法,实现一个线程。
-
实现Runnable接口实现一个线程。
继承缺点:继承扩展性不强,java只支持单继承,如果一个类继承了Thread类就不能继承其他类了。
如何启动线程?
Thread thread = new Thread(继承的Thread对象/实现Runnable对象);
thread.start();
启动线程使用start()方法,启动后执行的是run()方法。
如何区分线程?
问题:在一个系统中多个线程,每个线程都会打印日志,如何区分是那个线程打印的?
thread.setName("设置一个线程名");
在创建Thread对象时通过setName()方法设置一个线程名,这是一种规范,都要设置名称。
什么是线程并发库?
JDK5中增加了DougLea的并发库,方便了线程的管理和使用提供了便利性。
java.util.current包中提供了对线程优化,管理的各项操作,该包提供了线程的运行,线程池的创建,线程生命周期的控制。
通过Executors类提供四种静态方法可创建线程池:
- newCachedThreadPool:创建一个可缓存的线程池,如果线程池长度超过处理需要,可回收空闲线程,若无可回收,则新建线程。
- newFixedThreadPool:创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
- newScheduledThreadPool:创建一个定长线程池,支持定时及周期任务执行。
- newSingleThreadExecutor:创建一个单线程化的线程池,只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序执行。(FIFO、LIFO,优先级)
线程池的作用?
- 限定线程的个数,不会导致由于线程过多导致系统运行缓慢或崩溃、
- 提供了附加功能,比如定时,延时来执行某些线程。
13、什么是设计模式?常用的设计模式有什么?
设计模式就是经过前人的多次实践总计出的,设计过程中可反复使用的,可解决特定问题的设计方法。
-
单例模式(饱汉模式、饥汉模式)
1、构造方法私有化、除了自己的类中能创建外其它地方都不能创建。
2、在自己的类中创建一个单实例(饱汉模式是一出来就创建单实例,饥汉模式需要的时候才会创建)
3、提供一个方法获取该实例对象(创建时需要进行方法同步)
-
工厂模式:SpringIOC、对象的创建交给一个工厂去创建,无需自己创建。
-
代理模式:SpringAOP动态代理
-
包装模式
二、JavaWeb
1、get和post的区别?
共同点: get和post都是http的请求方式,用户通过不同的请求方式完成对url的不同操作。
区别:
1、get提交的数据在地址栏显示、post提交的数据在地址栏中不显示。
get请求以?分割URL,多个参数用&号拼接。
2、get请求对地址长度输入有限制、post无限制。
3、post安全性比get高。
2、什么是Servlet?
Servlet是用Java编写的服务器端程序、这些Servlet都要实现Servlet接口、主要用于数据交互、生成动态网页内容、运行于支持java的应用服务器中。
HttpServlet重写doGet和doPost方法或重写service方法完成对get/post请求的响应。
3、Servlet的生命周期
-
加载和实例化
将Servlet部署到容器中,容器启动后接受请求时,容器会在内存中查找是否有该Servlet实例,如果没有则创建,如果有直接取出响应请求,执行一次。
-
初始化
实例化完容器调用init()方法初始化、将Servlet处理请求前完成的一些资源加载,jdbc连接等,执行一次。
-
就绪状态(服务)
接收请求时调用service()方法、根据请求类型调用doGet()/doPost()方法、执行多次。
-
销毁
容器会判断Servlet是否要被资源回收、调用destroy()方法指明哪些资源回收。
简单描述:
- 调用构造,实例化,一次。
- 调用init()、初始化,一次。
- 调用service()、根据请求类型调用doGet()/doPost(),多次。
- 当服务器重启或关闭时,调用destroy()进行资源回收。
4、forward()与redirect()的区别?
forward():在服务器上执行、浏览器的地址栏URL不变、数据不丢失、一次请求。
redirect():在客户端上执行、浏览器的地址栏URL改变、数据会丢失、两次请求。
5、JSP和Servlet有什么区别?有什么关系?
JSP是Servlet的扩展,所有JSP文件都会被翻译为一个继承HttpServlet的类。
JSP主要用于视图样式、Servlet主要用于逻辑控制。
Servlet如果要实现HTML功能、需要使用Writer输出HTML标签太麻烦、而JSP是Java和HTML组合为一个扩展名为.jsp的文件、做页面展示比较方便而嵌入逻辑比较复杂。
6、JSP有哪些内置对象?分别有什么作用域和方法?
9个内置对象:
- request:客户端请求信息、包含get/post请求参数。
- response:服务器响应给客户端的信息。
- pageContext:页面属性管理jsp页面。
- session:一次会话、关闭浏览器结束。
- application:整个应用程序。
- out:页面输出数据
- config:本质是一个ServletConfig对象。
- page:当前页
- exception:异常页面对象。
四大作用域:
- page:在当前页面使用
- request:每次新的请求都会创建request对象、一次转发时使用。
- session:再一次会话期内有效。
- application:服务器启动时。
常用方法:
setAttribute(String key , Object value):key-value、存储在request或session中。
getAttribute(String key):通过key取value。
removeAttribute():从作用域中删除key
invalidate():设置session立即失效。
getRequestDispatcher("*.jsp").forward(request,response);转发
sendRedirect("*.jsp"):重定向;
7、Session和Cookie的区别?分别在项目哪里使用?
session和cookie都是会话跟踪技术。Cookie通过在客户端记录信息确定用户身份。
Session通过在服务器端记录信息确定用户身份、但Session的实现依赖于Cookie、sessionId(session唯一标示存放在客户端)。
区别:
session: 在服务器上保存数据、类型为Object、会话结束后数据销毁、保存重要数据。
cookie: 在客户端上保存数据、类型为String、长期保存在客户端、保存不重要的数据。
单个cookie保存的数据不超过4K、很多浏览器都限制一个站点最多保存20个cookie
8、MVC的部分有哪些技术来实现?
- M(Model)模型:JavaBean
- V(View)视图:JSP、html、freemaker、volicity…
- C(Controller)控制器:Servlet、Action
三、数据库
1、数据库的分类
数据库分为:关系型数据库和非关系型数据库
常用的关系型数据库
- MySql 免费
- Oracle 收费
- SqlServer 运行在Window上的。
常用的非关系型数据库
- redis
- memcache
- mogodb
- hadoop
2、关系型数据库的三大范式是什么?
什么是范式?
范式就是规范、就是关系型数据库在设计表时,要遵循的三个规范。
要想满足第二范式必须先满足第一范式、要满足第三范式必须先满足第二范式。
- 第一范式(1NF):列数据不可分割、即实体某个属性不能有多个值或不能有重复属性。
- 第二范式(2NF):表中的每行必须可被唯一标识区分、(加主键)。
- 第三范式(3NF):如果当前表中的的字段和另一张表中的字段重复了,不能全部引用进来,需要加外键关联起来。
反三范式:为了效率、可设置重复或可推导出的字段。
3、事务的ACID特性是什么?
什么是事务?
事务是并发控制的单位、是用户定义的一个操作序列。这些操作要么都成功,要么都失败、是不可分割的工作单位。
事务必须满足的四大特性
- 原子性: 指事务的操作要么都成功、要么都失败。
- 一致性: 要么都成功、要么都失败,如果失败了要对前面的操作进行回滚。
- 隔离性: 一个事务开始时不能被其他事务所干扰。
- 持久性: 事务开始了就不能终止。
4、MySql数据库的默认最大连接数是多少?
为什么需要最大连接数?
特定服务器上的数据库只能支持一定数目同时连接、这时需要设置最大连接数(最多同时服务多少连接)、数据库安装时都有一个默认的最大连接数为100。
max_connections=100
5、MySql的分页?Oracle的分页?
为什么需要分页?
在很多数据时、不可能完全显示数据、从而进行分段显示。
mysql使用关键字limit进行分页:limit offset ,size 表示从多少索引去多少位。
oracle好像要使用三层嵌套查询。
6、数据库的触发器的使用场景?
什么是触发器?:触发器需要有触发条件,当条件满足后做什么操作。
在增加日志时做一个后触发、在向通知表中写入条目、触发器的效率高。
比如:每插入一个帖子、希望将版面表中的最后发帖时间、帖子总数字段进行同步更新,使用触发器效率就很高。
7、存储过程的使用场景?
存储过程的优点:
- 存储过程只在创建时进行编译,以后每次执行存储过程时都不用重新编译、而一般的sql每句执行一次就编译一次、因此存储过程提高了执行速度。
- 复杂的业务需要多条sql语句、这些语句需要从客户机发送到服务器、当他们之间的操作过多时,会产生大量的网络传输、如果将这些操作放入存储过程、网络传输和网络负载都会大大的降低。
- 安全性高、可屏蔽底层数据库对象的直接访问。使用execute权限调用存储过程、无需拥有访问底层数据对象的显示权。
mysql在5.0时实现了对存储过程的支持。
如何定义存储过程:
创建存储过程
create procedure 存储过程名(参数)
begin
sql 操作语句;
end;
调用存储过程:call 存储过程名();
删除存储过程:drop procedure 存储过程名;
存储过程的三种参数类型:in out inout
in:输入参数、在存储过程中修改参数的值不能被返回默认值;
out:输出参数、该值可在存储过程内部改变、可返回;
inout:输入输出参数、调用时指定、并可被改变和返回;
语法:
create procedure | function (in | out | inout 参数名 类型)
调用输出参数:call 存储过程名 ('值',@参数名)
select @参数名;
|:代表或者;
@:代表约定;
注意:
into :变量名、将结果保存到变量中;
out:为输出参数、将计算结果输出存储过程;
8、JDBC如何调用存储过程?
1、 声明数据库驱动:DriverManager.getDriver(“数据库驱动”);
2、 获取Connection,调用getConnection()方法。
3、 通过Connection获取Statement
4、 利用Statement进行数据查询,返回结果集是ResultSet
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
//声明数据源
private static ComboPooledDataSource dataSource = null;
//设置驱动
static String DRIVER ="com.mysql.jdbc.Driver";
//url,用户名,密码
final static String URL = "jdbc:mysql://127.0.0.1:3306/t31";
final static String USER = "root";
final static String PWD = "root";
static{
try {
//加载驱动
Class.forName(DRIVER);
//获取数据源
dataSource = new ComboPooledDataSource();
//设置数据源,设置mysql驱动
dataSource.setDriverClass(DRIVER);
dataSource.setJdbcUrl(URL);
dataSource.setUser(USER);
dataSource.setPassword(PWD);
} catch (ClassNotFoundException | PropertyVetoException e) {
e.printStackTrace();
}
}
/**
* 数据源方法开始
* @return
*/
//声明QueryRunner
QueryRunner qr = new QueryRunner(dataSource);
//数据源 查询直接返回列表,,查询全部
public List<T> getEntityList(String sql,Class clazz,Object... pars){
List<T> list = null;
try {
list = qr.query(sql,new BeanListHandler<T>(clazz),pars);
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
//查询 单对象
public T getEntity(String sql,Class clazz,Object... pars){
T t = null;
try {
t=qr.query(sql,new BeanHandler<T>(clazz),pars);
} catch (SQLException e) {
e.printStackTrace();
}
return t;
}
//返回单个值 主要用在 count sum 单个值的时候
public Object getScaler(String sql,Object... pars){
Object o = null;
try {
o=qr.query(sql, new ScalarHandler(),pars);
} catch (SQLException e) {
e.printStackTrace();
}
return o;
}
//执行增删改
public int c3p0Update(String sql,Object... pars){
int row = -1;
try {
row = qr.update(sql,pars);
} catch (SQLException e) {
e.printStackTrace();
}
return row;
}
/**
* 数据源方法结束
* @return
* C3P0
*/
//建立连接
public Connection getconnection(){
try {
conn = DriverManager.getConnection(URL,USER,PWD);
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
//执行增删改
public int Update(String sql,Object... pars){
getconnection();
int row = -1;
try {
pstmt = conn.prepareStatement(sql);
//如果pars 参数为null
if (pars != null) {
for (int i = 0; i < pars.length; i++) {
pstmt.setObject(i+1, pars[i]);
}
}
row = pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally{
closeAll(null,pstmt,conn);
}
return row;
}
//执行查询
public ResultSet Query(String sql,Object... pars){
getconnection();
try {
pstmt = conn.prepareStatement(sql);
if (pars != null) {
for (int i = 0; i < pars.length; i++) {
pstmt.setObject(i+1,pars[i]);
}
}
rs =pstmt.executeQuery();
} catch (SQLException e) {
e.printStackTrace();
}
return rs;
}
//释放资源
public void closeAll(ResultSet rs,Statement stmt,Connection conn){
try {
if (rs != null)rs.close();
if (stmt != null)stmt.close();
if (conn != null)conn.close();
} catch (SQLException e) {
e.printStackTrace();
} {
}
}
}
9、说下你对JDBC的理解?
java.database.connection.java 数据库连接。
数据库管理系统有很多、每个管理系统支持的命令不一样。
java定义了接口,让数据库厂商自己实现接口、对于开发者只需导入对应厂商开发的实现即可,然后以接口的方式进行调用mysql+驱动+jdbc。
10、写一个JDBC的程序
-
加载驱动:Class.forName(“com.mysql.jdbc.Driver”);
-
获取连接:Connection conn = DriverManager.getConnection(“jdbc:mysql://127.0.0.1:3306/数据库名”,USER,PWD);
-
设置参数:conn.prepareStatement(sql);
-
执行SQL:
ResultSet pstmt.executeQuery();
pstmt.executeUpdate();
-
释放连接:
if (rs != null)rs.close();
if (stmt != null)stmt.close();
if (conn != null)conn.close();
11、PreparedStatement比Statement的优点
- PreparedStatement是预编译的、速度比statement快。
- 代码的可读性和可维护性强。
- PreparedStatement可防止sql注入(安全)、Statement不可以
12、数据库连接池的作用?
- 限制数据库的连接个数、不会因为数据库连接过多导致系统运行缓慢。
- 数据库连接不需每次创建或销毁、节约资源、响应时间快。
四、前端部分
1、HTML、CSS、JavaScript在网页开发中的定位?
三种技术都是前端基础开发技术。
- HTML:超文本标记语言、通过标签定义网页的结构。
- CSS:层叠样式表、用于美化页面。
- JavaScript:用于验证表单 或 动态交互。
2、介绍下Ajax?
ajax是什么?
异步的JavaScript和Xml请求。
作用?
通过ajax与服务器进行数据交互、可使网页实现局部刷新、而不是每次请求都会刷新整个页面。
如何实现?
通过XmlHttpRequest对象、该对象可异步向服务器发送异步请求,并获取响应结果,完成局部刷新。
使用场景?
登录失败不跳转页面、表单验证、二级联动…。
3、js和jQuery的关系?
jQuery是一个js库、封装了js的属性和方法并增强了js的功能、让用户使用起来更方便。
使用原生js要处理很多兼容性的问题、而jQuery封装了底层,不需要处理兼容性问题。
原生js的DOM和事件绑定和Ajax等操作比较麻烦、jQuery封装之后更方便。
4、jQuery的常用选择器?
-
基本选择器:
- #id:根据id属性查找一个元素(id唯一):$("#idNme");
- .class:根据class类属性查找元素:$(".className");
- 标签选择器:根据指定标签查找元素;
- 全局选择器:通过*号获取所有元素;
-
层级选择器:$(“选择器1 符号 选择器2”);
- 后代:获取元素中所有后代元素和孙子节点,空格隔开。
- 子集:只获取儿子节点、 > 大于号隔开。
- 相邻:获取当前元素之后的一个元素、 + 加号隔开。
- 同辈:获取当前元素之后的所有同辈元素、 ~ 波浪线隔开。
-
复合选择器:$(“选择器1 符号 选择器2”);
- 交集:必须多个选择器同时复合条件才生效、连续书写;
- 并集:元素都需要用一种操作时、, 逗号隔开。
-
属性选择器:获取包含当前属性的所有元素,使用中括号[]:$(“[属性名]”);
比如:
-
获取属性值为…什么的内容:$(“[属性名=’值’]”);
$("input[name='newsletter']").attr("checked", true);
-
获取属性值不为…什么的内容:$(“[属性名!=’值’]”);
$("input[name!='newsletter']").attr("checked", true);
-
获取以…什么开头的内容:$(“[属性名^=’a’]”);
$("input[name^='a']").attr("checked", true);
-
获取以…什么结尾的内容:$("[属性名 $ =‘c’]");
$("input[name$='r']").attr("checked", true);
-
获取属性值包含…什么内容:$(“[属性名*=’e’]”);
$("input[name*='e']").attr("checked", true);
html代码
<input type="checkbox" name="newsletter" value="Hot Fuzz" /> <input type="checkbox" name="newsletter" value="Cold Fusion" /> <input type="checkbox" name="accept" value="Evil Plans" />
-
5、jQuery的页面预加载完毕事件?
在获取元素时必须等到该元素被加载完后才能获取,我们可把js代码放入该元素的后面,但这样会造成js在我们的body中存在不好管理、所有页面加载完后所有元素当然已加载完毕、一般获取元素做操作要在页面加载完毕之后操作。
方式一:
$(document).ready(function(){});
$(document)将元素的dom对象转换为jQuery对象、转换后才可调用ready方法、
ready(function):表示页面结构被加载完后执行传入function函数。
方式二:
$(function(){});:页面加载完后执行里面的函数、常用。
6、jQuery的Ajax和原生JS实现Ajax有什么关系?
- jquery中的ajax是通过原生的js封装的,用起来更方便。
- 如果使用原生js的ajax方式实现是很麻烦的。
7、HTML5有哪些新技术?
html5是最新版本的html、在html4的基础上增加了一些标签。
html增加了画板、音频、web存储等高级功能、但html5太强调语义、导致开发中不知道选择哪个标签。
8、CSS3有哪些新技术?
CSS3是最新版本的CSS、是对CSS2的功能增强。
- 盒子圆角边框。
- 盒子和文字的阴影。
- 渐变、转换、移动、缩放、旋转等。
- 可实现响应式网站。
CSS3的缺点要根据不同浏览器处理兼容性。
9、Bootstrap是什么?
Bootstrap是一个移动设备优先的UI框架、不需要写CSS、JS、就可实现比较漂亮的交互性页面。
常用:
- 模态框
- 表单、表单项。
- 栅格系统。
五、后端框架
1、什么是框架?
框架(Framework)指约束性、指支撑柱。
框架指为解决一个开放性问题而设计的具有一定约束性的支撑结构。在结构上可根据具体问题扩展、安装更多的组成部分、可迅速和方便的构建完整的解决问题的方案。
- 框架可以快速解决特定问题。
- 框架配套了帮助某类问题的库或工具。
2、MVC模式
MVC全名是Model View Controller 是模型(Model)–视图(View)–控制器(Controller)的缩写。
是一种软件设计规范、用一种业务逻辑、数据、界面显示分离的方法组织代码、将业务逻辑聚集到一个部件中。
- 当控制器收到的请求
- 控制器调用javaBean完成业务。
- 完成业务后通过控制器跳转到JSP页面的方式给用户信息。
3、什么是MVC框架?
为了解决传统MVC模式问题而出现的框架。
传统MVC模式的问题:
- 所有Servlet的映射都要配置在web.xml中、不能实现模块化管理。
- 接收参数比较麻烦、只能单个接收、接收完封装为Model。
- 跳转页面比较单一、页面名称发生变化时需要修改Servlet源码。
4、Struts2的执行流程?
- 浏览器发送请求,经过很多处理器、到达核心过滤器(StrutsPrepareAndExecuteFilter)
- StrutsPrepareAndExecuteFilter通过ActionMapper判断当前请求是否需要某个Action处理、如果不需要、则走原来的流程、如果需要则把请求交给ActionProxy处理。
- ActionProxy通过ConfigurationManager询问配置文件(Struts.xml)找到需要调用的Action类。
- 创建一个ActionInvocation实例、调用Action的对应方法来获取结果集的名字、在调用前后会执行的拦截器。
- 通过结果集的名字知道对应的结果集来对浏览器进行响应。
5、Struts2中的拦截器和使用场景
Struts中的功能都是通过系统拦截器实现的、如果业务需要、也可自定义拦截器进行配置、执行Action的方法前后、加入相关逻辑完成业务。
使用场景:
- 用户登录判断、执行Action前判断是否登录、如果没有登录的跳转到登录页面。
- 用户权限判断。
- 操作日志…
6、SpringMVC的执行流程是什么?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IH4xeiGX-1618649345864)(E:\imgs\img\SpringMVC执行流程图2.png)]
详细说明:
- 客户发送请求被前端控制器DispatcherServlet接收并拦截。
- 前端控制器调用HandlerMapping根据请求的URL查找对应的Handler。
- 返回给前端控制器一个HandlerExecutionChain对象其中有对应的Handler。
- 由前端控制器请求给HandlerAdapter处理器适配器,去执行该请求。
- 根据请求执行Controller中的方法(Service、Dao、Mysql)
- 获取完数据和视图后将这些信息封装为一个ModelAndView对象并返回给前端控制器。
- 前端控制器在通过视图解析器ViewResolver对象解析该视图、并返回视图名称。
- 找到与视图名对应的文件后将数据渲染到视图中并响应给用户。
大概:
前端控制器拦截请求–>根据请求查找对应的Handler–>执行Handler–>选择ViewResolver–>通过ViewResolver渲染视图并返回结果。
7、Struts2和SpringMVC的区别?
-
核心控制器(前端控制器、预处理控制器):这些控制器主要用于处理所有请求、对字符编码、文件上传、参数接收、异常处理等进行统一的特殊处理。
SpringMVC的底层由Servlet来实现的。
Struts2的底层由Filter来实现的。
-
控制器实例:SpringMVC是基于方法设计的而Struts2是基于对象、每一次请求都会实例一个action每个action被注入属性。而SpringMVC由于底层是Servlet只有一个实例、每次请求执行对应方法。
(单例实例、要避免全局变量的修改、会产生线程安全问题)
-
管理方式:SpringMVC是Spring中的一个模块、所以Spring对SpringMVC的控制器管理更加方便、而且提供了各种功能的注解。而Struts2需要在XML中配置参数来管理。
-
参数传递:SpringMVC通过方法的形参进行接收、Struts2通过ValueStack值栈进行传递和赋值。
-
学习难度:SpringMVC比较简单、容易上手、Struts2有很多技术点、如拦截器、值栈和OGNL表达式、学习成本较高。
-
拦截器实现机制:SpringMVC是独立的AOP方式、Struts2有自己的Intercept机制。
-
处理返回JSON数据:SpringMVC使用@ResponseBody或@RestController注解返回JSON数据、Struts2通过插件的方式进行处理。
8、Spring中的两大核心是什么?
Spring是什么?
Spring是J2EE应用程序框架、是轻量级的IOC和AOP容器框架、主要对JavaBean的生命周期进行管理的轻量级容器、单独使用。
1、控制反转:IOC(Inversion of Control)
控制权反转
原来:controller创建service创建dao,缺点:高耦合
Spring:将我们要使用的对象自动注入到容器中,降低耦合度。
实现原理:通过配置文件(XML)+反射/工厂+容器(Map)
2、面向切面:AOP(Aspect Oriented Programming)
实现原理:使用动态代理的方式在执行方法的前后或出现异常后作出相关逻辑操作(可加入事 务、日志、安全等与业务无关的)。
9、AOP是什么?能做什么?
面向切面编程:AOP(Aspect Oriented Programming)
核心:使用动态代理的方式在执行方法的前后或出现异常后作出相关逻辑操作。
对业务的增强、可以做与主业务无关的逻辑。
如:事务处理:执行方法前、开启事务、执行完后关闭事务、出现异常回滚事务。
日志、安全等
10、Spring事务的传播特性是什么?
传播特性:指多个事务的存在是如何处理的策略
事务策略常量:
常量以**PROPAGATION_**开头、即:PROPAGATION_XXX
- REQUIRED:(默认)指定方法必须在事务内执行、若存在事务则支持当前事务、若没有事务,则创建事务。
- SUPPORTS:如果存在事务则支持当前事务、若没事务,可非事务方式执行。
- MANDATORY:如果存在事务则支持当前事务、若没有事务、则抛出异常。
- REQUIRES_NEW:总是新建一个事务、若存在事务,就讲当前事务挂起、知道新事物执行完毕。
- NOT_SUPPORTED:不能再事务环境中执行、如果存在事务、将事务挂起。
- NEVER:不能再事务环境中执行、如果存在事务,则抛异常。
- NESTED:如果存在事务则在当前事务内嵌套事务、若没有则创建。
11、Spring事务的隔离级别是什么?
事务隔离级别常量:
这些常量以ISOLATION_开头,即:ISOLATION_XXX
- DEFAULT:数据库默认,MySQL默认为:REPEATABLE_READ; Oracle默认为:READ_COMMITTED
- READ_UNCOMMITTED:读未提交、未解决任何并发问题(脏读)
- READ_COMMITTED:读已提交、解决脏读,存在 不可重复读与幻读
- REPEATABLE_READ:可重复读、解决脏读、不可重复读、存在幻读。
- SERIALIZABLE:串行化、不存在并发问题
12、什么是ORM?
对象关系映射(Object Relational Mapping,ORM)作用是在关系型数据库和java对象之间做一个映射。
ORM封装了数据库操作、因此可不写SQL语言、开发者只需使用面向对象编程与数据对象直接交互即可。
Java的ORM框架有:ibatis、Hibernate…
ORM优点:
- 容易更新和维护和重用代码
- 业务代码简单、语义性好、容易理解。
ORM缺点:
- 不是轻量级工具、学习成本高。
- 复杂查询ORM无法表达、性能不佳。
- 无法了解底层数据库的操作。
13、MyBatis与Hibernate的区别?
相同点:
都是java中的ORM框架、屏蔽了JDBC底层实现细节、不用与JDBC的API打交道、就可完成对数据库 的持久化操作。
**JDBC缺点:**代码固定、sql与java代码混杂、需要拼接sql、实现细节繁琐。
**MyBatis优点:**半自动的ORM映射工具、屏蔽了JDBC的实现细节、将sql与java代码进行分离、提供了将结果集自动封装为对象集合(queryForList返回对象集合、queryForObject返回单个对象)、提供了对象属性传递sql的参数。
**Hibernate优点:**全自动的ORM映射工具、自动生成sql并执行并返回结果。
不同点:
- Hibernate功能比MyBatis强大、因为自动生成SQL。
- MyBatis要在XML文件中写SQL语句、而Hibernate无法控制sql语句、因此无法写特定的高效sql。
- MyBatis更加灵活可以写复杂的sql、而Hibernate是自动生成的sql、不能写复杂的sql。
- MyBatis学习成本简单、是面向sql的、考虑对象间复杂的映射关系。
14、Hibernate映射对象的状态
**临时状态/瞬时状态:**用new创建、没有被持久化、没有用session的方法去操作临时对象。
**持久化状态/托管状态:**已经被持久化、加入session的缓存中、但session没有关闭该状态的对象为持久化对象。
**游离状态/脱管状态:**已经被持久化、但不处于session中。
**删除状态:**对象有关联的id、并在session管理下、但已经被事务提交的时候删除、如果没有事务就不能删除。
15、Hibernate缓存
1、为什么用Hibernate缓存?
为了提高访问速度、将磁盘或数据库访问变成内存访问。
2、Hibernate缓存原理?
Hibernate缓存包括两大类:一级缓存 和 二级缓存。
1、一级缓存:session的缓存内置不能被卸载、是事务范围的缓存。
2、二级缓存:SessionFactory的缓存、由于该对象的生命周期和应用程序的整个过程对应、因此二 级缓存是进程范围或集群范围的缓存、可能出现并发问题、要采取适当的并发访问策略。 二级缓存是可选的、默认不使用该缓存。
简单说明:
Hibernate缓存分为:一级缓存 和 二级缓存。
一级缓存是Session级别的缓存、在事务范围内有效,是内置的不能被卸载。二级缓存是 SessionFactory级别的缓存、从应用启动到应用结束有效果、是可选的、默认没有二级缓存。
保存数据后,在内存中保存一份、如果更新了数据就要同步更新。
什么样的数据适合放入二级缓存中?
- 很少被修改的数据
- 经常被查询的数据
- 不太重要的数据、偶尔出现并发的数据。
- 不会被并发访问的数据
- 常量数据
扩展: 二级缓存默认不支持分布式缓存、使用Memcahe、Redis来代替二级缓存。
16、WebService的使用场景?
WebService是一个SOA(面向服务编程)的构架、不依赖语言和平台、可实现不同语言间的互相调用、通过Internet基于HTTP协议的网络应用间的交互。
- 异构系统的整合(不同语言)
- 不同客户端的整合(浏览器、手机端(Android、IOS、塞班)、微信单、PC…)
例子:
天气预报:通过实现WebService客户端调用远程天气服务实现。
单点登录:一个服务是所有系统的登录。
17、Activity是什么?
Activity是一个业务流程管理(BPM)和工作流程系统、适用于开发人员和系统管理员、核心是快速稳定的BPMN2流程引擎、易与Spring整合使用。
主要在OA中,将线下流程放到线上、将现实生活中一些流程固定的活定义到系统中,然后通过输入表单数据完成业务。
六、高级部分
1、Linux是什么?用来做什么?
Linux是一个长时间运行稳定的操作系统、一般会作为服务器(Web、DB、App等)
Linux本身有C的编译环境、我们的一些软件没有软件包(Redis、Nginx等)需要在Linux的C编译环境 编译到软件包。
2、Linux有哪些常用命令?
常用:
pwd 获取当前路径
cd 跳转目录
su -u 切换到管理员
ls ll 列举目录
文件操作命令:
文件: tail 查看; rm -rf vi
文件夹:mkdir rm -r
3、用什么连接远程Linux服务器?
需要依赖于Linux服务器安装SSH服务端、SSH服务的端口为22;
需要依赖于Linux服务器安装SFTP服务端、SFTP服务的端口为25;
使用SSH连接Linux服务器、类似Windows的远程连接、但Linux通过SSH连接上后没有图形界 面、全是命令行。(客户端:Putty、Xshell)
使用SFTP来连接SFTP服务端,用来上传和下载文件。(客户端:Winscp、XFTP)
常用的组合:Putty+ Winscp 或 Xshell + XFTP = xmanager
简单说明:
使用xshell、putty等ssh客户端来连接服务器、使用xftp、winscp等sftp客户端来上传和下载文件、连 接和上传下载、依赖于服务器的ssh、sftp服务、Linux服务器需要启动这两个服务。
4、云主机?
云主机就是一些云服务运营商,提供的远程的服务器功能、开发者或企业只需按需付费即可租用对应的服务器。
使用ssh和sftp来进行操作。
5、数据库有哪些优化方面?
定位;查询;定位慢查询
优化手段
- 创建索引:创建合适的索引、在索引中查询到后直接找对应的记录。
- 分表:当一张表的数据量较多或一张表的某些字段值较多并很少用时,采用水平分表和垂直分表优化。
- 读写分离:当一台服务器不能满足需求时,采用读写分离进行集群。
- 缓存:使用Redis缓存。
6、如何查询慢查询并定位慢查询?
在项目测试之前启动mysql数据库时开启慢查询、并把执行慢的sql写入日志中,运行一定时间后,通过查看日志找到慢查询sql。
使用Explain慢查询sql来分析sql的问题。
7、数据库优化要遵循的范式?
数据库表设计时需要遵循的方式:
表的范式要先符合1NF才能满足2NF进一步满足3NF。
1NF:表的列具有原子性、列的信息不能分解。
2NF:表中的记录是唯一的、(设置主键即可实现)
3NF:表中不能用冗余数据。
反3NF:没有冗余的数据库未必是好的数据库、为了提高效率必须降低范式标准、适当保留冗余数据。
8、怎么选择合适的存储引擎?
常用存储引擎:MyISAM、innodb、memory
MyISAN: 如果表对事务要求不高、同时是以查询和添加为主的,可考虑使用该存储引擎。比如:发帖表、回复等。
INNODB: 对事务要求高,保存的数据都是重要数据。比如:订单表,账号表。
Memory: 对数据变化频繁、无需入库、同时又频繁的查询和修改可考虑该存储引擎。
9、MyISAM和INNODB的区别?
- 事务安全:myisam不支持事务而innodb支持。
- 查询和添加速度:myisam不支持事务就不用考虑同步所,所以查询和添加的速度快。
- 支持全文索引:myisam支持,innodb不支持。
- 外键:myisam不支持,innodb支持(通常不设置外键,在程序中保证数据的一致)
10、怎么创建合适的索引?
索引是帮助dbms高效获取数据的数据结构。
分类:普通索引、唯一索引、主键索引、全文索引。
- 普通索引:允许出现重复值
- 唯一索引:不能有重复值。
- 主键索引:设置主键时创建索引、唯一且没有null值。
- 全文索引:对表中的文本域进行索引。
11、索引使用的技巧
1、使用索引的弊端:
- 占用磁盘内存
- 对增删改操作速度变慢。
2、什么场景下使用索引?
- 在where条件经常使用、如果不查询就无意义。
- 该字段内容不是唯一的值(sex)。
- 字段内容不频繁修改。
3、使用技巧:
- 对于创建多列索引,不是使用的第一部分就不要使用索引。
- 使用like的查询、如果是’%abc’不会用索引而’abc%'会使用索引。
- 要求使用的所有字段,必须单独使用时才能用索引。
- 如果列类型是字符串、一定要在条件中将数据使用引号引起来,否则不使用。
- 如果使用全表扫描比使用索引快,则不使用索引。
12、数据库分表
分表分为水平分表(按行)和垂直分表(按列)。
为什么分表?
如果表数据达到百万级别、查询效率会很低容易造成表锁,而水平分表能减少这种压力。
如果一张表中某个字段值非常多、而且在很少查询的情况下,可以将这些字段单独放到一个表中、通过外键关联起来。
水平分表策略:
- 按时间分表:有一定举行线性。
- 按区间范围分表:在有严格的自增id需求上。
- hash分表:通过id或名称通过一定的hash算法计算出数据存储表的表名然后访问相应的表。
13、读写分离
数据库支持的最大并发连接数是有限的,如果用户并发访问过多、一台服务器满足不了要求就可以用集群处理,Mysql的集群处理常用的是读写分离。
主从同步
数据库会把数据持久化到磁盘、如果集群必须确保每个数据库服务器的数据是一致的。
能改变数据库数据库的操作都往一台数据库去写,而其他数据库从主数据库上同步数据。
读写分离
使用负载均衡来实现写的操作都往主数据去、而读的操作往从服务器去。
14、缓存
在持久层(dao)和数据库之间添加一个缓存层、如果用户访问的数据已经缓存起来时,在用户访问时直接从缓存中获取、不用访问数据库。
而缓存是操作内存的,访问速度快。
缓存作用: 减少数据库服务器压力,减少访问时间。
使用Redis来作为重要缓存,对缓存的数据进行集中处理。
15、SQL语句优化技巧
DDL优化:
1、通过禁用索引来提供导入数据性能,针对导入;
-- 去除键 key
alter table test1 disable keys;
-- 批量插入数据
insert into test1 select * from test;
-- 恢复键
alter table test1 enable keys;
2、关闭唯一校验
-- 关闭
set unique_checks = 0;
-- 开启
set unqiue_checks = 1;
3、修改事务提交方式(变为多次提交为一次)
-- 关闭
set autocommit = 0;
-- 开启
set autocommit = 1;
DML优化
insert into test values (1,2);
insert into test values (1,3);
insert into test values (1,4);
-- 合并为一条
insert into test values (1,2),(1,3),(1,4);
16、JDBC批量插入几百万条数据如何实现?
1、变多次提交为一次
2、使用批量操作
像这样的批量插入数据操作能不使用代码就不使用,可使用存储过程来实现。
17、Redis部分
1、什么是Redis?
redis是一个key-value的NoSQL数据库,先存到内存中,根据一定策略持久化到磁盘,即使断点也不丢失数据,支持的数据类型较多。
主要用来做缓存数据和web集群时当做中央缓存存放session。
2、Redis的使用场景?
- 缓存:将经常查询很少修改的数据,放入内存中,以便减少访问时间,减轻压力。
- Redis中的计数器是原子性的内存操作,可解决库存移除问题。
- session缓存服务器:web集群时作为session的缓存服务器。
3、Redis对象保存方式?
方式一:将对象转为JSON字符串、当做字符串处理,使用get/set设置。
优点:设置和获取简单。
缺点:没有专门的方法,需要把对象转换为JSON
方式二:使用字节,将对象序列号为字节保存。
JSON转对象消耗资源的情况分析:
- 使用json转换lib是否会出现性能问题。
- 数据量的级别,如果是大数据对象,建议采用存储序列化对象方式,如果是少量数据,建议采用json转换成String方式。
4、Redis数据淘汰机制
-
Redis允许用户设置最大使用内存大小(server.maxmemory),在内存限定的情况下是有用的。
- 比如:在一台8G电脑上部署了4个Redis服务点,每个服务店分配1.5G内存大小,减少内存紧张的情况,由此获取更为稳健的服务。
-
内存大小有限、需要保存有效的数据。
-
Redis内存数据集大小上升到一定大小时,会施行数据淘汰策略。
-
Redis提供了六种策略:
-
volatile-lru:从已设置过期时间的数据集中挑选最近最少使用的数据淘汰。
-
volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰。
-
volatile-randorn:从已设置过期时间的数据集中任意选择数据淘汰。
-
allkeys-lru:从数据集中挑选最近最少使用的数据淘汰。
-
allkeys-randorn:从数据集中任意选择数据淘汰。
-
no-enviction(驱逐):禁止驱逐数据。
redis确定驱逐某个键值对后,会删除这和数据并将这个数据变更消息发布到本地(AOF持久化)和从机(主从连接)。
-
5、Java访问Redis和集群
访问
- 使用Redis,Java客户端访问redis服务器,类似通过JDBC访问Mysql。
- 如果是Spring进行集成式,可使用SpringData访问Redis。
- SpringData是对Redis的二次封装。
集群
当一台服务器无法满足要求,可使用Redis集群来处理,类似MySQL的读写分离。
18、微信公众号的分类和开发原理?
分类
- 公众号:个人和企业都能申请。
- 服务号:企业才能申请。
- 企业号:企业才能申请。
原理
微信公众平台开发者,通过接入认证的方式,让我们的服务器能处理来自微信服务器转发的微信用户的请求,处理完后返回给微信服务器,由微信服务器对用户响应。
19、怎么把微信和业务平台绑定?
微信用户和注册用户绑定?
用户注册实体中包含一个微信号字段,当进行绑定时就是修改用户的微信号字段,在进行菜单跳转到页面后,就无法直接获取微信号的,要通过微信网页授权来获取微信号。
七、项目和业务部分
1、项目分类
公司做的项目分为两种:项目、产品。
项目: 给一些公司接的项目、开发完成后,会交互,后面这个项目代码就不在维护了。
产品: 考虑扩展性和基本业务,可在这个产品上进行定制开发。
2、项目参与者
产品经理PM、架构师SE。
- 开发团队:开发代码完成需求
- 测试团队:测试功能。
- UI:界面设计,静态代码。
- 资料:负责界面的文字描述。
- OA:通过项目质量监控和PM,SE同级。
开发和UI和资料,协同设计和开发,开发完成后转测试,测试完成后得出测试报告,提交BUG。
3、项目流程
- 进行分析和开工会。
- 需求分析
- 需求设计
- 项目开发迭代(会经过多个迭代)
- 项目验收
- 项目总结
4、业务注意事项
- 不要在项目中说同一个模块,如果要说是后面进行改进。
- 多写业务
谢谢观看、祝大家找到理想的工作!
更多推荐
2021 最新版Java开发面试题
发布评论