大数据------JavaWeb------JSP(完整知识点汇总)

JSP

  • 定义

    • JSP(Java Server Pages),即Java服务端页面。
    • 它是一种动态的网页技术,其中可以定义HTML、CSS、JS等静态内容,还可以定义Java代码的动态内容
    • JSP = HTML + Java
      • 说白了JSP就是一个页面,它既可以写HTML标签,又可以写Java代码
  • 简单示例

    在这里插入图片描述

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
        <head>
            <title>Title</title>
        </head>
        <body>
            <h1>JSP,HELLO WORLD!!!</h1>
            <%
                System.out.println("Hello JSP");
            %>
        </body>
    </html>
    
    • 其中html标签代码最终会被浏览器解析并显示在页面上;而java代码会显示在服务器的控制台上,运行截图如下

      在这里插入图片描述

    • 注意:若利用Tomcat插件运行导致jsp文件无法在浏览器解析,出现如图所示页面错误,代表当前所用的JDK版本太高了

      • 解决方式一:用自己本地的Tomcat运行Web项目(配置本地的Tomcat详见JavaWeb------Tomcat中的IDEA中使用Tomcat那一部分内容)
      • 解决方式二:将JDK版本降为1.8,然后用Tomcat插件运行就不会出错了

      在这里插入图片描述

JSP快速入门

  • 步骤

    • Step1:在pom.xml文件中导入JSP坐标依赖

      • JSP坐标需要设置坐标依赖范围为provided,即该坐标在编译和测试时有效
        • 因为Tomcat中已经提供好了JSP的jar包,所以在打包后应该排除掉自己所设置的jar包,若不排除则会报错

        • 注意Servlet坐标依赖也是需要设置坐标依赖范围为provided,原因与其相同

<dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>jsp-api</artifactId>
    <version>2.2</version>
    <scope>provided</scope>
</dependency>
- 完整pom.xml文件如下

  ```xml
  <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.example</groupId>
    <artifactId>JspDemo</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>JspDemo Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <dependencies>
      <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>3.8.1</version>
        <scope>test</scope>
      </dependency>
      
      <!--JSP坐标依赖  注意别忘了加上坐标依赖范围-->
      <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.2</version>
        <scope>provided</scope>
      </dependency>
      
    </dependencies>
    
    <build>
      <finalName>JspDemo</finalName>
      <plugins>
        <!-- Tomcat插件 -->
        <plugin>
          <groupId>org.apache.tomcat.maven</groupId>
          <artifactId>tomcat7-maven-plugin</artifactId>
          <version>2.2</version>
        </plugin>
      </plugins>
    </build>
  </project>
  ```
  • Step2:创建JSP文件

    • 注意:不能将JSP文件放到webapp目录下的WEB-INF目录下,因为该目录不能通过浏览器直接访问到,应该直接放到webapp目录下

    在这里插入图片描述

  • Step3:编写HTML标签和Java代码(该步骤省略可详见JSP快速入门)

    • Java代码被包裹在<% 这中间写Java代码 %>中间

JSP原理

  • JSP本质上就是一个Servlet。

    • JSP在被访问时,由JSP容器(即Tomcat)将其转换为Java文件(即Servlet),然后在由JSP容器(即Tomcat)将其编译,最终对外提供服务的其实就是这个字节码文件
  • 详解如下

    在这里插入图片描述

    • 浏览器请求资源且第一次访问hello.jsp文件时,JSP文件会被JSP容器(即Tomcat)转换为Servletjava文件(这个过程是Tomcat自动完成的),然后在由Tomcat自动进行编译最终向浏览器发出响应
      • JSP容器(即Tomcat)会自动将JSP文件解析为对应包含HTML代码和Java代码的Java文件
      • 提供服务的其实就是最后生成的字节码文件
  • JSP工作流程

    • 编写 JSP 页面: 开发者编写一个 JSP 页面,包含 HTML 和嵌入的 Java 代码。
    • 编译 JSP 页面: JSP 容器将 JSP 页面编译成一个 Java servlet 类,这个类继承自 HttpJspBase
      • 通过继承 HttpJspBase,JSP 页面的 servlet 能够有效地利用 servlet 的生命周期方法,并且使 JSP 页面能够与 servlet 容器集成,处理 HTTP 请求和响应。
    • 初始化: 在 servlet 被加载时,容器调用 jspInit() 方法进行初始化。
    • 处理请求: 每次请求到达时,容器调用 servlet 的 service() 方法,进而调用 _jspService() 方法来处理请求。
    • 销毁: 当 servlet 被卸载时,容器调用 jspDestroy() 方法进行清理。
  • 示例(以JSP快速入门的hello.jsp文件为例),hello.jsp代码如下

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
        <head>
            <title>Title</title>
        </head>
        <body>
            <h1>JSP,HELLO WORLD!!!</h1>
            <%
                System.out.println("Hello JSP");
            %>
        </body>
    </html>
    
    • Step1:代开当前Web项目的目录

      在这里插入图片描述

    • Step2:打开当前项目目录下的target目录→tomcat→work→然后一直进入到jsp目录下

      在这里插入图片描述

    • Step3:会发现有一个java文件,该文件就是JSP文件所生成的对应Java文件,打开该hello_jsp.java文件,代码如下

      package org.apache.jsp;
      
      import javax.servlet.*;
      import javax.servlet.http.*;
      import javax.servlet.jsp.*;
      
      public final class hello_jsp extends org.apache.jasper.runtime.HttpJspBase
          implements org.apache.jasper.runtime.JspSourceDependent {
      
        private static final javax.servlet.jsp.JspFactory _jspxFactory =
                javax.servlet.jsp.JspFactory.getDefaultFactory();
      
        private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;
      
        private javax.el.ExpressionFactory _el_expressionfactory;
        private org.apache.tomcat.InstanceManager _jsp_instancemanager;
      
        public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
          return _jspx_dependants;
        }
      
        public void _jspInit() {
          _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
          _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
        }
      
        public void _jspDestroy() {
        }
      
        public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
              throws java.io.IOException, javax.servlet.ServletException {
      
          final javax.servlet.jsp.PageContext pageContext;
          javax.servlet.http.HttpSession session = null;
          final javax.servlet.ServletContext application;
          final javax.servlet.ServletConfig config;
          javax.servlet.jsp.JspWriter out = null;
          final java.lang.Object page = this;
          javax.servlet.jsp.JspWriter _jspx_out = null;
          javax.servlet.jsp.PageContext _jspx_page_context = null;
      
      
          try {
            response.setContentType("text/html;charset=UTF-8");
            pageContext = _jspxFactory.getPageContext(this, request, response,
            			null, true, 8192, true);
            _jspx_page_context = pageContext;
            application = pageContext.getServletContext();
            config = pageContext.getServletConfig();
            session = pageContext.getSession();
            out = pageContext.getOut();
            _jspx_out = out;
      
            out.write("\r\n");
            out.write("\r\n");
            out.write("<html>\r\n");
            out.write("    <head>\r\n");
            out.write("        <title>Title</title>\r\n");
            out.write("    </head>\r\n");
            out.write("    <body>\r\n");
            out.write("        <h1>JSP,HELLO WORLD!!!</h1>\r\n");
            out.write("        ");
      
                  System.out.println("Hello JSP");
              
            out.write("\r\n");
            out.write("    </body>\r\n");
            out.write("</html>\r\n");
          } catch (java.lang.Throwable t) {
            if (!(t instanceof javax.servlet.jsp.SkipPageException)){
              out = _jspx_out;
              if (out != null && out.getBufferSize() != 0)
                try { out.clearBuffer(); } catch (java.io.IOException e) {}
              if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
              else throw new ServletException(t);
            }
          } finally {
            _jspxFactory.releasePageContext(_jspx_page_context);
          }
        }
      }
      
      • 在该代码中我们发现,Tomcat将jsp文件代码以java代码的形式写了出来

        在这里插入图片描述

      • Tomcat将JSP文件转换为Java文件后,该文件extends org.apache.jasper.runtime.HttpJspBaseHttpJspBase类继承自 HttpServlet,所以该Java文件属于Servlet类

  • HttpJspBase类详解

    • 初始化和清理: HttpJspBase 提供了 jspInit()jspDestroy() 方法,分别对应 servlet 的 init()destroy() 方法。这些方法允许 JSP 页面在初始化和销毁时执行特定的代码。
    • 服务方法: HttpJspBase 类会覆盖 service() 方法,以便调用 _jspService(HttpServletRequest request, HttpServletResponse response) 方法,这是每个 JSP 页面必须实现的一个方法,用于处理请求和生成响应。
    • 编译过程: 当 JSP 页面被容器(如 Apache Tomcat)编译时,它会生成一个继承自 HttpJspBase 的 servlet 类。生成的 servlet 类会实现 _jspService() 方法,该方法包含了 JSP 页面中的实际代码。

