JavaWeb

Java Web应用由一组Servlet,HTML页面,类,以及其他可以被绑定的资源构成。它可以在各种供应商提供的实现Servlet规范的Servlet容器中运行。

包含如下内容:

  • Servlet
  • JSP
  • 实用类
  • 静态文档如HTML,图片等
  • 描述Web应用的信息(web.xml)

Servlet与Servlet容器

image-20220118103058727

image-20220118103504643

web程序的目录结构

image-20220118130340097

Servlet

image-20220118133518933

Servlet 容器

管理Servlet的创建、使用、销毁

运行Servlet,JSP,Filter等的软件环境

可以用来创建Servlet,并调用Servlet的相关生命周期方法

http://c.biancheng.net/servlet2/container.html

现在的Servlet容器相当于Web服务器+Web容器

<servlet-mapping>
    <servlet-name>demo1</servlet-name>
    <url-pattern>/demo1</url-pattern>
</servlet-mapping>
执行原理
  1. 当服务器接收到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet资源路径
  2. 查找web.xml文件,是否有对应的标签体内容
  3. 如果有,则找到对应的全类名
  4. tomcat会将字节码文件加载进内存,并且创建其对象
  5. 调用其方法
生命周期
  1. 被创建:执行init方法,只执行一次

    • Servlet什么时候被创建?

      默认情况下,第一次被访问时,被创建

      可以配置执行Servlet的创建时机

      <servlet>
              <servlet-name>demo2</servlet-name>
              <servlet-class>Demo2</servlet-class>
                  
      <!--        指定Servlet的创建时机-->
      <!--        1. 第一次被访问时,创建-->
      <!--        <load-on-startup>的值为负数-->
      <!--        2. 服务器启动时,创建-->
      <!--        <load-on-startup>的值为0或正整数-->
                  
              <load-on-startup>5</load-on-startup>
          </servlet>
      
    • Servlet的init方法,只执行一次,说明一个Servlet在内存中只存在一个对象,Servlet是单例的
      • 多个用户同时访问时,可能存在线程安全问题

      • 解决:尽量不要在Servlet中定义成员变量,即使定义了成员变量,也不要对其修改值

  2. 提供服务:执行service方法,执行多次

    每次访问Servlet时,Service方法都会被调用一次

  3. 被销毁:执行destroy方法,只执行一次

    • Servlet被销毁时执行,服务器关闭时,Servlet被销毁

    • 只有服务器正常关闭时,才会执行destroy方法

    • destroy方法在Servlet被销毁之前执行,一般用于释放资源

相关配置

urlpartten:Servlet访问路径

  1. 一个Servlet可以定义多个访问路径:

    @WebServlet({"/d4","/dd4","/ddd4"})

  2. 路径定义规则:

    1. /xxx:路径匹配
    2. /xxx/xxx:多层路径,目录结构
    3. *.do:扩展名匹配

HTTP

概念

Hyper Text Transfer Protocol 超文本传输协议

传输协议:定义了,客户端和服务器端通信时,发送数据的格式

特点:

  1. 基于TCP/IP的高级协议
  2. 默认端口号:8080
  3. 基于请求/响应模式的:一次请求对应一次响应
  4. 无状态的:每次请求之间相互独立,不能交互数据

历史版本:

1.0:每一次请求响应都会建立新的连接

1.1:复用连接

响应消息数据格式
  1. 响应行

    组成:协议/版本 响应状态码 状态码描述

    响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态

    1. 都是3位数字

    2. 分类:

      1. 1XX:服务器接受客户端信息,但没有接收完成,等待一段时间后,发送1XX状态码

      2. 2XX:成功。代表:200

      3. 3XX:重定向。代表:302(重定向),304(访问缓存)

      4. 4XX:客户端错误。

        代表:

        ​ 404(请求路径没有对应的资源)

        ​ 405(请求方式没有对应的doXxx方法)

      5. 5XX:服务器端错误。代表:500(服务器内部出现异常)

  2. 响应头

    1. 格式:头名称:值

    2. 常见的响应头:

      1. Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式

      2. Content-disposition:服务器告诉客户端以什么格式打开响应体数据

        值:

        in-line:默认值,在当前页面内打开

        attachment;filename=xxx:以附件形式打开响应体,文件下载

  3. 响应空行

  4. 响应体:传输的数据

Response

功能:设置响应消息

  1. 设置响应行
    1. 格式:HTTP/1.1 200 ok
    2. 设置状态码:setStatus(int sc)
  2. 设置响应头:setHeader(String name, String value)
  3. 设置响应体
    1. 获取输出流
      1. 字符输出流:PrintWriter getWriter()
      2. 字节输出流:ServletOutputStream getOutputStream()
    2. 使用输出流,将数据输出到客户端浏览器

※ 案例:

  1. 完成重定向:访问/responseDemo1,会自动跳转到/responseDemo2

    第一种

    response.setStatus(302);
    response.setHeader("location","/day15/responseDemo2");
    

    第二种

    response.sendRedirect("/day15/responseDemo2");
    

    重定向(redirect)的特点:

    1. 地址栏发生变化
    2. 重定向可以访问其他站点(服务器)的资源
    3. 重定向是两次请求,不能使用request对象来共享数据

    转发(forward)的特点:

    1. 转发地址栏路径不变
    2. 转发只能访问当前服务器下的资源
    3. 转发是一次请求,可以使用request对象来共享数据
    request.getRequestDispatcher("/responseDemo2").forward(request, response);
    

    路径写法:

    1. 路径分类

      1. 相对路径:通过相对路径不能确定唯一资源

        不以/开头,以.开头的路径

        ./:当前目录

        ../:后退一级目录

      2. 绝对路径:通过绝对路径可以确定唯一资源

        以/开头的路径

        给客户端浏览器使用:需要加虚拟目录

        //动态获取虚拟目录
        String contextPath = request.getContextPath();
        

        给服务器使用:不需要加虚拟目录

        转发路径

  2. 服务器输出字符数据到浏览器

    //获取流对象前,设置流的默认编码
    response.setCharacterEncoding("GBK");
    //告诉浏览器,服务器发送的消息体数据的编码,建议浏览器使用该编码解码
    response.setHeader("content-type","text/html;charset=utf-8");
    //简单的形式,设置编码
    response.setContentType("text/html;charset=utf-8");
    //获取字符输出流
    PrintWriter pw = response.getWriter();
    //输出数据
    pw.write("hello");
    
  3. 服务器输出字节数据到浏览器

    //设置解码类型
    response.setContentType("text/html;charset=utf-8");
    //获取字节输出流
    ServletOutputStream sos = response.getOutputStream();
    //输出数据
    sos.write("hello".getBytes("utf-8"));
    
请求消息数据格式
  1. 请求行

    请求方式 请求url 请求协议/版本
    GET	/login.html HTTP/1.1
    
    请求方式

    HTTP协议中有7种请求方式,常用的有两种

    • GET
      1. 请求参数在请求行中,在url后
      2. 请求的url长度有限制
      3. 不太安全
    • POST
      1. 请求参数在请求体中
      2. 请求的url长度没有限制
      3. 相对安全
  2. 请求头

    请求头名称: 请求头值
    
    常见的请求头
    1. User-Agent:

      浏览器告诉服务器,我访问你使用的浏览器版本信息。可以用来在服务器端获取该头的信息,解决浏览器的兼容性问题

    2. Referer:http://localhost/login.html

      告诉服务器,当前请求从哪里来

      作用:

      1. 防盗链
      2. 统计工作
  3. 请求空行

    空行
    
  4. 请求体(正文)

    封装POST请求消息的请求参数的

