Java Servlet学习笔记——1. Servlet API概览与第一个Servlet程序

写在前面

第一次接触Java Servlet是在之前的软件工程大作业中学习构建一个在线课程平台,浏览器与服务器之间的响应是通过Servlet来完成的,后来根据老师的需要完成一个在线问卷调查开发。有必要系统的整理一下Servlet知识,不然总是遇到问题就上网查,查来查去也就这么点东西,太零碎了。所以开辟这个分类系统整理一下。

首先,这第一篇博客将主要对Servlet API的概览,从而实现对Servlet 的整体认识。

Servlet API概览

Servlet API有四个Java包:

  • javax.servlet, 其中包含定义Servlet和Servlet容器之间契约的类和接口。
  • javax.servlet.http, 其中包含定义HTTP Servlet和Servlet容器之间契约的类和接口。
  • javax.servlet.annotation, 其中包含标注Servlet、Filter、 Listener的标注。 它还为被标注元件定义元数据。
  • javax.servlet.descriptor, 其中包含提供程序化登录web应用程序的配置信息的类型。

Servlet技术的核心是Servlet, 它是所有Servlet类必须直接或间接实现的一个接口。 在编写实现Servlet的Servlet类时, 直接实现它。 在扩展实现这个接口的类时, 间接实现它。

Servlet接口定义了Servlet与Servlet容器之间的契约。 这个契约归结起来就是, Servlet容器将Servlet类载入内存, 并在Servlet实例上调用具体的方法。 在一个应用程序中, 每种Servlet类型只能有一个实例。

用户请求致使Servlet容器调用Servlet的Service方法, 并传入一个ServletRequest实例和一个ServletResponse实例。 ServletRequest中封装了当前的HTTP请求, 因此, Servlet开发人员不必解析和操作原始的HTTP数据。 ServletResponse表示当前用户的HTTP响应, 使得将响应发回给用户变得十分容易。

对于每一个应用程序, Servlet容器还会创建一个ServletContext实例。 这个对象中封装了上下文(应用程序) 的环境详情。 每个上下文只有一个ServletContext。每个Servlet实例也都有一个封装Servlet配置的ServletConfig。

Servlet

Servlet接口中定义了以下5个方法:

  • void init(ServletConfig config) throws ServletException
  • void service(ServletRequest request, ServletResponse response) throws ServletException, java.io.IOException
  • void destroy()
  • java.lang.String getServletInfo()
  • ServletConfig getServletConfig()

注意, 编写Java方法签名的惯例是, 对于与包含该方法的类型不处于同一个包中的类型, 要使用全类名。正因为如此, 在Service方法javax.servlet.ServletException的签名中(与Servlet位于同一个包中) 是没有包信息的, 而java.io.Exception则是编写完整的名称。

生命周期方法

  • init, 当该Servlet第一次被请求时, Servlet容器会调用这个方法。 这个方法在后续请求中不会再被调用。 我们可以利用这个方法执行相应初始化工作。调用这个方法时, Servlet容器会传入一个ServletConfig。 一般来说, 你会将ServletConfig赋给一个类级变量, 因此这个对象可以通过Servlet类的其他点来使用。
  • Service, 每当请求Servlet时, Servlet容器就会调用这个方法。 编写代码时, 是假设Servlet要在这里被请求。 第一次请求Servlet时, Servlet容器调用init方法和Service方法。 后续的请求将只调用Service方法。
  • destroy, 当要销毁Servlet时, Servlet容器就会调用这个方法。 当要卸载应用程序, 或者当要关闭Servlet容器时, 就会发生这种情况。 一般会在这个方法中编写清除代码。

非生命周期方法

  • getServletInfo, 这个方法会返回Servlet的描述。 你可以返回有用或为null的任意字符串。
  • getServletConfig, 这个方法会返回由Servlet容器传给init方法的ServletConfig。 但是, 为了让getServletConfig返回一个非null值, 必须将传给init方法的ServletConfig赋给一个类级变量。

注意线程安全性。 Servlet实例会被一个应用程序中的所有用户共享, 因此不建议使用类级变量, 除非它们是只读的, 或者是java.util.concurrent.atomic包的成员。

第一个Servlet程序

我将尝试按照书《Servlet、JSP和Spring MVC初学指南》来实现第一个Servlet程序。编写一个名为app01a的Servlet应用程序。 最初, 它会包含一个Servlet, 即MyServlet, 其效果是向用户发出一条问候。

要运行Servlets,需要一个Servlet容器,我采用的是Tomcat,它是一个开源的Servlet容器。安装教程网上有很多,我就不罗列了。

搞定Tomcat之后,可以编写和编译第一个Servlet类,按照惯例,Servlet类的名称要以Servlet作为后缀。代码如下:

package app01a;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;

@WebServlet(name = "MyServlet", urlPatterns = { "/my" } )
public class MyServlet implements Servlet {

    private transient ServletConfig servletConfig;

    @Override
    public void init(ServletConfig servletConfig)
            throws ServletException {
        this.servletConfig = servletConfig;
    } 

    @Override
    public ServletConfig getServletConfig() {
        return servletConfig;
    } 

    @Override
    public String getServletInfo() {
        return "My Servlet";
    } 

    @Override
    public void service(ServletRequest request,ServletResponse response) 
            throws ServletException,IOException {
        String servletName = servletConfig.getServletName();
        response.setContentType("text/html");
        PrintWriter writer = response.getWriter();
        writer.print("<html><head></head>"+ "<body>Hello YidaZhang from " + servletName + "</body></html>");
    } 

    @Override
    public void destroy() {

    }
}

这里面还是有很多东西,对于我这种还没有系统学过Java的人颇具挑战的,我们一条一条来看,参考常见的Java标注/Java注解和各种符号

  • @WebServlet标注类型用来声明一个Servlet。 命名Servlet时, 还可以暗示容器, 是哪个URL调用这个Servlet。 name属性是可选的, 如有, 通常用Servlet类的名称。 重要的是urlPatterns属性, 它也是可选的, 但是一般都是有的。 在MyServlet中, urlPatterns告诉容器, /my样式表示应该调用Servlet。
  • @Override:表示重写的方法,编译器会验证@Override下面的方法名是否是父类中存在的,如果不存在则会报错。
  • URL样式必须用一个正斜杠开头。URL是( Uniform Resource Locator )统一资源定位符的缩写。

URL完整格式

参考URL格式

scheme:[//[user[:password]@]host[:port]][/path][?query][#fragment]
  • 传送协议。
  • 层级URL标记符号(为[//],固定不变)
  • 访问资源需要的凭证信息(可省略)
  • 服务器。(通常为域名,有时为IP地址)
  • 端口号。(以数字方式表示,若为HTTP的默认值“:80”可省略)
  • 路径。(以“/”字符区别路径中的每一个目录名称)
  • 查询。(GET模式的窗体参数,以“?”字符为起点,每个参数以“&”隔开,再以“=”分开参数名称与数据,通常以UTF8的URL编码,避开字符冲突的问题)
  • 片段。以“#”字符为起点

回到刚才的程序,Servlet的init方法只被调用一次, 并将private transient变量ServletConfig设为传给该方法的ServletConfig对象:

调用Servlet

要测试这个Servlet, 需要启动或者重启Tomcat, 并在浏览器中打开下面的URL(假设Tomcat配置为监听端口8080, 这是它的默认端口) :

http://localhost:8080/app01a/my

输出结果如下:
这里写图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值