黑马程序员技术交流社区

标题: JavaEE课程笔记WEB39-Servlet篇 [打印本页]

作者: 小江哥    时间: 2018-8-22 18:51
标题: JavaEE课程笔记WEB39-Servlet篇
本帖最后由 小江哥 于 2018-8-22 18:59 编辑


1.1上次课内容回顾:
[AppleScript] 纯文本查看 复制代码
XML                :
* XML的概述:
    * 什么是XML:可扩展标记语言.
    * XML的作用:作为软件的配置文件,传输和存取数据.
    * XML的使用:
        * XML的基本语法:
            * 标签必须有开始和结束.
            * 必须有根标签
            * 区分大小写.
            * 正确嵌套.
        * XML的文档声明:<?xml version=”1.0” encoding=”UTF-8”?>
        * XML的注释:<!-- 注释 -->
        * XML的元素:
            * 命名规范:不能以数字开头,标签包含字母或数字,不能以xml开头,不能出现空格 冒号.
        * XML的属性:
            * 命名规范:与元素一致.属性必须加引号.
        * XML的特殊字符和CDATA区.
* XML的解析:
    * XML的解析方式有哪些:
        * DOM和SAX:
            * DOM一次性将文档加载到内存,形成树形结构.如果文档过大容易导致内存溢出.方便增删改的操作.
            * SAX边读边解析的方式,如果文档大,不会导致内存溢出,但是不能进行增删改.
    * 常见的解析XML的API:
        * JAXP,JDOM,DOM4J...
    * 使用DOM4J解析XML:
* XML的约束:(了解)
    * XML的约束有哪些区别是什么?
        * DTD和Schame:
            * DTD的语法是自成一体,Schema使用的XML的语法.
            * Schema有比DTD更强大的语义和语法的约束.
            * Schema支持名称空间.
Tomcat
* WEB的相关的内容:
    * 软件架构:
    * 服务器:就是一台电脑,这台电脑上安装了服务器的软件.
    * 常见的WEB服务器:WebSphere,WebLogic,Tomcat,JBoss,IIS,apache...
    * 使用Tomcat:
* 下载和安装Tomcat:
* Tomcat的目录的结构:
    * tomcat/conf:
    * tomcat/webapps:
    * tomcat/logs:
    * tomcat/bin:
* 发布一个web项目到服务器的方式:
    * 一、复制项目到webapps下.
    * 二、修改server.xml,配置<Context path=”” docBase=””/>
    * 三、在conf/Catalina/localhost/xxx.xml 配置<Context docBase=””/>
* 使用STS配置Tomcat:

1.2案例一:使用Servlet完成一个用户登录的案例.
1.2.1需求:
在网站的首页上,登录的链接,点击登录的链接,可以跳转到登录的页面.在登录的页面中输入用户名和密码点击登录的案例.完成登录的功能.
1.2.2分析:
1.2.2.1技术分析:
【HTTP的协议的概述】
[AppleScript] 纯文本查看 复制代码
?HTTP协议的作用:规范浏览器和服务器之间的数据传递.
?HTTP协议的特点:
* 基于请求和响应的模型.
    * 必须先有请求后有响应.
    * 请求和响应必须成对出现.
* 默认的端口号是80.
?HTTP协议的版本:
* 1.0        :每次响应后即刻关闭了连接.
* 1.1        :现在使用.不是每次响应后挂断,等待长时间以后没有请求会挂断.

【HTTP协议的演示】
[AppleScript] 纯文本查看 复制代码
抓包分析:GET方式:
* 请求部分:
GET /day09/demo1-http/demo2.html?name=aaa&age=23 HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
X-HttpWatch-RID: 59176-10011
Referer: http://localhost:8080/day09/demo1-http/demo1.html
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Accept-Encoding: gzip, deflate
Host: localhost:8080
DNT: 1
Connection: Keep-Alive

