Servlet学习阶段一

什么是servlet

1、Servlet 是 JavaEE 规范之一。规范就是接口 。
2、Servlet 就 JavaWeb 三大组件之一。三大组件分别是:Servlet 程序、Filter 过滤器、Listener 监听器。
3、Servlet 是运行在服务器上的一个 java 小程序,它可以接收客户端发送过来的请求,并响应数据给客户端。

重点:servlet可以接收客户端发送过来的请求,并响应数据给服务器。

Servlet 初体验

1、编写一个类去实现 Servlet 接口
2、实现 service 方法,处理请求,并响应数据
3、到 web.xml 中去配置 servlet 程序的访问地址

现在我们来实现一下这个事情,首先创建一个JavaEE的工程:
在这里插入图片描述
然后第一步,我们在src目录下编写一个类去实现servlet接口,同时还要去实现servlet接口中为我们准备好的方法:

package com.atguigu.servlet;

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

public class HelloServelt implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        
    }

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

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

    }

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

    @Override
    public void destroy() {

    }
}

这里我们重点关注一下service方法,因为这个方法就是用来执行我们的数据请求和响应的,这里我们打印一句话:Hello Servlet被访问了。

@Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("Hello Servlet 被访问了");
    }

然后第三步,我们去给web.xml配置文件中去配置servlet程序的访问地址,不然Tomcat是不知道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.atguigu.servlet.HelloServelt</servlet-class>
    </servlet>

    <!--servlet-mapping标签给servlet程序配置Tomcat的访问地址-->
    <servlet-mapping>
        <!--servlet-name标签的作用是告诉服务器,我当前配置的地址给哪个servlet程序使用-->
        <servlet-name>HelloServlet</servlet-name>
        <!--url-pattern标签配置访问地址
            /表示什么?
            表示在服务器解析的时候,表示地址为:http://ip:port/工程路径

            /hello表示什么?
            表示地址为:http://ip:port/工程路径/hello
        -->
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

</web-app>

然后我们启动Tomcat,可以看到8080默认是$END$
在这里插入图片描述
然后我们访问hello:
在这里插入图片描述
可以看到控制台打印了信息:
在这里插入图片描述

常见的错误

1、url-pattern 中配置的路径没有以斜杠打头。
在这里插入图片描述
2、servlet-name 配置的值不存在:
在这里插入图片描述
3、servlet-class 标签的全类名配置错误:
在这里插入图片描述

url地址到Servlet地址的访问过程

在这里插入图片描述

Servlet 的生命周期

就是在整个Servlet程序执行期间会调用的一些方法,这些方法都是Servlet接口中存在的(可以参考上面的HelloServlet代码):

1、执行 Servlet 构造器方法
2、执行 init 初始化方法
上面的第一、二步,是在第一次访问,的时候创建 Servlet 程序会调用。

3、执行 service 方法
第三步,每次访问都会调用。

4、执行 destroy 销毁方法
第四步,在 web 工程停止的时候调用。

GET 和 POST 请求的分发处理

从上面的学习中我们知道,servlet中的service方法只有一个,但是我们的请求却不止一个,比如GET和POST。那么怎么进行这两种请求的分发处理呢?
我们先写一个表单,在web工程下:
在这里插入图片描述
上面的表单提交之后就会跳转到我们的HelloServle的hello地址的页面。

但我们知道,请求方式的不同那么表单做的事情肯定也是不一样的,但我们一个servlet程序中只有一个service方法,那怎么处理两种请求呢?

有一种方法是,通过ServletRequest类型的servletRequest中的getMethod()方法可以得到当前这次请求的方式名称。

这里有个idea中的小技巧,用ctrl+h可以快速查看当前类的继承和实现体系。

但是要注意,我们的ServletRequest是个接口,而且它没有对应的实现类,所以我们不能直接使用servletRequest这个实例去调用getMethod方法,但我们可以使用它的子接口HttpServletRequest来得到getMethod()方法,因为该接口有一个实现类HttpServletRequestWrapper:
在这里插入图片描述
然后我们尝试写代码去得到当前请求的方式:

@Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        //强制类型转换为HttpServletRequest
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        //然后通过HttpServletRequest类型的实例对象去调用getMethod方法
        String method = httpServletRequest.getMethod();

        System.out.println("当前请求方式为:"+method);
    }

访问可以看到控制台输出:
在这里插入图片描述
说明我们成功了。
那么现在我们就可以实现不同请求方式的分发处理了:

@Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        //强制类型转换为HttpServletRequest
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        //然后通过HttpServletRequest类型的实例对象去调用getMethod方法
        String method = httpServletRequest.getMethod();

        if("GET".equals(method)){
            System.out.println("执行GET请求操作");
        }else if("POST".equals(method)){
            System.out.println("执行POST请求操作");
        }
    }

但是当我们处理请求所对应的代码操作过多时,写在一个service方法中会显得十分臃肿,所以我们可以将不同请求的操作单独出来作为一个方法,然后我们在service方法中调用会更好:

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

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        //强制类型转换为HttpServletRequest
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        //然后通过HttpServletRequest类型的实例对象去调用getMethod方法
        String method = httpServletRequest.getMethod();

        if("GET".equals(method)){
            doGet();
        }else if("POST".equals(method)){
            doPost();
        }
    }
    //处理get请求方法
    public void doGet(){
        System.out.println("所有的get请求操作");
    }

    //处理post请求方法
    public void doPost(){
        System.out.println("所有的post请求操作");
    }

通过继承 HttpServlet 实现 Servlet 程序

一般在实际项目开发中,都是使用继承 HttpServlet 类的方式去实现 Servlet 程序。
1、编写一个类去继承 HttpServlet 类
2、根据业务需要重写 doGet 或 doPost 方法
3、到 web.xml 中的配置 Servlet 程序的访问地址

我们来实现一下这个事情:

package com.atguigu.servlet;

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

//1、先编写一个类去继承HttpServlet类,这个类是Servlet接口的一个实现类
//因为HttpServlet使用起来对比Servlet接口来说会更加方便
public class HelloServlet2 extends HttpServlet {

    //2、重写HttpServlet中的请求方法
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        super.doGet(req, resp); 这个可以去掉,重写方法自带的
        System.out.println("doGet方法");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        super.doPost(req, resp); 这个可以去掉,重写方法自带的
        System.out.println("doPost方法");
    }
}

然后去web.xml中为HelloServlet2进行地址配置:

<!--配置HelloServlet2映射地址-->
    <servlet>
        <servlet-name>HelloServlet2</servlet-name>
        <servlet-class>com.atguigu.servlet.HelloServlet2</servlet-class>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>HelloServlet2</servlet-name>
        <url-pattern>/hello2</url-pattern>
    </servlet-mapping>

然后就可以测试啦。

使用IDEA菜单快速生成Servlet程序

在这里插入图片描述
然后配置 Servlet 的信息:
在这里插入图片描述

Servlet 类的继承体系

在这里插入图片描述

ServletConfig 类

ServletConfig 类从类名上来看,就知道是 Servlet 程序的配置信息类。

Servlet 程序和 ServletConfig 对象都是由 Tomcat 负责创建,我们负责使用。

Servlet 程序默认是第一次访问的时候创建,ServletConfig 是每个 Servlet 程序创建时,就创建一个对应的 ServletConfig 对 象。

ServletConfig 类的三大作用

1、可以获取 Servlet 程序的别名 servlet-name 的值
2、可以获取初始化参数 init-param
3、可以获取 ServletContext 对象

这个类在哪里用呢?回去查看我们之前写的HelloServlet类中可以看见实现的init方法中是有ServletConfig类的实例对象的:

@Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

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

我们来测试一下上面说的作用,测试之前,我们得先去web.xml中配置一下我们待会儿要用的init-param和ServletContext:

