javaweb(07) Servlet详解

javaweb(07) Servlet详解

什么是Servlet

简介

  • 从广义上来讲,Servlet规范是Sun公司制定的一套技术标准,包含与web应用相关的一系列接口,是web应用实现方式的宏观解决方案。而具体的Servlet容器负责提供标准的实现。
  • 从狭义上讲,Servlet指的是javax.servlet.Servlet接口及其子接口,也可以值实现了Servlet接口的实现类。
  • Servlet作为服务端的一个组件,它的本意是“服务端的小程序”。Servlet的实例对象由Servlet容器负责创建;Servlet的方法由容器在特定情况下调用;Servlet容器会在web应用卸载时销毁Servlet对象的实例
  • servlet 是运行在 Web 服务器中的小型 Java 程序。servlet 通常通过 HTTP(超文本传输协议)接收和响应来自 Web 客户端的请求。

Servlet作用

  1. 接受请求
  2. 处理请求
  3. 完成响应

第一个Servlet程序

步骤

1、编写一个类去实现 Servlet 接口

2、实现 service 方法,处理请求,并响应数据

3、到 web.xml 中去配置 servlet 程序的访问地址

具体实现及注释

1、编写一个类去实现 Servlet 接口

image-20200810003314855

2、实现 service 方法,处理请求,并响应数据

image-20200810002430291

3、到 web.xml 中去配置 servlet 程序的访问地址

image-20200810003244877

完成前面步骤后,启动服务器,在浏览器上输入 http://localhost:8080/05_servlet/hello即可发出请求,服务器会响应。

image-20200810003619121

扫描二维码关注公众号,回复: 11906348 查看本文章

实现流程图解

image-20200810003756653

Servlet的生命周期

  • servlet是跑在tomcat服务器上的,而servlet对象通过servlet容器在服务器上创建。
  • servlet的生命周期是指servlet从创建到销毁的过程

测试Servlet各个方法的运行时机

测试类代码:

package com.deserts.servlet1;

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

/**
 * @ClassName TestServlet
 * @Description 测试servlet的生命周期
 * @Author deserts
 * @Date 2020/8/9 17:38
 */
public class TestServlet implements Servlet {
    
    
    public TestServlet(){
    
    
        System.out.println("我是构造器...\n");
    }
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
    
    
        System.out.println("init...\n");
    }

    @Override
    public ServletConfig getServletConfig() {
    
    
        System.out.println("getServletConfig...\n");
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
    
    
        System.out.println("service...\n");
    }

    @Override
    public String getServletInfo() {
    
    
        System.out.println("getServletInfo...\n");
        return null;
    }

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

配置文件:

image-20200810131223781

启动服务器,发现没有方法被调用:

image-20200810131449813

访问test资源时,发现先调用构造方法创建对象,再调用初始化方法,再调用service方法:

image-20200810131647970

再次访问test资源时,发现只调用了service方法,并没有再次调用构造器创建对象:

image-20200810131815541

当我们断开与服务器的连接时,发现在断开前调用了destroy方法,销毁对象:

image-20200810131943748

servlet生命周期的总结

当我们第一次请求访问test资源时:

  1. 创建一个servlet对象
  2. 调用init方法,初始化servlet
  3. 调用service方法处理请求

以后再次请求:

  1. 只调用service方法处理请求

项目从服务器卸载时:

  1. 服务器会调用destroy方法销毁对象

servlet是一个单例,多线程运行。

ServletConfig

ServletConfig类的三大作用

  1. 可以获取 Servlet 程序的别名 servlet-name 的值

  2. 获取初始化参数 init-param

  3. 获取 ServletContext 对象

代码实现

配置文件主要内容:

image-20200810185157260

servlet主要代码(也可以在方法外声明servletConfig变量,在init方法初始化,在service中使用):

image-20200810185554624

控制台输出结果:

image-20200810191038895

ServletContext

什么是ServletContext

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

  2. 一个 web 工程,只有一个 ServletContext 对象实例。

  3. ServletContext 对象是一个域对象。(application)

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

什么是域对象?

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

ServletContext的四个作用

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

  2. 获取当前的工程路径,格式: /工程路径

  3. 获取工程部署后在服务器硬盘上的绝对路径 (资源的真实路径)

  4. 像 Map 一样存取数据

代码实现

配置文件主要内容:

image-20200810195414211

前三个功能的验证:
image-20200810200428872

运行结果:

image-20200810200505273

第四个作用在四大域对象学完一起总结。

HttpServlet

实际开发中我们继承HttpServlet抽象类去实现Servlet程序。

HttpServlet源码解析

继承体系

HttpServlet继承GenericServlet,而GenericServlet继承了Servlet:

image-20200810201454654

