常见Java面试题(二)

get和post请求的区别

1.Get请求提交的数据会在地址栏显示出来,而post请求不会再地址栏显示出来.
2.传输数据的大小,Get请求由于浏览器对地址长度的限制而导致传输的数据有限制。而POST请求不会因为地址长度限制而导致传输数据限制。
3、安全性,POST的安全性要比GET的安全性高。由于数据是会在地址中呈现,所以可以通过历史记录找到密码等关键信息。

forward()与redirect()的区别

1、forward是服务器端的转向而redirect是客户端的跳转。
2、使用forward浏览器的地址不会发生改变。而redirect会发生改变。
3、Forward是一次请求中完成。而redirect是重新发起请求。
4、Forward是在服务器端完成,而不用客户端重新发起请求,效率较高

jsp有哪些内置对象?作用分别是什么

9个内置的对象:
1.request 用户端请求,此请求会包含来自GET/POST请求的参数
2.response 网页传回用户端的响应
3.pageContext 取得任何范围的参数, 通过它可以获取 JSP页面的out、request、reponse、session、application 等对象。
4.session 用于保存用户的信息
5.application 将信息保存在服务器中
6.out 用来输出
7.config 取得服务器配置信息
8.page JSP网页本身
9.exception 显示异常信息
四大作用域:pageContext request session application 可以通过jstl从四大作用域中取值.
Jsp传递值:request session application cookie也能传值

session和cookie的区别

Session和cookie都是会话(Seesion)跟踪技术。Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份。但是Session的实现依赖于Cookie,sessionId(session的唯一标识需要存放在客户端)
1、cookie数据存放在客户的浏览器上,session数据放在服务器上。
2、cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session。
3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie。
4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。

关系数据库三范式

要想满足第二范式必须先满足第一范式,要满足第三范式必须先满足第二范式。
1.第一范式(1NF)无重复的列
第一范式(1NF)是指数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。列数据的不可分割
2.第二范式(2NF)属性完全依赖于主键(消除部分子函数依赖)
第二范式(2NF)要求数据库表中的每个行必须可以被唯一地区分。为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识。(主键)
第二范式(2NF)要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性,如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识。简而言之,第二范式就是属性完全依赖于主键。
3.第三范式(3NF)属性不依赖于其它非主属性(消除传递依赖)
满足第三范式(3NF)必须先满足第二范式(2NF)。简而言之,第三范式(3NF)要求一个数据库表中不包含已在其它表中已包含的非主关键字信息。

事务四个基本特征或ACID特性

事务必须满足四大特征:原子性,一致性,隔离性,持久性
1.原子性:表示事务内操作不可分割。要么都成功、要么都是失败.
2.一致性:要么都成功、要么都是失败.失败了要对前面的操作进行回滚。
3.隔离性:一个事务开始后,不能受其他事务干扰。
4.持久性:事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即使系统崩溃,修改的数据也不会丢失。

说一下你对JDBC的理解

Java database connection java数据库连接.数据库管理系统(mysql oracle等)是很多,每个数据库管理系统支持的命令是不一样的。
Java只定义接口,让数据库厂商自己实现接口,对于我们者而言。只需要导入对应厂商开发的实现即可。然后以接口方式进行调用.(mysql + mysql驱动(实现)+JDBC)
jdbc是 java数据库连接技术的简称,由一组使用java语言编写的类与接口组来成,可以为多种关系数据库提供统一访问。
Sun公司提供了JDBC的接口示范 —— JDBC API ,而数据库厂商或第三方中间厂商根据该接口规范提供针对不同数据库的具体实现 —— JDBC 驱动

写一个简单的JDBC的程序

注册驱动(com.mysql.jdbc.Driver,oracle.jdbc.driver.OracleDriver)
建立连接DriverManager.getConnection(url,username, password)
创建执行SQL的语句
执行语句 executeQuery executeUpdate
释放资源(是否连接要从小到大,必须放到finally

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public static void main(String[] args) throws Exception {
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;

//加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
//通过驱动管理类获取数据连接
connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","123456");
//定义SQL语句?示占位符
String sql = "select * from user where username = ?";
//获取预处理的statement
statement = connection.prepareStatement(sql);
//设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
statement.setString(1,"王五");
//向数据库发出sql执行查询,查询出结果集
resultSet = statement.executeQuery();
//遍历查询结果集
while(resultSet.next()){
System.out.println(resultSet.getString("id")+" "+resultSet.getString("username"));
}
//释放资源
resultSet.close();
statement.close();
connection.close();
}

JDBC中的PreparedStatement相比Statement的好处

1.PreparedStatement是预编译的,比Statement速度快
2.代码的可读性和可维护性
虽然用PreparedStatement来代替Statement会使代码多出几行,但这样的代码无论从可读性还是可维护性上来说.都比直接用Statement的代码高很多档次:

1
2
3
4
5
6
7
stmt.executeUpdate("insert into tb_name (col1,col2,col2,col4) values ('"+var1+"','"+var2+"',"+var3+",'"+var4+"')"); 
perstmt = con.prepareStatement("insert into tb_name (col1,col2,col2,col4) values (?,?,?,?)");
perstmt.setString(1,var1);
perstmt.setString(2,var2);
perstmt.setString(3,var3);
perstmt.setString(4,var4);
perstmt.executeUpdate();

3.安全性,PreparedStatement可以防止SQL注入攻击,而Statement却不能。

MVC模式

MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。
最简单的、最经典就是Jsp(view) + Servlet(controller) + JavaBean(model)

Spring中的两大核心

Spring是什么?
spring是J2EE应用程序框架,是轻量级的IoC和AOP的容器框架(相对于重量级的EJB),主要是针对javaBean的生命周期进行管理的轻量级容器,可以和SpringMVC、Mybatis框架组合使用。
1、IOC(Inversion of Control )或DI(Dependency Injection)
IOC控制权反转
原来:Service需要调用DAO,Service就需要创建DAO
Spring:Spring发现你Service依赖于dao,就给你注入.
核心原理:就是配置文件+反射(工厂也可以)+容器(map)
2、AOP:面向切面编程
核心原理:使用动态代理的设计模式在执行方法前后或出现异常做加入相关逻辑。
我们主要使用AOP来做:
1、事务处理 执行方法前开启事务,执行完成后关闭事务,出现异常后回滚事务
2、权限判断 在执行方法前,判断是否具有权限
3、日志 在执行前进行日志处理

SpringMVC工作流程

1、用户发送请求至前端控制器DispatcherServlet。
​2、DispatcherServlet收到请求调用HandlerMapping处理器映射器。
​3、处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(二者组成HandlerExecutionChain)一并返回给DispatcherServlet。
​4、DispatcherServlet调用HandlerAdapter处理器适配器。
​5、HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
​6、Controller执行完成返回ModelAndView。
​7、HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
​8、DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
​9、ViewReslover解析后返回具体View,这个view不是完整的,仅仅是一个页面(视图)名字,且没有后缀名。
​10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
​11、DispatcherServlet响应用户。

Spring的事务传播特性

  1. PROPAGATION_REQUIRED: 如果存在一个事务,则支持当前事务。如果没有事务则开启
  2. PROPAGATION_SUPPORTS: 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行
  3. PROPAGATION_MANDATORY: 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
  4. PROPAGATION_REQUIRES_NEW: 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
  5. PROPAGATION_NOT_SUPPORTED: 总是非事务地执行,并挂起任何存在的事务。
  6. PROPAGATION_NEVER: 总是非事务地执行,如果存在一个活动事务,则抛出异常
  7. PROPAGATION_NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行

Required 需要 如果存在一个事务,则支持当前事务。如果没有事务则开启
Supports 支持 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行
Mandatory 必要的 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
required_new 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
Not_support 总是非事务地执行,并挂起任何存在的事务。
Never 绝不 总是非事务地执行,如果存在一个活动事务,则抛出异常
Nested 嵌套的 如果有就嵌套、没有就开启事务

数据库优化

定位:查找、定位慢查询
优化手段:
a)创建索引:创建合适的索引,我们就可以现在索引中查询,查询到以后直接找对应的记录。
b)分表:当一张表的数据比较多或者一张表的某些字段的值比较多并且很少使用时,采用水平分表和垂直分表来优化
c)读写分离:当一台服务器不能满足需求时,采用读写分离的方式进行集群。
d)缓存:使用redis来进行缓存

Redis数据淘汰机制

redis 提供 6种数据淘汰策略:
volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
no-enviction(驱逐):禁止驱逐数据

抽象类和接口的区别

两者的区别:
1.抽象类可以有构造方法,接口中不能有构造方法。
2.抽象类中可以有普通成员变量,接口中没有普通成员变量。
3.抽象类中可以包含非抽象普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的方法。
4.抽象类中的抽象方法的访问权限可以是public、protected 和(默认类型,虽然eclipse不报错,但也不能用,默认类型子类不能继承),接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。
5.抽象类中可以包含静态方法,在 JDK1.8 之前接口中不能不包含静态方法,JDK1.8 以后可以包含。
6.抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问权限可以是任意的,但接口中定义的变量只能是 public static final 类型的,并且默认即为public static final类型。
7.一个类可以实现多个接口,用逗号隔开,但只能继承一个抽象类,接口不可以实现接口,但可以继承接口,并且可以继承多个接口,用逗号隔开。

欢迎关注我的其它发布渠道