Servlet技术之——概述、实现、细节、获取资源、ServletConfig、ServletContext

Servlet概述、实现、细节、获取资源、ServletConfig、ServletContext

(一) Setvlet基本概述

(1) 什么是Servlet ?

Servlet(Server Applet)是JavaServlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容是

JavaWeb中,我们将会接触到三大组件(Servlet、Filter、Listener),Servlet由服务器调用,处理服务器接收到的请求,即完成,接受请求数据 --> 处理请求 --> 完成响应,其本质就是一个实现了Servlet接口的java类

Servlet类由我们来写,但对象由服务器来创建,并且由服务器来调用相应的方法

(2) Servlet用来做什么?

网络中比较常见的一些功能,例如登录,注册,这样存在交互的功能,而Servlet就可以帮助我们处理这些请求,可以说Servlet是JavaWeb知识中重要的知识点之一

(二) 实现Servlet的方式

实现Servlet有三种方式:

  • 实现 javax.servlet.Servlet 接口;
  • 继承 javax.servlet.GenericServlet类;
  • 继承 javax.servlet.http.HttpServlet类;

实际开发中,我们通常会选择继承HttpServlet类来完成我们的Servlet,但认识Servlet接口这种方式也是很重要的,是我们入门知识中不可或缺的部分

(1) 创建我们的第一个Servelt

我们创建一个web项目,选择对应的参数,我们所装的jdk为1.8版本,可以选择到 JavaEE8的版本,对应versions也就是4.0,不过我们在这里选择市面上用的还是比较多的7版本

创建一个Demo类实现Servlet接口,然后我们快速生成这个接口中未实现的方法,我们先暂时忽略Servlet中其他四个方法,只关心service()方法,因为它是用来处理请求的方法,我们在该方法内给出一条输出语句

package cn.ideal.web.servlet;

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

public class ServeltDemo1 implements Servlet {
    //初始化方法
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
    }

    //Servlet配置方法
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    //提供服务方法
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("理想二旬不止");
    }

    //Servlet信息方法
    @Override
    public String getServletInfo() {
        return null;
    }

    //销毁方法
    @Override
    public void destroy() {
    }
}

写完了一个最简单Servlet代码,但是如何在浏览器中可以访问到呢?我们就需要对web/WEB-INF下的web.xml进行配置,我们在<web-app></web-app>中加入以下代码(虽然后期有优化的方法,但是很推荐大家记忆下来)

<servlet>
        <!--给这个Servlet起一个名字,一般与类名相同-->
        <servlet-name>ServletDemo1</servlet-name>
        <!--全类名-->
        <servlet-class>cn.ideal.web.servlet.ServeltDemo1</servlet-class>
    </servlet>

    <!--配置映射路径-->
    <servlet-mapping>
        <servlet-name>ServletDemo1</servlet-name>
        <!--外界访问的路径-->
        <url-pattern>/Demo1</url-pattern>
    </servlet-mapping>

现在我们根据我们在url-pattern中配置的路径来访问一下,在控制台中果然输出了,理想二旬不止这个字符串

(2) web.xml的作用

趁热打铁,我们来简单分析一下这个web.xml的因由,其实在web.xml中配置Servlet的目的,就是把在浏览器中的访问路径与对应Servlet绑到一起,上面的例子中就是把访问路径:“/Demo1” 与 “cn.ideal.web.servlet.ServeltDemo1” 绑定到了一起

1、<servlet></servlet> :指定ServletDemo1这个Servlet的名字为ServletDemo1,一般此处与对应类同名

2、<servlet-mapping></servlet=mapping> :设定访问的具体路径

而这两者又通过<servlet-name></servlet-name> 关联在一起

执行过程:

1、当服务器中接受到了浏览器的请求,解析URL路径,获取到Servlet的资源路径

2、寻找web.xml文件,找到 <url-pattern> 标签,寻找对应的全类名<servlet-class>

3、Tomcat将字节码文件加载进内存,并且创建对象,调用其中的方法

