Servlet详解

本文详细介绍了Servlet的概念、特点、工作模式以及继承关系。Servlet作为Java语言实现的服务器端程序,广泛应用于扩展基于HTTP协议的Web服务器。通过探讨Servlet接口中的关键方法,如destroy()、init()和service(),以及ServletConfig对象的作用,文章揭示了Servlet如何在服务器端生成动态Web内容,以及如何通过配置文件实现初始化参数的设置。同时,文章还对比了GenericServlet和HttpServlet的区别,帮助开发者更好地理解Servlet的应用与实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.什么是servlet?

    Servlet(Server Applet),全称Java Servlet,未有中文译文。是用Java编写的服务器程序。其主要功能在于交互式地浏览和修改数据,生成动态Web内容。狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的,一般情况下,人们将Servlet理解为后者。

Servlet运行于支持Java的应用服务器中。从实现上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议Web服务器

最早支持Servlet标准的是JavaSoft的Java Web Server。此后,一些其它的基于Java的Web服务器开始支持标准的Servlet。

   我们可以把Servlet看成可以看成是用java编写的CGI.

   CGI(Common GatewayInterface)是HTTP服务器与你的或其它机器 上的程序进行“交谈”的一种工具,其程序须运行在网络服务器上。

2.Servlet 特点

        1.可移植性

       Servlet用Java编写,ServletAPI具有完善的标准。

       2.功能比较强大

          可以使用Java API的所有功能

       3.高效耐久

         一旦载入,它就驻留在内存中,加快响应速度

       4.方便

          Servlet提供了大量的实用工具例程,例如自动地解析和解码HTML表单数据、读取和设置HTTP头、处理Cookie、跟踪会话状态等。

3.工作模式

          客户端发送请求至服务器

          服务器启动并调用Servlet,Servlet根据客户端请求生成响应内容并将其传给服务器

          服务器将响应返回客户端


4.Servlet继承关系

Servlet接口中定义了五个方法:

Methods
public voiddestroy()
由 servlet 容器调用,指示将从服务中取出该 servlet。此方法仅在 servlet 的 service 方法已退出或者在过了超时期之后调用一次。在调用此方法之后,servlet 容器不会再对此 servlet 调用service 方法。

此方法为 servlet 提供了一个清除持有的所有资源(比如内存、文件句柄和线程)的机会,并确保任何持久状态都与内存中该 servlet 的当前状态保持同步。

public void

init(ServletConfig config) throwsServletException
由 servlet 容器调用,指示将该 servlet 放入服务。

servlet 容器仅在实例化 servlet 之后调用 init 方法一次。在 servlet 可以接收任何请求之前,init 方法必须成功完成。servlet 容器无法将 servlet 放入服务,如果init 方法:

public voidservice(ServletRequest req, ServletResponse res) throws ServletException, java.io.IOException
由 servlet 容器调用,以允许 servlet 响应某个请求。

此方法仅在 servlet 的 init() 方法成功完成之后调用。

应该为抛出或发送错误的 servlet 设置响应的状态代码。

servlet 通常运行在可同时处理多个请求的多线程 servlet 容器中。开发人员必须知道要同步对所有共享资源(比如文件、网络连接以及 servlet 的类和实例变量)的访问。有关 Java 中多线程编程的更多信息,可从the Java tutorial on multi-threaded programming 中获得。

 

Properties
public ServletConfiggetServletConfig()
返回 ServletConfig 对象,该对象包含此 servlet 的初始化和启动参数。返回的 ServletConfig 对象是传递给 init 方法的对象。

此接口的实现负责存储 ServletConfig 对象,以便此方法可以返回该对象。实现此接口的 GenericServlet 类已经这样做了。

public StringgetServletInfo()
返回有关 servlet 的信息,比如作者、版本和版权。

