JAVA WEB SERVLET 基础知识点

Servlet


  • Servlet
  • Servlet API 概述
  • Servlet
  • 编写基础的Servlet应用程序
    • 1编写和编译Servlet类
    • 2应用程序的目录结构
    • 3调用Servlet
  • ServletRequest
  • ServletResponse
  • ServletConfig
  • ServletContext
  • GenericServlet
  • 1 HTTPServlet
    • 2 HttpServletRequest
    • 3 HttpServletResponse
  • 处理HTML表单
  • 使用部署描述符

掌握Servlet API 是成为一名技术高超的JAVA Web开发者的基础.必须非常熟悉Servlet API中所定义的70多种类型.
本篇博客将介绍Servlet API,并教你编写第一个Servlet应用程序.

1.Servlet API 概述

Servlet API中有4个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容器还为每个应用程序创建一个ServletContext实例.这个对象封装context(应用程序)的环境细节.每个context只有一个ServletContext.每个Servlet实例还有一个封装Servlet配置信息的ServletConfig.

2.Servlet

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

public void init(ServletConfig servletConfig)throws ServletException 

public void service(ServletRequest request,ServletResponse response) throws ServletException,IOException 

public void destroy()

public ServletConfig getServletConfig() 

public String getServletInfo() 

编写Java方法签名的规则是:与包含该方法的类型不在同一个包中的类型,要使用全类名.
init() service() destroy()方法是Servlet的生命周期方法,调用规则如下:

  • init(): 第一次请求Servlet时,Servlet容器会调用这个方法.在后续的请求中不会在调用.
  • service(): 每次请求Servlet时都会调用此方法,必须在这里编写要Servlet完成的响应代码. 第一次调用Servlet时会调用init()和service()方法,之后请求只调用service()方法.
  • destroy(): Servlet要销毁时调用此方法,通常发生在卸载应用程序,或者关闭Servlet容器的时候.
  • getServletInfo(): 该方法返回Servlet的描述,可以是任意字符串,甚至为null.
  • getServletConfig(): 该方法返回由Servlet容器传给init方法的ServletConfig.为了让getServletConfig返回非null值,应该为传给init方法的ServletConfig赋给一个类级变量.

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

3.编写基础的Servlet应用程序

Servlet应用程序编写起来非常简单,只需要创建一个目录结果,并将Servlet类放在某一个目录下即可.

3.1编写和编译Servlet类

在本节中,将学习如何编写一个简单的Servlet应用程序,将它命名为app01a.最初它只包含一个Servlet:MyServlet,其会给用户发送一条问候信息.

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(""
                + "Hello from " + servletName 
                + "");
    }

    @Override
    public void destroy() {
    }    
}

查看代码首先会注意到下面这个注解:

@WebServlet(name = “MyServlet”, urlPatterns = { “/my” })
注解中:name属性是可选的,一般用来提供Servlet类的名字,关键是urlPatterns它也是可选的,在MyServlet中,urlPatterns告诉容器,/my模式应该调用这个Servlet.

  • URL模式必须一条正斜线开头.

3.2应用程序的目录结构

Servlet应用程序必须以特定目录结果进行部署,应用程序包含WEB-INF目录
它有两个子目录:

  • classes目录:Servlet类和其他的Java类都必须放在这里.类下方的目录反映了类的包结构.
  • lib目录:在这里部署Servlet应用程序所需要的Jar文件.
    所有的图像文件可以放在一个image目录下,所有的JSP页面可以放在一个jsp目录下,以此类推.
    放在应用程序目录下的任何资源,用户可以通过输入该资源的URL而直接进行访问.如果希望某个资源可以被Servlet访问,但是不能被用户访问,那么应该把它放在WEB-INF目录下面.

把应用程序部署到Tomcat中:

  • 一种部署方法是将应用程序目录直接复制到Tomcate的webapps目录下
  • 可以通过在Tomcat的conf目录下编辑server.xml文件来部署应用程序
  • 为了不用编辑server.xml,而单独部署一个XML文件到conf\Catalina\localhost目录下.
  • 将应用程序打包成war文件来进行部署.war文件是指以war作为扩展名的jar文件.