JSP脚本

  • 作用:用于在JSP页面内定义Java代码

  • JSP脚本分类

    分类解释
    <%...%>内容会直接放到_jspService()方法之中
    <%=...%>内容会放到out.print()之中,作为out.print()的参数
    <%!...%>内容会直接放到_jspService()方法之外,被类继续包含。即跟属性、方法属于同一级
  • 示例

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
        <head>
            <title>Title</title>
        </head>
        <body>
            <h1>JSP,HELLO WORLD!!!</h1>
            <!--第一种脚本-->
            <%
                System.out.println("Hello JSP");
                int i = 3;
            %>
            
            <!--第二种脚本-->
            <%="i为" + 3%>
            
            <!--第三种脚本-->
            <%!
                void show(){}
                String name = "zhangsan";
            %>
        </body>
    </html>
    
    • 第一种脚本<%...%>,会在生成的java文件的_jspService()方法之中,如下代码所示(注意:博主把该_jspService方法内的无关代码均已删除,这样能清楚看出来该脚本内的代码在该方法之中)(html代码也在_jspService()方法之中, 如下代码所示

      public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
              throws java.io.IOException, javax.servlet.ServletException {
      
          try {
            out.write("\r\n");
            out.write("\r\n");
            out.write("<html>\r\n");
            out.write("    <head>\r\n");
            out.write("        <title>Title</title>\r\n");
            out.write("    </head>\r\n");
            out.write("    <body>\r\n");
            out.write("        <h1>JSP,HELLO WORLD!!!</h1>\r\n");
            out.write("        <!--第一种脚本-->\r\n");
            out.write("        ");
      
                  System.out.println("Hello JSP");
                  int i = 3;
              
            out.write("\r\n");
            out.write("        <!--第二种脚本-->\r\n");
            out.write("        ");
            out.print("i为" + i);
            out.write("\r\n");
            out.write("        <!--第三种脚本-->\r\n");
            out.write("        ");
            out.write("\r\n");
            out.write("    </body>\r\n");
            out.write("</html>\r\n");
          } 
        }
      
    • 第二种脚本<%=...%>,也会在生成的java文件的_jspService()方法之中,不过它的内容会放到out.print()之中,作为out.print()的参数,最终输出到页面上,代码详见第一种脚本处的代码,Tomcat运行该Web项目后,页面显示如下

      在这里插入图片描述

    • 第三种脚本<%!...%>,内容会直接放到_jspService()方法之外,被类继续包含。即跟属性、方法属于同一级,如下所示(注意:代码均为省略形式,以便明了)

      public final class hello_jsp extends org.apache.jasper.runtime.HttpJspBase
          implements org.apache.jasper.runtime.JspSourceDependent {
                  void show(){}
                  String name = "zhangsan";
      }
      

      在这里插入图片描述

JSP脚本示例

  • 将数据库中的商品显示在浏览器页面

    • brand对象类

      package at.guigu.pojo;
      
      public class Brand {
          // id 主键
          private Integer id;
          // 品牌名称
          private String brandName;
          // 企业名称
          private String companyName;
          // 排序字段 用于将某个品牌显示在最前面让消费者看到
          private Integer ordered;
          // 描述信息
          private String description;
          // 状态:0:禁用  1:启用
          private Integer status;
      
          public Brand() {}
      
          public Brand(Integer id, String brandName, String companyName, Integer ordered, String description, Integer status) {
              this.id = id;
              this.brandName = brandName;
              this.companyName = companyName;
              this.ordered = ordered;
              this.description = description;
              this.status = status;
          }
      
          public Integer getId() {
              return id;
          }
      
          public void setId(Integer id) {
              this.id = id;
          }
      
          public String getBrandName() {
              return brandName;
          }
      
          public void setBrandName(String brandName) {
              this.brandName = brandName;
          }
      
          public String getCompanyName() {
              return companyName;
          }
      
          public void setCompanyName(String companyName) {
              this.companyName = companyName;
          }
      
          public Integer getOrdered() {
              return ordered;
          }
      
          public void setOrdered(Integer ordered) {
              this.ordered = ordered;
          }
      
          public String getDescription() {
              return description;
          }
      
          public void setDescription(String description) {
              this.description = description;
          }
      
          public Integer getStatus() {
              return status;
          }
      
          public void setStatus(Integer status) {
              this.status = status;
          }
      
          @Override
          public String toString() {
              return "Brand{" +
                      "id=" + id +
                      ", brandName='" + brandName + '\'' +
                      ", companyName='" + companyName + '\'' +
                      ", ordered=" + ordered +
                      ", description='" + description + '\'' +
                      ", status=" + status +
                      '}';
          }
      }
      
    • brand.jsp文件

      <%@ page import="at.guigu.pojo.Brand" %>
      <%@ page import="java.util.ArrayList" %>
      <%@ page import="java.util.List" %>
      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      
      <%
          //模拟查询数据库
          List<Brand> brands = new ArrayList<>();
          brands.add(new Brand(1, "三只松鼠", "三只松鼠", 100, "三只松鼠,好吃不上火", 1));
          brands.add(new Brand(2, "优衣库", "优衣库", 200, "优衣库,服适人生", 0));
          brands.add(new Brand(3, "小米", "小米科技有限公司", 1000, "为发烧而生", 1));
      %>
      
      <!DOCTYPE html>
      <html lang="en">
          <head>
              <meta charset="UTF-8">
              <title>Title</title>
          </head>
          <body>
              <input type="button" value="新增"><br>
              <hr>
              <table border="1" cellspacing="0" width="800">
                  <tr>
                      <th>序号</th>
                      <th>品牌名称</th>
                      <th>企业名称</th>
                      <th>排序</th>
                      <th>品牌介绍</th>
                      <th>状态</th>
                      <th>操作</th>
                  </tr>
      
                  <%
                      for (int i = 0; i < brands.size(); i++) {
                          Brand brand = brands.get(i);//获取第i个对象
                  %>
      
                  <tr align="center">
                      <td><%=brand.getId()%></td>
                      <td><%=brand.getBrandName()%></td>
                      <td><%=brand.getCompanyName()%></td>
                      <td><%=brand.getOrdered()%></td>
                      <td><%=brand.getDescription()%></td>
                      <td>
                          <%
                              if (brand.getStatus() == 0) {
                          %>
                          		<%="禁用"%>
                          <%
                              }else {
                          %>
                          		<%="启用"%>
                          <%
                              }
                          %>
                      </td>
                      <td><a href="#">修改</a> <a href="#">删除</a></td>
                  </tr>
      
                  <%
                      }
                  %>
                  
              </table>
          </body>
      </html>
      
      • 注意以下这一部分代码可改为

        <td>
            <%
                if (brand.getStatus() == 0) {
            %>
            		<%="禁用"%>
            <%
                }else {
            %>
            		<%="启用"%>
            <%
                }
            %>
        </td>
        <!--等同于-->
        <%
                if (brand.getStatus() == 0) {
        %>
                    <td><%="禁用"%></td>
        <%
                }else {
        %>
                    <td><%="启用"%></td>
        <%
                }
        %>
        

      Tomcat运行该Web项目后页面运行截图如下

      在这里插入图片描述

  • 注意事项

    • 在JSP文件中Java代码可跟Html代码可嵌套来写,但是Java代码要写在JSP脚本中,Html代码不能写在脚本中,如下所示

      • 嵌套方式来写java和html代码比较麻烦,对于复杂的页面不利于阅读和调试等工作,所以最好不要在JSP中直接写Java代码
      <%
              if (brand.getStatus() == 0) {
      %>
                  <td><%="禁用"%></td>
      <%
              }else {
      %>
                  <td><%="启用"%></td>
      <%
              }
      %>
      

JSP缺点

  • 列举部分缺点如下:

    • 书写麻烦:特别是对于复杂的页面
    • 阅读麻烦
    • 复杂度高:运行需要依赖各种环境,比如:JRE、JSP容器、JavaEE等
    • 占用内存和磁盘:JSP会自动生成.java和.class文件占磁盘,运行的是.class文件占内存
    • 调试困难:出错后,需要找到自动生成的.java文件进行调试
    • 不利于团队写作:前端人员不会Java,后端人员不精Html
    • 由于以上缺点,JSP被Html+AJAX逐渐代替
  • 解决方式

    在这里插入图片描述

    • 不直接在JSP中写Java代码,而是利用Servlet和JSP的结合(即Java代码写在Servlet中,进行逻辑处理,封装数据;而JSP利用EL表达式JSTL标签 来获取数据并进行遍历展现数据)
      • EL表达式: 用来替换JSP中获取数据的Java代码
      • JSTL标签: 用来替换循环、遍历的Java代码

EL表达式

  • 定义

    • Expression Language表达式语言,用于简化JSP页面内的Java代码
  • 主要功能:获取数据

  • 语法:${key}

    • ${brands}:获取request域中存储的key为brands的数据
  • JavaWeb中四大域对象

    在这里插入图片描述

    • page:当前页面有效
    • request:当前请求有效
    • session:当前会话有效
    • application:当前应用有效
    • 注意:EL表达式获取数据时会依次从这4个域中寻找,直到找到为止
  • 简单示例

    • Step1:在at.guigu.web包下创建ServletDemo1类,将准备数据放入,最终代码如下

      package at.guigu.web;
      
      import at.guigu.pojo.Brand;
      
      import javax.servlet.*;
      import javax.servlet.http.*;
      import javax.servlet.annotation.*;
      import java.io.IOException;
      import java.util.ArrayList;
      import java.util.List;
      
      @WebServlet("/eldemo1")
      public class ServletDemo1 extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              //1 准备数据:模拟查询数据库并获取数据
              List<Brand> brands = new ArrayList<>();
              brands.add(new Brand(1, "三只松鼠", "三只松鼠", 100, "三只松鼠,好吃不上火", 1));
              brands.add(new Brand(2, "优衣库", "优衣库", 200, "优衣库,服适人生", 0));
              brands.add(new Brand(3, "小米", "小米科技有限公司", 1000, "为发烧而生", 1));
      
              //2 将数据存储到request域中
              request.setAttribute("brands", brands);
      
              //3 转发到el-demo.jsp
              request.getRequestDispatcher("/el-demo.jsp").forward(request, response);
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doGet(request, response);
          }
      }
      
    • Step2:创建el-demo.jsp文件,具体代码如下

      • 注意:要在JSP页面顶部<%@...%>标签体内加上isELIgnored="false",作用是防止Tomcat配置禁用EL表达式
      <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
      <html>
          <head>
              <title>Title</title>
          </head>
          <body>
              <!--获取request域中存储brands的数据-->
              ${brands}
          </body>
      </html>
      

      Tomcat运行该Web项目后运行截图如下

      在这里插入图片描述

JSTL标签

  • 定义

    • JSTL(即JSP Standarded Tag Library),是Java 服务器页面标准标签库,使用标签取代JSP页面上的Java代码
    • 它为 JSP 页面提供了一组标准的标签库,用于简化 JSP 页面中的常见任务,例如条件判断、循环迭代、字符串操作、国际化、数据库访问等。
  • JSTL标签

    标签解释
    <c:out>用于在JSP中显示数据,相当于<%=...>
    <c:set>用于保存数据
    <c:remove>用于删除数据
    <c:catch>用来处理产生错误的异常情况,并将错误信息储存起来
    <c:if>与java中的if一样
    <c:choose>本身只当作<c:when><c:otherwise>的父标签
    <c:when><c:choose>的子标签,用来判断条件是否成立
    <c:otherwise><c:choose>的子标签,接在<c:when>标签后,当<c:when>标签判断为false时被执行
    <c:import>检索一个绝对或相对URL,然后将其内容暴露给页面
    <c:forEach>基础迭代标签,接受多种集合类型
    <c:forTokens>根据指定的分隔符来分割内容并迭代输出
    <c:param>用来给包含或重定向的页面传递参数
    <c:redirect>重定向至一个新的URL
    <c:url>使用可选的查询参数来创造一个URL
  • JSTL标签使用步骤

    • Step1: 在Web项目的pom.xml文件中导入坐标依赖

      <dependency>
          <groupId>jstl</groupId>
          <artifactId>jstl</artifactId>
          <version>1.2</version>
      </dependency>
      <dependency>
          <groupId>taglibs</groupId>
          <artifactId>standard</artifactId>
          <version>1.1.2</version>
      </dependency>
      
    • Step2: 在JSP页面上引入JSTL标签库<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> ,如下所示

      <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <html>
          <head>
              <title>Title</title>
          </head>
          <body>
      
          </body>
      </html>
      
    • Step3: 使用标签

