jsp的静态包含和动态包含有生命区别
Ø 静态包含发生在:JSP---->java文件阶段。动态包含发生在:执行class文件阶段。动态加入。
Ø 静态包含:只生成一个java文件,动态包含:生成多个class文件。
Ø 从四个方面来区分:
Ø 概念:
Ø servlet是一种运行在服务器端的Java应用程序,独立于平台和协议,可以动态的生成web页面,它工作于客户端请求和服务器的中间层
Ø filter是一个可以复用的代码片段,可以用来转换请求,响应以及头信息,filter不能产生请求和响应,他只能在请求到达servlet之前对请求进行修改,或者在请求返回客户端之前对响应进行处理。
Ø 生命周期:
Ø servlet是在系统启动或者请求到达servlet时,通过init()方法进行初始化,一旦被装入了web服务器,一般不会从Web服务器删除,直到服务器关闭才会调用 destroy()方法进行销毁。每次请求,Request都会被初始化,响应请求后,请求被销毁。但是servlet不会随着请求的销毁而销毁
Ø 如果某个Servlet配置了 1 ,该Servlet也是在Tomcat(Servlet容器)启动时初始化。
Ø 如果Servlet没有配置1 ,该Servlet不会在Tomcat启动时初始化,而是在请求到来时初始化。
Ø filter是在系统启动的时候通过init()初始化的,每次请求都只会调用dofiter方法进行处理,服务器停止的时候调用destroy()进行销毁
Ø 注意:服务器关闭时,servlet和filter依次销毁
Ø 职责:
Ø servlet可以动态创建基于客户请求的页面;可以读取客户端发来的隐藏数据和显示数据;可以和其他的服务器资源进行通讯;通过状态代码和响应头向客户端返回数据。
Ø filter主要是对请求到达servlet之前对请求和请求头信息进行前处理,和对数据返回客户端之前进行后处理
Ø 区别:
Ø servlet的流程比较短,url来了之后就对其进行处理,处理完就返回数据或者转向另一个页面
Ø filter的流程比较长,在一个filter处理之后还可以转向另一个filter进行处理,然后再交给servlet,但是servlet处理之后不能向下传递了。
Ø filter可用来进行字符编码的过滤,检测用户是否登陆的过滤,禁止页面缓存等
29.Java 中会存在内存泄漏吗,请简单描述?
Ø 会。java导致内存泄漏的原因很明确:长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄漏,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不能被回收,这就是java中内存泄漏的发生场景。
Ø 1.集合类,集合类仅仅有添加元素的方法,而没有相应的删除机制,导致内存被占用。这一点其实也不明确,这个集合类如果仅仅是局部变量,根本不会造成内存泄漏,在方法栈退出后就没有引用了会被jvm正常回收。而如果这个集合类是全局性的变量(比如类中的静态属性,全局性的map等即有静态引用或final一直指向它),那么没有相应的删除机制,很可能导致集合所占用的内存只增不减,因此提供这样的删除机制或者定期清除策略非常必要。
Ø 2.单例模式。不正确使用单例模式是引起内存泄漏的一个常见问题,单例对象在被初始化后将在JVM的整个生命周期中存在(以静态变量的方式),如果单例对象持有外部对象的引用,那么这个外部对象将不能被jvm正常回收,导致内存泄漏
30.servlet与jsp的区别?
Ø 首先说明JSP出现的背景:Servlet体系是基于B/S架构开发web应用程序,使用Servlet类将HTTP请求和响应封装在标准JAVA类中来实现各种web应用方案的。当大量的B/S架构程序开发出来以后出现了很多问题:首先servlet类有大量冗余代码,其次是开发Servlet的没法做到有精美的页面效果。所以sun提出将服务端代码添加在已经设计好的静态页面上,经过JSP容器对JSP文件进行自动解析并转换成Servlet类来交给web服务器运行。
Ø
Ø 所以JSP在本质上就是Servlet,但是两者的创建方式不一样。Servlet都是由JAVA程序代码构成,用于流程控制和事务处理,通过Servlet来生成动态网页很不直观。而JSP由HTML代码和JSP标签构成,可以方便地编写动态网页.
Ø
Ø 另外总结一下,JSP与Servlet主要有两方面的不同:编译:JSP修改后可以立即看到结果,不需要编译;而Servelt缺需要编译。转换:JSP是动态网页开发技术,是运行在服务器端的脚本语言,而Servlet是web服务器端编程技术。所以JSP运行时就是转换为Servlet,也就是java程序来执行。
31.说说java的锁机制
Ø 一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限,在Java里边就是拿到某个同步对象的锁(一个对象只有一把锁); 如果这个时候同步对象的锁被其他线程拿走了,他(这个线程)就只能等了(线程阻塞在锁池等待队列中)。 取到锁后,他就开始执行同步代码(被synchronized修饰的代码);线程执行完同步代码后马上就把锁还给同步对象,其他在锁池中等待的某个线程就可以拿到锁执行同步代码了。这样就保证了同步代码在统一时刻只有一个线程在执行。
32.什么是java的序列化,如何实现java的序列化
Ø 序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题;
Ø 序列化的实现:将需要被序列化的类实现 Serializable 接口,该接口没有需实现的方法,implements Serializable 只是为了标注该对象是可被序列化的,然后使用一个输出流(如 FileOutputStream)来构造一个 ObjectOutputStream(对象流)对象,接着,使用 ObjectOutputStream 对象的 writeObject(Object obj)方法就可以将参数为 obj 的对象写出(即保存其状态),要恢复的话则用输入流。
33.mysql多表查询的方式有哪些。
Ø 交叉连接
Ø 内连接
Ø 外连接
Ø 子查询 :分为带in exists any all 的子查询;
34.javaweb各种乱码的解决方案
Ø 常识
Ø UTF-8国际编码,GBK中文编码。GBK包含GB2312,即如果通过GB2312编码后可以同过GBK解码,反之不能成立。
Ø web tomcat:默认是ISO8859-1,不支持中文的
Ø java.nio.charset.Charset.defaultCharset() 获得平台默认字符编码;
Ø getBytes() 是通过平台默认字符集进行编码;
Ø 浏览器调用jsp,html等页面中文显示乱码(假设文件是以utf-8保存的)
Ø 或
Ø <%@ pageEncoding=“utf-8”%>
Ø
Ø 通过浏览器调用servlet,页面显示乱码。
Ø 次要方法:response.setCharacterEncoding(“UTF-8”);目的是用于response.getWriter()输出的字符流的乱码问题。
Ø 主要方法:response。setContentType(”text/html;charset=UTF_8”);目的是为了控制浏览器的行为,即控制浏览器用UTF-8进行编码;
Ø GB2312的解决流程同上
Ø request乱码问题
Ø POST请求
Ø 在获取参数之前用Request.setCharacterEncoding(“GB2312”);即可解决。
Ø GET请求有两种解决方式:
Ø 第一种修改Tomcat的xml文中的协议对应的编码方式(不建议这样做)
Ø 第二种以ISO-8859-1解码,再以UTF-8编码:
Ø String usernameString = new String(username.getBytes(“ISO-8859-1”),“UTF-8”);
Ø 调用数据库出现乱码
Ø 安装数据的时候选择UTF-8
35.sleep() 和 wait() 有什么区别?
Ø sleep() 方法是线程类(Thread)的静态方法,让调用线程进入睡眠状态,让出执行机会给其他线程,等到休眠时间结束后,线程进入就绪状态和其他线程一起竞争cpu的执行时间。
Ø 因为sleep() 是static静态的方法,他不能改变对象的机锁,当一个synchronized块中调用了sleep() 方法,线程虽然进入休眠,但是对象的机锁没有被释放,其他线程依然无法访问这个对象。
Ø wait()是Object类的方法,当一个线程执行到wait方法时,它就进入到一个和该对象相关的等待池,同时释放对象的机锁,使得其他线程能够访问,可以通过notify,notifyAll方法来唤醒等待的线程
36.Array List和Vector的区别
Ø Vector是线程安全的,也就是说它的方法之间是线程同步的,而ArrayList线程不安全的它的方法之间是不同不的,同比下,ArrayList效率要比Vector高一些。
Ø 从数据增长上来说,ArrayList增长因子为0.5,Vector增长因子为1.0,而且Vector可以设置增长因子的大小。
37.hashSet和TreeSet的区别
Ø 都是单列集合,元素不可重复
Ø HashSet底层用的是HashMap哈希表结构存储,而TreeSet底层用的是TreeMap树结构存储
Ø HashSet是通过复写hashCode()方法和equals()方法来保证的,而HashSet通过Compareable接口的compareTo()方法来保证的唯一性的。
Ø HashSet无序,TreeSet有序
38.什么是存储过程?它有什么优点?
Ø 存储过程是一组予编译的SQL语句
Ø 它的优点:1.允许模块化程序设计,就是说只需要创建一次过程,以后在程序中就可以调用该过程任意次。
Ø 2.允许更快执行,如果某操作需要执行大量SQL语句或重复执行,存储过程比SQL语句执行的要快。
Ø 3.减少网络流量,例如一个需要数百行的SQL代码的操作有一条执行语句完成,不需要在网络中发送数百行代码。
Ø 4.更好的安全机制,对于没有权限执行存储过程的用户,也可授权他们执行存储过程。
39.对常见设计模式的理解
Ø 设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。
Ø 设计模式的六大原则
Ø 1、开闭原则
Ø 开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类。
Ø 2、里氏代换原则
Ø 里氏代换原则面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
Ø 3、依赖倒转原则
Ø 这个是开闭原则的基础,具体内容:真对接口编程,依赖于抽象而不依赖于具体。
Ø 4、接口隔离原则
Ø 这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。
Ø 5、迪米特法则(最少知道原则)
Ø 为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。
Ø 6、合成复用原则
Ø 原则是尽量使用合成/聚合的方式,而不是使用继承。
40.java中io流有哪些,各有什么特点和功能
Ø 流一共有三种分类:
Ø 方向分:输入流和输出流;
Ø 单位分:字节流和字符流;
Ø 字节流:
Ø InputStream/OutputStream 字节流的父接口
Ø FileInputStream/FileOutputStream 文件字节流 ((可以向下转换))
Ø DataInputStream/DataOutputStream 读写8种基本类型和以UTF-8读写String
Ø BufferedInputStream/BufferedOutputStream 带缓冲的输入/出流
Ø PrintStream 融合Data和Buffered, System.out所属的类
Ø Piped 管道 用于线程间交换数据
Ø RandomAccessFile 随机访问文件
Ø 字符流:处理字符编码问题
Ø Reader/Writer 字符流的父接口
Ø FileReader/FileWriter 文件字符流,和FileInputStream/FileOutputStream 文件流,((可以向下转换)) 与上面的(1)是相等,
Ø 只不过一个是字节流,下面是字符流,所以两个无法相传
Ø InputStreamReader/OutputStreamWriter 桥转换 将字节流转成字符流 在桥转换的过程中,可以制定编解码方式
Ø BufferedReader/PrintWriter 有缓冲
Ø 字符流转换为字节流时,指定编解码方式是在桥转换时指定的。
Ø 功能分:节点流和过滤流;
Ø 节点流:用于传输数据。
Ø 过滤流:帮助节点流更好的传输数据。
Ø piped(管道节点流):用于两个线程间传输数据。一个线程的输出,是另一个线程的输入。
Ø 对象序列化:
Ø 把对象放在流上传输ObjectInputStream/ObjectOutputStream
Ø 只有实现了Serializable接口的对象才能序列化
Ø 用transient修饰的属性,为临时属性,不参与序列化,只能修饰对象的属性。
41.hashmap底层实现原理
Ø HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
Ø HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。
Ø 当我们往HashMap中put元素的时候,先根据key的hashCode重新计算hash值,根据hash值得到这个元素在数组中的位置(即下标), 如果数组该位置上已经存放有其他元素了,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。如果数组该位置上没有元素,就直接将该元素放到此数组中的该位置上。
Ø HashMap 在底层将 key-value 当成一个整体进行处理,这个整体就是一个 Entry 对象。HashMap 底层采用一个 Entry[] 数组来保存所有的 key-value 对,当需要存储一个 Entry 对象时,会根据hash算法来决定其在数组中的存储位置,在根据equals方法决定其在该数组位置上的链表中的存储位置;当需要取出一个Entry时,
Ø 也会根据hash算法找到其在数组中的存储位置,再根据equals方法从该位置上的链表中取出该Entry。
Ø HashMap的初始容量为16,增长因子为0.75.
42.说说你对java中nio的理解
Ø Java NIO(New IO)是一个可以替代标准Java IO API的IO API(从Java1.4开始),Java NIO提供了与标准IO不同的IO工作方式。
Ø 所以Java NIO是一种新式的IO标准,与之间的普通IO的工作方式不同。标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入通道也类似。
Ø Java NIO 由以下几个核心部分组成:
Ø Buffer
Ø Channel
Ø Selector
Ø 传统的IO操作面向数据流,意味着每次从流中读一个或多个字节,直至完成,数据没有被缓存在任何地方。NIO操作面向缓冲区,数据从Channel读取到Buffer缓冲区,随后在Buffer中处理数据。
Ø Buffer的使用
Ø 利用Buffer读写数据,通常遵循四个步骤:
Ø 1.把数据写入buffer;
Ø 2.调用flip;
Ø 3.从Buffer中读取数据;
Ø 4.调用buffer.clear()
Ø 当写入数据到buffer中时,buffer会记录已经写入的数据大小。当需要读数据时,通过flip()方法把buffer从写模式调整为读模式;在读模式下,可以读取所有已经写入的数据。
Ø 当读取完数据后,需要清空buffer,以满足后续写入操作。清空buffer有两种方式:调用clear(),一旦读完Buffer中的数据,需要让Buffer准备好再次被写入,clear会恢复状态值,但不会擦除数据。
43.java中有哪几种线程池
Ø 1、newFixedThreadPool创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。
Ø 2、newCachedThreadPool创建一个可缓存的线程池。这种类型的线程池特点是:
Ø 1).工作线程的创建数量几乎没有限制(其实也有限制的,数目为Interger. MAX_VALUE), 这样可灵活的往线程池中添加线程。
Ø 2).如果长时间没有往线程池中提交任务,即如果工作线程空闲了指定的时间(默认为1分钟),则该工作线程将自动终止。终止后,如果你又提交了新的任务,则线程池重新创建一个工作线程。
Ø 3、newSingleThreadExecutor创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,如果这个线程异常结束,会有另一个取代它,保证顺序执行(我觉得这点是它的特色)。单工作线程最大的特点是可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的 。
Ø 4、newScheduleThreadPool创建一个定长的线程池,而且支持定时的以及周期性的任务执行,类似于Timer。(这种线程池原理暂还没完全了解透彻)
Ø 总结: 一.FixedThreadPool是一个典型且优秀的线程池,它具有线程池提高程序效率和节省创建线程时所耗的开销的优点。但是,在线程池空闲时,即线程池中没有可运行任务时,它不会释放工作线程,还会占用一定的系统资源。
Ø 二.CachedThreadPool的特点就是在线程池空闲时,即线程池中没有可运行任务时,它会释放工作线程,从而释放工作线程所占用的资源。但是,但当出现新任务时,又要创建一新的工作线程,又要一定的系统开销。并且,在使用CachedThreadPool时,一定要注意控制任务的数量,否则,由于大量线程同时运行,很有会造成系统瘫痪。
44.线程和进程的区别
Ø 进程可以认为是程序执行时的一个实例。进程是系统进行资源分配的独立实体, 且每个进程拥有独立的地址空间。一个进程无法直接访问另一个进程的变量和数据结构, 如果希望让一个进程访问另一个进程的资源,需要使用进程间通信,比如:管道,文件, 套接字等。
Ø 一个进程可以拥有多个线程,每个线程使用其所属进程的栈空间。 线程与进程的一个主要区别是,同一进程内的多个线程会共享部分状态, 多个线程可以读写同一块内存(一个进程无法直接访问另一进程的内存)。同时, 每个线程还拥有自己的寄存器和栈,其它线程可以读写这些栈内存。
Ø 线程是进程的一个特定执行路径。当一个线程修改了进程中的资源, 它的兄弟线程可以立即看到这种变化。
Ø 以下是分点小结:
Ø 进程是系统进行资源分配的基本单位,有独立的内存地址空间; 线程是CPU调度的基本单位,没有单独地址空间,有独立的栈,局部变量,寄存器, 程序计数器等。
Ø 创建进程的开销大,包括创建虚拟地址空间等需要大量系统资源; 创建线程开销小,基本上只有一个内核对象和一个堆栈。
Ø 一个进程无法直接访问另一个进程的资源;同一进程内的多个线程共享进程的资源。
Ø 进程切换开销大,线程切换开销小;进程间通信开销大,线程间通信开销小。
Ø 线程属于进程,不能独立执行。每个进程至少要有一个线程,成为主线程
45.说说你对much开发模式的理解,有何优缺点
Ø 应该是题目打印错误,应该是MVC模式
Ø MVC是Model—View—Controler的简称。即模型—视图—控制器。MVC是一种设计模式,它强制性的把应用程序的输入、处理和输出分开。
Ø 视图: 视图是用户看到并与之交互的界面。视图向用户显示相关的数据,并接受用户的输入。视图不进行任何业务逻辑处理。
Ø 模型: 模型表示业务数据和业务处理。相当于JavaBean。一个模型能为多个视图提供数据。这提高了应用程序的重用性
Ø 控制器: 当用户单击Web页面中的提交按钮时,控制器接受请求并调用相应的模型去处理请求。
Ø MVC的处理过程:首先控制器接受用户的请求,调用相应的模型来进行业务处理,并返回数据给控制器。控制器调用相应的视图来显示处理的结果。并通过视图呈现给用户。
Ø 如在项目中要对应MVC的话:View 对应项目中Jsp,Controler对应Action,Model 对应service+dao层的业务逻辑和持久层的操作。
Ø 优点:
Ø 1:耦合性低
Ø 视图层和业务层分离,这样就允许更改视图层代码而不用重新编译模型和控制器代码,同样,一个应用的业务流程或者业务规则的改变只需要改动MVC的模型层即可。因为模型与控制器和视图相分离,所以很容易改变应用程序的数据层和业务规则。
Ø 2:重用性高
Ø 随着技术的不断进步,需要用越来越多的方式来访问应用程序。MVC模式允许使用各种不同样式的视图来访问同一个服务器端的代码,因为多个视图能共享一个模型,它包括任何WEB(HTTP)浏览器或者无线浏览器(wap),比如,用户可以通过电脑也可通过手机来订购某样产品,虽然订购的方式不一样,但处理订购产品的方式是一样的。由于模型返回的数据没有进行格式化,所以同样的构件能被不同的界面使用。
Ø MVC使开发和维护用户接口的技术含量降低。
Ø 3:部署快
Ø 使用MVC模式使开发时间得到相当大的缩减,它使程序员(Java开发人员)集中精力于业务逻辑,界面程序员(HTML和JSP开发人员)集中精力于表现形式上。
Ø 4:可维护性高
Ø 分离视图层和业务逻辑层也使得WEB应用更易于维护和修改。
Ø 5:有利软件工程化管理
Ø 由于不同的层各司其职,每一层不同的应用具有某些相同的特征,有利于通过工程化、工具化管理程序代码。控制器也提供了一个好处,就是可以使用控制器来联接不同的模型和视图去完成用户的需求,这样控制器可以为构造应用程序提供强有力的手段。给定一些可重用的模型和视图,控制器可以根据用户的需求选择模型进行处理,然后选择视图将处理结果显示给用户。
Ø 缺点:
Ø 1:没有明确的定义
Ø 完全理解MVC并不是很容易。使用MVC需要精心的计划,由于它的内部原理比较复杂,所以需要花费一些时间去思考。同时由于模型和视图要严格的分离,这样也给调试应用程序带来了一定的困难。每个构件在使用之前都需要经过彻底的测试。
Ø 2:不适合小型,中等规模的应用程序
Ø 花费大量时间将MVC应用到规模并不是很大的应用程序通常会得不偿失。
Ø 3:增加系统结构和实现的复杂性
Ø 对于简单的界面,严格遵循MVC,使模型、视图与控制器分离,会增加结构的复杂性,并可能产生过多的更新操作,降低运行效率。
Ø 4:视图与控制器间的过于紧密的连接
Ø 视图与控制器是相互分离,但却是联系紧密的部件,视图没有控制器的存在,其应用是很有限的,反之亦然,这样就妨碍了他们的独立重用。
Ø 5:视图对模型数据的低效率访问
Ø 依据模型操作接口的不同,视图可能需要多次调用才能获得足够的显示数据。对未变化数据的不必要的频繁访问,也将损害操作性能。
Ø 6:一般高级的界面工具或构造器不支持模式
Ø 改造这些工具以适应MVC需要和建立分离的部件的代价是很高的,会造成MVC使用的困难。
46.说说你对java虚拟机的了解
Ø JVM是java的核心和基础,在java编译器和os平台之间的虚拟处理器。它是一种利用软件方法实现的抽象的计算机基于下层的操作系统和硬件平台,可以在上面执行java的字节码程序。
Ø java编译器只要面向JVM,生成JVM能理解的代码或字节码文件。Java源文件经编译成字节码程序,通过JVM将每一条指令翻译成不同平台机器码,通过特定平台运行。
Ø JVM执行程序的过程 :
Ø I.加载。class文件
Ø II.管理并分配内存
Ø III.执行垃圾收集
Ø JRE(java运行时环境)由JVM构造的java程序的运行环境