Servlet实战详解

1. Servlet概述(了解)

1.1. JavaWeb的三大组件

  Servlet是JavaWeb三大组件之一,它是我们学习JavaWeb最为基本的组件,也就是说你一定要 100% 的掌握它。
  其它两种:Filter(过滤器)、Listener(监听器),后续讲解

1.2. Servlet的作用

  Servlet,即Server Let的意思,用来处理用户请求。当客户端发出请求后,由Tomcat去找到可以处理这一请求的Servlet来处理。
  也就是说,用户的请求是由Servlet来处理的!例如用户发出登录请求,那么就应该由处理登录的Servlet来处理;用户发出登录请求,那么就应该有登录Servlet来处理。
在这里插入图片描述

在这里插入图片描述

2. Servlet初识(熟练)

2.1. 第一个Servlet

2.1.1. Servlet说明

  servlet 是运行在 Web 服务器中的小型 Java 程序。servlet 通常通过 HTTP(超文本传输协议)接收和响应来自 Web 客户端的请求。也就是说,Servlet是由我们自己来完成的!但Servlet一定要实现javax.servlet.Servlet接口,并且还要在web.xml文件中部署!不然Tomcat是找不到我们写的Servlet的。

2.1.2. Servlet接口

javax.servlet.Servlet接口中方法如下:

  • void init(ServletConfig servletConfig): 当Tomcat创建Servlet实例后,马上调用init()方法。这个方法只在创建后调用一次!用来做Servlet初始化工作!一个Servlet实例只被创建一次,所以init()方法也只被调用一次!(本方法编写对Servlet的初始化代码)
  • void service(ServletRequest request, ServletResponse response):Servlet实例在每次处理请求时都调用service()方法。
  • void destroy():当Tomcat要销毁Servlet实例时,会先调用destroy()方法,再销毁它。所谓销毁Servlet,其实就是在Servlet缓存池中把Servlet移除!一般只有Tomcat关闭时,才会销毁Servlet实例!
  • ServletConfig getServletConfig():这个方法返回ServletConfig对象,但我们不能自己去创建ServletConfig对象,所以一般我们会在init()方法中把init()方法的参数保存起来,然后再在本方法中返回它。ServletConfig对象对应web.xml中当前Servlet实例的配置信息。
  • String getServletInfo():这个方法只是返回一个字符串,用来说明当前Servlet。基本没用!

2.1.3. 创建Servlet

  • 第一步:常见HelloServlet实现Servlet的接口,实现接口中的方法;
package cn.tx.servlet;

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

public class Servlet1 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() {

    }
}
  • 第二步:配置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_3_1.xsd"
         version="3.1">
    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>cn.tx.servlet.Servlet1</servlet-class>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
</web-app>

