【JavaEE】【Servlet API详解】重点!!!

努力经营当下,直至未来明朗!


坚持一定很酷!

【Servlet API概述】

  1. API其实就是一组类/方法
  2. Servlet提供的类和方法很多,但是最主要就使用三个:
    ① HttpServlet: (继承)1

② HttpServletRequest:(方法参数)
③ HttpServletResponse:(方法参数)
2
(HttpServletRequest、HttpServletResponse中的方法都是和http报文格式有关的)


【HttpServlet】

  1. 核心方法
    3
    1)init:创建出HttpServlet实例会调用一次,其作用其实就是用来初始化。一般就是首次访问的时候会被实例化。
    2)destroy:不一定能够调用到。因为HttpServlet不再调用其实就是在tomcat关闭时,关闭tomcat有两种方法:
    ① 直接杀进程:如点击idea中的红色方框、cmd直接点击x、通过任务管理器结束进程等,此时destroy无法被调用。
    8005端口是用来控制tomcat的,通过该端口给tomcat发送一个关闭操作,此时tomcat就可以正常关闭,也就能够调用destroy了。

(工作中最常用的其实就是直接杀进程方式关闭,所以不太会调用到destroy方法)

3) service:tomcat收到请求之后实际上是先调用service方法,在service中根据方法来调用不同的doXXX方法。(实际开发中其实很少会重写service,重写doXXX方法就够了)

  1. 面试题】谈谈Servlet的生命周期?
    生命周期:其实就是正确的时间干正确的事儿。
    也就是回答:Servlet中有三个主要的方法:init、destroy、service,以及何时被调用:init在servlet被实例化的时候调用一次,destroy是在servlet销毁之前调用一次,service是每次收到请求调用(两次)。
    (调用两次service原因:两次service

【HttpServletRequest】

  1. 核心方法:
    30

  2. 写一个测试代码:
    10
    11
    (枚举类型是不可以通过下标访问和修改的)

  3. 如果不写content type,此时浏览器就不知道body是啥格式,就会去猜;但是一般不要让浏览器去猜,而是直接setContentType

body格式如:
tect/plain(纯文本)、text/html、 text/css、 application/js、 application/json、 image/png 等

  1. 还有一个重要场景就是:使用api获取到请求中的重要参数(query string中的值 以及 body中的值)
    对于query string来说,核心方法就是 getqueryString

1)实例:
31

(在服务器中打印)
32

(在浏览器中打印)
33

此时:浏览器没有正确识别出中文,当前不是没有urlencode的缘故(因为服务器这里的打印结果是正确的);但是返回的响应页面浏览器没能正确识别,为了让浏览器能够识别,需要显式在响应上加上content type。
35

注意:即使在地址栏输入的是encode的内容,但是servlet getParameter会自动的针对urlencode的结果进行decode,不需要我们手动处理

  • getParameter获取键值对的时候,如果是键key不存在,得到的就是null;如果是键存在、值不存在,得到的就是” ”;如果key、value都不存在,得到的也是null。

2)POST实例:
如果请求是post,如何获取到body中的参数?

A. 请求的body是x-www-form-urlencode 的 form表单形式:
这里也是使用getParameter来获取的。
但是post请求不是直接在地址栏输入就可以的,需要构造请求:
① 这里可以使用第三方工具postman来构造请求:构造完成后直接点send就可以看到结果
(postman也是http客户端,其地位和浏览器是对等的)
36

② 还可以搞个html页面,通过form表单发送请求。
(注:html创建是在webapp下,不是WEB-INF下!! new file)
(如果在idea中不好写代码,就切到vscode中写代码)

37
(一定要注意这里的路径:不是webapp,而是servl,之前在idea tomcat上设定的context path!!)

在提交之后可以在fiddler中看到body信息,也就是post请求构造成功。

(body中被form表单自动urlencode了)
38
(post请求路径)
39

(form表单类型)
40