使用标签—条件标签

<c:if>标签
  • 定义:相当于if判断
该标签中必有的属性解释
test该属性的属性值为逻辑表达式,结果若为true则执行该标签体中的内容
  • 简单示例,jstl-demo1.jsp文件代码如下

    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
        <head>
            <title>Title</title>
        </head>
        <body>
            <c:if test="true">
                <h1>判断为true</h1>
            </c:if>
        </body>
    </html>
    

    在这里插入图片描述

  • <c:if>标签通常与EL表达式联合使用来执行对应的代码,代码示例如下

    • ServletDemo1.java代码如下

      package at.guigu.web;
      
      import at.guigu.pojo.Brand;
      
      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.ArrayList;
      import java.util.List;
      
      @WebServlet("/jstldemo2")
      public class ServletDemo2 extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              //1 准备数据:模拟查询数据库并获取数据
              List<Brand> brands = new ArrayList<>();
              brands.add(new Brand(1, "三只松鼠", "三只松鼠", 100, "三只松鼠,好吃不上火", 1));
              brands.add(new Brand(2, "优衣库", "优衣库", 200, "优衣库,服适人生", 0));
              brands.add(new Brand(3, "小米", "小米科技有限公司", 1000, "为发烧而生", 1));
      
              //2 将数据存储到request域中
              request.setAttribute("brands", brands);
              //用来测试<c:if>标签
              request.setAttribute("status", 1);
      
              //3 转发到el-demo.jsp
              request.getRequestDispatcher("/jstl-demo2.jsp").forward(request, response);
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doGet(request, response);
          }
      }
      
    • jstl-demo2.jsp文件代码如下:

      <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
      <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
      <html>
          <head>
              <title>Title</title>
          </head>
          <body>
              <c:if test="${status==1}">
                  <h1>满足status==1则输出该条html语句</h1>
              </c:if>
          </body>
      </html>
      

      在这里插入图片描述

<c:choose><c:when><c:otherwise>
  • 以上三个标签联合使用用于实现多条件分支的逻辑控制,类似于 Java 中的 switch 语句或 if-else-if 结构。

  • 三个标签解释

    • <c:choose>
      • 该标签本身没有属性
      • 可包含一个或多个 <c:when> 标签,可以选择性包含一个 <c:otherwise> 标签
    • <c:when>标签
      • 用于定义每个条件分支
      • 具有唯一的必需属性test
    • <c:otherwise>标签
      • 用于定义在所有 <c:when> 条件都不满足时应该执行的代码块
      • 该标签没有属性,且必须位于 <c:choose> 标签内,并且通常放在所有 <c:when> 标签之后
      • 该标签内的内容在所有 <c:when> 条件都为 false 时执行
  • 代码示例1

    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
    <c:choose>
        <c:when test="${user.age < 18}">
            <p>您是未成年人。</p>
        </c:when>
        <c:when test="${user.age >= 18 and user.age <= 65}">
            <p>您是成年人。</p>
        </c:when>
        <c:otherwise>
            <p>您是老年人。</p>
        </c:otherwise>
    </c:choose>
    
    • 如果 user.age 小于 18,则显示“您是未成年人。
    • 如果 user.age 在 18 到 65 之间(含),则显示“您是成年人。
    • 如果以上两个条件都不满足(即 user.age 大于 65),则显示“您是老年人。
  • 代码示例2

    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
    <c:choose>
        <c:when test="${user.role == 'admin'}">
            <p>欢迎管理员!</p>
        </c:when>
        <c:when test="${user.role == 'user'}">
            <p>欢迎普通用户!</p>
        </c:when>
        <c:otherwise>
            <p>欢迎访客,请登录。</p>
        </c:otherwise>
    </c:choose>
    
    • 如果 user.roleadmin,则显示“欢迎管理员!”
    • 如果 user.roleuser,则显示“欢迎普通用户!”
    • 如果以上两个条件都不满足,则执行 <c:otherwise> 标签内的内容,显示“欢迎访客,请登录。

使用标签------迭代标签<c:forEach>

该标签的属性解释
items要迭代的集合(即被遍历的容器)。可以是数组、集合、映射等
var每次迭代时存储当前项的变量名(即遍历产生的临时变量)
varStatus一个变量,用于存储迭代状态(即遍历状态对象)(可选)(注意: 该属性的属性值字符串可随意写,属性值.index:序号从0开始;属性值.count:序号从1开始)
begin迭代的起始索引(可选)
end迭代的结束索引(可选)
step每次迭代的步长(可选)
  • 定义:相当于for循环
增强for循环

在这里插入图片描述

  • 增强for循环代码示例

    • Brand类代码

      package at.guigu.pojo;
      
      public class Brand {
          // id 主键
          private Integer id;
          // 品牌名称
          private String brandName;
          // 企业名称
          private String companyName;
          // 排序字段 用于将某个品牌显示在最前面让消费者看到
          private Integer ordered;
          // 描述信息
          private String description;
          // 状态:0:禁用  1:启用
          private Integer status;
      
          public Brand() {}
      
          public Brand(Integer id, String brandName, String companyName, Integer ordered, String description, Integer status) {
              this.id = id;
              this.brandName = brandName;
              this.companyName = companyName;
              this.ordered = ordered;
              this.description = description;
              this.status = status;
          }
      
          public Integer getId() {
              return id;
          }
      
          public void setId(Integer id) {
              this.id = id;
          }
      
          public String getBrandName() {
              return brandName;
          }
      
          public void setBrandName(String brandName) {
              this.brandName = brandName;
          }
      
          public String getCompanyName() {
              return companyName;
          }
      
          public void setCompanyName(String companyName) {
              this.companyName = companyName;
          }
      
          public Integer getOrdered() {
              return ordered;
          }
      
          public void setOrdered(Integer ordered) {
              this.ordered = ordered;
          }
      
          public String getDescription() {
              return description;
          }
      
          public void setDescription(String description) {
              this.description = description;
          }
      
          public Integer getStatus() {
              return status;
          }
      
          public void setStatus(Integer status) {
              this.status = status;
          }
      
          @Override
          public String toString() {
              return "Brand{" +
                      "id=" + id +
                      ", brandName='" + brandName + '\'' +
                      ", companyName='" + companyName + '\'' +
                      ", ordered=" + ordered +
                      ", description='" + description + '\'' +
                      ", status=" + status +
                      '}';
          }
      }
      
    • JstlServletDemo3代码

      package at.guigu.web;
      
      import at.guigu.pojo.Brand;
      
      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.ArrayList;
      import java.util.List;
      
      @WebServlet("/jstldemo3")
      public class JstlServletDemo3 extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              //1 准备数据:模拟查询数据库并获取数据
              List<Brand> brands = new ArrayList<>();
              brands.add(new Brand(1, "三只松鼠", "三只松鼠", 100, "三只松鼠,好吃不上火", 1));
              brands.add(new Brand(2, "优衣库", "优衣库", 200, "优衣库,服适人生", 0));
              brands.add(new Brand(3, "小米", "小米科技有限公司", 1000, "为发烧而生", 1));
      
              //2 将数据存储到request域中
              request.setAttribute("brands", brands);
              //用来测试<c:if>标签
              request.setAttribute("status", 1);
      
              //3 转发到el-demo.jsp
              request.getRequestDispatcher("/jstl-demo3.jsp").forward(request, response);
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doGet(request, response);
          }
      }
      
    • jstl-demo3.jsp代码

      <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
      <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
      <html>
          <head>
              <title>Title</title>
          </head>
          <body>
              <input type="button" value="新增"><br>
              <hr>
              <table border="1" cellspacing="0">
                  <tr>
                      <th>序号</th>
                      <th>品牌名称</th>
                      <th>企业名称</th>
                      <th>排序</th>
                      <th>品牌介绍</th>
                      <th>状态</th>
                      <th>操作</th>
                  </tr>
                  <c:forEach items="${brands}" var="brand">
                      <tr align="center">
                          <td>${brand.id}</td>
                          <td>${brand.brandName}</td>
                          <td>${brand.companyName}</td>
                          <td>${brand.ordered}</td>
                          <td>${brand.description}</td>
                          <c:choose>
                              <c:when test="${brand.status==1}">
                                  <td>启用</td>
                              </c:when>
                              <c:otherwise>
                                  <td>禁用</td>
                              </c:otherwise>
                          </c:choose>
                          <td><a href="#">修改</a> <a href="#">删除</a></td>
                      </tr>
                  </c:forEach>
              </table>
          </body>
      </html>
      

      在这里插入图片描述

  • 注意

    • EL表达式${对象名.属性名} 会被系统自动解析并调用对应的getXXX()方法来返回对应的值

    • 上述运行截图中序号对应的是数据库中的主键id,这就会有一个弊端,如果删除优衣库则由于主键是唯一的,不会分配给其它品牌,所以最终浏览器的页面上的品牌三只松鼠和小米的序号仍为1、3,并不会变成1、2

      • 为了解决该问题可使用varStatus属性,如下jsp文件代码所示

        示例一:序号从0开始

        <%--
          Created by IntelliJ IDEA.
          User: 10195
          Date: 2024/6/28
          Time: 9:19
          To change this template use File | Settings | File Templates.
        --%>
        <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
        <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
        <html>
            <head>
                <title>Title</title>
            </head>
            <body>
                <input type="button" value="新增"><br>
                <hr>
                <table border="1" cellspacing="0">
                    <tr>
                        <th>序号</th>
                        <th>品牌名称</th>
                        <th>企业名称</th>
                        <th>排序</th>
                        <th>品牌介绍</th>
                        <th>状态</th>
                        <th>操作</th>
                    </tr>
                    <c:forEach items="${brands}" var="brand" varStatus="xuhao">
                        <tr align="center">
                            <td>${xuhao.index}</td>
                            <td>${brand.brandName}</td>
                            <td>${brand.companyName}</td>
                            <td>${brand.ordered}</td>
                            <td>${brand.description}</td>
                            <c:choose>
                                <c:when test="${brand.status==1}">
                                    <td>启用</td>
                                </c:when>
                                <c:otherwise>
                                    <td>禁用</td>
                                </c:otherwise>
                            </c:choose>
                            <td><a href="#">修改</a> <a href="#">删除</a></td>
                        </tr>
                    </c:forEach>
                </table>
            </body>
        </html>
        

        在这里插入图片描述

        示例二:序号从1开始

        <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
        <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
        <html>
            <head>
                <title>Title</title>
            </head>
            <body>
                <input type="button" value="新增"><br>
                <hr>
                <table border="1" cellspacing="0">
                    <tr>
                        <th>序号</th>
                        <th>品牌名称</th>
                        <th>企业名称</th>
                        <th>排序</th>
                        <th>品牌介绍</th>
                        <th>状态</th>
                        <th>操作</th>
                    </tr>
                    <c:forEach items="${brands}" var="brand" varStatus="xuhao">
                        <tr align="center">
                            <td>${xuhao.count}</td>
                            <td>${brand.brandName}</td>
                            <td>${brand.companyName}</td>
                            <td>${brand.ordered}</td>
                            <td>${brand.description}</td>
                            <c:choose>
                                <c:when test="${brand.status==1}">
                                    <td>启用</td>
                                </c:when>
                                <c:otherwise>
                                    <td>禁用</td>
                                </c:otherwise>
                            </c:choose>
                            <td><a href="#">修改</a> <a href="#">删除</a></td>
                        </tr>
                    </c:forEach>
                </table>
            </body>
        </html>
        

        在这里插入图片描述

