您的位置:首页 > 其它

ServletContext与Web应用范围

2016-04-20 18:13 423 查看
在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开发技术详解》这本书很好
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: