技术点7:Servlet程序

时间:2020-11-10 16:45:00 来源:互联网 作者: 神秘的大神 字体:

Servlet程序

一、Servlet 技术

1、什么是 Servlet

  ① Servlet 是 JavaEE 规范之一。规范就是接口

  ② Servlet 就 JavaWeb 三大组件之一。三大组件分别是:Servlet 程序、Filter 过滤器、Listener 监听器。

  ③ Servlet 是运行在服务器上的一个 java 小程序,它可以接收客户端发送过来的请求,并响应数据给客户端。

2、手动实现 Servlet 程序

  ① 编写一个类去实现Servlet接口:

 

 

 

  ② 重写service()方法,处理请求,并响应数据:

package com.zixue.servlet;

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

/**
 * @author Mr Guo
 * @create 2020-11-10 10:57
 */
public class HelloServlet implements Servlet {
    @Override
    public void init(ServletConfig config) throws ServletException {

    }

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

    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        System.out.println("HelloServlet被访问了");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

  ③ 到web.xml中去配置Servlet程序的访问地址:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
<!--    servlet标签给Tomcat服务器配置Servlet程序-->
    <servlet>
<!--        servlet-name标签给Servlet程序起一个别名(一般是类名)-->
        <servlet-name>HelloServlet</servlet-name>
<!--        servlet-class标签是Servlet程序的全类名-->
        <servlet-class>com.zixue.servlet.HelloServlet</servlet-class>
    </servlet>
<!--    servlet-mapping标签给Servlet程序配置访问地址-->
    <servlet-mapping>
<!--        servlet-name标签是配置的访问地址给哪个Servlet程序使用的-->
        <servlet-name>HelloServlet</servlet-name>
<!--        url-pattern标签配置访问地址
            / : 在服务器解析的时候,表示的路径为:http://ip:port/工程路径 (映射到web目录)
            /helloServlet : 表示这个Servlet程序的访问地址为:http://ip:port/工程路径/helloServlet
-->
        <url-pattern>/helloServlet</url-pattern>
    </servlet-mapping>

</web-app>

3、url 地址到 Servlet 程序的访问

 

 

4、Servlet 的生命周期

   ① 执行Servlet构造器方法;

  ② 执行init初始化方法;

  ③ 执行service方法;

  ④ 执行destroy销毁方法。

注:

  ① 和②是在第一次访问创建Servlet程序的时候调用;

  ③ 每次访问都会调用;

  ④ 在整个web工程停止的时候调用。

package com.zixue.servlet;

import com.sun.media.sound.SoftTuning;

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

/**
 * @author Mr Guo
 * @create 2020-11-10 10:57
 */
public class HelloServlet implements Servlet {

    public HelloServlet() {
        System.out.println("1.构造器方法执行");
    }

    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("2.init初始化方法执行");
    }

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

    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        System.out.println("3.HelloServlet被访问了");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {
        System.out.println("4.执行destroy销毁方法");
    }
}

  浏览器地址栏第一次访问:

 

 

 

 

 

   继续访问:

 

 

   当停止整个web工程的时候:

 

 

 

 

 

 5、GET 和 POST 请求的分发处理

  我们在service方法中做请求的分发处理。service方法的形参位置有一个ServletRequest接口,它有一个子接口HttpServletRequest,其内部有一个方法getMethod(),这个方法可以实现请求的分发处理。

 

 

   在web下创建一个form.html文件,提供请求的方式GET/POST:

 

 

   form.html文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>请求的分发</title>
</head>
<body>
<form action="http://localhost:8080/06_servlet/helloServlet1" method="get">
    <input type="submit" />
</form>
</body>
</html>

  要访问的Servlet程序:HelloServlet1.java

package com.zixue.servlet;

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

/**
 * @author Mr Guo
 * @create 2020-11-10 11:26
 */
public class HelloServlet1 implements Servlet {
    @Override
    public void init(ServletConfig config) throws ServletException {

    }

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

    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        //1.类型转换:ServletRequest -- httpServletRequest(它有getMethod())
        HttpServletRequest httpServletRequest = (HttpServletRequest) req;
        //2.获取请求的方式
        String method = httpServletRequest.getMethod();
        if ("GET".equals(method)){
            doGet();
        }else if ("POST".equals(method)){
            doPost();
        }
    }

    /**
     * 做GET请求的操作
     */
    public void doGet(){
        System.out.println("GET请求");
        System.out.println("GET请求");
    }

    /**
     * 做POST请求的操作
     */
    public void doPost(){
        System.out.println("POST请求");
        System.out.println("POST请求");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

  浏览器地址栏访问form.html文件:

 

 

 

 

 

   结果如下:

 

 

   修改form.html文件中的请求方式为post:

 

 

   再次访问效果如下:

 

 

 

6、通过继承 HttpServlet 实现 Servlet 程序

  一般在实际项目开发中,都是使用继承 HttpServlet 类的方式去实现 Servlet 程序。

具体实现步骤:

  ① 编写一个类去继承HttpServlet类:

  ② 根据业务需要重写doGet()或doPost()方法:

  ③ 到web.xml中配置Servlet程序的访问地址;

HelloServlet2.java:

package com.zixue.servlet;

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

/**
 * @author Mr Guo
 * @create 2020-11-10 11:53
 */
public class HelloServlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("HelloServlet2的doGet方法");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("HelloServlet2的doPost方法");
    }
}

