Servlet详解

1.什么是Servlet

  1. 是javaEE的规范之一,规范接口

  2. Servlet是JavaWeb三大组件之一

  3. Servlet是运行在Web服务器中的Java小程序,可以接收客户端发送过来的请求,并响应数据给客户端

2.实现Servlet程序

  1. 实现Servlet接口

  2. 实现Servlet中的service方法:用于处理请求,并响应数据

  3. 到web.xml中配置

根据上面步骤实现一个简单的Servlet小程序

  • 第一步:实现Servlet接口
    //实现Servlet接口
    package com.carl.servlet;
    
    import javax.servlet.*;
    import java.io.IOException;
    
    /**
      * @author :Carl_蔡先生
      * @version :JDK1.8
      * @description:Servlet是javax包下的一个接口,需要导入第三方jar包,使用Maven和在tomcat中直接导入都可以
      *               Servlet被调用时会默认执行service方法
      * @date :2021/9/30 14:17
      * @month_name :9月
      * @week :
     **/
    public class MyServlet implements Servlet {
    }
    
    pom.xml导入依赖
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
        <scope>provided</scope>
    </dependency>
    
  • 第二步:实现service方法
    @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 {
        System.out.println("你好");
    }
    
    @Override
    public String getServletInfo() {
        return null;
    }
    @Override
    public void destroy() {
    
    }
    
  • 第三步:配置web.xml文件
    <servlet>
        <!--给servlet程序起别名-->
        <servlet-name>HelloServlet</servlet-name>
        <!--servlet-class是Servlet程序的全类名-->
        <servlet-class>com.carl.servlet.MyServlet</servlet-class>
    </servlet>
    <!--servlet-mapping标签是给Servlet程序配置访问地址的-->
    <servlet-mapping>
        <!--servlet-name标签的作用是告诉服务器,当前配置的地址是哪个Servlet程序->与上面的<servlet-name>内容一致-->
        <servlet-name>HelloServlet</servlet-name>
        <!--url-pattern标签配置访问地址
            /下级路径
            http://localhost:8080/ServletWeb/Carl
        -->
        <url-pattern>/Carl</url-pattern>
    </servlet-mapping>
    

注意事项:

  1. 如图所示的映射名称必须一致
    在这里插入图片描述报错:
    在这里插入图片描述
  2. 如图所示处的url必须加/
    在这里插入图片描述
    报错:在这里插入图片描述
  3. servlet-class标签的全类名配置错误:从src目录的下一级开始
    在这里插入图片描述
    报错:在浏览器处报错,服务器启动正常在这里插入图片描述

3.Web如何通过URL地址解析Servlet

  1. 浏览器通过URL访问指定主机下Tomcat程序中的工程,步骤如图所示
    在这里插入图片描述2. 加载Servlet,并调用service()方法
    在这里插入图片描述

4.Servlet的生命周期

  1. 执行Servlet构造器方法

  2. 执行init()初始化方法
    1、2、只有在第一次访问的时候创建Servlet程序时会调用(即启动Tomcat后,通过资源路径触发web.xml创建Servlet类的实例时被调用)
    http://localhost:8080/ServletWeb/Carl
    在这里插入图片描述

  3. 执行service方法(只要tomcat不重启,每次访问都会被调用)
    在这里插入图片描述

  4. 执行destory方法(在web工程停止时被调用)
    在这里插入图片描述

5.区分get请求和post请求

Servlet通过service方法的请求参数ServletRequest的子类对象HttpServletRequest,调用getMethod方法获取当前浏览器请求为get还是post。

