AJAX和servlet


AJAX和servlet


AJAX的引入

  • 同步交互

    • 首先用户向HTTP服务器提交一个处理请求。接着服务器端接收到请求后,按照预先编写好的程序中的业务逻辑进行处理,比如和数据库服务器进行数据信息交换。最后,服务器对请求进行响应,将结果返回给客户端,返回一个HTML在浏览器中显示,通常会有CSS样式丰富页面的显示效果

      同步交互

  • 异步交互

    • 指发送一个请求,不需要等待返回,随时可以再发送下一个请求,即不需要等待。在部分情况下,我们的项目开发中都会优先选择不需要等待的异步交互方式。将用户请求放入消息队列,并反馈给用户,系统迁移程序已经启动,你可以关闭浏览器了。然后程序再慢慢地去写入数据库去。这就是异步。异步不用等所有操作等做完,就响应用户请求。即先响应用户请求,然后慢慢去写数据库,用户体验较好

      异步交互

原生AJAX

  • 进行异步数据交互,进行少量的数据交互.减少服务器和浏览器的压力.就需要跟服务器进行通信.JS作为一个脚本语言,是无法调用硬件(网卡).在早期时,浏览器的厂商就对JS暴露一套API.这套API就可以让JS与服务器进行通信.

  • 核心方法

    方法 描述
    new XMLHttpRequest() 创建新的 XMLHttpRequest 对象
    abort() 取消当前请求
    getAllResponseHeaders() 返回头部信息
    getResponseHeader() 返回特定的头部信息
    open(method, url, async, user, psw) 规定请求 · method:请求类型 GET 或 POST · url:文件位置 · async:true(异步)或 false(同步) · user:可选的用户名称 · psw:可选的密码
    send() 将请求发送到服务器,用于 GET 请求
    send(string) 将请求发送到服务器,用于 POST 请求
    setRequestHeader() 向要发送的报头添加标签/值对
  • 核心属性

    属性 描述
    onreadystatechange 定义当 readyState 属性发生变化时被调用的函数(事件属性)
    readyState 保存 XMLHttpRequest 的状态。 · 0:请求未初始化 · 1:服务器连接已建立 · 2:请求已收到 · 3:正在处理请求 · 4:请求已完成且响应已就绪
    responseText 以字符串返回响应数据
    responseXML 以 XML 数据返回响应数据
    status 返回请求的状态号 · 200: “OK” · 403: “Forbidden” · 404: “Not Found” 如需完整列表请访问 Http 消息参考手册
    statusText 返回状态文本(比如 “OK” 或 “Not Found”)

AJAX之验证用户是否被占用

  • JS表单验证只能校验格式是否正确,但是无法验证用户名是否已经存在,这个就需要后台程序接受到数据后通过查询才能够完成的,那么这里就非常适用于使用异步方式校验,保证用于数据提交后,业务完成的成功率.提升用户体验感

    测试

  • 前端代码

    <html>
      <head>
        <title>$Title$</title>
      </head>
      <body>
        <form action="" method="post" >
          <p>用户名:<input type="text" name="username" id="username" onblur="checkUsername()"></p>
          <p>密码:<input type="text" name="password" id="password"></p>
          <p id="msg" style="color: red"></p>
          <button>注册</button>
        </form>
          
      <script>
        /*  判断用户是否存在 */
        /**
         *  1. 用户输入用户名
         *  2. 获取用户的用户名  当input 不再被输入时  失去焦点  onblur
         *  3. 发送给服务器  进行检查
         *      1. 创建通信对象
         *      2. 建立连接
         *      3. 发送数据
         *      4. 监听状态
         *      5. 发送请求
         *      6. 获取响应数据
         */
        // 1. 创建通信对象
        var request = new XMLHttpRequest();
        function  checkUsername() {
          //获取用户的用户名
          var username = document.getElementById("username").value;
          //2.建立连接
          request.open("GET","/server?username="+username);
          request.onreadystatechange = stateChange;
          //发送请求
          request.send();
        }
    
        /**
         * 自定义一个函数
         */
        function stateChange() {
          console.log("我执行了")
          //200 请求成功  4  表示请求完成
          if (request.status == 200 && request.readyState == 4){
              var  msg = request.responseText;
              console.log(msg);
              if (msg != 'ok'){
                //将不正常的消息 显示在页面
                document.getElementById("msg").innerText = msg;
              }
          }
        }
      </script>
      </body>
    </html>
    
  • 后端代码

    package com.abc.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    @WebServlet("/server")
    public class ServerServlet extends HttpServlet {
    
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("我执行了!");
            // 获取用户名
            String username = req.getParameter("username");
            // 在ajax请求时  必须使用 响应对象 返回数据
            resp.setCharacterEncoding("UTF-8");
            resp.setContentType("text/html;charset=utf-8");
            PrintWriter writer = resp.getWriter();
            String msg = "ok";
            if (username.equals("admin")){
                msg = "用户名已经存在";
            }
            writer.print(msg);
            writer.flush();
            writer.close();
        }
    }
    

AJAX的本质

  • ajax的本质是进行数据的交互.基于浏览器进行通信的请求,请求后返回的数据给程序自身,浏览器是不会解析和渲染这个数据的.需要程序自身处理数据.

  • 原生Ajax技术存在以下问题:

    1. 浏览器的兼容性问题.特别是IE浏览器.

    2. 整个API相对操作繁琐.主要以下步骤:

      1. 创建请求对象
      2. 建立连接
      3. 监听状态
      4. 发送请求
      5. 处理请求的响应

AJAX数据格式处理

  • ajax只支持文本数据,不支持字节这样的数据的.如果响应的数据是简单的字符串,可以简单的处理,但是如果是复杂的数据.例如:将学生列表数据返回.所以在ajax中,一般返回数据不使用普通的文本,早期时使用XML格式.但是XML耗内存,XML为了保证可读性,保留特殊字符.例如:空格 换行.在传输时是会占用流量.基于这样的情况,后期使用新的字符串格式:JSON : Javascript Object Notation.JS对象简谱.是指使用JS对象的格式组织字符串.

    • JS对象中只有两种格式: { } 和 [ ]

      • 使用{ } 代表对象
      • 使用[ ] 代表数组
      • 一般使用JSON格式返回ajax请求的数据格式.