web.xml:

 

 

 7、使用 IDEA 创建 Servlet 程序 

 

 

 配置Servlet的信息:

 

 

 web.xml中配置访问地址:

 

 

 8、Servlet 类的继承体系

 

 

 

二、ServletConfig 类

  ServletConfig 类从类名上来看,就知道是 Servlet 程序的配置信息类。
  Servlet 程序和 ServletConfig 对象都是由 Tomcat 负责创建,我们负责使用。
  Servlet 程序默认是第一次访问的时候创建,ServletConfig 是每个 Servlet 程序创建时,就创建一个对应的 ServletConfig 对象。

1、ServletConfig 类的三大作用

  ① 获取Servlet程序的别名servlet-name的值;

  ② 获取初始化参数init-param的值;

  ③ 获取ServletContext对象。

web.xml中的配置:

 

 

 Servlet中的代码:

 

 

 效果如下:

 

 

 注意点:

  

 

 

 三、ServletContext 类

1、什么是 ServletContext?

  ① ServletContext 是一个接口,它表示 Servlet 上下文对象;

  ② 一个 web 工程,只有一个 ServletContext 对象实例;

  ③ ServletContext 对象是一个域对象;

  ④ ServletContext 是在 web 工程部署启动的时候创建。在 web 工程停止的时候销毁。

什么是域对象?
  域对象,是可以像 Map 一样存取数据的对象,叫域对象。
  这里的域指的是存取数据的操作范围,整个 web 工程。

 

 

 2、ServletContext 类的四个作用

  ① 获取 web.xml 中配置的上下文参数 context-param;

  ② 获取当前的工程路径,格式: /工程路径;

  ③ 获取工程部署后在服务器硬盘上的绝对路径;

  ④ 像 Map 一样存取数据。

web.xml 中的配置: 

 

 演示ServletContext作用的代码:

package com.zixue.servlet;

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

/**
 * @author Mr Guo
 * @create 2020-11-10 13:41
 */
public class Servlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取web.xml中配置的上下文参数
        ServletContext context = getServletContext();
        String username = context.getInitParameter("username");
        System.out.println("上下文参数username = " + username);
        String password = context.getInitParameter("password");
        System.out.println("上下文参数password = " + password);

        //2.获取当前的工程路径 格式:/工程路径
        System.out.println("当前工程路径:" + context.getContextPath());

        //3.获取工程部署后在服务器磁盘上的绝对路径
        System.out.println("工程部署的路径是:" + context.getRealPath("/"));
    }
}

效果如下:

 

 当前的工程就在服务器磁盘的如下位置:

 

 

ServletContext像Map一样存取数据:

ContextServlet1代码:

package com.zixue.servlet;

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

/**
 * @author Mr Guo
 * @create 2020-11-10 13:57
 */
public class ContextServlet1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = getServletContext();
        System.out.println("保存之前,ContextServlet1获取key的值是:" + context.getAttribute("key"));
        context.setAttribute("key", "value");
        System.out.println("保存之后,ContextServlet1获取key的值是:" + context.getAttribute("key"));
    }
}

ContextServlet2代码:

package com.zixue.servlet;

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

/**
 * @author Mr Guo
 * @create 2020-11-10 13:59
 */
public class ContextServlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = getServletContext();
        System.out.println("ContextServlet2中获取的key值为:" + context.getAttribute("key"));
    }
}

  注:ServletContext对象在整个web工程只有一份,域数据未保存之前是无法获取到的。当域数据保存之后,无论在哪个Servlet程序中都可以进行访问。

 

四、HTTP 协议

1、什么是 HTTP 协议

什么是协议?
  协议是指双方,或多方,相互约定好,大家都需要遵守的规则,叫协议。
  所谓 HTTP 协议,就是指,客户端和服务器之间通信时,发送的数据,需要遵守的规则,叫 HTTP 协议。
  HTTP 协议中的数据又叫报文。 

2、请求的 HTTP 协议格式

 

 

 

 

 

 

 

 3、哪些是 GET 请求,哪些是 POST 请求

GET请求:

  ① form标签中的method=get

  ② a标签

  ③ link标签引入css

  ④ script标签引入js

  ⑤ img标签引入图片

  ⑥ iframe引入html页面

  ⑦ 浏览器地址栏输入地址敲回车

POST请求:

  form标签中的method=post

 

4、响应的 HTTP 协议格式

 

 

 

 

5、常用的响应码说明

  200  ---  请求成功

  302  ---  请求重定向

  404  ---  浏览器地址栏地址找不到

  500  ---  服务器代码错误

 

五、HttpServletRequest 类

1、HttpServletRequest 类有什么作用

  每次只要有请求进入 Tomcat 服务器,Tomcat 服务器就会把请求过来的 HTTP 协议信息解析好封装到 Request 对象中。然后传递到 service 方法(doGet 和 doPost)中给我们使用。我们可以通过 HttpServletRequest 对象,获取到所有请求的信息。