3.3调用Servlet

运行MyServlet应用程序,通过以下地址:

http://localhost:8080/app01a/my

允许结果:

恭喜!你的第一个Servlet应用程序已经运行!

4.ServletRequest

下面是ServletRequest接口中的部分方法:

public int getContentLength()

返回请求主体中的字节数,如果不知道字节长度,则返回-1;

public java.lang.String getContentType()

返回请求主体的MIME类型,如果不知道类型,则返回null;

public java.lang.String getProtocol()

返回这个HTTP请求的协议名称和版本号;

public java.lang.String getParameter(java.lang.String name)

返回指定请求参数的值,返回一个HTML表单域的值,获取查询字符串的值.如果不存在返回null;

利用getParameterNames getParameterMap和getParameterValues来获取表单域的名称和值,以及查询字符串.

5.ServletResponse

  • ServletResponse中定义了getWriter()方法,它返回可以将文本传给客户端的java.io.PrintWriter.默认情况下,PrintWriter对象采用ISO-8859-1编码.

  • 在发送任何HTML标签之前,先通过调用setContentType来设置响应的内容类型,比如:将text/html作为参数传递,告诉浏览器内容类型为HTML.

6.ServletConfig

  • getInitParameter(java.lang.String name)

从一个Servlet内部获取某个初始参数的值,由传入init方法的ServletConfig中调用getInitParameter.

  • java.util.Enumeration getInitParameterNames()

返回所有初始参数名称的一个Enumeration.

  • getServletContext()

从Servlet内部获取ServletContext.

举个ServletConfig的例子.添加一个ServletConfigDemoServlet:

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.WebInitParam;
import javax.servlet.annotation.WebServlet;

@WebServlet(name = "ServletConfigDemoServlet", 
    urlPatterns = { "/servletConfigDemo" },
    initParams = {
        @WebInitParam(name="admin", value="Harry Taciak"),
        @WebInitParam(name="email", value="[email protected]")
    }
)
public class ServletConfigDemoServlet implements Servlet {
    private transient ServletConfig servletConfig;

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

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

    @Override
    public void service(ServletRequest request, 
            ServletResponse response)
            throws ServletException, IOException {
        ServletConfig servletConfig = getServletConfig();
        String admin = servletConfig.getInitParameter("admin");
        String email = servletConfig.getInitParameter("email");
        response.setContentType("text/html");
        PrintWriter writer = response.getWriter();
        writer.print("" + 
                "Admin:" + admin + 
                "
Email:"
+ email + ""); } @Override public String getServletInfo() { return "ServletConfig demo"; } @Override public void destroy() { } }

7.ServletContext

ServletContext表示Servlet应用程序.每个Web应用程序只有一个context.
用ServletConfig中调用getServletContext方法可以获得ServletContext.
保存在ServletContext中的对象称作属性.
ServletContext中包含如下常用属性:
- getAttribute()
- getAttributeNames()
- setAttribute()
- removeAttribute()

8.GenericServlet

通过Servlet接口编写Servlet很麻烦,需要把它的所有方法都实现及时不用的方法,所以,我们有GenericServlet抽象类,它实现了Servlet和ServletConfig,并做了以下工作:

  • 将init方法中的ServletConfig赋给一个类级变量,使它可以通过调用getServletConfig来获取.
  • 为Servlet接口中的所有方法提供默认实现.
  • 提供方法来包装ServletConfig中的方法.

在类中如果覆盖了init()方法,则必须调用super.init(servletConfig)来保存ServletConfig.
可以通过覆盖无参的init方法来编写初始化代码,ServletConfig仍然由GenericServlet实例保存.
接下来举个继承GenericServlet的Servlet栗子:

package app01a;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.GenericServlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;