Request
  1. request对象和response对象的原理

    request和response对象是由服务器创建的,我们来使用它们

    request对象是来获取请求消息的,

    response对象是来设置响应消息的

    image-20220121113948019

  2. request对象继承体系结构

    ServletRequest -- 接口

    ​ | 继承

    HttpServletRequest -- 接口

    ​ | 实现

    org.apache.catalina.connector.RequestFacade 类(tomcat)

  3. request功能

    1. 获取请求消息数据

      • 获取请求行数据

        GET /day14/demo1?name=ethic HTTP/1.1

        方法:

        1. 获取请求方式:GET

          String getMethod()
          
        2. 获取虚拟目录:/day14 【重要!】

          String getContextPath()
          
        3. 获取Servlet路径:/demo1

          String getServletPath()
          
        4. 获取get方式请求参数:name=ethic

          String getQueryString()
          
        5. 获取请求URI:/day14/demo1【重要!】

          String getRequestURI()
          //得到/day14/demo1
          StringBuffer getRequestURL()
          //得到http://localhost/day14/demo1
              
          URL:统一资源定位符
          URI:统一资源标识符
          
        6. 获取协议及版本:HTTP/1.1

          String getProtocol()
          
        7. 获取客户机的IP地址:

          String getRemoteAddr()
          
      • 获取请求头数据

        1. 通过请求头的名称获取请求头的值【重要!】

          String getHeader(String name)
          
        2. 获取所有请求头名称

          Enumeration<String> getHeaderNames()
          
      • 获取请求体数据

        请求体:只有POST请求方式才有请求体,在请求体中封装了POST请求的请求参数

        步骤:

        1. 获取流对象

          //获取字符输入流,只能操作字符数据
          BufferedReader getReader()
          //获取字节输入流,可以操作所有类型的数据
          ServletInputStream getInputStream()
          
        2. 从流对象中拿数据

    2. 其他功能

      • 获取请求参数通用方式(GET和POST都可以)

        1. 根据参数名称获取参数值

          String getParameter(String name)
          
        2. 根据参数名称获取参数值的数组

          String[] getParameterValues(String name)
          
        3. 获取所有请求的参数名称

          getParameterNames()
          
        4. 获取所有参数的map集合

          Map<String,String[]> getParameterMap()
          
        5. 中文乱码问题:

          get方式:tomcat 8 已经将get方式乱码问题解决了

          post方式:在获取参数前,设置request的编码

          request.setCharacterEncoding("utf-8")
          
      • 请求转发:一种在服务器内部的资源跳转方式

        1. 通过request对象获取请求转发器对象

          RequestDispatcher getRequestDispatcher(String path)
          
        2. 使用RequestDispatcher对象来进行转发

          forward(ServletRequest request, ServletResponse response)
          
        3. 特点:

          浏览器地址栏路径不发生变化

          只能转发到当前服务器内部资源中

          转发是一次请求

      • 共享数据

        域对象:

        一个有作用范围的对象,可以在范围内共享数据

        request域:

        代表一次请求的范围,一般用于请求转发的多个资源***享数据

        方法:

        1. 存储数据

          void setAttribute(String name, Object obj)
          
        2. 通过键获取值

          Object getAttribute(String name)
          
        3. 通过键移除键值对

          void removeAttribute(String name)
          
      • 获取ServletContext

        ServletContext getServletContext()
        
ServletContext对象

概念:代表整个web应用,可以和程序的容器(服务器)来通信

