Servlet-01
文章目录
- Servlet
- 创建Servlet
- 探究Servlet的生命周期
- HttpServlet
- @WebServlet注解详解
- 重定向与请求转发
- ServletContext
- ServletContext中的接口
- HttpServletRequest
- HttpServletResponse
- 状态码解释
- Cookie
Servlet
Q:它能做什么呢?
A:我们可以通过实现Servlet来进行动态网页响应,使用Servlet,不再是直接由Tomcat服务器发送我们编写好的静态网页内容(HTML文件),而是由我们通过Java代码进行动态拼接的结果,它能够很好地实现动态网页的返回。
当然,Servlet并不是专用于HTTP协议通信,也可以用于其他的通信,但是一般都是用于HTTP。
创建Servlet
我们只需要实现Servlet
类即可,并添加注解@WebServlet
来进行注册。
@WebServlet("/test")
public class TestServlet implements Servlet {...实现接口方法
}
除了直接编写一个类,我们也可以在web.xml
中进行注册,现将类上@WebServlet
的注解去掉:
<servlet><servlet-name>test</servlet-name><servlet-class>com.example.webtest.TestServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>test</servlet-name><url-pattern>/test</url-pattern>
</servlet-mapping>
这样的方式也能注册Servlet
实际上,Tomcat服务器会为我们提供一些默认的Servlet,也就是说在服务器启动后,即使我们什么都不编写,Tomcat也自带了几个默认的Servlet,他们编写在conf目录下的web.xml中:
<!-- The mapping for the default servlet --><servlet-mapping><servlet-name>default</servlet-name><url-pattern>/</url-pattern></servlet-mapping><!-- The mappings for the JSP servlet --><servlet-mapping><servlet-name>jsp</servlet-name><url-pattern>*.jsp</url-pattern><url-pattern>*.jspx</url-pattern></servlet-mapping>
我们发现,默认的Servlet实际上可以帮助我们去访问一些静态资源,这也是为什么我们启动Tomcat服务器之后,能够直接访问webapp目录下的静态页面。
探究Servlet的生命周期
Q:一个Servlet是如何运行的。
A:首先我们需要了解,Servlet中的方法各自是在什么时候被调用的,我们先编写一个打印语句来看看:
public class TestServlet implements Servlet {public TestServlet(){System.out.println("我是构造方法!");}@Overridepublic void init(ServletConfig servletConfig) throws ServletException {System.out.println("我是init");}@Overridepublic ServletConfig getServletConfig() {System.out.println("我是getServletConfig");return null;}@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("我是service");}@Overridepublic String getServletInfo() {System.out.println("我是getServletInfo");return null;}@Overridepublic void destroy() {System.out.println("我是destroy");}
}
我们首先启动一次服务器,然后访问我们定义的页面,然后再关闭服务器,得到如下的顺序:
我是构造方法!
我是init
我是service
我是service(出现两次是因为浏览器请求了2次,是因为有一次是请求favicon.ico,浏览器通病)我是destroy
我们可以多次尝试去访问此页面,但是init和构造方法只会执行一次,而每次访问都会执行的是service
方法,因此,一个Servlet的生命周期为:
- 首先执行构造方法完成 Servlet 初始化
- Servlet 初始化后调用 init () 方法。
- Servlet 调用 service() 方法来处理客户端的请求。
- Servlet 销毁前调用 destroy() 方法。
- 最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。
现在我们发现,实际上在Web应用程序运行时,每当浏览器向服务器发起一个请求时,都会创建一个线程执行一次service
方法,来让我们处理用户的请求,并将结果响应给用户。
我们发现service
方法中,还有两个参数,ServletRequest
和ServletResponse
,实际上,用户发起的HTTP请求,就被Tomcat服务器封装为了一个ServletRequest
对象,我们得到是其实是Tomcat服务器帮助我们创建的一个实现类,HTTP请求报文中的所有内容,都可以从ServletRequest
对象中获取,同理,ServletResponse
就是我们需要返回给浏览器的HTTP响应报文实体类封装。
那么我们来看看ServletRequest
中有哪些内容,我们可以获取请求的一些信息:
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {//首先将其转换为HttpServletRequest(继承自ServletRequest,一般是此接口实现)HttpServletRequest request = (HttpServletRequest) servletRequest;System.out.println(request.getProtocol()); //获取协议版本System.out.println(request.getRemoteAddr()); //获取访问者的IP地址System.out.println(request.getMethod()); //获取请求方法//获取头部信息Enumeration<String> enumeration = request.getHeaderNames();while (enumeration.hasMoreElements()){String name = enumeration.nextElement();System.out.println(name + ": " + request.getHeader(name));}
}
我们发现,整个HTTP请求报文中的所有内容,都可以通过HttpServletRequest
对象来获取,当然,它的作用肯定不仅仅是获取头部信息
那么我们再来看看ServletResponse
,这个是服务端的响应内容,我们可以在这里填写我们想要发送给浏览器显示的内容:
//转换为HttpServletResponse(同上)
HttpServletResponse response = (HttpServletResponse) servletResponse;
//设定内容类型以及编码格式(普通HTML文本使用text/html,之后会讲解文件传输)
response.setHeader("Content-type", "text/html;charset=UTF-8");
//获取Writer直接写入内容
response.getWriter().write("我是响应内容!");
//所有内容写入完成之后,再发送给浏览器
现在我们在浏览器中打开此页面,就能够收到服务器发来的响应内容了。其中,响应头部分,是由Tomcat帮助我们生成的一个默认响应头。
HttpServlet
Servlet
有一个直接实现抽象类GenericServlet
,那么我们来看看此类做了什么事情。
我们发现,这个类完善了配置文件读取和Servlet信息相关的的操作,但是依然没有去实现service方法,因此此类仅仅是用于完善一个Servlet的基本操作,那么我们接着来看HttpServlet
,它是遵循HTTP协议的一种Servlet,继承自GenericServlet
,它根据HTTP协议的规则,完善了service方法。
在阅读了HttpServlet源码之后,我们发现,其实我们只需要继承HttpServlet来编写我们的Servlet就可以了,并且它已经帮助我们提前实现了一些操作,这样就会给我们省去很多的时间。
@WebServlet("/test")
public class TestServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("text/html;charset=UTF-8");resp.getWriter().write("<h1>恭喜你解锁了全新玩法</h1>");}
}
现在,我们只需要重写对应的请求方式,就可以快速完成Servlet的编写。
@WebServlet注解详解
我们接着来看WebServlet注解,我们前面已经得知,可以直接使用此注解来快速注册一个Servlet,那么我们来想细看看此注解还有什么其他的玩法。
首先name属性就是Servlet名称,而urlPatterns和value实际上是同样功能,就是代表当前Servlet的访问路径,它不仅仅可以是一个固定值,还可以进行通配符匹配:
@WebServlet("/test/*")
上面的路径表示,所有匹配/test/随便什么
的路径名称,都可以访问此Servlet,我们可以在浏览器中尝试一下。
也可以进行某个扩展名称的匹配:
@WebServlet("*.js")
这样的话,获取任何以js结尾的文件,都会由我们自己定义的Servlet处理。
那么如果我们的路径为/
呢?
@WebServlet("/")
此路径和Tomcat默认为我们提供的Servlet冲突,会直接替换掉默认的,而使用我们的,此路径的意思为,如果没有找到匹配当前访问路径的Servlet,那么久会使用此Servlet进行处理。
我们还可以为一个Servlet配置多个访问路径:
@WebServlet({"/test1", "/test2"})
我们接着来看loadOnStartup属性,此属性决定了是否在Tomcat启动时就加载此Servlet,默认情况下,Servlet只有在被访问时才会加载,它的默认值为-1,表示不在启动时加载,我们可以将其修改为大于等于0的数,来开启启动时加载。并且数字的大小决定了此Servlet的启动优先级。
@WebServlet(value = "/test", loadOnStartup = 1)
public class TestServlet extends HttpServlet {@Overridepublic void init() throws ServletException {super.init();log.info("我被初始化了!");}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("text/html;charset=UTF-8");resp.getWriter().write("<h1>balbalaba</h1>");}
}
重定向与请求转发
resp.sendRedirect("time");//重定向
req.getRequestDispatcher("/time").forward(req, resp);//请求转发
Q:请求转发有什么好处呢?
A:它可以携带数据!
req.setAttribute("test", "我是请求转发前的数据");
req.getRequestDispatcher("/time").forward(req, resp);
System.out.println(req.getAttribute("test"));
通过setAttribute
方法来给当前请求添加一个附加数据,在请求转发后,我们可以直接获取到该数据。
两者的区别为:
- 请求转发是一次请求,重定向是两次请求
- 请求转发地址栏不会发生改变, 重定向地址栏会发生改变
- 请求转发可以共享请求参数 ,重定向之后,就获取不了共享参数了
- 请求转发只能转发给内部的Servlet
ServletContext
ServletContext全局唯一,它是属于整个Web应用程序的,我们可以通过getServletContext()
来获取到此对象。
此对象也能设置附加值:
ServletContext context = getServletContext();
context.setAttribute("test", "我是重定向之前的数据");
resp.sendRedirect("time");
System.out.println(getServletContext().getAttribute("test"));
因为无论在哪里,无论什么时间,获取到的ServletContext始终是同一个对象,因此我们可以随时随地获取我们添加的属性。
它不仅仅可以用来进行数据传递,还可以做一些其他的事情,比如请求转发:
context.getRequestDispatcher("/time").forward(req, resp);
它还可以获取根目录下的资源文件(注意是webapp根目录下的,不是resource中的资源)
ServletContext中的接口
Enumeration<String> enumeration = getServletContext().getAttributeNames();//包含了ServletContext中的所有域属性名
Object object=getServletContext().getAttribute("name");//返回与之匹配的域属性值
getServletContext().removeAttribute("name");//删除该属性名对应的域属性
getServletContext().setAttribute("la","巴拉巴拉");//设置ServletContext的域属性,前者为属性名,后者为域属性值
上面的为全局的属性,也可以通过请求转发来实现一写信息的转发(下面还有解释)
req.setAttribute("name", "value");//设置域属性
String name=req.getAttribute("name");//获取域属性值
也可以获取web应用下的资源文件
其他方法遇到了再查,再记录
HttpServletRequest
-
HttpServletRequest
对象代表客户端的请求 -
当客户端/浏览器通过 HTTP 协议访问服务器时,HTTP 请求头中的所有信息都封装在这个对象中
HttpServletRequest
常用方法:
-
getRequestURI()
获取请求的资源路径 -
getRequestURL()
获取请求的统一资源定位符(绝对路径 -
getRemoteHost()
获取客户端的 主机, getRemoteAddr() -
getHeader()
获取请求头 -
getParameter()
获取请求的参数 -
getParameterValues()
获取请求的参数(多个值的时候使用), 比如 checkbox, 返回的数组 -
getMethod()
获取请求的方式 GET 或 POST -
setAttribute(key, value)
设置域数据 -
getAttribute(key)
获取域数据 -
getRequestDispatcher()
获取请求转发对象, 请求转发的核心对象
因为浏览器地址栏会停止在第一个 servlet ,如果你刷新页面,会再次发出请求(并且会 带数据), 所以在支付页面情况下,不要使用请求转发,否则会造成重复支付
HttpServletResponse
他是通过流来给客户端传递数据的
字节流 getOutputStream() 常用于下载(传递二进制数据)
字符流 getWriter() 常用于回传字符串(非常常用)
// 两个流同时只能使用一个,也就是用了字节流就不能用字符流了,用了字符流就不能用字节流了
对于getWriter
:
他获取的对象为PrintWriter
类型的数据
resp.getWriter().write("hello servlet");
//或者
PrintWriter writer=resp.getWriter();
writer.write("hello ");
在向客户端写入东西时,要设置编码规则!!!
resp.setContentType("text/html;charset=UTF-8");
还有一种方法:setHeader()
,应该没上面的好用,就不写了
状态码解释
状态码 | 状态码描述 | 说明 |
---|---|---|
200 | OK | 请求已成功,请求所希望的响应头或数据体将随此响应返回。出现此状态码是表示正常状态。 |
302 | Move temporarily | 重定向,请求的资源临时从不同的 地址响应请求。 |
304 | Not Modified | 从浏览器缓存中读取数据,不从服务器重新获取数据。例如,用户第一次从浏览器访问服务器端图片资源,以后在访问该图片资源的时候就不会再从服务器上加载而直接到浏览器缓存中加载,这样效率更高。 |
404 | Not Found | 请求资源不存在。通常是用户路径编写错误,也可能是服务器资源已删除。 |
403 | Forbidden | 服务器已经理解请求,但是拒绝执行它 |
405 | Method Not Allowed | 请求行中指定的请求方法不能被用于请求相应的资源 |
500 | Internal Server Error | 服务器内部错误。通常程序抛异常 |
Cookie
什么是Cookie?它可以在浏览器中保存一些信息,并且在下次请求时,请求头中会携带这些信息。
我们可以编写一个测试用例来看看:
Cookie cookie = new Cookie("test", "yyds");
resp.addCookie(cookie);
resp.sendRedirect("time");
for (Cookie cookie : req.getCookies()) {System.out.println(cookie.getName() + ": " + cookie.getValue());
}
相关文章:

Servlet-01
文章目录 Servlet创建Servlet探究Servlet的生命周期 HttpServletWebServlet注解详解 重定向与请求转发ServletContextServletContext中的接口 HttpServletRequestHttpServletResponse状态码解释Cookie Servlet Q:它能做什么呢? A:我们可以通…...

C语言:链表
链表 介绍单向链表节点结构创建节点插入节点删除节点遍历链表尾部插入查找节点链表反转示例程序程序1程序2 介绍 链表是一种常见的数据结构,用于存储一系列线性数据。与数组不同,链表中的元素在内存中不必是连续存放的,而是通过指针将每个元…...

【git使用二】gitee远程仓库创建与本地git命令用法
目录 gitee介绍 管理者注册gitee账号 管理者在gitee网站上创建远程仓库 每个开发者安装git与基本配置 1.git的下载和安装 2.配置SSH公钥 3.开发者信息配置 git命令用法 gitee介绍 Gitee(又称码云)是一个基于Git的代码托管服务,由开源…...

明星百科大全PHP网站源码
源码介绍 明星百科大全网站源码,国内外明星娱乐音乐、新闻八卦、写真照片、相关影视作品等等的明星百科网站源码。 源码截图 源码下载 明星百科大全PHP网站源码...

白酒:茅台镇白酒的品鉴会与文化交流活动
茅台镇,这个位于中国贵州省的小镇,因其与众不同的自然环境和杰出的酿酒工艺而成为世界著名的白酒产区。云仓酒庄豪迈白酒作为茅台镇的品牌,积极参与各种品鉴会和文化交流活动,向世界展示了中国白酒的魅力和文化底蕴。 近年来&…...

python中列表结构在点云数据处理中用法
1、前言 Python中的列表(list)是一种可变的序列类型,用于存储集合数据。列表用途非常广泛,包括但不限于以下几个方面: 存储集合数据:列表用于存储一系列有序的元素,这些元素可以是任何数据类型&…...

土耳其(小亚细亚)历史上的各个阶段
一个国家的历史书写方式有两种,其一是按本国主体民族的渊源,其二是本国国土内发生的都属于本国史。一般来说,这两种方式相当程度上是重合的,但也有例外,比如本文要讲述的土耳其。 土耳其的国土并不辽阔,其…...

Windows下基于Frida查看内存基址和修改寄存器
使用Frida能够方便地获取到DLL基址,还能修改寄存器值。首先要通过任务管理器获得进程的PID,然后写Python脚本把Frida附加到这个PID进程,根据IDA分析出来的函数地址,HOOK到目标函数,修改寄存器的值,最终实现…...

2024中国网络安全产品用户调查报告(发布版)
自2020年始,人类进入了21世纪的第二个十年,全球进入了百年未有之大变局,新十年的开始即被新冠疫情逆转了全球化发展的历程,而至2022年3月俄乌战争又突然爆发,紧接着2023年7月“巴以冲突"皱起,世界快速…...
手写图片懒加载
参考来自前辈 Aidan路修远i 的文章面试官:请你手写一下!懒加载 - 掘金 (juejin.cn) Hello.vue <template><div><!-- src里面为空,data-original里面写图片真正的url(此处省略) --><img src"" data-origina…...

大型语言模型(LLMs)的后门攻击和防御技术
大型语言模型(LLMs)通过训练在大量文本语料库上,展示了在多种自然语言处理(NLP)应用中取得最先进性能的能力。与基础语言模型相比,LLMs在少样本学习和零样本学习场景中取得了显著的性能提升,这得…...
力扣2594.修车的最少时间
力扣2594.修车的最少时间 二分答案 class Solution {public:long long repairCars(vector<int>& ranks, int cars) {ranges::sort(ranks);auto check [&](long long x) -> bool{long long res 0;for(auto v : ranks){long long k sqrt(x/v);res k;if(r…...

攻防演练之-成功的钓鱼邮件溯源
书接上文,《网络安全攻防演练风云》专栏之攻防演练之-网络安全产品大巡礼二,这里。 演练第一天并没有太大的波澜,白天的时间过得很快。夜色降临,攻防演练中心内的灯光依旧明亮。对于网络安全团队来说,夜晚和白天并没有…...

Gi标签管理
文章目录 前言理解标签创建标签操作标签总结 前言 理解标签 标签,可以理解为对某次commit的一次标识,相当于起起了一个别名。 例如,在项目发布某个版本时候,针对最后一次commit起一个v1.0这样的标签来标识里程碑的意义。 这有什…...
2024福建等保测评公司有哪些?分别叫做什么名字?
2024福建等保测评公司有哪些?分别叫做什么名字? 【回答】:2024年具有资质的福建等保测评公司有6家,其名称以及地址如下: 1、福建省网络与信息安全测评中心,福州市鼓楼区东街8号利达大厦A座8层;…...

王先宏老师厉害了,活页笔记版古琴曲谱拆箱图
王先宏老师走心了,活页笔记版古琴曲谱拆箱图,简直是史上最好的古琴学习利器!送的防滑垫还带铝合金夹层的,养弦膏都是市面上没有的的。 这些古琴谱上的笔记就是老师课堂上用的,直接拿来就可以跟着弹,不用您…...

TalkingData 是一家专注于提供数据统计和分析解决方案的独立第三方数据智能服务平台
TalkingData 是一家专注于提供数据统计和分析解决方案的独立第三方数据智能服务平台。通过搜索结果,我们可以了解到 TalkingData 的一些关键特性和市场情况,并将其与同类型产品进行比较。 TalkingData 产品特性 数据统计与分析:提供专业的数…...

Springboot的小型超市商品展销系统-计算机毕业设计源码01635
摘 要 科技进步的飞速发展引起人们日常生活的巨大变化,电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流,人类发展的历史正进入一个新时代。在现实运用中,应用软件的工作…...

UV胶开裂主要因素有哪些?如何避免?
UV胶开裂主要因素有哪些?如何避免? UV胶开裂的原因可能包括多个方面: 固化不足:UV胶的固化需要足够的紫外线照射。如果照射时间不够,或者紫外线光源的强度不足,胶水可能没有完全固化,从而导致开…...

LogicFlow 学习笔记——3. LogicFlow 基础 节点 Node
节点 Node LogicFlow 内置了一些基础节点,开发者在实际应用场景中,可以基于这些基础节点,定义符合自己业务逻辑的节点。 认识基础节点 LogicFlow是基于svg做的流程图编辑框架,所以我们的节点和连线都是svg基本形状,…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...