0
点赞
收藏
分享

微信扫一扫

JavaWeb学习指南 - Servlet详解

全栈顾问 2022-01-05 阅读 79

1. Servlet 核心技术

  • Servlet-Api 的 maven 配置
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.0</version>
      <scope>compile</scope>
    </dependency>

1.1 创建HelloServlet

  • 创建 HelloServlet类,并继承 HttpServlet 类, 重写 Service 和 doGet 方法
package cn.knightzz.servlet;


import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author 王天赐
 * @title: HelloServlet
 * @projectName lg-java-train
 * @description:
 * @website http://knightzz.cn/
 * @github https://github.com/knightzz1998
 * @date 2021/12/30 14:20
 */
public class HelloServlet  extends HttpServlet{

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("begin =====> HelloServlet doGet");
        super.doGet(req, resp);
        System.out.println("end =====> doGet");
    }

    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        System.out.println("begin =====> HelloServlet ServletRequest");
        super.service(req, res);
        System.out.println("end =====> HelloServlet ServletRequest");
    }
}

  • 在 web.xml 中配置
<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <!-- 配置ServletName 和 ServletClass 的映射-->
  <servlet>
    <servlet-name>HelloServlet</servlet-name>
    <servlet-class>cn.knightzz.servlet.HelloServlet</servlet-class>
  </servlet>

  <!-- 配置Servlet访问地址-->
  <servlet-mapping>
    <!-- HelloServlet是Servlet类的别名,与上述名称必须相同 -->
    <servlet-name>HelloServlet</servlet-name>
    <!--在浏览器中访问的地址-->
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>

</web-app>

  • 运行以后 在浏览器输入 http://localhost:8080/web-servlet-01/hello 即可

  • 这里需要注意的是 : web-servlet-01 是我自己 配置的 Application context 路径

    image-20211231094153103
  • 访问 /hello 路径后 会出现如下界面

    image-20211231094330279

  • 我们可以在控制台看到打印的数据表示实际访问到了 HelloServlet

image-20211231094348466

1.2 Servlet接口

1.2.1 Servlet基本概念

1.2.2 Servlet通用方法

image-20211231094755233

1.2.3 GenericServlet类

public abstract class GenericServlet 
    implements Servlet, ServletConfig, java.io.Serializable
  • javax.servlet.GenericServlet类主要用于定义一个通用的、与协议无关的servlet,该类实现了Servlet接口。

  • 若编写通用servlet,只需重写service抽象方法即可

  • 常用的方法

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

1.3 HttpServlet类

1.3.1 基本概念

  • javax.servlet.http.HttpServlet类是个抽象类并继承了GenericServlet类。
  • 用于创建适用于网站的HTTP Servlet,该类的子类必须至少重写一个方法

1.3.2 常用方法

image-20211231095610285

1.4 Servlet生命周期

image-20211231101642801

  • 构造方法只被调用一次,当第一次请求 Servlet 时调用构造方法来创建 Servlet 的实例。

  • init() 方法只被调用一次,当创建好 Servlet 实例后立即调用该方法实现 Servlet 的初始化。

  • service() 方法被多次调用,每当有请求时都会调用 service() 方法来用于请求的响应。

  • destroy() 方法只被调用一次,当该 Servlet 实例所在的 Web 应用被卸载前调用该方法来释放当前占用的资源

1.4.1 实现Servlet接口

package cn.knightzz.servlet;

import javax.servlet.*;
import java.io.IOException;

/**
 * @author 王天赐
 * @title: MyServlet
 * @projectName lg-java-train
 * @description: 直接实现Servlet接口
 * @website http://knightzz.cn/
 * @github https://github.com/knightzz1998
 * @date 2022/1/1 20:43
 */
public class MyServlet implements Servlet {

    public MyServlet() {
        System.out.println("=======> MyServlet create Object");
    }

    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("=======> MyServlet init");
    }

    @Override
    public ServletConfig getServletConfig() {
        return this.getServletConfig();
    }

    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        System.out.println("=======> MyServlet service be visited");
    }

    @Override
    public String getServletInfo() {
        return this.getServletInfo();
    }

    @Override
    public void destroy() {
        System.out.println("=======> MyServlet destroy");
    }
}