AJAX结合jquery实现

jQuery的ajax

  • 每次书写AJAX代码比较繁琐 步骤都是一样的,数据回显使用原生js代码也比较繁琐,可以使用jQuery对上述问题进行优化,jQuery不仅仅对dom操作进行了封装 同时也对AJAX提交和回显已经进行了封装,可大大简化AJAX的操作步骤

  • jQuery的ajax使用

    • 在jquery中,jquery主要提供了三个方法进行ajax的请求:
      1. $.ajax(url,option) : ajax方式是jquery 对原生的ajax进行了一个封装,简化了ajax开发,同时也是其他ajax请求方法的基本的方法
      2. $.get(url,data,callbackfunction) : 这个方法基于ajax方法的,但是只支持get请求
      3. $.post(url,data,callbackfunction) : 这个方法也是基于ajax方法的,但是支持post请求.
  • jQuery.ajax()属性详解

    • URL:

      • 要求为String类型的参数,(默认为当前页地址)发送请求的地址。
    • type:

      • 要求为String类型的参数,请求方式(post或get)默认为get。注意其他http请求方法,例如put和delete也可以使用,但仅部分浏览器支持。
    • timeout:

      • 要求为Number类型的参数,设置请求超时时间(毫秒)。此设置将覆盖$.ajaxSetup()方法的全局设置。
    • async:

      • 是否异步
      • 要求为Boolean类型的参数,默认设置为true,所有请求均为异步请求。如果需要发送同步请求,请将此选项设置为false。注意,同步请求将锁住浏览器,用户其他操作必须等待请求完成才可以执行。
    • data:

      • 要求为Object或String类型的参数,发送到服务器的数据。如果已经不是字符串,将自动转换为字符串格式。get请求中将附加在url后。防止这种自动转换,可以查看  processData选项。对象必须为key/value格式,

        例如{foo1:"bar1",foo2:"bar2"}转换为&foo1=bar1&foo2=bar2。如果是数组,JQuery将自动为不同值对应同一个名称。
        例如{foo:["bar1","bar2"]}转换为&foo=bar1&foo=bar2。
        
    • dataType:

      • 期望服务器返回的数据的格式,实际格式以服务器返回的数据格式为准.不同浏览器对该属性处理方式是不一样的.如:chrom会按照该类进行校验.如果不一致,没反应.Firefox浏览器,则会抛出转化失败的异常.

      • 要求为String类型的参数,预期服务器返回的数据类型。如果不指定,JQuery将自动根据http包mime信息返回responseXML或responseText,并作为回调函数参数传递。

      • 可用的类型如下:

        • xml:返回XML文档,可用JQuery处理。

        • html:返回纯文本HTML信息;包含的script标签会在插入DOM时执行。

        • script:返回纯文本JavaScript代码。不会自动缓存结果。除非设置了cache参数。注意在远程请求时(不在同一个域下),所有post请求都将转为get请求。

        • json:返回JSON数据。

        • jsonp:JSONP格式。使用JSONP形式调用函数时,例如myurl?callback=?,JQuery将自动替换后一个“?”为正确的函数名,以执行回调函数。

        • text:返回纯文本字符串。

    • beforeSend:

      • 要求为Function类型的参数,发送请求前可以修改XMLHttpRequest对象的函数,例如添加自定义HTTP头。在beforeSend中如果返回false可以取消本次ajax请求。

        XMLHttpRequest对象是惟一的参数。
        function(XMLHttpRequest){
             this; //调用本次ajax请求时传递的options参数
        }
        
    • complete:

      • 要求为Function类型的参数,请求完成后调用的回调函数(请求成功或失败时均调用)。参数:XMLHttpRequest对象和一个描述成功请求类型的字符串。

        function(XMLHttpRequest, textStatus){
        this; //调用本次ajax请求时传递的options参数
        }
        
    • success:

      • 要求为Function类型的参数,请求成功后调用的回调函数,有两个参数。

      • 由服务器返回,并根据dataType参数进行处理后的数据。

      • 描述状态的字符串。

        function(data, textStatus){
        //data可能是xmlDoc、jsonObj、html、text等等
        this; //调用本次ajax请求时传递的options参数
        }
        
    • error:

      • 要求为Function类型的参数,请求失败时被调用的函数。该函数有3个参数,即XMLHttpRequest对象、错误信息、捕获的错误对象(可选)。ajax事件函数如下:

        function(XMLHttpRequest, textStatus, errorThrown){
        //通常情况下textStatus和errorThrown只有其中一个包含信息
        this; //调用本次ajax请求时传递的options参数
        }
        
    • contentType:

      • 要求为String类型的参数,当发送信息至服务器时,内容编码类型默认为”application/x-www-form-urlencoded”。该默认值适合大多数应用场合。

实例:

前端代码

<html>
<head>
    <title>Title</title>
