Servlet浅析
HTTP网络协议包内部结构
HTTP请求协议包
是浏览器在发送请求时负责创建的,浏览器将请求信息,写入到请求协议包中。HTTP请求协议包内部自上而下有四层结构。

HTTP响应协议包
在服务端计算机的【资源调度软件】准备推送文件时,负责创建。【响应协议包内容】可以由【资源调度软件】写入,可以由Java命令(response)写入。HTTP响应协议包自上而下有四层结构。

客户端计算机上浏览器管理
命令浏览器向指定网站发送请求
-
通过FORM表单命令
<form action="http://www.baidu.com"> </form> -
通过超链接命令
<a href="http://www.baidu.com">163.com</a> -
浏览器的地址栏对象
window.location="http://www.sina.com";
请求方式[POST/GET]

如何控制浏览器采用的请求方式
- GET方式
- 超链接标签
- location对象
- FORM表单中method=GET
- POST方式
- FORM表单中method=POST
使浏览器在发送请求时,携带请求参数
固定的请求参数内容
-
超链接标签
<a href="http://www.baidu.com?uname=mike&age=23">百度</a> -
location对象
window.location="http://www.baidu.com?uname=mike&age=23"
动态请求参数内容【FORM表单】
- 【表单域标签分类】:input,select, textarea
- 【表单域标签作为请求参数条件】
- 表单域标签必须声明在FORM内部
- 表单域标签必须声明【name属性】,作为【请求参数名】
- 针对checkbox和radio,只有被选中的情况下,才能作为请求参数
HTTP服务器
Tomcat服务器
Tomcat端口号
存储位置:tomcat安装目录下/conf/server.xml
<Connector port="8080" protocol="HTTP/1.1"connectionTimeout="20000" redirectPort="8443" />
Servlet规范
基础
如何开发一个Servlet接口实现类
- 创建一个实现类,继承【HttpServlet】
- 【HttpServlet】存在Tomcat中
/lib/servlet-api.jar中javax.servlet.http.HttpServlet - 根据来访的浏览器采用的请求方式,重写对应doGet或者doPost方法
- 在
/WEB-INF中的web.xml注册Servlet接口实现类,通知Tomcat当前网站存在一个动态资源文件
Tomcat调用Servlet接口实现类流程