抓包分析:POST方式:
POST /day09/demo1-http/demo2.html HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
X-HttpWatch-RID: 59176-10031
Referer: http://localhost:8080/day09/demo1-http/demo1.html
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (Windows NT 6.3; 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: 15
DNT: 1
Connection: Keep-Alive
Cache-Control: no-cache

name=bbb&age=38

* 响应部分:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Accept-Ranges: bytes
ETag: W/"145-1461807615933"
Last-Modified: Thu, 28 Apr 2016 01:40:15 GMT
Content-Type: text/html
Content-Length: 145
Date: Thu, 28 Apr 2016 01:43:52 GMT

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>Demo2.html</h1>
</body>
</html>

【HTTP协议的详解】
[AppleScript] 纯文本查看 复制代码
?请求部分
* 请求行
    * 提交方式:
        * 提交方式有很多,常用的GET和POST:
        * GET和POST的区别:
            * GET的提交的参数会显示到地址栏上,而POST不显示.
            * GET往往是有大小限制的,而POST没有大小的限制.
            * GET没有请求体,而POST有请求体.
    * 提交路径:
    * 协议版本:
* 请求头
    * 都是键值对的形式显示的.一般一个key对应一个value,也有个别的是一个key对应多个value.
    * User-Agent                                :代表浏览器的类型. --- 文件下载:下载中文文件:IE使用URLEncodor进行编码,而Firefox使用Base64编码.
    * Referer                                :代表的是网页的来源. --- 防盗链.
    * If-Modified-Since                :通常与响应中的头Last-Modified一起使用查找本地缓存.
* 请求体
    * 就是POST提交方式的提交的参数.
?响应部分
* 响应行:
    * 协议版本
    * 状态码                :
        * 200        :成功
        * 302        :重定向
        * 304        :查找本地缓存
        * 404        :资源不存在
        * 500        :服务器内部错误
    * 状态码描述
* 响应头:键值对,一般一个key对应一个value,也有一个key对应多个value.
    * Last-Modified                        :与请求中的If-Modified-Since一起使用查找本地缓存.
    * Content-Dispostion        :文件下载的使用使用的一个头信息.
    * Location                                :重定向的跳转的路径.
    * Refresh                                :定时刷新/定时跳转.
* 响应体:显示浏览器的页面的内容.

【Servlet的概述】
[AppleScript] 纯文本查看 复制代码
?什么是Servlet:
* 就是一个运行在WEB服务器上的小的Java程序,用来接收和响应从客户端发送过来的请求,通常使用HTTP协议.
* Servlet就是SUN公司提供的一个动态网页开发技术.
?Servlet的作用:
* 用来处理从客户端浏览器发送的请求,并且可以对请求作出响应
?使用Servlet:
* 编写一个类实现Servlet接口.
* 将编写的这个类配置到服务器中.
?Servlet的入门:
* 编写类:
public class ServletDemo1 implements Servlet{

        @Override
        /**
         * 为用户处理请求和响应的方法.
         */
        public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
                res.getWriter().println("Hello Servlet...");
        }
...
}
* 配置:
  <!-- 配置Servlet -->
  <servlet>
          <!-- Servlet的名称 -->
          <servlet-name>test1</servlet-name>
          <!-- SErvlet的全路径 -->
          <servlet-class>com.itheima.a_servlet.ServletDemo1</servlet-class>
  </servlet>

  <!-- Servlet的映射 -->
  <servlet-mapping>
          <!-- Servlet的名称 -->
          <servlet-name>test1</servlet-name>
          <!-- Servlet的访问路径 -->
          <url-pattern>/ServletDemo1</url-pattern>
  </servlet-mapping>
* 访问:
http://localhost:8080/day09/ServletDemo1

【Servlet的实现的关系】
[AppleScript] 纯文本查看 复制代码
Servlet                        :接口
   |
GenericServlet        :通用的Servlet
   |
HttpServlet                :HttpServlet
* 编写一个类继承HttpServlet,重写doGet和doPost方法.
* 配置

1.2.3代码实现
1.2.3.1步骤一:创建数据库和表:
[AppleScript] 纯文本查看 复制代码
create database day09;
use day09;
create table user(
        id int primary key auto_increment,
        username varchar(20),
        password varchar(20),
        nickname varchar(20)
);
insert into user values (null,'aaa','111','小凤');
insert into user values (null,'bbb','111','小童童');

1.2.3.2步骤二:创建包和类:

1.2.3.3步骤三:引入jar包
* mysql的数据库的驱动包
* c3p0连接池的jar包
* dbutils的包
1.2.3.4引入login的页面

1.2.3.5编写Servlet-->Service-->DAO