如下: 可以看到在启动Tomact服务器后, tomcat 容器会自动实例化 Servlet类,

  1. Tomact容器创建Servlet实例
  2. Servlet初始化
  3. Servlet接收请求,反复调用 service() 方法
  4. Tomact服务器关闭,调用 destroy() 销毁实例
=======> MyServlet create Object
=======> MyServlet init
=======> MyServlet service be visited
C:\Dev\apache-tomcat-8.5.57\bin\catalina.bat stop
Using CATALINA_BASE:   "C:\Users\wangtianci\AppData\Local\JetBrains\IntelliJIdea2021.3\tomcat\21aec25b-5b21-4d35-831c-70b66daff382"
Using CATALINA_HOME:   "C:\Dev\apache-tomcat-8.5.57"
Using CATALINA_TMPDIR: "C:\Dev\apache-tomcat-8.5.57\temp"
Using JRE_HOME:        "C:\Dev\jdk8"
Using CLASSPATH:       "C:\Dev\apache-tomcat-8.5.57\bin\bootstrap.jar;C:\Dev\apache-tomcat-8.5.57\bin\tomcat-juli.jar"
01-Jan-2022 21:42:06.996 信息 [main] org.apache.catalina.core.StandardServer.await 通过关闭端口接收到有效的关闭命令。正在停止服务器实例。
01-Jan-2022 21:42:06.996 信息 [main] org.apache.coyote.AbstractProtocol.pause 暂停ProtocolHandler["http-nio-8080"]
01-Jan-2022 21:42:07.502 信息 [main] org.apache.catalina.core.StandardService.stopInternal 正在停止服务[Catalina]
01-Jan-2022 21:42:07.515 信息 [main] org.apache.coyote.AbstractProtocol.stop 正在停止ProtocolHandler ["http-nio-8080"]
01-Jan-2022 21:42:07.517 信息 [main] org.apache.coyote.AbstractProtocol.destroy 正在摧毁协议处理器 ["http-nio-8080"]
=======> MyServlet destroy
Disconnected from server

1.5 Servlet注解写法

  • 我们可以使用注解 @WebServlet(“URL”) 去简化Servlet, 这样不需要再 web.xml 中配置
  • **这里需要特别注意 urlPatterns 一定要加 / **
  • @WebServlet(name = "MyWebServlet", urlPatterns = "/my-web-servlet")
    • name 等价于 servlet-name urlPatterns 等价于 url-pattern
package cn.knightzz.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author 王天赐
 * @title: MyWebServlet
 * @projectName lg-java-train
 * @description: 使用注解简化Servlet配置
 * @website http://knightzz.cn/
 * @github https://github.com/knightzz1998
 * @date 2022/1/2 14:14
 */
@WebServlet(name = "MyWebServlet", urlPatterns = "/my-web-servlet")
public class MyWebServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("==================> MyWebServlet doGet Be Visited");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("==================> MyWebServlet doPost Be Visited");
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("==================> MyWebServlet Service Be Visited");
        super.service(req, resp);
    }
}

  • 直接访问 http://localhost:8080/web-servlet-01/my-web-servlet 即可
  • 这里需要注意 service 方法作用是决定请求是由 doGet 处理还是 doPost 处理

1.6 POST和GET请求

1.6.1 POST请求和GET请求的基本使用

  • GET请求特点: 会将请求数据添加到请求URL地址的后面,只能提交少量的数据、不安全

  • 如果需要处理POST请求则需要重写 doPost 方法

package cn.knightzz.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author 王天赐
 * @title: MyWebServlet
 * @projectName lg-java-train
 * @description: 使用注解简化Servlet配置
 * @website http://knightzz.cn/
 * @github https://github.com/knightzz1998
 * @date 2022/1/2 14:14
 */
