【JavaWeb回顾—Servlet(3)】

ServletContext对象

ServletContext是一个全局的储存信息的空间,服务器开始就存在,服务器关闭才释放。为了方便大家理解,我们将ServletContext和Cookie、Session做一个简单对比,如下图:
在这里插入图片描述
我们可以把ServletContext当成一个公用的空间,可以被所有的客户访问,如上图,A、B、C三个客户端都可以访问。
WEB容器在启动时,它会为每个Web应用程序都创建一个对应的ServletContext,它代表当前Web应用,并且它被所有客户端共享。

由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。ServletContext对象通常也被称之为context域对象。公共聊天室就会用到它。
当web应用关闭、Tomcat关闭或者Web应用reload的时候,ServletContext对象会被销毁。

ServletContext使用方法

1、ServletContext对象如何得到
this.getServletContext();
this.getServletConfig().getServletContext();
2、你可以把它想象成一张表,这个和Session非常相似:每一行就是一个属性,如下:

姓名(String)值(Object)

添加属性:setAttribute(String name, Object obj);
得到值:getAttribute(String name),这个方法返回Object
删除属性:removeAttribute(String name)

3、生命周期
ServletContext中的属性的生命周期从创建开始,到服务器关闭结束。

一个快速入门的案例:
我们创建Servlet1和Servlet2,分别用于在ServletContext中创建和读取属性:

Servlet1的doGet方法为:

public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    response.setContentType("text/html;charset=utf-8");
    PrintWriter out = response.getWriter();
    // 获取ServletContext对象的引用
    // 第一种方法

    ServletContext servletContext = this.getServletContext();
    // 第二种方法
    // ServletContext servletContext2 = this.getServletConfig().getServletContext();
    servletContext.setAttribute("name", "小明");
    out.println("将 name=小明  写入了ServletContext");
}

Servlet2的doGet方法为:

public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    response.setContentType("text/html;charset=utf-8");
    PrintWriter out = response.getWriter();
    // 取出ServletContext的某个属性
    //1.首先获取到ServletContext
    ServletContext servletContext = this.getServletContext();
    //2.取出属性
    String name = (String)servletContext.getAttribute("name");
    out.println("name="+name);
}

以此访问Servlet1和Servlet2,我们可以分别看到输出如下:
在这里插入图片描述
粗看之下,这个运行结果和Session,Cookie的应用似乎没什么区别,但事实上则完全不一样的。只要不关闭Tomcat或者reload该应用,当我们关闭当前的浏览器,或者是换一个浏览器,比如从360浏览器换到了IE浏览器再次访问Servlet2,我们依然可以看到这个结果!这就是和和Session,Cookie最大的不同了。之所以会造成这种不同,是因为ServletContext存在于服务器内存中的一个公共空间,它可以供所有的用户客户端访问。

ServletContext应用

1、多个Servlet可以通过ServletContext对象来实现数据间的共享
类似于Session,通过ServletContext对象我们也可以实现数据共享,但值得注意的是,Session是只能在一个客户端中共享数据,而ServletContext中的数据是在所有客户端中都可以实现数据共享的。

2、实现Servlet的请求转发
之前我们学过的请求转发是通过request对象的:
request.getRequestDispatcher("/url").forward(request, response);
这里要说明的是,ServletContext也可以实现请求转发:
this.getServletContext().getRequestDispatcher("/url").forward(request, response);
这两个转发效果是一样的。

3、获取Web应用的初始化参数
我们可以用标签为servlet配置初始化参数,然后使用ServletConfig对象获取这些参数,假如有如下的MyServlet,它的配置为:

<servlet>  
    <servlet-name>MyServlet</servlet-name>  
    <servlet-class>com.gavin.servlet.MyServlet</servlet-class>  
    <init-param>  
        <param-name>encoding</param-name>  
        <param-value>utf-8</param-value>  
    </init-param>  
</servlet>  

可以看到它配置了一个初始化参数:encoding=utf-8,那么我们在MyServlet的源代码中需要这样去得到这个参数:

String encoding = this.getServletConfig().getInitParameter("encoding");

注意,上述的参数配置方法只针对一个特定的Servlet有效,我们可以通过ServletContext来获取全局的、整个Web应用的初始化参数,全局的初始化参数是这样配置在web.xml文件中的:

<!-- 如果希望所有的Servlet都可以使用该配置,则必须这么做 -->
<context-param>
    <param-name>name</param-name>
    <param-value>gavin</param-value>
</context-param>

然后我们可以在任意一个Servlet中使用ServletContext获取这个参数:

String name = this.getServletContext().getInitParameter("name");