</head>
<body>
<p id="loading" style="display: none">加载中</p>
<button id="ajaxBtn">ajax</button>
<script src="js/jquery.js"></script>
<script>
    $("#ajaxBtn").click(function () {
        let m = 10;
        let option = {
            type:"post",//请求的方法
            data:{"username":"张三","password":"123"},//请求参数
            //contentType:"application/x-www-form-urlencoded",//表单的 url 编码的方式提交数据  key=value&key2=value
            //contentType:"application/json",//使用JSON格式提交数据
            //timeout:  //请求超时时间  浏览器 默认是不会主动的停止请求 请求没有完成 一般会等待.
            //timeout:3000,//3秒 请求最多3秒  如果超过3秒就主动断开
            async:false,//是否异步的参数  默认是 true 一般如果 请求的数据会参与后面的运算 ,使用同步
            //同步  当整个ajax 都执行完 才能执行之后的代码
            beforeSend:function(){//发送请求前调用的函数
                console.log("beforeSend");
                //展示
                $("#loading").show();

            },
            dataType:"json",//期望服务器返回的数据
            complete:function(rs){//请求完成调用  不论成功或者失败 都会调用
                console.log("xxxxcomplete")
                $("#loading").hide();
            },
            success:function (rs) {//只有当请求完成 且数据正常时才会调用
                console.log("success=============");
                console.log(rs);// rs 返回的数据
                m = m  + 100;
            },
            error:function (req,msg,ex) {  //当服务器发生异常时触发或者网络请求失败出现问题时触发
                console.log(req);// 请求对象
                console.log(msg);//错误信息
                console.log(ex);//异常对象
            }
        };
        $.ajax(/server”,option);
        console.log("m:"+m);
    });
</script>
</body>
</html>

后端代码

package com.abc.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/server")
public class ServerServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("我执行了!");
        //int m = 0;
        //System.out.println(10/m);
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 获取用户名
        String username = req.getParameter("username");
        // 在ajax请求时  必须使用 响应对象 返回数据
        resp.setCharacterEncoding("UTF-8");
        PrintWriter writer = resp.getWriter();
        String msg = "ok";
        if (username.equals("admin")){
            msg = "username is exist";
        }
        msg = "{\"msg\":\"username is exist\"}"; //JSON格式的字符串
        writer.print(msg);
        writer.flush();
        writer.close();
    }
}

jQuery实现AJAX的其他写法

  • $load()

    • jQuery load() 方法是简单但强大的 AJAX 方法,load() 方法从服务器加载数据,并把返回的数据放入被选元素中。默认使用 GET 方式 - 传递附加参数时自动转换为 POST 方式,

    • 语法:

      $(selector).load(URL,data,callback);
      
    • 参数含义:

      url: URL地址
      data:待发送参数。
      callback:载入成功时回调函数。
      
    • 测试:

    • 前端代码

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Title</title>
          <script src="js/jquery-1.11.1-min.js"></script>
      </head>
      <body>
      
      <button id="btn" onclick="sendAjax()">点我发送ajax请求</button>
      
      <script>
          function sendAjax() {
              /* load(url,[data],[callback])
              * url 是跳转的地址,必填
              * data: 跳转到指定地址,并且携带参数,参数格式采用json格式
              * callback : 回调函数(发送请求结束后,等待响应的结果,在回调函数中,可以获取到响应结果)
              *  这个参数是 函数形参数 成功时回调函数
              * */
              $("button").load("/server",{"username":"admin"},function (data) {
                  console.log(data);
              })
          }
      </script>
      </body>
      </html>
      
    • 后端代码

       @WebServlet("/server")
      public class ServerServlet extends HttpServlet {
      
          @Override
          protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              System.out.println("我执行了!");
              //int m = 0;
              //System.out.println(10/m);
              try {
                  Thread.sleep(3000);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
              // 获取用户名
              String username = req.getParameter("username");
              // 在ajax请求时  必须使用 响应对象 返回数据
              resp.setCharacterEncoding("UTF-8");
              PrintWriter writer = resp.getWriter();
              String msg = "ok";
              if (username.equals("admin")){
                  msg = "username is exist";
              }
              msg = "{\"msg\":\"username is exist\"}"; //JSON格式的字符串
              writer.print(msg);
              writer.flush();
              writer.close();
          }
      
      }
      
  • $.get()

    • 这是一个简单的 GET 请求功能以取代复杂 .$.ajax 。请求成功时可调用回调函数。如果需要在出错时执行函数,请使用 $.ajax。只支持异步的请求.都是使用$.ajax的默认属性值.$.get就是type为get

    • 语法为:

      $.get(url,[data],[callback],[type])
      
    • 参数含义:

      url: URL地址
      data:待发送参数。
      callback:载入成功时回调函数。
      type:返回内容格式,xml, html, script, json, text, _default
      
      等价于
      
      $.ajax({
        url: url,
        data: data,
        success: success,
        dataType: dataType
      });
      
    • 测试:

      <html>
      <head>
          <title>Title</title>
      </head>
      <body>
      <div id="content"></div>
      <button id="getBtn">get</button>
      <script src="js/jquery.js"></script>
      <script>
          $("#getBtn").click(function () {
              /**
               * 使用get方法 进行ajax请求
               */
              let param = {'username':'张三','age':123,sex:"男"}
              $.get("/server",param,function (rs) { //function 请求成功时调用的函数  rs 就是返回的数据
                  console.log(rs);
              })
          });
      </script>
      </body>
      </html>
      
  • $.post()

    • 这是一个简单的 POST 请求功能以取代复杂 $.ajax 。请求成功时可调用回调函数。如果需要在出错时执行函数,请使用 $.ajax。

    • 语法为:

      $.post(url,[data],[callback],[type])
      
    • 参数含义:

      url: URL地址
      data:待发送参数。
      callback:载入成功时回调函数。
      type:返回内容格式,xml, html, script, json, text, _default
      
      等价于
      
      $.ajax({
        type: 'POST',
        url: url,
        data: data,
        success: success,
        dataType: dataType
      });
      
    • 测试:

      <html>
      <head>
          <title>Title</title>
      </head>
      <body>
      <div id="content"></div>
      <button id="postBtn">post</button>
      <%-- 引入jquery --%>
      <script src="resources/jquery.js"></script>
      <script>
          $("#postBtn").click(function () {
              /**
               * 使用post方法 进行ajax请求
               */
              let param = {'username':'张三','age':123,sex:"男"}
              $.post("server",param,function (rs) { //function 请求成功时调用的函数  rs 就是返回的数据
                  console.log(rs);
              })
          });
      </script>
      </body>
      </html>
      
  • $.getJSON()

    • JSON是一种较为理想的数据传输格式,它能够很好的融合与JavaScript或其他宿主语言,并且可以被JS直接使用。使用JSON相比传统的通过 GET、POST直接发送“裸体”数据,在结构上更为合理,也更为安全。至于jQuery的getJSON()函数,只是设置了JSON参数的 ajax()函数的一个简化版本。就是将预期的返回的数据类型设置为:JSON.

    • 语法为:

      $.getJSON(
            url,             //请求URL
            [data],          //传参,可选参数
            [callback]       //回调函数,可选参数
          );
      
      等价于
      
      $.ajax({
        url: url,
        data: data,
        success: callback,
        dataType: json
      });
      
    • 仅仅是等效于上述函数,但是除此之外这个函数也是可以跨域使用的,相比get()、post()有一定优势。另外这个函数可以通过把请求url写 成”myurl?callback=X”这种格式,让程序执行回调函数X。

    • 前端代码

      <html>
      <head>
          <title>Title</title>
      </head>
      <body>
      <div id="content"></div>
      <button id="jsonBtn">getJson</button>
      <%-- 引入jquery --%>
      <script src="js/jquery.js"></script>
      <script>
          $("#jsonBtn").click(function () {
              /**
               * 使用post方法 进行ajax请求
               */
              let param = {'username':'张三','age':123,sex:"男"}
              $.getJSON("/server",param,function (rs) { //function 请求成功时调用的函数  rs 就是返回的数据
                  console.log(rs);
              })
          });
      </script>
      </body>
      </html>
      