功能
  1. 获取MIME类型

    1. MIME类型:在互联网通信过程中定义的一种文件数据类型

    2. 格式:大类型/小类型 text/html image/jpeg

    3. 获取:

      String getMimeType(String file)
      
  2. 域对象:共享数据

    1. setAttribute(String name, Object value)
    2. getAttribute(String name)
    3. removeAttribute(String name)
    

    ServletContext对象范围:所有用户所有请求的数据

  3. 获取文件的真实(服务器)路径

    方法:String getRealPath(String path)

    //获取文件的服务器路径
    String realPath = context.getRealPath("/b.txt");
    //web目录下资源访问
    File file = new File(realPath);
    String realPath = context.getRealPath("/WEB-INF/c.txt");//WEB-INF目录下的资源访问
    String realPath = context.getRealPath("/WEB-INF/classes/a.txt");//src目录下的资源访问
    

    文件下载需求:

    1. 页面显示超链接
    2. 点击超链接后弹出下载提示框
    3. 完成图片文件下载

    步骤:

    1. 定义页面,编辑超链接href属性,指向Servlet,传递资源名称filename

    2. 定义Servlet

      1. 获取文件名称
      2. 使用字节输入流加载文件进内存
      3. 指定response的响应头:
      content-disposition:attachment;filename=xxx
      
      1. 将数据写出到response输出流

    代码实现:

    //1.获取请求参数,文件名称
    String filename = request.getParameter("filename");
    //2.使用字节输入流加载文件进内存
    //2.1找到文件服务器路径
    ServletContext servletContext = this.getServletContext();
    String realPath = servletContext.getRealPath("/img/" + filename);
    //2.2用字节流关联
    FileInputStream fis = new FileInputStream(realPath);
    //3.设置response的响应头
    //3.1设置响应头类型:content-type
    String mimeType = servletContent.getMimeType(filename);
    response.setHeader("content-type",mimeType);
    //3.2设置响应头打开方式:content-disposition
    response.setHeader("content-disposition","attachment;filename="+filename);
    
    //解决中文文件名问题
    //1.获取user-agent请求头
    String agent = request.getHeader("user-agent");
    //2.使用工具类方法编码文件名即可
    filename = DownLoadUtils.getFileName(agent, filename);
    
    //4.将输入流的数据写出到输出流中
    ServletOutputStream sos = response.getOutputStream();
    byte[] buff = new byte[1024*8];
    int len = 0;
    while((len = fis.read(buff)) != -1){
    	sos.write(buff,0,len);
    }
    fis.close();
    
获取
  1. 通过request对象获取

    request.getServletContext();
    
  2. 通过HttpServlet获取

    this.getServletContext();
    
会话技术
  1. 会话:一次会话中包含多次请求和响应

    一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止

  2. 功能:在一次会话的范围内的多次请求间共享数据

  3. 方式:

    1. 客户端会话技术:Cookie
    2. 服务器端会话技术:Session
