【Java基础面试题】【03】

【常见面试问题总结目录>>>】


81、JDBC中如何进行事务处理?

答:Connection提供了事务处理的方法,通过调用setAutoCommit(false)可以设置手动提交事务;当事务完成后用commit()显式提交事务;如果在事务处理过程中发生异常则通过rollback()进行事务回滚。除此之外,从JDBC 3.0中还引入了Savepoint(保存点)的概念,允许通过代码设置保存点并让事务回滚到指定的保存点。

82、JDBC能否处理Blob和Clob?

答: Blob是指二进制大对象(Binary Large Object),而Clob是指大字符对象(Character Large Objec),因此其中Blob是为存储大的二进制数据而设计的,而Clob是为存储大的文本数据而设计的。JDBC的PreparedStatement和ResultSet都提供了相应的方法来支持Blob和Clob操作。

83、简述正则表达式及其用途。

答:在编写处理字符串的程序时,经常会有查找符合某些复杂规则的字符串的需要。正则表达式就是用于描述这些规则的工具。换句话说,正则表达式就是记录文本规则的代码。
说明:计算机诞生初期处理的信息几乎都是数值,但是时过境迁,今天我们使用计算机处理的信息更多的时候不是数值而是字符串,正则表达式就是在进行字符串匹配和处理的时候最为强大的工具,绝大多数语言都提供了对正则表达式的支持。

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

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

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

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());
        }
    }
}

85、获得一个类的类对象有哪些方式?
答:

  • 方法1:类型.class,例如:String.class
  • 方法2:对象.getClass(),例如:”hello”.getClass()
  • 方法3:Class.forName(),例如:Class.forName(“java.lang.String”)。

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

答:

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

87、如何通过反射获取和设置对象私有字段的值?

答:可以通过类对象的getDeclaredField()方法字段(Field)对象,然后再通过字段对象的setAccessible(true)将其设置为可以访问,接下来就可以通过get/set方法来获取/设置字段的值了。

89、简述一下面向对象的”六原则一法则”。