跨域

  • 由于ajax进行网络通信,js基于浏览器进行网络通信.浏览器出于安全的考虑,浏览器存在一个同源策略。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)

servlet

servlet的作用

  • 获取客户的请求信息

    • Servlet获取客户端的请求信息,基于ServletRequest对象,ServletRequest的子接口: HttpServletRequest。

      HttpServletRequest这个接口包含:客户端的请求参数,客户端的请求头信息。

  • 向客户端做出响应

    • Servlet向客户端做出响应,基于ServletResponse对象,ServletResponse的子接口:HttpServletResponse。

      HttpServletResponse这个接口:获取输出流(字节流,字符流),向客户端返回响应头信息。

servlet的使用方法

  • 创建servlet的三个步骤

    步骤 描述
    导入servlet-api.jar 在tomcat的lib文件夹下也有此jar包,开发过程中为防止报错需要导入,实际运行时需要移除此jar包避免版本冲突。
    自定义类继承HttpServlet 继承后,重写service方法。
    配置虚拟路径 1)可以通过注解配置 2)通过xml形式配置
  • 使用注解形式

    • JavaWeb开发中,Servlet开发配置相对繁琐。在web3.0之后,提供一些简化web配置的数据,@WebServlet就可以取代在web.xml中对servlet的配置

      @WebServlet("/hello")
      public class HelloServlet  extends HttpServlet {
      
         /**
       *  该类中的service方法 被调用了,说明什么?
       *
       *  这个类 它叫servlet  运行在tomcat服务器内部的小程序
       *  证明小程序 运行了
       *
       *  service 方法被调用,service 方法 是普通方法,应当由对象调用
       *  因此,Servlet 对象被创建了。
       *
       *  who  创建了Servlet 对象 ?
       *
       *  Tomcat 服务器 创建的
       *
       *  什么时候创建的? 创建了几个?
       *
       * 只有当第一次通过浏览器访问该Servlet的时候,Servlet对象被创建
       *
       * 一个 单例模式
       *
       *  它怎么创建的 ?
       *
       *   通过反射创建的 ,由于通过反射创建对象由两种方式:
       *   方式一: 通过字节码对象调用newInstance方法   (Class.forName(类的全限定名).newInstance() 前提是类中必须由无参构造)
       *   方式二:通过构造器对象调用newInstance方法   (Class.forName(类的全限定名).getConstructor(参数.class类型).newInstance(参数值))
       *
       *   Servlet 是通过方式一 创建的对象
       *
       *   理由: 第一,在web.xml中告知了servlet的全限定名,所以通过反射 能搞出字节码对象
       *         第二:Servlet 类中,必须提供一个公共的无参构造器,说明采用的方式是第一种
       *
       *
       * Servlet 的请求流程:
       *
       * 1. 当Tomcat服务器启动的时候,去加载web.xml文件
       * 2. 读取web.xml ,就等同于读取了 servlet 的配置
       * 3. 把配置信息获取到之后,存入了map 中,以 servlet 的 映射路径为key , 以 servlet 的全限定名为value
       * 4. 当用通过浏览器发出对servlet 的请求时,就立刻去map中匹配映射路径的内容如果,匹配成功,则意味着,获取到了servlet 的全限定名
       * 5. 通过反射创建servlet 的实例。调用init方法,接着调用service
       *
       */
      
          public HelloServlet(){
              System.out.println("servlet  create  ");
          }
      
          // 当请求方式是get 的时候,进入doGet方法处理
          @Override
          protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      
              System.out.println(“come in”);
       }
      }
      
  • 使用xml形式

    • 向服务器注册这个Servlet,servlet是要提供服务的

      1. 声明/定义servlet类
      2. servlet提供服务访问方式
           public HelloServlet(){
              System.out.println("servlet  create  ");
          }
      
          // 当请求方式是get 的时候,进入doGet方法处理
          @Override
          protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      
              // 生成动态的web 内容 给浏览器客户端
              resp.setContentType("text/html;charset=utf8");
              PrintWriter writer = resp.getWriter();
              writer.println("  这是后台生成的动态web 内容  "+new Date() +" ");
      
       }
      }
      
    • xml配置

      <servlet>
          <servlet-name>HelloServlet</servlet-name>
          <servlet-class>com.bjpowernode.servlet.HelloServlet</servlet-class>
        </servlet>
      <servlet-mapping>
          <servlet-name>HelloServlet</servlet-name>
          <url-pattern>/hello</url-pattern>
      </servlet-mapping>
      
  • 使用注解形式

    • 平时开发中能用注解形式则用注解形式。但如果类是第3方的,由于我们不能去修改第3方的源代码,无法在类上添加注解,则使用xml形式最为合适。例如:后期SpringMVC框架中的核心类DispatcherServlet就是使用的xml形式作为配置

      @WebServlet("/anno")
      public class HelloServlet  extends HttpServlet {
       
          public HelloServlet(){
              System.out.println("servlet  create  ");
          }
      
          // 当请求方式是get 的时候,进入doGet方法处理
          @Override
          protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      
              // 生成动态的web 内容 给浏览器客户端
              // 告知浏览器 ,响应的数据是什么格式 ,用什么编码打开
              // 告知浏览器,发送给浏览器的内容的格式以及使用指定的编码进行解析
              // 这句代码必须要在resp 对象使用之前设置
              resp.setContentType("text/html;charset=utf8");
              PrintWriter writer = resp.getWriter();
              writer.println("  这是后台生成的动态web 内容  "+new Date() +" ");
      
      
          }
      
      }
      