所以我们需要知道:Servlet中的大多数方法均不由我们来创建和调用,均由Tomcat完成

(三) Servlet 接口

(1) 生命周期简单概述

我将生命周期简单理解为这样几个过程:

生前——出生——服务——死亡——埋葬

1、生前:当Tomcat第一次访问Servlet,Tomcat会创建Servlet的实例

2、出生:Tomcat会调用init()方法初始化这个对象

3、服务: 客户端访问Servlet的时候,service()方法会被调用

4、死亡: 当Tomcat被关闭或者Servlet长时间不被使用,destroy()方法会被调用

5、埋葬: destroy()方法被调用后,Servlet就等待垃圾回收(不轻易),有需要则用init()方法重新初始化

(2) 生命周期详解

1、生前

服务器会在Servlet第一次被访问时,或者是在服务器启动时创建Servlet。如果服务器启动时就创建Servlet,那么还需要在web.xml文件中进行配置,也就是说默认情况下,Servlet是在第一次访问时由服务器创建的

一个Servlet类型,服务器只创建一个实例对象:例如我们第一次访问<http://localhost:8080/Demo1>,服务器通过/Demo1就找到了cn.ideal.web.servlet.ServeltDemo1 ,服务器就会判断这个类型的Servlet是否创建过,若没有才通过反射来创建ServletDmoe1的实例,否则就直接使用已经存在的实例

2、出生

在Servlet被创建后,服务器会立即调用Servlet的void init(ServletConfig)方法,而且一个Servlet的一生,这个方法只会被调用一次,我们可以把一些对Servlet的初始化工作放到方法中!

3、服务

当服务器每次接收到请求时,都会去调用Servlet的service()方法来处理请求。service()方法是会被调用多次的,服务器接收到一次请求,就会调用service() 方法一次,也正因为如此,所以我们才需要把处理请求的代码写到service()方法中!

4、死亡及埋葬

当服务器关闭时Servlet也需要被销毁了,但是销毁之前,服务器会先调用Servlet中的destroy()方法,我们可以把一些释放资源的代码放到此处

(3) Servlet接口的三个类型

在这五个方法中,我们可以在参数中看到三个我们没有接触过的类型

public void init(ServletConfig servletConfig) throws ServletException {}

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

也就是这个三个类型:ServletConfig、ServletRequest、ServletResponse

A:ServletConfig

ServletConfig是服务器创建的一个对象,然后传递到Servlet的init()方法中

下述方法中我们简单使用一下第一个 getServletName() 就可以了,后面的方法等我们学写了Context以及其他知识才能更好的理解

//获取Servlet在web.xml文件中的配置名称,即<servlet-name>指定的名称
String getServletName()

//用来获取ServletContext对象
ServletContext getServletContext()

//用来获取在web.xml中配置的初始化参数,通过参数名来获取参数值;
String getInitParameter(String name)

//用来获取在web.xml中配置的所有初始化参数名称
Enumeration getInitParameterNames()

B:ServletRequest & ServletResponse

这两个类型出现在Servlet的service()方法中,分别代表着请求响应对象,并且两者的实例也都是由服务器创建的

但是我们想要做一个web应用,归根结底要和HTTP相挂钩,如果我们希望在service() 方法中使用HTTP相关的功能,可以把 ServletRequest 和 ServletResponse 强转成 HttpServletRequest 和HttpServletResponse

HttpServletRequest方法:

//获取指定请求参数的值;
String getParameter(String paramName)

//获取请求方法,例如GET或POST
String getMethod()

//获取指定请求头的值;
String getHeader(String name)

//设置请求体的编码!
/*
    GET没有请求体,所以这个方法只只对POST请求有效当调用
    这个方法必须在调用getParameter()方法之前调用!
    使用request.setCharacterEncoding(“utf-8”)之后,再通过getParameter()方法获取参数
    时,参数值都已经通过了转码,即转换成了UTF-8编码
*/
void setCharacterEncoding(String encoding)

HttpServletResponse方法:

//获取字符响应流,使用该流可以向客户端输出响应信息。
PrintWriter getWriter()
Eg:response.getWriter().print(“<h1>Just for test</h1>”);

//获取字节响应流,例如可实现向客户端响应一张图片
ServletOutputStream getOutputStream()

//用来设置字符响应流的编码
void setCharacterEncoding(String encoding)

//向客户端添加响应头信息
void setHeader(String name, String value)
Eg:setHeader(“Refresh”, “3;url=http://www.xxx.com”) 表示三秒后自动刷新到该网址

//该方法是setHeader(“content-type”, “xxx”)的简便方法,即用来添加名为content-type响应头的方法
/*
    content-type响应头用来设置响应数据的MIME类型,例如要向客户端响应jpg的图片,那么
    可以setContentType(“image/jepg”),如果响应数据为文本类型,那么还要台同时设置编
    码,例如setContentType(“text/html;chartset=utf-8”)表示响应数据类型为文本类型
    中的html类型,并且该方法会调用setCharacterEncoding(“utf-8”)方法;
*/
void setContentType(String contentType)

//向客户端发送状态码,以及错误消息
void sendError(int code, String errorMsg)

(四) GenericServlet 类

A:通过查看这个类的源码可以知道,该类中只有

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

一个方法需要实现,其他的方法已经均在源码中有了定义

B:GenericServlet的init()方法

还需要提一提的两个方法就是

public void init(ServletConfig config) throws ServletException {
        this.config = config;
        this.init();
    }

public void init() throws ServletException {
}

GenericServlet 类实现了Servlet的init(ServletConfig)方法,把参数config赋给了本类的成员config,然后再调用本类自己的无参的init()方法

这个方法是 GenericServlet 自己的方法,而不是从Servlet继承下来的。当我们自定义Servlet时,如果想完成初始化作用就不要再重复 init(ServletConfig) 方法了,而是应该去重写init()方法。因为在 GenericServlet中的 init(ServletConfig) 方法中保存了 ServletConfig 对象,如果覆盖了保存 ServletConfig 的代码,那么就不能再使用 ServletConfig 了

C:实现了ServletConfig接口

GenericServlet还实现了ServletConfig接口,所以可以直接调用getInitParameter()、getServletContext()等ServletConfig的方法。

但是这个类我们仍然不是我们要讲的重点,我们接着看一下下一个类

(五) HttpServlet 类

(1) 概述

在上面我们实现 Servlet 接口,需要实现5个方法,十分麻烦,而HttpServlet类已经实现了Servlet接口的所有方法,编写Servlet时,只需要继承HttpServlet,重写你需要的方法即可,并且它提供了对HTTP请求的特殊支持,更加强大

(2) service()方法

在 HttpServlet 的 service(ServletRequest,ServletResponse)方法中会把 ServletRequestServletResponse 强转成 HttpServletRequestHttpServletResponse

//HttpServlet 源码节选
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        HttpServletRequest request;
        HttpServletResponse response;
        try {
            request = (HttpServletRequest)req;
            response = (HttpServletResponse)res;
        } catch (ClassCastException var6) {
            throw new ServletException("non-HTTP request or response");
        }

        this.service(request, response);
    }

强转过后,然后调用 HttpServlet 类中提供的 service(HttpServletRequest,HttpServletResponse)方法,这是这个类本身的方法,而不是继承而来的,这说明我们在使用的时候,只需要覆盖 service(HttpServletRequest,HttpServletResponse) 就可以了,不需要再进行强转这个两个对象了

注意:其实还有更一步简化的步骤,也不必使用 service(HttpServletRequest,HttpServletResponse)

(3) doGet() 和 doPost()

在HttpServlet的service(HttpServletRequest,HttpServletResponse) 方法会去判断这个请求是GET还是POST,如果是GET请求,就去调用类中的doGet()方法,如果是POST请求,就去调用doPost()方法,这说明我们在子类中去覆盖doGet()或doPost()方法就可以了

