文章目录
Servlet 生命周期
启动tomcat服务器,服务器会扫描webapps下所有项目的web.xml文件,将web.xml中servlet的url-partten与全类名组成键值对存储与map1集合中;
Map<String, String>
key value
---------------------------------------------------------
/login cn.qkmango.javaweb.servlet.LoginServlet
/delete cn.qkmango.javaweb.servlet.DeleteServlet
/insert cn.qkmango.javaweb.servlet.InsertServlet
当第一次访问某个servlet时,会通过map1得到该servlet的全类名,通过反射调用该servlet的无参构造方法,创建一个servlet对象(单例),然后将该servlet的url-partten与实例形成键值对存入另外一个map集合;
Map<String, Servlet>
key value
--------------------------------------
/login LoginServlet对象的引用
/delete DeleteServlet对象的引用
/insert InsertServlet对象的引用
描述Servlet对象生命周期
1)浏览器访问URL:http://localhost:8080/web_war_exploded/hello
2)web容器截取请求路径:/web_war_exploded/hello
3)web容器在容器上下文中找请求路径/web_war_exploded/hello
对应的Servlet对象
4.1)若没有找到对应的Servlet对象
- 会通过
web.xml
文件中的相关信息(实际上通过map),得到请求路径/web_war_exploded/hello
对应的Servlet完整类名 - 通过反射机制,调用Servlet类的无参构造方法完成Servlet对象的实例化
- web容器调用Servlet对象的
init()
方法完成初始化 - web容器调用Servlet对象的
service()
方法提供服务
4.2)若找到对应的Servlet对象
- web容器直接调用Servlet对象的
service()
方法提供服务
5)Servlet对象销毁
- web容器关闭的时候、webApp重新部署的时候、该Servlet对象长时间没有用户访问的时候,web容器会将Servlet对象销毁,在销毁Servlet对象前,会调用对象的
destroy()
方法进行销毁前的准备
ServletConfig接口
ServletConfig是一个Servlet对象的配置信息对象,ServletConfig对象中封装了一个Servlet对象的配置信息。Servlet对象的配置信息在web.xml文件中,一个Servlet对象对应一个ServletConfig对象对象,100个Servlet对象对应100个ServletConfig对象。
ServletConfig接口中的方法
-
String
getInitParameter(String name)
通过name,获取初始化参数name对应的value//获取name为driver所对应的value String driver = servletConfig.getInitParameter("driver");
-
Enumeration
getInitParameterNames()
获取初始化参数的name集合。//获取name集合 Enumeration<String> initParameterNames = servletConfig.getInitParameterNames(); //通过name集合循环遍历拿出name,通过name获取value while (initParameterNames.hasMoreElements()) { String name = initParameterNames.nextElement(); String value = servletConfig.getInitParameter(name); writer.print(name + " = " + value + "<br>"); }
-
String
getServletName()
获取servletName,<servlet-name>servletName</servlet-name>
String servletName = servletConfig.getServletName();
-
ServletContext
getServletContext()
获取ServletContext【Servlet上下文】对象ServletContext servletContext = servletConfig.getServletContext();
ServletContext接口
ServletContext到底是什么?什么时候被创建?什么时候被销毁?创建几个?
- ServletContext被译为:Servlet上下文
- 一个webapp只有一个web.xml文件,web.xml文件服务器启动阶段被解析
- 一个webapp只有一个ServletContext对象,ServletContext对象在服务器启动阶段被实例化
- ServletContext在服务器关闭的时候被销毁
- ServletContext对应的是web.xml文件,是web.xml文件的代表
- ServletContext是所有Servlet对象四周环境的代表,被所有Servlet共享【在同一个webapp中,所有Servlet对象共享一个四周环境对象,该对象就是ServletContext
-
- 所有用户若想共享同一个数据,可以将数据放到ServletContext对象中(写到web.xml文件中,或后期通过方法添加)
- 一般放到ServletContext对象中的数据不建议涉及到修改操作的,以为ServletContext是多线程共享的一个对象,修改的时候会存在线程安全问题
ServletContext接口中有哪些常用方法
- void `setAttribute(String name, Object object)` 向ServletContext中添加数据
- Object `getAttribute(String name)` 从ServletContext中获取数据
- void `removeAttribute(String name)` 从ServletContext中移除数据
- String `getInitParameter(String name)` 从ServletContext中获取name所对应的value初始化参数(\<context-param>标签中)
- Enumeration `getInitParameterNames()`从ServletContext中获取name所对应的value初始化参数(\<context-param>标签中)
- String `getRealPath(String path)` 获取文件绝对路径
ServletConfig与ServletContext中的getInitParameter()
、getInitParameterNames()
不同
-
ServletConfig是每个Servlet对象的配置信息对象,ServletConfig中的
getInitParameter()
与getInitParameterNames()
获取到的初始化参数是在<init-param>
标签中的,<init-param>
标签定义在<servlet>
标签里面 -
ServletContext是所有Servlet对象的共用的四周环境,ServletContext中的
getInitParameter()
与getInitParameterNames()
获取到的参数是在<context-param>
标签中的,<context-param>
标签定义在<web-app>
标签里面
ServletContext中的getInitParameter(String name)
与getAttribute(String name)
不同
getInitParameter(String name)
获取到的参数是写在web.xml文件<context-param>
标签中的,获取到的都是字符串参数getAttribute(String name)
获取到的数据是运行时添加到ServletContext中的数据,数据可以是任何类型,不同用户都可以通过name获取到数据
欢迎页面
-
欢迎页面是怎么设置的?
假设在web/html目录下创建welcome.html,想让welcome.html作为整个webapp的欢迎页面,应该在web.xml文件中添加如下标签<!--将welcome.html页面作为欢迎页面--> <!--注意开头没有“/”--> <welcome-file-list> <welcome-file>html/welcome.html</welcome-file> </welcome-file-list>
-
为什么设置欢迎页面?
- 为了访问更方便,为例提高用户的体验
- 设置欢迎页面之后,直接在浏览器地址栏上访问该webapp即可,自动定位到欢迎页面,例如
http://localhost:8080/webapp07/
-
欢迎页面可以设置多个
设置多个欢迎页面,越靠上越优先,当前面的欢迎页面找不到时才使用后面的欢迎页面<welcome-file-list> <welcome-file>html/welcome.html</welcome-file> <welcome-file>html/welcome2.html</welcome-file> </welcome-file-list>
-
欢迎页面可以是任何一种web资源
欢迎页面不仅可以是html文件,也可以时任何一种web资源,如Servlet
使用Servlet作为欢迎页面- 在web.xml文件中配置好Servlet
- <welcome-file>标签内填写<servlet>标签中的<url-pattern>标签中的内容,要注意,此时要去掉开头的“/”
<!--配置Servlet--> <servlet> <servlet-name>welcome</servlet-name> <servlet-class>cn.qkmango.Welcome</servlet-class> </servlet> <servlet-mapping> <servlet-name>welcome</servlet-name> <url-pattern>/system/welcome</url-pattern> </servlet-mapping> <!--Servlet作为欢迎页面--> <welcome-file-list> <!--注意此处,去掉开头的“/”--> <welcome-file>system/welcome</welcome-file> </welcome-file-list>
常见的错误代码 自定义错误页面(webapp08)
- 404 Not Found 资源未找到
- 500 Server Inner Error 服务器内部错误,一般都是服务器Java程序出现异常
404和500是HTTP协议状态码,是W3C制定的
正常响应的HTTP协议状态码是200
可以在web.xml中添加错误页面,当发生该错误时,自动跳转到指定页面
<error-page>
<error-code>404</error-code>
<!--此处的路径前省略了项目的根目录web目录,即相对于当前项目的根目录-->
<location>/errorPage/404.html</location>
</error-page>
Servlet路径的总结
客户端浏览器要处理的URL路径时,此时/
前代表的是主机名,如http://localhost:8080
,所以我们要以/webappName
开头。
例如页面有一个链接
<a href="/oa/login">登陆</a>
当你在浏览器点击这个超链接时,浏览器就会请求http://localhost:8080/oa/login
,所以,在需要浏览器请求的URL时,/
前省略了主机名。
后台服务器处理请求URL路径时,以/
开头,例如在web.xml文件中配置的servlet,此处的<url-pattern>/login</url-pattern>
就是以/
开头,/
前省略了hostName和webappName
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>cn.qkmango.login</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
注意:
在欢迎页面中的路径,是不以’’/’'开头的。
在重定向中的路径,要"以/项目别名"开头,跟在浏览器客户端相似。
自定义servle的三种方式
- 实现Servle接口
- 继承GenericServlet类
- 继承HttpServlet类
get与post方式发送请求
GET请求:如下是一个GET请求的登陆页面的请求,由于请求方式为GET,所以发送数据在请求行上发送!故请求体为空
GET /webapp10/login?username=admin&password=123 HTTP/1.1 请求行
Accept: text/html, application/xhtml+xml, image/jxr, */* 消息报头
X-HttpWatch-RID: 50301-10022
Referer: http://localhost:8080/webapp10/
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko
Accept-Encoding: gzip, deflate
Host: localhost:8080
Connection: Keep-Alive
空白行
请求体
POST请求:如下是一个POST请求的登陆页面的请求,请求体展示了请求的内容username=admin&password=***
POST /webapp10/login HTTP/1.1 请求行
Accept: text/html, application/xhtml+xml, image/jxr, */* 消息报头
X-HttpWatch-RID: 50301-10054
Referer: http://localhost:8080/webapp10/
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Host: localhost:8080
Content-Length: 27
Connection: Keep-Alive
Cache-Control: no-cache
空白行
username=admin&password=123 请求体
响应协议
响应协议包括四部分
- 状态行
- 响应报头
- 空白行
- 响应体
状态行:协议版本号 状态码
空白行:是用来分离响应报头和响应体的
响应协议中重点掌握状态码:
-
200 响应成功正常结束
-
404 资源未找到
-
500 服务器内部错误
…
如下是服务器的响应
HTTP/1.1 200 OK 状态行
Server: Apache-Coyote/1.1 响应报头
Content-Type: text/html;charset=UTF-8
Content-Length: 21
Date: Thu, 13 Aug 2020 10:15:13 GMT
空白行
<h1>登陆成功</h1> 响应体
GET请求与POST请求区别
-
什么情况下浏览器发送的请求是GET请求,什么情况下浏览器发送的请求是POST请求?
只有当使用表单form,并且讲form的标签的method属性设置为method=“post”,才是POST请求方式,其余剩下的所有请求都是基于GET请求
-
GET请求和POST请求有什么区别?
- GET请求在请求行上提交数据,格式
uri?name=value&name=value
,这种提交方式最终提交的数据会显示在浏览器地址栏上 - POST请求在请求体中提交数据,相对安全,提交格式
name=value&name=value
,这种提交方式最终不会显示在浏览器地址栏上 - POST请求在请求体中提交数据,所以POST请求提交的数据没有长度限制【POST可以提价大数据】
- GET请求在请求行上提交数据,所以GET请求提交的数据长度有限制 - GET请求只能提交字符串数据,POST请求可以提交任何类型的数据,包括视频…,所以文件上传必须使用POST请求
- GET请求最终的结果,会被浏览器缓存收纳,而POST不会被缓存收纳(为什么GET会被缓存?)
- GET请求在请求行上提交数据,格式
-
GET请求和POST请求应该如何选择?
- 有敏感数据 POST
- 传送的数据不是普通字符串 POST
- 传送的数据非常多 POST
- 这个请求是为了修改服务器端资源 POST
- GET请求多数情况下是从服务器中读取资源,这个读取的资源在短时间内不会发送变化,所以GET请求最终的结果会被浏览器缓存起来
- POST请求是为了修改服务器端的资源,而每一次修改结果都是不同的,最终结果没有必要被浏览器缓存
缓存解决方案
浏览器将资源缓存后,缓存的资源是和某个特定的路径绑定在一起的,只要浏览器再发送这个相同的请求路径,这个时候浏览器就会去缓存中获取资源,不再访问服务器,以这种方式降低服务器的压力,提高用户体验。
但是有的时候我们并不希望走缓存,希望每一次后哦访问服务器,可以在请求路径后面添加时间戳,例如:http://ip:port/oa/system/logout?timetamp=1234564635423