虽然已经显式地告诉了浏览器响应的编码方式,但是响应页面依旧是乱码:
41

查看发现服务器中也是乱码:
42

说明:服务器在针对请求进行解析的时候就已经乱码了。所以:需要显式地告诉servlet应该按照哪种编码来理解请求的body。
所以:给请求也设置编码方式:
43

  • 【请求处设置的utf8是告诉servlet(tomcat)如何解析;响应处设置的utf8是告诉浏览器如何解析】

响应这里设置字符集有两种写法:setContentType 以及 setCharacterEncoding,但是还是建议使用setContentType完整写法;
设置的字符集只是其中一部分,还需要设置格式。

【补充】

“爬虫”:其实就是一个HTTP客户端,是自己写的。能在浏览器中做的一切操作,理论上都是可以用爬虫来实现的。
(90%的爬虫都是违法的。服务器承受的请求压力是有限的,爬虫其实属于无效访问,还白白增大了服务器的压力,容易把别人的服务器搞挂了;另外,可能会涉及别人的隐私信息。(很多网站都是有反爬策略))

【注意】
43
顺序不能颠倒。务必要保证先设置所有的header,最后再设置body(servlet的坑)。
即:先格式 后写入!!

B. 请求的body是json:(使用 {键值对,} 构成的)

① 需要先读取body中的内容,使用getInputStream来读取流对象,然后再进一步来读取流对象。

② 如何解析json格式?
Servlet没有内置json解析,所以我们就使用第三方库。市面上很多第三方库如fastjson、jackson、gson等,但是我们主要使用的是jackson,因为jackson是Spring御用的json库。

③ 使用中央仓库maven(中央仓库)下载安装jackson:选择databind -> 随便选择一个版本(此时我选2.13.4.1)-> 复制如下图maven中内容 -> 拷贝到pom.xml中(依旧是dependecies中)-> 如果标红,就进行刷新操作
45
46

④ 其实使用jackson非常方便,掌握一个类两个方法就行:

ObjectMapper类:
① readValue方法:把JSON格式的数据转为java的对象
②writeValueAsString方法:把java对象转成jjson格式的字符串

【readValue方法:第一个参数可以是字符串,也可以是输入流; 第二个参数是获取类对象(类似于反射),也就是要解析出来的结果的对象的类】
47

【重点理解】

① 读取输入流,获取到要解析的字符串
② 把字符串按照json格式进行解析,得到一组键值对(Map)
③ 根据类对象创建一个实例
④ 遍历类对象中属性的名字,拿着名字去与上述Map中查询匹配,将匹配到的value赋值到对应对象的属性中去
⑤ 返回这个构造完成的对象。
(要求:json键值对中 键 的名字/类型要和类的 属性 一一对应

【注】

① 要实现java对象就要有java类,而类中的属性务必是public或者是带有public的getter/setter ,否则json无法访问该对象的属性。
② 另外,该类必须有无参版本的构造方法,如果不写任何构造方法,编译器能够自动生成无参的构造方法。(但是一旦写了有参的构造方法,就一定要自己手动写无参的构造方法)

在postman中构造post请求时,json格式设置方法如下:

49
50
在postman中写json格式的时候,务必要保证这里的key是带引号的!正常的json中key都是要带引号的! (但是js里的对象是不带的

具体参考代码JsonServlet


【HttpServletResponse】

  1. 核心方法:
    50

注:HttpServletRequest方法一般是get系列,而HttpServletResponse方法一般是set系列:因为doGet/doPost等这样的方法中的HttpServletResponse对象就是空对象,需要往里面写入数据

  1. 举个例子:
    1) 设置不同的状态码:
    (代码:StatusServlet
    这些状态码具体怎么处理(前端页面显示啥)都是由程序员自定义的。

2) 设置响应的header:
通过这个实现页面的自动刷新:header设置refresh属性,值是一个秒数。
在进行刷新时,刷新时间总是会比设定的时间稍多一些,理由:

① 进程调度消耗时间
② 网络传输消耗时间
③ 服务器响应消耗时间

(代码:AutoRefreshServlet

3)构造重定向响应(3开头系列):
(代码:RedirectServlet 没有referer的)


写例子:表白墙

  1. 之前写的表白墙,其内容只是在内存中存在(List保存),一旦刷新之后内容就丢失。
  2. 此时需要让用户留言的数据能够在服务器这儿保存,保证页面即使关闭之后数据也不会丢失!此时就可以保证页面加载数据时是从服务器这儿加载数据的,之前留言的内容不会丢失。

1)准备工作:创建maven项目MessageWall,引入依赖,创建目录结构

