1. forward(转发)和redirect(重定向)的区别:
forward是服务器行为,服务器请求资源,服务器直接访问目标地址的URL,把那个url的响应内容读取出来,然后把这些内容再发给浏览器,所以地址栏还是原来的地址。
Redirect是客户端行为,服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,所以地址栏显示的是新的URL,两次request,第一次客户端request A,服务器响应,并response回来,告诉浏览器,你应该去B.这时候可以看到地址变化,历史的回退按钮也亮了。
2. cookie和session的比较:
a. 存在的位置:cookie存在于客户端,临时文件中;session存在于服务器的内存中,一个session域对象为一个用户浏览器服务。
b. 安全性:cookie以明文的方式存放再客户端,安全性低,可以通过一个加密算法进行加密后存放;session存放于服务器的内存中,所以安全性好。
c. 网络传输量:cookie会传递消息给服务器;session本事存放于服务器,不会有传送流量。
d. 生命周期:cookie的生命周期是累计的,从创建时开始计时,20分钟后,cookie生命洲际结束;session的生命周期时间隔的,从创建时,如果20分钟内访问过session将重新计算session的生命周期;关机会造成session生命周期结束,但是对cookie没影响。关闭tomcat会使session失效
e. 访问范围:cookie为多个用户浏览器共享;session为一个用户独享。
3. JSP内置对象
a. request对象javax.servelt.http.HttpServletRequest,request对象代表客户端的请求信息,主要用于接受通过HTTP协议传送到服务器的数据。
b. response对象javax.servlet.http.HttpServletResponse,response代表的是对客户端的响应,主要是将JSP容器处理过的对象传回到客户端。
c. session对象javax.servlet.http.HttpSession,Session对象是一个JSP内置对象,它在第一个JSP也main被装载时自动创建,完成会话期管理。从一个客户打开浏览器并连接到服务器开始,到客户关闭浏览器离开这个服务器结束,被称为一个会话。当一个客户访问一个服务器时,可能会在这个服务器的几个页面之间切换,服务器通过Session对象知道这是一个客户。
d. application对象javax.servlet.ServletContext,application对象可将信息保存在服务器中,直到服务器关闭,否则application对象中保存的信息会在整个应用中都有效。与session对象相比,application对象生命周期更长,类似于系统的全局变量。
e. out对象javax.servlet.jsp.jspWriter,out对象用于在Web浏览器内输出信息,并且管理应用服务器上的输出缓存区。
f. pageContext对象javax.servelt.jsp.PageContext,pageContext对象的作用是取得任何范围的参数,通过它可以获取JSP页面的out、response、request、session、application等对象在jsp页面可以直接使用pageCOntext对象。
g. config对象javax.servlet.ServletConfig,config对象的主要作用是取得服务器的配置信息。
h. cookie对象,cookie是web服务器保存在用户硬盘上的一段文本。
i. exception对象java.lang.Throwable,exception对象的作用是显示异常信息,只有在包含isErrorPage=”true”的页面才可以使用,在一般的JSP页面中使用该对象将无法编译JSP文件。
4. Spring MVC接收参数的几种方式(原文地址):
a. 直接把表单的参数写在Controller相应的方法的形参中;
b. 通过HttpServeltRequest接收;
c. 通过一个bean来接收;
d. 通过json数据来接收;
5. 事务:
事务是一系列的动作,一旦其中一个动作出现错误,必须全部回滚,系统将事务中对数据库的所有已完成的操作全部撤销,回滚但事务开始的状态,避免出现由于数据不一致而导致的接下来的一系列的错误。事务的出现是为了保证数据的完整性和一致性。事务的四大特性:原子性(确保动作要全部完成)、一致性(完成时数据保持一致的状态)、隔离性(并发事务执行之间无影响)、持久性(一旦事务完成,数据库的改变必须是持久化的)。
事务并发所可能存在的问题:脏读(一个事务读到另一个事务未提交的更新数据)、不可重复读(一个事务两次读同一行数据,可是这两次读到的数据不一样)、幻读(一个事务执行两次查询,但第二次查询比第一次查询多出了一些数据)、丢失跟新(撤消一个事务时,把其他事务已提交的更新的数据覆盖了)。
5种事务隔离级别:TRANSACTION_NONE(jdbc驱动不支持事务)、TRANSACTION_READ_UNCOMMITTED(允许脏读、不可重复读、和幻读)、TRANSACTION_READ_COMMITTED(禁止脏读,但允许不可重复读和幻读)、TRANSACTION_REPEATABLE_READ(禁止脏读和不可重复读,单运行幻读)、TRANSACTION_SERIALIZABLE(禁止脏读、不可重复读和幻读)。隔离级别越高,意味着数据库事务并发性能越差,能处理的操作就越少。
6. Spring中常用的两种事务配置方式:
a. 注解式事务:@Transactional
b. 使用AOP的方式实现事务的配置
7. mybatis如何防止sql注入:
在编写mybatis的映射语句时,尽量采用“#{xxx}”这样的格式,因为${xxx}里面的参数会直接参与sql编译,而sql注入只能对编译过程起作用,所以不能避免注入攻击要用#{xxx},若不得不使用${xxx}这样的参数,要手工做好过滤工作。
8. MyBatis拦截器:
拦截器的一个作用就是我们可以拦截某些方法的调用,我们可以选择在这些被拦截的方法执行前后加上某些逻辑,也可以在执行这些被拦截的方法时执行自己的逻辑而不再执行被拦截的方法。
9. Hibernate一级缓存、二级缓存:
一级缓存就是Session级别,一个Session做了一个查询操作,它会把这个操作的结果放在一级缓存中,如果短时间内这个session又做了同一个操作,那么hibernate直接从一级缓存中拿,而不会再去连数据库取数据。这一级别属于事务范围的缓存,由hibernate管理,一般情况下无需进行干预。
二级缓存就是SessionFactory级别的缓存,就是查询的时候会把查询结果缓存到二级缓存中,如果同一个sessionFactory创建的某个session执行了相同的操作,hibernate就会从二级缓存中拿结果,而不会再去连数据库。这一级别属于进程范围或群集范围的缓存,这一级别的缓存可以进行配置和更改,并且可以动态加载和卸载。很少被修改的数据、不是很重要的数据,允许出现偶尔并发的数据、不会被并发访问的数据适合存放在二级缓存中。
10. 抽象类和接口的对比:
11. Equals方法:
普遍回答是==比较的是内存地址,equals比较的是值。但不是很标准。
Object对象的equals的定义是这样的:
所以在Object中==和equals是没有任何区别的,是用来比较两个对象的引用是否相等,即是否指向同一个对象。
但在String中,重写的equals方法是这样定义的:
String类对equals方法进行了重写,用来比较指向的字符串对象存储的字符串是否相等。其他的一些诸如Double,Date,Integer等都对equals方法进行了重写用来比较指向的对象所存储的内容是否相等。
对于==,如果作用于基本类型的变量,则直接比较其存储的值是否相等;如果作用于引用类型的变量,则比较的是所指向的对象的地址。
对于equals方法,注意:equals方法不能作用域基本数据类型的变量。如果没有对equals方法进行重写则比较的是引用类型的变量所指向的对象的地址;诸如String、Date等对equals方法进行了重写的话,比较的是所指向的对象的内容。
12. Integer和int的区别:
原始类型:boolean,char,byte,short,int,long,float,double
包装类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double
a. Ingeter是int的包装类,int的初值是0,Ingeter的初值为null;
b. 无论如何,Integer与new Integer不会相等。不会经历拆箱过程,new出来的对象放在堆,而非new的Integer常量则在常量池(方法区),它们的内存地址不一样,所以为false;
c. 两个都是非new出来的Integer,如果数在-128到127之间,则是true,否则为false。因为java在编译Integer i2 = 128的时候被翻译成:Integer i2 = Integer.valueOf(128);而valueOf函数会对-128到127之间的数进行缓存。
d. 两个都是new出来的都为false,内存地址不一样。
e. Int和Integer比都为true,因为会把Integer自动拆箱为int再去比。
13. Http协议错误代码大全:
1XX(临时相应):用于表示临时相应并需要请求者执行操作才能继续的状态代码。
2XX(成功):200(成功)服务器已成功处理了请求。
3XX(已重定向):已完成请求,您需要进一步进行操作。
4XX(请求错误):请求可能出错,已妨碍了服务器对请求的处理。
400(错误请求)服务器不理解请求的语法。
401(未授权)请求要求进行身份验证。
403(已禁止)服务器拒绝请求。
404(未找到)服务器找不到请求的网页。
405(方法禁用)禁用请求中指定的方法。
406(不接受)无法使用请求的内容特性来相应请求的网页。
408(请求超时)服务器等候请求时超时。
5XX(服务器错误)这些状态码表示,服务器在尝试处理请求时发生内部错误,这些错误可能是服务器本身的错误而不是请求出错。
14. Static:
Static方法:由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说是没有this的,因为它不依赖于任何对象。在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。
Static变量:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候初始化,存在多个副本,各个对象拥有的副本互不影响。
Static代码块:static块可以置于类中的任何地方,类中可以有多个static块,在类初次被加载的时候,会按照static块的顺序来执行每个static并且只会执行一次。
Java中static关键字不会改变成员的访问全限。Static不允许用来修饰局部变量。
在第一次创建一个类的对象或者第一次调用一个类的静态属性和方法时加载静态类。
类加载期间如果发现有静态属性就给对应的静态属性分配内存空间并赋值(在声明静态变量时不一定赋值),今后调用该类的静态属性时虚拟机会直接寻找该属性先前已经分配的内存空间地址,然后调用其值。基本数据类型的静态变量存在池里面。
15. Java基本类型占用的字节数:
1字节:byte,Boolean,byte范围是-128-127
2字节:short,char
4字节:int,float
8字节:long,double
1字节(byte)=8位(bits)
16. String,StringBuffer和StringBuilder
String字符串常量,StringBuffer字符串变量(线程安全),StringBuilder(非线程安全)。
大部分情况StringBuilder> StringBuffer > String
String用final修饰是不可变的对象,因此在每次对String类型进行改变的时候都等于生成了一个新的String对象,所以它是线程安全的,然后将指针指向新的String对象,所以经常改变内容的字符串最好不要用String,因为每次生成对象会对系统性能产生影响,特别当内存中无引用对象多了以后,JVM的GC就会开始工作,那速度是一定会相当慢的。
而StringBuffer每次都会对StringBuffer对象本身进行操作,而不是生成新的对象,再改变对象引用。
所以字符串对象经常改变的情况下一般推荐使用StringBuffer。
大部分情况StringBuffer> String
StringBuffer上的主要操作是append和insert方法,可重载这些方法,以接受任意类型的数据。
StringBuilder不能保证同步,该类被设计用作StringBuffer的一个简易替换,用在字符串缓冲区被单个线程使用的时候。
String name = ”I ” + ”am ” + ”chenssy ” ;在JVM眼中就是String name = ”I am chenssy ”
17. 序列化和持久化的区别与联系。
持久化即把数据(如内存中的对象)保存到可永久保存的存储设备中。持久化的主要应用是将内存中的对象存储再关系型的数据库中,当然也可以存储在磁盘文件中、XML数据文件中。JDBC,文件IO都是一种持久化机制。
序列化就是把内存中的对象序列化成流、或者把流反序列化成对象,Serialize,Deserialize.
序列化是为了解决对象的传输问题,传输可以在线程之间、进程之间、内存外存之间、主机之间。
18. Java类的加载机制:
a. 在初始化类的时候,首先加载父类的静态变量和静态语句块(按照代码上下顺序执行),然后加载子类的,然后加载父类的非静态变量和非静态语句块(按照代码上下顺序执行),最后加载父类的构造函数,然后加载子类的非静态变量和非静态语句块(按照代码上下顺序执行),最后加载子类的构造函数。类的静态方法和非静态方法只有在主动调用的时候才执行。
b. 如果父类存在,子类可以不存在;如果子类存在,父类必须存在。
c. 类加载机制首先是分配内存空间(堆空间,物理存储地址,每个属性都需要分配物理空间,方法是不需要的,且这个时候物理空间指向的是空null);
当空间分配好后,进行属性初始化,把值放在栈空间中,前面的第一步过程中物理空间存储地址指向这个栈空间,这样就完成了属性值的初始化;当属性值完成了初始化的时候,就开始调用构造函数了,执行构造函数里面的代码块。
d. 在子类初始化的时候必须先去初始化父类,给子类和所有的父类都分配了内存空间后,先搞定堆内存指向null,才会去进行属性值的初始化,也就是在栈空间里面是属性的内容,前面分配的内存空间地址这个时候就指向栈内存的值;同名属性不会被子类给覆盖掉,只是把父类的隐藏掉;同名方法是多态,只会去调用子类的重载方法(也就是说父类引用指向子类对象时,父类引用调用的时子类重载的方法。)。
19.nginx和tomcat的区别:
Apache/Nginx应该叫做 HTTP Server,即安装后生成httpd服务。一个 HTTP服务器,其关心的是 HTTP 协议层面的传输和访问控制,所以在 Apache/Nginx 上你可以看到代理、负载均衡等功能。客户端通过 HTTP Server 访问服务器上存储的资源(HTML 文件、图片文件等等)。通过 CGI 技术,也可以将处理过的内容通过 HTTP Server 分发,但是一个 HTTP Server 始终只是把服务器上的文件如实的通过 HTTP 协议传输给客户端。
Tomcat则是一个 Application Server,或者更准确的来说,是一个「Servlet/JSP」应用的容器(Ruby/Python 等其他语言开发的应用也无法直接运行在 Tomcat 上)。而应用服务器,则是一个应用执行的容器。它首先需要支持开发语言的 Runtime(对于 Tomcat 来说,就是 Java),保证应用能够在应用服务器上正常运行。其次,需要支持应用相关的规范,例如类库、安全方面的特性。对于 Tomcat 来说,就是需要提供 JSP/Sevlet 运行需要的标准类库、Interface 等。
20.nginx支持的负载均衡调度算法方式如下:
weight轮询(默认):接收到的请求按照顺序逐一分配到不同的后端服务器,即使在使用过程中,某一台后端服务器宕机,nginx会自动将该服务器剔除出队列,请求受理情况不会受到任何影响。 这种方式下,可以给不同的后端服务器设置一个权重值(weight),用于调整不同的服务器上请求的分配率;权重数据越大,被分配到请求的几率越大;该权重值,主要是针对实际工作环境中不同的后端服务器硬件配置进行调整的。
ip_hash:每个请求按照发起客户端的ip的hash结果进行匹配,这样的算法下一个固定ip地址的客户端总会访问到同一个后端服务器,这也在一定程度上解决了集群部署环境下session共享的问题。
fair:智能调整调度算法,动态的根据后端服务器的请求处理到响应的时间进行均衡分配,响应时间短处理效率高的服务器分配到请求的概率高,响应时间长处理效率低的服务器分配到的请求少;结合了前两者的优点的一种调度算法。但是需要注意的是nginx默认不支持fair算法,如果要使用这种调度算法,请安装upstream_fair模块
url_hash:按照访问的url的hash结果分配请求,每个请求的url会指向后端固定的某个服务器,可以在nginx作为静态服务器的情况下提高缓存效率。同样要注意nginx默认不支持这种调度算法,要使用的话需要安装nginx的hash软件包
21.NIO
IO是面向流的处理,NIO是面向块(缓冲区)的处理
面向流的I/O 系统一次一个字节地处理数据。
一个面向块(缓冲区)的I/O系统以块的形式处理数据。
NIO主要有三个核心部分组成:buffer缓冲区、Channel管道、Selector选择器
NIO就是通过Channel管道运输着存储数据的Buffer缓冲区的来实现数据的处理!
IO是单向的,NIO由于Channel所以是双向的。
22.String(原文链接)
(1)单独使用""引号创建的字符串都是常量,编译期就已经确定存储到String Pool常量池中;
(2)使用new String("")创建的对象会存储到heap中,是运行期新创建的;
new创建字符串时首先查看池中是否有相同值的字符串,如果有,则拷贝一份到堆中,然后返回堆中的地址;如果池中没有,则在堆中创建一份,然后返回堆中的地址(注意,此时不需要从堆中复制到池中,否则,将使得堆中的字符串永远是池中的子集,导致浪费池的空间)!
(3)使用只包含常量的字符串连接符如"aa" + "aa"创建的也是常量,编译期就能确定,已经确定存储到String Pool中;
(4)使用包含变量的字符串连接符如"aa" + s1创建的对象是运行期才创建的,存储在heap中;
23.JDK8新特性:
(1)Lambda表达式和函数式接口,Lambda表达式(也称为闭包)允许我们将函数当成参数传递给某个方法,或者把代码本身当作数据处理。
(2)接口的默认方法和静态方法,接口的某个方法用default修饰后可以在接口里实现,然后在实现方法里可以不用写实现。
(3)Stream API,例:long count = Stream.of(strArr).filter(w -> w.length() > 3).count()(统计一个字符串类型数组中,所有长度大于3的元素)
(4)新的日期和时间 API,LocalDate一个带有年份、月份和天数的日期
网友评论