<!--servlet标签给Tomcat配置Servlet程序-->
    <servlet>
        <!--servlet-name标签给servlet程序起一个别名(一般都是类名-->
        <servlet-name>HelloServlet</servlet-name>
        <!--servlet-class是servlet程序的全类名-->
        <servlet-class>com.atguigu.servlet.HelloServelt</servlet-class>
        <!--init-param是初始化参数,参数为KV键值对形式,
        ServletConfig对象可以通过K键来取对应的值
        并且这个初始化参数可以有多组-->
        <init-param>
            <!--param-name是参数名-->
            <param-name>username</param-name>
            <!--param-value是参数值-->
            <param-value>root</param-value>
        </init-param>
    </servlet>

然后我们通过ServletConfig对象来查看一下:

@Override
    public void init(ServletConfig servletConfig) throws ServletException {
//        1、可以获取 Servlet 程序的别名 servlet-name 的值
        System.out.println("HelloServlet程序的别名是:"+servletConfig.getServletName());
//        2、可以获取初始化参数 init-param
        System.out.println("HelloServlet程序的初始化参数username的值是:"+servletConfig.getInitParameter("username"));
//        3、可以获取 ServletContext 对象
        System.out.println("HelloServlet程序的ServletContext对象:"+servletConfig.getServletContext());

    }

注意:
每一个Servlet程序中都会有一个ServletConfig对象,我们可以通过getServletConfig()方法来静态调用得到一个ServletConfig对象,但是这个ServletConfig对象只能得到本Servlet程序中的配置信息,而不能得到其他Servlet程序中的配置信息嗷。

比如我们在HelloServlet2中调用getServletConfig方法:

package com.atguigu.servlet;

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

//1、先编写一个类去继承HttpServlet类,这个类是Servlet接口的一个实现类
//因为HttpServlet使用起来对比Servlet接口来说会更加方便
public class HelloServlet2 extends HttpServlet {

    //2、重写HttpServlet中的请求方法
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        super.doGet(req, resp); 这个可以去掉,重写方法自带的
        System.out.println("doGet方法");
        //可以直接得到ServletConfig对象
        ServletConfig servletConfig = getServletConfig();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        super.doPost(req, resp); 这个可以去掉,重写方法自带的
        System.out.println("doPost方法");
    }
}

还有一个地方要注意:
比如我们现在在HelloServlet2中写上init方法:

package com.atguigu.servlet;

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

//1、先编写一个类去继承HttpServlet类,这个类是Servlet接口的一个实现类
//因为HttpServlet使用起来对比Servlet接口来说会更加方便
public class HelloServlet2 extends HttpServlet {

    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("现在我们要做一些init操作!");
//        super.init(config); 默认重写提供的代码,引用父类的config
        //现在我们将其注释,则下面用到servletConfig的地方会报空指针异常
        
    }

    //2、重写HttpServlet中的请求方法
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        super.doGet(req, resp); 这个可以去掉,重写方法自带的
        System.out.println("doGet方法");
        ServletConfig servletConfig = getServletConfig();
        
        System.out.println("HelloServlet程序的别名是:"+servletConfig.getServletName());
        System.out.println("HelloServlet程序的初始化参数username的值是:"+servletConfig.getInitParameter("username"));
        System.out.println("HelloServlet程序的ServletContext对象:"+servletConfig.getServletContext());

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        super.doPost(req, resp); 这个可以去掉,重写方法自带的
        System.out.println("doPost方法");
    }
}

现在我们访问会报空指针异常:
在这里插入图片描述
所以我们一定要在重写了init时写上上面被注释掉的那句代码:

super.init(config);

为什么?

首先我们要注意这个getServletConfig是从哪里获取到的ServletConfig的实例对象。

在这里插入图片描述

可以看到该方法是GenericServlet中的方法。
之前我们说过,GenericServlet类实现了Servlet接口,做了很多空实现,并持有一个ServletConfig类的引用,且对ServletConfig的使用做了一些方法。

在这里插入图片描述
而这个config对象就是GenericServlet中定义的常量:
在这里插入图片描述
而在这个GenericService中也有init方法,这个类在init方法中将这个类中的config对象给保存起来了:
在这里插入图片描述
此时我们再来看刚刚的代码:

@Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("现在我们要做一些init操作!");
//        super.init(config); 默认重写提供的代码,引用父类的config
        //现在我们将其注释,则下面用到servletConfig的地方会报空指针异常
        
    }

