Servlet詳解

爲什麼要學習Servlet

早期請求的jsp實際上就是一個java類,這個類到底是什麼呢?

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
<head>
</head>
<body>
<%
    out.println("helloworld");
%>
</body>
</html>

以上jsp生成的部分代碼如下

public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {}

發現HttpJspBese這個類的繼承結構如下:

public abstract class org.apache.jasper.runtime.HttpJspBase extends javax.servlet.http.HttpServlet implements javax.servlet.jsp.HttpJspPage {}

總結:javax.servlet.http.HttpServlet就是Servlet的核心類,請求一個jsp頁面實際上就是請求一個Servlet

什麼是Servlet

Servlet 是一個 Java程序,是在服務器上運行以處理客戶端請求並做出響應的程序,Java Servlet是和平臺無關的服務器端組件,它運行在Servlet容器中Servlet容器負責Servlet和客戶的通信以及調用Servlet的方法,Servlet和客戶的通信採用“請求/響應”的模式

Servlet可完成如下功能

創建並返回基於客戶請求的動態HTML頁面。

創建可嵌入到現有 HTML 頁面中的部分 HTML 頁面(HTML 片段)

與其它服務器資源(如數據庫或基於Java的應用程序)進行通信

ServletAPI詳解

mark

Servlet接口

mark

該類的源代碼如下:

package javax.servlet;
import java.io.IOException;
public interface Servlet {
    public void init(ServletConfig config) throws ServletException;
    public ServletConfig getServletConfig();
    public void service(ServletRequest req, ServletResponse res)
    throws ServletException, IOException;
    public String getServletInfo();
    public void destroy();
}

ServletConfig接口

mark

該接口的源代碼如下

package javax.servlet;
import java.util.Enumeration;
public interface ServletConfig {
    public String getServletName();
    public ServletContext getServletContext();
    public String getInitParameter(String name);
    public Enumeration getInitParameterNames();
}

注意:一個Servlet對象與一個ServletConfig對象一一對應

GenericServlet

mark

源代碼如下:

package javax.servlet;
import java.io.IOException;
import java.util.Enumeration;
public abstract class GenericServlet 
    implements Servlet, ServletConfig, java.io.Serializable{
    private transient ServletConfig config;
    public GenericServlet() { }
    public void destroy() {}
    public String getInitParameter(String name) {
        return getServletConfig().getInitParameter(name);
    }
    public Enumeration getInitParameterNames() {
        return getServletConfig().getInitParameterNames();
    }   
    public ServletConfig getServletConfig() {
        return config;
    }
    public ServletContext getServletContext() {
        return getServletConfig().getServletContext();
    }
    public String getServletInfo() {
        return "";
    }
    public void init(ServletConfig config) throws ServletException {
        this.config = config;
        this.init();
    }
    public void init() throws ServletException {
    }
    public void log(String msg) {
        getServletContext().log(getServletName() + ": "+ msg);
    }
    public void log(String message, Throwable t) {
        getServletContext().log(getServletName() + ": " + message, t);
    }
    public abstract void service(ServletRequest req, ServletResponse res)
    throws ServletException, IOException;
    public String getServletName() {
        return config.getServletName();
    }
}

注意:該類是一個抽象類,對Servlet和ServletConfig接口中的大部分方法做了默認的實現,並且增加了log等方法

HttpServlet

mark

部分源代碼如下:

public void service(ServletRequest req, ServletResponse res)
        throws ServletException, IOException {

        HttpServletRequest  request;
        HttpServletResponse response;

        try {
            request = (HttpServletRequest) req;
            response = (HttpServletResponse) res;
        } catch (ClassCastException e) {
            throw new ServletException("non-HTTP request or response");
        }
        service(request, response);
}
protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {

        String method = req.getMethod();

        if (method.equals(METHOD_GET)) {
          …
        }else if(method.equals(METHOD_POST)) {
        …
        }
}

如何編寫一個Servlet程序

編寫一個類繼承HttpServlet

package cn.org.kingdom.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //如果在Servlet中用到response對象向客戶端響應時,此時要在得到流之前設置contentType
        response.setContentType("text/html;charset=utf-8");
        PrintWriter ps = response.getWriter();
        ps.write("<html>");
        ps.write("<head><title>helloServlet</title></head>");
        ps.write("<body>你好 Servlet</body>");
        ps.write("</html>");
        ps.close();
    }
}

在web.xml中配置該servlet

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>web04</display-name>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <servlet>
    <servlet-name>MyServlet</servlet-name>
    <servlet-class>cn.org.kingdom.servlet.MyServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>MyServlet</servlet-name>
    <url-pattern>/MyServlet</url-pattern>
  </servlet-mapping>
</web-app>

訪問該Servlet

mark

探究Servlet的生命週期

在前面講解Servlet接口的api中就提到生命週期的概念

This interface defines methods to initialize a servlet, to service requests, and to remove a servlet from the server. These are known as life-cycle methods and are called in the following sequence: 
    The servlet is constructed, then initialized with the init method. 
    Any calls from clients to the service method are handled. 
    The servlet is taken out of service, then destroyed with the destroy method, then garbage collected and finalized. 
In addition to the life-cycle methods, this interface provides the getServletConfig method, which the servlet can use to get any startup information, and the getServletInfo method, which allows the servlet to return basic information about itself, such as author, version, and copyright. 

圖解:

mark

可以設置當服務器啓動時,調用構造和init方法,在web.xml中設置以下代碼

<servlet>
        <servlet-name>LifeServlet</servlet-name>
        <servlet-class>cn.org.kingdom.servlet.LifeServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
        <servlet-name>LifeServlet</servlet-name>
        <url-pattern>/LifeServlet</url-pattern>
</servlet-mapping>

當訪問多次的時候,發現Servlet的構造方法不會執行多次,所以Servlet是一個單例設計,要求不要再servlet中定義成員變量(這個成員變量會被多個線程共享),有可能會產生線程安全問題

Servlet中配置初始化參數

在web.xml中的servlet節點配置初始化參數

<servlet>
        <servlet-name>LifeServlet</servlet-name>
        <servlet-class>cn.org.kingdom.servlet.LifeServlet</servlet-class>
        <init-param>
            <param-name>name</param-name>
            <param-value>hello LifeServlet</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
</servlet>

使用ServletConfig來進行獲取初始化參數的值

protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        System.out.println(this.getServletConfig().getInitParameter("name"));
}

獲得上下文參數

在web.xml中配置,該節點與Servlet節點處於同一級

<context-param>
    <param-name>name</param-name>
    <param-value>context-value</param-value>
</context-param>

使用ServletContext對象獲取上下文參數的值

String name = this.getServletContext().getInitParameter("name");
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章