servlet的生命周期

  • Servlet的生命周期,是指Servlet的实例的创建到到销毁的过程。

    // loadOnStartup 它的配置 是为了改变 servlet单例对象的创建时机 (tomcat服务器启动的时候 ,创建servlet对象)
    @WebServlet(value = "/life",loadOnStartup = 1)
    public class LifeCyleServlet extends HttpServlet {
    
         // 我们需要弄清楚 这些生命周期方法何时被调用, 才能确定我们可以利用这些方法,做什么事情
    
        /**
         *  该servlet 是单例模式
         *  只有当第一次通过浏览器访问的时候,才被创建出来
         *  对象被创建出来以后,紧接着会调用init方法,并且init方法只会调用一次
         *
         *  然后调用service方法,而service方法的执行时机是每次发送请求给该servlet
         *  即,service方法, 是用来处理浏览器的每次请求
         *
         *
         *  当服务器正常关闭的时候 ,会调用 destroy方法,非正常关闭服务,则不执行该destroy方法
         *
         *
         *  结论:
         *
         *    init方法只执行一次,我们可以用来初始化一些数据
         *
         *    根据destory 的特点, 不建议把收尾的工作交给该方法处理
         *
         *
         */
    
        public LifeCyleServlet(){
            System.out.println("create  方法");
        }
    
        @Override
        public void init(ServletConfig config) throws ServletException {
            System.out.println("init 方法");
            // 假如 在init 方法中做了一个耗时的操作 耗时 5分钟
    
    
        }
    
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("service 方法");
        }
    
        @Override
        public void destroy() {
            System.out.println("destroy 方法");
        }
    }
    
  • 结论:

    1. init 方法是初始化servlet的方法,默认第一次访问时初始化,且只会执行一次
    2. service 方法是每次访问都会调用,会执行多次
    3. destory 方法,是当服务器正常关闭时调用。执行一次,销毁servlet对象时执行.
    4. init –> service –> destory
  • 注意:

    1. Servlet是单例的模式.一个Servlet只有一个当前类对象.

    2. 默认init只会在第一次访问时,进行调用。如果希望服务器启动时,就希望调用init方法。

      <servlet>
          <servlet-name>servle01</servlet-name>
          <servlet-class>com.powernode.servlet.LifeCyleServlet </servlet-class>
          <!-- 只要大于0 都会在加载完成后调用 -->
          <load-on-startup>1</load-on-startup>
      </servlet>
      
    3. 如果配置了:1则当应用服务器启动时就会调用init方法。

    4. 也可以在注解中使用:@WebServlet(urlPatterns = “/servlet”,loadOnStartup = 1)

servlet的初始化参数

  • 在使用Servlet时,可以配置Servlet的一些初始化参数。为程序提供一些默认的配置。

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
        <servlet>
            <servlet-name>servle01</servlet-name>
            <servlet-class>com.powernode.servlet.ServletLife</servlet-class>
            <!-- servlet 默认的配置参数  是 map结构 -->
         <!--配置初始化参数: 什么是初始化参数? 当对象被创建之后,就可以获取到这些参数-->
    <init-param>
        <param-name>encoding</param-name>
        <param-value>utf-8</param-value>
    </init-param>
            <!-- 以上就是在配置servlet的配置参数 -->
            
            <!-- 只要大于0 都会在加载完成后调用 -->
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>servle01</servlet-name>
            <url-pattern>/servlet01</url-pattern>
        </servlet-mapping>
    </web-app>
    
  • 取值

    public class InitParamServlet extends HttpServlet {
    
     
        public InitParamServlet(){
            System.out.println("create  方法");
        }
    
    
         // ServletConfig 这个类的对象 谁创建的 ? 什么时候创建的?
         //   tomcat 服务器创建的   在调用init 方法之前创建的 
        private  ServletConfig config ;
        /**
         *
         * @param config
         * @throws ServletException
         */
        @Override
        public void init(ServletConfig config) throws ServletException {
            System.out.println("init 方法");
            // 假如 在init 方法中做了一个耗时的操作 耗时 5分钟
            String encoding = config.getInitParameter("encoding");
            System.out.println("encoding = " + encoding);
             this.config = config;
        }
    
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("service 方法");
           // servlet 对象 this
            String encoding = this.getInitParameter("encoding");
            System.out.println("encoding = " + encoding);
        }
    
        @Override
        public void destroy() {
            System.out.println("destroy 方法");
        }
    }
    

servlet的线程安全问题

  • Servlet的init方法只会执行一次,Servlet是单例的。非线程安全的,当出现并发访问,共享数据无法保证一致性.在使用Servlet不要定义共享成员变量.
  • 根据上图,Servlet实例是单例,多线程,servlet是非线程安全的。

servlet相关API

