Javaweb动态开发最重要的Servlet详解
作者:懒羊羊.java 发布时间:2023-04-09 20:11:17
一.导入方式
由于jdk中没有servlet对应的jar包,所以需要咱们手动引入,有两种方式:
1.可以采取向lib目录导入servlet-api的jar包的方式
2.在maven项目中设置如下坐标,并添加相关依赖到依赖库中即可(推荐使用这种,在maven里选择webapp的骨架建立项目会自动给你配置好web.xml文件)
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
版本号可以自己定,依赖范围要配置成provided,否则会和其他jar包冲突
二.Servlet生命周期
原生的Servlet项目都是实现Servlet接口,功能都是通过实现这个接口或者继承HttpServlet来完成的,其实在IDEA里重写方法的过程中所对应的顺序就是他的生命周期,以下面为例:
按照每一个方法翻译而来的字面意思,流程是:
初始化——得到服务配置——服务——获取服务信息——销毁,简言之,就是一个从初始化到服务再到消亡的过程。
初始化阶段:
public void init(ServletConfig servletConfig)
当服务器启动,读取web.xml文件的过程中,Tomcat加载 Servlet,加载完成后,Servlet 容器会创建一个 Servlet 实例 并调用 init()方法,init()方法只会调用一次,这个没什么好解析的,就是面向对象中类特性的体现
服务阶段:
public void service(ServletRequest servletRequest, ServletResponse servletResponse)
这个方法的形参里有两个ServletRequest和ServletResponse类型的接口,翻译过来就是服务请求、服务响应,Tomcat启动时自动装载某些 servlet,并在 Servlet 容器启动后,浏览器首次向 Servlet 发送请求,发送的请求和响应作为参数就传到了service方法对应的形参里进行处理。看了一下jdk的源码,发现两个接口下面都有很多的抽象方法,至于请求和响应在底层是怎样执行的源码里啥都没写,目前还不知道(推测是个底层驱动)
消亡阶段:
public void destroy()
从图中规定的顺序不难看出,执行到最后的方法也就预示着Servlet的生命即将结束
在JDK的源码中,Servlet接口下的destory()没有方法体,应该也是和启动线程的start0()方法类似被开发者封装简化了
完整流程演示:
@WebServlet("/demo1")
public class SevDemo1 implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {System.out.println("我在初始化~~~");}
@Override
public ServletConfig getServletConfig() {return null;}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("hello world!!!!");}
@Override
public String getServletInfo() {return null;}
@Override
public void destroy() {System.out.println("我走了,拜拜~~~");}
}
控制台打印的信息很好地反映了执行情况:
至于public ServletConfig getServletConfig()
和public String getServletInfo()
在实现接口后重写的方法中默认返回的是null,应该是两个起补充作用的方法
三.继承HttpServlet
在实际开发中采用继承HttpServlet类的方式开发Servlet程序更加方便,因为实现接口重写那麽多方法是真的麻烦,而通过继承的方式就可以根据需要选择性的重写doGe()或doPost()方法就简单很多,比如
public class HttpDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("执行 doGet()...");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("执行 doPost()...");
}
}
至于方法体里写什么内容就要看对应的业务场景了
气氛烘托到这里了就不得不说一下GET和POST的区别了
GET&POST
以前老师是教我这样理解的——我把一封信放在信封里邮寄出去,我可以选择密封或者不密封,而这就会导致信的内容会不会被别人看到,若是前者则对应POST,后者就对应GET
当然,这只是抽象层面,而从具体方面来看:
1.从功能上来讲,get是从服务器上获取数据,post是向服务器传送数据
2.从报文上来讲,在不带参数时区别就单纯是第一行方法名不同,而在带参数时GET方法的参数放在请求头URL中,POST方法的参数放在请求体BODY中 注:GET方法的参数写在?后,用&分割
3.从安全性来讲,其实他们都不安全,因为http是明文传输(在网页按F12进入开发者模式发现两种方式都能看到数据信息)。但是这张图应该很生动形象也能反映一些问题,相比较之下POST还是比GET安全,因为数据在地址栏不可见,哈哈哈
四.Servlet相关性质(八股文)
1.Servlet 是一个供其他 Java 程序(Servlet 引擎)调用的 Java 类,不能独立运行
2.对于每次访问请求,Servlet 引擎都会创建一个新的 HttpServletRequest 请求对象和一个 新的 HttpServletResponse 响应对象,然后将这两个对象作为参数传递给它调用的 Servlet 的 service()方法,service 方法再根据请求方式分别调用 doXXX 方法
3.针对浏览器的多次 Servlet 请求,通常情况下,服务器只会创建一个 Servlet 实例对象, 也就是说 Servlet 实例对象一旦创建,它就会驻留在内存中,为后续的其它请求服务,直至 web 容器退出/或者 redeploy 该 web 应用,servlet 实例对象才会销毁
4.如果在<servlet>元素中配置了一个<load-on-startup>元素,那么 WEB 应用程序在启动时, 就会装载并创建 Servlet 的实例对象、以及调用 Servlet 实例对象的 init()方法
5.在 Servlet 的整个生命周期内,init 方法只被调用一次。而对每次请求都导致 Servlet 引 擎调用一次 servlet 的 service 方法
——ps:刷dy整理出来的
五.Request&Response
对于这些内部方法来说我觉得会用API就行
1.HttpServletRequest
HttpServletRequest 表示请求过来的信息:
公共接口类HttpServletRequest继承自ServletRequest。客户端浏览器发出的请求被封装成为一个HttpServletRequest对象。对象包含了客户端请求信息包括请求的地址,请求的参数,提交的数据,上传的文件客户端的ip甚至客户端操作系统都包含在其内。
还是面向对象那一套,封装成类后调用里面的方法,部分常用方法如下:
public String getAuthType() | 返回这个请求的身份验证模式 |
---|---|
public Cookie[ ] getCookies() | 返回一个数组,该数组包含这个请求中当前的所有cookie |
public long getDateHeader(String name) | 返回指定的请求头域的值,这个值被转换成一个精确到毫秒的长整数 |
public String getHeader(String name) | 返回一个请求头域的值。(译者注:与上一个方法不同的是,该方法返回一个字符串) |
2.HttpServletResponse
HttpServletResponse 表示所有响应的信息,需要设置返回给客户端的信息,通过 HttpServletResponse 对象来进行设置即可,会用几个核心API就够了
addHeader(String name,String value) | 将指定的名字和值加入到响应的头信息中 |
---|---|
encodeURL(String url) | 编码指定的URL |
setStatus(int sc) | 给当前响应设置状态码 |
setHeader(String name,String value) | 将给出的名字和值设置响应的头部 |
六.请求转发模型
先前在网页中输出hello java!只是一次请求对应一个Servlet,浏览器——Tomcat——Servlet没有实现请求的转发,而在真实环境中网站不可能只进行一次交互,往往需要在一次请求中使用到多个servlet完成
1.一个 web 资源收到客户端请求后,通知服务器去调用另外 一个 web 资源进行处理
2. HttpServletRequest 对象(也叫 Request 对象)提供了一个 getRequestDispatcher 方法,该 方法返回一个 RequestDispatcher 对象,调用这个对象的 forward 方法可以实现请求转发
3. request 对象同时也是一个域对象,开发人员通过 request 对象在实现转发时,把数据 通过 request 对象带给其它 web 资源处理
在实际场景中,用户输入信息提交后得到反馈这一过程就是典型的请求转发,就像这样:
第一个Servlet里的情况
@WebServlet("/demo2")
public class Sevdemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("这里是demo2~~");
//存储数据
req.setAttribute("懒羊羊","你好!");
//请求转发
req.getRequestDispatcher("/demo3").forward(req,resp);
}
}
第二个Servlet里的情况
@WebServlet("/demo3")
public class Sevdemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("这里是demo3~~");
Object msg= req.getAttribute("懒羊羊");
System.out.println(msg);
}
}
当我启动Tomcat来访问demo2时:
实现了请求的转发!
既然是一个Servlet转发给另一个Servlet,且是部署在同一个Tomcat中,那就说明不能访问当前web工程外的资源、同一次 HTTP 请求中,进行多次转发,仍然是一次 HTTP 请求
七.请求重定向
和请求转发比较类似,请求重定向指:一个 web 资源收到客户端请求后,通知客户端去访问另外一个 web 资源,这称之为请求重定向,还是通过API调方法来实现,基本流程如下:
首先通过setStatus()设置响应状态码,然后setHeader(“location”,“http://www.taobao.com”)设置新地址
就实现了请求重定向
@WebServlet("/demo2")
public class Sevdemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("这里是demo2~~");
//设置响应状态码
resp.setStatus(302);
//设置新地址
resp.setHeader("location","http://www.taobao.com")
}
}
还有第二种方法,其实和这也大同小异
到这里动态web的核心Servlet就介绍完了
内容以及配图都是作者原创,若是觉得不错的话可以三连一下,懒羊羊蟹蟹你~
来源:https://iyu77.blog.csdn.net/article/details/125626625