4、利用ServletContext对象读取资源文件(比如properties文件)
读取资源文件要根据资源文件所在的位置来决定,一般分为以下两种情况:

4.1:文件在WebRoot文件夹下,即Web应用的根目录。这时候我们可以使用ServletContext来读取该资源文件。
假设我们Web根目录下有一个配置数据库信息的dbinfo.properties文件,里面配置了name和password属性,这时候可以通过ServletContext去读取这个文件:

// 这种方法的默认读取路径就是Web应用的根目录
InputStream stream = this.getServletContext().getResourceAsStream("dbinfo.properties");
// 创建属性对象
Properties properties = new Properties();
properties.load(stream);
String name = properties.getProperty("name");
String password = properties.getProperty("password");
out.println("name="+name+";password="+password);

4.2:如果这个文件放在了src目录下,这时就不能用ServletContext来读取了,必须要使用类加载器去读取。

// 类加载器的默认读取路径是src根目录
InputStream stream = MyServlet.class.getClassLoader().getResourceAsStream("dbinfo.properties")

如果这个文件此时还没有直接在src目录下,而是在src目录下的某个包下,比如在com.gavin包下,此时类加载器要加上包的路径,如下:

InputStream stream = MyServlet.class.getClassLoader().getResourceAsStream("com/gavin/dbinfo.properties")

补充一点,ServletContext只有在读取的文件在web应用的根目录下时,才能获取文件的全路径。比如我们在WebRoot文件夹下有一个images文件夹,images文件夹下有一个Servlet.jpg图片,为了得到这个图片的全路径,如下:

// 如何读取到一个文件的全路径,这里会得到在Tomcat的全路径
String path = this.getServletContext().getRealPath("/images/Servlet.jpg");

在网站开发中,有很多功能要使用ServletContext,比如

  1. 网站计数器
  2. 网站的在线用户显示
  3. 简单的聊天系统
    总之,如果是涉及到不同用户共享数据,而这些数据量不大,同时又不希望写入数据库中,我们就可以考虑使用ServletContext实现。

ServletContext使用建议
因为存在ServletContext中的数据在服务器中会长时间,这样就会占用很多内存,因此在使用ServletContext时,建议不要往里面添加过大的数据!

Servlet网页重定向

当文档移动到新的位置,我们需要向客户端发送这个新位置时,我们需要用到网页重定向。当然,也可能是为了负载均衡,或者只是为了简单的随机,这些情况都有可能用到网页重定向。

重定向请求到另一个网页的最简单的方式是使用 response 对象的 sendRedirect() 方法。下面是该方法的定义: 将请求重定向到另一页的最简单的方法是,用方法的sendRedirect()的响应对象。以下是这种方法的定义:

public void HttpServletResponse.sendRedirect(String location)
throws IOExceptio

该方法把响应连同状态码和新的网页位置发送回浏览器。您也可以通过把 setStatus() 和 setHeader() 方法一起使用来达到同样的效果:

....
String site = "http://www.newpage.com" ;
response.setStatus(response.SC_MOVED_TEMPORARILY);
response.setHeader("Location", site); 
....

实例

本实例显示了 Servlet 如何进行页面重定向到另一个位置:

import java.io.*;
import java.sql.Date;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class PageRedirect extends HttpServlet{
    
  public void doGet(HttpServletRequest request,
                    HttpServletResponse response)
            throws ServletException, IOException
  {
      // 设置响应内容类型
      response.setContentType("text/html");

      // 要重定向的新位置
      String site = new String("http://www.w3cschool.cn");

      response.setStatus(response.SC_MOVED_TEMPORARILY);
      response.setHeader("Location", site);    
    }
} 

现在让我们来编译上面的 Servlet,并在 web.xml 文件中创建以下条目:

....
 <servlet>
     <servlet-name>PageRedirect</servlet-name>
     <servlet-class>PageRedirect</servlet-class>
 </servlet>

 <servlet-mapping>
     <servlet-name>PageRedirect</servlet-name>
     <url-pattern>/PageRedirect</url-pattern>
 </servlet-mapping>
....

现在通过访问 URL http://localhost:8080/PageRedirect 来调用这个 Servlet。这将把您转到给定的 URL http://www.w3cschool.cn

servlet点击计数器

网页点击计数器