Servlet请求路径的写法
-
具体请求路径
【要求】:请求的【资源文件地址】与当前servlet中url-pattern完全一致;必须以
/开头。【例子】:
OneServlet <url-pattern>/one.do</url-pattern> localhost/myWeb/one.do 会被调用 localhost/myWeb/abc/one.do 不会被调用 -
前置条件请求路径
【要求】:请求的【资源文件地址】以当前Servlet中
的内容为开头;必须以 /开头,以*结尾【例子】:
OneServlet <url-pattern>/abc/*<url-pattern> localhost/myWeb/abc/two.do 会被调用 localhost/myWeb/abc/one.html 会被调用 -
后置条件请求路径
【要求】:请求的【资源文件地址】以当前Servlet中
的内容为结尾;不能以 /为开头,必须以*为结尾。【例子】:
OneServlet <url-pattern>*.do</url-pattern> localhost/myWeb/abc/one.do 会被调用 localhost/myWeb/five.do 会被调用 localhost/myWeb/five.do?uname=mike 会被调用 -
通配符请求路径:
【要求】:当前Servlet可以接受对当前网站的所有请求;
【例子】:
OneServlet <url-pattern>/*</url-pattern> localhost/myWeb/* 会被调用
优先级:【具体请求路径】>【前置条件】>【通配符】>【后置条件】
Servlet实例对象【生命周期】
-
所有Servlet实例对象都是由Tomcat负责创建,开发人员不能创建
-
创建时机:
-
【默认情况】:当第一个用户访问这个Servlet时,Tomcat负责创建
-
【人工干预】:要求Tomcat在启动时,创建Servlet实例对象
<servlet> <load-on-startup>0</load-on-startup> </servlet>
-
-
Tomcat运行期间,一个Servlet实现类只能被创建一个实例对象。
-
Tomcat关闭时,由Tomcat销毁所有的Servlet实例对象
五种工具对象
介绍
- HttpServletResponse:负责将运行结果写入到响应包中
- HttpServletRequest:负责读取请求协议包信息
- ServletContext:为当前网站中所有的Servlet提供【共享数据】
- Cookie:在一次会话中,存储浏览器在服务端产生的私人数据
- HttpSession:在一次会话中,存储浏览器在服务端产生的私人数据
HttpServletResponse接口
通过【响应对象】将【英文】字符串写入【响应体】中
String str="hello HttpServletResponse";
//从【响应对象】获得一个输出流
PrintWriter out=response.getWriter();
//利用【输出流】将【字符串】写入【响应体】
out.write(str);
//隐藏步:Tomcat在OneServlet调用完毕后,将响应包推送到浏览器中
out.write()与out.print()
int num=50;
PrintWriter out=response.getWriter();
out.write(num);//只能将字符串或者unicode码写入响应体中,一个值为50 的unicode码对应字符串为2
out.println(num);//将任意东西写入,并且保持原始状态
乱码与字符集
String str="下课休息";
//浏览器根据【响应头】中设置的【字符集】对接受的内容进行解码
//默认【响应头】中字符集是【ISO-8859-1】无法解析中文内容
response.setCharacterEncoding("GBK");
PrintWriter out = response.getWriter();
out.println(str);
String str="China中国<br/>America美国<br/>Franch法国";
//浏览器根据【响应头】中的【内容类型】处理接受的结果
//默认情况下【内容类型】为"text" ,即存放的是字符串内容
response.setCharacterEncoding("UTF-8");
//若返回内容包含html标签,则需要重新设置【内容类型】response.setContentType("text/html");
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write(str);
远程查询服务
步骤:
- 导入依赖的工具类(Dbutil,SqlSession)
- 导入mysql驱动包(WEB-INF下创建【lib】文件夹、将mysql驱动包复制到lib下)
- 创建实体类model.Dept
- 创建数据操控类 dao.DeptDao
- 创建Servlet controller.DeptFindServlet
DeptFindServlet
response.setContentType("text/html;charset=UTF-8");
DeptDao dao = new DeptDao();
List<Dept> deptList=null;
PrintWriter out=null;
//1.JDBC查询所有部门信息
deptList = dao.findAll();
//2.响应对象将查询结果写入响应体中
out = response.getWriter();
for(Dept dept:deptList){
out.write(dept.getDeptNo()+" "+dept.getDname()+" "+dept.getLoc());
}
DeptDao
public class DeptDao {
public List findAll(){
String sql = "select * from dept";
List deptList = SqlSession.selectList(sql,Dept.class);
return deptList;
}
}
Dept
public class Dept {
private Integer deptNo;
private String dname;
private String loc;
//setter&getter...
public Dept(Integer deptNo, String dname, String loc) {
this.deptNo = deptNo;
this.dname = dname;
this.loc = loc;
}
//确保有无参构造-反射
public Dept() {
}
}
HttpServletRequest接口
作用:
-
读取【请求行】信息(请求地址、请求方式)
String url=request.getRequestURL(); String method=request.getMethod(); -
读取【请求头】或【请求体】中所有的【请求参数名】
request.getParameterNames();//保存到枚举对象中 -
读取请求体或请求头中的【参数内容】(?uname=1&uname=2)
String value=request=request.getParameter("请求参数名");//单个参数 String array[]=request.getParameterValues("请求参数名");//多个参数
读取当前请求协议包所有的请求参数名称
Enumeration<String> parameterNames = request.getParameterNames();
while(parameterNames.hasMoreElements()){
String parametername = parameterNames.nextElement().toString();
response.getWriter().println(parametername);
}
TODO:request远程添加服务
请求对象与响应对象的生命周期【概念】
- 都是由Tomcat负责创建,当Tomcat收到一个【请求协议包】时,会为这个【请求协议包】创建一对request和response,一次请求对应一对erquest和ersponse。
- Tomcat调用被请求的Servlet中服务方法(doGet/doPost),负责将本次【请求对象和响应对象】作为参数传入到服务方法中。
- 在服务的Servlet工作完毕后,Tomcat负责销毁本次请求的request和response
中文请求参数乱码问题【概念】
-
在【GET】方式中,请求头中默认为【UTF-8】,Tomcat9.0默认采用【UTF-8】
-
在【POST】方式中,请求体中默认为【ISO-8859-1],需要重设request字符集
request.setCharacterEncoding("utf-8");
ServletContext接口
介绍
-
提供全局作用作用域对象,一个网站中一个,为当前工程中所有Servlet提供【共享数据】
-
使用
ServletContext application = request.getServletContext(); //向Tomcat所要全局作用域对象
共享数据来源
-
添加到
web.xml<context-param> <param-name>共享数据名</param-name> <param-value>共享数据内容</param-value> </context-param>使用【只读】
ServletContext application = request.getServletContext(); value=application.getInitParameter("name"); -
通过Servlet添加【可修改】
application.setAttribute("name",value); value=application.getAttribute("name");
会话【概念】
- 定义:一个浏览器与一个服务器的一次完整交流
- 特点:
- 在一次会话中,经历多次响应和请求
- 在一次会话中,同一个浏览器往往访问多个Servlet
- 需求:在一次会话过程中,在浏览器要访问的Servlet之间进行数据共享
- 解决方案:Cookie和HttpSession
Cookie
介绍
- Servlet规范提供的一个工具类,在一个会话过程中Servlet之间进行数据共享
- 存储在浏览器上,保存本次会话的共享数据
- 存在于【请求头】和【响应头】中,以
{key:value}形式存在
使用
Cookie c1=new Cookie("key",value);//一个Cookie中只能有一个键值对,只能存储String类型
Cookie c2=new Cookie("key2",URLEncoder.encode(饺子,"utf-8"));//中文编码问题
(Tomcat9以下)
URLDecoder.decode(name);//反编码
response.addCookie(c1);//写入响应头中
Cookie array[]=request.getCookies();//从请求头中读取cookie
生命周期
-
默认保存在浏览器内存中,关闭时Cookie消失
-
【人工干预】:要求保存到硬盘,并指定时间
cookie.setMaxAge(time);//以秒为单位的时间
Cookie应用
OneServlet 设置cookie
{
//1.读取当前用户的基本信息
String username = request.getParameter("username");
String jiaozi = request.getParameter("jiaozi");
//2.将当前用户的私人数据保存到Cookie中
//中文Cookie编码问题
Cookie c1 = new Cookie("key1",username);
Cookie c2 = new Cookie("key2", jiaozi);
//设置c1对象需要在用户硬盘上存活1分钟
c1.setMaxAge(60);//60s
//3.将Cookie对象写入到【响应包】中的【响应头】
response.addCookie(c1);
response.addCookie(c2);
}
TwoServlet读取cookie
{
//1.读取当期那来访浏览器推送的Cookie
Cookie[] cookies = request.getCookies();
//根据得到的Cookie
for(Cookie cookie:cookies){
String keyname = cookie.getName();//读取Cookie中关键字名称
String value = cookie.getValue();
if("key1".equals(keyname)){
System.out.println("欢迎"+value);
}else if ("key2".equals(keyname)){
System.out.println("已准备"+ value);
}
}
}
HttpSession接口
与Cookie的区别
-
相同点:都是为同一个会话的Servlet之间提供共享数据
-
不同点:
Cookie HttpSession 存储位置 浏览器内存或硬盘上 内存 存储内容 只能存储String类型 可以存储任意类型 存储数量 只能存储一个键值对 一个HttpSessio对象可以存储任意个键值对
使用
-
在浏览器来访时,Tomcat不会主动创建HttpSession对象
只有浏览器访问的Servlet提出要求时,才会创建Session对象
-
申请Session对象:
HttpSession session = request.getSession(); //已有session返回session,否则创建(用于存储数据) HttpSession session = request.getSession(true);//与无参一样 HttpSession session = request.getSession(false); //已有session返回session,否则返回null (用于验证) -
Tomcat如何将Session和浏览器关联:在Tomcat创建一个Session对象,并生成唯一编号,将编号保存到cookie中,推送到当前浏览器内存中。Tomcat根据浏览器返回的cookie判断是否有session对象
-
使用
session.setAttribute("key",共享数据) session.getAttribute("key")
HttpSession简单购物车
OneServlet
//1.读取浏览器推送过来的商品名称
String goodsName = request.getParameter("name");
//2.向Tomcat索要当前浏览器在服务端的HttpSesion
HttpSession session = request.getSession();
//3.将用户选择的商品保存到当前用户Session中
Integer goodsNum = (Integer)session.getAttribute(goodsName);
if(goodsNum==null){
session.setAttribute(goodsName, 1);
}else{
session.setAttribute(goodsName, goodsNum+1);
}
<center>
<h1>商品展示页面</h1>
<table border="2">
<tr>
<td>面包</td>
<td>15.00</td>
<td><a href="/myweb/one.do?name=面包">放入购物车</a></td>
</tr>
<tr>
<td>啤酒</td>
<td>10.00</td>
<td><a href="/myweb/one.do?name=啤酒">放入购物车</a></td>
</tr>
<tr>
<td>烤肠</td>
<td>30.00</td>
<td><a href="/myweb/one.do?name=烤肠">放入购物车</a></td>
</tr>
</table>
</center>
多个Servlet来处理同一次请求方案
前提:
- 一个Servlet只负责实现一个功能
- 浏览器在一次请求时,只能请求一个资源文件,如果客户需要多个Servlet协同完成,需要用户多次【手动提交请求】完成任务,降低服务质量
重定向
原理
- 【浏览器二次发送请求】,第一次得到302状态码,【地址栏会改变】,请求方式一定是【GET】
- 在第一个Servlet工作完成后,将第二个Servlet的地址推送给客户浏览器,浏览器根据这个地址自动向第二个Servlet发出请求

用法
response.sendRedirect("第二个Servlet地址");//将地址写入响应头中的location
适用场景:添加/删除/更新功能Servlet之后-->调用查询功能Servlet
请求转发
原理
- 【服务器自动请求第二个Servlet】,请求方式一律跟随浏览器发出的请求方式(否则会405异常),【地址栏不变】
- 在第一个Servlet工作完成后,代替浏览器向Tomcat申请调用第二个Servlet


用法
RequestDispatcher report = request.getRequestDispatcher("第二个Servlet地址");//创建资源申请报告对象,不能从网站根目录开始写,写url-pattern
report.forward(request,response);//推送申请报告
//数据共享域 application HttpSession request
适用场景:查询Servlet调用JSP时
不适用场景:添加/删除/更新功能Servlet 之后 -> 查询功能Servlet

浙公网安备 33010602011771号