此方法返回的字符串应该是纯文本,不应该是任何种类的标记(比如 HTML、XML,等等)。

      在web容器启动后,会读取标注(Annotation)或者web.xml的配置,根据当中的每个Servlet配置,将servlet类载入,并实例化,并为每个servlet的配置产生一个ServletConfig对象,然后调用Servlet里面的init()方法,并将产生的ServletConfig对象当作参数输入进去。

    ServletConfig对象:
       ServletConfig是针对特定的Servlet的参数或属性。ServletConfig是表示单独的Servlet的配置和参数,只是适用于特定的Servlet。从一个servlet被实例化后,对任何客户端在任何时候访问有效,但仅对本servlet有效,一个servlet的ServletConfig对象不能被另一个servlet访问。

1.首先要设置初始化参数,如果只有一个特定的servlet要设定的参数(Servlet名字以及其它参数等),其它servlet不能共享,应该配置为ServletConfig参数,如一个读取附件的servlet要用到绝对目录,而别的servlet不会用到:

<web-app>
<servlet>
     <servlet-name>GetAtt</servlet-name>
     <servlet-class>mail.GetAttServlet</servlet-class>
   <init-param>
    <param-name>absPath</param-name>
    <param-value>/usr/mail/ax/axman/Maildir/</param-value>
 </init-param>
</servlet>
</web-app>

2.其次要取得ServletConfig对象:

1).从init()方法中得到.

public class Test extends HttpServlet {
   ServletConfig config;
    public void init(ServletConfig config) throws ServletException {
    super.init(config);
    this.config = config;
}
2).从getServletConfig()方法中得到.

ServletConfig config=this.getServletConfig();

if(config.getInitParameter("absPath").eaquals("adsd"){
.......
}

    GenericServlet类

     GenericServlet 类可以说时JDK中最重要的类,也是最基本的类。程序员要编写Servlet 应用程序,一般要继承JSDK 提供的GenericServlet 类或它的子类HttpServlet类。service() 方法是类GenericServlet中最重要的方法。每次客户向服务器发出请求时,服务器就会调用这个方法。编程人员若想对客户的请求进行响应的话,就必须覆盖这个方法,并在这个方法中加入自己的代码来具体实现对客户的响应。Service有两个参数,ServletRequest 和ServletResponse。其中ServletRequest 保存了客户向服务器发请求的各种属性。

对象ServletResponse用来设置如何对客户进行响应,它有以下三个方法:

      *setContentType(String) 用来设置对客户响应的类型。

      *setContentlength(int) 用来设置对客户响应的长度。

      *getOutputStream() 它返回一个写响应数据的输出流。

例如:

public class HelloWorldServlet extends GenericServlet {

	@Override
	public void service(ServletRequest req, ServletResponse res)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		Date today = new Date();
		ServletOutputStream out = res.getOutputStream();
		out.println("HELLO WORLD");
		out.println(today.toString());
		
	}
	
}


 GenericServlet用于定义一般的且与协议无关的servlet 如果是继承GenericServlet的话,必须要重写service方法service方法是一个抽象方法,并且在每次访问servlet都会访问

在访问继承了HttpServlet的servlet的时候,首先访问的还是service方法 获取请求的类型,根据类型判断调用具体的doXXX()方法,所以通常继承HttpServlet抽象类的servlet只需要重写doXXX()方法

 继承genericServlet和继承HttpServlet的差别:
 1、继承genericServlet必须要重写service方法,而HttpServlet不需要
  2、genericServlet通常用于处理与请求协议无关的servlet,httpServlet处理与HTTP协议相关的请求
  3、继承httpServlet的话,最少必须要重写doXXX()方法之一
