Java琐碎小知识(四)


1、Servlet 应用程序框架
Servlet本质上就是一个Java程序,Java应用程序有一个或者多个Servlet组成。Servlet应用程序在Servlet容器(比如tomcat)中运行,Servlet容器也叫Servlet引擎,它把用户的请求传递给Servlet应用程序,把Servlet响应传递给用户。
2、Servlet
所有的Servlet必须直接或间接实现javax.servlet.Servlet接口,其定义了五个方法:
init(ServletConfig config):只有在首次请求Servlet时,Servlet容器才会调用这个方法。调用该方法时,Servlet容器会传递一个ServletConfig,一般来说,将这个ServletConfig赋值给一个类级变量,这样就可以从Servlet类中其他地方使用这个对象。
service(ServletRequest req,ServletResponse res):除第一次请求Servlet时,Servlet容器先调用init方法后在调用service,其他每次请求Servlet都会调用service方法。Servlet容器会传递参数中来两个对象,该方法是包含处理客户请求的实现。
destroy():Servlet即将销毁时,容器调用这个方法。当卸载应用程序或关闭Servlet容器时,Servlet容器就会销毁Servlet。(一般这个方法包含清除代码)
getServletInfo():这个方法返回Servlet的描述,可以返回任何可能有用的字符串,甚至是null。
getServletConfig():这个返回由Servlet容器传递给init方法的ServletConfig对象。但是这个样做就是需要init中把ServletConfig传递的对象赋值到该类中。
在这五个方法中,前三个init、service、destroy为生命周期方法,后两个为非生命周期方法。
**Servlet默认是单例多线程,即当多个用户同时请求同一个servlet时,Servlet容器只会实例化一个servlet实例,而对于多个用户的请求则是通过多个线程共享这个servlet实例来实现的,所以这就有线程安全问题了:即在Servlet中不能有类级的域(类变量),因为共享这个servlet实例,所以并发操作得到的域会出现不一致(除非同步该变量),但如果用户提交参数属于线程内的局部变量,则线程是安全的,因为线程之间是相互独立的。当然也可以继承接口使servlet变成单线程模式。
对于Java程序中的多个servlet类文件,当多个用户访问请求不同的servlet时,容器会为每一个servlet(不同的servlet类)创建一个实例,所以一个servlet请求可能有多个servlet实例(调转其他servlet)。**
编写自己的

servlet一般名字以Servlet结尾:MyServlet
对于每一个HTTP请求,Servlet容器都会创建一个ServletRequest和ServletResponse对象,(socket对应TCP连接)。
ServletContext对象表示Servlet应用程序,每个web应用程序只有一个上下文。ServletContext存在的主要原因是共享一个应用程序资源中的共同信息,并使web对象可以动态注册。前者通过将对象存储在ServletContext中的内部map来实现。存储在ServletContext中的对象称为属性,应用程序中的

任何Servlet都可以访问存储这里的对象。
3、反射:
反射是一种创建对象并在运行时操作其调用其成员的高级技术。一般创建对象需要获得实例化类的Class类对象,它是java.lang包的成员之一。每当JVM创建一个对象,它也创建了一个描述这个类对象的class对象。同一个类的所有实例共享一个Class对象,调用对象的getClass方法可以获得这个对象的Class对象(或者比如:int.class)。一旦有了class对象,就可以调用它的newInstance方法来创建对象,但这个适用于对象有默认无参构造器。否则的话就需要使用Constructor来实例化这个类。此外newInstance不能创建数组,需要创建数组,需要java.lang.reflect.Array.
1>创建对象
用反射创建对象有两种方法:
第一种调用Class的newInstance方法,这种方法需要实例化对象有默认的无参构造器:

Class<?>klass =Class.forName(fullQuailifiedName);
Object obj=klass.newInstance();

第二种先从Class对象中获得Constructor对象(方法中传递参数(也可以没有参数)决定确定的构造器),然后调用Constructor对象的newInstance方法:

Class<?> klass=Class.forName("java.lang.StringBuilder");
Constructor<?> constructor=klass.getConstructor(String.class)//其参数为class对象
Object obj=constructor.newInstance("hello world");

2>域操作
通过Class类提供的getField和getDeclareField来分别获取公有域和所有定义的域(包括私有),此外,getFields和java.lang.reflect.Fields方法返回Field对象数组。然后通过getXXX(getInt,getLong……)和setXXX(setBoolean、setChar….):

public class StringPoint {
public int x;//公有域
private int y;///私有域 ,在域的操作中,私有域和公有域是有区别的
public String str1="abababcdab";
public String str2="cdeertgbtyy";
public StringPoint(int x, int y) {
    super();
    this.x = x;
    this.y = y
    }
public int getX() {
    return x;
}
public void setX(int x) {
    this.x = x;
}
public int getY() {
    return y;
}
public void setY(int y) {
    this.y = y;
}
}
================================================
public class FieldTest {