1.2.4总结:
1.2.4.1Servlet的生命周期:(*****)
[AppleScript] 纯文本查看 复制代码
?生命周期:就是一个对象从创建到销毁的过程.
?Servlet生命周期:Servlet从创建到销毁的过程.
* 何时创建:用户第一次访问Servlet创建Servlet的实例
* 何时销毁:当项目从服务器中移除的时候,或者关闭服务器的时候.
?用户第一次访问Servlet的时候,服务器会创建一个Servlet的实例,那么Servlet中init方法就会执行.任何一次请求服务器都会创建一个新的线程访问Servlet中的service的方法.在service方法内部根据请求的方式的不同调用doXXX的方法.(get请求调用doGet,post请求调用doPost).当Servlet中服务器中移除掉,或者关闭服务器,Servlet的实例就会被销毁,那么destroy方法就会执行.

1.2.4.2Servlet的相关的配置:
【启动时创建Servlet】
Servlet默认是在第一次访问的时候创建的.现在让Servlet在服务器启动的时候创建好.进行对Servlet的配置:
在web.xml中在<servlet></servlet>标签中配置:
* <load-on-startup>2</load-on-startup>  --- 传入正整数,整数越小,被创建的优先级就越高.
【url-pattern的配置】
[AppleScript] 纯文本查看 复制代码
url-pattern配置方式共有三种:
1.完全路径匹配        :以 / 开始                                例如:        /ServletDemo4 , /aaa/ServletDemo5 , /aaa/bbb/ServletDemo6
2.目录匹配                :以 / 开始 需要以 * 结束.        例如: /* ,/aaa/* ,/aaa/bbb/*
3.扩展名匹配                :不能以 / 开始 以 * 开始的. 例如: *.do , *.action
***** 错误的写法        : /*.do

有如下的配置:
  <servlet>
    <servlet-name>ServletDemo4</servlet-name>
    <servlet-class>com.itheima.a_servlet.ServletDemo4</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>ServletDemo4</servlet-name>
    <url-pattern>/ServletDemo4</url-pattern>
  </servlet-mapping>

  <servlet>
    <servlet-name>ServletDemo5</servlet-name>
    <servlet-class>com.itheima.a_servlet.ServletDemo5</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>ServletDemo5</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>

  <servlet>
    <servlet-name>ServletDemo6</servlet-name>
    <servlet-class>com.itheima.a_servlet.ServletDemo6</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>ServletDemo6</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>

如果访问地址:
http://localhost:8080/day09/ServletDemo4                :第一个
http://localhost:8080/day09/aaa.do                                :第二个
***** 完全路径匹配 > 目录匹配 > 扩展名匹配

1.2.4.3开发中的路径的编写:
[AppleScript] 纯文本查看 复制代码
?相对路径:都是需要找位置相对关系.不能以 / 开始的.
* ./ 当前路径  ../上一级目录
* 使用相对路径访问:
    * http://localhost:8080/day09/demo4-url/demo1.html
    * http://localhost:8080/day09/ServletDemo6
?绝对路径:不需要找位置相对关系. 以 / 开始的.
* 绝对路径中分为客户端路径和服务器端路径:
    * 客户端路径一定要加工程名.                /day09/ServletDemo6
    * 服务器端路径不需要加工程名.        /ServletDemo6

1.3案例二:登录成功以后5秒钟跳转到另一个页面.
1.3.1需求:
在登录成功后,页面5秒钟跳转到其他的一个页面.
1.3.2分析:
1.3.2.1技术分析:
【使用Http协议中的Refresh头信息】
Refresh之前已经介绍可以定时页面跳转.需要使用程序设置头信息才可以.
【response中设置响应头】
[AppleScript] 纯文本查看 复制代码
 addHeader(String name,String value);                --- 针对一个key对应多个value的响应头.
    * addDateHeader(String name,long date);
    * addIntHeader(String name,int value);

* setHeader(String name,String value);                --- 针对一个key对应一个value的响应头.
    * setDateHeader(String name,long date);
    * setIntHeader(String name,int value);

例如:头信息: xxx:aaa
    * addHeader(“xxx”,”bbb”);                -->xxx:aaa,bbb
    * setHeader(“xxx”,”bbb”);                -->xxx:bbb

1.3.3代码实现:
[AppleScript] 纯文本查看 复制代码
在登录成功后的代码上,定时的跳转.
public class UserRefreshServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;

        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                try {
                        // 解决向页面输出中文的乱码问题!!!
                        response.setContentType("text/html;charset=UTF-8");
                        // 1.接收表单提交的参数.
                        String username = request.getParameter("username");
                        String password = request.getParameter("password");
                        // 2.封装到实体对象中.
                        User user = new User();
                        user.setUsername(username);
                        user.setPassword(password);
                       
                        // 3.调用业务层处理数据.
                        UserService userService = new UserService();
               
                        User existUser = userService.login(user);
                        // 4.根据处理结果显示信息(页面跳转).
                        if(existUser == null){
                                // 登录失败
                                response.getWriter().println("<h1>登录失败:用户名或密码错误!~</h1>");
                        }else{
                                // 登录成功
                                // response.getWriter().println("Login Success...");
                                response.getWriter().println("<h1>登录成功!您好:"+existUser.getNickname()+"</h1>");
                                response.getWriter().println("<h3>页面将在5秒后跳转!</h3>");
                                response.setHeader("Refresh", "5;url=/day09/demo5-refresh/index.html");
                        }
                } catch (Exception e) {
                        e.printStackTrace();
                }
               
               
               
        }

        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                doGet(request, response);
        }

}

1.3.4总结:
1.3.4.1使用JS控制读秒的效果.
[AppleScript] 纯文本查看 复制代码
<script type="text/javascript">
        var time = 5;
        window.onload = function(){
                setInterval('changeTime()',1000);
        }
       
        function changeTime(){
                time--;
                document.getElementById("s1").innerHTML = time;
        }
</script>

1.4案例三:记录网站的登录成功的人数.
1.4.3代码实现:
[AppleScript] 纯文本查看 复制代码
/**
* 登录代码的Servlet
*/
public class UserCountServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;

        @Override
        public void init() throws ServletException {
                // 初始化一个变量count的值为0.
                int count = 0;
                // 将这个值存入到ServletContext中.
                this.getServletContext().setAttribute("count", count);
        }

        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                try {
                        response.setContentType("text/html;charset=UTF-8");
                        // 1.接收表单提交的参数.
                        String username = request.getParameter("username");
                        String password = request.getParameter("password");
                        // 2.封装到实体对象中.
                        User user = new User();
                        user.setUsername(username);
                        user.setPassword(password);
                       
                        // 3.调用业务层处理数据.
                        UserService userService = new UserService();
               
                        User existUser = userService.login(user);
                        // 4.根据处理结果显示信息(页面跳转).
                        if(existUser == null){
                                // 登录失败
                                response.getWriter().println("<h1>登录失败:用户名或密码错误!</h1>");
                        }else{
                                // 登录成功
                               
                                // 记录次数:
                                int count = (int) this.getServletContext().getAttribute("count");
                                count++;
                                this.getServletContext().setAttribute("count", count);
                               
                                response.getWriter().println("<h1>登录成功:您好:"+existUser.getNickname()+"</h1>");
                                response.getWriter().println("<h3>页面将在5秒后跳转!</h3>");
                                response.setHeader("Refresh", "5;url=/day09/CountServlet");
                        }
                } catch (Exception e) {
                        e.printStackTrace();
                }
               
        }

        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                doGet(request, response);
        }

}

public class CountServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;

        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                // 获得Count的值。
                response.setContentType("text/html;charset=UTF-8");
                int count = (int) this.getServletContext().getAttribute("count");
                response.getWriter().println("<h1>您是第"+count+"位登录成功的用户!</h1>");
        }

        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                doGet(request, response);
        }

}

1.4.4.2ServletContext:重要
[AppleScript] 纯文本查看 复制代码
ServletContext的作用:
* 1.用来获得全局初始化参数.
* 2.用来获得文件的MIME的类型.
* 3.作为域对象存取数据.
ServletContext是一个域对象.
    * 作用范围:整个web工程.
    * 创建:服务器启动的时候,tomcat服务器为每个web项目创建一个单独ServletContext对象.
    * 销毁:服务器关闭的时候,或者项目从服务器中移除的时候.

* 4.用来读取web项目下的文件.






欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2