各种面试题4

Posted shan1393

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了各种面试题4相关的知识,希望对你有一定的参考价值。

1、面向对象的特征有哪些方面?

封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。

多态性:多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单的说就是用同样的对象引用调用同样的方法但是做了不同的事情。多态性分为编译时的多态性和运行时的多态性。方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)。

 

2、访问修饰符public,private,protected,以及不写(默认)时的区别?

作用域    当前类  同包 子类 其他

public        √        √       √      √

protected  √        √       √      ×

default       √       √       ×      ×

private       √        ×      ×      ×

类的成员不写访问修饰时默认为default。默认对于同一个包中的其他类相当于公开 public),对于不是同一个包中的其他类相当于私有(private)。受保护 protected)对子类相当于公开,对不是同一包中的没有父子关系的类相当于私有。

3、构造器(constructor)是否可被重写(override?

答:构造器不能被继承,因此不能被重写,但可以被重载。

4、两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?

答:不对,如果两个对象xy满足x.equals(y) == true,它们的哈希码(hash code)应当相同。Java对于eqauls方法和hashCode方法是这样规定的:(1)如果两个对象相同(equals方法返回true),那么它们的hashCode值一定要相同;(2)如果两个对象的hashCode相同,它们并不一定相同。

5、抽象类(abstract class)和接口(interface)有什么异同?

答:抽象类和接口都不能够实例化,但可以定义抽象类和接口类型的引用。一个类如果继承了某个抽象类或者实现了某个接口都需要对其中的抽象方法全部进 行实现,否则该类仍然需要被声明为抽象类。接口比抽象类更加抽象,因为抽象类中可以定义构造器,可以有抽象方法和具体方法,而接口中不能定义构造器而且其 中的方法全部都是抽象方法。抽象类中的成员可以是private、默认、protectedpublic的,而接口中的成员全都是public的。抽象 类中可以定义成员变量,而接口中定义的成员变量实际上都是常量。有抽象方法的类必须被声明为抽象类,而抽象类未必要有抽象方法。抽象类和接口中都可以包含静态成员变量。

6、抽象的(abstract)方法是否可同时是静态的(static,是否可同时是本地方法(native),是否可同时被synchronized修饰?

答:都不能。抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。本地方法是由本地代码(如C代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。synchronized和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的。

7、接口是否可继承(extends)接口抽象类是否可实现(implements)接口抽象类是否可继承具体类(concrete class?

答:接口可以继承接口。抽象类可以实现(implements)接口,抽象类可继承具体类,但前提是具体类必须有明确的构造函数。

8Anonymous Inner Class(匿名内部类)是否可以继承其它类?是否可以实现接口?

答:可以继承其他类或实现其他接口,在Swing编程中常用此方式来实现事件监听和回调。

9、数据类型之间的转换:

1)如何将字符串转换为基本数据类型?

2)如何将基本数据类型转换为字符串?

1)调用基本数据类型对应的包装类中的方法parseXXX(String)valueOf(String)即可返回相应基本类型; Integer.parseInt(a)   Integer.valueOf(a)

2)一种方法是将基本数据类型与空字符串(””)连接(+)即可获得其所对应的字符串;另一种方法是调用String 类中的valueOf(…)方法返回相应字符串 String.valueOf(int)   Integer.toString 

10、如何实现字符串的反转及替换? 

答:方法很多,可以自己写实现也可以使用StringStringBuffer / StringBuilder中的方法。有一道很常见的面试题是用递归实现字符串反转,代码如下所示:

[java] view plain copy

 1.public static String reverse(String originStr) {    

1.  2.        if(originStr == null || originStr.length() <= 1)     

2.  3.            return originStr;    

3.  4.        return reverse(originStr.substring(1)) + originStr.charAt(0);    

4.  5.    }    

 

11、列出一些你常见的运行时异常? 

答:

ArithmeticException(算术异常)

ClassCastException (类转换异常)

IllegalArgumentException (非法参数异常)

IndexOutOfBoundsException (下表越界异常)

NullPointerException (空指针异常)

SecurityException (安全异常)

12ListMapSet三个接口存取元素时,各有什么特点? 

答:List以特定索引来存取元素,可以有重复元素Set不能存放重复元素(用对象的equals()方法来区分元素是否重复)。Map保存键值对 key-value pair)映射,映射关系可以是一对一或多对一。SetMap容器都有基于哈希存储和排序树的两种实现版本,基于哈希存储的版本理论存取时间复杂度为 O(1),而基于排序树版本的实现在插入或删除元素时会按照元素或元素的键(key)构成排序树从而达到排序和去重的效果。

13、什么是进程,什么是线程?为什么需要多线程编程?

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,是操作系统进行资源分配调度的一个独立单位;

线程是进程的一个实体,是CPU调度和分 派的基本单位,是比进程更小的能独立运行的基本单位。

线程的划分尺度小于进程,这使得多线程程序的并发性高;进程在执行时通常拥有独立的内存单元,而线程之间可以共享内存。使用多线程的编程通常能够带来更好的性能和用户体验,但是多线程的程序对于其他程序是不友好的,因为它占用了更多的CPU资源。

14.阐述JDBC操作数据库的步骤 

答:下面的代码以连接本机的Oracle数据库为例,演示JDBC操作数据库的步骤。

1. 加载驱动。

[java] view plain copy

 Class.forName("oracle.jdbc.driver.OracleDriver");  

 

2. 创建连接。

[java] view plain copy

 Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "scott", "tiger");  

 

3. 创建语句。 

[java] view plain copy

 PreparedStatement ps = con.prepareStatement("select * from emp where sal between ? and ?");     

  ps.setInt(1, 1000);    

  ps.setInt(2, 3000);  

4. 执行语句。

[java] view plain copy

 ResultSet rs = ps.executeQuery();  

 

5. 处理结果。

[java] view plain copy

 while(rs.next()) {     

     System.out.println(rs.getInt("empno") + " - " + rs.getString("ename"));    }  

6. 关闭资源。

[java] view plain copy

 finally {      

     if(con != null) {        

       try {               

    con.close();            

   } catch (SQLException e) {                e.printStackTrace();            

   }        

   }     

  }  

15.StatementPreparedStatement有什么区别?哪个性能更好? 

Statement相比

①PreparedStatement接口代表预编译的语句,它主要的优势在于可以减少SQL的编译错误并增加SQL的安全性(减少SQL注射攻击的可能性)

②PreparedStatement中的SQL语句是可以带参数的,避免了用字符串连接拼接SQL语句的麻烦和不安全

当批量处理SQL或频繁执行相同的查询时,PreparedStatement有明显的性能上的优势,由于数据库可以将编译优化后的SQL语句缓存起来,下次执行相同结构的语句时就会很快(不用再次编译和生成执行计划)。

16、在进行数据库编程时,连接池有什么作用? 

    由于创建连接和释放连接都有很大的开销(尤其是数据库服务器不在本地时,每次建立连接都需要进行TCP的三次握手,释放连接需要进行TCP四次握手,造成的开销是不可忽视的),为了提升系统访问数据库性能,可以事先创建若干连接置于连接池中,需要时直接从连接池获取,使用结束时归还连接池而不必关闭连接,从而避免频繁创建和释放连接所造成的开销,这是典型的用空间换取时间策略(浪费了空间存储连接,但节省了创建和释放连接的时间)。池化技术在Java开发中是很常见的,在使用线程时创建线程池的道理与此相同。

17Java中是如何支持正则表达式操作的? 

答:Java中的String类提供了支持正则表达式操作的方法,包括:matches()replaceAll()replaceFirst()split()。此外,Java中可以用Pattern类表示正则表达式对象,它提供了丰富的API进行各种正则表达式操作,请参考下面面试题的代码。

面试题: - 如果要从字符串中截取第一个英文左括号之前的字符串,例如:北京市(朝阳区)(西城区)(海淀区),截取结果为:北京市,那么正则表达式怎么写?

[java] view plain copy

 import java.util.regex.Matcher;  

 import java.util.regex.Pattern;  

 class RegExpTest {     

  public static void main(String[] args){  

 String str = "北京市(朝阳区)(西城区)(海淀区)";       

    Pattern p = Pattern.compile(".*?(?=\()");        

   Matcher m = p.matcher(str);        

   if(m.find()) {          

     System.out.println(m.group());        }    

   }  

 }  

18、获得一个类的类对象有哪些方式? 反射

答: 

方法1:类型.class,例如:String.class 

方法2:对象.getClass(),例如:"hello".getClass() 

方法3Class.forName(),例如:Class.forName("java.lang.String")

19、如何通过反射创建对象? 

答: 

方法1:通过类对象调用newInstance()方法,例如:String.class.newInstance() 

方法2:通过类对象的getConstructor()getDeclaredConstructor()方法获得构造器(Constructor)对象并调用其newInstance()方法创建对象,例如:String.class.getConstructor(String.class).newInstance("Hello");

20、如何通过反射调用对象的方法? 

答:请看下面的代码:

[java] view plain copy

 import java.lang.reflect.Method;  

 class MethodInvokeTest {     

  public static void main(String[] args) throws Exception {      

     String str = "hello";         

  Method m = str.getClass().getMethod("toUpperCase");       

    System.out.println(m.invoke(str));  

   // HELLO     

  }  

 }  

21、简述一下面向对象的"六原则一法则" 

答: 

1)单一职责原则:一个类只做它该做的事情。(单一职责原则想表达的就是"高内聚",写代码最终极的原则只有六个字"高内聚、低耦合"

2)开闭原则:软件实体应当对扩展开放,对修改关闭。(在理想的状态下,当我们需要为一个软件系统增加新功能时,只需要从原来的系统派生出一些新类就可以,不需要修改原来的任何一行代码。要做到开闭有两个要点:抽象是关键,一个系统中如果没有抽象类或接口系统就没有扩展点;封装可变性,将系统中的各种可变因素封装到一个继承结构中,如果多个可变因素混杂在一起,系统将变得复杂而换乱) 

3)依赖倒转原则:面向接口编程。(该原则说得直白和具体一些就是声明方法的参数类型、方法的返回类型、变量的引用类型时,尽可能使用抽象类型而不用具体类型,因为抽象类型可以被它的任何一个子类型所替代) 

4)里氏替换原则:任何时候都可以用子类型替换掉父类型。(子类一定是增加父类的能力而不是减少父类的能力,因为子类比父类的能力更多,把能力多的对象当成能力少的对象来用当然没有任何问题。) 

5)接口隔离原则:接口要小而专,绝不能大而全。(臃肿的接口是对接口的污染,既然接口表示能力,那么一个接口只应该描述一种能力,接口也应该是高度内聚的。Java中的接口代表能力、代表约定、代表角色,能否正确的使用接口一定是编程水平高低的重要标识。) 

6)合成聚合复用原则:优先使用聚合或合成关系复用代码。(通过继承来复用代码是面向对象程序设计中被滥用得最多的东西,记住:任何时候都不要继承工具类,工具是可以拥有并可以使用的,而不是拿来继承的。) 

迪米特法则:迪米特法则又叫最少知识原则,一个对象应当对其他对象有尽可能少的了解。(迪米特法则简单的说就是如何做到"低耦合",门面模式和调停者模式就是对迪米特法则的践行。Java Web开发中作为前端控制器的ServletFilter不就是一个门面吗,浏览器对服务器的运作方式一无所知,但是通过前端控制器就能够根据你的请求得到相应的服务。调停者模式也可以举一个简单的例子来说明,例如一台计算机,CPU、内存、硬盘、显卡、声卡各种设备需要相互配合才能很好的工作。迪米特法则用通俗的话来将就是不要和陌生人打交道,如果真的需要,找一个自己的朋友,让他替你和陌生人打交道。)

=-22.简述一下你了解的设计模式

-工厂模式:工厂类可以根据条件生成不同的子类实例,这些子类有一个公共的抽象父类并且实现了相同的方法,但是这些方法针对不同的数据进行了不同的操作(多态方法)。当得到子类的实例后,开发人员可以调用基类中的方法而不必考虑到底返回的是哪一个子类的实例。 

代理模式:给一个对象提供一个代理对象,并由代理对象控制原对象的引用。0.实际开发中,按照使用目的的不同,代理可以分为:远程代理、虚拟代理、保护代理、Cache代理、防火墙代理、同步化代理、智能引用代理。 

适配器模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起使用的类能够一起工作。 

模板方法模式:提供一个抽象类,将部分逻辑以具体方法或构造器的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法(多态实现),从而实现不同的业务逻辑。 

23、用Java写一个单例类。 

饿汉式单例

[java] view plain copy

 public class Singleton {  

     private Singleton(){}     

  private static Singleton instance = new Singleton();     

  public static Singleton getInstance(){        return instance;     

  }  

 }  

懒汉式单例

[java] view plain copy

 public class Singleton {  

 private Singleton() {}    

   private static Singleton instance = null;      

     public static synchronized Singleton getInstance(){      

     if (instance == null)  

  instance  new Singleton();        

   return instance;     

  }  

 }  

注意:实现一个单例有两点注意事项,将构造器私有,不允许外界通过构造器创建对象;通过公开的静态方法向外界返回类的唯一实例。这里有一个问题可以思考:springIoC容器可以为普通的类创建单例,它是怎么做到的呢?

24.什么是DAO模式?

答:DAODataAccess Object)顾名思义是一个为数据库或其他持久化机制提供了抽象接口的对象,在不暴露数据库实现细节的前提下提供了各种数据操作。将所有对数据源的访问操作进行抽象化后封装在一个公共API中。在这个应用程序中,当需要和数据源进行交互的时候则使用这个接口,并且编写一个单独的类来实现这个接口,在逻辑上该类对应一个特定的数据存储。DAO模式实际上包含了两个模式,一是Data Accessor(数据访问器),二是Data Object(数据对象),前者要解决如何访问数据的问题,而后者要解决的是如何用对象封装数据。

 

25.Servlet的生命周期

Web容器加载Servlet并将其实例化后,Servlet生命周期开始,容器运行其init()方法进行Servlet的初始化;请求到达时调用Servletservice方法,service方法会调用与请求对应doGetdoPost等方法;当服务器关闭会项目被卸载时服务器会将Servlet实例销毁,此时会调用Servletdestroy方法。

26.转发(forward)和重定向(redirect)的区别?

