目录
概述:
- HttpServletResponse接口:负责将运行结果写入响应包
- HttpServletRequest接口:负责读取请求协议包信息
- ServletContext接口:可以为当前网站中所有的Servlet提供【共享数据】
- Cookie:在一次会话过程中,存储浏览器在服务端产生的私人数据
- HttpSession接口:在一次会话过程中,存储浏览器在服务端产生的私人数据
HttpServletResponse接口:
介绍:
- 一个来自于Servlet规范中的接口,由Tomcat负责提供这个接口实现类
- 负责在Servlet运行完毕后,将相关的数据写入到【响应头】和【响应体】
- 开发人员习惯于将HttpServletResponse接口修饰对象,称为【响应对象】
response.setCharacterEncoding()与response.setContentType()
- 相同点:都可以设置响应头中【字符集】
- 不同点:response.setContentType()还可以设置【内容类型】
响应头和响应体中的信息
- 为字符串
Protected void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
String str ="Hello"; //OneServlet运行后结果
//通过【响应对象】将【英文字符串】写入到【响应体】
//从【响应对象】获得一个【输出流】
PrintWriter out = response.getWriter();
//【输出流】将【英文字符串】写入到【响应体】
out.writer(str);
} //Tomcat在OneServlet调用完毕后,将响应包推送到浏览器上
- 为数字
/*
*out.write();只能将“字符串”或者【unicode码】写入到相应体
*out.write(50);一个值为50的unicode写入到响应体,值为50的unicode码对应的字符串"2"
*out.print();可以将任意类型数据写入到【响应体】并保持原有的特征
*
*如果将字符串写入到响应体,可以使用out.write,也可以使用out.print
*如果将非字符串类型数据写入到响应体,只可以使用out.print
*/
Protected void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
int num= 50; //OneServlet运行后结果
//通过【响应对象】将【英文字符串】写入到【响应体】
PrintWriter out = response.getWriter();
out.print(num);
} //Tomcat在OneServlet调用完毕后,将响应包推送到浏览器
- 为汉字
/*
1.浏览器根据【响应头】中设置的【字符集】对接收内容进行解码的
2.在默认情况下【响应头】中字符集为【ISO-8859-1】
3.所以导致浏览器使用【ISO-8859-1】字符集解析中文内容时出错了
4.如果需要将【中文内容】交给浏览器,必须提前设置【响应头】中字符集
*/
Protected void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
String str="你好";
//首先,一定要在获得输出流之前,设置响应头中字符集
response.setCharacterEncoding("GBK");
response.getWriter().write(str);
} //Tomcat在OneServlet调用完毕后,将响应包推送到浏览器
- 为html
/*
1.浏览器根据【响应头】的【内容类型】处理接收结果
2.默认情况下【响应头】的【内容类型】是"text",告诉浏览器响应体存放都是【文字内容】,导致浏览器将所有文字内容输出到页面上
3.如果返回内容包含了html标签,需要通知浏览器
4.应该重新设置响应头内容类型
response.setContentType("text/html")
*/
Protected void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
String str="中国<br/>美国<br/>法国";
//设置响应头内容类型
response.setContentType("text/html;charset=GBK");
//获得输出流
PrintWriter out = response.getWriter();
//将内容写入到响应体
out.write(str);
} //Tomcat在OneServlet调用完毕后,将响应包推送到浏览器
HttpServletRequest接口:
介绍:
- 来自于Servlet规范中一个接口,接口实现类由Tomcat负责提供的
- 由HttpServletRequest接口修饰对象,可以帮助开发人员读取【请求协议包】信息,相当于【Scanner】
- 一般习惯于将HttpServletRequest接口修饰对象称为【请求对象】
作用:
- 读取【请求行】信息
//读取【请求行】中【请求的资源文件地址】
String url= request.getRequstURL();
//读取【请求行】中【请求方式】
String method = request.getMethod();
- 读取【请求头】或者【请求体】中所有的【请求参数名】
//读取当前请求协议包所有的请求参数名称
request.getParameternames();
/*
http:localhost:555/myWeb/two.do?uname=mile&age=23
*/
Protected void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
Enumeration paramNames= request.getParameterNames();
while(paramNames.hasMoreElements())
{
String paramName = (String)paramNames.nextElement();
System.out.println("浏览器发送请求时,携带的请求参数"+paramName);
}
}
结果:
浏览器发送请求时,携带的请求参数uname
浏览器发送请求时,携带的请求参数age
- 读取请求头或者请求体中【参数内容】
//读取【单个请求参数内容】
String value =request.getParameter("请求参数名");
//读取【一个参数关联多个内容】,例如:复选框作为参数时
String array[] =request.getParamentervalues("请求参数名");
Protected void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
String userAge =request.getParameter("age");
System.out.println("浏览器发送的age参数值"+userAge);
//读取【一个参数关联多个内容】
String array[] = request.getParameterValues("home");
for(String home:array)
{
System.out.println("浏览器发送的home参数"+home);
}
}
请求对象与响应对象生命周期:
- 都是由Tomcat负责创建的
- 每当Tomcat收到一个【请求协议包】时,就会为这个请求协议包创建一对【请求对象和响应对象】
- 一次请求对应一对【请求对象和响应对象】
- 在Tomcat调用被请求的Servlet中服务方法(doGet/doPost)时,负责将本次【请求对象和响应对象】作为参数传入到服务方法
- 在服务方法工作完毕后,Tomcat销毁本次请求相关的request和response
- Tomcat负责将【响应包】推送到浏览器上
中文请求参数乱码问题:
原因:跟浏览器采用【请求方式】
如果浏览器以【GET方式】发送请求,【请求参数】在【请求头】存放在请求协议包到达服务端之后,【请求头】内容是由Tomcat负责解析Tomcat9.0在解析数据时,默认采用的字符集【utf-8】,所以如果浏览器以【GET】方式发送中文参数,此时在服务端不会出现中文乱码问题
如果浏览器以【POST方式】发送请求,【请求参数】在【请求体】存放在请求协议包到达服务端之后,【请求体】内容是由对应【请求对象request】负责解码的,request对象默认使用【ISO-8859-1】字符集,所以如果浏览器以【POST】方式发送中文参数,此时在服务端必须会出现中文乱码问题
解决方案:
在request对象解析数据之前,重新设置request对象字符集【utf-8】即可
request.setCharacterEncoding("utf-8");
String value =request.getParameter("参数")
ServletContext接口
介绍:
- servlet规范中一个接口,接口实现类由Tomcat负责提供
- 负责为当前工程中所有Servlet提供【共享数据】
- 开发人员习惯于将ServletContext接口修饰对象称为【全局作用域对象】
生命周期:
- 【全局作用域对象】在Tomcat启动时,由Tomcat为当前网站来创建
- 一个网站中只能有一个全局作用域对象
- 从网站启动开始一直到网站关闭时,由Tomcat负责销毁当前网站的全局作用域对象
如何得到当前工程中【全局作用域对象】
ServletContext application = request.getServletContext();
向Tomcat索要当前工程的全局作用域对象
共享数据来源方式一:
在网站启动之前,开发人员可以将网站中绝大多数Servlet需要使用的数据添加到web.xml
<context-param>
<param-name>共享数据名称</param-name>
<param-value>共享数据内容</param-value>
<context-param>
在网站启动时:Tomcat首先为当前网站创建一个【全局作用域对象】,Tomcat然后将web.xml配置共享数据添加到【全局作用域对象】
在网站运行时,当前某一个Servlet需要使用【共享数据】时,可以从全局作用域对象索要数据
//返回是object对象
共享数据内容 = application.getInitParameter("共享数据名称");
共享数据不可以被修改
共享数据来源方式二:
在Tomcat运行期间,可以将某一个Servlet提供的数据保存到全局作用域对象中,供当前网站中其他的Servlet来使用
AServlet: 提供共享数据
application.setAttribute("共享数据名",共享的数据); 返回值是object
BServlet:
共享的数据 =application.getAttribute("共享数据")
由Servlet存入共享数据可以被修改
OneServlet.java
Protected void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
//向Tomcat索要当前网站的ServletContext对象
ServletContext application = request.getServletContext();
//将数据保存到ServletContext对象,作为共享数据
application.setAttribute("key",10000);
}
TwoServlet.java
Protected void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
//向Tomcat索要当前网站中全局作用域对象
ServletContext application =request.getServletContext();
//从全局作用域对象读取OneServlet共享的数据
Integer mo =(Integer)application.getAttribute("key");
System.out.println("TwoServlet从全局作用域对象得到OneServlet提供共享数据"+mo)
}
会话:
定义:一个浏览器与一个服务端的一次完整的交流
特点:
- 在一次会话过程中,经历多次请求与响应
- 在一次会话过程中,同一个浏览器往往访问多个Servlet
需求:在一次会话过程中,在浏览器要访问的Servlet之间进行数据共享
解决方案:Cookie和HttpSession
Cookie:
介绍:
- Cookie是Servlet规范提供一个工具类
- 在参与一个会话过程中Servlet之间,进行【数据共享】
- Cookie存储在浏览器上,保存本次会话的【共享数据】
工作原理:
- 在浏览器访问【OneServlet】时,【OneServlet】负责将当前浏览器产生的私人数据保存到Cookie,然后【OneServlet】负责将Cookie推送到当前浏览器上
- 在浏览器再此来访问当前网站【TwoServlet】时,需要无条件的嫁给你服务端之前推送过来的【Cookie】在推送回去,这样TwoServlet得到【OneServlet】提供的共享数据
Cookie的使用:
1.创建一个Cookie对象,来保存共享数据
/*
一个Cookie对象只能有一个键值对
Cookie对象只能存储String类型共享数据
*/
Cookie c1= new Cookie("key","共享数据");
2.如何将Cookie写入到响应包【响应头】
response.addCookie(c1);
3.如何从请求协议包的【请求头】读取浏览器返还的Cookie
Cookie array[] =request.getCookies();
Cookie对象的生命周期
默认情况:
Cookie是保存在浏览器的内存中,所以在浏览器关闭时,Cookie会被windows进行销毁
人工干预:
要求将Cookie保存到客户端计算机的【硬盘上】,同时指定Cookie在硬盘上存活时间,在存活时间范围之内,关闭浏览器甚至关闭计算机,都不会导致Cookie被销毁
//设置Cookie存活时间
Cookie.setMaxAge(以秒为单位时间);
Cookie缺点:
- 一个Cookie对象只能存放一个键值对,如果存储的数据较多,需要管理多个Cookie
- Cookie只能存放String类型数据,无法存放【高级类型Java数据,比如List,Map】
例子:
OneServlet.java
Protected void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
//读取当前【用户】基本信息
String name =request.getParameter("userName");
String jiaozi = request.getParameter("jiaozi");
//将当前用户私人数据保存到Cookie中
Cookie c1 = new Cookie("key1",name);
Cookie c2 = new Cookie("key2",jiaozi);
//设置c1对象需要在用户硬盘上存活一分钟
c1.setMaxAge(60);
//将Cookie对象写入到【响应包】中的【响应头】
response.addCookie(c1);
response.addCookie(c2);
}
TwoServlet.java
Protected void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
//读取当前来访的浏览器推送回去的Cookie
Cookie array[] =request.getCookies();
//根据得到Cookie,来招待当前用户
for(Cookie cookie:array)
String keyName = cookie.getName(); //读取cookie中关键字名称
String value = cookie.getValue(); //读取cookie中共享数据
if("key1".equals(KeyName)){
Ststem.out.println(value+"客人,请进");
}else if("key2".equals(keyName)){
System.out.println("我们早将"+value+"给您准备好了");
}
}
}
HTML页面
<html>
<head>
<title>Title</title>
</head>
<body>
<center>
<h1>新用户点餐页面</h1>
<form action="/myWeb/one.do">
客人名称:<input type="text" name="userName"><br/>
饺子类型:<input type="radio" name="jiaozi" value="三鲜饺子">三鲜饺子
<input type="radio" name="jiaozi" value="西葫芦饺子">西葫芦饺子
<input type="radio" name="jiaozi" value="虾仁饺子">虾仁饺子<br/>
<input type="radio"value="点餐"/>
</form>
</center>
</body>
</html>
HttpSession接口
介绍:
- 来自于Servlet规范中接口,接口实现类来自于Tomcat
- 为参与同一个会话的Servlet之间提供共享数据
- 习惯于将HttpSession接口修饰的对象称为【会话作用域对象】也可以叫做【Seesion对象】
HttpSession与Cookie区别:
相同点:
为参与同一个会话的Servlet之间提供共享数据
不同点:
【存储位置】:Cookie存储在客户端浏览器内存中或者硬盘上,HttpSession存储在服务端计算机的内存中
【存储内容】:Cookie只能存储String类型数据,HttpSession可以存储任意类型数据
【存储数量】:一个Cookie只可以存储一个键值对,一个HttpSession对象可以任意个数的键值对
使用:
- 在浏览器来访时,Tomcat不会主动为当前浏览器创建对应的HttpSession对象
- 只有浏览器所访问的Servlet向Tomcat提出要求时,Tomcat才会为当前浏览器创建一个HttpSession对象
- 如何在Servlet中为当前浏览器,申请一个HttpSession对象
//三种方式
HttpSession session = request.getSession();
HttpSession session = request.getSession(ture);
HttpSession session = request.getSession(false);
三者区别:
getSession():如果当前浏览器在服务端中已经拥有了一个Session对象,此时Tomcat需要将这个Session对象进行返回,如果当前浏览器在服务端中尚未拥有Session对象,此时Tomcat需要创建一个全新的Session对象放回
getSession(true):与getSession()完全一致
getSession(false):如果当前浏览器在服务端中已经拥有一个Session对象,此时Tomcat需要将这个Session对象进行返回,如果当前浏览器在服务端中尚未拥有Session对象,此时返回一个null
注:如果来访的用户身份已经确认合法了,此时可以使用getSession()或者getSession(true),如果来访的用户身份不确认,此时只可以使用getSession(false)
Tomcat是如何将浏览器与Session对象关联
在Tomcat创建了一个Session对象时,为Session对象生成一个唯一编号,然后将这个编号保存到Cookie中,推送到当前的浏览器内存中,等到浏览器再此发送请求时,Tomcat就可以通过读取浏览器返回的Cookie来判断浏览器在服务端中是否有Session对象
如何使用HttpSession对象
在本次会话过程中,AServlet需要为本次会话中其他Servlet提供共享数据
session.setAttribute("key",共享数据)
在本次会话过程中,Bservlet需要得到当前浏览器session的数据
session.getAttribute("key")
例子:
/*
需求:购物车购买面包,点击一次,要在后台加一,在返回给客户端
*/
Protected void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
//读取浏览器推送过来的【商品名称】
String goodName = request.getParameter("name");
//向Tomcat索要当前浏览器在服务端的Session对象
HttpSession session = request.getSession();
//将用户选择商品保存到当前用户Session
Integer goodSum =(Integer)session.getAttribute(goodsName);
if(goodName==null)
Session.setAttribute(goodsName,1);
}else{
session.setAttribute(goodsName,goodsNum+1);
}
Http状态码
介绍:
- Http状态码是由一个三位数字组成符号
- Http状态码由Tomcat负责创建生成
- Http状态码由Tomcat写入到【状态行】
- Http状态码通知浏览器在接收到响应包之后的行为,Http状态码通知浏览器,服务端无法提供本次服务的原因
分类介绍:5类
【1xx】:通知浏览器本次放回的资源文件并不完整,需要浏览器继续向服务器发送申请
【2xx】:通知浏览器,服务端将一个完整的文件推送给浏览器
200:浏览器与服务端进行了一次完美通信
【3xx】:服务端推送给浏览器的是一个【网址】,要求浏览器在接收到这个网址后,立即自动向这个网址发送请求
response.sendRedirect("地址");
【4xx】:通知浏览器,服务端本次未能提供服务的原因,是由于服务端没有对应的资源文件
404:服务端没有对应的资源文件
405:服务端有本次请求对应的Servlet,但是Servlet不负责处理浏览器当前的请求方式(浏览器使用GET方式发送请求,但是对应Servlet中没有重写doGet方法)
【5xx】:通知浏览器,服务端本次未能提供服务的原因,被调用Servlet在运行时抛出异常
默认欢迎资源文件:
定义:Http服务器接收到一个【默认请求时】返回的资源文件
默认请求:浏览器向某一个网站发送请求时,并没有指定索要的文件的情况
http://localhost:8080/myWeb //默认请求
http://localhost:8080/myWeb/one.html //具体请求
默认欢迎文件配置:
第一种方式:手动在web.xml配置
<welcome-file-list>
<welcome-file>one.html</welcome-file>
</welcome-file-list>
第二种方式:由Tomcat自行确认
如果Tomcat在当前网站中没有找到<welcome-file-list>标签,此时Tomcat回到自己的config文件夹下寻找一个web.xml文件,在这个web.xml寻找<welcom-file-list>标签,来获得默认欢迎文件地址
默认欢迎资源文件分类:
- 首选html文件或者jsp文件
- 也可以是一个Servlet,但是这个servlet应该是一个查询Servlet并且在运行是不需要得到浏览器发送的请求参数
多个Servlet来处理同一次请求方案
前提:
- 一个Servlet只负责实现一个功能
- 浏览器在一次请求时,只能请求一个资源文件
- 如果浏览器的请求需要由多个Servlet来协同完成,需要用户多次通过【手动提交请求】来完成任务,这样降低服务质量(如添加一个用户信息,添加完毕之后,用户想确认是否添加成功,还需要在点查询功能,这样就增加了用户的操作数)
方案分类:
只需要用户手动通过浏览器发送一次请求,就可以将与本次请求相关的Servlet来依次调用
- 重定向方案
- 请求转发方案
重定向方案原理:
在第一个Servlet工作完毕后,将【第二个Servlet地址】推送给用户浏览器,由用户浏览器根据这个地址来【自动的】向第二个Servlet发送请求
重定向方案涉及的命令
response.sendRedirect(第二个Servlet地址);
将一个地址写入到【响应头】中location,浏览器接受到响应包之后,自动根据location地址发送第二次请求,这样好处避免用户多次手动发送请求
重定向方案特征:
【发生位置】:在客户端的浏览器上
【浏览器发送的请求次数】:多次
【地址栏内容是否会发生变化】:会发生变化,内容是浏览器第二次需要访问的资源地址
【重定向时,浏览器采用的请求方式】:由于此时通过地址栏命令浏览器发送请求,所以浏览器采用请求方式一定是GET
【重定向时,访问的资源文件范围】:可以访问的资源文件可以是同一个网站的资源,也可以是其他网站的资源
重定向方案使用场景:
- 添加功能Servlet 调用 查询功能Servlet
- 删除功能Servlet 调用 查询功能Servlet
- 更新功能Servlet 调用 查询功能Servlet
OneServlet.java
protected void doGet(HttpServletRequest request,HttpSrevletReponse response) throws ServletException,IOException{
System.out.println("OneServlet负责洗菜工作");
response.sendRedirect("/myWeb/two.do");
}
TwoServlet.java
protected void doGet(HttpServletRequest request,HttpSrevletReponse response) throws ServletException,IOException{
System.out.println("OneServlet负责炒菜");
}
请求转发原理:
在第一个Servlet工作完毕后,代替当前浏览器向Tomcat申请调用第二个Servlet,Tomcat在接受到申请之后,调用第二个Servlet来完成本次请求中剩余任务
请求转发涉及的命令:
OneServlet.java
//创建一个资源申请报告对象
RequestDispatcher report = request.getRequestDispatcher("第二个Servlet地址");
//将申请报告推送给Tomcat,同时将OneServlet拥有的【request和response】一并交给Tomcat
report.forward(request,response)
//Tomcat在接受到报告之后,就会调用第二个Servlet来完成剩余任务
请求转发时为什么将第一个Servlet中request和response交给Tomcat
- Tomcat在接受到请求时,需要调用第二个Servlet
- Tomcat此时需要为第二个Servlet提供运行时需要【request】和【response】
- 但是,本次请求是由第一个Servlet来发送的,没有对应的【请求协议包】,因为导致Tomcat在接受到请求后,不会创建【request】和【response】
- 为了解决这个问题,需要将第一个Servlet使用【request】和【response】通过Tomcat交给第二个Servlet使用
请求转发特征:
【发生位置】:发生在服务端
【浏览器发送请求次数】:浏览器只向服务端发送了一次请求
【地址栏内容是否会发生变化】:由于请求转发发生在服务端,因此浏览器地址内容保持在一次请求内容
【调用资源文件范围】:只能访问同一个访问内部的资源文件
【通过请求转发调用的Servlet接受的请求方式】:与浏览器第一次发送请求时,使用的请求方式保持一致,参与同一次请求转发的所有Servlet接受的请求方式是一样的
【参与同一次请求转发的所有Servlet之间如何进行数据共享】:
- 可以使用全局作用域对象,提供共享数据
- 可以使用会话作用域对象,提供共享数据
- 可以使用请求作用域对象,提供共享数据
请求转发不适合场景:
- 添加功能Servlet 调用 查询功能Servlet
- 删除功能Servlet 调用 查询功能Servlet
- 更新功能Servlet 调用 查询功能Servlet
请求转发适合场景:
查询Servlet调用JSP时
OneServlet.java
protected void doGet(HttpServletRequest request,HttpSrevletReponse response) throws ServletException,IOException{
System.out.println("OneServlet负责洗菜工作");
RequestDispatcher report =request.getRequestDispatcher("/two.do");
report.forward(request,response);
}
TwoServlet.java
protected void doGet(HttpServletRequest request,HttpSrevletReponse response) throws ServletException,IOException{
System.out.println("OneServlet负责炒菜");
}