请求信息相关API

  • 在Servlet中,应用服务器将所有的请求信息封装为了HttpServletRequest对象,可以根据HttpServletRequest对象获取请求相关信息.

    请求响应

  • 请求参数

  • 前端

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
       <form action="/request" method="get">
            账号: <input type="text" name="username"/><br/>
            密码:<input type="password" name="password"/> <br/>
            爱好:<input type="checkbox" name="hobby" value="java">java
           <input type="checkbox" name="hobby" value="c">c
           <input type="checkbox" name="hobby" value="c#">c#
           <input type="checkbox" name="hobby" value="android">android <br/>
               <input type="submit" value="登录"/>
       </form> 
    </body>
    </html>
    
  • 后台

    package com.abc.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    @WebServlet("/request")
    public class RequestServlet extends HttpServlet {
         
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
             // 为何 表单中输入中文,接收的时候,是乱码呢? 因为 tomcat 服务器 是 外国人写的,人家默认使用的编码 为 iso8859-1
             // 一定要在方法的第一行 增加编码设置 , 这个编码设置 只针对 post 请求 有效 , get 请求中的乱码 已经被 tomcat服务器高版本(8.0)进行处理
             req.setCharacterEncoding("utf-8");
            System.out.println("--------掌握-----------------------");
            // 获取请求行中的信息
            // 请求方式
            String method = req.getMethod();
            // 请求路径
            String uri = req.getRequestURI();
            StringBuffer url = req.getRequestURL();
            // 协议
            String protocol = req.getProtocol();
            System.out.println("method = " + method);
            System.out.println("uri = " + uri); // 资源的映射路径
            System.out.println("url = " + url); // 完整路径
            System.out.println("protocol = " + protocol);
    
            // 获取请求头的信息
            String accept = req.getHeader("Accept");
            System.out.println("accept = " + accept);
    
            // 获取请求体中的信息
            String username = req.getParameter("username");
            System.out.println("username = " + username);
            String password = req.getParameter("password");
            System.out.println("password = " + password);
    
            // getParamter 方法 只能获取 单个值 的情况
            String hobby = req.getParameter("hobby");
            System.out.println("hobby = " + hobby);
    
            // 获取param多个值
            Map parameterMap = req.getParameterMap();
            parameterMap.forEach((x,y)-> System.out.println(x + Arrays.toString(y)));
    
            System.out.println("---------------不重要----------------------------");
            //  获取一个key 对应有多个值的情况
            String[] hobbies = req.getParameterValues("hobby");
            System.out.println(Arrays.toString(hobbies));
       }
    }
    
  • 设置编码

    • 在Servlet中,Servlet会在第一次获取请求参数时,将网络传输的流数据,解析为map集合。并且默认post请求是按照IOS-8859-1的编码格式进行解析的,以后再次获取请求参数时,直接从map容器中获取请求参数,根据map中key获取,key就是参数名称.

    • 注意

      • 如果要设置字符编码,必须在getParameter之前设置,否则由于只会解析一次,map容器就会存放使用IS0-8859-1转换的编码字符串,即Map中可能就是存放乱码数据。
      //1.修改request对象编码
       request.setCharacterEncoding("UTF-8");
      
  • 获取请求行信息

    • 获取请求的网络相关信息

      package com.abc.servlet;
      
      
      import javax.servlet.ServletException;
      import javax.servlet.annotation.WebServlet;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import java.io.IOException;
      import java.util.*;
      
      
      @WebServlet("/api")
      public class ServletApi extends HttpServlet {
      
          @Override
          protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                      netInfo(req,resp);
      
          }
      
          /**
           *  网络信息相关的API
           * @param req
           * @param resp
           * @throws ServletException
           * @throws IOException
           */
          private void netInfo(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              //获取 网络请求的请求方法
              String method = req.getMethod();//GET  POST  DELETE PUT 等等
              System.out.println("请求方法是:"+method);
              //获取请求协议
              String protocol = req.getProtocol();
              System.out.println("请求协议是:"+protocol);
              //获取请求的URL
              StringBuffer url = req.getRequestURL();// 获取请求的URL
              System.out.println("请求的URL:"+url);
               //获取请求的资源路径
              String uri = req.getRequestURI();
              System.out.println("获取请求的URI:"+uri);
          }
      }
      
    • 请求头信息

      • HttpServletRequest可以获取请求头信息。获取方式主要分为两类:

        1. 根据API提供固有的方法,获取相应的值。
        2. 根据API指定请求头key,获取对应的值。
        package com.abc.servlet;
        
        
        import javax.servlet.ServletException;
        import javax.servlet.annotation.WebServlet;
        import javax.servlet.http.HttpServlet;
        import javax.servlet.http.HttpServletRequest;
        import javax.servlet.http.HttpServletResponse;
        import java.io.IOException;
        import java.util.*;
        
        /**
         * @Description: Servlet API的介绍
         */
        @WebServlet("/api")
        public class ServletApi extends HttpServlet {
        
            @Override
            protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                        headerInfo(req,resp);
        
            }
        
            /**
             * 请求头信息
             * @param req
             * @param resp
             * @throws ServletException
             * @throws IOException
             */
            private void headerInfo(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                //内置的方法
                String contentType = req.getContentType();
                System.out.println("contentType : "+ contentType);
                int contentLength = req.getContentLength();
                System.out.println("contentLength  "+ contentLength);
                // 根据指定的头的key  获取对应的值
                //text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
                String accept = req.getHeader("Accept");
                System.out.println("accept :"+accept);
                //获取所有的请求头name值
                Enumeration headerNames = req.getHeaderNames();
            }
        }
        