    public static void main(String[] args) throws Exception{
        // TODO Auto-generated method stub

        Class<?>klass=Class.forName("cm.StringPoint");//包含包名的全限定名
        Constructor constructor =   klass.getConstructor(int.class,int.class);
        Object obj=constructor.newInstance(3,2);
        StringPoint sp=(StringPoint)obj;
        System.out.println("x="+sp.getX()+"   y="+sp.getY());

        Field fieldX=klass.Field("x");//可以获取公有域X不可以获取私有域y

        Field fieldY=klass.getDeclaredField("y");//可以获取私有和公有域,且私有域必须有下一行设置才可以获取否则出现非法访问错误
        fieldY.setAccessible(true);
        System.out.println("反射获取X="+fieldX.getInt(obj));
        System.out.println("反射获取Y="+fieldY.getInt(obj));

        fieldX.setInt(obj, 6);
        fieldY.setInt(obj, 7);

        System.out.println("反射set后获取X="+fieldX.getInt(obj));
        System.out.println("反射set获取Y="+fieldY.getInt(obj));

    }
x=3   y=2
反射获取X=3
反射获取Y=2
反射set后获取X=6
反射set获取Y=7

3>方法操作
java.lang.reflect.Method类表示实例或者静态方法。用getMethods和getDeclareedMethods可以获得所有的方法和声明方法。getName返回函数名,getModifiers返回修饰符每个整数进行OR的运算结果:

public class MethodTest {
public static void main(String[] args)throws Exception {
     Class<?> klass=Class.forName("cm.StringPoint");
     Constructor constructor=klass.getConstructor(int.class,int.class);
     Object obj=constructor.newInstance(5,6);
     Method[]methods=klass.getDeclaredMethods();
     for(Method method:methods){
         System.out.println(method.getModifiers()+" "+method.getReturnType()+" "+method.getName()+" "+method.getParameterCount());;
     }
}
}
1 boolean equals 1
1 int hashCode 0
1 int getX 0
1 void setX 1
1 int getY 0
1 void setY 1
//第一列的1 表示public  2表示private 0表示default

3>方法调用
Method类的invoke方法:public Object invoke(Object object, Object… args);
第一个参数表示调用这个方法的类对象,如果被调用的方法是静态的,这个参数可以为空,第二个参数是参数数组,可以是多个参数,如果没有参数可以为空。方法返回值是基本类型的包装对象,int就是integer;void 是null。

public class InvokeTest {

    public static void main(String[] args)throws Exception {
        // TODO Auto-generated method stub
         Class<?> klass=Class.forName("cm.StringPoint");
         Constructor constructor=klass.getConstructor(int.class,int.class);
         Object obj=constructor.newInstance(5,6);
         Method method=klass.getMethod("getX");
         System.out.println(method.invoke(obj));
    }

}
5

4>创建数组
用反射创建任意类型的数组,需要用到java.lang.reflect.Array类的静态方法Object newInstance(Class

package com.lr.reflect;

import java.lang.reflect.Array;

public class CreateArrayTest {
 public static Object createStringArray(int dim){
     Object instance =null;
     try {
        Class<?> klass =Class.forName("java.lang.String");
        instance=Array.newInstance( klass, dim);//有点像list 可以设置数组大小也可以不设置
        for(int i=0;i<dim;i++){
           Array.set(instance, i, "string"+i);
        }
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
     return instance;
 }
 public static Object CreateTwoDimStringArray(int dim1,int dim2)
 {
     Object instance=null;
     try {
        Class<?> klass=Class.forName("java.lang.String");
        instance=Array.newInstance(klass, dim1,dim2);
        for(int i=0;i<dim1;i++)
        {
            Object stringArray=createStringArray(dim2);
            Array.set( instance, i, stringArray);
        }
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
     return instance;
 }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
      int dim=4;
      Object arrayInstance=createStringArray(dim);
      for(int i=0;i<dim;i++)
      {
          Object element=Array.get(arrayInstance,i);
          System.out.println(element);
      }
      System.out.println("======================");
      int dim1=3,dim2=4;
      Object twoDimStringArray=CreateTwoDimStringArray(dim1,dim2);
      for(int i=0;i<Array.getLength(twoDimStringArray);i++){
          Object elements=Array.get(twoDimStringArray, i);
          for(int j=0;j< Array.getLength(elements);j++){
              Object element=Array.get( elements, j);
              System.out.println(element);
          }

      }
    }

}
string0
string1
string2
string3
======================
string0
string1
string2
string3
string0
string1
string2
string3
string0
string1
string2
string3

发表评论

邮箱地址不会被公开。 必填项已用*标注

昵称 *