public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
    System.out.println("你好");
    //将service方法中的servletRequest参数强制转换为HttpServletRequest,因为这个类由getMethod()方法
    HttpServletRequest hsr=(HttpServletRequest) servletRequest;
    String method = hsr.getMethod();
    System.out.println(method);
    if ("GET".equals(method)) {
        System.out.println("get请求");
    }else{
        System.out.println("post请求");
    }
}
  1. 我们需要调用的是HttpServletRequest对象的getMethod方法,所以需要强制转换

  2. 因为service方法主要用于接收浏览器的请求,因此这也是为什么上述生命周期中所说,每次调用tomcat服务都会触发service的调用
    在这里插入图片描述
    而当判断中存在大量的执行语句,就可以封装到方法中,只需要调用方法即可

    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("你好");
        //将service方法中的servletRequest参数强制转换为HttpServletRequest,因为这个类由getMethod()方法
        HttpServletRequest hsr=(HttpServletRequest) servletRequest;
        String method = hsr.getMethod();
        System.out.println(method);
        if ("GET".equals(method)) {
            doGet();
        }else{
            doPost();
        }
    }
    public void doGet(){
        System.out.println("get请求");
    }
    public void doPost(){
        System.out.println("post请求");
    }
    

6.GenericServlet和HttpServlet

如何解决继承Servlet接口时,需要实现所有的方法,但是实际开发中不是所有的方法都需要被实现

Servlet有两个扩展的子类:GenericServletHttpServlet
在这里插入图片描述
GenericServlet是一个普通的servlet;

HttpServlet是一个专门用于通过Http接收和响应web客户端请求的Servlet,重新实现了service方法,并实现了请求方法的分发处理

在GenericServlet类的doGet和doPost方法中都是负责抛出异常(抛出一个不支持Get/Post请求的异常)

//必须重写service方法
public class MyGenericServlet extends GenericServlet {
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

    }
}

HttpServlet需要重写doGet和doPost方法,根据表单的返回类型决定是重写doGet()还是重写doPost()方法

public class MyHttpServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
        System.out.println("MyHttpServlet->doGet()");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
        System.out.println("MyHttpServlet->doPost");
    }
}

doGet()方法和doPost()方法中如果存在super()方法则无法获取http的get或post方法
在这里插入图片描述

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

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

在IDEA中快捷创建Servlet
在这里插入图片描述
使用注解的方式生成Servlet类
在这里插入图片描述

7.ServeltConfig和ServletContext

ServletConfig和ServletContext是Tomcat负责创建的,不需要自己创建

7.1ServletConfig

ServletConfig是Servlet程序的配置信息类

作用:

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

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

  3. 获取ServletContext对象
    在这里插入图片描述

测试代码:

配置web.xml

<?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>
        <!--给servlet程序起别名-->
        <servlet-name>HelloServlet</servlet-name>
        <!--servlet-class是Servlet程序的全类名-->
        <servlet-class>com.carl.servlet.MyServlet</servlet-class>
        <init-param>
            <param-name>username</param-name>
            <param-value>root</param-value>
        </init-param>
        <init-param>
            <param-name>password</param-name>
            <param-value>root</param-value>
        </init-param>
        <init-param>
            <param-name>url</param-name>
            <param-value>jdbc:mysql://localhost:3306/javamysql</param-value>
        </init-param>
        <init-param>
            <param-name>driverClassName</param-name>
            <param-value>com.mysql.cj.jdbc.Driver</param-value>
        </init-param>
    </servlet>
    <!--servlet-mapping标签是给Servlet程序配置访问地址的-->
    <servlet-mapping>
        <!--servlet-name标签的作用是告诉服务器,当前配置的地址是哪个Servlet程序->与上面的<servlet-name>内容一致-->
        <servlet-name>HelloServlet</servlet-name>
        <!--url-pattern标签配置访问地址
            /下级路径
            http://localhost:8080/ServletWeb/Carl
        -->
        <url-pattern>/Carl</url-pattern>
    </servlet-mapping>
</web-app>

获取web.xml中的信息