2)设计前后端如何交互:前端啥时候给后端发请求,发的请求是啥样的,返回的响应是啥样的。

① 在表白墙中,希望点击提交之后数据能够在服务器中保存(存档);
② 当关闭页面再重新启动/刷新之后,需要从服务器获取到之前保存过的数据并在页面上进行显示(读档)

【客户端和服务器的交互是根据业务需求的】

3)理清请求和响应的细节。
① 发送数据给服务器:
51

接口约定的方式是无穷的,必须要确定一个唯一方案,这样前后端才可以配合开发。

②从服务器获取到已经保存的数据:
52

4)开发后端和前端代码

① 前端代码是在webapp目录底下! 然后使用vscode打开并操作
② 注意:将资源都放到webapp下,包括写Servlet,其实编译之后的.class文件也是在webapp底下的;webapp就描述了当前网站的Context Path。

53

55
(发送请求:前端代码,前面还加了一个script 引入jquery)

③ 页面进行加载的时候就需要进行“读档”操作:直接写在script标签中的代码都是在页面加载的时候执行的

④ 注:smart tomcat 会把一部分内存中的数据保存下来,后续重启服务器的时候数据就会恢复回来。

【注意:请求、响应过程!】

web程序一旦出现问题,起手式就是“抓包”,通过抓包确定是前端问题还是后端问题。


5)需要让数据在数据库中持久化保存:jdbc编程
① 在中央仓库搜索mysql:
58

② 选择5.1.49版本,复制代码并粘贴到pom.xml的dependencies中

③ 设计数据库表结构:几张,表里有哪些

本表白墙中只需要一张表message,列:from、to、message(id可以没有)

在cmd中操作:首先 目录要cd到mysql.exe所在的目录,然后输入mysql -u root -p进入数据库(也可以直接使用mysql client)

59此时建表成功(注意关键字要加上``)

④ 此时重新修改后端代码,直接保存在数据库中。
记忆数据库操作代码


6)DataSource存在多份,这不太合理,所以使用单例模式对DataSource进行封装。
① 单例模式:只创建一个实例!
② 一般由两种模式:懒汉模式和饿汉模式,一般更倾向于使用懒汉模式。
懒汉模式涉及到一个线程安全问题。

③ 所以考虑:Servlet代码中是否涉及到多线程/线程安全问题?

① Servlet写的是一个服务器,同一时刻可能要处理多个客户端的请求。
② 一旦同时有多个客户端都发来请求,服务器就势必要同时处理多个请求。Tomcat内部正是使用了多线程的方式来处理的。
③ 则:Servlet代码中涉及到多线程/线程安全问题。


表白墙参考代码

参考代码表白墙


小结

  1. HttpServlet
    ① doXXX:处理哪种http请求会调用的对应的方法
    ② init/destroy/service:Servlet的生命周期

  2. HttpServletRequest:HTTP请求,get系列方法
    可以获取到以下信息:
    协议名(版本号)、URL、query string、header、query string/body的键值对等

  3. HttpServletResponse:HTTP响应,set系列方法
    可以设置以下信息:
    状态码、各种header、body等

  4. 表白墙代码:主要注意 mysql +单例模式(线程安全)

yyy

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

'Dream是普通小孩耶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值