引言
Servlet:简单来说可以理解为一个程序实例。要学习servlet首先要了解HTTP响应协议和请求协议
HTTP请求协议
如上图所示,请求协议由三部分组成:请求行、请求头、请求体。
请求行:
①是请求方法,GET和POST是最常见的HTTP方法,除此以外还包括DELETE、HEAD、OPTIONS、PUT、TRACE。在地址栏输入地址的请求方式都是doGet,doGet请求方式将请求信息放在【请求行】中。
②为请求对应的URL地址,它和报文头的Host属性组成完整的请求URL。
③是协议名称及版本号。
请求头:
④是HTTP的报文头,报文头包含若干个属性,格式为“属性名:属性值”。还有Cookie。
请求体:
⑤是报文体,它将一个页面表单中的组件值通过param1=value1¶m2=value2的键值对形式编码成一个格式化串,它承载多个请求参数的数据。不但报文体可以传递请求参数,请求URL也可以通过类似于“/chapter15/user.html? param1=value1¶m2=value2”的方式传递请求参数。
HTTP响应协议
如上图所示,响应协议包括响应行、响应头、空行、响应体
响应首行:HTTP版本,状态码,
响应头:响应也都是键值对形式,服务器端将信息以键值对的形式返回给客户端
Location 指定响应的路径,需要与状态码302配合使用,完成跳转。
Content-Type 响应正文的类型(MIME类型)。 取值:text/html;charset=UTF-8
Content-Disposition 通过浏览器以下载方式解析正文。 取值:attachment;filename=xx.zip
Set-Cookie 与会话相关技术。服务器向浏览器写入cookie
Content-Encoding 服务器使用的压缩格式。 取值:gzip
Content-length 响应正文的长度
Refresh 定时刷新,格式:秒数;url=路径。url可省略,默认值为当前页。取值:3;url=www.itcast.cn //三秒刷新页面到www.itcast.cn
Server 指的是服务器名称,默认值:Apache-Coyote/1.1。可以通过conf/server.xml配置进行修改。< Connector port=”8080” … server=”itcast”/>
Last-Modified 服务器通知浏览器,文件的最后修改时间。与If-Modified-Since一起使用。
空行
响应体:是一个HTML页面
环境搭建
idea2019.3+Tomcat9
在Application Server栏选择Tomcat的安装目录,然后勾选Web Application(4.0)然后Next,给工程起名字。
如上图创建servlet程序,注意Creat Java EE 6 annotated class的√要去掉。然后在web->WEB-INF->web.xml文件里为这个Servlet程序起一个简短别名。
可以在servlet程序的doGet方法里面写一个输出语句。然后就运行这个项目。
按图所示点击+,点击Artifact,选择要运行的servlet工程。
在浏览器地址栏输入你为这个Servlet程序起的别名之后,在idea中就可以看到你的输出语句的执行结果了。
正文
servlet:
指定动态资源文件的开发步骤、
指定HTTP服务器调用动态资源文件规则、
指定HTTP服务器管理动态资源文件实例对象规则。
- HTTP服务器能调用的动态资源文件必须是一个Servlet接口的实现类,这个Servlet接口是在servlet-api.jar这个包里的。
- 所以这里指的动态资源文件就是实现Servlet接口的Java类。只有当你自定义的类implement Servlet时,Tomcat才有权利调用。
我们在写servlet程序的时候只需要继承HttpServlet接口,没必要继承Servlet接口,因为实现Servlet接口需要重写5个方法,而这5个方法中只有service方法Tomcat调用的时候能用到,其余都用不到。HttpServlet有爸爸辈和爷爷辈,他们都是抽象类,都将servlet接口中的5个方法进行抽象实现了。需要哪个就重写。HttpServlet类中已经实现了service方法,首行就是res.getMethod(),看请求行的请求方式。
当你浏览器向Tomcat服务器发送请求协议的时候,服务器会为这个请求协议自动new两个对象,请求对象和响应对象。然后看你请求参数是调用这个web工程里面的哪个方法,我在Tomcat服务器里面为这个方法提供单例对象,然后看请求协议里面是什么请求方式,比如说是doGet方式,就将请求对象、响应对象作为实参传递到这个doget方法里面。
当doGet方法执行完毕的时候,这就意味着本次的请求就处理完毕了。就会对请求对象和响应对象进行销毁,之后再将请求的处理结果,也就是相应协议包发送给浏览器。
Servlet接口实现类的开发步骤:
1、创建一个Java类实现HttpServlet接口,使之成为一个Servlet接口实现类。
2、重写HttpServlet父类中的两个方法,doget、dopost
3、将Servlet接口实现类信息【注册】到Tomcat服务器上 ,就是在web.xml文件里给servlet程序起别名
Servlet对象生命周期
①网站中所有的servlet对象都只能由HTTP服务器创建,开发人员不能手动创建servlet接口实现类对象、
②一个servlet接口实现类只能创建一个实例对象。
③在HTTP服务器关闭时实例对象进行销毁
HttpServletResponse,Tomcat服务器响应的编写以及注意事项。
HttpServletResponse接口负责将doGet和doPost方法执行结果写到响应体中交给浏览器。开发人员习惯将HttpServletResponse接口修饰的对象称为【响应对象】
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//执行doget方法的结果,就是你要传的数据
String result ="hello ,这是doget方法";
String result2="大连</br>西安路</br>中央大道";
//②另外,当我们要传输的字符串中有HTML的语法时,应该在索要输出流之前,通过响应对象响应头中content-type="text/html",来设置。
response.setContentType("text/html;charset=utf-8");
//③设置location属性,控制浏览器向指定服务器发送请求
response.sendRedirect("http://www.baidu.com");
//通过响应对象,向Tomcat索要输出流
PrintWriter out=response.getWriter();
//①通过输出流,将执行结果以二进制形式写入到响应体
out.write(result);//这个输出流用完之后不需要关闭,不是你自己的输出流,而是你想Tomcat借的输出流
/**
* out.write(),只能写【字符】,【字符串】,【ASCII】码,当你写整型的时候它默认给你你输入的是ASCII。
* 所以我们不用这个,通常用out.print();
*/
out.print(50);
}//doget执行完毕,Tomcat将响应包推送给浏览器。
HttpServletResponse主要功能:
①将doget。dopost方法的执行结果以二进制的形式写入响应体中。
②设执行迎头中的content-type属性值,从而控制浏览器使用,对应编译器将响应体二进制数据编译为【文字、图片、视频、命令】。同时还将值定浏览器的编码格式。
③设置响应头的【location 】属性,讲一个请求地址赋值给location。从而控制浏览器向指定服务器(就是你location设置的属性值)发送请求。
HttpServletRequest
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//读取HTTP请求协议包中【请求行】信息
//通过请求对象,读取【请求行】中【url】信息
String url=request.getRequestURI().toString();
//通过请求对象,读取【请求行】中【method】信息, 就是doget还是dopost方式
String method =request.getMethod();
/**
* uri: 资源文件精准定位地址,在请求行里并没有这个属性
* 实际上是从URL中截取的一个字符串。这个字符串的格式“/网站名/资源文件名”
*/
String uri=request.getRequestURI();//里面就相当于substring,字符串的截取方法。
System.out.println("url:"+url);
System.out.println("method:"+method);
System.out.println("uri:"+uri);
//获取【请求头】所有请求参数的名称,保存在一个枚举对象里面。
Enumeration paramNames= request.getParameterNames();
while (paramNames.hasMoreElements()) {
String paramName=(String) paramNames.nextElement();
//获取请求参数对应的值
String value= request.getParameter(paramName);
System.out.println("请求参数名称:"+paramName+"请求参数值"+value);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//①通知请求对象,使用utf-8字符集对请求体二进制内容进行一次重写解码
request.setCharacterEncoding("utf-8");
String value=request.getParameter("userName");//获取Post方式中userName的请求参数值
}
①
- 浏览器以get方式发送请求,请求参数保存在【请求头】中,Http请求协议包到达Http服务器之后,第一件事是进行解码,请求头二进制内容由Tomcat负责解码。在Tomcat9中默认使用【utf-8】字符集
- 浏览器以post方式发送请求,请求参数保存在【请求体】中,Http请求协议包到达Http服务器之后,请求体二进制内容由当前请求对象(request)负责解码。request默认使用【IS0-8859-1】字符集,会出现中文乱码。
当用post方式发送请求参数,并且请求参数中有中文,在读取请求参数值得时候要先指定字符集在idea中用Tomcat本地服务器做网页
Cookie
cookie来自于servlet规范中的一个工具类,存在于Tomcat提供的servlet-api.jar中
如果两个servlet来自于同一个网站,并且为同一个浏览器/用户提供服务,此时借助于Cookie对象进行数据共享
Cookie存放当前用户的私人数据,在共享过程当中提高服务质量。
servlet程序在第一次运行期间创建一个Cookie存放于当前用户相关的数据,servlet工作完之后【将Cookie写入到响应头】 交还给当前浏览器。浏览器收到响应包之后,将cookie存储在浏览器的缓存,下一次浏览器访问同一个地址的时候,【浏览器需要无条件的将该网站之前推送过来的Cookie,写入到请求头】,然后发送过去。
Cookie销毁时机
在默认情况下,Cookie对象存放在浏览器中,只要浏览器关闭了,Cookie对象就被销毁掉
在手动设置的情况下,可以要求浏览器将接受的Cookie存放在客户端计算机硬盘上。同时需要指定Cookie在硬盘上存活时间。存活时间到达时,Cookie自动从硬盘上被删除
cookie.setMacAge(60);//表示cookie在硬盘上存活1分钟,60秒
代码示例:
Cookie cookie =new Cookie(parameterName,value);//表示你要存的参数名称以及参数值
cookie.setMaxAge(60);
Cookie与HttpSession区别
Cookie将缓存存在客户端的硬盘中,并且只能存String类型的数据,一个Cookie对象只能存一个共享数据
HttpSession将数据存储在服务端的计算器中。可以存储任意类型数据,相当于map集合,可以存储任意数量共享数据
HttpSession代码示例(通过session对象存入数据)
HttpSession session =request.getSession();//向Tomcat服务器索要当前用户的session
session.setAttribute("key",value);
读取数据
//Tomcat 在创建一个HttpSession对象的时候自动为这个对象生成一个唯一的编号,将这个编号保存到Cookie对象,推送到浏览器保存
HttpSession session =request.getSession();//向Tomcat服务器索要当前用户的session
request.getSession(false);//如果当前用户在服务器端存的map是空的,此时tomcat返回null,如果没有false,是空的则创建一个session
session.setAttribute("key",value);
//类似取Url中的参数以及参数值
Enumeration<String> attributeNames = session.getAttributeNames();
while (attributeNames.hasMoreElements()){
//是从map中取得值,不存在空指针异常
String attributeName =attributeNames.nextElement();
String value2=request.getParameter(attributeName);
}
HttpSession销毁时机
Tomcat为每个HttpSession对象设置空闲时间,默认是30分钟,如果当前HttpSession对象空闲达到30分钟,则Tomcat会销毁这个HttpSession对象
这个空闲时间也可以手动设置
在当前网站/web/WEB-INF/web.xml文件下
<session-config>
<session-timeout>5</session-timeout><!--当前网站HttpSession对象空闲时间就是5分钟-->
</session-config>
实现数据共享
HttpServletRequest实现数据共享
在一个OneServlet程序的doget方法中写
request.setAttribute(“key1”,199);//将数据添加到请求作用域对象,做数据共享。
request.getRequestDispatcher("/第二个Servlet程序的别名").forward(request,response);
在另一个TwoServlet程序的doget方法中写
String value=request.getAttribute(“key1”);//从同一个请求作用域对象的到oneservlet写入的共享数据
重定向实现一次请求调用多个servlet程序
location属性不是可以调用另一个页面吗,这里就用location属性,例如:response.sendRedirect("/myweb/two"); 这个请求方式也是【Get】
作用域对象:
在Servlet规范中,两个servlet之间提供数据共享方案的对象
ServletContext: 全局作用域对象
HttpSession: 会话作用域对象
HttpServletResquest:请求作用域对象
监听器
监听器接口ServletContextListener开发规范:
1.选择相应的监听器接口,并实现
2.重写监听器接口生命监听事件处理方法
3.在web.xml文件将监听器接口实现类注册到Http服务器
创建一个OneListener类继承ServletContextListener类
重写这个类里面的两个方法
contextInitialized方法,全局作用域对象被创建被初始化的时候会调用该方法。
contextDestoryed()方法,全局作用域对象被销毁的时候调用该方法
在Tomcat服务器启动的时候会创建全局作用域对象,关闭的时候会销毁全局作用域对象。
OneListener(监听器)继承ServletContextAttributeListener接口
作用:通过这个接口合法的检测全局作用域对象共享数据变化时刻
attributeAdded()//当全局作用域对象增加数据的时候,会调用该方法
attributeRemoved()//当全局作用域对象删除数据的时候,会调用该方法。
attributeReplaced()//全局作用域对象更新数据时调用。
在Servlet程序的doGet方法中
ServletContext application=request.getServletContext();
application.setAttribute("key1",100);//新增共享数据
application.setAttribute("key1",200);//更新共享数据
application.removeAttribute("key1");//删除共享数据
过滤器接口(Filter)
写一个普通的Java类,继承Filter接口,Javax包下面的
重写doFilter类。
在doFilter类中进行你要过滤的操作
然后在web.xml文件里
<!--将过滤器类文件路径交给Tomcat-->
<filter>
<filter-name>oneFilter</filter-name>
<filter-class>类的全限定名称</filter-class>
</filter>
<!--通知tomcat在调用何种文件时需要过滤器拦截-->
<filter-mapping>
<filter-name>oneFilter</filter-name>
<url-pattern>/调哪个文件要过滤</url-pattern>
</filter-mapping>