HttpServlet中Service方法源代码如下:

 protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {

        String method = req.getMethod();

        if (method.equals(METHOD_GET)) {
            long lastModified = getLastModified(req);
            if (lastModified == -1) {
                // servlet doesn't support if-modified-since, no reason
                // to go through further expensive logic
                doGet(req, resp);
            } else {
                long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                if (ifModifiedSince < (lastModified / 1000 * 1000)) {
                    // If the servlet mod time is later, call doGet()
                    // Round down to the nearest second for a proper compare
                    // A ifModifiedSince of -1 will always be less
                    maybeSetLastModified(resp, lastModified);
                    doGet(req, resp);
                } else {
                    resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                }
            }

        } else if (method.equals(METHOD_HEAD)) {
            long lastModified = getLastModified(req);
            maybeSetLastModified(resp, lastModified);
            doHead(req, resp);

        } else if (method.equals(METHOD_POST)) {
            doPost(req, resp);
            
        } else if (method.equals(METHOD_PUT)) {
            doPut(req, resp);        
            
        } else if (method.equals(METHOD_DELETE)) {
            doDelete(req, resp);
            
        } else if (method.equals(METHOD_OPTIONS)) {
            doOptions(req,resp);
            
        } else if (method.equals(METHOD_TRACE)) {
            doTrace(req,resp);
            
        } else {
            //
            // Note that this means NO servlet supports whatever
            // method was requested, anywhere on this server.
            //

            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[1];
            errArgs[0] = method;
            errMsg = MessageFormat.format(errMsg, errArgs);
            
            resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
        }
    }
通过源码我们可以看出,在Service方法中,系统已经帮我们处理好了get和post方式请求,所以我们在使用Servlet的时候,直接继承于HttpServlet,不需要重写Service方法,只需要重写dopost或者doget方法。

 

### Servlet 详解及其在 Java Web 开发中的作用 #### 什么是 ServletServlet 是一种用于扩展服务器功能的小型 Java 程序,它运行于支持 Java 的 Web 容器(如 Tomcat 或 Jetty)中。Servlet 提供了一种标准的方法来响应客户端请求并生成动态网页内容[^1]。 #### Servlet 的基本概念 Servlet 是 Java Web 应用程序的核心组件之一,主要用于处理 HTTP 请求和返回 HTTP 响应。它的主要职责包括接收客户端请求、处理业务逻辑以及向客户端发送响应数据。以下是几个关键点: - **跨平台性**:由于 Java 的“Write Once, Run Anywhere”特性,基于 Servlet 构建的应用可以轻松部署到不同操作系统上的兼容容器中[^2]。 - **丰富的生态系统**:Java 社区提供了大量成熟的框架(如 Spring 和 Hibernate),它们通常依赖或封装了底层的 Servlet 技术[^2]。 #### Servlet 生命周期 Servlet 的生命周期由 Servlet 容器管理,主要包括以下几个阶段: 1. **加载与实例化**:当第一个请求到达时,或者按照配置文件指定的时间提前加载,容器会创建 Servlet 实例[^4]。 2. **初始化 (init)**:调用 `init()` 方法完成必要的准备工作,例如读取配置参数或建立数据库连接[^4]。 3. **服务 (service)**:每次接收到新的请求都会触发此方法执行相应的操作;`doGet()` 和 `doPost()` 则分别对应 GET 和 POST 类型的具体实现[^4]。 4. **销毁 (destroy)**:当 servlet 不再被需要时(比如关闭应用),容器将释放资源并通过 destroy() 进行清理工作[^4]。 #### 如何编写一个简单的 Servlet? 下面展示了一个基础的例子演示如何定义自己的自定义 Servlet 并设置上下文路径访问全局变量: ```java package example; import java.io.IOException; import javax.servlet.*; import javax.servlet.http.*; public class HelloWorldServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 设置响应的内容类型为 text/html 编码 UTF-8 resp.setContentType("text/html;charset=UTF-8"); try(PrintWriter out = resp.getWriter()) { out.println("<!DOCTYPE html>"); out.println("<html><head><title>Hello</title></head><body>"); // 输出 HTML 页面内容给浏览器显示 out.println("<h1>你好世界!</h1>"); out.println("</body></html>"); } } } ``` 此外还展示了另一个例子用来获取整个网站范围内的初始参数值: ```java public class ContextParamExample extends HttpServlet { private static final long serialVersionUID = 1L; public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{ ServletContext context=getServletContext(); String paramValue=context.getInitParameter("myAppPropertyKey"); PrintWriter writer=response.getWriter(); writer.write(paramValue); } } ``` 以上代码片段来自实际项目经验分享[^3]^。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

le4

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值