Servlet(多个Servlet的交互)(中)
Servlet文章目录Servlet1.资源欢迎文件2.状态码1.资源欢迎文件概念:访问网页默认弹出的资源叫作欢迎资源文件;默认欢迎资源文件:位置:Tomcat9/conf/web.xml—>文件末尾根据下述源码可知,当未设置具体访问资源时,浏览器会默认访问index.html,index.htm或者index.jsp。文件。或者另外两个文件。<welcome-file-list>
Servlet
1.资源欢迎文件
概念:
访问网页默认弹出的资源叫作欢迎资源文件;
默认欢迎资源文件:
位置:
Tomcat9/conf/web.xml—>文件末尾
根据下述源码可知,当未设置具体访问资源时,浏览器会默认访问index.html
,index.htm
或者index.jsp
。
文件。
或者另外两个文件。
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
自行设置欢迎资源文件:
位置:
网站/web/WEB-INF/web.xml
自行设置之后Tomcat自带的默认欢迎文件将失效。
语法规范:
<!----资源名可以是动态资源文件,也可以是静态资源文件---->
<welcome-file-list>
<welcome-file>(资源名)(login.html)</welcome-file>
</welcome-file-list>
2.状态码
定义:
由三位数字组成的一个符号(100~599);
位置:
Http服务器推送【响应包】前,根据处理结果将状态码写入【响应包】的【状态行】上。
作用:
向浏览器通知处理结果或向浏览器解释不能提供服务的原因。
典例:
①100:通知资源文件不完整,需要继续索要缺失部分;
②200:通知本次资源文件返回完整无缺失;
③302:通知本次返回的不是资源内部而是资源的地址,需浏览器根据返回的地址继续索要资源文件;
④404:通知B端S端没有定位到被访问文件;
⑤405:通知B端S端定位到被访问文件但无法访问(访问方式错误);
⑥500:通知B端S端定位到被访问文件,也存在访问方法,但出现了Java语句的异常。
3.多个Servlet的调用规则:
(1).重定向的解决方案:
原理:
用户第一次手动访问OneServlet,访问结束时,将TwoServlet地址写入响应头的【location】中,浏览器接收到响应包时,读取到302状态,根据【location】发起第二次请求,访问TwoServlet。
特点:
①浏览器至少发送两条请求;
②该方案的请求方式一定是【Get】;
优缺点:
优点:
该方案能调用当前网站资源或站外的其他网站资源;
缺点:
增加了用户等待时间,效率较低。
实现命令:
//根据相应对象设置location属性
response.sendRedirect("(网站名)");
//网站名格式应为/网站名/资源名
(2).请求转发解决方法:
原理:
用户第一次手动访问OneServlet,放完结束后,通过当前请求对象代替浏览器向Tomcat发送请求,申请调用TwoServlet,完成任务即可。
特点:
①浏览器仅仅发送了一次请求(推送了一个请求包)
②请求方式只取决于第一次请求方式保持不变(因为只有一个请求包)
优缺点:
优点:
无论涉及到多少Servlet,仅发出一次请求,减少浏览器与服务器的交互次数。
缺点:
只能调用当前网站下的资源,无法站外调用。
实现命令:
//通过【请求对象】拿到资源文件申请报告对象
//资源文件名格式写为"/jsp”或“/html"格式
RequestDispatcher report = request.getRequestDispatcher("(资源文件名)");
//将报告对象发送给Tomcat服务器
report.forward((当前请求对象),(当前响应对象));
4.多个Servlet的数据共享
(1).ServletContext接口(全文):
概述:
①存在于Servlet规范中,Tomcat中存在【servlet-api.jar】包下;
②如果两个Servlet来自同一个网络,则可通过网站的【ServletContext实例对象】实现数据共享。
③开发人员习惯将其称为【全局作用域对象】。
特点:
①每个网站都存在一个全局作用域对象(类似于Map采用键值对储存)
②当前网站所有Servlet都可从中获取到相关数据。
生命周期:
①http服务器启动时,自动创建一个【全局作用域对象】;
②http服务器运行时,仅有一个【全局作用域对象】存在且一直存活;
③http服务器关闭时,自动销毁【全局作用域对象】。
核心:【全局作用域对象】周期贯穿整个服务器运行期间。
实现命令:
在OneServlet中:
//通过请求对象向Tomcat服务器索要【全局作用域对象】
ServletContext application = request.getServletContext();
//将共享数据添加到【全局作用域对象中】
application.setAttribute("key1",(值));
在TwoServlet中:
//通过请求对象向Tomcat服务器索要【全局作用域对象】
ServletContext application = request.getServletContext();
//从【全局作用域对象】中获取key1所对应的数据
datatype data = application.getAttribute("key1");
(2).Cookie类:
概述:
①存在于Servlet的工具类中,Tomcat中存在的【servlet-api.jar】包下;
②如果两个Servlet来自同一个网站,且为同一个浏览器提供服务,则可通过【Cookie】对象进行数据共享;
③存放私人数据,为提高服务质量。
原理:
用户通过浏览器向网站发送请求申请OneServlet,OneServlet在运行期间会创建一个【Cookie】对象存当前用户的相关数据,工作完毕后,将Cookie写入响应头交还给浏览器。收到响应包后,将Cookie存入缓存,用户通过同一浏览器再次向Two发送请求时,浏览器将Cookie推给请求头发送过去。(类比会员卡机制)
特点:
①Cookie相当于一个Map存储;
②一个Cookie只能存储一个键值对;
③键值对都只能是String类型,key不能是中文。
实现命令:
OneServlet中:
//创建一个Cookie对象,存放共享数据
Cookie cookie = new Cookie("key1","abc");
//将Cookie对象交给响应头,交给浏览器
response.addCookie(cookie);
TwoServlet中:
//调用请求对象从请求头拿到浏览器的Cookie
Cookie[] cookieArray = request.getCookies();
//遍历数据拿到每一个Key和value
for(Cookie c:cookieArray){
String key = c.getName();
String value = c.getValue();
...(对Key和Value做处理即可)...
}
(3).补充请求包和响应包:
请求包:
【请求行】组成规则:方法 /url HTTP/版本号 例:GET /xinwen/2018-07/17/content_5307156.htm HTTP/1.1
【请求头】包含了客户端的环境,例:(地址http://tools.jb51.net/table/http_header)
【请求体】要发送的数据(一般post方式会使用);例:userName=123&password=123&returnUrl=/
响应包:
【响应行】规则:HTTP/版本号 响应码(状态码) 例:HTTP/1.1 200 OK
【响应头】服务器端的信息
【响应体】 显示在浏览器的内容(与响应头配合,显示出来)
(4).Cookie的项目实例(点餐系统):
a.书写欢迎页面index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>订餐系统欢迎页面</title>
</head>
<body>
<center>
<font style="color:red;font-size:40px">新会员申请开卡</font>
<form action="/myWeb/one">
<table border="2">
<tr>
<td>用户名</td>
<td><input type="text" name="userName"/></td>
</tr>
<tr>
<td>预存金额</td>
<td><input type="text" name="money"/></td>
</tr>
<tr>
<td><input type="submit" value="申请开卡" /></td>
<td><input type="reset" value="重置"/></td>
</tr>
</table>
</form>
</center>
</body>
</html>
b.创建OneServlet用来识别会员卡,创建TwoServlet用来划卡消费
c.配置web.xml文件(web.xml文件)
<servlet>
<servlet-name>OneServlet</servlet-name>
<servlet-class>OneServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>OneServlet</servlet-name>
<url-pattern>/one</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>TwoServlet</servlet-name>
<servlet-class>TwoServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TwoServlet</servlet-name>
<url-pattern>/two</url-pattern>
</servlet-mapping>
d.书写点餐界面order.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<center>
<font style="color:red;font-size:40px">点餐页面</font>
<form action="/myWeb/two">
食物类型:<input type="checkbox" name="food" value="dumpling"/>饺子(30RMB)
<input type="checkbox" name="food" value="noodles"/>面条(20RMB)
<input type="checkbox" name="food" value="rice"/>盖浇饭(15RMB)<br/>
<input type="submit" value="划卡消费">
</form>
</center>
</body>
</html>
e.补充完整OneServlet与TwoServlet
OneServlet:
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class OneServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//初始化变量区
String userName,money;
//通过【请求对象】获取到用户的参数信息
userName = request.getParameter("userName");
money = request.getParameter("money");
//创建两个Cookie对象
Cookie cookie1 = new Cookie("userName",userName);
Cookie cookie2 = new Cookie("money",money);
//将Cookie对象存入响应体中
response.addCookie(cookie1);
response.addCookie(cookie2);
//响应体将点餐页面发送给浏览器(请求转发)
response.sendRedirect("/myWeb/order.html");
}
}
TwoServlet:
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class TwoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//变量初始化区
int dumpling_money = 30;
int noodles_money = 20;
int rice_money = 15;
int cost = 0;
int money = 0;
int balance = 0;
String userName;
String[] food = new String[3];
Cookie[] cookieArray;
PrintWriter out = null;
Cookie newCard = null;
//①读取请求头参数,得到用户点餐类型
food = request.getParameterValues("food");
for (String s:food) {
if ("dumpling".equals(s)) {
cost += dumpling_money;
} else if ("noodles".equals(s)) {
cost += noodles_money;
} else if ("rice".equals(s)) {
cost += rice_money;
}
}
//System.out.println(cost);
//②读取请求头中的Cookie,得到用户会员卡
cookieArray = request.getCookies();
//③根据食物类型进行消费处理
for (Cookie data : cookieArray) {
String key = data.getName();
//拿到用户名和预存金额
String value = data.getValue();
if ("userName".equals(key)){
userName = value;
}else if ("money".equals(key)){
money = Integer.valueOf(value);
}
}
//System.out.println(money);
response.setContentType("text/html;charset=utf-8");
out = response.getWriter();
if (cost > money){
balance = money;
out.print("<font style='color:red;font-size:40px'>对不起,您的余额不足,请充值(●'◡'●)</font>");
}else{
balance = money-cost;
out.print("<font style='color:blue;font-size:40px'>消费成功(●'◡'●),您的卡上余额剩余"+balance+"元!");
}
//④将Cookie交还给用户,并将消费记录写入响应体
newCard = new Cookie("balance",balance+"");
response.addCookie(newCard);
}
}
f.结果演示:
登录会员卡:
点击申请开卡弹出点餐页面:
将三种食物全选,点击”划卡消费“:
如果开始开卡钱数不够,则消费失败:
g.开发过程总结与反思
本次开发过程中,进行了将案例中的单选框改为复选框,认为返回的值应可以依次存储在数组里,比如,我在三种食物处都打上勾,那么会不会将三种食物以字符串形式存入字符串数组里。原代码:
//初始化字符串数组存储食物名称
int dumpling_money = 30;
int noodles_money = 20;
int rice_money = 15;
int cost = 0;
String[] food = new String[10];
for(int i = 0;i < 3;i++){
//从输入的复选框中拿到选项参数
food[i] = request.getParameter("food");
//如果拿到某种食物,则让花费变量cost加上该种食物的价格
if("dumpling".equals(food[i])){
cost+=dumpling_money;
}else if("noodles".equals(food[i])){
cost+=noodles_money;
}else if("rice".equals(food[i])){
cost+=rice_money;
}
}
后来发现,这种做法仅能用于单选框情况,如果如图代码会将识别到的第一种食物重复算三次。比如三种食物全选,会得到cost最后的值为饺子价格的三倍(30x3)经过查阅资料,对多选框得到了下面这种解法:
int dumpling_money = 30;
int noodles_money = 20;
int rice_money = 15;
int cost = 0;
Stirng[] food = new String[10];
//直接通过getParameterValues方法拿到整个复选框字符串数组
food = request.getParameterValues("food");
//再去遍历这个字符串数组,即可拿到多选的每个食物
for (String s:food) {
if ("dumpling".equals(s)) {
cost += dumpling_money;
} else if ("noodles".equals(s)) {
cost += noodles_money;
} else if ("rice".equals(s)) {
cost += rice_money;
}
}
同理,这种代码写法如果三种食物全选时,cost最后的值为三种食物的价格总和(30+20+15),结果合理。
(5).HttpSession接口(会话):
概述:
①存在于Servlet规范中,Tomcat中存在servlet-api.jar中,Tomcat提供了实现类;
②如果两个Servlet来自于同一个网站,且为同一个浏览器提供服务,则可通过HttpSession实现类对象进行数据共享;
③开发人员习惯将其成为【会话作用域对象】。
Session和Cookie的对比:
①Cookie存在于客户端计算机内存;
而Session存在于服务端计算机的内存中;
② Cookie对象仅能存储String类型数据;
而Session实现类对象可以存储任意类型;
③一个Cookie对象只能存一个共享数据;
而Session实现类对象用map进行储存,可存任意数量的对象;
④Cookie相当于用户服务端的【会员卡】;
而Session相当于服务端的【私人保险柜】。
命令实现:
OneServlet中:
以下两种方法的区别:
前者:如果用户存在已有的【私人保险柜】,返回对应的【私人保险柜】
如果用户不存在【私人保险柜】,tomcat会创建一个全新的【私人保险柜】。
后者:如果用户存在已有的【私人保险柜】,返回对应的【私人保险柜】
如果用户不存在【私人保险柜】,tomcat拒绝服务,直接返回null。
//调用【请求对象】向Tomcat索要Session
HttpSession session = request.getSession();
//或者
HttpSession session = request.getSession(false);
//将数据添加到【私人保险柜】Session对象中
session.setAttribute("key1",data);
TwoServlet中:
//调用【请求对象】向Tomcat索要Session
HttpSession session = request.getSession();
//从【会话作用域对象】中获取共享数据
Object data = session.getAttribute("key1");
Session的销毁时机:
①用户与Session关联时使用的Cookie仅存在于缓存中;
②浏览器关闭时,Session与用户的联系被切断;
③Tomcat无法得知浏览器是否关闭,所以浏览器关闭时Tomcat并不会销毁Session;
④为了解决③中的问题,Tomcat设置了默认的【空闲时间】30min,到时间后自动销毁Session。
⑤也可手动设置Session实现类对象的销毁时机。
手动设置Session的销毁时机:
(在web.xml下)
<!---手动设置5分种后销毁Session实现类对象--->
<session-config>
<session-timeout>5</session-timeout>
</session-config>
(6).HttpServletRequest接口(请求):
概述:
①两个Servlet通过【请求转发】互相调用,彼此共享一个请求协议包,此时可共享数据;
②开发人员将其对象叫作【请求作用域对象】。
命令实现:
OneServlet中:
//将数据存入【请求作用域对象】中
request.setAttribute("key1",data);
//向Tomcat申请调用TwoServlet
RequestDispatcher report = request.getRequestDispatcher("/two");
report.forward();
TwoServlet中:
//从当前【请求对象】中拿出共享数据
Object data = request.getAttribute("key1");
更多推荐
所有评论(0)