响应信息相关的API

  • 设置相应数据编码

    • 设置响应编码,浏览器根据设置的响应编码进行数据解析编码,保证数据避免乱码

      @Override
      protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
          //此时指定的是按照 UTF-8编码 指定将字符转化为字节的编码格式
          resp.setCharacterEncoding("UTF-8");
          //数据时  html的字符串 按照 UTF-8的编码
          resp.setContentType("text/html;charset=UTF-8");
          // tomcat 默认编码 ISO-8859-1
          //文件是 : UTF-8编码
          PrintWriter writer = resp.getWriter();
          writer.print("你好 客户端!!!");
          writer.flush();
          writer.close();
      }
      
  • 获取响应流的信息

    • 在Servlet响应流信息主要分为2类:

      resp.getOutputStream();// 获取字节网络输出流
      resp.getWriter();// 获取字符网络输出流
      
    • 字节流 : 多用于文件的下载,处理一些非字符串数据

    • 字符流 : 多用于处理文本,主要与ajax结合使用

  • 验证码案例

    • 使用Hutool的API生成验证码

    • 先导入Hutool的jar包

    • https://www.hutool.cn/docs/#/

      package com.abc;
      
      import cn.hutool.captcha.CaptchaUtil;
      import cn.hutool.captcha.LineCaptcha;
      
      import javax.servlet.ServletException;
      import javax.servlet.annotation.WebServlet;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import java.io.IOException;
      
      @WebServlet("/img")
      public class Img extends HttpServlet {
          @Override
          protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              //createLineCaptcha(宽度,高度,字符个数,干扰元素个数)
              LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(300, 100, 4, 6);
              //验证码图片中字符串 验证码字符串
              String code = lineCaptcha.getCode();//放在session
              System.out.println(code);
              // 把验证码存入到session
              req.getSession().setAttribute("sessionCode",code);
              //使用响应流 将验证码图片数据输出
              lineCaptcha.write(resp.getOutputStream());
          }
      }
      
  • 前端页面代码

    • 使用ajax验证

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Title</title>
          <script src="js/jquery-3.6.1.min.js"></script>
      </head>
      <body>
      <form id="formId" action="/code" method="post">
          账号:<input type="text" name="username"/><br/>
          密码:<input type="password" name="pwd"/><br/>
          验证码:<input type="text" name="yzm"/>
          <img src="/img" onclick="clickMethod(this)" width="100px"/>
          <br/>
          <span style="color: red" id="tip"></span><br/>
          <input id="butId" type="button" value="登陆">
      </form>
      <script>
          window.onload=function () {
              $("#butId").click(function () {
                  $.post("/code",$("#formId").serialize(),function (data) {
                      if (data.bol) {
                          alert("登录成功")
                      }else {
                          $("#tip").text(data.hint)
                      }
                  })
              })
          }
          function clickMethod(img) {
              img.src="/img?time="+ new Date();
          }
      </script>
      </body>
      </html>
      
  • 后台验证代码

    • 代码

      package com.abc;
      
      import com.alibaba.fastjson.JSON;
      import com.powernode.util.JSONUtil;
      
      import javax.servlet.ServletException;
      import javax.servlet.annotation.WebServlet;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import java.io.IOException;
      @WebServlet("/code")
      public class Code extends HttpServlet {
          @Override
          protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              req.setCharacterEncoding("utf-8");
              resp.setContentType("application/json;charset=utf-8");
              String username = req.getParameter("username");
              String pwd = req.getParameter("pwd");
              String yzm = req.getParameter("yzm");
              JSONUtil jsonUtil = new JSONUtil();
              if (yzm == null || yzm == ""){
                  String s = JSON.toJSONString(jsonUtil.mick("验证码不能为空"));
                  resp.getWriter().write(s);
                  resp.getWriter().flush();
                  return;
              }
              Object sessionCode = req.getSession().getAttribute("sessionCode");
              if (!yzm.equals(sessionCode)) {
                  String s = JSON.toJSONString(jsonUtil.mick("验证码错误"));
                  resp.getWriter().write(s);
                  resp.getWriter().flush();
                  return;
              }
              if (username == null || username == ""){
                  String s = JSON.toJSONString(jsonUtil.mick("账号不能为空"));
                  resp.getWriter().write(s);
                  resp.getWriter().flush();
                  return;
              }
              if (pwd == null || pwd == ""){
                  String s = JSON.toJSONString(jsonUtil.mick("密码不能为空"));
                  resp.getWriter().write(s);
                  resp.getWriter().flush();
                  return;
              }
      
              if (!username.equals("abc") && !pwd.equals("123")){
                  String s = JSON.toJSONString(jsonUtil.mick("账号或密码错误"));
                  resp.getWriter().write(s);
                  resp.getWriter().flush();
                  return;
              }else {
                  String s = JSON.toJSONString(jsonUtil);
                  resp.getWriter().write(s);
                  resp.getWriter().flush();
              }
          }
      }
      
    • 定义一个响应的数据类

      package com.abc.util;
      
      public class JSONUtil {
          private boolean bol = true;
          private String hint ;
      
          public JSONUtil mick(String str){
              this.hint = str;
              this.bol = false;
              return this;
          }
      
          public boolean isBol() {
              return bol;
          }
      
          public String getHint() {
              return hint;
          }
      }
      
    • 效果图

      验证码

  • 文件的上传和下载

    • 文件上传

    • 如果实现文件上传功能 从0到1 去实现,其实是很复杂的, 本质是流的拷贝。难点在读取上传的文件的二进制流,市面上 提供了一个FileUpload 工具类, 来辅助我们完成文件的上传,下载, 今天我们使用更简单的方式,这种方式 只使用与 当前学习的servlet , 文件上传功能 ,已经被 servlet 3.0以上的版本 支持了

    • 前端页面

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Title</title>
      </head>
      <body>
      <form action="/upload" method="post" enctype="multipart/form-data">
      选择文件:<input type="file" name="fileImg"/><br/>
          <input type="submit" value="提交"/>
      </form>
      </body>
      </html>
      
    • 后台代码

      package com.abc.upload;
      
      import jdk.nashorn.internal.ir.CallNode;
      
      import javax.servlet.ServletException;
      import javax.servlet.annotation.MultipartConfig;
      import javax.servlet.annotation.WebServlet;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import javax.servlet.http.Part;
      import java.io.IOException;
      import java.util.UUID;
      
      @MultipartConfig
      @WebServlet("/upload")
      public class FileUpload extends HttpServlet {
          @Override
          protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              resp.setContentType("text/html;charset=utf-8");
              //使用getPart()方法接收文件
              Part fileImg = req.getPart("fileImg");
      
              //获取文件的名字
              String fileName = fileImg.getSubmittedFileName();
      //        System.out.println(fileName);
      
              //获取文件的大小
              long size = fileImg.getSize();
      //        System.out.println(size);
      
              //获取文件的格式
              String contentType = fileImg.getContentType();
      //        System.out.println(contentType);
      
              //文件上传路径
              String partPath = "D:\\course11\\04-javaweb\\03-ajax&servlet\\uploadproject\\web\\upload";
      
              //获取文件的后缀名
              String substring = fileName.substring(fileName.lastIndexOf("."));
      
              //随机生成一个文件名
              String newImgName = UUID.randomUUID().toString();
      
              //生成新的文件名
              String name = newImgName + "." + substring;
      
              //上传文件
              fileImg.write(partPath + "/" + name);
          }
      }
      
  • 文件下载

    • 前端页面

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Title</title>
      </head>
      <body>
      点击下载资源:<a href="/download?filename=1.jpg">1.jpg</a>
      </body>
      </html>
      
    • 后台代码

      package com.powernode.servlet;
      
      import com.sun.javaws.HtmlOptions;
      
      import javax.servlet.ServletException;
      import javax.servlet.ServletOutputStream;
      import javax.servlet.annotation.WebServlet;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import java.io.File;
      import java.io.FileInputStream;
      import java.io.IOException;
      import java.net.URLEncoder;
      
      @WebServlet("/download")
      public class Download extends HttpServlet {
          @Override
          protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              //获取下载文件的名称
              String filename = req.getParameter("filename");
              //获取下载文件的文件夹的路径
              String path = "D:\\course11\\04-javaweb\\03-ajax&servlet\\downloadpeoject\\web\\download";
              //获取下载文件的路径
              String filePath = path + "/" + filename;
      
              // URLEncoder.encode(fileName,"utf-8") 把编码记性设置 , 必须要在 设置头信息的 同时 去修改编码
              //  通过header 修改了 下载的文件的名称  如果不设置 header 它会使用默认名称 来作为下载文件的名称 (download)
              resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(filename,"utf-8") );
      
              //下载的本质是copy,利用流来进行下载
              //创建文件输入流
              FileInputStream fileInputStream = new FileInputStream(new File(filePath));
      
              //使用浏览器的默认下载路径
              ServletOutputStream outputStream = resp.getOutputStream();
              int len = 0;
              byte[] bytes = new byte[1024];
              while ((len = fileInputStream.read(bytes)) != -1){
                  outputStream.write(bytes,0,len);
                  outputStream.flush();
              }
              outputStream.close();
              fileInputStream.close();
      
          }
      }
      