2.1.4. JavaWeb请求响应流程

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
  当Tomcat接收到请求(http://localhost:8080/servlet_pro/logon)后,Tomcat会找到servlet_pro项目中的web.xml文件,然后通过logon这个请求路径,查找处理这个请求的Servlet类型。这刚好与<url-pattern>/logon</url-pattern>匹配,这说明存在一个可以通过这个请求的Servlet。然后再通过<url-pattern>/logon </url-pattern>查找到<servlet-name>login</servlet-name>,然后再通过<servlet-name>login </servle-name>查找到<servlet-class>com.rl.servlet.LoginServlet</servlet-class>。这时Tomcat已经得到了一个Servlet类名字(一个字符串而已)。
  Tomcat通过Servlet类名字去查找内存中是否存在Servlet对象,如果存在,那么就不用再去创建,直接获取这个Servlet实例,调用它的service()方法完成请求!
  如果这个Servlet不存在,那么Tomcat会通过反射来创建Servlet实例,并把Servlet实例存放到Servlet池中,再去调用Servlet的service方法处理请求。

2.2. Servlet生命周期

javax.servlet.Servlet接口中,有三个方法说明了Servlet的生命周期:

  • void init(ServletConfig):创建后马上调用init()完成初始化;
  • void service(ServletRequest,ServletResponse):每次处理请求时调用service()方法;
  • void destroy():当Tomcat要销毁Servlet实例时,先调用destroy()方法。
    在这里插入图片描述
      Servlet对象的实例默认情况下是在浏览器第一次调用servlet时候被创建的(可以修改其创建时机后续讲解)
      现在你应该已经清楚了,Servlet的实例不由我们创建,Servlet的方法不由我们来调用,这一切都是由Tomcat来完成!!!这就是说由Tomcat来管理Servlet,而我们只需要去编写Servlet实现类,并将其部署到web.xml文件中去!
      再次提醒,只有这三个方法是生命周期中的方法。也就是说,生命周期方法会被Tomcat在不同的时间点来调用!而其它方法就不会被调用了!!!如果你在自己写的Servlet中添加了其他方法,那么Tomcat也是不会去调用它们的!但你可以让生命周期方法去调用你自己写的方法就OK了!

3. HttpServlet(精通)

3.1. HttpServlet介绍

  因为现在我们的请求都是基于HTTP协议的,所以我们应该专门为HTTP请求写一个Servlet做为通用父类。
在这里插入图片描述
在这里插入图片描述

由上图我们可以看出,以后再写Servlet 可以直接继承HttpServlet

  • Servlet是一个标准
  • GenericServlet是Servlet接口子类
  • HttpServlet是GenericServlet子类,一个专门处理Http请求的Servlet

3.2. Http请求方法

HTTP请求方法不只是GET和POST,还有其他的方法,但基本上用不上。这里只是简单介绍一下。你自己心里有个数,HTTP请求除了GET和POST之外还有别的就行了。

  • GET: 通过请求URI得到资源
  • POST: 用于添加新的内容
  • PUT 用于修改某个内容
  • DELETE 删除某个内容
  • CONNECT 用于代理进行传输,如使用SSL
  • OPTIONS 询问可以执行哪些方法
  • PATCH 部分文档更改
  • RACE 用于远程诊断服务器
  • HEAD 类似于GET, 但是不返回body信息,用于检查对象是否存在,以及得到对象的元数据
  • TRACE 用于远程诊断服务器

3.3. 创建HttpServlet

3.3.1. 第一种方法

创建一个类继承HttpServlet:

package cn.tx.servlet;

import javax.servlet.http.HttpServlet;

public class Servlet2 extends HttpServlet{
    
}

配置Servlet的映射路径:

<servlet>
    <servlet-name>hello2</servlet-name>
    <servlet-class>cn.tx.servlet.Servlet2</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>hello2</servlet-name>
    <url-pattern>/hello2</url-pattern>
</servlet-mapping>

3.3.2. 第二种方法

  • IDEA直接创建servlet:
    在这里插入图片描述
  • 填写Servlet名称:
    在这里插入图片描述
  • 创建完成,自己填写映射路径:
    在这里插入图片描述

3.3.3. Servlet创建顺序

  有些Servlet需要在Tomcat启动时就被创建,而不是第一次访问时被创建,那么可以在web.xml文件中配置<servlet>元素。
  在<servlet>元素中添加子元素<load-on-startup>元素!

<servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>cn.tx.servlet.Servlet1</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

在这里插入图片描述
  当值为0或者大于0时,表示容器在应用启动时就加载这个servlet;
  所有添加了<load-on-startup>子元素的Servle,都会在Tomcat启动时被创建!当然,只是被创建,但没有处理请求!但我们知道在Servlet生命周期中init()方法会在创建后被调用,所以你可以在init()方法中做一些输出,查看是否在Tomcat启动时调用了它。
  <load-on-startup>元素的值是一个序号,Tomcat会使用这个序号给多个Servlet排序!然后在Tomcat启动时会按这个顺序来创建Servlet实例对象!

4. ServletConfig(熟练)

  ServletConfig对象对应web.xml文件中的<servlet>元素。例如你想获取当前Servlet在web.xml文件中的配置名,那么可以使用servletConfig.getServletName()方法获取!
  你不能自己去创建ServletConfig对象,Servlet的init()方法的参数就是ServletConfig类型的。Tomcat在调用init()方法时,会传递ServletConfig对象。你可以在init()方法中使用它!

<servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>cn.tx.servlet.Servlet1</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>txjava</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
String username = servletConfig.getInitParameter("username");
System.out.println("username:"+username);
Enumeration<String> parameterNames = servletConfig.getInitParameterNames();
while (parameterNames.hasMoreElements()){
    String element = parameterNames.nextElement();
    System.out.println(element+":"+servletConfig.getInitParameter(element));
}

  添加了两个初始化参数,第一个参数的名称为paramName1,第一个参数的值为paramValue1;第二个参数的名称为paramName2,第二个参数值为paramValue2。
  在<servlet>元素中可以加载多个<init-param>,每个<init-param>表示一个参数。<init-param>下有两个子元素:<param-name><param-value>,其中<param-name>表示参数的名称,而<param-value>元素参数的值。
  注意,<init-param>是添加到<servlet>元素中,而不是<servlet-mapping>中。
  使用ServletConfig对象的getInitParameter(String paramName)方法可以获取指定参数名称的参数值。getInitParameterNames()方法返回所有参数的名字,返回值类型为Enumeration。

5. Servlet映射路径(熟练)

关于Url-Pattern的配置:

  • 完全路径匹配:servlet中比较推荐的写法,怎么写的就怎么访问以/开头,例如 /aaa、/aaa/bbb 、 /web/demo4
  • 目录匹配:以/开头,例如 /aaa/* 、 /* 、 * :通配符,表示任意字符。
  • 扩展名匹配:不能以/开头,否则会出现异常,以后缀名结尾。例如 *.do 、 *.action …

  优先级: 完全路径匹配 > 目录匹配 > 扩展名匹配
  经典错误: /*.do

  • 举例:
    • 对于如下的一些映射关系:
      • Servlet1 映射到 /abc/*
      • Servlet2 映射到 /*
      • Servlet3 映射到 /abc
      • Servlet4 映射到 *.do
  • 问题:
    • URL为“/abc/a.html”,“/abc/* ”和“/*”都匹配,哪个servlet响应?
      答:Servlet引擎将调用Servlet1。同样是目录匹配所限定范围更精确的先匹配
    • URL为“/abc”时,“/abc/*”和“/abc”都匹配,哪个servlet响应?
      答:Servlet引擎将调用Servlet3。
    • URL为“/abc/a.do”时,“/abc/* ”和“*.do”都匹配,哪个servlet响应?
      答:Servlet引擎将调用Servlet1。
    • URL为“/a.do”时,“/* ”和“*.do”都匹配,哪个servlet响应?
      答:Servlet引擎将调用Servlet2.
    • URL为“/xxx/yyy/a.do”时,“/* ”和“*.do”都匹配,哪个servlet响应?
      答:Servlet引擎将调用Servlet2。
    • 服务器端路径 /demo4 (转发、包含…)

6. ServletContext(熟练)

6.1. ServletContext介绍

  ServletContext是一个全局的储存信息的空间,服务器开始,其就存在,服务器关闭,其才释放。request,一个用户可有多个;session,一个用户一个;而servletContext,所有用户共用一个。所以,为了节省空间,提高效率,ServletContext中,要放必须的、重要的、所有用户需要共享的线程又是安全的一些信息。
在这里插入图片描述

  • WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前web应用。
  • 由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。ServletContext对象通常也被称之为context域对象。
  • 查看ServletContext API文档,了解ServletContext对象的功能。

6.2. ServletContext API

MethodSummary
ObjectgetAttribute(String name)
Returns the servlet container attribute with the given name, or null if there is no attribute by that name.
StringgetContextPath()
Returns the context path of the web application.
StringgetInitParameter(String name)
Returns a String containing the value of the named context-wide initialization parameter, or null if the parameter does not exist.
StringgetRealPath(String path)
Returns a String containing the real path for a given virtual path
voidsetAttribute(String name, Object object)
Binds an object to a given attribute name in this servlet context.
InputStreamgetResourceAsStream(String path)
Returns the resource located at the named path as an InputStream object.

6.3. ServletContext使用

6.3.1. 常规应用:

  • 获取WEB应用的全局初始化参数
  • 通过ServletContext对象实现数据共享
<context-param>
    <param-name>company</param-name>
    <param-value>拓薪教育</param-value>
</context-param>
ServletContext servletContext = config.getServletContext();
String company = servletContext.getInitParameter("company");
System.out.println("company:"+company);

示例:
统计站点访问次数:

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doPost(request, response);
}

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    ServletContext servletContext = getServletContext();
    Integer visitNums = (Integer)(servletContext.getAttribute("visitNums"));
    visitNums = visitNums == null ? 0 : visitNums;
    servletContext.setAttribute("visitNums",++visitNums);
    response.setCharacterEncoding("UTF-8");
    response.getWriter().write("当前网站访问人次:"+visitNums);
}

6.3.2. 通过ServletContext对象读取资源文件

  • 第一种方法,通过ServletContext.getRealPath()方法;
// 获得到ServletContext对象
ServletContext servletContext = config.getServletContext();

// 获得工程目录web下文件的绝对路径 D:\workspace\idea\servlet-demo1\out\artifacts\servlet_demo1_war_exploded\tx.properties
// getRealPath的参数内容不会被校验,只有真正要用这个路径的时候才知道路径对不对
// String path = servletContext.getRealPath("tx.properties");

String path = servletContext.getRealPath("tx.properties");
System.out.println(path);
try {
    InputStream is = new FileInputStream(path);
    Properties p = new Properties();
    p.load(is);
    String username = p.getProperty("username");
    System.out.println(username);
} catch (Exception e) {
    e.printStackTrace();
}
  • 第二种方法,使用servletContext.getResourceAsStream()方法;
//获得工程目录web下文件的流第一个/代表项目的根目录
InputStream is = servletContext.getResourceAsStream("/WEB-INF/tx1.properties");
  • 第三种方法,使用getClass().getClassLoader().getResourceAsStream()方法;
//使用类加载器的方式来读取classpath下的资源文件,好处不依赖与ServletContext,任何类都可以获得classpath下的资源文件,
//不需要再自己指定/WEB-INF/classes
InputStream is = this.getClass().getClassLoader().getResourceAsStream("tx2.properties");

7. Servlet相关资料(熟练)

7.1. 面试题

7.1.1. 单例的Servlet

  因为Servlet实例是由Tomcat来创建的,但Tomcat只会创建一个Servlet实例,所以Servlet就是单例的!这与我们自己写的单例模式不太一样。因为这种单例是通过容器tomcat来管理而实现的!

一个实例需要在同一个时间点上处理多个请求!
同步就是安全,但效率太低!
Servlet是线程不安全的!

注意:

  • 不写属性;
  • 不写可以存储数据的属性!

7.1.2. Servlet的生命周期

  • Servlet 通过调用 init () 方法进行初始化。
  • Servlet 调用 service() 方法来处理客户端的请求。
  • Servlet 通过调用 destroy() 方法终止(结束)。
  • 最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。

8. 学习目标

  • 了解Servlet概念和JavaWeb的三大组件都包含哪些组件;
  • 创建一个Servlet实现javax.servlet.Servlet接口,并自行验证Servlet的生命周期;
  • 创建一个Servlet继承javax.servlet.http.HttpServlet类,提供一个初始化属性,并在Servlet初始化时打印它;
  • 自己实现统计网址访问人次的功能;
  • 熟练掌握两道面试题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值