很多时候,您可能有兴趣知道网站的某个特定页面上的总点击量。使用 Servlet 来计算这些点击量是非常简单的,因为一个 Servlet 的生命周期是由它运行所在的容器控制的。
以下是实现一个简单的基于 Servlet 生命周期的网页点击计数器需要采取的步骤:

  • 在 init() 方法中初始化一个全局变量。
  • 每次调用 doGet() 或 doPost() 方法时,都增加全局变量。
  • 如果需要,您可以使用一个数据库表来存储全局变量的值在 destroy() 中。在下次初始化 Servlet 时,该值可在 init() 方法内被读取。这一步是可选的。
  • 如果您只想对一个 session 会话计数一次页面点击,那么请使用 isNew() 方法来检查该 session 会话是否已点击过相同页面。这一步是可选的。
  • 您可以通过显示全局计数器的值,来在网站上展示页面的总点击量。这一步是可选的。
    在这里,我们假设 Web 容器将无法重新启动。如果是重新启动或 Servlet 被销毁,计数器将被重置。

实例
本实例演示了如何实现一个简单的网页点击计数器:

import java.io.*;
import java.sql.Date;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class PageHitCounter extends HttpServlet{
    
  private int hitCount; 
               
  public void init() 
  { 
     // 重置点击计数器
     hitCount = 0;
  } 

  public void doGet(HttpServletRequest request,
                    HttpServletResponse response)
            throws ServletException, IOException
  {
      // 设置响应内容类型
      response.setContentType("text/html");
      // 该方法在 Servlet 被点击时执行 
      // 增加 hitCount 
      hitCount++; 
      PrintWriter out = response.getWriter();
      String title = "总点击量";
      String docType =
      "<!doctype html public \"-//w3c//dtd html 4.0 " +       "transitional//en\">\n";
      out.println(docType +
        "<html>\n" +
        "<head><title>" + title + "</title></head>\n" +
        "<body bgcolor=\"#f0f0f0\">\n" +
        "<h1 align=\"center\">" + title + "</h1>\n" +
        "<h2 align=\"center\">" + hitCount + "</h2>\n" +
        "</body></html>");

  }
  public void destroy() 
  { 
      // 这一步是可选的,但是如果需要,您可以把 hitCount 的值写入到数据库
  } 
} 

现在我们来变异上面的servlet,并在web.xml文件穿件以下条目:

....
 <servlet>
     <servlet-name>PageHitCounter</servlet-name>
     <servlet-class>PageHitCounter</servlet-class>
 </servlet>

 <servlet-mapping>
     <servlet-name>PageHitCounter</servlet-name>
     <url-pattern>/PageHitCounter</url-pattern>
 </servlet-mapping>
....

现在通过访问 URL http://localhost:8080/PageHitCounter 来调用这个 Servlet。这将会在每次页面刷新时,把计数器的值增加 1,结果如下所示:
在这里插入图片描述

servlet和jsp的区别

jsp作为Servlet技术的扩展,经常会有人将jsp和Servlet搞混。本文,将为大家带来servlet和jsp的区别,希望对大家有所帮助。

servlet和jsp的区别
1、Servlet在Java代码中可以通过HttpServletResponse对象动态输出HTML内容。
2、JSP是在静态HTML内容中嵌入Java代码,然后Java代码在被动态执行后生成HTML内容。

servlet和jsp的各自的特点
1、Servlet虽然能够很好地组织业务逻辑代码,但是在Java源文件中,因为是通过字符串拼接的方式生成动态HTML内容,这样就容易导致代码维护困难、可读性差。
2、JSP虽然规避了Servlet在生成HTML内容方面的劣势,但是在HTML中混入大量、复杂的业务逻辑。

通过MVC双剑合璧
JSP和Servlet都有自身的适用环境,那么有没有什么办法能够让它们发挥各自的优势呢?答案是肯有的,MVC模式就能够完美解决这一问题。
MVC模式,是Model-View-Controller的简称,是软件工程中的一种软件架构模式,分为三个基本部分,分别是:模型(Model)、视图(View)和控制器(Controller):
Controller——负责转发请求,对请求进行处理
View——负责界面显示
Model——业务功能编写(例如算法实现)、数据库设计以及数据存取操作实现
在JSP/Servlet开发的软件系统中,这三个部分的描述如下所示:
在这里插入图片描述
1、Web浏览器发送HTTP请求到服务端,然后被Controller(Servlet)获取并进行处理(例如参数解析、请求转发)
2、Controller(Servlet)调用核心业务逻辑——Model部分,获得结果
3、Controller(Servlet)将逻辑处理结果交给View(JSP),动态输出HTML内容
4、动态生成的HTML内容返回到浏览器显示
MVC模式在Web开发中有很大的优势,它完美规避了JSP与Servlet各自的缺点,让Servlet只负责业务逻辑部分,而不会生成HTML代码;同时JSP中也不会充斥着大量的业务代码,这样能大提高了代码的可读性和可维护性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值