(六) Servlet细节

(1) 线程安全问题

Servlet只会被服务器创建一个实例对象,很多情况下,一个Servlet需要处理多个请求,显然,Servlet虽然效率高,但也不是线程安全的

所以我们不应该在Servlet中轻易创建成员变量,因为可能会存在多个线程同时对这个成员变量进行不同的操作

结论:不要在Servlet中创建成员!创建局部变量即可,可以创建无状态成员量,或者状态只为可读的成员

(2) 服务器启动时就创建Servlet

之前我们将生命周期的时候有说过,Servlet是在第一次访问时由服务器创建的,但我们可以通过在web.xml中对Servlet进行配置,使服务器启动时就创建Servlet

<servlet>
    <servlet-name>ServletDemo1</servlet-name>
    <servlet-class>cn.ideal.web.ServletDemo1</servlet-class>
     <!--在<servlet>中配置<load-on-startup>,其中给出一个非负整数!-->
    <load-on-startup>0</load-on-startup>
</servlet>

它的作用是确定服务器启动时创建Servlet的顺序

(3) 一个Servlet可以绑定多个URL

<servlet-mapping>
    <servlet-name>Servlet</servlet-name>
    <url-pattern>/AServlet</url-pattern>
    <url-pattern>/BServlet</url-pattern>
</servlet-mapping>  

这样配置后无论访问/AServlet还是/BServlet,访问的都是AServlet

(4) 通配符匹配问题

<url-pattern>中可以使用通配符,也就是 “ * ” ,它可以匹配任何前缀或者后缀

<!--路径匹配-->
<url-pattern>/servlet/*<url-patter>:/servlet/a、/servlet/b,都匹配/servlet/*;

<!--扩展名匹配-->
<url-pattern>*.xx</url-pattern>:/abc/de.xx、/a.xx,都匹配*.xx;

<!--什么都匹配-->
<url-pattern>/*<url-pattern>:匹配所有URL;

通配符要么为前缀,要么为后缀,不能出现在URL中间位置,并且一个URL中最多只能出现一个通配符,如果存在更具体的地址,会优先访问具体的地址

(七) ServletContext

(1) 概述

服务器会为每个web应用创建一个 ServletContext 对象,可以说它就代表着这个web站点,并且这个对象,在Tomcat启动时就创建,在Tomcat关闭时才会销毁

(2) 功能

所有Servlet都共享着一个ServletContext对象,所以ServletContext对象的作用是在整个Web应用的动态资源之间共享数据,也就是说不同的Servlet之间可以通过ServletContext进行通讯,从而共享数据

(3) 获取ServletContext对象

GenericServlet类有getServletContext()方法,所以可以直接使用this.getServletContext()来获取

public class MyServlet implements Servlet {
    public void init(ServletConfig config) {
        ServletContext context = config.getServletContext();
    }
}
public class MyServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) {
        ServletContext context = this.getServletContext();
    }
}

(4) 域对象的功能

所有域对象都有存取数据的功能,可以将这种存储数据的方式看做,Map的方式

我们来看几个常见的用来操作数据的方法

存储

//用来存储一个对象,也可以称之为存储一个域属性
void setAttribute(String name, Object value)

Eg:servletContext.setAttribute(“xxx”, “XXX”)
//在ServletContext中保存了一个域属性,域属性名称为xxx,域属性的值为XXX

获取

//用来获取ServletContext中的数据
Object getAttribute(String name)
//获取名为xx的域属性
Eg:String value = (String)servletContext.getAttribute(“xxx”);

//获取所有域属性的名称;
Enumeration getAttributeNames()

移除

//用来移除ServletContext中的域属性
void removeAttribute(String name)

访问量统计的小案例

package cn.ideal.web.servlet;

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

public class ServletDemo2 extends GenericServlet {
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        //获取ServletContext对象
        ServletContext servletContext = this.getServletContext();
        //获取ServletContext对象中的count属性
        Integer count = (Integer) servletContext.getAttribute("count");
        if (count == null) {
            //如果在ServletContext中不存在count属性,name设置为count的值为1,表示第一次访问
            count = 1;
        } else {
            //如果在Servlet中存在count属性,说明以前被访问过,name让count在原来的基础上加1
            count++;
        }
        servletResponse.setContentType("text/html;charset=UTF-8");
        //向客户端响应本页面被访问的次数
        servletResponse.getWriter().print("<h1>本页面一共访问" + count + "次</h1>");
        //保存count的值到ServletContext对象中
        servletContext.setAttribute("count", count);
    }
}

(八) 获取资源相关方法

(1) 获取路径

使用ServletContext对象可以用来获取Web应用下的资源,例如在一个web应用的根目录下创建aaa.txt文件,WEB-INF目录下创建bbb.txt文件,如果我们想要通过Servlet获取这两者的路径就可以这样来写

//获取aaa.txt的路径
String realPath = servletContext.getRealPath(“/aaa.txt”)

//获取bbb.txt的路径
?String realPath = servletContext.getRealPath(“/WEB-INF/b.txt”)

获取单个文件路径是这样,我们还有一种方式,可以获取到指定目录下所有的资源路径,例如获取/WEB-INF下的所有资源路径

Set set = context.getResourcePaths("/WEB-INF");
System.out.println(set);

(2) 获取资源流

不仅我们可以使用ServletContext获取路径,我们还可以获取资源流,以上面假设的两个文件为例

//获取aaa.txt
InputStream in = servletContext.getResourceAsStream(“/aaa.txt”);

//获取bbb.txt
InputStream in = servletContext.getResourceAsStream(“/WEB-INF/b.txt”);

(3) 获取类路径下资源

InputStream in = this.getClass().getClassLoader().getResourceAsStream("xxx.txt");
System.out.println(IOUtils.toString(in));

(九) 使用注解,不再配置web.xml

每创建一个Servlet我们就需要在web.xml中配置,但是如果我们的Servlet版本在3.0以上,就可以选择不创建web.xml,而使用注解来解决,十分简单方便

例如我们创建一个Servlet,配置web.xml如下

<servlet>
    <servlet-name>ServletDemo2</servlet-name>
    <servlet-class>cn.ideal.web.servlet.ServletDemo2</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>ServletDemo2</servlet-name>
    <url-pattern>/Demo2</url-pattern>
</servlet-mapping>
//在类名的上方写入这样一句代码,引号内为外部访问路径
@WebServlet("/Demo2")

是不是很简单方便,我们看一下其中的原理:

//WebServlet 源码节选
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebServlet {
    String name() default "";

    String[] value() default {};

    String[] urlPatterns() default {};

    int loadOnStartup() default -1;

这个注解可以看到,@Target({ElementType.TYPE})作用范围为类上,@Retention(RetentionPolicy.RUNTIME)保留在运行期,name()方法反而在这里没有那么重要,因为在web.xml中,name主要起一个关联的作用,其中我们最重要的就是这个String[] urlPatterns() default {};配置一个地址,它的定义为一个数组,当然配置一个也是可以的,即urlPatterns = "/Demo2"而其中value所代表的最重要的值,其实也就代表这个地址,所以可以写为 Value = "/Demo2" ,而 Value又可以省略,所以可以写成 "/Demo2"

结尾:

如果内容中有什么不足,或者错误的地方,欢迎大家给我留言提出意见, 蟹蟹大家 !^_^

如果能帮到你的话,那就来关注我吧!(系列文章均会在公众号第一时间更新)

在这里的我们素不相识,却都在为了自己的梦而努力 ?

一个坚持推送原创Java技术的公众号:理想二旬不止

原文地址:https://www.cnblogs.com/ideal-20/p/11407196.html

时间: 2024-10-18 12:25:03

Servlet技术之——概述、实现、细节、获取资源、ServletConfig、ServletContext的相关文章

web开发技术中Servlet技术的概述

1.servlet是什么:servlet是一个位于服务器端的java应用程序它可以像jsp一样,直接输出信息 servlet类必须继承HttpServlet类,否则,不能称为serlvet servlet类是一个java类,但是有自己的规则servlet必须在web.xml文件中注册服务器在启动的时候,可以根据这些配置来加载servlet类....... 2.servlet作用:C:控制层serlvet主要用来做控制转发,需要结合到MVC模式(套路) 3.servlet生命周期:initserv

QML Image获取资源路径的细节

ML是门相当新的UI描述语言,因此在文档上总难免有疏漏之处,如果因此产生了bug,则就需要花费大量的时间去排查. 在最近笔者使用QML的过程中,在Image获取资源路径的细节上就出现了这样的情况. Image 是qml中一个非常普通的元素,通常使用方法如下: Image {  width: 120; height: 120  fillMode: Image.TileHorizontally  smooth: true  source: "qtlogo.png"  } 其中,source

servlet和普通类获取资源文件的方法

package cn.servlet.demo1; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.util.Properties; import javax.servlet

Java web(Servlet技术基础)

1.Servlet技术 1.1 Servlet概述: 什么是Servlet:它是运行在web服务器端的一个Java小程序,简单来说,它就是一个Java类. 在使用Servlet时,需要导入javax.servlet下的jar包.比如:Tomcat服务器 提供了Servlet的servlet-api.jar包,所以在开发时用Tomcat服务器就不需要 再导入Servlet的jar包. Servlet它是一个资源,是用来被用户访问的资源,同时是一个动态资源,它是由sun公司指定的Servlet规范.

【Java】Java Servlet 技术简介

Java 开发人员兼培训师 Roy Miller 将我们现有的 servlet 介绍资料修改成了这篇易于学习的实用教程.Roy 将介绍并解释 servlet 是什么,它们是如何工作的,如何使用它们来创建您能够想像到的任意复杂度的 Web 应用程序,以及作为一名专业编程人员,您如何才能最有效地使用 servlet. 5 评论: Roy W. Miller ([email protected]), 独立的软件开发辅导员.程序员和作者, RoleModel Software 2004 年 12 月 2

Java Servlet 技术简介

Java Servlet 技术简介 Java 开发人员兼培训师 Roy Miller 将我们现有的 servlet 介绍资料修改成了这篇易于学习的实用教程.Roy 将介绍并解释 servlet 是什么,它们是如何工作的,如何使用它们来创建您能够想像到的任意复杂度的 Web 应用程序,以及作为一名专业编程人员,您如何才能最有效地使用 servlet. 4 评论: Roy W. Miller ([email protected]), 独立的软件开发辅导员.程序员和作者, RoleModel Soft

Servlet技术的特点及使用

一.Servlet的简介 Servlet的概述servlet是运行在服务端的java程序 servlet是一套规范(接口) 外界都可以访问到 servlet的快速入门步骤:(1) 创建一个类 实现servlet(2)覆盖servlet接口中的全部方法(尤其是service方法)(3)需要进行虚拟路径的配置web.xml配置部分: <?xml version="1.0" encoding="UTF-8"?> <web-app version=&quo

Java Web之Servlet技术

1.Servlet基础 针对Servlet技术开发,Sun公司提供了一些列接口和类,其中最重要的是javax.servlet.Servlet接口,两个重要的包是javax.servlet和javax.servlet.http,Servlet就是一种实现了Servlet接口的类,它由Web容器(Tomcat/Jetty等)负责调用并创建,用于接收和响应用户请求.Servlet接口中定义了5个抽象方法: 方法 功能 void init(ServletConfig config) 负责Servlet初

Java EE之Servlet技术

Java EE之Servlet技术 java Servlet介绍 Java Servlet是java EE标准规范之一.Servlet是Java Web 技术的核心基础, 因此掌握好Servlet是很有必要的.掌握Servlet的工作原理是成为一名合格的 Java Web技术开发人员的基本要求. Servlets are very important topic of Java EE and all of the web applications framework such as Spring