1.Session和Cookie的区别
2.Session的原理和主要作用
- Session由服务器端创建。保存在服务器端。
- 当用户访问某一个网站,服务器会检测其请求中是否包含sessionId或者session是否已经过期,如果不满足,则创建一个新的session,将sessionId通过响应方式传递给客户端。
- 下一次用户再次访问时,就可以将sessionId传递给服务器,服务器就可以区别不同的用户了
- session的主要作用是页面之间的值传递。默认有效期为30分钟。
- 当一个用户访问某一个网站,点击添加购物车,那么他又向服务器发送了一个新的请求,由于HTTP的无状态特性,服务器并不知道到底是哪个用户发送的请求。引入session后,可以通过sessionID的方式区分用户。此外由于页面之间需要值传递,因此当用户打开这个站点其他页面时,其他页面可以从session中获取对应用户的信息来对页面中相关信息渲染,比如显示当前登陆用户名。
3.如果客户端禁用cokice,session还可以用吗
可以使用,通过URL传参数,但是安全性不高
4.如何防止SQL注入
- 使用预编译的SQL语句 Prepared Statement
- 在Mybatis中使用#{} 而不是用${}
5.Prepared Statement和Statement的区别
- 在代码编写过程中:Statement需要进行字符串拼接,非常麻烦;Prepared Statement使用?占位符代替,相对简洁。
stmt.executeUpdate("insert into tb_name (col1,col2,col2,col4) values ('"+var1+"','"+var2+"',"+var3+",'"+var4+"')");
pstmt = con.prepareStatement("insert into tb_name(col1,col2,col2,col4) values (?,?,?,?)");
pstmt.setString(1,var1);
pstmt.setString(2,var2);
pstmt.setString(3,var3);
pstmt.setString(4,var4);
pstmt.executeUpdate();
- 性能方面。由于Prepared Statement是预编译的,执行同一个SQL语句仅仅参数不同不会再次编译,因此效率要高。Statement每次都要重新编译。
- Prepared Statement可以防止SQL注入问题,安全性更好。并且可以实现批量执行
6.异常相关问题
为什么要处理异常
- 程序在运行过程中会产生各种异常,如果不进行处理的话,就会导致程序中断,无法使用。因此如果不想让程序中断的话,就需要捕获异常,让程序继续执行下去
抛出异常和捕获异常
- 抛出异常:如果程序出现了异常,没有办法将具体的异常打印出来,不做任何处理;程序中断。
- 捕获异常:如果程序出现了异常,就能够详细的打印是什么原因导致了异常并且能够做出相应的处理,能够显示详细的日志,程序不中断。
在方法中使用了throw抛出异常,需要同时在函数声明上声明这个方法抛出异常
public void test() throws Exception {
throw new Exception("exception");
}
try catch finally 这三部分哪个可以省略
- try不可以,catch finally不能同时省略
try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?
- finally 一定会执行,即使是 catch 中 return 了,catch 中的 return 会等 finally 中的代码执行完之后,才会执行。
https://zhuanlan.zhihu.com/p/96032528
try-catch-finally中的return
- 只要finally中有return,那么就直接执行finally块中的return,自动忽略其他的finally
- 如果finally中没有return
- 在catch块中有return,比如return a,那么JVM会将a暂时存起来,等待finally中执行完毕后,在将a取出来返回。即使finally中修改了a的值,那么返回的也是暂存起来的a
- try块中有return同理
- try catch块中都有return,当没有异常发生的时候走的是try中的return,如果有异常则走的是catch中的return
7.Forward和redirect的区别
- forward是服务器内部转发 url不会变化,redirect是重定向 url会变化
- forward客户机只发送一次请求,并且不知道具体是哪个controller响应的;url会请求两次
- forward中request中数据是共享的,redirect不是共享的
- forward效率高
8.POST和GET的区别
- 两者都是TCP协议
- 参数传递方式不同。GET在URL中传递参数,POST在requestBody中传递数据
- 数据长度不同。GET方式受到URL长度的限制。POST参数长度无限制
- GET请求的参数只能是文本数据,POST请求的数据可以是文本数据,也可以是二进制数据
- GET请求不安全,参数暴露,POST请求相对安全
- GET请求效率高,可以使用缓存; POST请求效率低,不适用缓存
- 请求次数不同。GET发送一次,将头部和数据一并发送;POST请求两次,先发送头部,等待服务器响应后继续发送数据
9.工厂模式
为什么要使用工厂模式:
- 主要原因是要解耦,没有工厂模式,创建者和调用者在一起,导致代码的耦合性很高,为了解耦,引入工厂模式,将调用者和创建者分离。
产品等级和产品簇
- 产品等级:即有继承结构的同种类的产品,我们称之为产品等级。比如:苹果手机、小米手机。
- 产品族:一个具体工厂生产的不同等级的一组产品称为一个产品族。比如:小米手机、小米扫地机等。
工厂模式分类
- 无工厂模式的时候,创建者和调用者是在一起的。引入工厂模式就是实现了对象的创建者和调用者的分离。
- 简单工厂,创建一个工厂类,通过传入的内容不同而返回不同的对象。缺点:每增加一个产品就要增加一个具体产品类和修改工厂类,这增加了系统的复杂度,违背了开闭原则(不支持增加新产品,增加新产品需要修改代码)
- 工厂方法:将工厂独立成一个接口,每增加一个新的产品,就创建一个接口的具体实现类,这样就不需要修改原有代码,程序扩展起来非常方便。缺点:容易造成类的数量过多,增加系统的复杂性(支持增加新产品)
- 抽象工厂。(支持增加产品族,但不支持增加新产品)
10.对IOC的理解
- IOC就是将自己设计的Bean对象控制权交给IOC容器控制,而不是在传统的对象中创建。
- IOC包含三大部分,容器,控制反转和依赖注入。
容器 - IOC容器的本质是一个Map,里面保存了所有的bean对象,key为对象的id值,value为bean对象对应的类的一个实例。
控制反转
- 没有IOC之前,我们直接在对象内部通过new进行创建对象 是程序主动去创建依赖对象。从而导致类与类之间高耦合,难于测试;
- 在引入了IOC之后,所有的对象都在bean中创建完成,我们创建对象也不再使用new关键字,而是直接从IOC容器中去取。对象由原来的主动创建转化为了被动获取,实现了控制反转。对象与对象之间是松散耦合,系统灵活性增加
- 通过IOC实现了对象的获取从主动创建到被动接受到转换。
依赖注入:
- IOC容器动态的将某个依赖关系注入到组件之中,从而提升组件复用的频率
优点
- 实现了对象集中管理,实现了资源的易配置
- 降低了模块之间的耦合
缺点
- 配置复杂,不直观
- 由于底层采用的是反射技术,在性能上有一定的损耗
IOC的具体实现
- 创建BeanFactory接口,里面有一个getBean方法
- 创建BeanFacotry的实现类ClassPathXmlApplicationContext。其中包含一个成员变量BeanMap
- 在这个类的构造方法中实现加载xml文件,并解析xml实现bean对象的装载和依赖注入。
- Bean装载
- 首先在构造方法中,需要传入一个参数,参数为xml的路径
- 根据xml的路径,读取到该文件,然后进行xml解析。
- 遍历所有节点,找到为bean的节点,获取到id和class属性
- 根据class属性的值,通过反射的方法创建对象,以id为key,以对象为value,添加到beanMap中。完成bean的注入
- 依赖注入
- 再次循环整个xml中的所有节点,找到bean节点,判断bean节点的子节点中是否存在propoerty节点
- 如果存在,则获取到对象的ref和name属性的值
- 根据name,获取到field对象。根据ref,从IOC容器中找到被依赖对象,最后通过反射给field字段赋值,完成依赖注入