@WebServlet(name = "GenericServletDemoServlet", 
    urlPatterns = { "/generic" },
    initParams = {
        @WebInitParam(name="admin", value="Harry Taciak"),
        @WebInitParam(name="email", value="[email protected]")
    }
)
public class GenericServletDemoServlet extends GenericServlet {

    private static final long serialVersionUID = 62500890L;

    @Override
    public void service(ServletRequest request, 
            ServletResponse response)
            throws ServletException, IOException {
        ServletConfig servletConfig = getServletConfig();
        String admin = servletConfig.getInitParameter("admin");
        String email = servletConfig.getInitParameter("email");
        response.setContentType("text/html");
        PrintWriter writer = response.getWriter();
        writer.print("" + 
                "Admin:" + admin + 
                "
Email:"
+ email + ""); } }

9.1 HTTPServlet

javax.servlet.http包是Servlet API中的第二个包,其包含了编写Servlet应用程序的类和接口.
HttpServlet类覆盖javax.servlet.GenericServlet类.
HttpServlet中有两项特性是GenericServlet所没有的:

  • 不覆盖service方法,而是覆盖doGet doPost,或者两者都覆盖掉.在极少数情况下,还要覆盖以下某个方法:doHead() doPut() doTrace() doOptions()或doDelete().
  • 将用HttpServletRequest和HttpServletResponse代替ServletRequest和ServletResponse.

9.2 HttpServletRequest

HttpServletRequest表示HTTP环境中的Servlet请求.它继承java.servlet.ServletRequest接口,并增加了几个方法:

  • String getContextPath()

返回表示请求context的请求URI部分.

  • Cookie[] getCookies()

返回一个Cookie对象数组.

  • String getHeader(String name)

返回指定HTTP标头的值.

  • String getMethod()

返回发出这条请求的HTTP方法的名称.

  • String getQueryString()

返回请求URL中的查询字符串.

  • HttpSession getSession()

返回与这个请求有关的session对象.如果没有找到,则创建新的session对象.

  • HttpSession getSession(boolean create)

返回与这个请求有关的session对象.如果没有找到,并且create参数为true,那么将创建新的session对象.

9.3 HttpServletResponse

HttpServletResponse表示HTTP环境下的Servlet响应.

  • void addCookie(Cookie cookie) 给这个响应对象添加cookie
  • void addHeader(String name,String value) 给这个响应对象添加标头.
  • void sendRedirect(String location) 发送响应代号,将浏览器重定向到指定的位置.

10.处理HTML表单

每个Web应用程序中几乎都会包含一个或者多个HTML表单,用来接收用户输入.可以轻松地将一个HTML表单从Serlet发送到浏览器.
HTML输入域或文本域中的值将被当作字符串发送到服务器.空白的输入域或文本域将发送一条空白的字符串,因此,带有一个输入域名称的ServletRequest.getParameter将永远不会返回null.

  • 接下来举个栗子:FormServlet类示范了处理HTML表单的方法.它的doGet方法发送了一个给浏览器.它的doPost方法获取输入的值,并输出它们.
package app01b;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name = "FormServlet", urlPatterns = { "/form" })
public class FormServlet extends HttpServlet {
    private static final long serialVersionUID = 54L;
    private static final String TITLE = "Order Form";