普通for循环

在这里插入图片描述

  • 作用:可用来定义分页工具条

  • 代码示例

    • Brand及JstlServletDemo3代码与增强for循环一样,此处省略

    • jstl-demo3.jsp代码

      <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
      <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
      <html>
          <head>
              <title>Title</title>
          </head>
          <body>
              <input type="button" value="新增"><br>
              <hr>
              <table border="1" cellspacing="0">
                  <tr>
                      <th>序号</th>
                      <th>品牌名称</th>
                      <th>企业名称</th>
                      <th>排序</th>
                      <th>品牌介绍</th>
                      <th>状态</th>
                      <th>操作</th>
                  </tr>
                  <c:forEach items="${brands}" var="brand" varStatus="xuhao">
                      <tr align="center">
                          <td>${xuhao.count}</td>
                          <td>${brand.brandName}</td>
                          <td>${brand.companyName}</td>
                          <td>${brand.ordered}</td>
                          <td>${brand.description}</td>
                          <c:choose>
                              <c:when test="${brand.status==1}">
                                  <td>启用</td>
                              </c:when>
                              <c:otherwise>
                                  <td>禁用</td>
                              </c:otherwise>
                          </c:choose>
                          <td><a href="#">修改</a> <a href="#">删除</a></td>
                      </tr>
                  </c:forEach>
              </table>
              <hr>
              <c:forEach begin="1" end="10" step="1" var="i">
                  <a href="#">${i}</a>
              </c:forEach>
          </body>
      </html>
      

      在这里插入图片描述

理论知识

MVC模式

在这里插入图片描述

  • 定义:MVC是一种分层开发的模式

    • M(Model):即业务模型,用于处理业务
    • V(View):即视图,用于页面展示
    • C(Controller):即控制器,用于处理请求,调用模型和视图
  • MVC模式实现过程

    浏览器向服务器端请求数据时会先请求控制器,控制器调用模型来获取数据,之后控制器会将数据传给视图,并由视图响应给浏览器,实现最终的页面展示

  • 特点

    • 由Servlet充当控制器,JavaBean充当模型,JSP充当视图
    • 职责单一,互不影响
    • 有利于分工协作
    • 有利于组件重用

三层架构

在这里插入图片描述

  • 解释:将一个完整的项目分为三个层面

    • 表现层:接收请求,封装数据,调用业务逻辑层,响应数据
      • 包名默认为:at.guigu.webat.guigu.controller
      • 对应的框架为:SpringMVCStruts2
    • 业务逻辑层:对业务逻辑进行封装,组合数据访问层层中的基本功能,从而形成复杂的业务逻辑功能
      • 包名默认为:at.guigu.service
      • 对应的框架为:Spring
      • 解释:假设现在数据访问层有多个增删改查方法,若表现层有多个实现Servlet的类需要用到其中增和删两个方法,此时若在实现类中频繁写重复代码就造成了冗余,所以我们可以将其封装起来作为一个业务方法,以此来供实现Servlet接口的实现类使用,这样可增加代码的复用性
    • 数据访问层(持久层):对数据库进行CRUD(增删改查)的基本操作
      • 包名默认为:at.guigu.daoat.guigu.mapper
        • 若我们用到了MyBatis技术则使用后者,反之使用前者
      • 对应的框架为:MyBatisHibername
  • 三层架构实现过程

    浏览器向服务器端请求数据时会先请求表现层的控制器(即Servlet),然后控制器会调用业务逻辑层的代码(这些代码组装了数据访问层的CRUD等基本功能)来获取数据库中的数据,并将数据返回给表现层中的控制器(即Swervlet),然后再由控制器(即Servlet)对数据进行封装,放到request域中传给视图(即JSP),最终由视图(即JSP)将响应数据返回给浏览器,使其展现在页面上

  • MVC模式和三层架构的区别

    在这里插入图片描述

案例

注意:本案例已提交到Gitee,可自行下载:https://gitee.com/cgrs572/brand-demo.git

在这里插入图片描述

环境准备

在这里插入图片描述

  • 创建新的Web项目BrandDemo,引入坐标(在pom.xml文件中引入坐标依赖),并配置Tomcat(可详见Tomcat部分)

    • 需要的坐标依赖有mybatis、mysql驱动、servlet、jsp、jstl

    • 需要的插件有Tomcat插件

    • 完整pom.xml文件如下

      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>org.example</groupId>
        <artifactId>BrandDemo</artifactId>
        <packaging>war</packaging>
        <version>1.0-SNAPSHOT</version>
        <name>BrandDemo Maven Webapp</name>
        <url>http://maven.apache.org</url>
        <dependencies>
          <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
          </dependency>
      
          <!--MyBatis依赖-->
          <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.16</version>
          </dependency>
      
          <!--mysql驱动-->
          <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
          </dependency>
      
          <!--Servlet依赖-->
          <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
            <!--依赖范围关键字provided:在编译环境和测试环境有效,但在真正运行时就不会在使用该jar包-->
          </dependency>
      
          <!--JSP依赖-->
          <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2</version>
            <scope>provided</scope>
          </dependency>
      
          <!--jstl依赖-->
          <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
          </dependency>
          <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
          </dependency>
      
        </dependencies>
        <build>
          <finalName>BrandDemo</finalName>
      
          <plugins>
            <!-- Tomcat插件 -->
            <plugin>
              <groupId>org.apache.tomcat.maven</groupId>
              <artifactId>tomcat7-maven-plugin</artifactId>
              <version>2.2</version>
            </plugin>
          </plugins>
      
        </build>
      </project>
      
  • 创建三层架构包结构

    在这里插入图片描述

  • 创建数据库表tb_brand并使IDEA与数据库建立连接,SQL代码如下

    DROP TABLE IF EXISTS tb_brand;
    
    -- 创建品牌表brand
    CREATE TABLE IF NOT EXISTS tb_brand
    (
    	-- id 主键
    	id int PRIMARY KEY auto_increment,
    	-- 品牌名称
    	brand_name VARCHAR(20),
    	-- 企业名称
    	company_name VARCHAR(20),
    	-- 排序字段
    	ordered INT,
    	-- 描述信息
    	description VARCHAR(100),
    	-- 状态:0:禁用  1:启用
    	status INT
    );
    
    -- 添加数据
    INSERT INTO tb_brand(brand_name, company_name, ordered, description, status) 
    VALUES ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
    			 ('华为', '华为技术有限公司', 100, '华为致力于构建万物互联的世界', 1),
           ('小米', '小米科技有限公司', 50, 'Are you OK', 1);
    
    SELECT * FROM tb_brand;
    

    在这里插入图片描述

  • 创建实体类Brand此为Pojo类 :存放对数据库中数据封装的对象),代码如下

    package at.guigu.pojo;
    
    public class Brand {
        // id 主键
        private Integer id;
        // 品牌名称
        private String brandName;
        // 企业名称
        private String companyName;
        // 排序字段 用于将某个品牌显示在最前面让消费者看到
        private Integer ordered;
        // 描述信息
        private String description;
        // 状态:0:禁用  1:启用
        private Integer status;
    
        public Brand() {}
    
        public Brand(Integer id, String brandName, String companyName, Integer ordered, String description, Integer status) {
            this.id = id;
            this.brandName = brandName;
            this.companyName = companyName;
            this.ordered = ordered;
            this.description = description;
            this.status = status;
        }
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getBrandName() {
            return brandName;
        }
    
        public void setBrandName(String brandName) {
            this.brandName = brandName;
        }
    
        public String getCompanyName() {
            return companyName;
        }
    
        public void setCompanyName(String companyName) {
            this.companyName = companyName;
        }
    
        public Integer getOrdered() {
            return ordered;
        }
    
        public void setOrdered(Integer ordered) {
            this.ordered = ordered;
        }
    
        public String getDescription() {
            return description;
        }
    
        public void setDescription(String description) {
            this.description = description;
        }
    
        public Integer getStatus() {
            return status;
        }
    
        public void setStatus(Integer status) {
            this.status = status;
        }
    
        @Override
        public String toString() {
            return "Brand{" +
                    "id=" + id +
                    ", brandName='" + brandName + '\'' +
                    ", companyName='" + companyName + '\'' +
                    ", ordered=" + ordered +
                    ", description='" + description + '\'' +
                    ", status=" + status +
                    '}';
        }
    }
    
  • MyBrtis基础环境配置

    • 在mapper包下创建BrandMapper接口

    • 在项目的源代码配置文件目录(即main包下的resources目录下)创建多层目录,多层目录对应Mapper接口所在的多层包,然后再该包中创建BrandMapper.xmlSQL映射文件,基本代码如下

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      
      <!--
          namespace:名称空间
      -->
      <mapper namespace="at.guigu.mapper.BrandMapper">
          
          <!--结果映射-->
          <resultMap id="brandResultMap" type="brand">
              <!--由于id为主键,且数据库中的字段名和对应结果映射的目标类中的属性名一样,所以此处不需要主键映射,只需进行非主键映射即可-->
              <result column="brand_name" property="brandName"/>
              <result column="company_name" property="companyName"/>
          </resultMap>
      
      </mapper>
      
    • 在项目的源代码配置文件目录(即main包下的resources目录下)创建MyBatis核心配置文件mybatis-config.xml,代码如下

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE configuration
              PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
              "https://mybatis.org/dtd/mybatis-3-config.dtd">
      <configuration>
      
          <!--设置别名-->
          <typeAliases>
              <package name="at.guigu.pojo"/>
          </typeAliases>
      
          <environments default="development">
              <environment id="development">
                  <transactionManager type="JDBC"/>
                  <dataSource type="POOLED">
                      <!--数据库 连接信息-->
                      <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                      <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false&amp;serverTimezone=Asia/Shanghai"/>
                      <property name="username" value="root"/>
                      <property name="password" value="123456"/>
                  </dataSource>
              </environment>
          </environments>
          
          <mappers>
              <!--加载SQL映射文件:传入sql映射文件的路径-->
      <!--        <mapper resource="at/guigu/mapper/BrandMapper.xml"/>-->
              <package name="at.guigu.mapper"/>
          </mappers>
      </configuration>
      

    在这里插入图片描述

