JavaWeb——Servlet详解

2023-11-12

什么是Servlet?

  • Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。
  • 狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。Servlet运行于支持Java的应用服务器中。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。

Servlet及其子类

在这里插入图片描述

其中GenericServlet同时也继承了ServletConfigSerializable

Servlet中常用方法

  • void init(ServletConfig var1) throws ServletException;

  • void service(ServletRequest request, ServletResponse response) throws ServletException, IOException;

  • void destroy();

  • ServletConfig getServletConfig();

  • String getServletInfo();

init

用来初始化由Servlet容器实例化的对象。在GenericServlet中实现了该方法。
在这里插入图片描述
在这里插入图片描述
上面是GenericServlet中的类级属性和init方法的实现,在Servlet容器初始化Servlet时,会根据配置信息创建一个ServletConfig对象,然后将该参数传给init方法完成初始化。

service

每当客户端向Servlet发送请求时,就会调用service方法,该方法会根据请求方式调用相应的方法。
在这里插入图片描述
该方法有两个参数:Request和Response,当客户端发送请求时,Servlet容器会创建这两个对象,并且传参给sevice。

distory

该方法用来销毁Servlet。当要卸载应用程序或者关闭Servlet容器时,就会调用该方法。

Servlet的生命周期

Servlet对象的创建到销毁就是Servlet的生命周期。

下面是Servlet从创建到销毁的过程:

  1. 当Servlet第一次收到请求时,Servlet容器会首先通过反射机制实例化一个Servlet对象,然后调用init方法初始化该对象,最后调用service方法

  2. 当Servlet第二次收到请求时只会调用service方法,之后收到请求也同样如此。

  3. 终止程序,关闭Servlet容器,此时就会调用distory

下面用代码演示一下该过程:

public class TestServlet01 extends HttpServlet {
    public TestServlet01(){
        System.out.println("正在实例化......");
    }
    @Override
    public void init() throws ServletException {
        System.out.println("正在初始化......");
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("正在服务......");
    }

    @Override
    public void destroy() {
        System.out.println("正在销毁......");
    }
}

在服务器第一次收到请求时,首先进行了实例化,在进行了init(初始化),最后就行了 service(服务)
在这里插入图片描述

在之后的每次请求时,只会调用service
在这里插入图片描述

最后终止程序,关闭Servlet容器,会调用destory
在这里插入图片描述

Servlet初始化时机

在上文提到了Servlet的初始化时机,即在第一次收到请求时会进行初始化,其实在配置Servlet时可以设置参数来改变这个时机。
可以在配置时添加如下代码:

 <servlet>
        <servlet-name>TestServlet01</servlet-name>
        <servlet-class> servlets.TestServlet01</servlet-class>
        <load-on-startup>0</load-on-startup><!--添加这行代码-->
 </servlet>

加了该参数之后(参数大于0),一旦Web项目开始,就会加载该Servlet,实例化该Servlet对象并且调用init()初始化,在参数大于0的情况下,参数越小,加载的时机就越靠前,如果参数是负数,跟没有加是一样的效果。

当我们修改完配置后再次运行这段代码:
在这里插入图片描述

钝化和活化

钝化: 当服务器正常关闭时,还存活着的session(在设置时间内没有销毁) 会随着服务器的关闭被以文件(“SESSIONS.ser”)的形式存储在tomcat 的work 目录下,这个过程叫做Session 的钝化。

活化: 当服务器再次正常开启时,服务器会找到之前的“SESSIONS.ser” 文件,从中恢复之前保存起来的Session 对象,这个过程叫做Session的活化。

注意:只有实现了Serializable接口的对象才能被钝化和活化。

