ServletContext与Web应用范围

来源:互联网 发布:python sample 编辑:程序博客网 时间:2024/05/16 12:22

在Servlet容器启动一个Web应用的时候,会为它创建唯一的ServletContext对象,终止应用的时候,就会销毁这个对象。同生共死,他俩的生命周期的同步的。

以下内容为源码的注释内容,自己翻译理解下。

Defines a set of methods that a servlet uses to communicate with its servlet container, for example, to get the MIME type of a file, dispatch requests, or write to a log file.
定义一系列servlet可以使用来和它的容器进行通信的方法,例如,获得文件的MEME类型,传递请求,或者往日志的文件写入。

There is one context per “web application” per Java Virtual Machine. (A “web application” is a collection of servlets and content installed under a specific subset of the server’s URL namespace such as “/catalog”and possibly installed via a“ .war” file.)
每一个Web应用对应一个虚拟机,对应一个context对象。Web应用是多个servlet的集合,这些servlet由服务器具体的URL 甚至文件 子集配置。(个人理解就是映射吧)

In the case of a web application marked “distributed” in its deployment descriptor, there will be one context instance for each virtual machine. In this situation, the context cannot be used as a location to share global information (because the information won’t be truly global). Use an external resource like a database instead.
当Web应用在部署的时候被标记为分布式时,每个虚拟机只有一个context实例,此时context不能共享全局的信息。可以用数据库来替换。

The ServletContext object is contained within the ServletConfig object, which the Web server provides the servlet when the servlet is initialized.
ServletContext对象中包含有ServletConfig对象,这个对象包含了容器提供的初始化的一些数据和信息

要想在Web应用生命周期内在组件之间进行数据共享,直接将共享的对象绑定到ServletContext对象,其实就是关联。为此要提供一对属性名和属性值,使用这几个方法增加获取和移除共享数据。

removeAttribute(String name)

getAttribute(String name)

setAttribute(String name,Object object)

注意:别和setParameter()搞混淆。从名字看,一个是属性值,后者是参数,也就是浏览器请求资源时附加的参数,get和post方式中参数位置不同,数据量的大小限制不同。
来个共享数据的小例子,统计网站的访问次数。在Web应用的生命周期里,这个Count对象将会一直存在。
计数器:

package com.neo.domain;/** * @author neo */public class Counter {    private int count;    public Counter(){        this(0);    }    public Counter(int count){        this.count = count;    }    public int getCount() {        return count;    }    public void setCount(int count) {        this.count = count;    }    public void add(int step){        count += step;    }}

计数的servlet

package com.neo.controller;import java.io.IOException;import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.neo.domain.Counter;@WebServlet(urlPatterns = { "/count" })public class CounterServlet extends HttpServlet {    private static final long serialVersionUID = 1L;    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        response.setCharacterEncoding("utf-8");        ServletContext context = getServletContext();        Counter counter = (Counter) context.getAttribute("counter");        if(null == counter){            counter = new Counter(0);            context.setAttribute("counter", counter);        }           counter.add(1);        context.getRequestDispatcher("/count.jsp").forward(request, response);    }    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        doGet(request, response);    }}

计数信息将会以图片的形式发送到客户端,表示Servlet还能生成动态图像,用了java的图形绘制的相关类。

package com.neo.controller;import java.awt.Color;import java.awt.Font;import java.awt.Graphics;import java.awt.image.BufferedImage;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.ServletOutputStream;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.sun.image.codec.jpeg.JPEGCodec;import com.sun.image.codec.jpeg.JPEGImageEncoder;@WebServlet("/image")public class ImageServlet extends HttpServlet {    private static final long serialVersionUID = 1L;    //字体    private Font font = new Font("Courier", Font.BOLD, 12);    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        response.setCharacterEncoding("utf-8");        //得到待显示的数字        String count = request.getParameter("count");        //数字的长度        int len = count.length();        //设置响应正文的类型        response.setContentType("image/jpeg");        ServletOutputStream out = response.getOutputStream();        //创建一个位于缓存中的图像,长为11*len,高为16        BufferedImage image = new BufferedImage(11 * len, 16, BufferedImage.TYPE_INT_RGB);        //得到画笔        Graphics g = image.getGraphics();        g.setColor(Color.black);        //画一个黑色的矩形,长度为11*len,高度为16        g.fillRect(0, 0, 11*len, 16);        g.setColor(Color.white);        g.setFont(font);        char c;        for(int i=0; i < len; i++){            c = count.charAt(i);            //写白色的数字            g.drawString(c + "", i*11+1, 12);            //画一条白色的竖线            g.drawLine( ( i + 1) * 11, 0, (i+1)*11-1, 16);        }        //输出JPEG格式的图片        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);        //对图像进行JPEG格式编码,并且利用out输出图像数据        encoder.encode(image);        out.close();    }    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        doGet(request, response);    }}

将共享的信息转发到jsp进行显示,最最简单的将业务逻辑和界面分开。当然啦,最好是界面里不要有java代码,用标签或者是EL表达式来替换。这里可以直接用jsp的9个隐式对象。

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%><%@ page import="com.neo.domain.Counter" %><%    ServletContext context = getServletContext();    Counter counter = (Counter) context.getAttribute("counter");%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><title>Counter's jsp</title></head><body>    欢迎光临本站,您是第<img src='image?count=${counter.count}' />位访问者。</body></html>

访问多次,每次增加1。
这里写图片描述
打开多个窗口,显示结果在之前的结果上加1。
将tomcat关闭或者在控制台将Web应用关闭,再启动,将看到从1开始计数。

参考书籍:孙卫琴老师的《Tomcat与Java Web开发技术详解》这本书很好

0 0
原创粉丝点击