答:

  • 单一职责原则:一个类只做它该做的事情。(单一职责原则想表达的就是”高内聚”,写代码最终极的原则只有六个字”高内聚、低耦合”。
  • 开闭原则:软件实体应当对扩展开放,对修改关闭。(在理想的状态下,当我们需要为一个软件系统增加新功能时,只需要从原来的系统派生出一些新类就可以,不需要修改原来的任何一行代码。要做到开闭有两个要点:①抽象是关键,一个系统中如果没有抽象类或接口系统就没有扩展点;②封装可变性,将系统中的各种可变因素封装到一个继承结构中,如果多个可变因素混杂在一起,系统将变得复杂而换乱,如果不清楚如何封装可变性,可以参考《设计模式精解》一书中对桥梁模式的讲解的章节。)
  • 依赖倒转原则:面向接口编程。(该原则说得直白和具体一些就是声明方法的参数类型、方法的返回类型、变量的引用类型时,尽可能使用抽象类型而不用具体类型,因为抽象类型可以被它的任何一个子类型所替代,请参考下面的里氏替换原则。)
  • 里氏替换原则:任何时候都可以用子类型替换掉父类型。(关于里氏替换原则的描述,Barbara Liskov女士的描述比这个要复杂得多,但简单的说就是能用父类型的地方就一定能使用子类型。里氏替换原则可以检查继承关系是否合理,如果一个继承关系违背了里氏替换原则,那么这个继承关系一定是错误的,需要对代码进行重构。例如让猫继承狗,或者狗继承猫,又或者让正方形继承长方形都是错误的继承关系,因为你很容易找到违反里氏替换原则的场景。需要注意的是:子类一定是增加父类的能力而不是减少父类的能力,因为子类比父类的能力更多,把能力多的对象当成能力少的对象来用当然没有任何问题。)
  • 接口隔离原则:接口要小而专,绝不能大而全。(臃肿的接口是对接口的污染,既然接口表示能力,那么一个接口只应该描述一种能力,接口也应该是高度内聚的。例如,琴棋书画就应该分别设计为四个接口,而不应设计成一个接口中的四个方法,因为如果设计成一个接口中的四个方法,那么这个接口很难用,毕竟琴棋书画四样都精通的人还是少数,而如果设计成四个接口,会几项就实现几个接口,这样的话每个接口被复用的可能性是很高的。Java中的接口代表能力、代表约定、代表角色,能否正确的使用接口一定是编程水平高低的重要标识。)
  • 合成聚合复用原则:优先使用聚合或合成关系复用代码。(通过继承来复用代码是面向对象程序设计中被滥用得最多的东西,因为所有的教科书都无一例外的对继承进行了鼓吹从而误导了初学者,类与类之间简单的说有三种关系,Is-A关系、Has-A关系、Use-A关系,分别代表继承、关联和依赖。其中,关联关系根据其关联的强度又可以进一步划分为关联、聚合和合成,但说白了都是Has-A关系,合成聚合复用原则想表达的是优先考虑Has-A关系而不是Is-A关系复用代码,原因嘛可以自己从百度上找到一万个理由,需要说明的是,即使在Java的API中也有不少滥用继承的例子,例如Properties类继承了Hashtable类,Stack类继承了Vector类,这些继承明显就是错误的,更好的做法是在Properties类中放置一个Hashtable类型的成员并且将其键和值都设置为字符串来存储数据,而Stack类的设计也应该是在Stack类中放一个Vector对象来存储数据。记住:任何时候都不要继承工具类,工具是可以拥有并可以使用的,而不是拿来继承的。)
  • 迪米特法则:迪米特法则又叫最少知识原则,一个对象应当对其他对象有尽可能少的了解。(迪米特法则简单的说就是如何做到”低耦合”,门面模式和调停者模式就是对迪米特法则的践行。对于门面模式可以举一个简单的例子,你去一家公司洽谈业务,你不需要了解这个公司内部是如何运作的,你甚至可以对这个公司一无所知,去的时候只需要找到公司入口处的前台美女,告诉她们你要做什么,她们会找到合适的人跟你接洽,前台的美女就是公司这个系统的门面。再复杂的系统都可以为用户提供一个简单的门面,Java Web开发中作为前端控制器的Servlet或Filter不就是一个门面吗,浏览器对服务器的运作方式一无所知,但是通过前端控制器就能够根据你的请求得到相应的服务。调停者模式也可以举一个简单的例子来说明,例如一台计算机,CPU、内存、硬盘、显卡、声卡各种设备需要相互配合才能很好的工作,但是如果这些东西都直接连接到一起,计算机的布线将异常复杂,在这种情况下,主板作为一个调停者的身份出现,它将各个设备连接在一起而不需要每个设备之间直接交换数据,这样就减小了系统的耦合度和复杂度。

90、简述一下你了解的设计模式。

答:所谓设计模式,就是一套被反复使用的代码设计经验的总结(情境中一个问题经过证实的一个解决方案)。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。设计模式使人们可以更加简单方便的复用成功的设计和体系结构。将已证实的技术表述成设计模式也会使新系统开发者更加容易理解其设计思路。
在GoF的《Design Patterns: Elements of Reusable Object-Oriented Software》中给出了三类(创建型[对类的实例化过程的抽象化]、结构型[描述如何将类或对象结合在一起形成更大的结构]、行为型[对在不同的对象之间划分责任和算法的抽象化])共23种设计模式,包括:Abstract Factory(抽象工厂模式),Builder(建造者模式),Factory Method(工厂方法模式),Prototype(原始模型模式),Singleton(单例模式);Facade(门面模式),Adapter(适配器模式),Bridge(桥梁模式),Composite(合成模式),Decorator(装饰模式),Flyweight(享元模式),Proxy(代理模式);Command(命令模式),Interpreter(解释器模式),Visitor(访问者模式),Iterator(迭代子模式),Mediator(调停者模式),Memento(备忘录模式),Observer(观察者模式),State(状态模式),Strategy(策略模式),Template Method(模板方法模式), Chain Of Responsibility(责任链模式)。
面试被问到关于设计模式的知识时,可以拣最常用的作答,例如:

  • 工厂模式:工厂类可以根据条件生成不同的子类实例,这些子类有一个公共的抽象父类并且实现了相同的方法,但是这些方法针对不同的数据进行了不同的操作(多态方法)。当得到子类的实例后,开发人员可以调用基类中的方法而不必考虑到底返回的是哪一个子类的实例。
  • 代理模式:给一个对象提供一个代理对象,并由代理对象控制原对象的引用。实际开发中,按照使用目的的不同,代理可以分为:远程代理、虚拟代理、保护代理、Cache代理、防火墙代理、同步化代理、智能引用代理。
  • 适配器模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起使用的类能够一起工作。
  • 模板方法模式:提供一个抽象类,将部分逻辑以具体方法或构造器的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法(多态实现),从而实现不同的业务逻辑。
    除此之外,还可以讲讲上面提到的门面模式、桥梁模式、单例模式、装潢模式(Collections工具类和I/O系统中都使用装潢模式)等,反正基本原则就是拣自己最熟悉的、用得最多的作答,以免言多必失。

92、什么是UML?

答:UML是统一建模语言(Unified Modeling Language)的缩写,它发表于1997年,综合了当时已经存在的面向对象的建模语言、方法和过程,是一个支持模型化和软件系统开发的图形化语言,为软件开发的所有阶段提供模型化和可视化支持。使用UML可以帮助沟通与交流,辅助应用设计和文档的生成,还能够阐释系统的结构和行为。

93、UML中有哪些常用的图?

答:UML定义了多种图形化的符号来描述软件系统部分或全部的静态结构和动态结构,包括:用例图(use case diagram)、类图(class diagram)、时序图(sequence diagram)、协作图(collaboration diagram)、状态图(statechart diagram)、活动图(activity diagram)、构件图(component diagram)、部署图(deployment diagram)等。在这些图形化符号中,有三种图最为重要,分别是:用例图(用来捕获需求,描述系统的功能,通过该图可以迅速的了解系统的功能模块及其关系)、类图(描述类以及类与类之间的关系,通过该图可以快速了解系统)、时序图(描述执行特定任务时对象之间的交互关系以及执行顺序,通过该图可以了解对象能接收的消息也就是说对象能够向外界提供的服务)。

94、什么是ORM?

答:对象关系映射(Object-Relational Mapping,简称ORM)是一种为了解决程序的面向对象模型与数据库的关系模型互不匹配问题的技术;简单的说,ORM 是通过使用描述对象和数据库之间映射的元数据(可以用XML或者是注解),将Java程序中的对象自动持久化到关系数据库中或者将关系数据库表中的行转换成Java对象,其本质上就是将数据从一种形式转换到另外一种形式。

95、说一下你对约定优于配置(CoC)的理解。

答:约定优于配置(convention over configuration),也称作按约定编程,是一种软件设计范式,旨在减少软件开发人员需做决定的数量,获得简单的好处而又不失灵活性。CoC本质是说,开发人员仅需规定应用中不符约定的部分。例如,如果模型中有个名为Sale的类,那么数据库中对应的表就会默认命名为sales。只有在偏离这一约定时,例如将该表命名为products_sold,才需写有关这个名字的配置。如果您所用工具的约定与你的期待相符,便可省去配置;反之,你可以配置来达到你所期待的方式。遵循约定虽然损失了一定的灵活性,不能随意安排目录结构,不能随意进行函数命名,但是却能减少配置。更重要的是,遵循约定可以帮助开发人员遵守构建标准,包括各种命名的规范,这对团队开发是非常有利的。

96、说出Servlet的生命周期

答:Web容器加载Servlet并将其实例化后,Servlet生命周期开始,容器运行其init()方法进行Servlet的初始化;请求到达时调用Servlet的service方法,service方法会调用与请求对应的doGet或doPost等方法;当服务器关闭,项目被卸载时服务器会将Servlet实例销毁,此时会调用Servlet的destroy方法。
Servlet接口定义了5个方法,其中前三个方法与Servlet生命周期相关:

  • 1.void init(ServletConfig config) throws ServletException
  • 2.void service(ServletRequest req, ServletResponse resp) throws - - ServletException, java.io.IOException
  • 3.void destory()
  • 4.java.lang.String getServletInfo()
  • 5.ServletConfig getServletConfig()

97、转发(forward)和重定向(redirect)的区别?

答:forward是容器中控制权的转向,是服务器请求资源,服务器直接访问目标地址的URL,把那个URL 的响应内容读取过来,然后把这些内容再发给浏览器,浏览器根本不知道服务器发送的内容是从哪儿来的,所以它的地址栏中还是原来的地址。redirect就是服务器端根据逻辑,发送一个状态码(302),告诉浏览器重新去请求那个地址,因此从浏览器的地址栏中可以看到跳转后的链接地址。前者更加高效,在前者可以满足需要时,尽量使用转发(通过RequestDispatcher对象的forward方法,RequestDispatcher对象可以通过ServletRequest对象的getRequestDispatcher方法获得),并且,这样也有助于隐藏实际的链接;在有些情况下,比如,需要跳转到一个其它服务器上的资源,则必须使用重定向(通过HttpServletResponse对象调用其sendRedirect方法)。

98、JSP有哪些内置对象?作用分别是什么?

答:JSP有9个内置对象:
- 1.request:封装客户端的请求,其中包含来自GET或POST请求的参数;
- 2.response:封装服务器对客户端的响应;
- 3.pageContext:通过该对象可以获取其他对象;
- 4.session:封装用户会话的对象;
- 5.application:封装服务器运行环境的对象;
- 6.out:输出服务器响应的输出流对象;
- 7.config:Web应用的配置对象;
- 8.page:JSP页面本身(相当于Java程序中的this);
- 9.exception:封装页面抛出异常的对象。

【补充】如果用Servlet来生成网页中的动态内容无疑是非常繁琐的工作,另一方面,所有的文本和HTML标签都是硬编码,即使做出微小的修改,都需要进行重新编译。JSP解决了Servlet的这些问题,它是Servlet很好的补充,可以专门用作呈现给用户的视图(View),而Servlet作为控制器(Controller)专门负责处理用户请求并转发或重定向到某个页面。基于Java的Web开发很多都同时使用了Servlet和JSP。JSP页面其实是一个Servlet,能够运行Servlet的服务器(Servlet容器)通常也是JSP容器,可以提供JSP页面的运行环境,Tomcat就是一个Servlet/JSP容器。第一次请求一个JSP页面时,Servlet/JSP容器首先将JSP页面转换成一个JSP页面的实现类,这是一个实现了JspPage接口或其子接口HttpJspPage的Java类。JspPage接口是Servlet的子接口,因此每个JSP页面都是一个Servlet。转换成功后,容器会编译Servlet类,之后容器加载和实例化Java字节码,并执行它通常对Servlet所做的生命周期操作。对同一个JSP页面的后续请求,容器会查看这个JSP页面是否被修改过,如果修改过就会重新转换并重新编译并执行。如果没有则执行内存中已经存在的Servlet实例。

99、get和post请求的区别?

答:

  • ①get请求用来从服务器上获得资源,而post是用来向服务器提交数据;
  • ②get将表单中数据按照name=value的形式,添加到action 所指向的URL 后面,并且两者使用“?”连接,而各个变量之间使用“&”连接;post是将表单中的数据放在HTML头部(header),传递到action所指向URL;
  • ③get传输的数据要受到URL长度限制(1024字节);而post可以传输大量的数据,上传文件只能使用post方式;
  • ④使用get时参数会显示在地址栏上,如果这些数据不是敏感数据,那么可以使用get;对于敏感数据还是应用使用post;
  • ⑤get使用MIME类型application/x-www-form-urlencoded的URL 编码(URL encoding,也叫百分号编码)文本的格式传递参数,保证被传送的参数由遵循规范的文本组成,例如一个空格的编码是”%20”。

100、JSP 和Servlet 有有什么关系?

答: Servlet是一个特殊的Java程序,它运行于服务器的JVM中,能够依靠服务器的支持向浏览器提供显示内容。JSP本质上是Servlet的一种简易形式, JSP会被服务器处理成一个类似于Servlet的Java程序,可以简化页面内容的生成。Servlet和JSP最主要的不同点在于,Servlet 的应用逻辑是在Java 文件中,并且完全从表示层中的HTML分离开来。而JSP的情况是Java和HTML可以组合成一个扩展名为.jsp 的文件(有人说,Servlet就是在Java中写HTML,而JSP就是在HTML中写Java代码,当然,这个说法还是很片面的)。JSP侧重于视图,Servlet更侧重于控制逻辑,在MVC架构模式中,JSP适合充当视图(view)而Servlet适合充当控制器(controller)。

101、JSP中的四种作用域?

答:page、request、session和application,具体如下:

  • ①page 代表与一个页面相关的对象和属性。
  • ②request 代表与Web客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个Web 组件;需要在页面显示的临时数据可以置于此作用域
  • ③session代表与某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户自己的session中
  • ④application代表与整个Web应用程序相关的对象和属性,它实质上是跨越整个Web应用程序,包括多个页面、请求和会话的一个全局作用域。

102、实现会话跟踪的技术有哪些?

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

  • ①URL 重写:在URL中添加用户会话的信息作为请求的参数,或者将唯一的会话ID添加到URL结尾以标识一个会话。
  • ②设置表单隐藏域:将和会话跟踪相关的字段添加到隐式表单域中,这些信息不会在浏览器中显示但是提交表单时会提交给服务器。
    这两种方式很难处理跨越多个页面的信息传递,因为如果每次都要修改URL或在页面中添加隐式表单域来存储用户会话相关信息,事情将变得非常麻烦。
  • ③cookie:cookie有两种,一种是基于窗口的,浏览器窗口关闭后,cookie就没有了;另一种是将信息存储在一个临时文件中,并设置存在的时间。当用户通过浏览器和服务器建立一次会话后,会话ID就会随响应信息返回存储在基于窗口的cookie中,那就意味着只要浏览器没有关闭,会话没有超时,下一次请求时这个会话ID又会提交给服务器让服务器识别用户身份。会话中可以为用户保存信息。会话对象是在服务器内存中的,而基于窗口的cookie是在客户端内存中的。如果浏览器禁用了cookie,那么就需要通过下面两种方式进行会话跟踪。当然,在使用cookie时要注意几点:首先不要在cookie中存放敏感信息;其次cookie存储的数据量有限(4k),不能将过多的内容存储cookie中;再者浏览器通常只允许一个站点最多存放20个cookie。当然,和用户会话相关的其他信息(除了会话ID)也可以存在cookie方便进行会话跟踪。
  • ④HttpSession:在所有会话跟踪技术中,HttpSession对象是最强大也是功能最多的。当一个用户第一次访问某个网站时会自动创建HttpSession,每个用户可以访问他自己的HttpSession。可以通过HttpServletRequest对象的getSession方法获得HttpSession,通过HttpSession的setAttribute方法可以将一个值放在HttpSession中,通过调用HttpSession对象的getAttribute方法,同时传入属性名就可以获取保存在HttpSession中的对象。与上面三种方式不同的是,HttpSession放在服务器的内存中,因此不要将过大的对象放在里面,即使目前的Servlet容器可以在内存将满时将HttpSession中的对象移到其他存储设备中,但是这样势必影响性能。添加到HttpSession中的值可以是任意Java对象,这个对象最好实现了Serializable接口,这样Servlet容器在必要的时候可以将其序列化到文件中,否则在序列化时就会出现异常。

103、过滤器有哪些作用和用法?

答: Java Web开发中的过滤器(filter)是从Servlet 2.3规范开始增加的功能,并在Servlet 2.4规范中得到增强。对Web应用来说,过滤器是一个驻留在服务器端的Web组件,它可以截取客户端和服务器之间的请求与响应信息,并对这些信息进行过滤。当Web容器接受到一个对资源的请求时,它将判断是否有过滤器与这个资源相关联。如果有,那么容器将把请求交给过滤器进行处理。在过滤器中,你可以改变请求的内容,或者重新设置请求的报头信息,然后再将请求发送给目标资源。当目标资源对请求作出响应时候,容器同样会将响应先转发给过滤器,再过滤器中,你可以对响应的内容进行转换,然后再将响应发送到客户端。
常见的过滤器用途主要包括:对用户请求进行统一认证、对用户的访问请求进行记录和审核、对用户发送的数据进行过滤或替换、转换图象格式、对响应内容进行压缩以减少传输量、对请求或响应进行加解密处理、触发资源访问事件、对XML的输出应用XSLT等。
和过滤器相关的接口主要有:Filter、FilterConfig、FilterChain

104、监听器有哪些作用和用法?

答:Java Web开发中的监听器(listener)就是application、session、request三个对象创建、销毁或者往其中添加修改删除属性时自动执行代码的功能组件,如下所示:

  • ①ServletContextListener:对Servlet上下文的创建和销毁进行监听。
  • ②ServletContextAttributeListener:监听Servlet上下文属性的添加、删除和替换。
  • ③HttpSessionListener:对Session的创建和销毁进行监听。
    补充:session的销毁有两种情况:1、session超时(可以在web.xml中通过/标签配置超时时间);2、通过调用session对象的invalidate()方法使session失效。
  • ④HttpSessionAttributeListener:对Session对象中属性的添加、删除和替换进行监听。
  • ⑤ServletRequestListener:对请求对象的初始化和销毁进行监听。
  • ⑥ServletRequestAttributeListener:对请求对象属性的添加、删除和替换进行监听。

105、web.xml 的作用?

答:用于配置Web应用的相关信息,如:监听器(listener)、过滤器(filter)、 Servlet、相关参数、会话超时时间、安全验证方式、错误页面等。例如:

106、你的项目中使用过哪些JSTL标签?

答:项目中主要使用了JSTL的核心标签库,包括、、、、等,主要用于构造循环和分支结构以控制显示逻辑。
【说明】虽然JSTL标签库提供了core、sql、fmt、xml等标签库,但是实际开发中建议只使用核心标签库(core),而且最好只使用分支和循环标签并辅以表达式语言(EL),这样才能真正做到数据显示和业务逻辑的分离,这才是最佳实践。

107、使用标签库有什么好处?如何自定义JSP标签?

答:使用标签库的好处包括以下几个方面:

  • 1.分离JSP页面的内容和逻辑,简化了Web开发;
  • 2.开发者可以创建自定义标签来封装业务逻辑和显示逻辑;
  • 3.标签具有很好的可移植性、可维护性和可重用性;
  • 4.避免了对Scriptlet(小脚本)的使用(很多公司的项目开发都不允许在JSP中书写小脚本)
    自定义JSP标签包括以下几个步骤:
  • 1.编写一个Java类实现实现Tag/BodyTag/IterationTag接口(通常不直接实现- 这些接口而是继承TagSupport/BodyTagSupport/SimpleTagSupport类,这是对适配器模式中缺省适配模式的应用)
  • 2.重写doStartTag()、doEndTag()等方法,定义标签要完成的功能
  • 3.编写扩展名为tld的标签描述文件对自定义标签进行部署,tld文件通常放在WEB-INF文件夹或其子目录
  • 4.在JSP页面中使用taglib指令引用该标签库。

108、表达式语言(EL)的隐式对象及其作用?

答:pageContext、initParam(访问上下文参数)、param(访问请求参数)、paramValues、header(访问请求头)、headerValues、cookie(访问cookie)、applicationScope(访问application作用域)、sessionScope(访问session作用域)、requestScope(访问request作用域)、pageScope(访问page作用域)。用法如下所示:

${pageContext.request.method}
${pageContext["request"]["method"]}
${pageContext.request["method"]}
${pageContext["request"].method}
${initParam.defaultEncoding}
${header["accept-language"]}
${headerValues["accept-language"][0]}
${cookie.jsessionid.value}
${sessionScope.loginUser.username}

【补充】表达式语言的.和[]运算作用是一致的,唯一的差别在于如果访问的属性名不符合Java标识符命名规则,例如上面的accept-language就不是一个有效的Java标识符,那么这时候就只能用[]运算符而不能使用.获取它的值。

109、表达式语言(EL)支持哪些运算符?

答:除了.和[]运算符,EL还提供了:

  • •算术运算符:+、-、*、/或div、%或mod
  • •关系运算符:==或eq、!=或ne、>或gt、>=或ge、<或lt、<=或le
  • •逻辑运算符:&&或and、||或or、!或not
  • •条件运算符:${statement? A : B}(跟Java的条件运算符类似)
  • •empty运算符:检查一个值是否为null或者空(数组长度为0或集合中没有元素也返回true)

110、请对以下Java EE中的名词进行解释

答:

  • 1.容器:容器为Java EE应用程序组件提供了运行时支持。容器提供了一份从底层Java EE API到应用程序组件的联合视图。Java EE应用程序组件不能直接地与其它Java EE应用程序组件交互。它们通过容器的协议和方法来达成它们之间以及它们与平台服务之间的交互。在应用程序组件和Java EE服务之间插入一个容器,这允许该容器透明地为组件注入必须的服务,例如声明式事务管理,安全检查,资源池和状态管理。
  • 2.资源适配器:资源适配器是一个系统级的组件,它通常实现了对外部资源管理器的网络连接。资源适配器能够扩展Java EE平台的功能。这只需要实现一个Java EE标准服务API(例如JDBC驱动程序),或者定义并实现一个能连接到外部应用程序系统的资源适配器就可以达到。资源适配器也可以提供完整的本地或本地资源的服务。资源适配器接口通过Java EE服务供应商接口(Java EE SPI)来连接Java EE平台。使用Java EE SPI连接到Java EE平台的资源适配器可以和所有的Java EE产品协同工作。
  • 3.JNDI(Java Naming & Directory Interface):Java命名目录接口,主要提供的功能是:提供一个目录系统,让其它各地的应用程序在其上面留下自己的索引,从而满足快速查找和定位分布式应用程序的功能。
  • 4.JMS(Java Message Service):Java消息服务是用于消息发送的标准API,它支持可靠的“点对点”消息发送和“发布-订阅”模型。Java EE规范要求JMS供应商同时实现“点对点”消息发送和”发布/订阅”型消息发送。
  • 5.JTA(Java Transaction API):Java 事务编程接口。Java事务API由两部分组成:①一个应用程序级的边界划分接口,容器和应用程序组件用它来划分事务边界;②一个介于事务管理器和资源管理器之间的Java EE SPI级接口。
  • 6.JPA(Java Persistence API):Java持久化API是用于持久化和对象/关系映射管理的标准API。通过使用一个Java域模型来管理关系型数据库,Java EE规范为应用程序开发者提供了一种对象/关系映射功能。Java EE必须对Java持久化API提供支持。它也可以用在Java SE环境中。
  • 7.JAF(JavaBean Activation FrameWork):JAF API提供了一个框架来处理不同MIME类型的数据,它们源于不同的格式和位置。JavaMail API使用了JAF API。JAF API包含在Java SE中,因此它可以被Java EE应用程序使用。
  • 8.JAAS(Java Authentication and Authorization Service):使服务能够基于用户进行验证和实施访问控制。它实现了一个Java版的标准的的Plugable Authentication Module (PAM)框架,并支持基于用户的授权。Java Authorization Service Provider Contract for Containers (JACC) 定义了Java EE应用程序服务器和授权服务提供方之间的协议,允许将自定义的授权服务提供方插入任何Java EE产品中。
  • 9.JMX(Java Management Extension):Java平台企业版管理规范中定义了一种API,通过一种特殊的管理型EJB来管理Java EE服务器。JMX API也提供了一些管理上的支持。

111、你是如何理解控制反转(IoC)和依赖注入(DI)的?

答:控制反转 (Inversion of Control, IoC)是把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”就是对组件对象控制权的转移,从程序代码本身转移到了外部容器,由容器来创建对象并管理对象之间的依赖关系。IoC体现了好莱坞原则:“Don’t call me, we will call you”。依赖注入(Dependency Injection,DI)的基本原则是:应用组件不应该负责查找资源或者其他依赖的协作对象。配置对象的工作应该由容器负责,查找资源的逻辑应该从应用组件的代码中抽取出来,交给容器来完成。DI是对IoC更准确的描述,即组件之间的依赖关系由容器在运行期决定,形象的来说,即由容器动态的将某种依赖关系注入到组件之中。
举个例子:一个类A需要用到接口B中的方法,那么就需要为类A和接口B建立关联或依赖关系,最原始的方法是在类A中创建一个接口B的实现类C的实例,但这种方法需要开发人员自行维护二者的依赖关系,也就是说当依赖关系发生变动的时候需要修改代码并重新构建整个系统。如果通过一个容器来管理这些对象以及对象的依赖关系,则只需要在类A中定义好用于关联接口B的方法(构造器或setter方法),将类A和接口B的实现类C放入容器中,通过对容器的配置来实现二者的关联。

112、请说出Spring 中依赖注入和AOP的实现机制。

答:

  • 实现依赖注入的方式包括:构造器注入、设值注入和接口(回调)注入。Spring中可以通过设值注入(setter方法注入)和构造器注入实现IoC,推荐使用的方式为设值注入。
  • 实现AOP的方式包括:编译时AOP(需要特殊的编译器)、运行时AOP(代理模式)、加载时AOP(需要特殊的类加载器)。Spring中使用了运行时的AOP,主要通过代理的方式对原来的代码进行增强实现。对于实现了接口的类,Spring通过Java的动态代理(请参考Proxy类和InvocationHandler接口)来进行增强;对于没有实现接口的类,Spring使用第三方字节码生成工具CGLIB,通过继承的方式对原有代码进行增强。

113、你的项目选择使用Spring框架的原因是什么?

答:

  • 1.Spring提供了企业级开发的一站式选择,有大量的功能模块可供选择,并且可以根据项目的需要自由取舍。Spring通过POJO简化了JavaEE开发,低侵入式的编程提供了代码的持续集成能力和易测试性。
  • 2.Spring框架的核心功能是依赖注入(DI)。DI使得代码的单元测试更加方便、系统更好维护、代码也更加灵活。DI代码自身很容易测试,通过构建实现了应用所需的接口的“模拟”对象就可以进行功能的黑盒测试。DI代码也更容易复用,因为其“被依赖的”功能封装在在定义良好的接口中,允许其他对象根据需要将其插入到所需的对象中,这些对象是在其他应用平台中进行配置的。DI使代码更加灵活,由于其天生的松耦合性,它允许程序员仅需考虑自己所需的接口和其他模块暴露出来的接口来就可以决定对象之间如何关联。
  • 3.Spring支持面向切面编程(AOP),允许通过分离应用业务逻辑和系统服务从而进行内聚性的开发。AOP通常用来支持日志、审计、性能和内存监控等功能。
  • 4.Spring还提供了许多实现基本功能的模板类,使得Java EE应用的开发更加容易。例如,JdbcTemplate类和JDBC、JpaTemplate类和JPA,JmsTemplate类和JMS都可以很好地结合起来使用。RestTemplate类非常简洁,使用这个模板的代码的可读性和可维护性也都很好。
  • 5.Spring提供了声明性事务处理,工作调度,身份认证,成熟的Web MVC框架以及和其他框架的集成,例如Hibernate、MyBatis、JasperReports、JSF、Struts、Tapestry、Seam和Quartz等等。
  • 6.Spring Bean对象可以通过Terracotta在不同的JVM之间共享。这就允许使用已有的Bean并在集群中共享 ,将Spring应用上下文事件变为分布式事件,还可以通过Spring JMX导出集群Bean,使得Spring应用高可用、集群化。
  • 7.Spring倾向于使用非受检异常(运行时异常)和减少不当try、catch和finally代码块,例如JpaTemplate这样的Spring模板类会负责关闭或释放数据库连接,这避免了潜在的外部资源泄露问题并提高了代码的可读性。

你可能感兴趣的:(面试,面试)