Cookie
  1. 概念:客户端会话技术,将数据保存到客户端

  2. 快速入门

    使用步骤

    1. 创建Cookie对象,绑定数据

      new Cookie(String name, String value)
      
    2. 发送Cookie对象

      response.addCookie(Cookie cookie)
      
    3. 获取Cookie,拿到数据

      Cookie[] request.getCookies()
      
  3. 实现原理

    基于响应头set-cookie和请求头cookie实现

  4. Cookie的特点和作用

    1. cookie存储数据在客户端浏览器
    2. 浏览器对于单个cookie的大小有限制(4kb),以及对于同一个域名下的总cookie数量也有限制(20个)
    3. cookie一般用于存储少量的不太敏感的数据,在不登录的情况下,完成服务器对客户端的身份识别
  5. Cookie的细节

    1. 一次可不可以发送多个cookie?

      可以创建多个Cookie对象,使用response调用多次addCookie方法发送cookie即可

    2. cookie在浏览器中保存多长时间?

      1. 默认情况下,当浏览器关闭后,Cookie数据被销毁

      2. 持久化存储

        setMaxAge(int seconds)

        1. 正数:将Cookie数据写到硬盘的文件中,持久化存储。cookie存活时间。
        2. 负数:默认值
        3. 零:删除cookie信息
        c1.setMaxAge(30);
        //将cookie持久化到硬盘,30秒后自动删除cookie文件
        
    3. cookie能不能存中文?

      tomcat 8之前不可以,需要转码,之后可以

    4. cookie共享问题?

      1. 假设在一个tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享?

        默认情况下不能。setPath(String path):设置cookie的获取范围。默认情况下不能共享。如果要共享,可以把path设置成"/"

      2. 不同的tomcat服务器间cookie共享问题?

        setDomain(String path):如果设置一级域名相同,那么多个服务器之间cookie可以共享

        setDomain(".baidu.com"),那么tieba.baidu.com和news.baidu.com中cookie可以共享

  6. 案例:记住上一次访问时间

    1. 需求

      1. 访问一个Servlet,如果是第一次访问,提示:您好,欢迎您首次访问
      2. 如果不是第一次访问,提示:欢迎回来,您上次访问时间是:显示时间字符串
    2. 分析

      1. 可以采用cookie来完成
      2. 在服务器中的Servlet判断是否有一个名为lastTime的cookie
        1. 有:不是第一次访问
          1. 响应数据:欢迎回来,您上次的访问时间是2022年1月25日10:05:59
          2. 写回Cookie:lastTime=2022年1月25日10:05:59
        2. 没有:是第一次访问
          1. 响应数据:您好,欢迎您首次访问
          2. 写回Cookie:lastTime=2022年1月25日10:05:59
    3. 代码实现

      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              //设置响应的消息体的数据格式以及编码
              response.setContentType("text/html;charset=utf-8");
      
              //1.获取所有Cookie
              Cookie[] cookies = request.getCookies();
              boolean flag = false;//没有cookie为lastTime
              //2.遍历cookie数组
              if(cookies != null && cookies.length > 0){
                  for (Cookie cookie : cookies) {
                      //3.获取cookie的名称
                      String name = cookie.getName();
                      //4.判断名称是否是lastTime
                      if("lastTime".equals(name)){
                          //有该cookie,不是第一次访问
                          flag = true;//有lastTime的cookie
      
                          //设置Cookie的value
                          //获取当前时间的字符串,重新设置Cookie的值,重新发送cookie
                          Date date = new Date();
                          SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
                          String str_date = sdf.format(date);
                          cookie.setValue(str_date);
                          //URL编码
                          str_date = URLEncoder.encode(str_date,"utf-8");
                          cookie.setValue(str_date);
                          //设置cookie的存活时间
                          cookie.setMaxAge(60 * 60 * 24 * 30);
                          response.addCookie(cookie);
      
                          //响应数据
                          //获取Cookie的value,时间
                          String value = cookie.getValue();
                          //URL解码
                          value = URLDecoder.decode(value, "utf-8");
                          response.getWriter().write("<h1>欢迎回来,您上次访问时间为:"+value+"</h1>");
                      }
                  }
              }
      
              if(cookies == null || cookies.length == 0 || flag == false){
                  //设置Cookie的value
                  //获取当前时间的字符串,重新设置Cookie的值,重新发送cookie
                  Date date = new Date();
                  SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
                  //URL编码
                  String strDate = URLEncoder.encode(sdf.format(date),"utf-8");
                  Cookie cookie = new Cookie("lastTime",strDate);
                  //设置cookie的存活时间
                  cookie.setMaxAge(60 * 60 * 24 * 30);
                  response.addCookie(cookie);
      
                  response.getWriter().write("<h1>您好,欢迎您首次访问</h1>");
              }
          }
      