猜你喜欢
- 最近开发过程中遇到了一个问题,之前没有太注意,这里记录一下。我用的SpringBoot版本是2.0.5,在跟前端联调的时候,有个请求因为用户
- 登陆的时候,发现输入账号的不同大小写竟然能够登陆。Mybatis查询代码如下<select id="selectById&q
- 本文实例为大家分享了C#添加PDF文件水印的具体代码,供大家参考,具体内容如下using System;using System.Colle
- Spring的 * 缓存Spring * 缓存是为了解决对象间的循环依赖问题。A依赖B,B依赖A,这就是一个简单的循环依赖。我们来先看看 * 缓存
- 目录目标为什么操作步骤工程截图运行效果完整源代码目标在SpringBoot中集成内存数据库H2.为什么像H2、hsqldb、derby、sq
- 最近没事写了一个简易浏览器,在刚开始写的时候遇到一些问题,主要的问题就是如何在自己的webview中显示所有的网页数据,不过不指
- Struts2Struts2是在WebWork2基础发展而来的。和struts1一样, Struts2也属于MVC框架。不过有一点
- Spring 注入static属性值本文介绍Spring中如何从属性文件给static字段注入值。实际应用中一些工具类中static属性值需
- 缘起标准的RABC, 权限需要支持动态配置,spring security默认是在代码里约定好权限,真实的业务场景通常需要可以支持动态配置角
- 1、需求在代码中经常会遇到需要把对象复制一遍,或者把属性名相同的值复制一遍。比如:public class Student {
- 前言平时我们都有用到LeakCanary来分析内存泄露的情况,这里可以来看看LeakCanary是如何实现的,它的内部又有哪些比较有意思的操
- 本文实例讲述了Java编程调用微信接口实现图文信息等推送功能。分享给大家供大家参考,具体如下:Java调用微信接口工具类,包含素材上传、获取
- 之前我们有介绍通过Spring Boot Admin来检测服务的上下线,然后进行通知功能。https://www.jb51.net/arti
- 本文实例讲述了Java Swing实现简单的体重指数(BMI)计算器功能。分享给大家供大家参考,具体如下:BMI,Body Mass Ind
- 1.理解全过程1.1.概述需要具备的知识Socket网络编程反向代理的理解平滑加权轮询算法的理解线程池的理解目的:实现Socket 集群服务
- 一、首先在Spring Boot项目中,手动添加异常方法进行测试@Transactional(rollbackFor=Exception.c
- 配置文件m103替换为hdfs服务地址。要利用Java客户端来存取HDFS上的文件,不得不说的是配置文件hadoop-0.20.2/conf
- 平时开发的工作中, 自己组内的很多大佬经常使用Optional的用法, 自己问他们, 这个到底有什么好处呢,他们说可以很好的规避好空指针的问
- 许多开发人员对异步代码和多线程以及它们的工作原理和使用方法都有错误的认识。在这里,你将了解这两个概念之间的区别,并使用c#实现它们。我:“服
- Android移动开发实现简单计算器功能,供大家参考,具体内容如下前言android 开发小实验android 移动开发实现 简易计算器功能