请求转发和重定向

请求转发

  • 浏览器发出一个请求,由一个AServlet 进行接收处理,最后没有处理完毕,然后它(AServlet) 转交交给 (BServlet) 进行处理,把 AServlet 转交给 BServlet 这个动作叫请求转发

  • API:

    request.getRequestDispatcher("跳转的路径").forward(request,response);
    
  • 请求转发的特点

    1. 只发送一次请求
    2. 响应到浏览器的结果是一最后的servlet 为准
    3. 可以共享地址栏中的参数信息
    4. 可以访问 WEB-INF 下面的资源
    5. 不可以访问 站外资源 (不能跨域)
    6. 可以共享request 域对象的数据

重定向

  • 浏览器发送请求到 a servlet ,然后 a servlet 完成一部分需求,告知浏览器,b servlet 能完成剩余的需求,因此,浏览器 会 再一次发送请求 到 b servlet 最终 完成了 整个请求

  • API:

    response.sendRedirect("跳转路径")
    
  • 重定向的特点

    1. 发送了多次请求(至少两次)
    2. 不能共享地址栏中的参数信息
    3. 最终显示的结果 以最后一个Servlet (和请求转发的特点一样)
    4. 不能访问WEB-INF 下面的资源
    5. 可以访问站外资源
    6. 不可以共享request 域对象中的数据

请求转发和重定向的选择

  1. 如果需要访问WEB-INF下面的资源 ,则 必须使用 请求转发

  2. 如果需要访问站外资源,则必须使用 重定向

  3. 其它,则可以 随便使用

    • 一般是这样用的:如果地址栏的地址 应该 发生变化,则使用重定向

    • 如果地址栏的地址,可以 不用变化,也能理解 则使用请求转发

转发与重定向的应用场景

  • 应用场景:登录、购物车结算采用重定向,其他一律采用转发。

servlet的三大作用域

域对象的理解

  • 域对象 : 存储数据的容器
  • Servlet 中 有 4 个 能存储数据的 容器 (域对象)
  • PageContext Request Session ServletContext (Application)
  • 容器(域对象)的容量大小 是一样的,不同容器(域对象)的区别
    • Request : 一次请求中有效 (只在请求转发中使用)
    • Session: 一次会话中有效 (从浏览器打开,到关闭 称为一次会话)
    • ServletContext (Application): 当前应用 (项目开启 到 关闭)
  • 共同操作域对象 的API:
    • 存:setAttribute(key,value)
    • 取:getAttribute(key)
  • 获取Reqeust 对象 : 直接使用
  • 获取Session 对象 : request.getSession():
  • 获取ServletContext 对象: request.getServletContext(): (上下文)

作用域的选择

  • 能用小的 绝不用大的,够用原则:

  • Request < session < ServletContext


文章作者: 勾魂大猩猩
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 勾魂大猩猩 !
  目录