    @Override
    public void doGet(HttpServletRequest request,
            HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter writer = response.getWriter();
        writer.println("");
        writer.println("");
        writer.println(""</span> + TITLE + <span class="hljs-string">"");
        writer.println("

" + TITLE + "

"
); writer.println("
"); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println("
Name:
Address:
Country:
Delivery Method: + "name='deliveryMethod'" + " value='First Class'/>First Class"); writer.println(" + "name='deliveryMethod' " + "value='Second Class'/>Second Class
Shipping Instructions:
 
Please send me the latest " + "product catalog: + "name='catalogRequest'/>
 " + "
"
); writer.println(""
); writer.println(""); writer.println(""); } @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter writer = response.getWriter(); writer.println(""); writer.println(""); writer.println(""</span> + TITLE + <span class="hljs-string">""); writer.println(""); writer.println("

" + TITLE + "

"
); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println(""); writer.println("
Name:" + request.getParameter("name") + "
Address:" + request.getParameter("address") + "
Country:" + request.getParameter("country") + "
Shipping Instructions:"); String[] instructions = request .getParameterValues("instruction"); if (instructions != null) { for (String instruction : instructions) { writer.println(instruction + "
"
); } } writer.println("
Delivery Method:" + request.getParameter("deliveryMethod") + "
Catalog Request:"); if (request.getParameter("catalogRequest") == null) { writer.println("No"); } else { writer.println("Yes"); } writer.println("
"
); writer.println("
"); writer.println("Debug Info
"
); Enumeration parameterNames = request .getParameterNames(); while (parameterNames.hasMoreElements()) { String paramName = parameterNames.nextElement(); writer.println(paramName + ": "); String[] paramValues = request .getParameterValues(paramName); for (String paramValue : paramValues) { writer.println(paramValue + "
"
); } } writer.println("
"
); writer.println(""); writer.println(""); } }
  • 空白的订单表单:
    JAVA WEB SERVLET 基础知识点_第1张图片
  • 填写完表单,并单击Submit(提交)按钮.在表单中输入的值将会通过HTTP POST方法发送到服务器,这样就会调用Servlet的doPost方法.在订单表单中输入的值:
    JAVA WEB SERVLET 基础知识点_第2张图片

11.使用部署描述符

使用部署描述符是配置Servlet应用程序的另一种方法,部署描述符总是命名为web.xml,并放在WEB-INF目录下.

栗子:有两个没有@WebServlet进行标注的Servlet:分别为:SimpleServlet和WelcomeServlet.以及部署描述符文件:web.xml:

  • 未标注的SimpleServlet类:
package app01c;
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 SimpleServlet extends HttpServlet {
    private static final long serialVersionUID = 8946L;

    @Override
    public void doGet(HttpServletRequest request,
            HttpServletResponse response) 
            throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter writer = response.getWriter();
        writer.print("" +
                "Simple Servlet);
    }
}
  • 未标注的WelcomeServlet类
package app01c;
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 WelcomeServlet extends HttpServlet {
    private static final long serialVersionUID = 27126L;

    @Override
    public void doGet(HttpServletRequest request,
            HttpServletResponse response) 
            throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter writer = response.getWriter();
        writer.print(""
                + "Welcome");
    }
}
  • 部署描述符web.xml:

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0"> 

    <servlet>
        <servlet-name>SimpleServletservlet-name>
        <servlet-class>app01c.SimpleServletservlet-class>
        <load-on-startup>10load-on-startup>
    servlet>

    <servlet-mapping>
        <servlet-name>SimpleServletservlet-name>
        <url-pattern>/simpleurl-pattern>
    servlet-mapping>  


    <servlet>
        <servlet-name>WelcomeServletservlet-name>
        <servlet-class>app01c.WelcomeServletservlet-class>
        <load-on-startup>20load-on-startup>
    servlet>

    <servlet-mapping>
        <servlet-name>WelcomeServletservlet-name>
        <url-pattern>/welcomeurl-pattern>
    servlet-mapping>
web-app>

部署描述符的好处:

  • 可以包含@WebServlet中没有的元素,如load-on-startup表示在应用程序启动时加载Servlet,而不是第一次调用Servlet时加载.
  • 如果需要修改配置值,如Servlet路径,就不需要重新编译Servlet类.
  • 可以将初始参数传给一个Servlet,并且不需要重新编译Servlet类就可以对它们进行编译.
  • 部署描述符还允许覆盖Servlet注解中指定的值.可以在标注完Servlet之后,又在同一个应用程序的部署描述符中声明Servlet.

www.yaojiawei.cc

                                                未完待续...

你可能感兴趣的:(JAVA,WEB)