服务器运行Servlet,那为什么实现HttpServlet就可以了呢?可以从Servlet接口和GenericServlet中找到答案

Servlet接口

image-20200810202828534

Servlet接口有几个抽象方法,其中service是处理请求的核心方法,接下来看看GenericServlet!

GenericServlet抽象类

GenericServlet抽象类没有太大的特别之处,大boss是HttpServlet。

 public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

HttpServlet抽象类

查看HttpServlet的类结构,发现该类重载了service方法,两个方法参数类型不同:

image-20200810203913588

接下来可以看看参数类型未ServletRequest和ServletResponse的方法:

image-20200810204100532

可以知道,该方法将两个参数进行强转,并调用了另一个重载的service方法,接下来可以看看这个方法:

第一部分,获取http请求的类型,如果为GET类型,调用doGet方法,处理请求:

image-20200810204634737

第二部分,如果为其它类型的,根据类型处理请求,若请求类型不是http类型的,抛异常:

image-20200810205026211

总结

至此可知,继承HttpServlet的类处理请求,服务器会调用原始的service方法,在该方法中对两个参数进行强转,再调用与强转后类型匹配的service重载方法,在该重载方法中,会获取客户端发出的HTTP请求的类型,再根据请求类型调用相应的方法处理请求,因此,我们在继承HttpServlet抽象类后,只需要重写doXXX方法,服务器会自动调用,我们一般重写doGet方法和doPost方法。

过程图解

image-20200810210033003

HttpServletResponse类的作用

作用

  1. 给浏览器响应字符串
  2. 可以重定向到一个页面或其它资源,重定向就是告诉浏览器重新请求别的资源

示例

image-20200810211856498

HttpServletRequest类的作用

作用

  1. 获取请求数据。当键值是一对一时(如文本框),使用getParameter()获取;当键值是多对一时(如多选框),使用getParameterValues()获取多选框的内容。
  2. 获取请求头信息
  3. 转发一个页面或资源
  4. 作为域对象共享数据(request)

示例

核心代码:

image-20200810220545533

index.html表单代码:

image-20200810220622211

服务器开启后的页面:

image-20200810220717427

提交后的页面:

image-20200810220803359

控制台输出:

image-20200810220832245

转发和重定向的区别

转发和重定向过程图解

转发:

image-20200810221902056

重定向:

image-20200810221934266

区别

转发 重定向
浏览器地址 不会变化 会变化
Request 同一个请求 两次请求
API Request对象 Response对象
位置 服务器内部完成 浏览器完成
WEB-INF文件夹 可以访问 不能访问
共享请求域数据 可以共享 不可以共享
目标资源 必须是当前web应用中的资源 不局限于当前web应用

乱码问题

  • 编码:将字符转换为二进制数
  • 解码:将二进制数转换为字符
  • 乱码:一段文本,使用A字符集编码,使用B字符集解码,就会产生乱码。所以解决乱码问题的根本办法就是统一编码和解码的字符集。

响应乱码

产生原因:服务器响应时,浏览器不知道服务器传输的数据的内容类型和编码集

解决方案:告诉浏览器传输的数据的内容类型和编码集

image-20200810232148607

post乱码

产生原因:浏览器将数据编码并提交上来,但是服务器不知道编码规则

解决方法:让服务器知道编码规则即可,重新设置请求的编码格式

image-20200810234955206

get乱码

出现原因:浏览器将地址栏也编码,服务器不知道,而且8080接收到url后,已经按默认解码规则解码了

解决方法:修改tomcat服务器server.xml配置文件,在8080端口号处增加URIEncoding=“UTF-8”

image-20200810235821995

路径问题

相对路径与绝对路径

image-20200811204550881

转发和重定向绝对路径的注意点

1.转发中使用绝对路径写时,/表示从项目的根路径开始,即http://localhost:8080/项目名/如:

request.getRequestDispatcher("/index.html").forword(request,response);

表示的地址是:http://localhost:8080/05_servlet/index.html

2.重定向用绝对路径表示,/表示从Tomcat的根目录开始,即http://localhost:8080/如:

response.sendRedirect("/05_servlet/pages/a.html");

表示的路径是:http://localhost:8080/05_servlet/pages/a.html

重定向时我们动态获取项目的路径,不写死使移植性更高:

response.sendRedirect(request.getContextPath() + "/page/a.html");

base标签的使用

使用base标签,作用就是指定页面上的路径的基础路径,所有路径都是以base标签中指定的基础路径开始。只有相对路径的写法,会按照base标签指定的基础路径来拼接新的路径。如:

<base href="htto://localhost:8080/05_servlet/" />
<a href = "path.html"/>

猜你喜欢

转载自blog.csdn.net/weixin_45834777/article/details/107944582
今日推荐