1forward是容器中控制权的转向,是服务器请求资源,服务器直接访问目标地址的URL,把那个URL 的响应内容读取过来,然后把这些内容再发给浏览器,浏览器根本不知道服务器发送的内容是从哪儿来的,所以它的地址栏中还是原来的地址。

2redirect就是服务器端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,因此从浏览器的地址栏中可以看到跳转后的链接地址。

3)前者更加高效,在前者可以满足需要时,尽量使用转发(通过RequestDispatcher对象的forward方法,RequestDispatcher对象可以通过ServletRequest对象的getRequestDispatcher方法获得),并且,这样也有助于隐藏实际链接;在有些情况下,比如,需要跳转到一个其它服务器上的资源,则必须使用重定向(通过HttpServletResponse对象调用其sendRedirect方法)。

27.getpost请求的区别?

①get请求用来从服务器上获得资源,而post是用来向服务器提交数据

②get将表单中数据按照name=value的形式,添加到action 指向的URL 后面,并且两者使用“?”连接,而各个变量之间使用&”连接;post是将表单中的数据放在html头部header),传递到action所指向URL

③get传输的数据要受到URL长度限制(1024字节);而post可以传输大量的数据,上传文件只能使用post方式;

使用get时参数会显示在地址栏上,如果这些数据不是敏感数据,那么可以使用get;对于敏感数据还是应用使用post

28JSP Servlet 有有什么关系?

答:其实这个问题在上面已经阐述过了,Servlet是一个特殊的Java程序,它运行于服务器的JVM中,能够依靠服务器的支持向浏览器提供显示内容。  

JSP本质上是Servlet的一种简易形式, JSP会被服务器处理成一个类似于ServletJava程序,可以简化页面内容的生成。

ServletJSP最主要的不同点在于,Servlet 的应用逻辑是在Java 文件中,并且完全从表示层中的HTML分离开来。而JSP的情况是JavaHTML可以组合成一个扩展名为.jsp 的文件(有人说,Servlet就是在Java中写HTML,而JSP就是在HTML中写Java代码,当然,这个说法还是很片面的)。

JSP侧重于视图,Servlet更侧重于控制逻辑,MVC架构模式中JSP适合充当视图(viewServlet适合充当控制器controller)。

29JSP中的四种作用域?

答:pagerequestsessionapplication,具体如下:

①page 代表与一个页面相关的对象和属性。

②request 代表与Web客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个Web 组件;需要在页面显示的临时数据可以置于此作用域

③session代表与某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户自己的session

④application代表与整个Web应用程序相关的对象和属性,它实质上是跨越整个Web应用程序,包括多个页面、请求和会话的一个全局作用域。

30.实现会话跟踪的技术有哪些?

答:由于HTTP协议本身是无状态的,服务器为了区分不同的用户,就需要对用户会话进行跟踪,简单的说就是为用户进行登记,为用户分配唯一的ID,下一次用户在请求中包含此ID,服务器据此判断到底是哪一个用户。

①URL 重写:在URL中添加用户会话的信息作为请求的参数,或者将唯一的会话ID添加到URL结尾以标识一个会话。

设置表单隐藏域:将和会话跟踪相关的字段添加到隐式表单域中,这些信息不会在浏览器中显示但是提交表单时会提交给服务器。

③cookiecookie当用户通过浏览器和服务器建立一次会话后,会话ID就会随响应信息返回存储在基于窗口的cookie,那就意味着只要浏览器没有关闭,会话没有超时,下一次请求时这个会话ID又会提交给服务器让服务器识别用户身份。会话中可以为用户保存信息。会话对象是在服务器内存中的,而基于窗口的cookie是在客户端内存中的。

④HttpSession:在所有会话跟踪技术中,HttpSession对象是最强大也是功能最多的。当一个用户第一次访问某个网站时会自动创建HttpSession,每个用户可以访问他自己的HttpSession。与上面三种方式不同的是,HttpSession放在服务器的内存中

31.JSP中的静态包含和动态包含有什么区别? 

答:静态包含是通过JSPinclude指令包含页面,动态包含是通过JSP标准动作<jsp:forward>包含页面。静态包含是编译时包含,如果包含的页面不存在则会产生编译错误,而且两个页面的"contentType"属性应保持一致,因为两个页面会合二为一,只产生一个class文件,因此被包含页面发生的变动再包含它的页面更新前不会得到更新。动态包含是运行时包含,可以向被包含的页面传递参数,包含页面和被包含页面是独立的,会编译出两个class文件,如果被包含的页面不存在,不会产生编译错误,也不影响页面其他部分的执行。代码如下所示:

<%-- 静态包含 --%><%@ include file="..." %> <%-- 动态包含 --%><jsp:include page="...">    <jsp:param name="..." value="..." /></jsp:include>

32、什么是Web ServiceWeb服务)? 

答:从表面上看,Web Service就是一个应用程序,它向外界暴露出一个能够通过Web进行调用的API。例如可以创建一个提供天气预报的Web Service,那么无论你用哪种编程语言开发的应用都可以通过调用它的API并传入城市信息来获得该城市的天气预报。

补充:这里必须要提及的一个概念是SOAService-Oriented Architecture,面向服务的架构)显然,Web ServiceSOA的一种较好的解决方案,它更多的是一种标准,而不是一种具体的技术。

33hashmaphashtable区别

   1.hashMap去掉了HashTable contains方法,但是加上了containsValue()和containsKey()方法。

   2.hashTable同步的,而HashMap是非同步的,效率上逼hashTable要高。

   3.hashMap允许空键值,而hashTable不允许。

 

34Socket的通信机制?

套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。

 

应用层通过传输层进行数据通信时,TCP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP连接或多个应用程序进程可能需要通过同一个 

TCP协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCPIP协议交互提供了套接字(Socket)接口。应用层可以和传输层通过Socket接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。

建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket ,另一个运行于服务器端,称为ServerSocket 

套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。

 

服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。

 

客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。

 

连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。

35Http的通信机制?

HTTP协议即超文本传送协议(Hypertext Transfer Protocol 

),是Web联网的基础,也是手机联网常用的协议之一,HTTP协议是建立在TCP协议之上的一种应用。

 

HTTP连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为一次连接

 

1)在HTTP 1.0中,客户端的每次请求都要求建立一次单独的连接,在处理完本次请求后,就自动释放连接。

 

2)在HTTP 

1.1中则可以在一次连接中处理多个请求,并且多个请求可以重叠进行,不需要等待一个请求结束后再发送下一个请求。

 

由于HTTP在每次请求结束后都会主动释放连接,因此HTTP连接是一种短连接,要保持客户端程序的在线状态,需要不断地向服务器发起连接请求。通常的做法是即时不需要获得任何数据,客户端也保持每隔一段固定的时间向服务器发送一次保持连接的请求,服务器在收到该请求后对客户端进行回复,表明知道客户端在线。若服务器长时间无法收到客户端的请求,则认为客户端下线,若客户端长时间无法收到服务器的回复,则认为网络已经断开。

由于通常情况下Socket连接就是TCP连接,因此Socket连接一旦建立,通信双方即可开始相互发送数据内容,直到双方连接断开。但在实际网络应用中,客户端到服务器之间的通信往往需要穿越多个中间节点,例如路由器、网关、防火墙等,大部分防火墙默认会关闭长时间处于非活跃状态的连接而导致 

Socket 连接断连,因此需要通过轮询告诉网络,该连接处于活跃状态。

 

HTTP连接使用的是请求响应的方式,不仅在请求时需要先建立连接,而且需要客户端向服务器发出请求后,服务器端才能回复数据。

 

很多情况下,需要服务器端主动向客户端推送数据,保持客户端与服务器数据的实时与同步。此时若双方建立的是Socket连接,服务器就可以直接将数据传送给客户端;若双方建立的是HTTP连接,则服务器需要等到客户端发送一次请求后才能将数据传回给客户端,因此,客户端定时向服务器端发送连接请求,不仅可以保持在线,同时也是在询问服务器是否有新的数据,如果有就将数据传给客户端。

 

36HttpServlet容器响应Web客户请求流程?

1Web客户向Servlet容器发出Http请求;

2Servlet容器解析Web客户的Http请求;

3Servlet容器创建一个HttpRequest对象,在这个对象中封装Http请求信息

4Servlet容器创建一个HttpResponse对象

5Servlet容器调用HttpServletservice方法,这个方法中会根据requestMethod判断具体是执行doGet还是doPost,把HttpRequestHttpResponse对象作为service方法的参数传给HttpServlet对象;

6HttpServlet调用HttpRequest的有关方法,获取HTTP请求信息;

7HttpServlet调用HttpResponse的有关方法,生成响应数据;

8Servlet容器把HttpServlet的响应结果传给Web客户

 

37hibernateSessionloadget方法的区别是什么? 

答:主要有以下三项区别: 

① 如果没有找到符合条件的记录get方法返回nullload方法抛出异常。 

② get方法直接返回实体类对象load方法返回实体类对象的代理 

③ Hibernate 3之前,get方法只在一级缓存中进行数据查找,如果没有找到对应的数据则越过二级缓存,直接发出SQL语句完成数据读取;load方法则可以从二级缓存中获取数据;从Hibernate 3开始,get方法不再是对二级缓存只写不读,它也是可以访问二级缓存的。

说明:对于load()方法Hibernate认为该数据在数据库中一定存在可以放心的使用代理来实现延迟加载,如果没有数据就抛出异常,而通过get()方法获取的数据可以不存在

38、如何理解Hibernate的延迟加载机制

答:延迟加载就是并不是在读取的时候就把数据加载进来,而是等到使用时再加载。Hibernate使用了虚拟代理机制实现延迟加载。返回给用户的并不是实体本身,而是实体对象的代理。代理对象在用户调用getter方法时就会去数据库加载数据。

39、简述Hibernate常见优化策略。

制定合理的缓存策略

② 采用合理的Session管理机制

③ 尽量使用延迟加载特性

如果可以选用基于version的乐观锁替代悲观锁

在开发过程中开启hibernate.show_sql选项查看生成的SQL, 从而了解底层的状况;开发完成后关闭此选项

40、什么是IoCDIDI是如何实现的? 

答:IoC叫控制反转,是Inversion of Control的缩写,控制反转是把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的"控制反转"就是对组件对象控制权的转移,从程序代码本身转移到了外部容器,由容器来创建对象并管理对象之间的依赖关系。

控制反转——Spring通过一种称作控制反转(IoC)的技术促进了松耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象,是容器在对象初始化时不等对象请求就主动将依赖传递给它。通过IOC反转控制DI依赖注入完成各个层之间的注入,使得层与层之间实现完全脱耦,增加运行效率利于维护。

 

41、解释一下什么叫AOP(面向切面编程)? 

答:

    springAOP面向切面编程,实现在不改变代码的情况下完成对方法的增强。比较常用的就是spring的声明式事务管理,底层通过AOP实现,避免了我们每次都要手动开启事物,提交事务的重复性代码,使得开发逻辑更加清晰。

   简单点解释,比方说你想在你的service层所有类中都加上一个打印你好的功能这你经可以用aop思想来做,你先写个类写个方法,方法经实现打印你好然后你Ioc这个类 ref“service.*”让每个类都注入。

   aop就是面向切面的编程。比如说你每做一次对数据库操作,都要生成一句日志。如果,你对数据库的操作有很多类,那你每一类中都要写关于日志的方法。但是如果你用aop,那么你可以写一个方法,在这个方法中有关于数据库操作的方法,每一次调用这个方法的时候,就加上生成日志的操作。

 

42、选择使用Spring框架的原因(Spring框架为企业级开发带来的好处)?

答:可以从以下几个方面作答:

1. IoC容器:IoC容器帮助应用程序管理对象以及对象之间的依赖关系,对象之间的依赖关系如果发生了改变只需要修改配置文件而不是修改代码,因为代码的修改可能意味着项目的重新构建和完整的回归测试。有了IoC容器,程序员再也不需要自己编写工厂、单例,这一点特别符合Spring的精神不要重复的发明轮子

2. AOP:面向切面编程,将所有的横切关注功能封装到切面(aspect)中,通过配置的方式将横切关注功能动态添加到目标代码上,进一步实现了业务逻辑和系统服务之间的分离。另一方面,有了AOP程序员可以省去很多自己写代理类的工作。

3. MVCSpringMVC框架是非常优秀的,从各个方面都可以甩Struts 2几条街,为Web表示层提供了更好的解决方案。

4. 事务管理:Spring以宽广的胸怀接纳多种持久层技术,并且为其提供了声明式的事务管理,在不需要任何一行代码的情况下就能够完成事务管理。

 43 简述拦截器的工作原理以及你在项目中使用过哪些自定义拦截器

答:Struts 2中定义了拦截器的接口以及默认实现,实现了Interceptor接口或继承了AbstractInterceptor的类可以作为拦截器。接口中的init()方法在拦截器被创建后立即被调用,它在拦截器的生命周期内只被调用一次,可以在该方法中对相关资源进行必要的初始化。每拦截一个请求,intercept()方法就会被调用一次destory()方法将在拦截器被销毁之前被调用它在拦截器的生命周期内也只被调用一次。

项目中使用过的有权限拦截器、执行时间拦截器、令牌拦截器等。

44、谈一下拦截器和过滤器的区别

答:拦截器和过滤器都可以用来实现横切关注功能,其区别主要在于:

1、拦截器是基于java反射机制的,而过滤器是基于函数回调的。

2、过滤器依赖于servlet容器,而拦截器不依赖于servlet容器。

3、拦截器只能对Action请求起作用,而过滤器则可以对几乎所有请求起作用。

4拦截器可以访问Action上下文、值栈里的对象,而过滤器不能。

5、在Action的生命周期中,拦截器可以多次调用,而过滤器只能在容器初始化时被调用一次。

 过滤器,是在java web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts action进行业务逻辑,比如过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),或者在传入servlet或者strutsaction前统一设置字符集,或者去除掉一些非法字符. 

  拦截器,是在面向切面编程的就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作

执行顺序:过滤前 - 拦截前 - Action处理 - 拦截后 - 过滤后。

