ServletContext与Web应用范围

在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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 整个Web应用程序范围共享的数据应该放在ServletContext对象中。它代表Web应用程序,与特定用户请求无关,并且可以由应用程序的所有部分访问。可以使用ServletContext对象中的setAttribute()方法将数据存储在其中,使用getAttribute()方法从ServletContext对象中检索数据。与此不同,HttpServletResponse和HttpServletRequest对象是与每个用户请求相关的,而HttpSession对象是与特定会话相关的。它们都不是整个Web应用程序范围共享的数据存储的最佳位置。 ### 回答2: 整个Web应用程序范围共享的数据放在ServletContext中。ServletContext是一个全局的对象,它在整个Web应用程序中都是唯一的。它的作用是在应用程序的所有组件之间共享数据。我们可以通过ServletContext对象来获取和存储应用程序范围内的数据。 在Web应用程序中,一般可以通过以下步骤在ServletContext中存储和获取数据: 1. 存储数据: 通过获取ServletContext对象,使用其setAttribute()方法来存储数据。例如,可以使用如下代码将一个字符串存储在ServletContext中: ```java // 获取ServletContext对象 ServletContext context = request.getServletContext(); // 存储数据 context.setAttribute("dataKey", "Hello, World!"); ``` 2. 获取数据: 通过获取ServletContext对象,使用其getAttribute()方法来获取数据。例如,可以使用如下代码获取之前存储的字符串数据: ```java // 获取ServletContext对象 ServletContext context = request.getServletContext(); // 获取数据 String data = (String) context.getAttribute("dataKey"); ``` 通过ServletContext对象存储的数据可以在整个Web应用程序范围内被所有的组件共享访问。这意味着无论是在Servlet、JSP页面还是在过滤器等其他组件中,都可以通过ServletContext对象来存储和获取共享数据。这对于需要在整个应用程序中共享的数据,例如数据库连接池、应用程序配置参数等,非常有用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值