查询所有

在这里插入图片描述

  • 解释:页面上有一个“查询所有”的超链接,单击该链接即显示出查询数据,如图所示

  • 要完成该问则需满足三层架构,各层需要做的工作如下所示

    在这里插入图片描述

  • Dao层/Map层

    • Step1: BrandMapper接口中写入查询所有数据的方法

      package at.guigu.mapper;
      
      import at.guigu.pojo.Brand;
      import java.util.List;
      
      public interface BrandMapper {
          //查询并返回所有商品
          /*@Select("select * from tb_brand")
          @ResultMap("brandResultMap")*/
          List<Brand> selectAll();
      }
      
      • 注意:
        1. 对数据库中的字段进行结果映射后,若想要用注解方式输写SQL语句则需要另外加上注解@ResultMap("brandResultMap"),才能使结果映射生效(结果映射可详见MyBatis那一节)
        2. 由于我在SQL映射文件中输入SQL语句,所以不需要改代码中的两个注解;若使用MyBatis注解开发(即SQL语句写在注解中)则需要加上以上两个注解
    • Step2: 在对应的SQL映射文件BrandMapper.xml中写入SQL语句

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      
      <!--
          namespace:名称空间
      -->
      <mapper namespace="at.guigu.mapper.BrandMapper">
          <!--结果映射-->
          <resultMap id="brandResultMap" type="brand">
              <!--由于id为主键,且数据库中的字段名和对应结果映射的目标类中的属性名一样,所以此处不需要主键映射,只需进行非主键映射即可-->
              <result column="brand_name" property="brandName"/>
              <result column="company_name" property="companyName"/>
          </resultMap>
      
          <!--
              id:为sql语句的唯一标识
              resultType:为对应sql语句执行完毕后返回结果的类型
          -->
          <select id="selectAll" resultMap="brandResultMap">
              select * from tb_brand;
          </select>
      </mapper>
      
  • Service层

    • 由于Service层中的类均需要调用Mapper接口中的方法,那么该层中的类就都需要载核心配置文件,来获取SqlSessionFactorySQL连接工厂对象,所以就可以将SqlSessionFactory封装为一个工具类。所以在完善Service层之前需要先在util包下将工具类SqlSessionFactoryUtils创建好,代码如下:

      package at.guigu.util;
      
      import org.apache.ibatis.io.Resources;
      import org.apache.ibatis.session.SqlSessionFactory;
      import org.apache.ibatis.session.SqlSessionFactoryBuilder;
      
      import java.io.IOException;
      import java.io.InputStream;
      
      public class SqlSessionFactoryUtils {
          private static SqlSessionFactory sqlSessionFactory;
          static {
              //静态代码快会随着类的加载而自动执行,且只执行一次
      
              try {
                  //配置mybatis-config.xml文件路径。注意:若该文件直接在resources目录下,则直接写文件名即可
                  String resource = "mybatis-config.xml";
                  //利用Resources类中的静态方法将配置文件加载到内存
                  InputStream inputStream = Resources.getResourceAsStream(resource);
                  //获取SqlSessionFactory对象
                  sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
      
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
          public static SqlSessionFactory getSqlSessionFactory() {
              return sqlSessionFactory;
          }
      }
      
    • Step1:service包下创建BrandService类来调用mapper包下的BrandMapper接口中的方法,代码如下

      注意:获取SqlSessionFactory对象的代码放在了成员变量的位置,这样所有方法可共用该对象,并不需要重复获取

      package at.guigu.service;
      
      import at.guigu.mapper.BrandMapper;
      import at.guigu.pojo.Brand;
      import at.guigu.util.SqlSessionFactoryUtils;
      import org.apache.ibatis.session.SqlSession;
      import org.apache.ibatis.session.SqlSessionFactory;
      
      import java.io.IOException;
      import java.util.List;
      
      
      public class BrandService {
      
                  //1 获取SqlSessionFactory对象
              SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
          public List<Brand> getAll() throws IOException {
      
              //2 获取SqlSession对象,执行SQL语句
              //2.1 获取SqlSession对象
              SqlSession sqlSession = sqlSessionFactory.openSession();
              //2.2 获取Mapper接口UserMapper的代理对象
              BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
              //2.3 执行sql语句
              List<Brand> brands = brandMapper.selectAll();
              
              sqlSession.close();
              return brands;
          }
      }
      
  • Web层

    • Step1:由于是通过单击页面index.html查询所有从而显示出查询数据,所以首先要创建一个index.html页面,代码如下

      • 注意:html文件名默认为index时,若我们不输入资源则运行该Web项目后浏览器会默认访问到该html页面
      <!DOCTYPE html>
      <html lang="en">
          <head>
              <meta charset="UTF-8">
              <title>Title</title>
          </head>
          <body>
              <a href="/BrandDemo/selectAllServlet">查询所有</a>
          </body>
      </html>
      
    • Step2:创建SelectAllServlet类,且代码如下

      • 注意:创建一个私有的BrandService对象应将其放在成员变量的位置,因为对于大工程来说可能会多次用到Service对象
      package at.guigu.web;
      
      import at.guigu.pojo.Brand;
      import at.guigu.service.BrandService;
      
      import javax.servlet.*;
      import javax.servlet.http.*;
      import javax.servlet.annotation.*;
      import java.io.IOException;
      import java.util.List;
      
      @WebServlet("selectAllServlet")
      public class SelectAllServlet extends HttpServlet {
          //1 创建一个私有的BrandService对象
          private BrandService brandService = new BrandService();
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              //2 调用BrandService中的方法查询所有数据
              List<Brand> brands = brandService.getAll();
      
              //2 存储数据到Request域中
              request.setAttribute("brands", brands);
              //3 转发到brand.jsp中
              request.getRequestDispatcher("/brand.jsp").forward(request, response);
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doGet(request, response);
          }
      }
      
    • Step3:在Web项目核心目录下创建brand.jsp,且代码如下

      <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
      <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
      <html>
          <head>
              <title>Title</title>
          </head>
          <body>
              <input type="button" value="新增"><br>
              <hr>
              <table border="1" cellspacing="0">
                  <tr>
                      <th>序号</th>
                      <th>品牌名称</th>
                      <th>企业名称</th>
                      <th>排序</th>
                      <th>品牌介绍</th>
                      <th>状态</th>
                      <th>操作</th>
                  </tr>
                  <c:forEach items="${brands}" var="brand" varStatus="xuhao">
                      <tr align="center">
                          <td>${xuhao.count}</td>
                          <td>${brand.brandName}</td>
                          <td>${brand.companyName}</td>
                          <td>${brand.ordered}</td>
                          <td>${brand.description}</td>
                          <c:choose>
                              <c:when test="${brand.status==1}">
                                  <td>启用</td>
                              </c:when>
                              <c:otherwise>
                                  <td>禁用</td>
                              </c:otherwise>
                          </c:choose>
                          <td><a href="#">修改</a> <a href="#">删除</a></td>
                      </tr>
                  </c:forEach>
              </table>
          </body>
      </html>
      
  • 三层架构都准备完毕后Tomcat启动该Web项目,Web项目启动成功后会默认运行index.html文件,然后单击查询所有即可跳转到另一页面显示出查询数据,如图所示

    在这里插入图片描述

添加

在这里插入图片描述

  • 解释

    单击新增按钮后跳转到添加品牌的页面(该页面为addBrand.jsp),然后输入要添加的品牌信息后单击提交,提交后浏览器将请求数据提交到服务器的Servlet,然后将数据保存到数据库中,最后重新展示一下查询所有的页面,即可显示出最新的所有数据

  • 各层需要做的工作如图所示

    在这里插入图片描述

  • Dao层/Map层

    • Step1: BrandMapper接口中写入添加数据的方法

      package at.guigu.mapper;
      
      import at.guigu.pojo.Brand;
      import at.guigu.service.BrandService;
      import org.apache.ibatis.annotations.ResultMap;
      import org.apache.ibatis.annotations.Select;
      
      import java.util.List;
      
      public interface BrandMapper {
          //查询并返回所有商品
          /*@Select("select * from tb_brand")
          @ResultMap("brandResultMap")*/
          List<Brand> selectAll();
          //添加商品
          /*
          @Select("insert into tb_brand values(#{brandName},#{companyName},#{ordered},#{description},#{status})")
          */
          void add(Brand brand);
      }
      
      • 注意:
        1. 对数据库中的字段进行结果映射后,若想要用注解方式输写 查询 的SQL语句则需要另外加上注解@ResultMap("brandResultMap"),才能使结果映射生效(结果映射可详见MyBatis那一节)
        2. 由于我在SQL映射文件中输入 查询 的SQL语句,所以不需要代码中的两个注解;若使用MyBatis注解开发(即SQL语句写在注解中)则需要加上以上两个注解
    • Step2: 在对应的SQL映射文件BrandMapper.xml中写入SQL语句

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      
      <!--
          namespace:名称空间
      -->
      <mapper namespace="at.guigu.mapper.BrandMapper">
          <!--结果映射-->
          <resultMap id="brandResultMap" type="brand">
              <!--由于id为主键,且数据库中的字段名和对应结果映射的目标类中的属性名一样,所以此处不需要主键映射,只需进行非主键映射即可-->
              <result column="brand_name" property="brandName"/>
              <result column="company_name" property="companyName"/>
          </resultMap>
      
          <!--
              id:为sql语句的唯一标识
              resultType:为对应sql语句执行完毕后返回结果的类型
          -->
          <select id="selectAll" resultMap="brandResultMap">
              select * from tb_brand;
          </select>
          <insert id="add">
              insert into tb_brand values (null, #{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
          </insert>
      </mapper>
      
  • Service层

    • 工具类SqlSessionFactoryUtils代码省略,详见查询所有中的SqlSessionFactoryUtils代码

    • Step1: 在service包下创建BrandService类来调用mapper包下的BrandMapper接口中的方法,代码如下

      package at.guigu.service;
      
      import at.guigu.mapper.BrandMapper;
      import at.guigu.pojo.Brand;
      import at.guigu.util.SqlSessionFactoryUtils;
      import org.apache.ibatis.session.SqlSession;
      import org.apache.ibatis.session.SqlSessionFactory;
      
      import java.io.IOException;
      import java.util.List;
      
      
      public class BrandService {
      
          //1 获取SqlSessionFactory对象
          SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
          /**
           * 查询所有
           * @return
           * @throws IOException
           */
          public List<Brand> getAll() throws IOException {
      
              //2 获取SqlSession对象,执行SQL语句
              //2.1 获取SqlSession对象
              SqlSession sqlSession = sqlSessionFactory.openSession();
              //2.2 获取Mapper接口UserMapper的代理对象
              BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
              //2.3 执行sql语句
              List<Brand> brands = brandMapper.selectAll();
      
              sqlSession.close();
              return brands;
          }
          
          /**
           * 添加品牌
           * @param brand
           */
          public void add(Brand brand){
              //2 获取SqlSession对象,执行SQL语句
              //2.1 获取SqlSession对象
              SqlSession sqlSession = sqlSessionFactory.openSession();
              //2.2 获取Mapper接口UserMapper的代理对象
              BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
              //2.3 执行添加品牌的sql语句
              brandMapper.add(brand);
      
              //3 注意:增删改的SQL语句需要手动提交事务让其生效
              sqlSession.commit();
      
              //释放资源
              sqlSession.close();
          }
      }
      
  • Web层

    • Step1:在Web项目核心目录下创建addBrand.jsp,且代码如下

      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <html>
          <head>
              <title>添加品牌</title>
          </head>
          <body>
              <h3>添加品牌</h3>
              <!--action的属性值为浏览器提交到服务器的资源路径-->
              <form action="/BrandDemo/addServlet" method="post">
                  品牌名称:<input name="brandName"><br>
                  企业名称:<input name="companyName"><br>
                  排序:<input name="ordered"><br>
                  描述信息:<testarea rows="5" cols="20" name="description"></testarea><br>
                  状态:
                      <input type="radio" name="status" value="0">禁用
                      <input type="radio" name="status" value="1">禁用<br>
                  <input type="submit" value="提交">
              </form>
          </body>
      </html>
      
    • Step2:通过JavaScript代码来为brand.jsp中的新增按钮添加鼠标单击事件 (可详见前端知识点汇总),单击新增按钮后页面跳转到添加品牌的页面(即addBrand.jsp)代码如下所示

      <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
      <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
      <html>
          <head>
              <title>Title</title>
          </head>
          <body>
              <input type="button" value="新增" id="add"><br>
              <hr>
              <table border="1" cellspacing="0">
                  <tr>
                      <th>序号</th>
                      <th>品牌名称</th>
                      <th>企业名称</th>
                      <th>排序</th>
                      <th>品牌介绍</th>
                      <th>状态</th>
                      <th>操作</th>
                  </tr>
                  <c:forEach items="${brands}" var="brand" varStatus="xuhao">
                      <tr align="center">
                          <td>${xuhao.count}</td>
                          <td>${brand.brandName}</td>
                          <td>${brand.companyName}</td>
                          <td>${brand.ordered}</td>
                          <td>${brand.description}</td>
                          <c:choose>
                              <c:when test="${brand.status==1}">
                                  <td>启用</td>
                              </c:when>
                              <c:otherwise>
                                  <td>禁用</td>
                              </c:otherwise>
                          </c:choose>
                          <td><a href="#">修改</a> <a href="#">删除</a></td>
                      </tr>
                  </c:forEach>
              </table>
              <script>
                  document.getElementById("add").onclick = function () {
                      //addBrand.jsp的路径
                      location.href = "/BrandDemo/addBrand.jsp";
                  }
              </script>
          </body>
      </html>
      
    • Step3:创建AddServlet类,且代码如下

      package at.guigu.web;
      
      import at.guigu.pojo.Brand;
      import at.guigu.service.BrandService;
      
      import javax.servlet.*;
      import javax.servlet.http.*;
      import javax.servlet.annotation.*;
      import java.io.IOException;
      
      @WebServlet("/addServlet")
      public class AddServlet extends HttpServlet {
          //1 创建一个私有的BrandService对象
          private BrandService brandService = new BrandService();
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              //添加数据时注意要处理中文乱码问题
              //处理post请求乱码
              request.setCharacterEncoding("UTF-8");
      
              //2 接收表单提交的数据并封装为Brand对象
              String brandName = request.getParameter("brandName");
              String companyName = request.getParameter("companyName");
              String ordered = request.getParameter("ordered");
              String description = request.getParameter("description");
              String status = request.getParameter("status");
              Brand brand = new Brand();
              brand.setBrandName(brandName);
              brand.setCompanyName(companyName);
              //将字符串数字先转换为Integer类型在存入Brand中
              brand.setOrdered(Integer.parseInt(ordered));
              brand.setDescription(description);
              brand.setStatus(Integer.parseInt(status));
      
              //3 调用brandService完成添加
              brandService.add(brand);
      
              //转发到查询所有的Servlet
              request.getRequestDispatcher("/selectAllServlet").forward(request, response);
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doGet(request, response);
          }
      }
      
  • 三层架构都准备完毕后Tomcat启动该Web项目,Web项目启动成功后会默认运行index.html文件,然后单击查询所有即可跳转到另一页面显示出查询数据,之后单击新增按钮,填写完新增数据后单击提交按钮,数据被提交到数据库保存,然后页面会自动跳转到查询所有的页面,显示出所有品牌数据,如图所示

    在这里插入图片描述

修改——回显数据

在这里插入图片描述

  • 解释

    单击对应品牌的修改按钮后,会跳转到新的页面(该页面为update.jsp),该页面会显示你要修改的品牌上次所保存的内容

  • 各层需要做的工作如图所示

    在这里插入图片描述

  • Dao层/Map层

    • Step1: BrandMapper接口中写入修改数据的方法

      package at.guigu.mapper;
      
      import at.guigu.pojo.Brand;
      import at.guigu.service.BrandService;
      import org.apache.ibatis.annotations.Insert;
      import org.apache.ibatis.annotations.ResultMap;
      import org.apache.ibatis.annotations.Select;
      
      import java.util.List;
      
      public interface BrandMapper {
          /*@Select("select * from tb_brand")
          @ResultMap("brandResultMap")*/
          List<Brand> selectAll();
          //@Insert("insert into tb_brand values (null, #{brandName}, #{companyName}, #{ordered}, #{description}, #{status})")
          void add(Brand brand);
          //修改——回显数据
          void selectById(int id);
      }
      
    • Step2: 在对应的SQL映射文件BrandMapper.xml中写入SQL语句

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      
      <!--
          namespace:名称空间
      -->
      <mapper namespace="at.guigu.mapper.BrandMapper">
          <!--结果映射-->
          <resultMap id="brandResultMap" type="brand">
              <!--由于id为主键,且数据库中的字段名和对应结果映射的目标类中的属性名一样,所以此处不需要主键映射,只需进行非主键映射即可-->
              <result column="brand_name" property="brandName"/>
              <result column="company_name" property="companyName"/>
          </resultMap>
      
          <!--
              id:为sql语句的唯一标识
              resultType:为对应sql语句执行完毕后返回结果的类型
          -->
          <!--查询所有品牌-->
          <select id="selectAll" resultMap="brandResultMap">
              select * from tb_brand;
          </select>
          <!--添加品牌-->
          <insert id="add">
              insert into tb_brand values (null, #{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
          </insert>
          <!--修改——回显数据:根据id查询-->
          <select id="selectById" resultMap="brandResultMap">
              select * from tb_brand where id = #{id};
          </select>
      </mapper>
      
  • Service层

    • 工具类SqlSessionFactoryUtils代码省略,详见查询所有中的SqlSessionFactoryUtils代码

    • Step1: 在service包下创建BrandService类来调用mapper包下的BrandMapper接口中的方法,代码如下

      package at.guigu.service;
      
      import at.guigu.mapper.BrandMapper;
      import at.guigu.pojo.Brand;
      import at.guigu.util.SqlSessionFactoryUtils;
      import org.apache.ibatis.session.SqlSession;
      import org.apache.ibatis.session.SqlSessionFactory;
      
      import java.io.IOException;
      import java.util.List;
      
      
      public class BrandService {
      
          //1 获取SqlSessionFactory对象
          SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
          /**
           * 查询所有
           * @return
           * @throws IOException
           */
          public List<Brand> getAll() throws IOException {
      
              //2 获取SqlSession对象,执行SQL语句
              //2.1 获取SqlSession对象
              SqlSession sqlSession = sqlSessionFactory.openSession();
              //2.2 获取Mapper接口UserMapper的代理对象
              BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
              //2.3 执行sql语句
              List<Brand> brands = brandMapper.selectAll();
      
              sqlSession.close();
              return brands;
          }
          /**
           * 添加品牌
           * @param brand
           */
          public void add(Brand brand){
              //2 获取SqlSession对象,执行SQL语句
              //2.1 获取SqlSession对象
              SqlSession sqlSession = sqlSessionFactory.openSession();
              //2.2 获取Mapper接口UserMapper的代理对象
              BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
              //2.3 执行添加品牌的sql语句
              brandMapper.add(brand);
      
              //3 注意:增删改的SQL语句需要手动提交事务让其生效
              sqlSession.commit();
      
              //释放资源
              sqlSession.close();
          }
      
          /**
           * 修改——回显数据:根据id查询
           * @param id
           * @return
           * @throws IOException
           */
          public Brand selectById(int id) throws IOException {
              //2 获取SqlSession对象,执行SQL语句
              //2.1 获取SqlSession对象
              SqlSession sqlSession = sqlSessionFactory.openSession();
              //2.2 获取Mapper接口UserMapper的代理对象
              BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
              //2.3 执行修改——回显数据的sql语句
              Brand brand = brandMapper.selectById(id);
              //释放资源
              sqlSession.close();
              return brand;
          }
      }
      
  • Web层

    • Step1:在Web项目核心目录下创建update.jsp,且代码如下

      <%--
        Created by IntelliJ IDEA.
        User: 10195
        Date: 2024/6/30
        Time: 16:49
        To change this template use File | Settings | File Templates.
      --%>
      <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
      <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
      <html>
          <head>
              <title>修改品牌</title>
          </head>
          <body>
              <h3>修改品牌</h3>
              <!--action的属性值为浏览器提交到服务器的资源路径-->
              <form action="/BrandDemo/addServlet" method="post">
                  品牌名称:<input name="brandName" value="${brand.brandName}"><br>
                  企业名称:<input name="companyName" value="${brand.companyName}"><br>
                  排序:<input name="ordered" value="${brand.ordered}"><br>
                  描述信息:<textarea rows="5" cols="20" name="description">${brand.description}</textarea><br>
                  状态:
                  <c:choose>
                      <c:when test="${brand.status == 0}">
                          <input type="radio" name="status" value="0" checked>禁用
                          <input type="radio" name="status" value="1">启用<br>
                      </c:when>
                      <c:otherwise>
                          <input type="radio" name="status" value="0">禁用
                          <input type="radio" name="status" value="1" checked>启用<br>
                      </c:otherwise>
                  </c:choose>
                  <input type="submit" value="提交">
              </form>
          </body>
      </html>
      
    • Step2:通过JavaScript代码来为brand.jsp中的修改按钮添加鼠标单击事件 (可详见前端知识点汇总),单击修改按钮后页面会根据id跳转到对应品牌的页面(即.jsp),代码如下所示

      <%--
        Created by IntelliJ IDEA.
        User: 10195
        Date: 2024/6/28
        Time: 19:40
        To change this template use File | Settings | File Templates.
      --%>
      <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
      <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
      <html>
          <head>
              <title>Title</title>
          </head>
          <body>
              <input type="button" value="新增" id="add"><br>
              <hr>
              <table border="1" cellspacing="0">
                  <tr>
                      <th>序号</th>
                      <th>品牌名称</th>
                      <th>企业名称</th>
                      <th>排序</th>
                      <th>品牌介绍</th>
                      <th>状态</th>
                      <th>操作</th>
                  </tr>
                  <c:forEach items="${brands}" var="brand" varStatus="xuhao">
                      <tr align="center">
                          <td>${xuhao.count}</td>
                          <td>${brand.brandName}</td>
                          <td>${brand.companyName}</td>
                          <td>${brand.ordered}</td>
                          <td>${brand.description}</td>
                          <c:choose>
                              <c:when test="${brand.status==1}">
                                  <td>启用</td>
                              </c:when>
                              <c:otherwise>
                                  <td>禁用</td>
                              </c:otherwise>
                          </c:choose>
                          <td><a href="/BrandDemo/selectByIdServlet?id=${brand.id}">修改</a> <a href="#">删除</a></td>
                      </tr>
                  </c:forEach>
              </table>
              <script>
                  document.getElementById("add").onclick = function () {
                      //addBrand.jsp的路径
                      location.href = "/BrandDemo/addBrand.jsp";
                  }
              </script>
          </body>
      </html>
      
    • Step3:创建SelectByIdServlet类,且代码如下

      package at.guigu.web;
      
      import at.guigu.pojo.Brand;
      import at.guigu.service.BrandService;
      
      import javax.servlet.*;
      import javax.servlet.http.*;
      import javax.servlet.annotation.*;
      import java.io.IOException;
      
      @WebServlet("/selectByIdServlet")
      public class SelectByIdServlet extends HttpServlet {
          //1 创建一个私有的BrandService对象
          private BrandService brandService = new BrandService();
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              //2 接收id
              String id = request.getParameter("id");
              //3 调用对应的Service查询
              Brand brand = brandService.selectById(Integer.parseInt(id));
              //4 将该Brand对象存储到request域中
              request.setAttribute("brand", brand);
              //5 转发到update.jsp中
              request.getRequestDispatcher("/update.jsp").forward(request,response);
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doGet(request, response);
          }
      }
      
  • 三层架构都准备完毕后Tomcat启动该Web项目,Web项目启动成功后会默认运行index.html文件,然后单击查询所有即可跳转到另一页面显示出查询数据,之后单击修改按钮后会自动跳转到修改品牌页面,如图所示

    在这里插入图片描述

修改——修改数据

在这里插入图片描述

  • 解释:修改数据是在回显数据的基础上进行操作的,即对update.jsp页面的表单进行修改后单击提交按钮,将数据保存到数据库中,最后重现展示一下查询所有的页面,即可显示出最新的所有数据

  • 各层需要做的工作如图所示

    在这里插入图片描述

  • Dao层/Map层

    • Step1: BrandMapper接口中写入修改数据的方法

      package at.guigu.mapper;
      
      import at.guigu.pojo.Brand;
      import at.guigu.service.BrandService;
      import org.apache.ibatis.annotations.Insert;
      import org.apache.ibatis.annotations.ResultMap;
      import org.apache.ibatis.annotations.Select;
      
      import java.util.List;
      
      public interface BrandMapper {
          /*@Select("select * from tb_brand")
          @ResultMap("brandResultMap")*/
          List<Brand> selectAll();
          //@Insert("insert into tb_brand values (null, #{brandName}, #{companyName}, #{ordered}, #{description}, #{status})")
          void add(Brand brand);
      
          /**
           * //修改——回显数据:根据id查询
           * @param id
           * @return
           */
          /*@Select("select * from tb_brand where id = #{id}")
          @ResultMap("brandResultMap")*/
          Brand selectById(int id);
          
          //修改——修改数据
          void update(Brand brand);
      }
      
    • Step2: 在对应的SQL映射文件BrandMapper.xml中写入SQL语句

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      
      <!--
          namespace:名称空间
      -->
      <mapper namespace="at.guigu.mapper.BrandMapper">
          <!--结果映射-->
          <resultMap id="brandResultMap" type="brand">
              <!--由于id为主键,且数据库中的字段名和对应结果映射的目标类中的属性名一样,所以此处不需要主键映射,只需进行非主键映射即可-->
              <result column="brand_name" property="brandName"/>
              <result column="company_name" property="companyName"/>
          </resultMap>
      
          <!--
              id:为sql语句的唯一标识
              resultType:为对应sql语句执行完毕后返回结果的类型
          -->
          <!--查询所有品牌-->
          <select id="selectAll" resultMap="brandResultMap">
              select * from tb_brand;
          </select>
          <!--添加品牌-->
          <insert id="add">
              insert into tb_brand values (null, #{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
          </insert>
          <!--修改——回显数据:根据id查询-->
          <select id="selectById" resultMap="brandResultMap">
              select * from tb_brand where id = #{id};
          </select>
      
          <!--修改——修改数据-->
          <update id="update">
              update tb_brand
              set brand_name=#{brandName},
                  company_name=#{companyName},
                  ordered=#{ordered},
                  description=#{description},
                  status=#{status}
              where id=#{id};
          </update>
      </mapper>
      
  • Service层

    • 工具类SqlSessionFactoryUtils代码省略,详见查询所有中的SqlSessionFactoryUtils代码

    • Step1: 在service包下创建BrandService类来调用mapper包下的BrandMapper接口中的方法,代码如下

      package at.guigu.service;
      
      import at.guigu.mapper.BrandMapper;
      import at.guigu.pojo.Brand;
      import at.guigu.util.SqlSessionFactoryUtils;
      import org.apache.ibatis.session.SqlSession;
      import org.apache.ibatis.session.SqlSessionFactory;
      
      import java.io.IOException;
      import java.util.List;
      
      
      public class BrandService {
      
          //1 获取SqlSessionFactory对象
          SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
          /**
           * 查询所有
           * @return
           * @throws IOException
           */
          public List<Brand> getAll() throws IOException {
      
              //2 获取SqlSession对象,执行SQL语句
              //2.1 获取SqlSession对象
              SqlSession sqlSession = sqlSessionFactory.openSession();
              //2.2 获取Mapper接口UserMapper的代理对象
              BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
              //2.3 执行sql语句
              List<Brand> brands = brandMapper.selectAll();
      
              sqlSession.close();
              return brands;
          }
          /**
           * 添加品牌
           * @param brand
           */
          public void add(Brand brand){
              //2 获取SqlSession对象,执行SQL语句
              //2.1 获取SqlSession对象
              SqlSession sqlSession = sqlSessionFactory.openSession();
              //2.2 获取Mapper接口UserMapper的代理对象
              BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
              //2.3 执行添加品牌的sql语句
              brandMapper.add(brand);
      
              //3 注意:增删改的SQL语句需要手动提交事务让其生效
              sqlSession.commit();
      
              //释放资源
              sqlSession.close();
          }
      
          /**
           * 修改——回显数据:根据id查询
           * @param id
           * @return
           */
          public Brand selectById(int id){
              //2 获取SqlSession对象,执行SQL语句
              //2.1 获取SqlSession对象
              SqlSession sqlSession = sqlSessionFactory.openSession();
              //2.2 获取Mapper接口UserMapper的代理对象
              BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
              //2.3 执行修改——回显数据的sql语句
              Brand brand = brandMapper.selectById(id);
              //释放资源
              sqlSession.close();
              return brand;
          }
          
              /**
           * 修改——修改数据
           * @param brand
           */
          public void update(Brand brand) {
              //2 获取SqlSession对象,执行SQL语句
              //2.1 获取SqlSession对象
              SqlSession sqlSession = sqlSessionFactory.openSession();
              //2.2 获取Mapper接口UserMapper的代理对象
              BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
              //2.3 执行修改——修改数据的sql语句
              brandMapper.update(brand);
      
              //3 注意:增删改的SQL语句需要手动提交事务让其生效
              sqlSession.commit();
              
              //释放资源
              sqlSession.close();
          }
      }
      
  • Web层

    • Step1:修改在回显数据内容中的update.jsp,代码如下

      • 注意:由于是通过id进行品牌数据的修改,所以需要将id提交到服务端
      <%--
        Created by IntelliJ IDEA.
        User: 10195
        Date: 2024/6/30
        Time: 16:49
        To change this template use File | Settings | File Templates.
      --%>
      <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
      <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
      <html>
          <head>
              <title>修改品牌</title>
          </head>
          <body>
              <h3>修改品牌</h3>
              <!--action的属性值为浏览器提交到服务器的资源路径-->
              <form action="/BrandDemo/updateServlet" method="post">
                  <%--通过隐藏域提交id,作用:隐藏id的提交--%>
                  <input type="hidden" name="id" value="${brand.id}">
                  品牌名称:<input name="brandName" value="${brand.brandName}"><br>
                  企业名称:<input name="companyName" value="${brand.companyName}"><br>
                  排序:<input name="ordered" value="${brand.ordered}"><br>
                  描述信息:<textarea rows="5" cols="20" name="description">${brand.description}</textarea><br>
                  状态:
                  <c:choose>
                      <c:when test="${brand.status == 0}">
                          <input type="radio" name="status" value="0" checked>禁用
                          <input type="radio" name="status" value="1">启用<br>
                      </c:when>
                      <c:otherwise>
                          <input type="radio" name="status" value="0">禁用
                          <input type="radio" name="status" value="1" checked>启用<br>
                      </c:otherwise>
                  </c:choose>
                  <input type="submit" value="提交">
              </form>
          </body>
      </html>
      
    • Step2:通过JavaScript代码来为brand.jsp中的修改按钮添加鼠标单击事件 (可详见前端知识点汇总),单击修改按钮后页面会根据id跳转到对应品牌的页面(即.jsp),代码详见回显数据部分内容

    • Step3:创建UpdateServlet类,且代码如下

      package at.guigu.web;
      
      import at.guigu.pojo.Brand;
      import at.guigu.service.BrandService;
      
      import javax.servlet.*;
      import javax.servlet.http.*;
      import javax.servlet.annotation.*;
      import java.io.IOException;
      
      @WebServlet("/updateServlet")
      public class UpdateServlet extends HttpServlet {
          //1 创建一个私有的BrandService对象
          private BrandService brandService = new BrandService();
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              //添加数据时注意要处理中文乱码问题
              //处理post请求乱码
              request.setCharacterEncoding("UTF-8");
      
              //2 接收表单提交的修改数据并封装为Brand对象
              String id = request.getParameter("id");
              String brandName = request.getParameter("brandName");
              String companyName = request.getParameter("companyName");
              String ordered = request.getParameter("ordered");
              String description = request.getParameter("description");
              String status = request.getParameter("status");
              Brand brand = new Brand();
              brand.setId(Integer.parseInt(id));
              brand.setBrandName(brandName);
              brand.setCompanyName(companyName);
              //将字符串数字先转换为Integer类型在存入Brand中
              brand.setOrdered(Integer.parseInt(ordered));
              brand.setDescription(description);
              brand.setStatus(Integer.parseInt(status));
      
              //3 调用brandService完成修改
              brandService.update(brand);
      
              //转发到查询所有的Servlet
              request.getRequestDispatcher("/selectAllServlet").forward(request, response);
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doGet(request, response);
          }
      }
      
  • 三层架构都准备完毕后Tomcat启动该Web项目,Web项目启动成功后会默认运行index.html文件,然后单击查询所有即可跳转到另一页面显示出查询数据,之后单击修改按钮后会自动跳转到修改品牌页面,修改完数据后单击提交按钮,数据被提交到数据库保存,然后页面会自动跳转到查询所有的页面,显示出所有品牌数据,如图所示

    在这里插入图片描述


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/767899.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【每日刷题】Day79

【每日刷题】Day79 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 1619. 删除某些元素后的数组均值 - 力扣&#xff08;LeetCode&#xff09; 2. 1365. 有多少小于当前…

Python UUID模块:深入理解与使用技巧

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

Spark入门教程(非常详细)从零基础入门到精通,看完这一篇就够了

文章目录 引言1. Spark 基础 1.1 Spark 为何物1.2 Spark VS Hadoop1.3 Spark 优势及特点 1.3.1 优秀的数据模型和丰富计算抽象1.3.2 完善的生态圈-fullstack1.3.3 spark的特点 1.4 Spark 运行模式 2. Spark Core 2.1 RDD详解 2.1.1 RDD概念2.1.2 RDD属性2.1.3 RDD API 2.1.3.1…

还有人不会挑智能猫砂盆?详细测评热门品牌糯雪、空气萝卜、CEWEY!

在现代家居生活中&#xff0c;宠物已成为许多家庭不可或缺的一员&#xff0c;而猫砂盆作为猫咪日常如厕的重要工具&#xff0c;选择什么类型的智能猫砂盆更是关乎猫咪健康与生活质量的关键。而市面上的智能猫砂盆品类众多&#xff0c;令人在挑选的时候眼花缭乱&#xff0c;不知…

监控平台zabbix对接grafana

目录 1.安装grafana并启动 2.浏览器访问 3.导入zabbix数据&#xff0c;对接grafana 4.如何导入模板 5.使用zabbix监控nginx并发量连接数 5.1 修改nginx配置 5.2 编写监控数据脚本 5.3 设置键值 5.4 在zabbix web端完成自定义监控项 5.5 连接到grafana 以上一篇博客&l…

GCN结合Transformer炸场!性能暴涨74%,效率翻3倍

最近发现了两篇效果很妙的GCN结合Transformer的最新工作&#xff0c;分享给大家&#xff1a; MP-GT&#xff1a;通过结合GCN和Transformer方法来增强App使用预测的准确性&#xff0c;实现了74.02%的性能提升&#xff0c;且训练时间减少了79.47%。 MotionAGFormer&#xff1a;结…

Dubbo简介

Apache Dubbo是一款高性能、轻量级的开源服务框架。 1.单体架构 比如现在有一个学生成绩管理平台&#xff0c;里面有学生管理&#xff0c;教师管理&#xff0c;成绩管理。然后将这个系统打包上线&#xff0c;部署在一个2核4G的服务器上&#xff0c;但是现在用户对成绩管理模块…

Shell Expect自动化交互(示例)

Shell Expect自动化交互 日常linux运维时&#xff0c;经常需要远程登录到服务器&#xff0c;登录过程中需要交互的过程&#xff0c;可能需要输入yes/no等信息&#xff0c;所以就用到expect来实现交互。 关键语法 ❶&#xff3b;#!/usr/bin/expect&#xff3d; 这一行告诉操…

民宿小程序开发,在线预订模式

一、开发背景 如今&#xff0c;随着互联网技术的快速发展&#xff0c;大众的生活消费都集中在了手机上&#xff0c;通过手机进行各种活动&#xff0c;同时也包括了预订酒店民宿&#xff0c;由此&#xff0c;民宿预约小程序出现在了大众的生活中。 二、民宿小程序特点 民宿小…

怎么参与场外期权?

今天期权懂带你了解怎么参与场外期权&#xff1f; 目前个人投资者暂时还不能直接参与场外个股期权&#xff0c;因为场外个股期权现在只能机构来进行交易。 所以个人投资者目前只能通过机构通道来进行操作&#xff0c;类似期权懂&#xff0c;找到期权懂经理&#xff0c;然后通…

深入浅出:C语言线程以及线程锁

目录 线程和线程锁概念 线程锁的概念 线程的特点 线程的使用 创建线程 pthread_create 回收线程pthread_join 退出线程 pthread_exit 线程锁的使用 线程同步之互斥锁&#xff08;Mutex&#xff09; 初始化互斥锁 获取互斥锁 释放互斥锁 销毁互斥锁 初始化条件变量…

SSMOA办公系统-计算机毕业设计源码19159

摘 要 随着现代信息技术的快速发展以及企业规模不断扩大&#xff0c;实现办公线上流程自动化已成为提升企业核心竞争力的关键。本文主要介绍的是利用Spring、SpringMVC和MyBatis&#xff08;简称为&#xff1a;SSM&#xff09;框架&#xff0c;MySQL数据库等先进的互联网开源技…

X86 +PC104+支持WinCE5.0,WinCE6.0,DOS,WinXP, QNX等操作系统,工业控制数据采集核心模块板卡定制

CPU 模块 是一款基于RDC 3306的SOM Express模块。RDC 3306这款X86架构的CPU是一款性能高、稳定性强的处理器。 它是一款灵活精巧的主板&#xff08;尺寸为91.8mm68.6mm&#xff09;&#xff0c;可以灵活的运用于用户的底板&#xff0c;节约开发成本。模块的接插件使用插针形式…

基于PHP花涧订购系统的设计与实现-计算机毕业设计源码00332

摘 要 近年来&#xff0c;电子商务的快速发展引起了行业和学术界的高度关注。花涧订购系统旨在为用户提供一个简单、高效、便捷的花卉购物体验&#xff0c;它不仅要求用户清晰地查看所需信息&#xff0c;而且还要求界面设计精美&#xff0c;使得功能与页面完美融合&#xff0c;…

固定网国内数据传送业务经营许可证

一、国内固定网数据传送业务是什么&#xff1f; 固定网国内数据传送业务是指互联网数据传送业务以外的&#xff0c;在固定网中以有线方式提供的国内端到端数据传送业务。主要包括基于IP承载网、ATM网、X.25分组交换网、DDN网、帧中继网络的数据传送业务等。该业务属于A2类基础…

Vision Transformer论文阅读笔记

目录 An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale -- Vision Transformer摘要Introduction—简介RELATED WORK—相关工作METHOD—方法VISION TRANSFORMER (VIT)—视觉Transformer(ViT) 分析与评估PRE-TRAINING DATA REQUIREMENTS—预训练数据…

PDF文档如何统计字数,统计PDF文档字数的方法有哪些?

在平时使用pdf阅读或者是处理文档的时候&#xff0c;常常需要统计文档的字数。pdf在查看文字时其实很简单。 PDF文档是一种常见的电子文档格式&#xff0c;如果需要对PDF文档中的字数进行统计&#xff0c;可以使用以下方法&#xff1a; Adobe Acrobat DC&#xff1a;Adobe Ac…

【服装识别系统】图像识别+Python+人工智能+深度学习+算法模型+TensorFlow

一、介绍 服装识别系统&#xff0c;本系统作为图像识别方面的一个典型应用&#xff0c;使用Python作为主要编程语言&#xff0c;并通过TensorFlow搭建ResNet50卷积神经算法网络模型&#xff0c;通过对18种不同的服装&#xff08;‘黑色连衣裙’, ‘黑色衬衫’, ‘黑色鞋子’, …

从 ClickHouse 到 Apache Doris:快成物流的数智化货运应用实践

导读&#xff1a;随着快成物流的大宗商品产业链的不断发展&#xff0c;货运轨迹规划和实时数据分析的需求日益迫切&#xff0c;为了保障数据报表更新、用户画像圈选与物流轨迹实时更新等大数据核心系统性能&#xff0c;快成物流引入 Apache Doris 实时数仓升级了大数据算法平台…

乘积最大子数组

代码实现&#xff1a; 方法一&#xff1a;暴力法 方法二&#xff1a;动态规划 int maxProduct(int *nums, int numsSize) {long imax nums[0], imin nums[0], res nums[0];for (int i 1; i < numsSize; i) {if (nums[i] < 0) {int temp imax;imax imin;imin temp;…