@Override
public void init(ServletConfig servletConfig) throws ServletException {
    ServletContext servletContext = servletConfig.getServletContext();
    String servletName = servletConfig.getServletName();
    String url = servletConfig.getInitParameter("url");
    String username = servletConfig.getInitParameter("username");
    String password = servletConfig.getInitParameter("password");
    String driverClassName = servletConfig.getInitParameter("driverClassName");

    System.out.println("Servlet被init:[servlet的ServletContext=>"+servletContext +";\n"
            +"Servlet的别名=>"+servletName+"initParam=>url="+url+"\n"
            +"username="+username+"\n"
            +"password="+password+"\n"
            +"driverClassName="+driverClassName+"\n"
            +"]");
}

也可以在其他方法中使用ServletConfig,需要使用静态方法getServletConfig()获取

@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
    ServletConfig servletConfig = getServletConfig();
    ServletContext servletContext = servletConfig.getServletContext();
    String servletName = servletConfig.getServletName();
    String url = servletConfig.getInitParameter("url");
    String username = servletConfig.getInitParameter("username");
    String password = servletConfig.getInitParameter("password");
    String driverClassName = servletConfig.getInitParameter("driverClassName");

    System.out.println("Servlet被init:[servlet的ServletContext=>"+servletContext +";\n"
            +"Servlet的别名=>"+servletName+"initParam=>url="+url+"\n"
            +"username="+username+"\n"
            +"password="+password+"\n"
            +"driverClassName="+driverClassName+"\n"
            +"]");
}

注意事项:如果在init以外的方法中获取ServletConfig实例对象

  1. 实现Servlet接口,在service()方法中使用ServletConfig实例对象

    private transient ServletConfig servletConfig;
    public void init(ServletConfig config) throws ServletException {
      this.servletConfig = config;
    }
    
  2. 继承HttpServlet和GenericServlet类,只需要在重写的init方法中调用父类的init()方法即可,或者不重写init()方法也可以

    @Override
    public void init(ServletConfig config) throws ServletException {
      super.init(config);
    }
    

    如果没有按照上面两种方法解决问题,仅仅只是使用了ServletConfig实例,就会报错NullPointException
    原因:ServletConfig是随着Servlet的创建而一起创建的,因此需要通过init()方法内部调用时,传入一个ServletConfig实例,当子类重写init方法后,很显然只会调用子类的init()方法,所以,要么自己在init方法中赋值,要么调用父类的init方法去赋值

7.2ServletContext

ServletContext是一个接口,针对每一个Web工程创建的一个域对象,该对象工程中全局唯一且共享,因此也叫全局共享对象
作用:

  1. 获取web.xml中配置的上下文参数context-param(全局参数)
    //获取context-param全局参数
    //获取web.xml中<param-name>对应的<param-value>值
    String namespace = context.getInitParameter("namespace");//Carl
    //获取所有的<param-name>标签内容
    Enumeration<String> initParameterNames = context.getInitParameterNames();
    System.out.println(namespace);
    while(initParameterNames.hasMoreElements()){
        String s = initParameterNames.nextElement();
        System.out.println(s);
    }
    
  2. 获取当前的工程路径名称
    //获取当前工程路径
    String contextPath = context.getContextPath();
    System.out.println(contextPath);///ServletWeb
    
  3. 获取工程部署后在服务器硬盘上的绝对路径(工程目录下的资源文件)
    //获取绝对路径
    String realPath = context.getRealPath("/");
    System.out.println(realPath);//E:\文档\Java_WorkSpace\ServletWeb\out\artifacts\ServletWeb\
    String realPath1 = context.getRealPath("/html");
    System.out.println(realPath1);//E:\文档\Java_WorkSpace\ServletWeb\out\artifacts\ServletWeb\html
    
  4. 像Map一样存取数据
    //存储数据
    context.setAttribute("root", "root123");
    //获取数据
    Object root = context.getAttribute("root");
    System.out.println(root);//root123
    //删除数据
    context.removeAttribute("root");
    Object root1 = context.getAttribute("root");
    System.out.println(root1);//null
    
  • 21
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Carl·杰尼龟

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

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

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

打赏作者

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

抵扣说明:

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

余额充值