Session
  1. 概念:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中

  2. 快速入门:

    1. 获取HttpSession对象

      HttpSession session = request.getSession();
      
    2. 使用HttpSession对象

    Object getAttribute(String name)
    void setAttribute(String name, Object value)
    void removeAttribute(String name)
    
  3. 原理:Session的实现是依赖于Cookie的

  4. 细节:

    1. 客户端关闭后,服务器不关闭,两次获取session是否为同一个?

      默认情况下,不是

      如果需要相同,则可以创建Cookie,键为JSESSIONID,设置最大存活时间,让cookie持久化保存

      Cookie c = new Cookie("JSESSIONID",session.getId());
      c.setMaxAge(60*60);
      response.addCookie(c);
      
    2. 客户端不关闭,服务器关闭后,两次获取的session是同一个吗?

      不是同一个,但是要确保数据不丢失

      • session的钝化(序列化)

        在服务器正常关闭之前,将session对象序列化到硬盘上

      • session的活化(反序列化)

        在服务器启动后,将session文件转化为内存中的session对象即可

    3. session什么时候被销毁?

      1. 服务器关闭

      2. session对象调用invalidate()

      3. session默认失效时间是30分钟

        选择性配置修改

        <session-config>
        	<session-timeout>30</session-timeout>
        </session-config>
        
  5. session的特点

    session用于存储一次会话的多次请求的数据,存在服务器端

    session可以存储任意类型,任意大小的数据

    session与cookie的区别:

    1. session存储数据在服务器端,cookie在客户端
    2. session没有数据大小限制,cookie有
    3. session数据安全,cookie相对来说不安全
  6. 案例:验证码

    1. 案例需求:
      1. 访问带有验证码的登录页面login.jsp
      2. 用户输入用户名、密码以及验证码
        1. 如果用户名和密码输入有误,跳转登录页面,提示:用户名或密码错误
        2. 如果验证码输入有误,跳转登录页面,提示:验证码错误
        3. 如果全部输入正确,则跳转到主页success.jsp,显示:用户名 欢迎你
JSP
  1. 概念

    Java Server Pages:java服务器端页面

    可以理解为一个特殊的页面,其中既可以定义html标签,又可以定义java代码

  2. 原理

    JSP本质上就是一个Servlet

  3. 指令

    作用:用于配置JSP页面,导入资源文件

    格式:

    <%@ 指令名称 属性名1=属性值1 属性名2=属性值2 ...%>
    

    指令名称

    1. page: 配置JSP页面的

      • contentType:等同于response.setContentType()

      设置响应体的mime类型以及字符集

      设置当前jsp页面的编码

      (只能是高级的IDE才能生效,如果使用低级工具,需要设置pageEncoding属性设置当前页面的字符集)

      • import:导包

      • errorPage:当前页面发生异常后,会自动跳转到指定的错误页面

      • isErrorPage:标识当前是否是错误页面

        true:是,可以使用内置对象exception

        false:否,默认值,不可以使用内置对象exception

    2. include:页面包含的,导入页面的资源文件

      <%@include file="top.jsp"%>
      
    3. taglib: 导入资源

      <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
      

      prefix:前缀,自定义的

    <% 代码 %>
    //定义的java代码在service方法中
    //service方法中可以定义什么,里面就可以定义什么
    <%! 代码 %>
    //定义的java代码,在jsp转换后的java类的成员位置
    <%= 代码 %>
    //定义的java代码会输出到页面上
    
  4. 注释

    1. html注释:

      只能注释html代码片段

      <%-- --%> 可以注释所有

  5. JSP的内置对象

    在jsp页面中不需要获取和创建,可以直接使用的对象

    jsp一共有9个内置对象

    1. request

      真实类型:HttpServletRequest

      一次请求访问的多个资源(转发)

    2. response

      真实类型:HttpServletResponse

      响应对象

    3. out

      真实类型:JspWriter

      字符输出流对象。可以将数据输出到页面上。和response.getWriter()类似

      response.getWriter()和out.write()的区别:

      在tomcat服务器真正给客户端做出响应之前,会先找response缓冲区数据,再找out缓冲区数据

      response.getWriter()数据输出永远在out.write()之前

    4. pageContext

      真实类型:PageContext

      当前页面共享数据,还可以获取其他八个内置对象

    5. session

      真实类型:HttpSession

      一次会话的多个请求间

    6. application

      真实类型:ServletContext

      所有用户间共享数据

    7. page

      真实类型:Object

      当前页面(Servlet)的对象,this

    8. config

      真实类型:ServletConfig

      Servlet的配置对象

    9. exception

      真实类型:Throwable

      异常对象

MVC开发模式

为了简化JSP出现的

M:Model,模型(JavaBean)

完成具体的业务操作,如:查询数据库、封装对象

V:View,视图(JSP)

展示数据

C:Controller,控制器(Servlet)

获取用户的输入,调用模型,将数据交给视图进行展示

优点:

  1. 耦合性低,方便维护,利于分工协作
  2. 重用性高

缺点:

项目架构变得复杂

EL表达式
  1. 概念:Expression Language 表达式语言

  2. 作用:替换和简化jsp页面中java代码的编写

  3. 语法:${表达式}

  4. 注意:

    jsp默认支持el表达式,如果要忽略el表达式

    1. 设置jsp中page指令中:isELIgnored="true"忽略当前jsp页面中所有的el表达式
    2. \${表达式}:忽略当前这个el表达式
  5. 使用:

    1. 运算

      1. 算数运算符:+ - * / (div) % (mod)

      2. 比较运算符:> < >= <= == !=

      3. 逻辑运算符:&&(and) ||(or) !(not)

      4. 空运算符:empty

        功能:用于判断字符串、集合、数组对象是否为null并且长度是否为0

        ${empty list}:判断字符串、集合、数组对象是否为null或者长度为0

        ${not empty str}:表示字符串、集合、数组对象是否不为null 并且 长度>0

    2. 获取值

      1. el表达式只能从域对象中获取值

      2. 语法:

        1. ${域名称.键名}:从指定域中获取指定键的值

          域名称:

          pageScope ——> pageContext

          requestScope ——> request

          sessionScope ——> session

          applicationScope ——> application(ServletContext)

          举例:在request域中存储了name=张三

          获取:${requestScope.name}

        2. ${键名}:表示依次从最小的域中查找是否有该键对应的值,直到找到为止

      3. 获取对象,List集合,Map集合的值

        1. 对象:${域名称.键名.属性名}

          本质上会去调用对象的getter方法

        2. List集合:${域名称.键名[索引]}

        3. Map集合:

          ${域名称.键名.key名称}

          ${域名称.键名["key名称"]}

    3. 隐式对象

      el表达式中有11个隐式对象

      pageContext:获取jsp其他八个内置对象、

      动态获取虚拟目录

      ${pageContext.request.contextPath}
      
