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详解 的相关文章

  • 如何为最终用户方便地启动Java GUI程序

    用户想要从以下位置启动 Java GUI 应用程序Windows 以及一些额外的 JVM 参数 例如 javaw Djava util logging config file logging properties jar MyGUI jar
  • Spring Batch 多线程 - 如何使每个线程读取唯一的记录?

    这个问题在很多论坛上都被问过很多次了 但我没有看到适合我的答案 我正在尝试在我的 Spring Batch 实现中实现多线程步骤 有一个包含 100k 条记录的临时表 想要在 10 个线程中处理它 每个线程的提交间隔为 300 因此在任何时
  • 为什么 i++ 不是原子的?

    Why is i Java 中不是原子的 为了更深入地了解 Java 我尝试计算线程中循环的执行频率 所以我用了一个 private static int total 0 在主课中 我有两个线程 主题 1 打印System out prin
  • 如何在 Play java 中创建数据库线程池并使用该池进行数据库查询

    我目前正在使用 play java 并使用默认线程池进行数据库查询 但了解使用数据库线程池进行数据库查询可以使我的系统更加高效 目前我的代码是 import play libs Akka import scala concurrent Ex
  • Android:捕获的图像未显示在图库中(媒体扫描仪意图不起作用)

    我遇到以下问题 我正在开发一个应用程序 用户可以在其中拍照 附加到帖子中 并将图片保存到外部存储中 我希望这张照片也显示在图片库中 并且我正在使用媒体扫描仪意图 但它似乎不起作用 我在编写代码时遵循官方的Android开发人员指南 所以我不
  • INSERT..RETURNING 在 JOOQ 中不起作用

    我有一个 MariaDB 数据库 我正在尝试在表中插入一行users 它有一个生成的id我想在插入后得到它 我见过this http www jooq org doc 3 8 manual sql building sql statemen
  • 如何在PreferenceActivity中添加工具栏

    我已经使用首选项创建了应用程序设置 但我注意到 我的 PreferenceActivity 中没有工具栏 如何将工具栏添加到我的 PreferenceActivity 中 My code 我的 pref xml
  • 十进制到八进制的转换[重复]

    这个问题在这里已经有答案了 可能的重复 十进制转换错误 https stackoverflow com questions 13142977 decimal conversion error 我正在为一个类编写一个程序 并且在计算如何将八进
  • 在两个活动之间传输数据[重复]

    这个问题在这里已经有答案了 我正在尝试在两个不同的活动之间发送和接收数据 我在这个网站上看到了一些其他问题 但没有任何问题涉及保留头等舱的状态 例如 如果我想从 A 类发送一个整数 X 到 B 类 然后对整数 X 进行一些操作 然后将其发送
  • getResourceAsStream() 可以找到 jar 文件之外的文件吗?

    我正在开发一个应用程序 该应用程序使用一个加载配置文件的库 InputStream in getClass getResourceAsStream resource 然后我的应用程序打包在一个 jar文件 如果resource是在里面 ja
  • 如何在 javadoc 中使用“<”和“>”而不进行格式化?

    如果我写
  • 仅将 char[] 的一部分复制到 String 中

    我有一个数组 char ch 我的问题如下 如何将 ch 2 到 ch 7 的值合并到字符串中 我想在不循环 char 数组的情况下实现这一点 有什么建议么 感谢您花时间回答我的问题 Use new String value offset
  • Android 中麦克风的后台访问

    是否可以通过 Android 手机上的后台应用程序 服务 持续监控麦克风 我想做的一些想法 不断聆听背景中的声音信号 收到 有趣的 音频信号后 执行一些网络操作 如果前台应用程序需要的话 后台应用程序必须能够智能地放弃对麦克风的访问 除非可
  • 如何在桌面浏览器上使用 webdriver 移动网络

    我正在使用 selenium webdriver 进行 AUT 被测应用程序 的功能测试自动化 AUT 是响应式网络 我几乎完成了桌面浏览器的不同测试用例 现在 相同的测试用例也适用于移动浏览器 因为可以从移动浏览器访问 AUT 由于它是响
  • 玩!框架:运行“h2-browser”可以运行,但网页不可用

    当我运行命令时activator h2 browser它会使用以下 url 打开浏览器 192 168 1 17 8082 但我得到 使用 Chrome 此网页无法使用 奇怪的是它以前确实有效 从那时起我唯一改变的是JAVA OPTS以启用
  • 声明的包“”与预期的包不匹配

    我可以编译并运行我的代码 但 VSCode 中始终显示错误 早些时候有一个弹出窗口 我不记得是什么了 我点击了 全局应用 从那以后一直是这样 Output is there but so is the error The declared
  • simpleframework,将空元素反序列化为空字符串而不是 null

    我使用简单框架 http simple sourceforge net http simple sourceforge net 在一个项目中满足我的序列化 反序列化需求 但在处理空 空字符串值时它不能按预期工作 好吧 至少不是我所期望的 如
  • 捕获的图像分辨率太大

    我在做什么 我允许用户捕获图像 将其存储到 SD 卡中并上传到服务器 但捕获图像的分辨率为宽度 4608 像素和高度 2592 像素 现在我想要什么 如何在不影响质量的情况下获得小分辨率图像 例如我可以获取或设置捕获的图像分辨率为原始图像分
  • 有没有办法为Java的字符集名称添加别名

    我收到一个异常 埋藏在第 3 方库中 消息如下 java io UnsupportedEncodingException BIG 5 我认为发生这种情况是因为 Java 没有定义这个名称java nio charset Charset Ch
  • 节拍匹配算法

    我最近开始尝试创建一个移动应用程序 iOS Android 它将自动击败比赛 http en wikipedia org wiki Beatmatching http en wikipedia org wiki Beatmatching 两

随机推荐