@WebServlet(name = "MyWebServlet", urlPatterns = "/my-web-servlet")
public class MyWebServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("==================> MyWebServlet doGet Be Visited");
        // 可以直接让Get请求让Post处理
        this.doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("==================> MyWebServlet doPost Be Visited");
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("==================> MyWebServlet Service Be Visited");
        // 获取请求方法类型
        String method = req.getMethod();
        System.out.println("method = " + method);
        switch (method) {
            case "GET":
                doGet(req, resp);
                break;
            case "POST":
                doPost(req, resp);
                break;
        }
    }
}

  • webapp 目录下面创建 request.html 分别添加链接和表单
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>POST和GET请求</title>
</head>
<body>

<a href="my-web-servlet">GET请求</a>
<hr/>
<form action="my-web-servlet" method="post">
    <input type="submit" />
</form>

</body>
</html>
  • 访问 http://localhost:8080/web-servlet-01/request.html即可查看GET请求POST请求

1.6.2 ServletRequest接口

  • javax.servlet.ServletRequest 接口主要用于向servlet提供客户端请求信息,可以从中获取到任何请求信息。

  • Servlet 容器创建一个ServletRequest对象,并将其作为参数传递给 Servlet 的 service方法

  • 常用方法

    • String getParameter(Stringname) 以字符串形式返回请求参数的值,如果该参数不存在,则返回值
    • String[] getParameterValues(String name) 返回一个字符串对象数组,其中包含给定请求参数所具有的所有值,如果该参数不存在,则返回空值
    • Enumeration getParameterNames() 返回包含此请求中包含的参数名称的字符串对象的枚举。如果请
      求没有参数,则方法返回空枚举
    • Map<String, String[]> getParameterMap() 返回请求参数的键值对,一个键可以对应多个值
    • String getRemoteAddr() 返回发送请求的客户端或最后一个代理的IP地址
    • int getRemotePort() 返回发送请求的客户端或最后一个代理的端口号

1.6.3 HttpServletRequest接口

  • javax.servlet.http.HttpServletRequest接口是ServletRequest接口的子接口,主要用于提供HTTP
    请求信息的功能。

  • 不同于表单数据,在发送HTTP请求时,HTTP请求头直接由浏览器设置。

  • 可直接通过HttpServletRequest对象提供的一系列get方法获取请求头数据

  • 常用方法

    • String getRequestURI() 返回此请求的资源路径信息
    • StringBuffer getRequestURL() 返回此请求的完整路径信息
    • String getMethod() 返回发出此请求的HTTP方法的名称,例如GET、POST
    • String getQueryString() 返回路径后面请求中附带的参数
    • String getServletPath() 返回此请求中调用 servlet 的路径部分
  • 代码演示

        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("MyParams doPost ====>");
    
            // 获取请求资源路径
            System.out.println("req.getRequestURI() = " + req.getRequestURI());
            // 获取请求的完整路径
            System.out.println("req.getRequestURL() = " + req.getRequestURL());
            // 获取HTTP请求方式
            System.out.println("req.getMethod() = " + req.getMethod());
        }
    

    结果如下 :

    req.getRequestURI() = /web-servlet-01/my-params
    req.getRequestURL() = http://localhost:8080/web-servlet-01/my-params
    req.getMethod() = GET
    

#### 1.6.4 ServletResponse接口

  • javax.servlet.ServletResponse接口用于定义一个对象来帮助Servlet向客户端发送响应。

  • Servlet容器创建ServletResponse对象,并将其作为参数传递给servletservice方法。

  • 常用方法

    image-20220104162955702

1.6.5 HttpServletResponse接口

  • javax.servlet.http.HttpServletResponse接口继承ServletResponse接口,以便在发送响应时提供

    特定于HTTP的功能。

  • 常用方法

    image-20220104163203744

  • 使用示例

    @WebServlet(name = "MyResponseServlet", urlPatterns = "/response")
    public class MyResponseServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            this.doPost(req, resp);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            // 设置响应码
            resp.setContentType("text/html;charset=utf-8");
            // 获取响应输出流
            PrintWriter writer = resp.getWriter();
            // 利用输出流输出信息
            writer.println("<html><body>" +
                    "Hello Servlet" +
                    "</body></html>");
            // 关闭流
            writer.close();
        }
    }
    
    

    如下图所示, 直接在页面输出 Hello Servlet

    image-20220105140702655

举报

相关推荐

0 条评论