Http协议

  1. 超文本传输协议(Hyper Text Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。请求和响应消息的头以ASCII形式给出;而 消息内容则具有一个类似MIME的格式

  2. Http连接是一次性连接,当服务器和客户端进行完请求和响应后,连接就会断开,这样http就不会处于等待状态,及时地释放连接可以大大提高服务器的执行效率。

  3. Http是无状态协议,即服务器不保留与客户交易时的任何状态。这就大大减轻了服务器记忆负担,从而保持较快的响应速度。

  4. Http请求响应包含两个部分:请求和响应

    ----------请求
    请求包含三个部分:请求行,请求消息头,请求主题
    (1) 请求行:包含三个信息:请求的方式 ; 请求的url ; 请求的协议
    (2) 请求消息头:包含了很多客户端要告诉服务器的信息(比如说浏览器的版本型号,能够接受响应的类型等)
    (3)请求体:
    get方式没有请求体,但是有queryString
    post方式,有请求体,form data
    json格式,有请求体,request payload

    ---------响应
    响应包含三个部分:响应行; 响应头; 响应体
    (1)响应行:协议;响应状态码
    (2)响应头:包含了服务器的信息
    (3)响应的实际内容(比如请求html页面时,响应就时该html文件中的具体内容)

Session

Http是无状态连接,并且是一次性连接,所以同一个Servlet无法判断两次请求是否来自同一个客户端,session就解决了该问题。

会话跟踪技术

  1. 客户端第一次发请求给服务器,服务器获取尝试session,获取不到,则创建新的,然后响应给客户端。
  2. 下次客户端发送请求时会将已有的session发送给服务器。

常用API

    request.getSession() 获取当前会话,没有创建一个新的
    request.getSession(true) 获取当前会话,没有获取一个新的,和无参的一样
    request.getSession(false) 获取当前会话,没有返回null,不会创建新的

    session.isNew(); 判断当前会话是否是新创建的
    session.getMaxInactiveInterval();获取会话的最大非激活间隔时常(一定时间不发送请求,会话就会失效,进行一次请求和响应,该时间就会刷新),默认为1800s
    session.setMaxInactiveInterval(int interval);设置session的最大非激活间隔时常,interval为正数时表示以秒为单位的时长,负数表示永不失效    
   session.invalidate();强制让会话失效

演示

public class TestServlet03 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //HttpSession session = req.getSession();
        //Object o = session.getAttribute("123");
        HttpSession session = req.getSession();
        System.out.println("session id = " +session .getId());
        System.out.println("isNew = " + session.isNew());
    }
}

在这里插入图片描述

Session保存作用域

每一个session都有自己的保存作用域,在作用域内以键值对的方式保存信息,拥有相同session的请求(同一个客户端)可以访问该作用域。

Session类中有以下常用API:

  • void setAttribute(String key,Object value) ------- 以键值对的方式保存信息。
  • Object getAttribute(String key) ------- 通过key来获取value
  • void removeAttribute(String key) ----- 通过key来删除键值对

服务器端内部转发和客户端重定向

服务器内部转发

//var是要跳转的Servlet
request.getRequestDispatcher(String var).forward(ServletRequest request,ServletResponse response);

在这里插入图片描述

客户端只知道自己向Servlet01发送了请求,并且收到了响应,服务器内部发生了什么,自己不知道,所以客户端从发送请求至收到响应自己的地址栏(url)并不会发生改变,页面不会发生跳转。

客户端重定向

//var是重定向的Servlet
response.sendRedirect(String var);

在这里插入图片描述
此时客户端向test04发送请求,test04响应客户端,让其向test05发送请求。客户端的地址栏会发生改变,页面会跳转。

get()和post()区别

  1. 客户端直接请求servlet时默认请求方式为get。
  2. 提交html表单时,使用get方式会将参数数据放在url的后边发给服务器,不安全。
  3. 提交html表单时,使用post方式会将参数数据放在http的请求体里面发给服务器,较为安全。
  4. get传送的数据是添加在url后边的,浏览器对url都有自己的长度限制,所以通过get方式发送的数据量较小。
  5. post发送数据的是添加在http请求体里的,发送数据量较大,但是一般服务器会对post发送的数据量进行限制

ServletRequest和ServletResponse

对于每一个Http请求,Servlet容器都会创建一个ServletRequest,和一个ServletResponse请求,并且传给service方法。

常用API

ServletRequest中:

//获取指定参数的值,常用来获取HTML表单指定参数的值
public String getParameter(String name)

ServletResponse中:

//通过getWriter方法获取PrintWriter对象,然后通过调用print/println向客户端发送数据。
 PrintWriter writer = response.getWriter();
 writer.print("发送内容");

在向客户端发送数据前需要告诉服务器编码类型,如果发送的是HTML标签,同样也需要告诉客户端,如下:

resp.setHeader("Content-Type","text/html;charset=utf-8");

Request保存作用域

类似于session的保存作用域,每一个请求和响应的过程中都有一个保存作用域,在响应完成前可以访问该保存作用域。响应前,在servlet中采用服务器内部转发,在另外一个servlet中同样可以访问该作用域。
Request中常用API

  • void setAttribute(String key,Object value) ------- 以键值对的方式保存信息。
  • Object getAttribute(String key) ------- 通过key来获取value
  • void removeAttribute(String key) ----- 通过key来删除键值对

ServletContext

ServletContext表示Servlet应用程序,通过ServletContext可以访问应用范围的初始化参数和属性,即在一个应用程序范围内可以访问application保存作用域里的内容。
应用程序范围:服务器开启到服务器关闭。
application作用域:在应用程序范围内,所有请求都可以访问该作用域。
ServletContextd对象的获取: 调用ServletConfig中的getServletContext()方法,GenericServlet抽象类中实现了该方法。
ServletContext对象中常用API

  • void setAttribute(String key,Object value) ------- 以键值对的方式保存信息。
  • Object getAttribute(String key) ------- 通过key来获取value
  • void removeAttribute(String key) ----- 通过key来删除键值对
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JavaWeb——Servlet详解 的相关文章

  • 从txt文件中读取数据而不下载它?

    我想从提供的文本文件中解析信息 有没有一种方法可以在应用程序中执行此操作 而无需先下载文件 以某种方式传输文本内容 打开到 URL 的 Http 连接 使用内置 HttpURLConnection 或使用 commons httpclien
  • 在Java Servlet中获取通过jquery ajax发送的参数[重复]

    这个问题在这里已经有答案了 我在网上搜索这个主题 但找不到有效的示例 我会很高兴有人能给我帮助 这就是我测试的 ajax url GetJson type POST dataType json contentType application
  • 从 Android 函数更新 Textview

    有人可以告诉我如何从函数更新 Android Textview 控件吗 我在互联网上进行了深入搜索 看到很多人都问同样的问题 我测试了线程但无法工作 有人有一个简单的工作示例吗 例如 调用一个函数 在循环中运行多次 并且该函数在 TextV
  • Selector.close() 是否关闭所有客户端套接字?

    我是 nio 套接字的新手 我已经使用 nio 套接字编写了一个服务器 现在我正在尝试编写关闭钩子以确保通过清理资源正常退出 我的问题是Selector close 方法关闭所有客户端套接字 如果没有 请告诉我如何访问所有客户端套接字 而无
  • Java:为什么.class文件中的方法类型包含返回类型,而不仅仅是签名?

    class 文件的常量池中有一个 NameAndType 结构 它用于动态绑定 该类可以 导出 的所有方法都被描述为 签名 返回类型 喜欢 getVector Ljava util Vector 当某些 jar 中方法的返回类型发生更改时
  • Spring 从 JBoss 上下文加载 PropertySourcesPlaceholderConfigurer

    我有一个使用 PropertySourcesPlaceholderConfigurer 的 spring 3 1 应用程序加载设置 我想管理测试和生产环境 只需从服务器上下文加载设置覆盖本地文件属性中指定的设置 下一个示例在 Tomcat
  • 如何在正则表达式中编写可选单词?

    我想编写一个识别以下模式的 java 正则表达式 abc def the ghi and abc def ghi 我试过这个 abc def the ghi 但是 它没有识别第二种模式 我哪里出错了 abc def the ghi 删除多余
  • 是否可以使用 Apache Tika 提取表信息?

    我正在寻找 pdf 和 MS Office 文档格式的解析器 以从文件中提取表格信息 当我看到 Apache Tika 时 正在考虑编写单独的实现 我能够从任何这些文件格式中提取全文 但我的要求是提取表格数据 我希望有 2 列采用键值格式
  • 是否可以创建 Java RAM 磁盘以与 java.io.* API 一起使用?

    我正在使用一个第三方库 它基本上创建一个输出目录 其中包含不同类型的文件和子目录 我希望能够编写单元测试来确认输出正确 我希望能够将库与 RAM 磁盘一起使用 这样库所做的任何事情都不会以任何方式接触实际的磁盘板 这个想法是让测试运行和清理
  • 在 Eclipse 中删除空块之前的新行

    我更喜欢奥尔曼式 http en wikipedia org wiki Brace style Allman style大括号 例如 if foo magical prancing unicorn stuff 而不是 if foo unma
  • 扩展多个类

    我知道 Java 不支持多重继承 因为不允许扩展多个类 我只是想知道我的问题是否有解决方法 我有一个名为CustomAction需要扩展两个抽象类 BaseAction and QuoteBaseAction 我无法更改这些抽象类中的任何一
  • 如何在 JmsMessagingTemplate.sendAndReceive 上设置等待超时

    我在 MVC 控制器中使用 JmsMessagingTemplate 的 sendAndReceive 但如果没有发送回复消息 它似乎会永远等待回复 该文档指出 返回 回复 如果无法接收消息 例如由于超时 则可能为 null 然而 我只是不
  • javadoc 子集/java 库组织

    我自己从来没有运行过javadoc 无论是在命令行还是ant 的 javadoc 任务 http ant apache org manual Tasks javadoc html 我将使用 ant 我需要为我编写的库生成 javadoc 问
  • 在 Eclipse RCP 应用程序中禁用插件贡献

    我经常遇到这个问题 但尚未找到解决方案 每当我编写一个新的基于 Eclipse RCP 的应用程序并包含来自 Eclipse 平台的插件时 我都会 继承 其中一些插件的 UI 贡献 大多数贡献 菜单项 键盘快捷键 属性页 都很有用 但有时我
  • 向Java类库添加函数

    我使用的 Java 类库在很多方面都不完整 有很多类我认为应该内置其他成员函数 但是 我不确定添加这些成员函数的最佳实践 让我们调用不足的基类A class A public A long arbitrary arguments publi
  • 如何在一次操作中使用 Thymeleaf 检查 null 和空条件?

    有什么方法可以检查 Thymeleaf 中的 null 和empty 条件吗 方法一 1 variable1 variable2 variable3 2 variable null 3 variable 如果我们结合两个条件 例如 vari
  • 为什么/何时应该使用泛型方法?

    学习Java的时候遇到过通用方法 public
  • 假布尔值=真?

    我在一本书中找到了这段代码 并在 Netbeans 中执行了它 boolean b false if b true System out println true else System out println false 我只是不明白为什
  • Axis2 的 wsdl2java 在 RPC/Encoded 样式 Web 服务上失败

    Axis2 有替代方案吗 或者让它工作的方式 例如不同的数据绑定 Retrieving document at Exception in thread main org apache axis2 wsdl codegen CodeGener
  • Graphics2D setfont() 严重减慢了 java 应用程序的启动速度

    我正在用java制作一个游戏 它每秒刷新60次 每次执行循环时 我都会使用 g2d 来绘制图像和字符串 如果我这样做的话一切都会很好g2d setFont new Font Arial Font PLAIN 8 和抽绳 这将是正常的 但如果

随机推荐