2、HttpServletRequest 类的常用方法

 

 

RequestAPIServlet.java:

package com.zixue.servlet;

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

/**
 * @author Mr Guo
 * @create 2020-11-10 14:51
 */
public class RequestAPIServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取请求的资源路径
        System.out.println("URI = " + req.getRequestURI());
        //2.获取请求的统一资源定位符
        System.out.println("URL = " + req.getRequestURL());
        //3.获取客户端的ip地址
        System.out.println("客户端ip地址为:" + req.getRemoteHost());
        //4.获取请求头
        System.out.println("请求头User-Agent的值为:" + req.getHeader("User-Agent"));
        //5.获取请求参数
        System.out.println("请求参数username = " + req.getParameter("username"));
        System.out.println("请求参数password = " + req.getParameter("password"));
        //6.获取请求的方式
        System.out.println("请求方式为:" + req.getMethod());
    }
}

浏览器地址栏访问:

 

 效果如下:

 

 3、POST 请求的中文乱码解决

 

 

4、请求的转发 

什么是请求的转发?
  请求转发是指,服务器收到请求后,从一个资源跳转到另一个资源的操作叫请求转发。

 

 

Servlet1代码:

public class Servlet1 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //请求的转发
        //1.获取请求的参数
        String username = request.getParameter("username");
        System.out.println("Servlet1中的请求参数username = " + username);

        //2.向request域中保存数据
        request.setAttribute("key","value");

        //3.获取请求转发的对象
        /*
        请求转发必须要以斜杠打头,/ 斜杠表示地址为:http://ip:port/工程名/ , 映射到 IDEA 代码的 web 目录
         */
        RequestDispatcher requestDispatcher = request.getRequestDispatcher("/servlet2");

        //4.前往Servlet2
        requestDispatcher.forward(request,response);
    }
}

Servlet2代码:

public class Servlet2 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取请求的参数
        String username = request.getParameter("username");
        System.out.println("Servlet2中的请求参数username = " + username);

        //2.获取request域中保存的数据
        System.out.println(request.getAttribute("key"));

        //3.处理自己的业务
        System.out.println("Servlet2自己的业务");
    }
}

浏览器地址栏访问:

 

 效果如下:

 

 

5、base 标签的作用

在web目录下有一个index.html页面,内容如下:

 

 在web/a/b目录下有一个c.html页面,内容如下:

 

 目录结构如下:

 

   启动当前工程,默认会访问当前工程的index.html页面:

 

   点击超链接a标签会跳转到c.html页面:

 

   它们之间的跳转是没有任何问题的(可以来回跳转)。解释如下:

    所有的相对路径在跳转的时候都会相对于浏览器地址栏中的地址进行跳转。在index.html页面,浏览器地址栏中的地址是:http://localhost:8080/06_servlet/index.html。映射到当前工程的web目录下。点击超链接,超链接的地址为:a/b/c.html。此时的跳转没有任何问题。在c.html页面,浏览器地址栏的地址为:http://localhost:8080/06_servlet/a/b/c.html。点击超链接,超链接地址为:../../index.html。父亲的父亲刚好映射到web目录,此时的跳转也没有问题。

 

使用请求转发进行跳转:

   Servlet程序ForwardC.java如下:

 

   工程启动后,默认访问index.html页面,此时,我们访问ForwardC这个Servlet程序:http://localhost:8080/06_servlet/forwardC。会转发到c.html页面:

 

  此时,点击超链接,超链接地址为:../../index.html。浏览器地址栏地址为:http://localhost:8080/06_servlet/forwardC。这时已经无法访问到index.html页面了。

那么,如何解决这个问题呢?

使用base标签:

 

 

6、Web 中的相对路径和绝对路径

 

 

7、web 中 / 斜杠的不同意义

 

 

六、HttpServletResponse 类

1、HttpServletResponse 类的作用

  HttpServletResponse 类和 HttpServletRequest 类一样。每次请求进来,Tomcat 服务器都会创建一个 Response 对象传递给 Servlet 程序去使用。HttpServletRequest 表示请求过来的信息,HttpServletResponse 表示所有响应的信息,我们如果需要设置返回给客户端的信息,都可以通过 HttpServletResponse 对象来进行设置

2、两个输出流的说明

 

 

  两个流同时只能使用一个。
  使用了字节流,就不能再使用字符流,反之亦然,否则就会报错。

3、如何往客户端回传数据

public class ResponseIOServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter writer = response.getWriter();
        writer.write("response's content");
    }
}

效果如下:

 

 4、响应的乱码解决

  当我们试图向客户端回传带有中文的数据时:

 

 

  会出现如下的乱码问题:

 

   怎么解决呢?

 

   效果如下:

 

 

5、请求重定向

  请求重定向,是指客户端给服务器发请求,然后服务器告诉客户端说。我给你一些地址。你去新地址访问。叫请求重定向(因为之前的地址可能已经被废弃)。

 

 Response1代码:

 

 Response2代码:

 

 效果如下: