一、单项选择题(共10题,每题2分,共20分)
1. 下列说法哪一个是正确的。( B )
A.Java程序经编译后会产生machine code
B.Java程序经编译后会产生bytecode
C.Java程序经编译后会产生DLL
D.以上都不正确
2. 提供Java存取数据库能力的包是。( A )
A.java.sql B.java.awt C.java.lang D.java.swing
3. 执行如下程序代码后,C的值是。( C )
a=0;c=0;
do{
--c;
a=a-1;
}while(a>0);
A.0 B.1 C.-1 D.死循环
4. 下面的语句中正确的表达式为。( C )
A.byte b = 128;
B.boolean n = null;
C.double d = 0.9239d;
D.float f = 0.9239;
5. 将一个十六进制值赋给一个long型变量的正确写法为。( D )
A.long number = 345L;
B.long number = 0345;
C.long number = 0345L;
D.long number = 0x345L;
6. 以下程序代码的输出是。( B )
public classtest (
public static void main (String args[]) (
System.out.printIn (6 ^ 3);
)
)
A.3 B.5 C.6 D.11
7. 以下程序代码的输出是。(E )
public class test (
private static int j = 0;
private static boolean methodB(int k) (
j += k;
return true;
)
public static void methodA(int i) {
boolean b:
b = i< 10 | methodB (4);
b = i< 10 || methodB (8);
)
publicstatic void main (String args[] } (
methodA (0);
system.out.printIn(j);
)
)
A.0 B.4 C.8 D.12 E.不能编译通过
8. 以下程序代码的输出是。( A)
public class test {
public static void add3 (Integer i) }
int val = i.intValue ( );
val += 3;
i = new Integer (val);
}
public static void main (String args [ ] ) {
Integer i = new Integer (0);
add3(i);
system.out.printIn (i.intValue ( ) );
}
)
A.编译失败 B.编译成功但在第三行会出现异常 C.0 D.3
9. 以下程序代码执行后,哪个说法正确?( B )
int index = 1;
boolean[] test =new Boolean[3];
boolean foo=test [index];
A.有异常抛出。
B.无法编译。
C.foo的值是0。
D.foo的值是null。
E.foo的值是true。
F.foo的值是false。
10. 以下哪个类是swt包中的。( D )
A.MessageBox B.MessageDialog C.JDialog D.DisplayMode
多项选择题(共5题,每题4分,共20分)
11. 在下面的选项中合法的标识符有。( ADEF )
A._ok
B.*point
C.this
D.$byte
E.const
F.ILikeJLCSS
12. 下面的选项中哪些不是java的关键字。( ABD )
A.TRUE
B.sizeof
C.goto
D.const
E.super
F.void
13. 下面的叙述中正确的有。( AC )
A.环境变量可在编译source code时指定。
B.在编译程序时,所能指定的环境变量不包括class path。
C. javac一次可同时编译数个Java源文件。
D. javac.exe能指定编译结果要置于哪个目录(directory)。
14. 下面的叙述中正确的有。( C )
A.equals()方法判定引用值是否指向同一对象。
B.= = 操作符判定两个分立的对象的内容和类型是否一致。
C.equals()方法只有在两个对象的内容一致时返回true。
D.类File重写方法equals()在两个分立的对象的内容和类型一致时返回true。
15. 下面有关变量及其作用域的陈述哪些是对的。( A C )
A. 在方法里面定义的局部变量在方法退出的时候被撤销。
B. 局部变量也叫自动变量。
C. 在方法外面定义的变量(译注:即实例变量)在对象被构造时创建。
D. 在方法中定义的方法的参变量只要该对象被需要就一直存在。
二、简答题(共7题,共40分)
1. 请写出一个输出“Hello World!” 的程序。(3分)
答:public Class Hello World
{
Public static void main(String[]args)
{
System.out.println(“HELLO WOTLD”);
}
}
2. char型变量中能不能存贮一个中文汉字? 为什么? (3分)
答:能存储一个汉字;因为它能存储四个字节而每个汉字只占两个字节。
3. 常见的两种xml解析技术是什么? 区别是什么? (4分)
答:常见的两种有:SAX和DOM。
区别:SAX 是一种事件驱动的xml解析方式。每次访问一个xml文件中的某个节点的时候,sax就会搜索一遍xml文件,在找到相应的节点后就会触发一个事件来处理请求。只读
DOM是一种基于树状的查找方式。DOM会将xml解析成一棵树,存在内存中。开发者可以通过查找树的节点来取得文件的内容或者修改内容。可读写
4. MVC是什么,如何实现? (5分)
答:MVC是一个是一个设计模式,它强制性的使应用程序的输入,处理和输出分开。使用MVC应用程序被分为三个核心部件:M----------MODO模型,V ----------VIEW 试图,C --------- Contral控制
实现:首先有页面(jsp)发送请求给控制器(servlet),然后由控制器接收用户的请求,并决定应该调用哪个模型(javabean)来进行处理,然后模型用业务逻辑来处理用户的请求并返回数据,最后控制器用相应的视图格式化模型返回的数据,并通过表示层显示给用户。
5. .J2EE是什么?(6分)
答:J2EE 是Sun公司提出的多层(multi-diered),分布式(distributed),基于组件(component-base)的企业级应用模型(enterpriese application model).在这样的一个应用系统中,可按照功能划分为不同的组件,这些组件又可在不同计算机上,并且处于相应的层次(tier)中。所属层次包括客户层(clietn tier)组件,web层和组件,Business层和组件,企业信息系统(EIS)层。
6. jsp有哪些内置对象?作用分别是什么? (9分)
答:1.request 用户端请求,此请求会包含来自GET/POST请求的参数;2.response 网页传回用户端的回应;3.pageContext 网页的属性是在这里管理;4.session 与请求有关的会话期;5.application servlet 正在执行的内容;6.out 用来传送回应的输出;7.config servlet的构架部件;8.page JSP网页本身;9.exception 针对错误网页,未捕捉的例外
7. 作用域public,private,protected,以及不写时的区别 ?(10分)
答:作用域 当前类 同一package 子孙类 其他package
public √ √ √ √
protected √ √ √ ×
friendly √ √ × ×
private √ × × ×
不写时默认为friendly
编码及论述题(共2题,每题10分,共20分)
8. 什么是Singleton,它的作用是什么,它有几种形式?请用代码写出一个Singleton类。
答:Java Singleton 模式用来保证在运行的应用程序中,一个Class只是实例化一次,也就是只有一个相应的对象存在。
它有三种形式
public classSingleton
{
private static Singleton instance = null;
public static synchronized Singleton getInstance()
{
if (instance==null)
instance=new Singleton();
return instance;
}
}
9. 在Struts + Spring + Hibernate的组合框架模式中,三者各自的特点都是什么?
答:Strtus WEB层 Spring是业务层 Hiebenate是持久化层
SSH试题
1.Hibernate工作原理及为什么要用?
原理: 1.读取并解析配置文件 2.读取并解析映射信息,创建SessionFactory 3.打开Session 4.创建事务Transation 5.持久化操作 6.提交事务 7.关闭Session 8.关闭SesstionFactory
为什么要用: 1. 对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。 2. Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。他很大程度的简化DAO层的编码工作 3. hibernate使用Java反射机制,而不是字节码增强程序来实现透明性。 4. hibernate的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。
2.Hibernate是如何延迟加载?
1. Hibernate2延迟加载实现:a)实体对象 b)集合(Collection)
2. Hibernate3 提供了属性的延迟加载功能 当Hibernate在查询数据的时候,数据并没有存在与内存中,当程序真正对数据的操作时,对象才存在与内存中,就实现了延迟加载,他节省了服务器的内存开销,从而提高了服务器的性能。
3.Hibernate中怎样实现类之间的关系?(如:一对多、多对多的关系)
类与类之间的关系主要体现在表与表之间的关系进行操作,它们都市对对象进行操作,我们程序中把所有的表与类都映射在一起,它们通过配置文件中的many-to-one、one-to-many、many-to-many
4.Struts1流程:
1、客户端浏览器发出HTTP请求。2、根据web.xml配置,该请求被ActionServlet接收。3、根据struts-config.xml配置,ActionServlet先将请求中的参数填充到ActionForm中,然后ActionServlet再将请求发送到Action 进行处理。4、是否验证,需要验证则调用ActionForm的validate方法,验证失败则跳转到input,成功则继续。5、Action从ActionForm获得数据,调用javabean 中的业务方法处理数据。6、Action返回ActionForward对象,跳转到相应JSP页面或Action。7、返回HTTP响应到客户端浏览器。
MVC设计模式:modal:“模型” 也称业务逻辑,是正真完成任务的代码,相当与JavaBeanview:视图,其实就是显示界面,相当于JSPcontroller:控制器,他控制模型和视图的交互过程,相当于servletstruts1是基于MVC设计模式hibernate是基于ORM对象关系映射
5.struts是什么?
struts1是基于JSP和servlet的一个开源的Web应用框架,使用的是MVC的设计模式struts2是基于webwork技术的框架,是sun和webwork公司联手开发的一个功能非常齐全的框架,struts2和struts1没有任何关系,是一个全新的框架
6.spring是什么?
spring是一个集成了许多第三方框架的大杂烩,其核心技术是IOC(控制反转,也称依赖注入)和AOP(面向切面编程)
7.hibernate是什么?
hibernate是基于ORM对象关系映射(完成对象数据到关系数据映射的机制)实现的,做数据持久化的工具
8.JSF是什么?
JavaServer Face是基于组件的web开发框架,跟sturts差不多的框架
9.数据库里面的索引和约束是什么?
索引是为了提高数据的检索速度,索引是建立在数据表上,根据一个或多个字段建立的约束是为了保持数据的完整性,约束有非空约束,主键约束,外键约束等等。
10.spring是什么
这个问题,往往可以通过我们为什么要使用spring这个问题来切入:AOP 让开发人员可以创建非行为性的关注点,称为横切关注点,并将它们插入到应用程序代码中。使用 AOP 后,公共服务(比 如日志、持久性、事务等)就可以分解成方面并应用到域对象上,同时不会增加域对象的对象模型的复杂性。 IOC 允许创建一个可以构造对象的应用环境,然后向这些对象传递它们的协作对象。正如单词倒置 所表明的,IOC 就像反 过来的 JNDI。没有使用一堆抽象工厂、服务定位器、单元素(singleton)和直接构造(straight construction),每一个对象都是用其协作对象构造的。因此是由容器管理协作对象(collaborator)。 Spring即使一个AOP框架,也是一IOC容器。 Spring 最好的地方是它有助于您替换对象。有了 Spring,只要用 JavaBean 属性和配置文件加入依赖性(协作对象)。然后可以很容易地在需要时替换具有类似接口的协作对象。
11.用自己的话简要阐述struts2的执行流程。
Struts 2框架本身大致可以分为3个部分:核心控制器FilterDispatcher、业务控制器Action和用户实现的企业业务逻辑组件。核心控制器FilterDispatcher是Struts 2框架的基础,包含了框架内部的控制流程和处理机制。业务控制器Action和业务逻辑组件是需要用户来自己实现的。用户在开发Action和业务逻辑组件的同时,还需要编写相关的配置文件,供核心控制器FilterDispatcher来使用。
Struts 2的工作流程相对于Struts 1要简单,与WebWork框架基本相同,所以说Struts2是WebWork的升级版本。基本简要流程如下:1、客户端浏览器发出HTTP请求。2、根据web.xml配置,该请求被FilterDispatcher接收。3、根据struts.xml配置,找到需要调用的Action类和方法,并通过IoC方式,将值注入给Aciton。4、Action调用业务逻辑组件处理业务逻辑,这一步包含表单验证。5、Action执行完毕,根据struts.xml中的配置找到对应的返回结果result,并跳转到相应页面。6、返回HTTP响应到客户端浏览器。
12.谈谈你mvc的理解
MVC是Model—View—Controler的简称。即模型—视图—控制器。MVC是一种设计模式,它强制性的把应用程序的输入、处理和输出分开。
MVC中的模型、视图、控制器它们分别担负着不同的任务。
视图: 视图是用户看到并与之交互的界面。视图向用户显示相关的数据,并接受用户的输入。视图不进行任何业务逻辑处理。
模型: 模型表示业务数据和业务处理。相当于JavaBean。一个模型能为多个视图提供数据。这提高了应用程序的重用性
控制器: 当用户单击Web页面中的提交按钮时,控制器接受请求并调用相应的模型去处理请求。
然后根据处理的结果调用相应的视图来显示处理的结果。
MVC的处理过程:首先控制器接受用户的请求,调用相应的模型来进行业务处理,并返回数据给控制器。控制器调用相应的视图来显示处理的结果。并通过视图呈现给用户。
Java笔试算法试题
1.现在输入n个数字,以逗号,分开;然后可选择升或者降序排序
我的评论:
本题的splitStringByComma(String )方法纯属多余,可以用String的split方法一句话代替,且可读性也更强,下面的一段话源自JDK1.6API,StringTokenizer类已不再提倡使用,保留仅为旧代码。
StringTokenizer是出于兼容性的原因而被保留的遗留类(虽然在新代码中并不鼓励使用它)。建议所有寻求此功能的人使用String的split方法或 java.util.regex 包。
importjava.util.*;
publicclass bycomma{
public static String[]splitStringByComma(String source){
if(source==null||source.trim().equals(""))
return null;
StringTokenizer commaToker = newStringTokenizer(source,",");
String[] result = newString[commaToker.countTokens()];
int i=0;
while(commaToker.hasMoreTokens()){
result[i] =commaToker.nextToken();
i++;
}
return result;
}
public static void main(String args[]){
String[] s =splitStringByComma("5,8,7,4,3,9,1");
int[] ii = new int[s.length];
for(int i = 0; i<ii.length;i++){
ii[i] =Integer.parseInt(s[i]);
}
Arrays.sort(ii);
//asc
for(int i=0;i<ii.length;i++ ){
System.out.println(ii[i]);
}
//desc
for(int i=(s.length-1);i>=0;i--){
System.out.println(ii[i]);
}
}
}
2.编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串。但是要保证汉字不被截半个,如"我ABC"4,应该截为"我AB",输入"我ABC汉DEF",6,应该输出为"我ABC"而不是"我ABC+汉的半个"。
代码:
publicstatic boolean isLetter(char c){
int k=0X80;
return c/k==0?true:false;
}
public static int lengths(String strSrc){
if (strSrc==null){
return 0;
}
int len=0;
char[] strChar=strSrc.toCharArray();
for (int i=0;i<strChar.length;i++){
len++;
if (!isLetter(strChar[i])) len++;
}
return len;
}
public static String subString(Stringorigin,int len){
if (origin==null ||origin.equals("")|| len<1){
return "";
}
if (len>lengths(origin)){
return origin;
}
byte[] strByte=new byte[len];
System.arraycopy(origin.getBytes(),0,strByte,0,len);
int count=0;
for (int i=0;i<len;i++){
int value=(int)strByte[i];
if (value<0) count++;
}
if (count % 2 !=0){
//len=(len==1)?++len:--len;
--len;
}
return new String(strByte,0,len);
}
publicstatic void main(String[] args) {
System.out.println(""+subString("我ABC汉DEF",6));
}
3、排序都有哪几种方法?请列举。用JAVA实现一个快速排序。
排序的方法有:插入排序(直接插入排序、希尔排序),交换排序(冒泡排序、快速排序),选择排序(直接选择排序、堆排序),归并排序,分配排序(箱排序、基数排序)
快速排序的伪代码。
/ /使用快速排序方法对a[ 0:n- 1 ]排序从a[ 0 :n- 1 ]中选择一个元素作为m I d d l e,该元素为支点把余下的元素分割为两段left 和r I g h t,使得l e f t中的元素都小于等于支点,而right 中的元素都大于等于支点递归地使用快速排序方法对left 进行排序递归地使用快速排序方法对right 进行排序所得结果为l e f t + m I d d l e + r I g h t
//以下为java程序实现的快速排序算法:
publicstatic void sort(int[] data) {
quickSort(data,0,data.length-1);
}
publicstatic void quickSort(int[] data,int low,int high){
int pivotIndex=(low+high)/2;
swap(data,pivotIndex,high);
int k=partition(data,low-1,high,data[high]);
swap(data,k,high);
if ((k-low)>1) partition(data,low,k-1);
if ((high-k)>1)partition(data,k+1,high);
}
publicstatic int partition(int[] data int low,int high, int pivot ){
do {
while (data[++low]<pivot) ;
while (high!=0 && data[--high]>pivot);
swap(data,low,high);
}
while (low<high) ;
swap(data,low,high);
return low;
}
publicstatic void swap(int[] data int low,int high){
int tmp=data[low];
data[low]=data[high];
data[high]=tmp;
}
publicstatic void main(String[] args){
int[] data = newint[]{89,32,425,32,78,1,53,92};
sort(data);
}
4.试用递归的方法写一下计算菲波那契数列的通项f(n),已知f1=1,f2=1,以后每项都是前两项的和。
..............
publicstatic long fibonacci(long m){
if (m==0 ||m==1) return m;
else returnfibonacci(m-1)+fibonacci(m-2);
}
5. 写一个Singleton出来。
Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。
我的评论:第一种形式是饿汉式单例类,第二种是懒汉式单例类;可以如此速记,饿汉式太饿了,所以迫不及待在内部new出一个实例,而懒汉式太懒了,所以知道应用时才检查有没有实例存在,如不存在才new一个实例出来。
一般Singleton模式通常有几种种形式:
第一种形式: 定义一个类,它的构造函数为private的,它有一个static的private的该类变量,在类初始化时实例话,通过一个public的getInstance方法获取对它的引用,继而调用其中的方法。
Publicclass Singleton {
private Singleton(){}
//在自己内部定义自己一个实例,是不是很奇怪?
//注意这是private 只供内部调用
private static Singleton instance = newSingleton();
//这里提供了一个供外部访问本class的静态方法,可以直接访问
public static Singleton getInstance() {
return instance;
}
}
第二种形式:
publicclass Singleton {
private staticSingleton instance = null;
public staticsynchronized Singleton getInstance() {
//这个方法比上面有所改进,不用每次都进行生成对象,只是第一次
//使用时生成实例,提高了效率!
if (instance==null)
instance=new Singleton();
return instance;
}
}
其他形式:
定义一个类,它的构造函数为private的,所有方法为static的。
一般认为第一种形式要更加安全些
6、创建一个静态方法,给它传入一个对象,请循环的打印出该对象所在类的类名和所实现的方法名(华为笔试最后一道编程)
importjava.lang.reflect.*;
publicclass Test{
publicstatic void test(Object obj){
Class clazz=obj.getClass();
//System.out.println("类名:"+clazz.getName());
Method[] ms=clazz.getDeclaredMethods();
long len=Array.getLength(ms);
for(int i=0;i<len;i++){
System.out.println("类名:"+clazz.getName()+"方法名:"+ms[i].getName());
}
}
class A{
public void b(){}
public void c(){}
public void d(){}
public void e(){}
}
publicstatic void main(String[] args){
Test t=new Test();
Test.A a=t.new A();
test(a);
}
}
7、假设字符串类似这样的aba和aab就相等,现在随便给你二组字符串,请编程比较他们看是否相等
BufferedReaderbr = new BufferedReader(new InputStreamReader(System.in));
String s =null;
try {
s =br.readLine();
} catch(IOException e) {
e.printStackTrace();
}
StringTokenizerst = new StringTokenizer(s);
String s1 =st.nextToken();
String s2 =st.nextToken();
byte[] sa1= s1.getBytes();
byte[] sb2= s2.getBytes();
Arrays.sort(sa1);
Arrays.sort(sb2);
String ss1= new String(sa1);
String ss2= new String(sb2);
if(ss1.equals(ss2))
System.out.println("equal");
else
System.out.println("notequal");
8、给你一组字符串如:iu7i8hy4jnb2,让你编程输出里面的数字:7842
用正规表达式:"iu7i8hy4jnb2".replaceAll("[^\\d]","");
9、给你一组字符串让你把它倒叙输出
publicstatic String flashBack(String origin) {
String result = "";
for (int i = origin.length(); i > 0; i--){
String tmp = origin.substring(i - 1, i);
result += tmp;
}
return result;
}
10、给你一组字符如{1,3,4,7,2,1,1,5,2},让你输出里面出现次数最多且数值最大的一个,出现几次
public voidfun4() {
int[] a = { 4, 1, 2, 4, 5, 1, 1, 1, 5, 1,3, 4, 5 };
Arrays.sort(a);
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
System.out.println();
int maxNumber = a[a.length - 1], maxCount =1;
int curNumber = a[a.length - 1], curCount =1;
for (int i = a.length - 1; i > 0; i--) {
curNumber = a[i];
if (a[i] == a[i - 1]) {
curCount++;
} else {
System.out.println("i="+ i + ",curCount=" + curCount+ ",maxCount=" + maxCount +",maxNumber=" + maxNumber);
if (curCount > maxCount) {
maxCount = curCount;
maxNumber = curNumber;
}
curCount = 1;
}
}
if (curCount > maxCount) {
maxCount = curCount;
//maxNumber = curNumber;
}
System.out.println("curCount="+ curCount + ",maxCount=" + maxCount + ",maxNumber=" +maxNumber);
}
11、求两个数的公约数,M,N
int divisor=1;
for (int i= 2; i <= b; i++) {
if(a%i==0&& b%i==0){
divisor =i;
}
}
System.out.println(a+"和"+b+"的最大公约数是:"+divisor);
}
12、实现数组复制
我的理解:这是深复制,数组a,b不再有关联
public voidfun8(){
int[] a ={1,2,3,4,56,7,8};
int[] b =(int[])a.clone();
Conica.print(a);
Conica.print(b);
b[0]=100;
Conica.print(a);
Conica.print(b);
}
13、冒泡排序的实现
public voidfun9(){
int[] a ={1,5,2,6,8,74,1,25,69,8};
Conica.print(a);
for(inti=0; i<a.length-1; i++){
for(intj=0; j<a.length-i-1;j++){
if(a[j]>a[j+1]){
int temp =a[j];
a[j] =a[j+1];
a[j+1] =temp;
}
}
}
Conica.print(a);
}
14、编程显示某一文件目录下的文件名
public voidfun10(){
File file =new File("G:\\03月份");
if(file.exists()){
if(file.isDirectory()){
String[]files = file.list();
Conica.println(files);
}
}
}
15、从键盘输入4个十进制数字字符,将其转换为4位时间之数并显示出来
16、编程实现统计文本文件中某个单词的出现频率,并输出统计结果
用HashMap来解决
假设单词不存在跨行的,每个单词用,. ;分割
publicstatic void countNum() throws IOException {
BufferedReader br = null;
try {
br = new BufferedReader(newFileReader("c://file.txt"));
Map map = new HashMap();
for (String s = br.readLine(); s != null; s= br.readLine()) {
StringTokenizer st = newStringTokenizer(s, ",. ;");
while (st.hasMoreTokens()) {
String temp = st.nextToken();
if (map.containsKey(temp)) {
map.put(temp, newInteger((Integer)map.get(temp) + 1));
} else {
map.put(temp, new Integer(1));
}
}
}
for (Iterator it =map.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
System.out.println(entry.getKey() +"-->" + entry.getValue()
+ "times");
}
} finally {
br.close();
}
}
Java面试题
1、作用域public,private,protected,以及不写时的区别
答:区别如下:
作用域 当前类 同一package 子孙类 其他package
public √ √ √ √
protected √ √ √ ×
friendly √ √ × ×
private √ × × ×
不写时默认为friendly
4、&和&&的区别
答:&是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑与(and)
5、Collection 和 Collections的区别
答:Collection是集合类的上级接口,继承与他的接口主要有Set 和List.
Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作
6、什么时候用assert
答:assertion(断言)在软件开发中是一种常用的调试方式,很多开发语言中都支持这种机制。在实现中,assertion就是在程序中的一条语句,它对一个boolean表达式进行检查,一个正确程序必须保证这个boolean表达式的值为true;如果该值为false,说明程序已经处于不正确的状态下,系统将给出警告或退出。一般来说,assertion用于保证程序最基本、关键的正确性。assertion检查通常在开发和测试时开启。为了提高性能,在软件发布后,assertion检查通常是关闭的
7、String s = newString("xyz");创建了几个String Object
答:两个,一个字符对象,一个字符对象引用对象
9、short s1 = 1; s1 =s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错
答:short s1 = 1; s1 = s1 + 1; (s1+1运算结果是int型,需要强制转换类型)shorts1 = 1; s1 += 1;(可以正确编译)
11、数组有没有length()这个方法? String有没有length()这个方法
答:数组没有length()这个方法,有length的属性。String有有length()这个方法
13、Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别
答:Set里的元素是不能重复的,那么用iterator()方法来区分重复与否。equals()是判读两个Set是否相等
equals()和==方法决定引用值是否指向同一对象equals()在类中被覆盖,为的是当两个分离的对象的内容和类型相配的话,返回真值
15、error和exception有什么区别
答:error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况
exception 表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况
16、List, Set, Map是否继承自Collection接口
答: List,Set是,Map不是
19、接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concreteclass)
答:接口可以继承接口。抽象类可以实现(implements)接口,抽象类是否可继承实体类,但前提是实体类必须有明确的构造函数
20、构造器Constructor是否可被override
答:构造器Constructor不能被继承,因此不能重写Overriding,但可以被重载Overloading
22、try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不会被执行,什么时候被执行,在return前还是后
答:会执行,在return前执行
23、用最有效率的方法算出2乘以8等於几
答:2 << 3
25、当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递
答:是值传递。Java 编程语言只有值传递参数。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的内容可以在被调用的方法中改变,但对象的引用是永远不会改变的
28、char型变量中能不能存贮一个中文汉字?为什么?
答:是能够定义成为一个中文的,因为java中以unicode编码,一个char占16个字节,所以放一个中文是没问题的
30、float型float f=3.4是否正确?
答:不正确。精度不准确,应该用强制类型转换,如下所示:float f=(float)3.4
34、谈谈final, finally,finalize的区别
答:final—修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为 abstract的,又被声明为final的。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,不能重载
finally—再异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)
finalize—方法名。Java 技术允许使用finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的
35、面向对象的特征有哪些方面
答:主要有以下四方面:
1.抽象:
抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节。抽象包括两个方面,一是过程抽象,二是数据抽象。
2.继承:
继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。
3.封装:
封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。
4. 多态性:
多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。
36、String是最基本的数据类型吗
答:基本数据类型包括byte、int、char、long、float、double、boolean和short。
java.lang.String类是final类型的,因此不可以继承这个类、不能修改这个类。为了提高效率节省空间,我们应该用StringBuffer类
37、int 和 Integer 有什么区别
答:Java 提供两种不同的类型:引用类型和原始类型(或内置类型)。Int是java的原始数据类型,Integer是java为int提供的封装类。Java为每个原始类型提供了封装类。
原始类型封装类,booleanBoolean,charCharacter,byteByte,shortShort,intInteger,longLong,floatFloat,doubleDouble
引用类型和原始类型的行为完全不同,并且它们具有不同的语义。引用类型和原始类型具有不同的特征和用法,它们包括:大小和速度问题,这种类型以哪种类型的数据结构存储,当引用类型和原始类型用作某个类的实例数据时所指定的缺省值。对象引用实例变量的缺省值为 null,而原始类型实例变量的缺省值与它们的类型有关
38、运行时异常与一般异常有何异同
答:异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误。java编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。
41、heap和stack有什么区别
答:栈是一种线形集合,其添加和删除元素的操作应在同一段完成。栈按照后进先出的方式进行处理。堆是栈的一个组成元素
43、Java中的异常处理机制的简单原理和应用
答:当JAVA程序违反了JAVA的语义规则时,JAVA虚拟机就会将发生的错误表示为一个异常。违反语义规则包括2种情况。一种是JAVA类库内置的语义检查。例如数组下标越界,会引发IndexOutOfBoundsException;访问null的对象时会引发NullPointerException。另一种情况就是JAVA允许程序员扩展这种语义检查,程序员可以创建自己的异常,并自由选择在何时用throw关键字引发异常。所有的异常都是java.lang.Thowable的子类。
44、垃圾回收的优点和原理。并考虑2种回收机制
答:Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理。由于有个垃圾回收机制,Java中的对象不再有"作用域"的概念,只有对象的引用才有"作用域"。垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。回收机制有分代复制垃圾回收和标记垃圾回收,增量垃圾回收。
45、你所知道的集合类都有哪些?主要方法?
答:最常用的集合类是 List 和 Map。 List 的具体实现包括 ArrayList 和 Vector,它们是可变大小的列表,比较适合构建、存储和操作任何类型对象的元素列表。 List 适用于按数值索引访问元素的情形。
Map 提供了一个更通用的元素存储方法。 Map 集合类用于存储元素对(称作"键"和"值"),其中每个键映射到一个值。
46、描述一下JVM加载class文件的原理机制?
答:JVM中类的装载是由ClassLoader和它的子类来实现的,Java ClassLoader 是一个重要的Java运行时系统组件。它负责在运行时查找和装入类文件的类。
48、JAVA语言如何进行异常处理,关键字:throws,throw,try,catch,finally分别代表什么意义?在try块中可以抛出异常吗?
答:Java通过面向对象的方法进行异常处理,把各种不同的异常进行分类,并提供了良好的接口。在Java中,每个异常都是一个对象,它是Throwable类或其它子类的实例。当一个方法出现异常后便抛出一个异常对象,该对象中包含有异常信息,调用这个对象的方法可以捕获到这个异常并进行处理。Java的异常处理是通过5个关键词来实现的:try、catch、throw、throws和finally。一般情况下是用try来执行一段程序,如果出现异常,系统会抛出(throws)一个异常,这时候你可以通过它的类型来捕捉(catch)它,或最后(finally)由缺省处理器来处理。
用try来指定一块预防所有"异常"的程序。紧跟在try程序后面,应包含一个catch子句来指定你想要捕捉的"异常"的类型。
throw语句用来明确地抛出一个"异常"。
throws用来标明一个成员函数可能抛出的各种"异常"。
Finally为确保一段代码不管发生什么"异常"都被执行一段代码。
可以在一个成员函数调用的外面写一个try语句,在这个成员函数内部写另一个try语句保护其他代码。每当遇到一个try语句,"异常"的框架就放到堆栈上面,直到所有的try语句都完成。如果下一级的try语句没有对某种"异常"进行处理,堆栈就会展开,直到遇到有处理这种"异常"的try语句。
49、一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制?
答:可以。必须只有一个类名与文件名相同。
50、java中有几种类型的流?JDK为每种类型的流提供了一些抽象类以供继承,请说出他们分别是哪些类?
答:字节流,字符流。字节流继承于InputStream OutputStream,字符流继承于InputStreamReaderOutputStreamWriter。在java.io包中还有许多其他的流,主要是为了提高性能和使用方便。
51、java中会存在内存泄漏吗,请简单描述
答:会。自己实现堆载的数据结构时有可能会出现内存泄露,可参看effective java.
52、java中实现多态的机制是什么?
答:方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。
54、静态变量和实例变量的区别
答:static i = 10; //常量 class A a; a.i =10;//可变
55、什么是java序列化,如何实现java序列化?
答:序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。
序列化的实现:将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。
56、是否可以从一个static方法内部发出对非static方法的调用?
答:不可以,如果其中包含对象的method();不能保证对象初始化.
58、在JAVA中,如何跳出当前的多重嵌套循环?
答:用break; return 方法。
59、List、Map、Set三个接口,存取元素时,各有什么特点?
答:List 以特定次序来持有元素,可有重复元素。Set 无法拥有重复元素,内部排序。Map 保存key-value值,value可多值。
60、说出一些常用的类,包,接口,请各举5个
答:常用的类:BufferedReader BufferedWriter FileReader FileWirter String Integer
常用的包:java.lang java.awt java.io java.util java.sql
常用的接口:Remote List Map Document NodeList
Jsp面试题
一、简答题
1.forward和redirect的区别
forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器,浏览器根本不知道服务器发送的内容是从哪儿来的,所以它的地址栏中还是原来的地址。
redirect就是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,一般来说浏览器会用刚才请求的所有参数重新请求,所以session,request参数都可以获取。
2.说出Servlet的生命周期,并说出Servlet和CGI的区别
Servlet被服务器实例化后,容器运行其init方法,请求到达时运行其service方法,service方法自动派遣运行与请求对应的doXXX方法(doGet,doPost)等,当服务器决定将实例销毁的时候调用其destroy方法。
与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。
3.JSP中动态INCLUDE与静态INCLUDE的区别?
动态INCLUDE用jsp:include动作实现 <jsp:includepage="included.jsp" flush="true" />它总是会检查所含文件中的变化,适合用于包含动态页面,并且可以带参数。
静态INCLUDE用include伪码实现,并不会检查所含文件的变化,适用于包含静态页面<%@ include file="included.htm" %>
4.什么情况下调用doGet()和doPost()?
Jsp页面中的form标签里的method属性为get时调用doGet(),为post时调用doPost()。
5.servlet的生命周期
web容器加载servlet,生命周期开始。通过调用servlet的init()方法进行servlet的初始化。通过调用service()方法,根据请求的不同调用不同的do***()方法。结束服务,web容器调用servlet的destroy()方法。
6.如何现实servlet的单线程模式
<%@ page isThreadSafe="false"%>
7.页面间对象传递的方法
request,session,application,cookie等
8.JSP和Servlet有哪些相同点和不同点,他们之间的联系是什么?
JSP技术构建在Servlet技术之上,是Servlet技术的扩展,本质上是Servlet的简易方式,JSP能做到的,Servlet都能做到,但是它们却各有所长。JSP更强调应用的外表表达。JSP编译后是"类servlet"。Servlet比较适合作为控制类组件,比如视图控制器等。另外,Servlet还可以作为过滤器、监听器等。Servlet不仅可以动态生成HTML内容,还可以动态生成图形。Servlet和JSP最主要的不同点在于,Servlet的应用逻辑是在Java文件中,并且完全从表示层中的HTML里分离开来。而JSP的情况是Java和HTML可以组合成一个扩展名为.jsp的文件。总而言之,Servlet在项目中作为控制类的组件,并且处理一些后台业务,JSP则作为显示组件。JSP侧重于视图,Servlet主要用于控制逻辑。
9.四种会话跟踪技术
会话作用域 | Servlets | JSP | 页面描述 |
page | 否 | 是 | 代表与一个页面相关的对象和属性。一个页面由一个编译好的 Java servlet 类(可以带有任何的 include 指令,但是没有 include 动作)表示。这既包括 servlet 又包括被编译成 servlet 的 JSP 页面 |
request | 是 | 是 | 代表与 Web 客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个 Web 组件(由于 forward 指令和 include 动作的关系) |
session | 是 | 是 | 代表与用于某个 Web 客户机的一个用户体验相关的对象和属性。一个 Web 会话可以也经常会跨越多个客户机请求 |
application | 是 | 是 | 代表与整个 Web 应用程序相关的对象和属性。这实质上是跨越整个 Web 应用程序,包括多个页面、请求和会话的一个全局作用域 |
10.Servlet执行时一般实现哪几个方法?
Public void init(ServletConfig config)
public ServletConfig getServletConfig()
public String getServletInfo()
public void service(ServletRequest request,ServletResponse response)
public void destroy()
11.url重写有几种方式?
由于cookie可以被人为的禁止,必须有其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。经常被使用的一种技术叫做URL重写,就是把session id直接附加在URL路径的后面,附加方式也有两种,一种是作为URL路径的附加信息,表现形式为
http://...../xxx;jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
另一种是作为查询字符串附加在URL后面,表现形式为http://...../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
这两种方式对于用户来说是没有区别的,只是服务器在解析的时候处理的方式不同,采用第一种方式也有利于把session id的信息和正常程序参数区分开来。为了在整个交互过程中始终保持状态,就必须在每个客户端可能请求的路径后面都包含这个session id。
12.在jsp中引用使用<jsp:useBean id=" " ...scope=" "/>来引用javabean.
Ⅰscope的值有哪些,这些值的区别是什么?不同的jsp页面中引用javabean时,id能否相同,如果能相同,对scope的值有什么要求?
scope可以为:application|page|session|requeat这个东西就是指定ID的有效范围。如果scope=page,那么useBean的有用范围就只能在page内有效,到了session|application|requeat就无效了。可以指定scope属性,使得Bean不只是与当前页面建立单关联。如果共享了Bean,获取对现有Bean的引用就很有用,因此jsp;useBean操作表示公当不存在具有相同id和scope的对象时才实例化一个新对象。这样就可以节约资源。
二、问答题
1.JSP的内置对象及方法
Request表示HttpServletRequest对象。它包含了有关浏览器请求的信息,并且提供了几个用于获取cookie,header, 和session数据的有用的方法。
Response表示HttpServletResponse对象,并提供了几个用于设置送回 浏览器的响应的方法(如cookies,头信息等)
out对象是javax.jsp.JspWriter的一个实例,并提供了几个方法使你能用于向浏览器回送输出结果。
pageContext表示一个javax.servlet.jsp.PageContext对象。它是用于方便存取各种范围的名字空间、servlet相关的对象的API,并且包装了通用的servlet相关功能的方法。
Session表示一个请求的javax.servlet.http.HttpSession对象。Session可以存贮用户的状态信息
applicaton 表示一个javax.servlet.ServletContext对象。这有助于查找有关servlet引擎和servlet环境的信息
config表示一个javax.servlet.ServletConfig对象。该对象用于存取servlet实例的初始化参数。
Page表示从该页面产生的一个servlet实例
2.JSP的常用指令
<%@ page
language="scriptingLanguage": 主要指定JSP Container要用什么语言来编译JSP 网页。JSP 2.0 规范中指出,目前只可以使用Java语言,不过未来不排除增加其他语言,如C、C++、Perl 等等。默认值为Java
extends = "className": 主要定义此JSP 网页产生的Servlet 是继承哪个父类
import = "importList":主要定义此JSP 网页可以使用哪些Java API
session = "true | false": 决定此JSP 网页是否可以使用session 对象。默认值为true
buffer = "none | size in kb":决定输出流 (output stream)是否有缓冲区。默认值为8KB 的缓冲区
autoFlush = "true | false":决定输出流的缓冲区是否要自动清除,缓冲区满了会产生异常 (Exception)。默认值为 true
isThreadSafe = "true |false": 主要是告诉JSP Container,此JSP 网页能处理超过一个以上的请求。默认值为 true,如果此值设为 false,SingleThreadModel 将会被使用。SingleThreadModel 在Servlet 2.4 中已经声明不赞成使用(deprecate)
info = "text": 主要表示此JSP 网页的相关信息
errorPage = "error_url":表示如果发生异常错误时,网页会被重新指向那一个URL
isErrorPage = "true | false":表示此JSP Page 是否为处理异常错误的网页
contentType = "ctinfo":表示MIME 类型和JSP 网页的编码方式
pageEncoding = "ctinfo":表示JSP 网页的编码方式
isELIgnored = "true | false":表示是否在此JSP 网页中执行或忽略EL 表达式。如果为true 时,JSP Container将忽略EL表达式;反之为false时,EL 表达式将会被执行
注意:只有import 这个属性可以重复设定,其他则否。
%>
<%@include file="filename"%>
<%@taglib prefix="c"uri=" http://……"%>
3.Request对象的主要方法:
setAttribute(String name,Object):设置名字为name的request的参数值
getAttribute(String name):返回由name指定的属性值
getAttributeNames():返回request对象所有属性的名字集合,结果是一个枚举的实例
getCookies():返回客户端的所有Cookie对象,结果是一个Cookie数组
getCharacterEncoding():返回请求中的字符编码方式
getContentLength():返回请求的Body的长度
getHeader(String name):获得HTTP协议定义的文件头信息
getHeaders(String name):返回指定名字的request Header的所有值,结果是一个枚举的实例
getHeaderNames():返回所以request Header的名字,结果是一个枚举的实例
getInputStream():返回请求的输入流,用于获得请求中的数据
getMethod():获得客户端向服务器端传送数据的方法
getParameter(String name):获得客户端传送给服务器端的有name指定的参数值
getParameterNames():获得客户端传送给服务器端的所有参数的名字,结果是一个枚举的实例
getParameterValues(String name):获得有name指定的参数的所有值
getProtocol():获取客户端向服务器端传送数据所依据的协议名称
getQueryString():获得查询字符串
getRequestURI():获取发出请求字符串的客户端地址
getRemoteAddr():获取客户端的IP地址
getRemoteHost():获取客户端的名字
getSession([Boolean create]):返回和请求相关Session
getServerName():获取服务器的名字
getServletPath():获取客户端所请求的脚本文件的路径
getServerPort():获取服务器的端口号
removeAttribute(String name):删除请求中的一个属性
4.jsp有哪些动作?作用分别是什么?
JSP共有以下6种基本动作
jsp:include:在页面被请求的时候引入一个文件。
Jsp:useBean:寻找或者实例化一个JavaBean。
Jsp:setProperty:设置JavaBean的属性。
Jsp:getProperty:输出某个JavaBean的属性。
Jsp:forward:把请求转到一个新的页面。
Jsp:plugin:使您能插入所需的特定的浏览器的OBJECT或EMBED元素来指定浏览器运行一个JAVA Applet所需的插件。根据浏览器类型为Java插件生成OBJECT或EMBED标记。
<jsp:plugintype="bean|applet" code="classFileName"codebase="classFileDirectoryName"
[ name="instanceName" ]
[ archive="URIToArchive, ..." ]
[ align="bottom|top|middle|left|right" ]
[ height="displayPixels" ]
[ width="displayPixels" ]
[ hspace="leftRightPixels" ]
[ vspace="topBottomPixels" ]
[ jreversion="JREVersionNumber | 1.1" ]
[ nspluginurl="URLToPlugin" ]
[ iepluginurl="URLToPlugin" ] >
[ <jsp:params>
[ <jsp:param name="parameterName"
value="{parameterValue | <%= expression %>}" /> ]+
</jsp:params> ]
[ <jsp:fallback> text messagefor user </jsp:fallback> ]
</jsp:plugin>
举例:
<jsp:plugin type=appletcode="Molecule.class" codebase="/html">
<jsp:params>
<jsp:param name="molecule"value="molecules/benzene.mol" />
</jsp:params>
<jsp:fallback>
<p>Unable to load applet</p>
</jsp:fallback>
</jsp:plugin>
5.过滤器 监听 servlet 三者的区别和实际中主要的应用场景
过滤器(Filter)
作为过滤器,在Servlet作为过滤器使用时,它可以对客户的请求进行过滤处理,当它处理完成后,它会交给下一个过滤器处理,就这样,客户的请求在过滤链里一个个处理,直到请求发送到目标。举个例子,某个网站里有提交"修改的注册信息"的网页,当用户填写完成修改信息并提交后,服务端在进行真正的处理时需要做两个处理:客户端的会话是否有效;对提交的数据进行统一的编码,比如GB2312。这两个处理可以在由两个过滤器组成的过滤链里进行处理。当过滤器处理成功后,把提交的数据发送到最终目标;如果过滤器处理不成功(比如客户端的会话无效),它将把视图派发到指定的错误页面。可以看出,过滤器就像一扇门,客户端要和服务端的某个目标交互,必须通过这扇门。
过滤器是用于过滤Servlet的请求和响应,过滤器是存在于请求和被请求资源之间的。
过滤器就像当于一个中间件,请求要经过过滤器,然后过滤器才去调用Servlet,Servlet的响应也会被过滤器截获并作相应的处理。
Filter是一个接口,要写一个自己的Filter就只能实现Filter接口。
Filter也有自己的生命周期,他的生命周期和Servlet比较相似,也是会先调用init()方法,然后再调用核心的处理过滤的方法doFilter(),这个方法中可定义过滤规则,然后是destory()方法销毁Filter对象。
dofilter(ServletRequestrequest,ServletResponse response,FilterChain chain)
这个是过滤的核心方法,FilterChain的方法doFilter(ServletRequest request, ServletResponse response)也就是过滤后的请求调用资源的方法,如果不写这个方法,也就不会去调用相应的资源。
Filter的配置
Filter的配置和Servlet相似。
<filter>
<filter-name>SessionFilter</filter-name>
<filter-class>alan.filter.SessionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SessionFilter</filter-name>
<url-pattern>/protected/*</url-pattern>
<!--这里的url-pattern就是要过滤的Servlet的url-pattern-->
<dispatcher>request</dispatcher>
<dispatcher>forward</dispatcher>
<dispatcher>include</dispatcher>
<!--上面的三个是过滤的范围-->
</filter-mapping>
CharArrayWriter类,是一个将数据保存在字符数组中的输出流,我们可以使用它来构造一个PrintWriter对象,也就实现了向内存输出。CharArrayWriter类的toString()和toCharArray()方法就可以取得写入内存中的数据。
注意:CharArrayWriter类是一个不会真正输出的类,他的write()方法只会将内容写入字符数组,而且这个字符数组是会自动增长的。
例子:两个JSP页面,前一个页面用户输入一些信息然后提交,后一个页面显示用户提交的信息。在提交信息后,要经过两个过滤器的处理,一个检查用户是否登录,一个把用户的提交信息用GB2312进行重新编码。
开发一个Filter,这个Filter需要实现Filter接口,Filter接口定义了以下的方法:
destroy() //由Web容器调用,销毁此Filter
init(FilterConfig filterConfig) ///由Web容器调用,初始化此Filter
doFilter(ServletRequest request, ServletResponseresponse,
FilterChain chain)//具体过滤处理代码
对提交信息用GB2312进行重新编码的Filter:
1 // ==================== ProgramDiscription =====================
2 // 程序名称:示例14-7 : EncodingFilter .java
3 // 程序目的:学习使用编码过滤器
4 //==========================================================
5 importjavax.servlet.FilterChain;
6 import javax.servlet.ServletRequest;
7 importjavax.servlet.ServletResponse;
8 import java.io.IOException;
9 import javax.servlet.Filter;
10 importjavax.servlet.http.HttpServletRequest;
11 importjavax.servlet.http.HttpServletResponse;
12 importjavax.servlet.ServletException;
13 import javax.servlet.FilterConfig;
15 public class EncodingFilterimplements Filter
16 {
18 private StringtargetEncoding = "gb2312";
19 protectedFilterConfig filterConfig;
21 public void init(FilterConfigconfig) throws ServletException {
22 this.filterConfig = config;
23 this.targetEncoding =config.getInitParameter("encoding");
24 }
27 public void doFilter(ServletRequest srequest, ServletResponse sresponse,FilterChainchain)
28 throws IOException, ServletException{
30 HttpServletRequest request =(HttpServletRequest)srequest;
31 request.setCharacterEncoding(targetEncoding);//把请求用指定的方式编码
32 // 把处理发送到下一个过滤器
33 chain.doFilter(srequest,sresponse);
34 }
36 public voiddestroy()
37 {
38 this.filterConfig=null;
39 }
41 public void setFilterConfig(final FilterConfig filterConfig)
42 {
43 this.filterConfig=filterConfig;
44 }
45 }
【程序注解】
正如前面所说,EncodingFilter的目的是把客户端的请求用指定的方式编码,具体的处理在request.setCharacterEncoding(targetEncoding)完成了。LoginFilter判断用户在进入目标之前是否登录,if((isLog!=null)&&((isLog.equals("true"))||(isLog=="true")))将检查用户是否登录,如果已登录,那么把视图让过滤链继续处理,如果没有登录,把视图派发到登录页面,过滤链处理结束。
下面我们来看怎么在web.xml里配置这两个过滤器,代码如下所示:
1 // ==================== ProgramDiscription =====================
2 // 程序名称:示例14-7 : EncodingFilter .java
3 // 程序目的:学习使用编码过滤器
4 //==========================================================
5 importjavax.servlet.FilterChain;
6 importjavax.servlet.ServletRequest;
7 importjavax.servlet.ServletResponse;
8 import java.io.IOException;
9 import javax.servlet.Filter;
10 importjavax.servlet.http.HttpServletRequest;
11 importjavax.servlet.http.HttpServletResponse;
12 importjavax.servlet.ServletException;
13 importjavax.servlet.FilterConfig;14
15 public class EncodingFilterimplements Filter
16 {
18 private StringtargetEncoding = "gb2312";
19 protectedFilterConfig filterConfig;
21 public voidinit(FilterConfig config) throws ServletException {
22 this.filterConfig = config;
23 this.targetEncoding =config.getInitParameter("encoding");
24 }
27 public void doFilter(ServletRequest srequest,ServletResponse sresponse,FilterChain chain)
28 throws IOException, ServletException{
30 HttpServletRequest request = (HttpServletRequest)srequest;
31 request.setCharacterEncoding(targetEncoding);//把请求用指定的方式编码
32 // 把处理发送到下一个过滤器
33 chain.doFilter(srequest,sresponse);
34 }
36 public voiddestroy()
37 {
38 this.filterConfig=null;
39 }
40
41 public void setFilterConfig(final FilterConfig filterConfig)
42 {
43 this.filterConfig=filterConfig;
44 }
45 }
【程序注解】
可以看出,配置Filter时,首先指定Filter的名字和Filter的实现类,如果有必要,还要配置Filter的初始参数;然后为Filter做映射,这个映射指定了需要过滤的目标(JSP、Servlet)。在上面的例子中,指定了EncodingFilter 为所有的JSP和Servlet做过滤,LoginFilter为target.jsp做过滤。这样,当客户请求target.jsp时,首先要经过EncodingFilter的处理,然后经过LoginFilter的处理,最后才把请求传递给target.jsp。
【运行程序】
把程序部署到Web服务器里(比如Tomcat),然后启动Web服务器,在浏览器里输入以下URL(根据具体请求改变URL):http://127.0.0.1:8080/ch14/target.jsp
那么Filter将会把视图派发到:http://127.0.0.1:8080/ch14/init.jsp
在init.jsp里,我们使用:
<%session.setAttribute("isLog","true");%>
来设置用户已经登录(这里是简化的,在实际项目中,可能要经过验证处理)。在init.jsp里,可以提交一些中文的信息。由于提交的信息被EncodingFilter使用GB2312统一编码了,故在target.jsp里能够正确显示中文。您可以做一个试验,把web.xml改为:
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/nothing</url-pattern>
</filter-mapping>
然后重新启动Web服务器。那么在target.jsp里,中文将不能正确显示。
监听器
Listener是Servlet的监听器,它可以监听客户端的请求、服务端的操作等。通过监听器,可以自动激发一些操作,比如监听在线的用户的数量。当增加一个HttpSession时,就激发sessionCreated(HttpSessionEventse)方法,这样就可以给在线人数加1。
以下是3个Listener接口。
ServletContextAttributeListener:监听对ServletContext属性的操作,比如增加、删除、修改属性
ServletRequestListener:
HttpSessionListener:监听HttpSession的操作。当创建一个Session时,激发session Created(HttpSessionEventse)方法;当销毁一个Session时,激发sessionDestroyed(HttpSessionEvent se)方法
HttpSessionAttributeListener:监听HttpSession中的属性的操作。当在Session增加一个属性时,激发attributeAdded(HttpSessionBindingEvent se) 方法;当在Session删除一个属性时,激发attributeRemoved(HttpSessionBindingEventse)方法;当在Session属性被重新设置时,激发attributeReplaced(HttpSessionBindingEventse) 方法
ServletContextListener:监听ServletContext。当创建ServletContext时,激发contextInitialized(ServletContextEventsce)方法;当销毁ServletContext时,激发contextDestroyed(ServletContextEventsce)方法
这三个监听器接口,分别监听Servlet中3种比较重要的对象的创建和销毁。这三个接口中分别有监听该对象创建和销毁事件的方法,服务器本身就是事件源。
listener的配置
<listener>
<listener-class>alan.servlet.listener.AlanContextListener</listener-class>
<!--listener-class也就是实现Listener接口的类-->
</listener>
Servlet中的重要对象(只针对应用)
| 数量 | 生命周期 | 是否线程安全 |
ServletContext | 1 | 全局的。只有在应用关闭时才销毁 | 不安全。需要加同步访问 |
HttpSession | 和用户的数量相同 | 局部的。只在有效时间内存在 | 不安全。需要加同步访问 |
ServletRequest | 多个 | 局部的。只在service()和doGet()、doPost()中存在 | 线程安全 |
下面我们开发一个具体的例子,这个监听器能够统计在线的人数。在ServletContext初始化和销毁时,在服务器控制台打印对应的信息。当ServletContext里的属性增加、改变、删除时,在服务器控制台打印对应的信息。
要获得以上的功能,监听器必须实现以下3个接口:
HttpSessionListener
ServletContextListener
ServletContextAttributeListener
//==================== Program Discription =====================
2 // 程序名称:示例14-9 : EncodingFilter .java
3 // 程序目的:学习使用监听器
4 // ==============================================================
5 import javax.servlet.http.*;
6 import javax.servlet.*;
8 public class OnLineCountListener implements HttpSessionListener,
ServletContextListener,ServletContextAttributeListener
9 {
10 private int count;
11 private ServletContext context = null;
13 public OnLineCountListener()
14 {
15 count=0;
16 //setContext();
17 }
18 //创建一个session时激发
19 public void sessionCreated(HttpSessionEvent se)
20 {
21 count++;
22 setContext(se);
24 }
25 //当一个session失效时激发
26 public void sessionDestroyed(HttpSessionEvent se)
27 {
28 count--;
29 setContext(se);
30 }
31 //设置context的属性,它将激发attributeReplaced或attributeAdded方法
32 public void setContext(HttpSessionEvent se)
33 {
34 se.getSession().getServletContext().setAttribute("onLine",newInteger(count));
35 }
36 //增加一个新的属性时激发
37 public void attributeAdded(ServletContextAttributeEvent event) {
39 log("attributeAdded('" + event.getName() + "', '" +
40 event.getValue() + "')");
42 }
44 //删除一个新的属性时激发
45 public void attributeRemoved(ServletContextAttributeEventevent) {
47 log("attributeRemoved('" + event.getName() + "', '" +
48 event.getValue() + "')");
50 }
52 //属性被替代时激发
53 public void attributeReplaced(ServletContextAttributeEventevent) {
55 log("attributeReplaced('" + event.getName() + "', '" +
56 event.getValue() + "')");
57 }
58 //context删除时激发
59 public void contextDestroyed(ServletContextEventevent) {
61 log("contextDestroyed()");
62 this.context = null;
64 }
66 //context初始化时激发
67 public void contextInitialized(ServletContextEvent event) {
69 this.context = event.getServletContext();
70 log("contextInitialized()");
72 }
73 private void log(String message) {
75 System.out.println("ContextListener: " + message);
76 }
77 }
【程序注解】
在OnLineCountListener里,用count代表当前在线的人数,OnLineCountListener将在Web服务器启动时自动执行。当OnLineCountListener构造好后,把count设置为0。每增加一个Session,OnLineCountListener会自动调用sessionCreated(HttpSessionEvent se)方法;每销毁一个Session,OnLineCountListener会自动调用sessionDestroyed(HttpSessionEventse)方法。当调用sessionCreated(HttpSessionEvent se)方法时,说明又有一个客户在请求,此时使在线的人数(count)加1,并且把count写到ServletContext中。ServletContext的信息是所有客户端共享的,这样,每个客户端都可以读取到当前在线的人数。
为了使监听器生效,需要在web.xml里进行配置,如下所示:
<listener>
<listener-class>OnLineCountListener</listener-class>
</listener>
测试程序:
<%@ pagecontentType="text/html;charset=gb2312" %>
目前在线人数:
<font color=red><%=getServletContext().getAttribute("onLine")%></font><br>
getServletContext().getAttribute("onLine")获得了count的具体值。客户端调用
退出会话:
<form action="exit.jsp"method=post>
<inputtype=submit value="exit">
</form>
客户端调用:
<%session.invalidate() ;%>
使Session失效,这样监听器就会使count减1。
web.xml做好以上的配置,把OnLineCountListener放在WEB-INF/class目录下,启动Web服务器,在浏览器里输入以下URL(根据具体情况不同):http://127.0.0.1:8080/ch14/listener.jsp
浏览器将会打印目前在线人数。在服务器端有以下输出:
…
ContextListener: contextInitialized()
ContextListener: attributeReplaced('org.apache.
catalina.WELCOME_FILES', '[Ljava.lang.String;@1d98a')
…
ContextListener: attributeAdded('onLine', '1')
ContextListener: attributeReplaced('onLine', '1')
ContextListener: attributeReplaced('onLine', '0')
ContextListener: attributeReplaced('onLine', '1')
ContextListener: attributeReplaced('onLine', '2')
三、程序题
1.现在输入n个数字,以逗号,分开;然后可选择升或者降序排序;按提交键就在另一页面显示按什么排序,结果为,提供reset
import java.util.*;
public class bycomma{
public static String[] splitStringByComma(String source){
if(source==null||source.trim().equals(""))
return null;
StringTokenizer commaToker = newStringTokenizer(source,",");
String[] result = newString[commaToker.countTokens()];
int i=0;
while(commaToker.hasMoreTokens()){
result[i] = commaToker.nextToken();
i++;
}
return result;
}
public static void main(String args[]){
String[] s = splitStringByComma("5,8,7,4,3,9,1");
int[] ii = new int[s.length];
for(int I = 0;i<s.length;i++){
ii[i] =Integer.parseInt(s[i]);
}
Arrays.sort(ii);
//asc
for(int i=0;i<s.length;i++){
System.out.println(ii[i]);
}
//desc
for(inti=(s.length-1);i>=0;i--){
System.out.println(ii[i]);
}
}
}
2.我们在web应用开发过程中经常遇到输出某种编码的字符,如iso8859-1等,如何输出一个某种编码的字符串?
Public Stringtranslate (String str) {
String tempStr = "";
try {
tempStr = newString(str.getBytes("ISO-8859-1"), "GBK");
tempStr = tempStr.trim();
}
catch (Exception e) {
System.err.println(e.getMessage());
}
return tempStr;
}
3. Session中存储一个String变量,变量名称为studentname,写出在jsp中如何得到这个session变量的值的语句。
<%
String studentName = session.getAttribute(“studentname”) == null? “” : (String)session.getAttribute(“studentname”);
%>
4.在Web应用中,各举POST请求和GET请求应用场景的一个例子
<form name=” …” method=”get” action=”…”></form>
<form name=” …” method=”post”action=” …”></form>
5.编写一个servlet。servlet的功能要求:记录访问该servlet的客户端的ip和访问时间,把记录写入client_ip.log文件。 client_ip.log里的格式大致如下:
9:362005-4-8 192.168.0.1
9:362005-4-8 127.0.0.1
package com.itjob.st;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyServlet extends HttpServlet {
private File clientIp;
private FileOutputStreamfos;
/**
* Constructor of the object.
*/
public MyServlet() {
super();
}
/**
* Destruction of the servlet. <br>
*/
public void destroy() {
super.destroy(); //Just puts "destroy" string in log
// Put your code here
}
public voidservice(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponseresp) throws javax.servlet.ServletException, java.io.IOException {
openFileOutputStream();
String clientIp = req.getRemoteAddr();
SimpleDateFormat sdf =new SimpleDateFormat("HH:mm yyyy-MM-dd");
Date date = newDate();
String currDate =sdf.format(date);
String clientIpLog =clientIp + " " + currDate;
this.fos.write(clientIpLog.getBytes());
this.fos.flush();
closeFileOutputStream();
}
/**
* The doGet method of the servlet. <br>
*
* This method is called when a form has itstag value method equals to get.
*
* @param request the request send by theclient to the server
* @param response the response send by theserver to the client
* @throws ServletException if an erroroccurred
* @throws IOException if an error occurred
*/
public voiddoGet(HttpServletRequest request, HttpServletResponse response)
throwsServletException, IOException {
response.setContentType("text/html");
PrintWriter out =response.getWriter();
out
.println("<!DOCTYPEHTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
out.println("<HTML>");
out.println(" <HEAD><TITLE>AServlet</TITLE></HEAD>");
out.println(" <BODY>");
out.print(" This is ");
out.print(this.getClass());
out.println(",using the GET method");
out.println(" </BODY>");
out.println("</HTML>");
out.flush();
out.close();
}
/**
* The doPost method of the servlet. <br>
*
* This method is called when a form has itstag value method equals to post.
*
* @param request the request send by theclient to the server
* @param response the response send by theserver to the client
* @throws ServletException if an erroroccurred
* @throws IOException if an error occurred
*/
public void doPost(HttpServletRequestrequest, HttpServletResponse response)
throwsServletException, IOException {
response.setContentType("text/html");
PrintWriter out =response.getWriter();
out
.println("<!DOCTYPEHTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
out.println("<HTML>");
out.println(" <HEAD><TITLE>AServlet</TITLE></HEAD>");
out.println(" <BODY>");
out.print(" This is ");
out.print(this.getClass());
out.println(",using the POST method");
out.println(" </BODY>");
out.println("</HTML>");
out.flush();
out.close();
}
/**
* Initialization of the servlet. <br>
*
* @throws ServletException if an error occure
*/
public void init() throwsServletException {
clientIp = new File("D:\\client_ip.log");
}
private voidopenFileOutputStream() {
try {
fos = newFileOutputStream(clientIp);
}
catch(FileNotFoundExceptionfnfe) {
fnfe.printStackTrace();
}
}
private voidcloseFileOutputStream() {
try {
fos.close();
fos = null;
}
catch(IOExceptionfnfe) {
fnfe.printStackTrace();
}
}
}