JSTL标签
  1. 概念:JavaServer Pages Tag Library JSP标准标签库

  2. 作用:用于简化和替换jsp页面上的java代码

  3. 使用步骤:

    1. 导入jstl相关jar包
    2. 引入标签库:taglib指令 <%@ taglib %>
    3. 使用标签
  4. 常用的JSTL标签

    使用前需引入如下代码

    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/c" %>
    
    1. if

      • 属性

        test为必须属性,接受boolean表达式

        如果表达式为true,显示if标签体内容,如果为false,不显示标签体内容

        一般情况下,test属性值会结合el表达式一起使用

      • 注意

        <c: if>标签没有else的情况,想要else情况,可以再定义一个<c: if>标签

    2. choose (相当于switch声明)

      when (相当于case)

      otherwise (相当于default)

      <%
      	request.setAttribute("number",3);
      %>
      
      <c:choose>
          <c:when test="${number == 1}">星期一			</c:when>
          <c:when test="${number == 2}">星期二			</c:when>
          <c:when test="${number == 3}">星期三			</c:when>
          <c:when test="${number == 4}">星期四			</c:when>
          <c:when test="${number == 5}">星期五			</c:when>
          <c:when test="${number == 6}">星期六			</c:when>
          <c:when test="${number == 7}">星期日			</c:when>
          
          <c:otherwise>数字输入有误</c:otherwise>
      </c:choose>
      
    3. foreach

      1. 完成重复的操作

        for(int i=0; i<10; i++){}
        

        begin:开始值

        end:结束值

        var:临时变量

        step:步长

        varStatus:循环状态对象

        ​ index:容器中元素的索引,从0开始

        ​ count:循环次数,从1开始

        <c:forEach begin="1" end="10" var="i" step="1" varStatus="s">${i} ${s.index}</c:forEach>
        
      2. 遍历容器

        List<User> list;
        for(User user: list){}
        

        items:容器对象

        var:容器中元素的临时变量

        varStatus:循环状态对象

        ​ index:容器中元素的索引,从0开始

        ​ count:循环次数,从1开始

        <c:forEach items="${list}" var="str" varStatus="s">
        ${s.index} ${s.count} ${str}
        </c:forEach>
        
      3. 练习

        需求:在request域中有一个存有User对象的List集合,需要使用jstl+el将list集合数据展示到jsp页面的表格table中

        <%
        	List list = new ArrayList();
        list.add(new User("张三",23,new Date()));
        list.add(new User("李四",24,new Date()));
        list.add(new User("王五",25,new Date()));
        	request.setAttribute("list",list);
        %>
        
        <table border="1" width="500" align="center">
            <tr>
                <th>编号</th>
                <th>姓名</th>
                <th>年龄</th>
                <th>生日</th>
            </tr>
            
            <c:forEach items="${list}" var="user" varStatus="s">
                <tr>
                    <td>${s.count}</td>
                    <td>${user.name}</td>
                    <td>${user.age}</td>
                    <td>${user.birStr}</td>
                </tr>
            </c:forEach>
        </table>
        
三层架构

软件设计架构

  1. 界面层:用户看的界面,

    用户可以通过界面上的组件和服务器进行交互

  2. 业务逻辑层:处理业务逻辑的

  3. 数据访问层:操作数据存储文件的

image-20220128125752636

Filter
  1. 概念

    当访问服务器的资源的时候,过滤器可以将请求拦截下来,完成一些特殊的功能

    过滤器的作用:一般用于完成通过的操作,如:登录验证、统一编码处理、敏感字符过滤

  2. 快速入门

    1. 步骤

      1. 定义一个类,实现接口Filter
      2. 复写方法
      3. 配置
      @WebFilter("/*") //访问所有资源之前,都会执行该过滤器
      public class FilterDemo1 implements Filter {
          @Override
          public void init(FilterConfig filterConfig) throws ServletException {
      
          }
      
          @Override
          public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
              filterChain.doFilter(servletRequest,servletResponse);
          }
      
          @Override
          public void destroy() {
      
          }
      }
      
    2. 过滤器细节

      1. web.xml配置

        <filter>
            <filter-name>demo1</filter-name>
            <filter-class>
         cn.itcast.web.filter.FilterDemo1
            </filter-class>
        </filter>
        <filter-mapping>
            <filter-name>demo1</filter-name>
            <!-- 拦截路径 -->
            <url-pattern>/*</url-pattern>
        </filter-mapping>
        
      2. 过滤器执行流程

        1. 执行过滤器
        2. 执行放行后的资源
        3. 回来执行过滤器放行代码下的代码
      3. 过滤器生命周期方法

        doFilter方法,每一次请求被拦截时,会执行

        服务器启动后,会创建Filter对象,然后调用init方法

        在服务器关闭后,Filter对象被销毁

        如果服务器正常关闭,执行destroy方法

      4. 过滤器配置详解

        拦截路径配置

        1. 具体资源路径:/index.jsp 只有访问index.jsp资源时,过滤器才会被执行
        2. 拦截目录:/user/* 访问/user下的所有资源时,过滤器都会被执行
        3. 后缀名拦截:*.jsp 访问所有jsp资源时,过滤器都会被执行
        4. 拦截所有资源:/* 访问所有资源时,过滤器都会被执行

        拦截方式配置:资源被访问的方式

      5. 过滤器链(配置多个过滤器)

Listener