张慧的博客

张慧的博客

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  45 Posts :: 0 Stories :: 24 Comments :: 0 Trackbacks

置顶随笔 #

对于Servlet的生命周期,主要围绕着init()、service()和destroy()三个回调方法展开的。什么是回调方法?通俗的说就是这三个方法定义完后由web容器负责在特定时间(需要的时候)调用。

Servlet容器,如Tomcat一般会在用户第一次请求Servlet的时候实例化该对象。另一种情况是在服务器启动时立即加载并实例化,但这需要在web.xml文件中对Servlet进行load-on-startup的配置。

当第一个用户请求到来时,服务器根据部署描述符找到所访问的Servlet类,并查找当前容器,发现没有此类的实例,说明是第一次访问此Servlet,所以容器开始加载Servlet,并实例化此对象,实例化之后会立即调用init()方法,而且init()方法由始至终只被调用一次,所以比较适合进行对象的初始化工作,比如读取配置文件,初始化属性等。当调用完init()方法后,Servlet实例处于ready状态,这时开始调用其service()方法,并等待着下一次请求的到来。

service()方法是服务方法,只要再有请求到来,服务器都会产生一个新的线程,调用service()方法,进行相关的服务。service()方法会检查HTTP请求的类型(GET、POST等),来相应的调用doGet()、doPost()等。GET请求起因于正常URL请求,或没有指定Method的HTML表单;Post请求起因于将Method定为Post的HTML表单。从图中可见,service()方法可以被调用多次,因为之后用户每一次访问该Servlet,都会触发服务器调用service()方法。

如果实例长时间未被访问,或者web服务器关闭,则容器会负责调用destroy()方法,该方法可以将一些资源释放,destroy()方法也是只被调用一次,之后Servlet实例将被JVM回收空间。这样通过init()-->service()-->destroy(),完成了Servlet的一个生命周期。

上图是UML中的状态图,形象的描述了一个对象在不同事件触发时,其内部状态的变更过程。实心的圆圈代表初始状态,代表Servlet刚刚被实例化:中间写Ready的椭圆形代表就绪状态,最下面的圆圈代表结束,这时对象已被JVM的GC回收。图中的另外一个分支,代表在执行init()操作时抛出了异常,造成无法调用service()方法,生命周期提前终止。

posted @ 2012-07-08 23:33 张慧 阅读(1411) | 评论 (0)编辑 收藏

这是在一个opensource项目中看到的获取访问者ip的方法: 
/**
      * 获取访问者IP
      * 
      * 在一般情况下使用Request.getRemoteAddr()即可,但是经过nginx等反向代理软件后,这个方法会失效。
      * 
      * 本方法先从Header中获取X-Real-IP,如果不存在再从X-Forwarded-For获得第一个IP(用,分割),
      * 如果还不存在则调用Request .getRemoteAddr()。
      * 
      * 
@param request
      * 
@return
      
*/
     public static String getIpAddr(HttpServletRequest request) {
         String ip = request.getHeader("X-Real-IP");
         if (!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
             return ip;
         }
         ip = request.getHeader("X-Forwarded-For");
         if (!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
             // 多次反向代理后会有多个IP值,第一个为真实IP。
             int index = ip.indexOf(',');
             if (index != -1) {
                 return ip.substring(0, index);
             } else {
                 return ip;
             }
         } else {
             return request.getRemoteAddr();
         }
     }
posted @ 2012-07-08 23:31 张慧 阅读(2963) | 评论 (0)编辑 收藏

在java中经常需要获取一些系统信息,如系统的资源空间等。下面就是一些Runtime的应用:


public static void main(String[] a){
         Runtime runtime 
= Runtime.getRuntime();
         
long freeMemoery = runtime.freeMemory();
         
long totalMemory = runtime.totalMemory();
         
long usedMemory = totalMemory - freeMemoery;
         
long maxMemory = runtime.maxMemory();
         
long useableMemory = maxMemory - totalMemory + freeMemoery;
         
         System.out.println(
"当前时间:"+runtime);
         System.out.println(
"系统闲置空间:"+freeMemoery);
         System.out.println(
"系统总空间:"+totalMemory);
         System.out.println(
"系统被用的空间:"+usedMemory);
         System.out.println(
"系统最大空间:"+maxMemory);
         System.out.println(
"系统可用空间:"+useableMemory);
     }

运行效果:


当前时间:java.lang.Runtime@c3c749
 系统闲置空间:
4873672
 系统总空间:
5177344
 系统被用的空间:
303672
 系统最大空间:
66650112
 系统可用空间:
66346440

 

posted @ 2012-07-08 23:30 张慧 阅读(736) | 评论 (0)编辑 收藏