个人认为过滤是一个横向的过程,首先把客户端提交的内容进行过滤(例如未登录用户不能访问内部页面的处理);过滤通过后,拦截器将检查用户提交数据的验证,做一些前期的数据处理,接着把处理后的数据发给对应的ActionAction处理完成返回后,拦截器还可以做其他过程(还没想到要做啥),再向上返回到过滤器的后续操作。

 

45struts1.2struts2.0的区别?

   struts1.2struts2.0的对比

   aAction类:

      struts1.2要求Action类继承一个基类。struts2.0 Action要求继承ActionSupport基类

   b、线程模式

      struts1.2 Action是单例模式的并且必须是线程安全的有线程安全问题,因为仅有一个Action的实例来处理所有的请求。 struts2.0 Action为每一个请求产生一个实例,因此没有线程安全问题。

   cServlet依赖

      struts1.2 Action依赖于Servlet API,因为当一个Action被调用时HttpServletRequestHttpServletResponse被传递给execut方法。 struts2.0 Action不依赖于容器,允许Action脱离容器单独测试。

 

46、常见的网络协议有哪些?

    1.IP协议:互联网协议

主要用于负责IP寻址、路由选择和IP数据包的分割和组装。通常我们所说的IP地址可以理解为符合IP协议的地址。

    2.TCP协议:传输控制协议

    该协议主要用于在主机间建立一个虚拟连接,以实现高可靠性的数据包交换。IP协议可以进行IP数据包的分割和组装,但是通过IP协议并不能清楚地了解到数据包是否顺利地发送给目标计算机。而使用TCP协议就不同了,在该协议传输模式中在将数据包成功发送给目标计算机后,TCP会要求发送一个确认;如果在某个时限内没有收到确认,那么TCP将重新发送数据包。另外,在传输的过程中,如果接收到无序、丢失以及被破坏的数据包,TCP还可以负责恢复。

    3.FTPFile Transfer Protocol):远程文件传输协议,允许用户将远程主机上的文件拷贝到自己的计算机上。

    4.HTTP超文本传输协议HTTPHyperText Transfer Protocol)互联网上应用最为广泛的一种网络协议。所有的WWW文件都必须遵守这个标准。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。

    5.ARP协议:AddressResolutionProtocol地址解析协议

简单地说,ARP协议主要负责将局域网中的32IP地址转换为对应的48位物理地址,即网卡的MAC地址。

 

47计算机网络分层,每层所用协议,协议所占端口

1)应用层:与其他计算机进行通讯的一个应用,它是对应应用程序的通信服务的。示例:telnetHTTP,FTP,WWW,NFS,SMTP等。 

    2)表示层:这一层的主要功能是定义数据格式及加密。示例:加密,ASII等。 

    3)会话层:他定义了如何开始、控制和结束一个会话,包括对多个双向小时的控制和管理,以便在只完成连续消息的一部分时可以通知应用,从而使表示层看到的数据是连续的。示例:RPCSQL等。 

   4)传输层:这层的功能包括是否选择差错恢复协议还是无差错恢复协议,及在同一主机上对不同应用的数据流的输入进行复用,还包括对收到的顺序不对的数据包的重新排序功能。示例:TCPUDPSPX 

   5)网络层:这层对端到端的包传输进行定义,他定义了能够标识所有结点的逻辑地址,还定义了路由实现的方式和学习的方式。。示例:IP,IPX等。 

   6)数据链路层:他定义了在单个链路上如何传输数据。

   7)物理层:OSI的物理层规范是有关传输介质的特性标准,这些规范通常也参考了其他组织制定的标准。

 

48html访问全过程

A)解析Web页面的URL,得到Web服务器的域名

    B)通过DNS服务器获得Web服务器的IP地址

I)与Web服务器建立TCP连接

    E)与Web服务器建立HTTP连接

C)从Web服务器获得URL指定的文档

    G)浏览器解释页面文档,并显示在屏幕

 

49classloader原理

    1classLoader的介绍及加载过程

与普通程序不同的是,Java程序(class文件)并不是本地的可执行程序。当运行Java程序时,首先运行JVMJava虚拟机),然后再把Java class加载到JVM里头运行,负责加载Java class的这部分就叫做Class Loader。所以classLoader的目的在于把class文件装入到jvm中。

那么classLoader又在那里的啦?又由谁调用呢?其实classLoader只是jvm的一个实现的一部分。Jvm提供的一个顶级的classLoaderbootStrap classLoader),bootStrap classLoader负责加载java核心的API以满足java程序最基本的需求。Jvm还提供的两个classLoader,其中Extension ClassLoader负责加载扩展的Java classApplication ClassLoader负责加载应用程序自身的类。而Extension ClassLoaderApplication ClassLoader则由bootStrap classLoader加载。

2classLoader加载的基本流程

   当运行一个程序的时候,JVM启动,运行bootstrap classloader,该ClassLoader加载java核心APIExtClassLoaderAppClassLoader也在此时被加载),然后调用ExtClassLoader加载扩展API,最后AppClassLoader加载CLASSPATH目录下定义的Class,这就是一个程序最基本的加载流程。

3classLoader加载的方式

   其实classLoader在加载class文件的时候就采用的双亲委托模式。每一个自定义ClassLoader都必须继承ClassLoader这个抽象类,而每个ClassLoader都会有一个parent ClassLoader,我们可以看一下ClassLoader这个抽象类中有一个getParent()方法,这个方法用来返回当前ClassLoaderparent

 

50、快速排序原理

 原理:

    快速排序也是分治法思想的一种实现,他的思路是使数组中的每个元素与基准值(Pivot,通常是数组的首个值,A[0])比较,数组中比基准值小的放在基准值的左边,形成左部;大的放在右边,形成右部;接下来将左部和右部分别递归地执行上面的过程:选基准值,小的放在左边,大的放在右边。。。直到排序结束。

 步骤:

1.找基准值,设Pivot = a[0] 

2.分区(Partition):比基准值小的放左边,大的放右边,基准值(Pivot)放左部与右部的之间。

3.进行左部(a[0] - a[pivot-1])的递归,以及右部(a[pivot+1] - a[n-1])的递归,重复上述步骤。

[java] view plain copy

 1.//快速排序    

 2.void quick_sort(int s[], int l, int r)    

 3.{    

1.  4.    if (l < r)    

2.  5.    {    

3.  6.        //Swap(s[l], s[(l + r) / 2]); //将中间的这个数和第一个数交换 参见注1    

4.  7.       int i = l, j = r, x = s[l];    

5.  8.       while (i < j)    

6.  9.       {    

7.  10.        while(i < j && s[j] >= x) // 从右向左找第一个小于x的数    

8.  11.                j--;      

9.  12.          if(i < j)     

10.  13.          s[i++] = s[j];    

11.  14.                

12.  15.       while(i < j && s[i] < x) // 从左向右找第一个大于等于x的数    

13.  16.            i++;      

14.  17.         if(i < j)     

15.  18.          s[j--] = s[i];    

16.  19.        }    

17.  20.        s[i] = x;    

18.  21.        quick_sort(s, l, i - 1); // 递归调用     

19.  22.        quick_sort(s, i + 1, r);    

20.  23.    }    

 24.}    

51、各种集合类之间的区别

 1ArrayList: 元素单个,效率高,多用于查询

2Vector:  元素单个,线程安全,多用于查询

3LinkedList:元素单个,多用于插入和删除

4HashMap:  元素成对,元素可为空

5HashTable: 元素成对,线程安全,元素不可为空

 

52、内存溢出和内存泄漏

    内存溢出是指已有的数据超过了其获得到的内存所能存储的范围,比如用一个字节存放1000这个数字就属于内存溢出。比如说你申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。

    Java内存泄漏就是没有及时清理内存垃圾,导致系统无法再给你提供内存资源(内存资源耗尽)。Java内存泄露是说程序逻辑问题,造成申请的内存无法释放.这样的话无论多少内存,早晚都会被占用光的.最简单的例子就是死循环了.由于程序判断错误导经常发生此事。

 

53jvm布局

    以下是JVM的一个基本架构图,在这个基本架构图中,栈有两部份,Java线程栈以及本地方法栈

.说说你对缓存的理解?

1.使用缓存的目的:

提高应用程序的性能,减少到数据库的访问次数,

举个简单应用场景,比如微信群聊,当服务器收到一条消息的时候,需要把消息插入数据库。

最原始的做法,就是每当有一条聊天记录到达服务器的时候,就进行一次数据库的插入操作。如果不考虑服务器带宽,这种情况下数据库的每秒io次数约等于每秒聊天记录插入的次数。

换一种实现思路,用redis做缓存,消息到达服务器的时候,并不是立刻比如数据库,而是存在redis里。当redis聊天记录到达60条的时候,再执行1次数据库插入操作。

这样子,粗略估计,服务器性能就提高了60倍

2.缓存的介质(缓存的存储位置)

内存:临时性存储空间 存取数据快  减少网络通信量

硬盘:永久性存储空间 存取速度慢

3.缓存的分类

客户端缓存:浏览器 cookie

服务器缓存:oscache,redis,memcache,session

4.缓存什么样的数据?

经常访问,又不经常修改的数据

5.缓存的有效性

为了避免脏数据的产生,要刷新缓存,这时就用到了事务为了避免页面显示问题,需要更新缓存和数据库保证一致性

6.脏数据

如果缓存中的数据和数据库中的数据不一致,那么缓存中的数据就被称之为脏数据

7.刷新缓存的方式

手动刷新:写程序的时候调用指定的代码清除缓存数据

定时刷新:当到达缓存过期时间后,会自动刷新数据

8.缓存的层次(一般我们将缓存加载service中)

jsp-->action-->service-->dao

缓存越靠前对性能的提高越大

9.缓存的清除策略:(缓存空间不足需要进行清理的时候使用)

LRU:最近最少使用原则.(理解:存储书)

FIFO:先进先出的缓存策略.(理解:排队)

10.什么时候使用缓存的清除策略?

当缓存中的数据已满,又有新的数据进来时,执行缓存的清除策略

2.你对Maven是怎么理解的?

Maven两个重点:根据Maven的约定由于配置了四个文件的文件名必须是固定的,还有一个loge日志的名字也是固定的,这样不需要去加载这些文件直接通过Maven的约定由于配置自动加载好

还有根据maven的依赖管理在pom.xml中配置jar与这个jar包相关的jar包自动配置好

我当时是怎么配置maven的通过在服务端中setting 中配置这个mirror镜像配置访问nexus的访问路径

这样我们就可以通过pom.xml先到我们的本地去找,如果本地仓库找不到在去maven私服去找如果私服找不到在去外网下载使用maven这样可以提高我们的开发效率与节省了下载带宽,以及jar包的重用性。

3.Spring MVC中的注解你都用过哪些,SpringMVC的运行原理是什么?

@Controller:使其普通的java类充当控制层的作用。

@RequestMapping:有两个参数 url 代表要访问的路径 method请求方式

@Service::使其java类充当service层。

@Repository::使其java类充当持久层。Er4

@Resource:默认按照名字注入指定的bean

@Autowired:默认按照类型进行注入可以结合@Qualifier("bean的的名字 名字")使使其按照名字进行注入。他是 其按照名字进行注入。他是Spring中的注解。

@RespsonceBody:将controller的方法返回的对象通过适当的转换器转换为指定个时候将其输出(通常适用于返回json/xml

@RequestParam

作用:1.在文件上传时注解 @requestParam 后跟multilpartFile属性

2.接收指定参数名的参数并对方法中的参数赋值并且可以设置默认值

 我对Spring MVC的理解和运用。

 

我们通常使用Spring MVC来充当我们项目中的控制层,我们控制层的作用就是接受前台传递的参数,调用业务逻辑层进行业务处理以及将返回的结果集返回前台进行展示,首先我们要在web.xml中配置Spring MVC的前端总控制器DispatcherServlet并加载Spring MVC的配置文件,我们在Controller层上加上@Controller注解,使其充当控制层,并且要在Spring mvc的配置文件中通过component-scanController层进行扫描从而使类中的@Controller注解生效,Spring mvc用方法来接收参数,所以我们说Spring mvc是基于方法的设计,我们也可以通过@PathVariable从路径中获取信息,我们通常通过@Resource这个注解来进行Bean注入,他是java中的注解,而不是Spring中的,默认是按照属性名进行注入,我们也可以通过设置name属性的值,让其只能按照属性名进行注入,我们也可以用@Autowired注解来进行Bean的注入,他默认是按照类型进行注入,如果要按属性名进行注入我们需要结合@Qualifier注解使其按照名字进行注入,我们可以将返回值的类型改为ModelAndView并在配置文件中配置视图解析器的前缀和后缀,以此来给我们前台页面传递数据,也可以在方法中通过ModelMap进行返回数据。也可以通过@ResponseBody将返回的实体类或者实体类的集合转换为指定的格式进行前台页面交互。并且要在配置文件中进行相关的配置。@RequestMapping是将Url映射到具体的方法上。文件上传时我们通过@RequestParam来接收前台上传的文件。以上就是我对Spring MVC的理解和运用。

 

 

4.SSH整合的流程/SSI整合的流程/SSM整合的流程?

SSH整合的流程

在项目中首先是通过在web.xml中配置strtus2的前端控制器filterDispatcher加载struts.xml

配置文件并对指定的后缀名进行拦截,并且通过配置spring的监听器contextLoadListener

加载spring的相关配置文件如

spring-service.xml,spring-dao.xml,spring-common.xml,

之后新建控制层的类继承于BaseAction,BaseAction继承于ActionSupport

BaseAction中封装了常用的方法如getRealPath(),outJson()等,

之后控制层注入service层,service层注入dao,dao层继承于HibernateDaoSupport

并注入spring-common.xml中配置的sessionFactory,sessionFactory注入dataSource连接数据库,

注入hibernate.cfg.xml从而加载hbm.xml文件,

除此之外还通过Spring中的Aop配置了事务并且通过切点表达式对Servcie层代码进行控制。

======================================================================SSM整合的流程

在项目中通过在web.xml配置springMVC的核心控制器DispatcherServlet

并加载Spring-mvc-controller.xml,并且通过配置Spring的监听器contextLoaderListener

加载spring-common.xml,之后新建控制层并在类上加入@Controller@RequestMapping注解,

并通过@Resouce注入service层,在

service的实现类上加入@Service注解并通过@Autowired注入dao层,

dao层只有接口并没有实现类,

是通过在mybatis中对应的含有sql语句的xml文件中来通过namespace指明要实现的dao层的接口,

并使sql语句的iddao层接口中的方法名一致从而明确调用指定dao层接口时要执行的sql语句。

并且在spring-mvc-controller.xml中配置了component-scancontroller

进行扫描从而使控制层的注解生效还配置了内部视图解析器从而在控制层进行页面跳转时加上指定的前缀和后缀,

spring-common.xml中配置了dbcp数据库连接池以及sqlSession来加载mapper下所有的xml

并对所有的mapper层进行扫描也就是对dao层的扫描,

还通过Aop中的切点表达式对service层进行事务控制,并且对service层进行扫描使其注解生效。

5.谈谈你对Spring的理解?

Spring 是完全面向接口的设计,降低程序耦合性,主要是事务控制并创建bean实例对象。在ssh整合时,充当黏合剂的作用。IOC(Inversion of Control) 控制反转/依赖注入,又称DI(Dependency Injection) (依赖注入)  

IOC的作用:产生对象实例,所以它是基于工厂设计模式的

Spring IOC的注入

       通过属性进行注入,通过构造函数进行注入,

       注入对象数组     注入List集合   

       注入Map集合      注入Properties类型

 Spring IOC 自动绑定模式:

          可以设置autowire按以下方式进行绑定

             byType只要类型一致会自动寻找

                     byName自动按属性名称进行自动查找匹配.

AOP 面向方面(切面)编程

AOPOOP的延续,是Aspect Oriented Programming的缩写,

    意思是面向方面(切面)编程。

  注:OOP(Object-Oriented Programming ) 面向对象编程

 

 AOP  主要应用于日志记录,性能统计,安全控制,事务处理(项目中使用的)等方面。

 

 Spring中实现AOP技术:

     Spring中可以通过代理模式来实现AOP

     代理模式分为

           静态代理:一个接口,分别有一个真实实现和一个代理实现。

           动态代理:通过代理类的代理,接口和实现类之间可以不直接发生联系,而             可以在运行期(Runtime)实现动态关联。

 

    动态代理有两种实现方式,可以通过jdk的动态代理实现也可以通过cglib

    来实现而AOP默认是通过jdk的动态代理来实现的。jdk的动态代理必须要有

    接口的支持,而cglib不需要,它是基于类的。

 

Spring AOP事务的描述:

spring-common.xml里通过<aop:config>里面先设定一个表达式,设定对service里那些方法  如:对add* ,delete*,update*等开头的方法进行事务拦截。我们需要配置事务的传播(propagation="REQUIRED")特性,通常把增,,改以外的操作需要配置成只读事务(read-only="true".只读事务可以提高性能。之后引入tx:advice,tx:advice引用 transactionManager(事务管理),在事务管理里再引入sessionFactory,sessionFactory注入 dataSource,最后通过<aop:config>引入txAdvice

 

Spring实现ioc控制反转描述:

 

原来需要我们自己进行bean的创建以及注入,而现在交给

spring容器去完成bean的创建以及注入。

 

所谓的控制反转就是 对象控制权的转移,

从程序代码本身转移到了外部容器。

 

官方解释:

控制反转即IoC (Inversion of Control)

它把传统上由程序代码直接操控的对象的调用权交给容器,

通过容器来实现对象组件的装配和管理。

所谓的控制反转概念就是对组件对象控制权的转移,

从程序代码本身转移到了外部容器。

 

6.HashMapHashTable的区别?

1.Map是一个以键值对存储的接口。Map下有两个具体的实现,分别是HashMapHashTable.

2.HashMap是线程非安全的,HashTable是线程安全的,所以HashMap的效率高于HashTable.

3.HashMap允许键或值为空,而HashTable不允许键或值为空.

 

7.HashMap的底层原理?(源代码)

HashMap底层就是一个数组结构,数组中的每一项又是一个链表。

当新建一个HashMap的时候,就会初始化一个数组。

 

Entry就是数组中的元素,每个 Entry 其实就是一个key-value对,

它持有一个指向下一个元素的引用,这就构成了链表。

 

 

HashMap 在底层将 key-value 当成一个整体进行处理,这个整体就是一个 Entry 对象。

HashMap 底层采用一个 Entry[] 数组来保存所有的 key-value 对,

当需要存储一个 Entry 对象时,会根据hash算法来决定其在数组中的存储位置,

再根据equals方法决定其在该数组位置上的链表中的存储位置;当需要取出一个Entry时,

也会根据hash算法找到其在数组中的存储位置,

再根据equals方法从该位置上的链表中取出该Entry

8.jre,jdk,jvm的区别?

JdkJava Development ToolKit】就是java开发工具箱, JDK是整个JAVA的核心里边包含了jre,它除了包含jre之外还包含了一些javac的工具类,把java源文件编译成class文件,java文件是用来运行这个程序的,除此之外,里边还包含了java源生的APIjava.lang.integerrtjar包里边【可以在项目中看到】,通过rt这个jar包来调用我们的这些io流写入写出等

JDK有以下三种版本:

 

J2SEstandard edition,标准版,是我们通常用的一个版本

J2EEenterpsise edtion,企业版,使用这种JDK开发J2EE应用程序

J2MEmicro edtion,主要用于移动设备、嵌入式设备上的java应用程序

JreJava  Runtime  Enviromental】是java运行时环境,那么所谓的java运行时环境,就是为了保证java程序能够运行时,所必备的一基础环境,也就是它只是保证java程序运行的,不能用来开发,而jdk才是用来开发的,所有的Java程序都要在JRE下才能运行。

包括JVMJAVA核心类库和支持文件。与JDK相比,它不包含开发工具——编译器、调试器和其它工具。

 

Jre里边包含jvm

Jvm:【Java Virtual Mechinal】因为jrejava运行时环境,java运行靠什么运行,而底层就是依赖于jvm,即java虚拟机,java虚拟机用来加载类文件,java中之所以有跨平台的作用,就是因为我们的jvm

 

关系:

 J2se是基于jdkjre

 JDK是整个JAVA的核心里边包含了jre

 Jre里边包含jvm

 

9.Set,List,Collection,Collections的区别?

1.ListSet都是接口,他们都继承于接口Collection,List是一个有序的可重复的集合,而Set的无序的不可重复的集合。Collection是集合的顶层接口,Collections是一个封装了众多关于集合操作的静态方法的工具类,因为构造方法是私有的,所以不能实例化。

 

2.List接口实现类有ArrayList,LinkedList,VectorArrayListVector是基于数组实现的,所以查询的时候速度快,而在进行增加和删除的时候速度较慢LinkedList是基于链式存储结构,所以在进行查询的时候速度较慢但在进行增加和删除的时候速度较快。又因为Vector是线程安全的,所以他和ArrayList相比而言,查询效率要低。

 

10.系统管理的描述?

我负责项目中的系统管理模块,其中包含用户管理,菜单管理以及给用户赋角色,给角色赋权限;涉及到的表有用户表,角色表,用户角色关联表,菜单表,角色菜单关联表。在菜单管理模块采用ztree进行菜单的增删改查操作,为了将权限控制到按钮级别我们在进行菜单管理时会设置该菜单是属于按钮级别还是普通菜单,通过在数据库中增加一个type类型的字段来实现,如type1则是普通菜单,type2则是按钮菜单。

 

这样用户在登录的时候根据用户名和密码到用户表验证信息是否合法,如果合法则获取用户信息,之后根据用户id再到用户角色关联表中得到相关联的角色id集合,之后根据角色id集合再到角色权限关联表中获取该角色所拥有的权限id集合,然后再根据权限id集合到权限表(菜单表)中获取具体的菜单,展现给当前登录用户,从而达到不同用户看到不同的菜单权限。

 

为了防止用户不登录而直接访问后台资源我通过在项目中加入LoginInterceptor拦截器对未经认证的用户进行拦截,如果未经认证则跳转到登录页面使用户再次登录,除此之外还加入了PermissionInterceptor拦截器来对用户无权访问的资源进行拦截,如果无访问权限则跳转到没rr4有访问权限的页面。

 

再者考虑到性能将用户登录后所拥有的资源权限通过OScache结合单例设计模式将数据存储到了缓存中,这样可以避免每次操作都需要重新进行查询的代价,减少和数据库的交互次数,提高系统性能。考虑到单例的设计模式在多线程中会出现线程安全的问题,所以就给单例加了双重判断锁,从而避免该问题的发生。

11.抽象类和接口的区别?

共同点:

1. 都可以写抽象方法

2. 都不能被实例化对象

3. 类继承抽象类需要重写抽象方法,类实现接口也必须重写抽象方法

不同点

1. 类和接口是两个不同的概念,抽象类是由abstract修饰的类;接口不是类,interface定义

2. 接口中只能有抽象方法,抽象类中既可以有抽象方法,又可以有普通方法

3. 类是单继承多实现,实现一个抽象类,需要继承.实现接口需要implements

4. 接口定义的变量默认是public static final,而抽象类没有这个限制

 

12.GetPost的区别?

1.get是从服务器上获取数据,post是向服务器传送数据

2.get传送的数据量较小,不能大于2KBpost传送的数据量较大,一般被默认为不受限制。

3.get安全性非常低,post安全性较高。但是执行效率却比Post方法好。

4.在进行文件上传时只能使用post而不能是get

    5.不明确是post请求的都是get请求

 

 

13.RedirectForward的区别?

1、从数据共享上

      Forword是一个请求的延续,可以共享request的数据

      Redirect开启一个新的请求,不可以共享request的数据

2、从地址栏

      Forword转发地址栏不发生变化

      Redirect转发地址栏发生变化

 

 

14.Http协议的理解?

HTTP是一个超文本传输协议,属于OSI七层模型的应用层,由请求和响应构成,

是一个标准的客户端服务器模型。HTTP是无状态的也就是说同一个客户端的这次请求和上次请求是没有对应关系。

 

http的工作流程:

当发送一个http请求时,首先客户机和服务器会建立连接,

之后发送请求到服务器,请求中包含了要访问的url地址,请求的方式(get/post),

以及要传递的参数和头信息,服务器接到请求后会进行响应,

包括状态行,状态码,响应头,以及要响应的主体内容。客户端接收

到请求后将其展示到浏览器上然后断开和服务器端的连接。

 

简单说就是:建立连接--》发送请求--》响应--》断开连接

15.长连接和短连接?

HTTP/1.0中,默认使用的是短连接。也就是说,浏览器和服务器每进行一次HTTP操作,就建立一次连接,

但任务结束就中断连接。

 

 HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头有加入这行代码:

Connection:keep-alive

在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的 TCP连接不会关闭,

如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。

Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。

实现长连接要客户端和服务端都支持长连接。

 

HTTP协议的长连接和短连接,实质上是TCP协议的长连接和短连接。

16.你对jquery的理解?

 jquery是一个轻量级的js框架,具有跨浏览器的特性,兼容性好,

 并且封装了很多工具,方便使用。

 常用的有:  选择器 dom操作 ajax(ajax不能跨域) ,特效,工具类 

 

17.事务的概述?

 在数据库中,所谓事务是指一组逻辑操作单元即一组sql语句。当这个单元中的一部分操作失败,整个事务回滚,只有全部正确才完成提交。

判断事务是否配置成功的关键点在于出现异常时事务是否会回滚

 

事务的ACID属性

1. 原子性(Atomicity

原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,

要么都不发生。  

 

2. 一致性(Consistency

事务必须使数据库从一个一致性状态变换到另外一个一致性状态。(数据不被破坏)

 

3. 隔离性(Isolation

事务的隔离性是指一个事务的执行不能被其他事务干扰.

 

4. 持久性(Durability

 

持久性是指一个事务一旦被提交,

它对数据库中数据的改变就是永久性的.即使系统重启也不会丢失.

 

JDBC中,

事务默认是自动提交的,

每次执行一个 SQL 语句时,如果执行成功,

就会向数据库自动提交,而不能回滚

 

为了让多个 SQL 语句作为一个事务执行:

1)执行语句前调用 Connection 对象的 setAutoCommit(false);

     以取消自动提交事务

2)在所有的 SQL 语句都成功执行后,调用 commit(); 方法提交事务

3)在出现异常时,调用 rollback(); 方法回滚事务。

 

18.索引的概述?

1、索引的概念

    索引就是为了提高数据的检索速度。

数据库的索引类似于书籍的索引。

在书籍中,索引允许用户不必翻阅完整个书就能迅速地找到所需要的信息。

在数据库中,索引也允许数据库程序迅速地找到表中的数据,

不必扫描整个数据库.

2、索引的优点

  1.创建唯一性索引,保证数据库表中每一行数据的唯一性

  2.大大加快数据的检索速度,这也是创建索引的最主要的原因

  3.减少磁盘IO(向字典一样可以直接定位)

3、索引的缺点

   1.创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加

  2.索引需要占用额外的物理空间

   3.当对表中的数据进行增加、删除和修改的时候,

索引也要动态的维护,降低了数据的维护速度

4、索引的分类

1.普通索引和唯一性索引

  普通索引:CREATE  INDEX mycolumn_index ON mytable (myclumn)

      唯一性索引:保证在索引列中的全部数据是唯一的

   CREATE unique INDEX mycolumn_index ON mytable (myclumn)

    2. 单个索引和复合索引

      单个索引:对单个字段建立索引

      复合索引:又叫组合索引,在索引建立语句中同时包含多个字段名,

      最多16个字段

      CREATE INDEX name_index ON userInfo(firstname,lastname)

     3.顺序索引,散列索引,位图索引

 

 

19.三层分页的SQL语句?(手写)

首先不考虑查询条件 先写分页语句 在写条件

1.例如:河北省不满18周岁的男的456条信息

select * from

(select t.* ,rownum rn from

(select id,name, age,sex from t_student where name="河北" and age<18 and sex=""t

where rownum <= 6)

where rn >=4

2.女生年龄从高到低排序 每页3条 查询第3

select * from

(select  t.*,rownum rn from

(select  id,name,age from t_student order by age desc) t

where rownum <= 9)

where rn>=7

 

 

 

20.数据库三范式?

第一范式(1NF):强调的是列的原子性,即列不能够再分成其他几列。

    第二范式(2NF: 首先是满足第一范式,另外包含两部分内容,一是表必须有一个主键;二是没有包含在主键中的列必须完全依赖于主键,而不是部分依赖。

    第三范式(3NF: 首先满足第二范式,非主键列直接依赖于主键,消除传递依赖。

 

 

21.idrowidrownum的区别?

rowid物理位置的唯一标识。 

id是逻辑上的唯一标识,所以rowid查找速度要快于id,是目前最快的         

定位一条记录的方式

rowidrownum都是"伪数列"

所谓伪数列也就是默认隐藏的一个数列。

rownum用于标记结果集中结果顺序的一个字段,

它的特点是按顺序标记,而且是连续的,

换句话说就是只有有rownum=1的记录,才可能有rownum=2的记录。

rownum关键字只能和<或者<=直接关联

如果是>或者=则需要给他0起个别名

 

22.单例设计模式?(手写)

单例就是该类只能返回一个实例(实例只会创建一次)

单例所具备的特点:

1.私有的构造函数

2.私有的静态的全局变量

3.公共的静态的方法

双重锁定式

public class Singleton {

private Singleton(){};

private  static Singleton single;

public static Singleton getInstance(){

if(null ==single){

Synchronized(single){

if(null == single){

single = new Singleton();

}

}

}

return single;

}

}

 

23.主键和唯一索引的区别?

 在创建主键的同时会生成对应的唯一索引,主键在保证数据唯一性的同时不允许为         空,而唯一可以有一个为空数据项,一个表中只能有一个主键,但是一个主键可以         有多个字段,一个表中可以有多个唯一索引。

 

24.数据库连接池运行原理?

数据库连接池的优点运行原理:

在我们不使用数据库连接池的时候,每次访问数据库都需要创建连接,

使用完成之后需要释放关闭连接,而这样是很耗费资源的。当我们使用

数据库连接池的时候,在tomcat启动的时候就创建了指定数量的连接,

之后当我们程序使用的时候就直接从连接池里面取,而不需要创建,同理,

当我们使用完的时候也不需要关闭连接,而是将连接返回到连接池中,供

其他请求继续使用

 

DBCP:比较稳定。

C3P0: 性能比较高。

25.jdbc,ibatis,hibernate的区别?

Hibernate属于全自动, Ibatis属于半自动,Jdbc属于手动从开发效率上讲hibernate较高,ibatis居中,jdbc较低,从执行效率上讲hibernate较低,ibatis居中,jdbc较高,因为jdbc是手工写sql语句,程序员对sql的控制能力更大,可以根据业务需要进行优化,而ibatis虽然也可以对sql进行优化,但是他里面将resultset封装为实体的过程中采用了反射机制所以一定程度上影响了性能,而hibernate因为高度封装所以开发效率相对较高,但正因为这个原因,所以程序员在对sql语句的控制和优化方面相对比较弱,而且在将resultset封装成实体的过程中也采用了反射机制,所以在性能方面较低

 

26.SQL优化?

外键必须加索引。

避免在 where 子句中对有索引的字段进行运算,这会导致索引失效,从而进行全表扫描。

 where order by 涉及的列上建立索引,要尽量避免全表扫描。

在设计表时要避免表中字段出现null的情况,通常要为其设置默认值。

避免在查找时放弃使用索引而进行全表扫描。

SELECT语句中避免使用‘*,只查询需要返回的字段 ,这样可以减少oracle解析sql语句的时间。

NOT EXISTS 替换 NOT IN 操作符,用 EXISTS  替换 IN

27.Java代码优化?

解析大文件的xml

 

数据使用sax替代dom4j,使用分段批量提交来完成大数据量的插入。

对于大批量字符串的拼接使用stringbuffer或者stringbuilder代替string进行+拼接。

根据业务情况使用缓存减少对数据库的访问。

单线程应尽量使用 HashMap, ArrayList,因为HashTable,Vector使用了同步机制,降低了性能。

finally块中关闭流,断开连接,释放资源

避免在循环条件中使用复杂表达式 

 

28.Hibernate优化?

3.Hibernate优化:

在处理大数据量时,会有大量的数据缓冲保存在Session的一级缓存中,这缓存大太时会严重显示性能,所以在使用Hibernate处理大数 据量的,可以使用session. clear()或者session. evict(Object) ,在处理过程中,清除全部的缓存或者清除某个对象。

通过使用Hibernate的一级缓存,二级缓存,查询缓存等来提高性能 (必须)

Hibernate可以通过设置hibernate.jdbc.fetch_sizehibernate.jdbc.batch_size等属性,对Hibernate进行优化。

        Batch Size是设定对数据库进行批量删除,批量更新和批量插入的时候的批次大小,Batch Size越大和数据库交互的次数就越少,速度就越快, 但也不要无限的大下去,通常选择一个合适的值,如100条;其次我们在进行大批量数据的导入操作时,可以结合batchsize进行分段批量提交,从而达到最优效果。

 

29.数据库优化?(被动说)

数据库优化:作为开发人员最主要是从sql语句的优化方面考虑的,对于数据库底层的优化,是由DBA完成的。

在我们公司里面做项目的时候,在开发过程中最主要是由程序员对java代码以及sql语句这方面进行优化,至于数据库 底层的优化,则由DBA在项目基本结尾进行压力测试的时候参与进来,通过对数据库的分析,确定影响性能的sql语句以及相关的表,通过和我们进行交流然后对其进行适当的改进。

 

30.mysql优化?【慢日志,分表,sql执行计划】

慢日志就是在我们设置的时间内执行慢的语句可以在慢日志看到!

 

2.分表:

时间划分  地区划分

水平划分  垂直划分(把平常经常使用的提取出来加上索引)

3.mysql中通过explain查看执行计划

 

31.Freemarker静态化?

在做XX电商项目的时候,考虑到提高网站前台的性能,承受更大的并发,我们将网站首页和很多文章页面都进行了静态化。当时采用的方式是通过freemarker模板引擎spring定时器来结合完成的。前台美工通过网站管理后台用freemarker编写首页模板以及相关的样式,之后将模板信息存入模板表,我负责编写spring定时器在每晚的凌晨从数据库中的模板表中取出各种类型的模板并和相关的数据结合起来生成静态的html页面。并且考虑到减少前台美工编写freemarker标签的难度,我将经常用到的一些功能像分页,列表展示等通过#macro编写为freemarker的宏命令,方便前台美工直接使用。对于及时性要求比较高的特别热门的频道,则在用户点击发布时直接调用编写的接口通过freemarker和数据结合生成html静态页面

32.Redis分布式缓存?

redis是一个基于key,value的支持多种数据类型(StringListSetzSetHash)的可进行持久化内存数据库。我们在项目中通常使用redis来充当缓存服务器来缓存分类列表,品牌列表,热销商品,推荐商品以及该商品的关联商品等等。以前做项目的时候,我们是把商品的信息存放在redis里面,redis支持多种数据类型,有两种方法存储对象:1,可以把对象序列化进行存储,然后反序列化取出。2.hash结构存储,最后发现,还是用hash存取比较快

当时我们就是在redis中设置maxmemory【最大内存】,把maxmemory-policy【数据清除策略】设置为allkeys-lru。为了保证redis不会因为占用内存过大而导致系统宕机,也会设置最大内存数据清除策略。使用了jedis作为客户端,并考虑到性能问题使用了jedis连接池。考虑到redis服务器的高可用性,我们做了redis的主从复制,刚开始配置redis的时候,我是关闭它的保护模式,虽然实现了功能,但是不安全,最后是在redis.conf配置文件中绑定具体的ip地址,这样只有该ip地址才能访问redis服务器,并且设置长度为20位左右的密码,从而保证只有进行了密码授权才能进行相关的操作,为了信息安全,我们配置了redis的主从复制,在从服务器的配置文件中通过配置slaveof绑定主服务器的ip地址和端口号,

当设置好slave服务器后,slave会建立和master的连接,然后发送sync命令。无论是第一次同步建立的连接还是连接断开后的重新连接,master都会启动一个后台进程,将数据库 

快照保存到文件中,同时master主进程会开始收集新的写命令并缓存起来。后台进程完成写文件后master就发送文件给slaveslave将文件保存到磁盘上,然后加载到内存恢复数据库快照到slave上。接着master就会把缓存的命令转发给slave。而且后续master收到的写命令都会通过开始建立的连接发送给slave。从masterslave的同步数据的命令和从 client发送的命令使用相同的协议格式。当masterslave的连接断开时slave可以自动重新建立连接。如果master同时收到多个slave发来的同步连接命令,只会使用启动一个进程来写数据库镜像,然后发送给所有slave

哨兵要监视 Redis 服务器,就必须连接 Redis 服务器。启动哨兵的时候需要指定一个配置文件,程序初始化的时候会读取这个配置文件,获取被监视 Redis 服务器的 IP 地址和端口等信息。

哨兵连接redis服务器发送两个连接一个是普通连接,另一个是订阅发布专用连接。哨兵在初始化订阅发布连接的时候,做了两个工作:一是,向 Redis 服务器发送 SUBSCRIBE SENTINEL_HELLO_CHANNEL命令;二是,注册了回调函数 sentinelReceiveHelloMessages()

哨兵会向 hello 频道发送包括:哨兵自己的IP 地址和端口,runid,当前的配置版本;其所监视主机的 IP 地址,端口,当前的配置版本。【这里要说清楚,什么是 runid 和配置版本】虽然未知的信息很多,但我们可以得知,当一个哨兵新加入到一个 Redis 集群中时,就能通过 hello 频道,发现其他更多的哨兵,而它自己也能够被其他的哨兵发现,哨兵向与 Redis 服务器的命令连接通道上,发送了一个INFO 命令(字符串);并注册了回调函数sentinelInfoReplyCallback()Redis 服务器需要对 INFO 命令作出相应,能在 redis.c 主文件中找到 INFO 命令的处理函数:当 Redis 服务器收到INFO命令时候,会向该哨兵回传数据,包括:

关于该 Redis 服务器的细节信息,rRedis 软件版本,与其所连接的客户端信息,内存占用情况,数据落地(持久化)情况,各种各样的状态,主从复制信息,所有从机的信息,CPU 使用情况,存储的键值对数量等。

由此得到最值得关注的信息,所有从机的信息都在这个时候曝光给了哨兵,哨兵由此就可以监视此从机了。

Redis 服务器收集了这些信息回传给了哨兵,刚才所说哨兵的回调函数 sentinelInfoReplyCallback()会被调用,它的主要工作就是着手监视未被监视的从机;完成一些故障修复(failover)的工作。连同上面的一节,就是Redis  auto discover 的全貌了。

在哨兵的定时程序中,哨兵会向所有的服务器,包括哨兵服务器,发送 PING 心跳,而哨兵收到来自 Redis 服务器的回应后,也会更新相应的时间点或者执行其他操作,哨兵不仅仅凭借自己的信息,还依据其他哨兵提供的信息判断 Redis 服务器是否下线的方法称为客观方法,即通过所有其他哨兵报告的主机在线状态来判定某主机是否下线。

 

一个 Redis 集群难免遇到主机宕机断电的时候,哨兵如果检测主机被大多数的哨兵判定为下线,就很可能会执行故障修复,重新选出一个主机。一般在 Redis 服务器集群中,只有主机同时肩负读请求和写请求的两个功能,而从机只负责读请求,从机的数据更新都是由之前所提到的主从复制上获取的。因此,当出现意外情况的时候,很有必要新选出一个新的主机。

 

优选选择优先级高的从机

优先选择主从复制偏移量高的从机,即从机从主机复制的数据越多

优先选择有 runid 的从机

如果上面条件都一样,那么将 runid 按字典顺序排序

 

并且通过加入哨兵来使redis主服务器宕机时,从服务器自动转换为主服务器继续提供服务。

 

 

33.jdbc操作数据库的步骤?   

  ①加载数据库驱动程序(Class.forName("数据库驱动类");)
      连接数据库(Connection con  = DriverManager.getConnection();)
      操作数据库(PreparedStatement stat = con.prepareStatement(sql);stat.executeQuery();)
      关闭数据库,释放连接(con.close();)

34.悲观锁,乐观锁?

悲观锁/乐观锁:

悲观锁(Pessimistic Lock), 每次去查询数据的时候都认为别人会修改,

所以每次在查询数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。

传统的关系型数据库里边就用到了这种锁机制,比如通过select ....for update进行数据锁定。

 

乐观锁(Optimistic Lock), 每次去查询数据的时候都认为别人不会修改,

所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,

可以使用版本号时间戳等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量。

 

35.Spring中事务的隔离级别,传播特性?

spring中事务的传播特性好像有5个左右,

我做项目的时候使用最多的就是PROPAGATION_REQUIRED

它所代表的意思支持当前事务,如果当前没有事务,就新建一个事务。

 

spring中事务的隔离级别有5个,默认使用的是ISOLATION_DEFAULT,

它代表使用数据库默认的事务隔离级别,也是我们项目中最常使用的。

除此之外还有

 

读未提交:

它充许另外一个事务可以看到这个事务未提交的数据,

这种隔离级别会产生脏读,不可重复读和幻像读。

 

     

读提交:    

保证一个事务修改的数据提交后才能被另外一个事务读取,

也是大多数数据库的默认值。可以避免脏读,但会产生不可重复读和幻像读。

 

重复读:

在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。     

 

串行化:

顺序执行事务。除了防止脏读,不可重复读外,还避免了幻像读。

并发性也最低,但最安全。

        

不可重复读的重点是修改 :

同样的条件 , 你读取过的数据 , 再次读取出来发现值不一样了

幻读的重点在于新增或者删除 

同样的条件 , 1 次和第 2 次读出来的记录数不一样。

36.MongoDB概述?

mongodb是一个nosql数据库,我们在项目中通常用它来存储评论信息,

【评论id,商品id,标题,评分,内容,评论人信息,评论的发布时间】

因为每个商品都会有评论信息,而且某些热门商品的评论信息可能是数千条,

mongodb正好适用于这种大数据量、高并发、弱事务的互联网应用。考虑

mongodb的高可用性我们搭建了3mongodb数据库来实现副本集,这样

不仅可以达到故障自动转移的特性而且也可以通过读写分离提高性能,即便

主服务器宕机了,还会通过投票选举出下一个主服务器继续提供服务。

 

 

再者考虑到我们的项目最后要部署到多台tomcat通过nginx来实现负载均衡,

为了对项目中的文件以及图片进行统一的管理,我们就用mongodb来充当文件服务器。

对于大部分的单张图片和单个文件来说小于16M,所以我们就以常规的方式来将

文件转换为二进制的字节数组进行保存。考虑到高可用性以及为了应对后期随着文件数量的不断

增加而能够方便进行扩容,我们建立了3个分片并将分片和副本集做了整合,每个分片都是一个副本集,这样

不仅满足了大数据量的存储也避免了分片中单台机器导致的单点故障问题。考虑到可能要处理

大于16M的文件,所以又增加了支持大文件存储的gridfs,这样即便再大的文件也会被gridfs分解为多个

chunk进行存储。

37.Easyui概述?

我们在项目中通常用EasyUI来充当展示层,因为它是一个RIA富客户端框架,

自身提供了很多功能强大的插件,可以提高用户的体验度而且也有助于我们

开发人员直接使用,提高开发效率。我们在项目中使用到的EasyUI插件有Layout布局,

EasyUItree,Tab页面,datagrid,form表单,Dialog对话框,Messager提示信息还有

Accordion手风琴效果,progress进度条等。

 

EasyUItree的生成方式有两种,一种是通过一条sql语句查询所有的菜单信息,

然后在java中通过递归的方式将其拼装成符合指定json格式的数据,这种适用

于数据量比较小的情况,通过减少数据库的访问次数提高性能,另一种是通过

ajax异步加载的方式,每点击一下树节点就向后台发送一次请求,从而来获取

该节点下的子节点,这种适用于数据量比较大的情况。这时候如果采用取出全

部数据递归拼装的话就有可能出现内存溢出。

 

 

我们当时在项目中是通过Easyuitree来生成菜单,考虑到菜单的

数据量也不是特别的大,所以就采用了第一种取出所有数据递归将其

拼装指定Json的方式来提高性能,再者考虑到每个用户的菜单信息并

不是经常改变,所以又结合oscache缓存以及带有双重判定锁的单例模式

将其缓存到内存中,从而再次提高了性能。

 

点击树形菜单,动态添加tab的时候一定要注意,为了避免每次点击

都添加一个新的tab页,我们的做法是当点击事件发生时,先判断当前

选中的菜单所对应的tab是否已经存在,如果存在就将其激活选中,否则

再添加新的。多个tab页出现的另一个问题就是不同tab页间的数据可能不

同步,所以我们会在每个tab页上面都增加一个刷新按钮,可以通过点击

该按钮给该tab页所对应的iframesrc属性重新赋值,来起到刷新的作用。

 

datagrid也是我们在项目中经常使用到的,在使用datagrid时应该注意的是

在拼装好的json数据中,需要有totalrows这两个属性,其中total用来

指明数据的总条数rows用来指明当前页的数据列表;在前台页面中要保证

columns中的fieldrows中的属性名相对应,否则数据就展现不出来,而且

对于图片等制定格式数据的展示需要结合formatter对其进行格式化才能进行

正确的显示。最后就是在datagridform表单结合进行数据查询时调用的是

load方法,进行增删改后刷新datagrid调用的是reload方法。

38.BootStrap概述?

Bootstrap是一个支持响应式的Css框架它提供了很多组件,

如导航条,面板,菜单,form表单,还有栅格,

而且他们这些都是支持响应式的,可以在各种

设备上进行完美的展现。这里面我感觉最有价值的就是

bootstrap提供的栅格系统,这个栅格系统将

整个页面分为12列,而且可以根据屏幕的宽窄进行自动

调节,这也是响应式的关键所在。在使用栅格系统的时候

要注意最外层样式是Container,里面是row,row里面包含

的是列,列里面可以用来填充各种各样的组件。

 

我在项目中使用bootstrap完成的情况大概是这个样子,

首先我使用了bootstrap的导航条,并将其固定在顶部,

使其在拖拉滚动条的时候不至于看不到,

之后在导航条的下面采用了bootstrap的栅格系统将其分为左右两部分,

左边使用bootstrapTreeview组件,将菜单展现出来,当点击treeview

上的菜单节点时结合一个第三方的tab组件,将需要展示的内容放到tab页内,

并进行上下切分,上面使用了bootstrapform组件,

下面使用了它的响应式表格以及分页组件,在进行增加修改时,

使用了第三方的bootbox弹出框。

 

 

 

 

40.你上家公司在哪?你在哪住?你去公司怎么坐车?

  北京市海定区阜外亮甲1号中关注联网创意产业园27号楼 丰台区)

 海淀区蓝靛厂 晨月园小区  远大路公交站上车   355/79/118线都能到 坐六站(定慧北桥下车)走大概5分钟就到了  

公司附近 在那边有一个丰台科技原生态主题公园

晨月园附近有个巨人学校

 从育新坐606路公交到成府路南口下车然后在步行到公司 

41.你期望薪资多少?你上家工资多少?税后拿到手的有多少?扣了多少钱的税?

 15K    14K   13K    1000

42.你哪个学校毕业的?学的什么专业?你们学校校长叫什么名字?你们学校还有啥其他专业吗?你大学都学了什么?

郑州理工专修学院    计算机科学与技术       刘信古 

有,还有,酒店服务管理 建筑工程  行政管理  轨道交通运营  等等。。。

计算机原理 计算机网络 高级语言 编程语言  操作系统 数据结构

43.你今年多大了?属相是啥?

26        

44.你为啥从上家公司离职?

合同到期,想换一个新的环境,公司这边也挽留我,但是在公司也呆了,2.3年了,

   想换一个新的平台,来不断提升充实自己。

45.你交社保了吗?为啥没交?

 在上家公司的时候,人事说咱们公司的五险一金如果要上的话都是从自己工资里面扣的,

    当时感觉没啥必要也就没上。

46.你的优缺点是啥?

这几年做程序,因为要不断的对代码进行验证确认,所有感觉自己现在有点强迫症。

47.你的五年规划是啥?

2,3年继续加强自己的技术功底,然后朝着项目经理(技术经理,产品经理)方面发展

48.你啥时候上的大学?哪年毕业的?从火车站怎么到你们学校?你们学校周围都有啥?

20089     20126   下了火车打个车10来块钱   

(吹牛逼的活) 有一些卖衣服的 卖吃的 小超市 酒店什么的....

49.你知道五险一金都是啥吗?

养老保险,医疗保险,失业保险,工伤保险,生育险 住房公积金

50.你们公司有多少人?你们公司有哪几个部门?

  60人左右   技术部 销售部 行政部  人力资源部  财务部

 

 

51.你对ajax是怎么理解的(融入ajax跨域的解决方案)?

 ajax全称是异步javascriptxml

     ajax的核心JavaScript中的xmlHttpRequest(XHR)

     使用ajax可以提高用户的体验度,进行异步数据传输从而提高性能。ajax不能跨域,所谓不能跨域就是不能跨多个网站(多个域名),不能跨多个项目可以通过jsonp来解决ajax跨域的问题,而jsonp的实质就是通过动态添加script标签来实现的

52.Ajax超时、Ajax同步异步、原生的Ajax

Ajax是默认没有超时时间,如果我们想要ajax超时在ajax中有一个timeout这个属性设置它的时间是根据秒来设置

Ajax 异步是跳转页面加载一部分数据当点击按钮的时候加载另一部分数据这样的使用于大数据量的加载

Ajax同步 是跳转页面一下子执行了说有的ajax请求加载了所有的数据这样的如果在大量数据中页面会卡

Ajax中有async属性 async =”true”是同步flase是异步 默认的是异步

原生的ajaxxmlhttprequest

 

 

53.你对webservice是怎么理解的?

(主动说)

     webserviceSOA(面向服务编程)的一种实现,

     主要是用来实现异构平台通信也就      

     不同平台不同项目之间的数据传输,从而避免了信息孤岛的问题,

     它之所以能够

     进行异构平台通信是因为它是完全基于xml的,

     所以说,webService是跨平台

     跨语言,跨框架的,在java中通常有三种技术框架分别是xfire,cxf,axis2

     我们为了保证        

webservice的安全性,采用了基于

WS-Security标准的安全验证(使用回调函数)

 

 

 

(没必要主动说)

     webservice的三要素分别是:

     wsdlwebservice description language

     用来描述发布的接口(服务)

     

     soap(simple object access protocol)

     xmlhttp的结合,是webservice数据通信的协议

     

     uddi 用来管理,查询webService的服务

(没必要主动说)

     webservice的具体三种实现方式(框架)或者三种实现框架的区别

      1. Axis2:可以用多种语言开发,

      是一个重量级框架,功能非常强大,

      但是它的性能比较低。

 

      2. Xfire:它相比Axis2来说是一个轻量级框架,

      它的性能要比Axis2高。

      3. cxf:是Xfire的升级版,就好比是,

      struts2webwork的升级,

      然后cxfspring集成起来非常方便,简易,

      性能方面也要比Xfire高。

      【注】jdk6 自带的webservice  jws

 

(主动说)

业务场景

我在以前做项目的时候,其中遇到一个功能,

需要进行两个项目之间的数据的传输,

项目经理让我去完成这个任务,我根据以往的项目经验,

想到两种解决方案,第一种

就是开放另外一个项目的数据库的权限给我,

然后我直接通过访问另外一个项目的数据

库,来得到需要的信息,但后来我分析了下,觉的这种方式不安全,

而且因为当时

这个项目是另外一家公司负责在做,所以数据库里面的表结构,

以及以后牵涉

到的责任问题都很多,所以我就采用了第二种方案,

即通过webservices的方式,进行

异构系统之间数据信息的传递,webservices的具体实现,

xfire,cxf,axis2,

我根据以往的项目经验,了解到cxfxfire的升级版本,适用于java语言,

xfire/cxf 性能比axis2要高,并且和spring整合起来也比较方便,

axis2支持更多的语言,

性能相对于cxf要低,通过上面分析,

结合我们目前的两个项目都是基于java      

语言的,所以我采用cxf这种方式实现了两个项目之间数据的传递,

我们为了保证        

webservice的安全性我们采用了基于

WS-Security标准的安全验证(使用CXF回调函数)

 

(没必要主动说)

webservice服务端配置流程

首先在web.xml中引入cxfServlet核心类,

指定对以/cxf开头的url路径提供webservice服务,

之后我们在要发布成webservice接口上添加@Webservice 注解,

而且还要在实现类上添加同样的webservice注解并且要说明实现了哪个接口,

之后在spring-webservice.xml中发布webservice服务,

通过jaxws:endpoint这个标签,

并且在标签配置implementoraddress来表明实现服务的类,

以及发布的地址,

最后在浏览器中输入相关的webservice地址?wsdl来验证服务是否发布成功。

 

(没必要主动说)

webservice客户端的配置

首先通过wsdl2java根据发布的webservice服务端地址的wsdl

生成客户端调用的中间桥梁java类,

将生成的java类拷贝到客户端项目中,

配置spring-client.xml文件,

通过jaxws:client定义一个bean,

并通过address属性指明要访问的webservice的服务地址,

通过serviceClass指明充当中间桥梁的服务类,之后获取该bean,

就可以通过它来访问发布的webservice接口中的方法。

 

54.你对负载均衡这块有认识吗?

负载均衡:

(了解)

    我们在做这个项目时,考虑到服务器性能的问题,最开始想到使用纵向扩展,来增加硬件的配置提高其性能,但这样做比较耗费资金,而且服务器内存空间也是有限的;所以后来就使用横向扩展来达到这一目的.

 

(主动说)

     当时我们使用nginxn g s+3tomcat进行负载均衡,在我们不进行负载均衡之前,那所有的请求都由一台tomcat进行处理,这样会使我们的tomcat所承受的压力增大,而我们进行负载均衡之后,同样数量的请求经过nginx将其分发到多台tomcat进行处理,从而降低每台tomcat所承受的压力,而且当其中一台机器宕机时,其他机器还可以继续提供服务,保证服务不间断。

 

    当时项目在部署完成后,遇到这么个问题,用户登录输入验证码的时候,明明验证码输入的正确,但总是提醒说验证码不正确从而不能正常登录,经过分析后发现有可能第一次

请求被发送到t1上,那么放在session中的验证码就被放到了t1上,当用户输入验证码点击登录时,新发送的请求有可能被发送到t2上面,这样在进行对比时就肯定会不一致从

而提示验证码输入错误,后来我就考虑使用ip_hash这种负载均衡策略来代替默认的轮询策略,虽然解决了验证码错误问题,但是在后续的测试中发现如果用户在使用过程中

突然一台服务器宕机了,那么因为session在这台服务器上存储着,所以就会提示用户重新登录,这样使用户的体验度非常不好,最后就通过将session信息保存到redis服务器中从而在

多台web服务器中实现session共享,这样就解决了上面所说的那些问题。

 

怎么避免nginx产生单点故障(被动说)

同时我们为了避免nginx的单点故障,达到高可用性,就在nginx的前面又加了一个F5,从而将请求分配给多个nginx,再通过nginx分配给多个不同的Tomcat。这样大大的提高了服务的有效性,并且进一步提高了性能。

 

55.你在linux上怎么部署项目?

1.Linux下常见的分支:

CentOS:服务端【纯开源】

RedHat:服务器端【收费】

Ubantu:个人电脑

2.访问方式:通过SSH/Putty客户端连接服务器

3.如何使用:

1.虚拟机的好处?

可以在虚拟机中随意操作系统,不怕影响或损害电脑;

2.克隆(备份):快速创建当前系统的备份,快速创建另外一个虚拟系统;

manage 下的clone

linked(链接克隆) 软克隆 优点:速度快,生成文件小;

full(完整克隆) 硬克隆 优点:文件大,速度比较慢;

选择桥接模式;

只查出四行 ping Ip -c 4

3.快照:可以将当前的虚拟系统快速还原到某一时刻;都是一个虚拟系统。

快照 Snapshot 下的 Take Snapshot

快照的好处:埋下几个点,方便还原

4.命令:

 

注意:

rpmLinux下一种软件安转包的后缀名。如*rpm ,等同于windows中的exe.rpm是一个命令,用来进行和软件安装相关的操作。(安转,卸载,查找)

linux下没有盘符的概念,它是通过相关的目录来管理资源的。我们通常在/home中创建文件夹来存放需要安转的软件

tab键自动补全    *代表当前目录下的所有文件

JDK默认安装在 usr/java

设置jdk的环境变量:

修改/etc/profile文件

用文本编辑器打开 /etc/profile

profile文件末尾加入:

export JAVA_HOME = /usr/java/jdk.1.7.0_79

export PATH = $JAVA_HOME/binL$PATH

source  /etc/profile 使修改立即生效

echo $PATH     查看PATH

 

56.你对linux中的常用命令都了解哪些?

1.ifconfig:查看IP地址

2.java -version :jdk的版本

3.rpm -qa | grep 软件的名称 :查找和指定名称相关的软件

4.rpm -e --nodeps 软件的名称 :卸载指定的软件

5.rpm -ivh 软件名称 :安装指定的软件

6.uname -a 查看Linux系统的基本信息(计算机名,操作位数,版本号)

7.LL 查看文件夹下的文件

8.mkdir 创建文件夹

9.vi文件名: 对指定的文件名进行编译。

i进入编辑模式,

ESC键进入命令模式

wq! 强制保存并退出

q!强制退出(!是强制的意思)

   10.pwd :查看当前目录的完整路径

11.unzip 文件名.zip :解压后缀名为zip的压缩文件

zip 文件名.zip 要压缩的文件

12.mv 源文件 目标文件名(mv可以移动/重命名)

13.rm -rf 文件夹名 :递归强制删除文件夹及其下的文件

14.service iptables stop 禁用防火墙

15.chmod +x *.sh :使所有的后缀名为sh的文件,拥有可执行的权限

16.bin目录下 ./startup.sh 启动tomcat

17.bin目录下通过tail -f ../logs/catalina.out 来查看启动日志 tail -n 300 ../logs/catalina.out 查看最后三百行的信息

18.cat 文件名:查看整个文件内容

19. ps -ef | grep 进程名:查看指定进程是否启动

20.kill -9 进程号 :强制杀死进程

killall -9 进程名

21. find / -name 文件名 -print   :查看指定文件的路径

vi 在命令模式下  yy复制当前光标所在行

  p粘贴

  dd 删除当前行

vi /etc/sysconfig/iptables 更改防火墙的配置文件,开放新的端口号

重启防火墙 service iptables restart

查看当前防火墙的状态 service iptables status

export JAVA_HOME = /usr/java/jdk.1.7.0_79

export PATH = $JAVA_HOME/binL$PATH

source  /etc/profile 使修改立即生效

echo $PATH     查看PATH

 

57.MySQL主从复制  读写分离【主动】

我们在项目中的关系型数据库采用的是MySQL,考虑到对事务的支持使用的是InnoDB引擎,为了保证数据库数据的安全,达到高可用性,以及分担服务器压力我们对MySQL进行了主从复制的配置并结合MyCat这个数据库中间件进行读写分离。我们项目 目前采用的是一主带2或者3从的架构。因为互联网项目一般都是读的多,写的少,所以通过这种一主多从的架构分担了单台数据库的压力并且在一台服务器宕机的情况下也能保证项目的基本运行。

 

58.主从复制的配置步骤:【被动】

主从复制的配置比较简单,最主要是开启主服务器的二进制日志并指明一个唯一的标识,从服务器也要指明一个唯一的标识,并且在主服务器上创建账号,开启复制权限;在主服务器上运行show master status查看主服务器的状态,之后在从服务器上用刚才建立的账号连接指定的的主服务器,并指明要复制的二进制文件以及起始位置,最后运行start slave就可以了,然后通常运行show slave status查看从服务器的状态,如果slave_ioslave_sqlyes,就证明配置成功了。

 

59.主从复制的运行原理:【被动】

最主要就是主服务器上的二进制日志以及从服务器上的IO线程,SQL线程,以及中继日志。主服务器将其自身的改变存入到二进制日志中去,从服务器连接主服务器并通过IO线程读取主服务器上的二进制日志,将读取的内容存入自身的中继日志,之后SQL线程会读取中继日志中的sql语句对其进行执行,这样就保证了从服务和主服务器的一致性。MySQL的主从复制默认是基于sql语句进行的。

60.MyCat概述

 

 

61.项目的生命周期

    1.需求分析

2.概要设计

3.详细设计(用例图,流程图,类图)

4.数据库设计(powerdesigner)

5.代码开发(编写)

6.单元测试(junit 白盒测试)(开发人员)

svn版本管理工具(提交,更新代码,文档)

7.集成测试 (黑盒测试,loadrunner(编写测试脚本)(高级测试)

8.上线试运行 (用户自己体验)

9.压力测试(loadrunner

10.正式上线

11.维护

 

62.httpClient

httpClient是一个支持http协议的客户端编程工具包,我们在java中调用httpClient是通过url模拟了一个http请求,这样就可以通过java代码直接发送请求获得服务端响应数据,首先构建HttpClient,new DefaultHttpClient(); httpClient发送请求的方式也分成两种形式:一个 new httpGet(),一个是new httpPost() 把请求的url放进去,然后用excute发送请求,获取响应信息,里面包含状态码,成功为200,包含响应内容,将内容转换为字符串,最后关闭连接,其中post请求是模拟表单提交完成的、不能传递参数

 

63.多线程

1.java中实现线程的方式

java中实现线程有两种方式:继承Thread类,实现Runable接口,一个java main程序默认会开启两个线程一个是主线程,一个垃圾回收线程。

2.线程不安全与安全:

多个线程访问同一个资源,导致结果和期望值不同,我们就说它是 非线程安全的(线程不安全),反之我们就说它是 线程安全的。

了解:

a.多个线程访问同一个资源(这里的资源通常指的是全局变量或者静态变量),如果每次运行结果和单线程运行的结果一样的,就是线程安

全的。

b.线程安全问题都是由全局变量静态变量引起的。

c.若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;

若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。

3.线程的状态

1、新建状态(New):新创建了一个线程对象。

2、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU使用权

3、运行状态(Running):就绪状态的线程获取了CPU执行程序代码

4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:

  ()等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。

  ()同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。

  ()、其他阻塞:运行的线程执行sleep()join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期

了解:

1、线程的实现有两种方式,一是继承Thread类,二是实现Runnable接口,但不管怎样,当我们new了这个对象后,线程就进入了初始

状态;

2、当该对象调用了start()方法,就进入可运行状态;

3、进入可运行状态后,当该对象被操作系统选中,获得CPU时间片就会进入运行状态;

4、进入运行状态后情况就比较复杂了

4.1run()方法或main()方法结束后,线程就进入终止状态;

4.2、当线程调用了自身的sleep()方法或其他线程的join()方法,就会进入阻塞状态(该状态既停止当前线程,但并不释放所占有的资

源)。当sleep()结束或join()结束后,该线程进入可运行状态,继续等待OS分配时间片;

4.3、线程调用了yield()方法,意思是放弃当前获得的CPU时间片,回到可运行状态,这时与其他进程处于同等竞争状态,O566S有可能会接

着又让这个进程进入运行状态;

4.4、当线程刚进入可运行状态(注意,还没运行),发现将要调用的资源被synchronized(同步),获取不到锁标记,将会立即进入锁

池状态,等待获取锁标记(这时的锁池里也许已经有了其他线程在等待获取锁标记,这时它们处于队列状态,既先到先得),一旦线程获

得锁标记后,就转入可运行状态,等待OS分配CPU时间片;

4.5、当线程调用wait()方法后会进入等待队列(进入这个状态会释放所占有的所有资源,与阻塞状态不同),进入这个状态后,是不能自

动唤醒的,必须依靠其他线程调用notify()notifyAll()方法才能被唤醒(由于notify()只是唤醒一个线程,但我们由不能确定具体唤醒的

是哪一个线程,也许我们需要唤醒的线程不能够被唤醒,因此在实际使用时,一般都用notifyAll()方法,唤醒有所线程),线程被唤醒后

会进入锁池,等待获取锁标记。

补充:(waitsleep的区别)

wait时会释放锁资源但sleep不会释放锁资源,wait通常和notify以及notifyAll结合使用,需要notify或者notifyAll对其进行唤醒,sleep通常在指定的时间内自动唤醒

4.解决线程安全的问题的方案:

a.通过加锁synchronized)的方式解决线程安全问题

1.synchronized 方法

2.synchronized (同步代码块)

b.避免使用全局变量

c.使用ThreadLocal(参考:http://blog.csdn.net/drifterj/article/details/7782706)

1. 为多线程并发的互斥控制提供了另一种全新的解决思路

2. 通过ThreadLocal为其他模块的API传递参数

5.java线程池 (可参考:http://www.oschina.net/question/565065_86540)

1.减少了创建和销毁线程的次数,

每个线程都可以被重复利用

可执行多个任务

2.可以根据系统的承受能力,

调整线程池中线程的数目

防止因为消耗过多的内存,

而导致服务器宕机

(每个线程需要大约1MB内存,线程开的越多,

消耗的内存也就越大,最后宕机)

通常我们使用的线程池是实现了ExecutorServiceThreadPoolExecutor

6.死锁

死锁是因为多线程访问共享资源,由于访问的顺序不当所造成的,通常是一个线程锁定了一个资源A,而又想去锁定资源B;在另一个线程

中,锁定了资源B,而又想去锁定资源A以完成自身的操作,两个线程都想得到对方的资源,而不愿释放自己的资源,造成两个线程都在等

待,而无法执行的情况。

死锁产生的原因:是由访问共享资源顺序不当所造成的.

简单的说:所谓死锁,是指两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。

7.守护线程

Java中有两类线程:User Thread(用户线程)Daemon Thread(守护线程)

用个比较通俗的比如,任何一个守护线程都是整个JVM中所有非守护线程的保姆:

只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结束时,守护线程随着JVM

一同结束工作。

Daemon的作用是为其他线程的运行提供便利服务,守护线程最典型的应用就是 GC (垃圾回收器),它就是一个很称职的守护者。

UserDaemon两者几乎没有区别,唯一的不同之处就在于虚拟机的离开:如果 User Thread已经全部退出运行了,只剩下Daemon

Thread存在了,虚拟机也就退出了。 因为没有了被守护者,Daemon也就没有工作可做了,也就没有继续运行程序的必要了。

 

64AOP——面向切面编程

1.概念以及和oop的比较

2.AOP:面向切面编程

1.AOPOOP(面向对象编程)的延续,是Aspect Oriented Programming的缩写,意思是面向方面编程或者面向切面编程AOP是基于代理模式来实现的。(23种设计模式:工厂模式、代理模式、单例模式、适配器模式、责任链模式、装饰模式,模式的应用场景不是很明确,什么场景用什么模式都是可以理解或解释的。一个项目并不是运用的模式越多,则代表项目更强大,反而显得臃肿,复杂度提高了,从而影响代码的效率、开发人员的开发效率,项目的维护成等)

2.AOP主要应用于日志记录,性能统计,安全控制,事务处理等方面。它的主要意图就要将日志记录,性能统计,安全控制等等代码从

核心代码中清楚的划分出来。

3.AOP代理可以通过jdk动态代理实现,也可以通过cglib实现,默认是通过jdk动态代理实现的。jdk动态代理需要接口的支持,如果没有接口只有类,则使用cglib来实现。

jdk基于接口,cglib基于类

2.Spring AOP基于代理设计模(基于JDK的动态代理)

所谓代理设计模式:在代理模式中有个接口,接口中有个代理实现和一个真实实现,要用代理实现去代表真实实现。

1. 静态代理:

一个接口,分别有一个真实实现和一个代理实现。静态代理中,真实实现和代理实现都是实现了同一个接口,并且把真实实现作为参数传递给代理实现去调用。

 

缺点:这种模式的代理类只能为一个接口的对象进行代理,这即是静态代理。要解决这样的问题,可以采用动态代理。

 

1. 动态代理(基于jdk的动态代理):

使用一个代理类便可以代理所有接口动态代理,通过代理类的代理,接口和实现类之间可以不直接发生联系,而可以在运行期(Runtime)实现动态关联,代理实现 都需要实现InvocationHandler接口,这个时候我们需要用到Proxy里面 newProxyInstance需要有三个参数1.实现类,2.接口3.当前对象

 

3.AOP中的概念解释:

 

1.切面(Aspect): 切点(PointCut)通知(Advice)组成,它既包括横切逻辑的定义,也包括了连接点的定义。

2.切点(Pointcut):一个切点定位多个类中的多个方法。(定义类或者方法的)

3.通知也叫增强(Advice):方位横切逻辑构成,所谓的方位指的是前置通知,后置通知,返回后通知,环绕通知,抛出异常后通知

4.连接点(JoinPoint):由切点方位构成,用来描述在在哪些类的指定方法之前或之后执行

 

方位:

<1>.前置通知(Before advice:某连接点(join point)之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异

常)。

<2>.返回后通知(After returning advice:在某连接点(join point正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回。

<3>.抛出异常后通知After throwing advice):在方法抛出异常退出时执行的通知。

<4>后置通知(After (finally) advice):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。

<5>环绕通知(Around Advice):包围一个连接点(join point)的通知,如方法调用。这是最强大的一种通知类型

环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行

 

66.Java流概述

 文件通常是由一连串的字节或字符构成,组成文件的字节序列称为字节流,组成文件的字符序列称为字符流Java中根据流的方向可以分为输入流和输出流。输入流是将文件或其它输入设备的数据加载到内存的过程;输出流恰恰相反,是将内存中的数据保存到文件或其他输出设备,详见下图:

 

 

 

 

 

文件是由字符或字节构成,那么将文件加载到内存或再将文件输出到文件,需要有输入和输出流的支持,那么在Java语言中又把输入和输出流分为了两个,字节输入和输出流,字符输入和输出流,见下表:

 

 

 

 

 

 

 

 

 

 

InputStream(字节输入流)

InputStream是字节输入流,InputStream是一个抽象类,所有继承了InputStream的类都是字节输入流,主要了解以下子类即可:

 

 

 

 

 

主要方法介绍:

 void

close()
          关闭此输入流并释放与该流关联的所有系统资源。

abstract  int

read()
          从输入流读取下一个数据字节。

 int

read(byte[] b)
          从输入流中读取一定数量的字节并将其存储在缓冲区数组 b 中。

 int

read(byte[] b, int off, int len)
          将输入流中最多 len 个数据字节读入字节数组。

Reader(字符输入流)

所有继承了Reader都是字符输如流

 

 

主要方法介绍

abstract  void

close()
          关闭该流。

 int

read()
          读取单个字符。

 int

read(char[] cbuf)
          将字符读入数组。

abstract  int

read(char[] cbuf, int off, int len)
          将字符读入数组的某一部分。

 

 

OutputStream(字节输出流)

所有继承了OutputStream都是字节输出流

 

主要方法介绍

void

close()
          关闭此输出流并释放与此流有关的所有系统资源。

 void

flush()
          刷新此输出流并强制写出所有缓冲的输出字节。

 void

write(byte[] b)
          b.length 个字节从指定的字节数组写入此输出流。

 void

write(byte[] b, int off, int len)
          将指定字节数组中从偏移量 off 开始的 len 个字节写入此输出流。

abstract  void

write(int b)
          将指定的字节写入此输出流。

示例代码:

 

Writer(字符输出流)

所有继承了Writer都是字符输出流

 

 

主要方法介绍

Writer

append(char c)
          将指定字符追加到此 writer

abstract  void

close()
          关闭此流,但要先刷新它。

abstract  void

flush()
          刷新此流。

 void

write(char[] cbuf)
          写入字符数组。

abstract  void

write(char[] cbuf, int off, int len)
          写入字符数组的某一部分。

 void

write(int c)
          写入单个字符。

 void

write(String str)
          写入字符串。

 void

write(String str, int off, int len)
          写入字符串的某一部分。

缓冲流

缓冲流主要是为了提高效率而存在的,减少物理读取次数,缓冲流主要有:BufferedInputStreamBufferedOutputStreamBufferedReaderBufferedWriter,并且BufferedReader提供了实用方法readLine(),可以直接读取一行,BuffereWriter提供了newLine()可以写换行符。

BufferedInputStream(字节输入缓冲流)

BufferedOutputStream(字节输出缓冲流)

BufferedReader(字符输入缓冲流)

BufferedWriter(字符输出缓冲流)

 

 

67.从数组中获取到最大的数据?

方式有很多

(递归)

 

通过先取出数组中的第一个值 然后用for依次循环是数组中的值是否大于第一个值如果大于第一个值 取出在用for循环 循环以后的值  按照这种方式找到数组中最大的值

 

 

68.工作流2.0

工作流2.0的定义是:实现工作过程管理的自动化、智能化和整合化。工作流2.0最主要的特征就是可以灵便的实现数据整合和数据统计,消除信息孤岛,既能实现OA办公系统内部工作流之间的数据整合,如借款与报销、预算与决算等,又能实现OA办公系统工作流与其他业务系统之间的数据整合,如HRERPCRM等。工作流2.0能彻底的弥补工作流1.0的不足,它不但实现OA办公系统内部的数据整合,也实现OA办公系统和第三方应用系统之间的数据整合。

如果给工作流1.0打上标签的话,那就是无纸化、重复工作、流程孤岛、系统孤岛、数据孤岛;工作流2.0对应的便是智能化、效率质量提升、外部数据整合、消除信息孤岛、内部数据整合。毫无疑问,工作流2.0更加智能,更加整合,能够实现数据的同步交换和共享的特征更受用户欢迎,能有效帮助企业简化多余流程,是未来工作流技术发展的方向。

69.

  JVM -- java virtual machine
      JVM就是我们常说的java虚拟机,它是整个java实现跨平台的 最核心的部分,所有的java程序会首先被编译为.class的类文件,这种类文件可 以在虚拟机上执行,也就是说class并不直接与机器的操作系统相对应,而是经过虚拟机间接与操作系统交互,由虚拟机将程序解 释给本地系统执行。
       JVM Java 平台的基础,和实际的机器一样,它也有自己的指令集,并且在运行 时操作不同的内存区域。 JVM 通过抽象操作系统 CPU 结构,提供了一种与平台无关的代码执行方法,即与特殊的实现方 法、主机硬件、主机操作系统无关。但是在一些小的方面, JVM 的实现也是互不相同的,比如垃圾回收 算法,线程调度算法(可能不同 OS 有不同的实现)。 
        JVM 的主要工作是解释自己的指令集(即字节码)到 CPU 的指令集或 OS 的系统调用,保护用户免被恶意程序骚扰。 JVM 对上层的 Java 源文件是不关心的,它关注的只是由源文件生成的类文件( class file )。类文件的 组成包括 JVM 指令集,符号表以及一些补助信息。

    JRE -- java runtime environment
      JRE是指java运行环境。光有JVM还不能成class的 执行,因为在解释class的时候JVM需要调用解释所需要的类库lib。 在JDK的安装目 录里你可以找到jre目录,里面有两个文件夹binlib,在 这里可以认为bin里的就是jvmlib中则是jvm工 作所需要的类库,而jvmlib和起来就称为jre。所以,在你写完java程序编译成.class之后,你可以把这个.class文件 jre一起打包发给朋友,这样你的朋友就 可以运行你写程序了。(jre里有运行.classjava.exe
       JRE Sun 公司发布的一个更大的系统,它里面就有一个 JVM JRE 就与具体的 CPU 结构和操作系统有关,我们从 Sun 下载 JRE 的时候就看到了不同的各种版本。同 JVM 一起组成 JRE 的还有一些 API (如 awt swing 等)。 JRE 是运行 Java 程序必不可少的。
        JRE Java Runtime Environment ),是运行 Java 程序必不可少的(除非用其他一些编译环境编译成.exe可执行文件……),JRE的 地位就象一台PC机一样,我们写好的Win32应用程序需要操作系统帮 我们运行,同样的,我们编写的Java程序也必须要JRE才能运行。
JRE里面有一个 JVM JRE 与具体的 CPU 结构和操作系统有关,我们从 Sun 下载 JRE 的时候就看到了不同的各种版本,,同 JVM 一起组成 JRE 的还有 一些 API (如 awt swing 等), JRE 是 运行 Java 程序必不可少的.

       JDK -- java development kit
      JDKjava开发工具包,基本上每个学java的人都会先在机器 上装一个JDK,那他都包含哪几部分呢?让我们看一下JDK的安装目录。在目录下面有 六个文件夹、一个src类库源码压缩包、和其他几个声明文件。其中,真正在运行java时起作用的 是以下四个文件夹:binincludelibjre。现在我们可以看出这样一个关系,JDK包含JRE,而JRE包 含JVM
      bin:最主要的是编译器(javac.exe)
      include:javaJVM交互用的头文件
      lib:类库
      jre:java运行环境
(注意:这里的binlib文件夹和jre里的binlib是 不同的)总的来说JDK是用于java程序的开发,jre则 是只能运行class而没有编译的功能。
      eclipseidea等 其他IDE有自己的编译器而不是用JDK bin目录中自带的,所以在安装时你会发现他们只要求你 选中jre路径就ok了。

     三者联系
     Java 喊出的带有标志性的口号“ Write Once Run Anywhere (一次编写,到处运行),正是建立在 JRE 的基础之上。何以实现?就是在 Java 应用程序和操作系统之间增加了一虚拟层—— JRE
      程序源代码不是直 接编译、链接成机器代码,而是先转化到字节码( bytecode ) 这种特殊的中间形式,字节码再转换成机器码或系统调用。前者是传统的编译方法,生成的机器代码就不可避免地跟特殊的操作系统和特殊的机器结构相关。
 Java 程序的字节码文件可以放到任意装有 JRE 的计算机运行,再由不同 JRE 的将它们转化成相应的机器代码,这就实现了 Java 程序的可移植性。这样程序员也不用去 关心程序运行的具体环境,而可以专心编写软件。这种分层抽象、隐藏细节的思想在计算机科学中处处可见,比如机器组织结构的设计、网络协议的实现等。 Pascal 语言的发明者 Niklaus Wirth ,就富有预见性地指出应该有这样一种可移植的语言,其生成的中间代码可以在一台假想的机器( a hypothetical machine )上运行。
 Java 虚拟机( Java virtual machine JVM )就是这样的一台机器,它模拟实际处理器的结构,解释字节码。 怎么一会说是 JRE ,一会儿又成了 JVM ,两者是否同物不同名? 回答是否定的。
       JRE的地位就象一台PC机一样,我们写好的Win32应用程序需要操作系统帮 我们运行,同样的,我们编写的Java程序也必须要JRE才能运行。
要运行Applet,在客户端必须安装有 JRE,即运行时,容易一点理解,就象所谓的插件,要开发JAVA应用程序Web应用,就必须在服务器端安装相应的 JVM+JDK (开发应用 Java web应用 时,客户端不需要安装任何的JVM
      如果你使用JAVA开发应用,就需要安装 JRE+JDK,就是 J2SE.   
      如果在客户端运行Applet,客户端浏览器必须嵌有JAVA JVM,如果没有,就需要安装,即: 在客户端创建JRE(运行时,包含JVM),而客户端是不需要做开发的,所以,JDK就没有必要安装 了。
      不同版本的Applet在不同的JVM下可能无法正常运行,Microsoft JVM只是Sun JVM低版本,微软在windows xp/2003中干脆将JVM去掉了.

 

 

 

 

StringBuilderStringBuffer

StringBuilderStringBuffer都是可变字符串,前者线程不安全,后者线程安全。

StringBuilderStringBuffer的大部分方法均调用父类AbstractStringBuilder的实现。其扩容机制首先是把容量变为原来容量的2倍加2。最大容量是Integer.MAX_VALUE,也就是0x7fffffffRr54

StringBuilderStringBuffer的默认容量都是16,最好预先估计好字符串的大小避免扩容带来的时间消耗。

因为string是不可变的,所以绝对安全。StringBuilder实际上自身维护一个char[]数组,append是没有synchronizedStringBufferappend等很多操作都是带有synchronized的,所以同样线程安全。

所以单线程字符串拼接一般采用StringBuilder,效率高。多线程环境则采用Stringbuffer,虽然安全,但是相对效率会低些。

StringBuffer 类被final 修饰所以不能继承没有子类

2StringBuffer 对象是可变对象,因为父类的 value [] char 没有被final修饰所以可以进行引用的改变,而且还提供了方法可以修改被引用对象的内容即修改了数组内容。

3、在使用StringBuffer对象的时候尽量指定大小这样会减少扩容的次数,也就是会减少创建字符数组对象的次数和数据复制的次数,当然效率也会提升。存储过程

1.存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般 SQL 语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度。
  2.当对数据库进行复杂操作时(如对多个表进行 Update,Insert,Query,Delete 时),可将此复杂操作用存储过程封装起来与数据库提供的事务处理结合一起使用。这些操作,如果用程序来完成,就变成了一条条的 SQL 语句,可能要多次连接数据库。而换成存储,只需要连接一次数据库就可以了。
  3.存储过程可以重复使用,可减少数据库开发人员的工作量
  4.安全性高,可设定只有某此用户才具有对指定存储过程的使用
拦截器

拦截器:需要门写一个普通类,继承interceptorAdapter,里面定义一个Adapter方法,我们那会儿怎么实现的呢,就是说当用户登陆成功以后,我都会把它登陆后的信息放到session里面,然后我们取的时候可以直接用看session里面有没有信息,如果有证明用户已经登陆了,就让他继续执行,如果没有信息springMVC里面的response.send redrecte这个方法让它重定向到登陆页面,还需在配置文件里面配置相应的标签,标签里面有两个属性:1path(就是拦截器需要拦截的路径),然后就是引入咱们的定义的拦截器类,这也就简单实现e4咱们拦截器这样一个功能。

 

 

 

mybatis

mybatis 是持久层它是ORM的一个实现,它是半自动化的框架,相比hibernate它的执行效率更高,它可以直接通过写sql这种方式来操作数据库,并且对sql的优化也比较方便,hibernate呢它是对jdbc的高度封装,所以对sql优化方面比较欠缺,在使用的时候呢,在它的配置文件里面的namespacse与咱们的接口进行匹配,像里面的resultMap(返回值集合)resultType(返回对象) parameterType(参数类型对象)parameterMap(参数集合)

远程接口:

服务端:

1.提供json视图/xml视图

2.提供jsonp方式的数据

3.webservice[服务端]

客户端:

1.ajaxjsonp

2.httpclient

3.webservice[客户端]

webservice用于传统的企业[非互联网企业]CXF

SOA[面向服务编程][思想/理念]

webservice[实现方式]

xfire[技术框架]

cxf

axis2【很多公司】【掌握】

 

解决了  信息孤岛   的问题

 

跨语言,跨平台。

 

webService的三要素

1.wsdl(webservie描述语言):描述发布接口的信息

2.soap(简单对象访问协议)(webservice使用的协议):http+xml

3.uddi(查询和管理webservice)

 

 

cxf:

服务端的配置:

1.web.xml中通过cxfServlet这个核心类对指定的url进行拦截

2.通过在接口上加入@webservice的注解

3.通过配置spring-cxf-server.xml这个配置文件进行接口的发布

4.在地址栏输入http//ip地址:端口号/项目名/web.xml中配置的servleturl-pattern/spring-cxf-

 

server.xml中发布的接口的address?wsdl。【验证】

 

客户端的配置:【多种实现方式】【wsdl2java来生成客户端】【导入jar包】

1.配置环境变量 path=D:javaapache-cxf-2.7.18in

2.wsdl2java -p 包名 -d 目标路径 服务器生成的接口路径

3.通过spring-cxf-client.xml来配置客户端

4.验证客户端代码以及服务端【单元测试】

简介

 

之前jsp-->controller-->service-->dao

 

webservice改变:

服务端:service-->dao

客户端:jsp-->controller-->远程service

 

httpclient/json视图 改变:

服务端:controller-->service-->dao

客户端:jsp-->controller-->service-->通过httpclient调用远程的json视图

 

ajax jsonp 改变:

服务端:controller-->service-->dao

客户端:jsp-->ajax jsonp


























































以上是关于各种面试题4的主要内容,如果未能解决你的问题,请参考以下文章

面试题: 各种 !=!=未看

各种面试题

各种面试题2

各种面试题3

Python 实习遇见的各种面试题

单链表含环的各种面试题