父类与子类中都含有init方法,那么根据多态的知识则对象调用的init只会是我们这个类HelloServlet2中的init方法,那么我们刚刚看源码时在GenericServlet(即我们的父类)类中的保存config对象的操作就会丢失。所以使用config对象时会报空指针异常,所以我们必须写上super.init(config);这可以让我们得到父类中保存起来的config对象。

ServletContext 类

什么是 ServletContext?

1、ServletContext 是一个接口,它表示 Servlet 上下文对象
2、一个 web 工程,只有一个 ServletContext 对象实例。
3、ServletContext 对象是一个域对象。
4、ServletContext 是在 web 工程部署启动的时候创建。在 web 工程停止的时候销毁。

什么是域对象?

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

在这里插入图片描述

ServletContext 类的四个作用

1、获取 web.xml 中配置的上下文参数 context-param
2、获取当前的工程路径,格式: /工程路径
3、获取工程部署后在服务器硬盘上的绝对路径
4、像 Map 一样存取数据

我们来实现一下这个事情:
首先创一个ContextServlet类:

package com.atguigu.servlet;

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

public class ContextServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        1、获取 web.xml 中配置的上下文参数 context-param
        
//        2、获取当前的工程路径,格式: /工程路径
//        3、获取工程部署后在服务器硬盘上的绝对路径
//        4、像 Map 一样存取数据
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    }
}

然后我们现在去web.xml中设置一下上下文参数:

<!--context-param是上下文参数(它属于整个web工程,且可以配置多组)-->
    <context-param>
        <param-name>username</param-name>
        <param-value>context</param-value>
    </context-param>

然后我们就可以通过getServletConfig方法来调用getServletContext方法得到上下文参数:

package com.atguigu.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;

public class ContextServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        1、获取 web.xml 中配置的上下文参数 context-param
        ServletContext context = getServletConfig().getServletContext();
        String username = context.getInitParameter("username");
        System.out.println("context-param参数username的值是:"+username);
//        2、获取当前的工程路径,格式: /工程路径
        System.out.println("当前工程路径:"+context.getContextPath());
//        3、获取工程部署后在服务器硬盘上的绝对路径
        /*
        斜杠被服务器解析地址为:http://ip:port/工程名/ 映射到IDEA代码的web目录
         */
        System.out.println("工程部署的路径:"+context.getRealPath("/"));
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    }
}

还有第四个作用:ServletContext 像 Map 一样存取数据。

在这里插入图片描述

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
	ServletContext context = getServletContext();
	System.out.println(context); 
	System.out.println("Context2 中获取域数据 key1 的值是:"+ context.getAttribute("key1")); 
}

Http协议

什么是 HTTP 协议

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

请求的 HTTP 协议格式

客户端给服务器发送数据叫请求。
服务器给客户端回传数据叫响应。
请求又分为 GET 请求,和 POST 请求两种。

GET 请求

在这里插入图片描述
在这里插入图片描述

POST 请求

在这里插入图片描述
在这里插入图片描述

常用请求头的说明

Accept: 表示客户端可以接收的数据类型
Accpet-Languege: 表示客户端可以接收的语言类型
User-Agent: 表示客户端浏览器的信息
Host: 表示请求时的服务器 ip 和端口号

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

GET 请求有哪些:
1、form 标签 method=get
2、a 标签
3、link 标签引入 css
4、Script 标签引入 js 文件
5、img 标签引入图片
6、iframe 引入 html 页面
7、在浏览器地址栏中输入地址后敲回车

POST 请求有哪些:
1、form 标签 method=post

响应的 HTTP 协议格式

在这里插入图片描述
在这里插入图片描述

常用的响应码说明

在这里插入图片描述

MIME 类型说明

MIME 是 HTTP 协议中数据类型。
MIME 的英文全称是"Multipurpose Internet Mail Extensions" 多功能 Internet 邮件扩充服务。MIME 类型的格式是“大类型/小 类型”,并与某一种文件的扩展名相对应。

常见的 MIME 类型:
在这里插入图片描述
在这里插入图片描述
谷歌浏览器如何查看 HTTP 协议:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

在地球迷路的怪兽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值