JSP

**JSP(全称:Java Server Pages):Java 服务端页面。**是一种动态的网页技术,其中既可以定义 HTML、JS、CSS等静态内容,还可以定义 Java代码的动态内容,也就是 JSP = HTML + Java。如下就是jsp代码

<html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <h1>JSP,Hello World</h1>
        <%
        	System.out.println("hello,jsp~");
        %>
    </body>
</html>

上面代码 h1 标签内容是展示在页面上,而 Java 的输出语句是输出在 idea 的控制台。

JSP本质是Servlet

1. JSP快速入门

  1. 创建一个web项目,pom.xml依赖坐标如下

    <dependencies>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>4.0.1</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>javax.servlet.jsp</groupId>
                <artifactId>jsp-api</artifactId>
                <version>2.2</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>
    

    JSP本质是Servlet,所以需要导入S ervlet依赖,且两个 scope 必须设置为 provided,因为 tomcat 中有这两jar包了,所以在打包时我们是不希望将该依赖打进到我们工程的war包中。

  2. 在项目的 webapp 下创建hello.jsp页面

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <h1>hello jsp</h1>
    
        <%
            System.out.println("hello,jsp~");
        %>
    </body>
    </html>
    
  3. 启动web项目,在地址栏输入http://localhost:8080/jsp-demo/hello.jsp,访问jsp

1.1 Jsp原理

探索JSP访问流程

  1. 浏览器第一次访问 hello.jsp 页面
  2. tomcat 会将 hello.jsp 转换为名为 hello_jsp.java 的一个 Servlet
  3. tomcat 再将转换的 servlet 编译成字节码文件 hello_jsp.class
  4. tomcat 会执行该字节码文件,向外提供服务

我们可以到项目所在磁盘目录下找 target\tomcat\work\Tomcat\localhost\jsp-demo\org\apache\jsp 目录,而这个目录下就能看到转换后的 servlet

out.write("\n");
            out.write("\n");
            out.write("<html>\n");
            out.write("<head>\n");
            out.write("    <title>Hello JSP</title>\n");
            out.write("</head>\n");
            out.write("<body>\n");
            out.write("<h1>hello jsp</h1>\n");
            System.out.println("welcome jsp");
            out.write("\n");
            out.write("<input type=\"button\" value=\"新增\"><br>\n");
            out.write("<hr>\n");
            out.write("\n");

1.2 JSP 脚本

JSP脚本用于在 JSP页面内定义 Java代码

JSP 脚本有如下三个分类:

  • <%...%>:内容会直接放到_jspService()方法之中

    <%%>数据定义在了 _jspService() 方法中

  • <%=…%>:内容会放到out.print()中,作为out.print()的参数

    <%="hello"%>相当于out.write("hello")

  • <%!…%>:内容会放到_jspService()方法之外,被类直接包含

    <%! int i = 3; %>定义的内容在class成员位置

代码示例

<%--这个是定义在_jspService中--%>
    <%
    int i = 3;
    %>
<%--这个内容被放在`out.print()` 中,out.print("你好呀")--%>
    <%="你好呀"%>

<%--    这个定义在Servlet class成员位置,成员变量,和方法--%>
    <%!
    void show(){};
    public String str = "Welcome";
    %>

1.3 案例

使用JSP脚本展示品牌数据

代码实现

<%@ page import="com.example.pojo.Brand" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.List" %>
<%--
  Created by IntelliJ IDEA.
  User: hades
  Date: 2022/5/16
  Time: 11:50 上午
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Hello JSP</title>
</head>
<body>
<h1>hello jsp</h1>
<%
    System.out.println("welcome jsp");
%>
<input type="button" value="新增"><br>
<hr>

<%
    // 查询数据库
    List<Brand> brands = new ArrayList<Brand>();
    brands.add(new Brand(1,"三只松鼠","三只松鼠",100,"三只松鼠,好吃不上火",1));
    brands.add(new Brand(2,"优衣库","优衣库",200,"优衣库,服适人生",0));
    brands.add(new Brand(3,"小米","小米科技有限公司",1000,"为发烧而生",1));
%>
<table border="1" cellspacing="0" width="800">
    <tr>
        <th>序号</th>
        <th>品牌名称</th>
        <th>企业名称</th>
        <th>排序</th>
        <th>品牌介绍</th>
        <th>状态</th>
        <th>操作</th>
    </tr>
    <%
        for (Brand brand : brands) {
            %>
        <tr align="center">
            <td><%=brand.getId()%></td>
            <td><%=brand.getBrandName()%></td>
            <td><%=brand.getCompanyName()%></td>
            <td><%=brand.getOrdered()%></td>
            <td><%=brand.getDescription()%></td>
            <td><%=brand.getStatus() == 1 ? "启用":"禁用"%></td>
            <td><a href="#">修改</a> <a href="#">删除</a></td>
        </tr>
    <%
        }
    %>

<!--
    <tr align="center">
        <td>1</td>
        <td>三只松鼠</td>
        <td>三只松鼠</td>
        <td>100</td>
        <td>三只松鼠,好吃不上火</td>
        <td>启用</td>
        <td><a href="#">修改</a> <a href="#">删除</a></td>
    </tr>

    <tr align="center">
        <td>2</td>
        <td>优衣库</td>
        <td>优衣库</td>
        <td>10</td>
        <td>优衣库,服适人生</td>
        <td>禁用</td>

        <td><a href="#">修改</a> <a href="#">删除</a></td>
    </tr>

    <tr align="center">
        <td>3</td>
        <td>小米</td>
        <td>小米科技有限公司</td>
        <td>1000</td>
        <td>为发烧而生</td>
        <td>启用</td>

        <td><a href="#">修改</a> <a href="#">删除</a></td>
    </tr>
    -->
<%--这个是定义在_jspService中--%>
    <%
    int i = 3;
    %>
<%--这个内容被放在`out.print()` 中,out.print("你好呀")--%>
    <%="你好呀"%>

<%--    这个定义在Servlet class成员位置,成员变量,和方法--%>
    <%!
    void show(){};
    public String str = "Welcome";
    %>
</table>
</body>
</html>

1.4 JSP缺点

通过上面的案例,我们可以看到 JSP 的很多缺点。

由于 JSP页面内,既可以定义 HTML 标签,又可以定义 Java代码,造成了以下问题:

  • 书写麻烦:特别是复杂的页面

    既要写 HTML 标签,还要写 Java 代码

  • 阅读麻烦

    上面案例的代码,相信你后期再看这段代码时还需要花费很长的时间去梳理

  • 复杂度高:运行需要依赖于各种环境,JRE,JSP容器,JavaEE…

  • 占内存和磁盘:JSP会自动生成.java和.class文件占磁盘,运行的是.class文件占内存

  • 调试困难:出错后,需要找到自动生成的.java文件进行调试

  • 不利于团队协作:前端人员不会 Java,后端人员不精 HTML

    如果页面布局发生变化,前端工程师对静态页面进行修改,然后再交给后端工程师,由后端工程师再将该页面改为 JSP 页面

由于上述的问题, **JSP 已逐渐退出历史舞台,**以后开发更多的是使用 HTML + Ajax 来替代。Ajax 是我们后续会重点学习的技术。有个这个技术后,前端工程师负责前端页面开发,而后端工程师只负责前端代码开发。下来对技术的发展进行简单的说明

  1. 第一阶段:使用 servlet 即实现逻辑代码编写,也对页面进行拼接。这种模式我们之前也接触过

  2. 第二阶段:随着技术的发展,出现了 JSP ,人们发现 JSP 使用起来比 Servlet 方便很多,但是还是要在 JSP 中嵌套 Java 代码,也不利于后期的维护

  3. 第三阶段:使用 Servlet 进行逻辑代码开发,而使用 JSP 进行数据展示

  4. 第四阶段:使用 servlet 进行后端逻辑代码开发,而使用 HTML 进行数据展示。而这里面就存在问题,HTML 是静态页面,怎么进行动态数据展示呢?这就是 ajax 的作用了。

那既然 JSP 已经逐渐的退出历史舞台,那我们为什么还要学习 JSP 呢?原因有两点:

  • 一些公司可能有些老项目还在用 JSP ,所以要求我们必须动 JSP
  • 我们如果不经历这些复杂的过程,就不能体现后面阶段开发的简单

接下来我们来学习第三阶段,使用 EL表达式JSTL 标签库替换 JSP 中的 Java 代码。

2. EL 表达式

EL(全称Expression Language )表达式语言,用于简化 JSP 页面内的 Java 代码。

EL 表达式的主要作用是 获取数据。其实就是从域对象中获取数据,然后将数据展示在页面上。

而 EL 表达式的语法也比较简单,${expression} 。例如:${brands} 就是获取域中存储的 key 为 brands 的数据。

需求:把上面在jsp中使用Java代码的按钮在jsp中使用EL表达式实现

2.1 案例

  1. 定义Servlet

    package com.example.web;
    
    import com.example.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("/demo1")
    public class ServletDemo1 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            List<Brand> brands = new ArrayList<Brand>();
            brands.add(new Brand(1,"三只松鼠","三只松鼠",100,"三只松鼠,好吃不上火",1));
            brands.add(new Brand(2,"优衣库","优衣库",200,"优衣库,服适人生",0));
            brands.add(new Brand(3,"小米","小米科技有限公司",1000,"为发烧而生",1));
    //      存储数据
            request.setAttribute("list", brands);
    //        转发到jsp
            request.getRequestDispatcher("/el-demo.jsp").forward(request,response);
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doGet(request, response);
        }
    }
    
    
    
  2. el-demo.jsp 中通过 EL表达式 获取数据

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>el表达式</title>
    </head>
    <body>
    ${list}
    </body>
    </html>
    
    
  3. 浏览器输出List结果如下

    [Brand{id=1, brandName='三只松鼠', companyName='三只松鼠', ordered=100, description='三只松鼠,好吃不上火', status=1}, Brand{id=2, brandName='优衣库', companyName='优衣库', ordered=200, description='优衣库,服适人生', status=0}, Brand{id=3, brandName='小米', companyName='小米科技有限公司', ordered=1000, description='为发烧而生', status=1}]
    

3. 域对象

JavaWeb中有四大域对象,分别是:

  • page:当前页面有效
  • request:当前请求有效
  • session:当前会话有效
  • application:当前应用有效

el 表达式获取数据,会依次从这4个域中寻找,直到找到为止。而这四个域对象的作用范围如下图所示

例如: ${list},el 表达式获取数据,会先从page域对象中获取数据,如果没有再到 requet 域对象中获取数据,如果再没有再到 session 域对象中获取,如果还没有才会到 application 中获取数据。

4. JSTL标签

JSP标准标签库(Jsp Standarded Tag Library) ,使用标签取代JSP页面上的Java代码。如下代码就是JSTL标签

JSTL 提供了很多标签

标签描述
<c:out>用于在JSP中显示数据,就像<%=“hello”%>
<c:set>用于保存数据
<c:remove>用于删除数据
<c:catch>用于处理产生错误的异常状况,并将错误信息存储起来
<c:if>和Java中的if判断一样
<c:choose>本身当做<c:when> 和 <c:otherwise>的父标签
<c:when><c:choose>的子标签,用来判断是否成立,相对于Java switch
<c:otherwise><c:choose>的子标签,接在<c:when>后面,当<c:when>为false后执行
<c:import>检索一个绝对或相对URL,然后将其暴露给页面
<c:forEach>基础迭代,相当于Java for
<c:forTokens>根据指定的分隔符分割内容,并迭代输出
<c:param>用于给包含或重定向的页面传递参数
<c:redirect>重定向至一个新的URL
<c:url>使用可选参数来创建一个新的URL

我们只对两个最常用的标签进行讲解,<c:forEach> 标签和 <c:if> 标签。

4.1 JSTL使用

  1. 导入坐标

    <!--        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>
                <classifier>sources</classifier>
                <type>jar.sha256</type>
            </dependency>
    
  2. 在JSP页面上引入JSTL标签库

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

    4.1.1 if标签

    属性:test,用于定义条件表达式

    <c:if test="${status ==1}">
        启用
    </c:if>
    
    <c:if test="${status ==0}">
        禁用
    </c:if>
    

    代码演示

    定义一个 servlet ,在该 servlet 中向 request 域对象中添加 键是 status ,值为 1 的数据

    @WebServlet("/servletDemo2")
    public class ServletDemo2 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            request.setAttribute("status",1);
            request.getRequestDispatcher("/jstl-demo.jsp").forward(request,response);
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doGet(request, response);
        }
    }
    

    定义 jstl-demo.jsp 页面,在该页面使用 <c:if> 标签

    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>JSTL标签Demo</title>
    </head>
    <body>
    <c:if test="${status ==1}">
        启用
    </c:if>
    
    <c:if test="${status ==0}">
        禁用
    </c:if>
    </body>
    </html>
    

4.2 forEach 标签

<c:forEach>:相当于 for 循环。java中有增强for循环和普通for循环,JSTL 中的 <c:forEach> 也有两种用法

用法一

类似于 Java 中的增强for循环。涉及到的 <c:forEach> 中的属性如下

  • items:被遍历的容器

  • var:遍历产生的临时变量

  • varStatus:遍历状态对象

如下代码,是从域对象中获取名为 brands 数据,该数据是一个集合;遍历遍历,并给该集合中的每一个元素起名为 brand,是 Brand对象。在循环里面使用 EL表达式获取每一个Brand对象的属性值

<c:forEach items="${brands}" var="brand">
    <tr align="center">
        <td>${brand.id}</td>
        <td>${brand.brandName}</td>
        <td>${brand.companyName}</td>
        <td>${brand.description}</td>
    </tr>
</c:forEach>

代码演示:

在servlet里面向jsp转发list,此处忽略。

jstl-demo.jsp代码如下

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>JSTL标签Demo</title>
</head>
<body>
<c:if test="${status ==1}">
    启用
</c:if>

<c:if test="${status ==0}">
    禁用
</c:if>

<table border="1" cellspacing="0" width="800">
    <tr>
        <th>序号</th>
        <th>品牌名称</th>
        <th>企业名称</th>
        <th>排序</th>
        <th>品牌介绍</th>
        <th>状态</th>
        <th>操作</th>
    </tr>
    <c:forEach items="${list}" var="item" varStatus="status">
        <tr align="center">
                <%--<td>${brand.id}</td>--%>
            <td>${status.count}</td><!-- id:可以是数据库索引(有时候索引不一定是从小到大),可以是查询数据的角标索引 -->
            <td>${item.brandName}</td>
            <td>${item.companyName}</td>
            <td>${item.ordered}</td>
            <td>${item.description}</td>
            <c:if test="${item.status==1}">
                <td>启用</td>
            </c:if>
            <c:if test="${item.status!=1}">
                <td>禁用</td>
            </c:if>
            <td><a href="#">修改</a> <a href="#">删除</a></td>
        </tr>
    </c:forEach>
</table>
</body>
</html>

用法二

类似于 Java 中的普通for循环。涉及到的 <c:forEach> 中的属性如下

  • begin:开始数
  • end:结束数
  • step:步长

实例代码:

从0循环到10,变量名是 i ,每次自增1

<c:forEach begin="0" end="10" step="1" var="i">
    <a href="#">${i}</a>
</c:forEach>

5. MVC模式和三层架构

5.1 MVC模式

MVC 是一种分层开发的模式,其中:

  • M:Model,业务模型,处理业务

  • V:View,视图,界面展示

  • C:Controller,控制器,处理请求,调用模型和视图

Controller(serlvlet)用来接收浏览器发送过来的请求,控制器调用Model(JavaBean)来获取数据,比如从数据库查询数据;控制器获取到数据后再交由View(JSP)进行数据展示。

MVC 好处:

  • 职责单一,互不影响。每个角色做它自己的事,各司其职。

  • 有利于分工协作。

  • 有利于组件重用

5.2 三层架构

三层架构是将我们的项目分成了三个层面,分别是 表现层业务逻辑层数据访问层

  • 数据访问层:对数据库的CRUD基本操作
  • 业务逻辑层:对业务逻辑进行封装,组合数据访问层层中基本功能,形成复杂的业务逻辑功能。例如 注册业务功能 ,我们会先调用 数据访问层selectByName() 方法判断该用户名是否存在,如果不存在再调用 数据访问层insert() 方法进行数据的添加操作
  • 表现层:接收请求,封装数据,调用业务逻辑层,响应数据

而整个流程是,浏览器发送请求,表现层的Servlet接收请求并调用业务逻辑层的方法进行业务逻辑处理,而业务逻辑层方法调用数据访问层方法进行数据的操作,依次返回到serlvet,然后servlet将数据交由 JSP 进行展示。

三层架构的每一层都有特有的包名称:

  • 表现层: com.example.controller 或者 com.example.web
  • 业务逻辑层:com.example.service
  • 数据访问层:com.example.dao 或者 com.example.mapper

后期我们还会学习一些框架,不同的框架是对不同层进行封装的

5.2 MVC 和 三层架构

通过 MVC 和 三层架构 的学习,那他们有什么区别和联系?

如上图上半部分是 MVC 模式,上图下半部分是三层架构。 MVC 模式 中的 C(控制器)和 V(视图)就是 三层架构 中的表现层,而 MVC 模式 中的 M(模型)就是 三层架构 中的 业务逻辑层 和 数据访问层。

可以将 MVC 模式 理解成是一个大的概念,而 三层架构 是对 MVC 模式 实现架构的思想。 那么我们以后按照要求将不同层的代码写在不同的包下,每一层里功能职责做到单一,将来如果将表现层的技术换掉,而业务逻辑层和数据访问层的代码不需要发生变化。

6. 综合案例

需求:完成品牌数据的增删改查操作

结合之前所学的技术,对这个综合案例对之前所学的技术进行复习巩固。

6.1 环境准备

环境准备工作,我们分以下步骤实现:

  • 创建项目引入坐标

  • 创建三层架构的包结构

  • 数据库表 tb_brand

  • 实体类 Brand

  • MyBatis 基础环境

    • Mybatis-config.xml

    • BrandMapper.xml

    • BrandMapper接口

6.1.1 项目分析

分析如上案例需要用到哪些技术,明确需要哪些依赖库(坐标)

  • 需要操作数据库。mysql的驱动包
  • 要使用mybatis框架。mybaits的依赖包
  • web项目需要用到servlet和jsp。servlet和jsp的依赖包
  • 需要使用 jstl 进行数据展示。jstl的依赖包

pom.xml 坐标内容如下:

<dependencies>
        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.5</version>
        </dependency>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.46</version>
        </dependency>
<!--        servlet-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </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>
        <!--        jstl,standard-->
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
            <classifier>sources</classifier>
            <type>jar.sha256</type>
        </dependency>

    </dependencies>

6.1.2 创建工程包

创建不同的包结构,用来存储不同的类。包结构如下

6.1.3 准备mybatis环境

定义核心配置文件 Mybatis-config.xml ,并将该文件放置在 resources

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--起别名-->
    <typeAliases>
        <package name="com.itheima.pojo"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql:///mybatis?useSSL=false" />
                <property name="username" value="root" />
                <property name="password" value="1234" />
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--扫描mapper-->
        <package name="com.example.mapper" />
    </mappers>
</configuration>

resources 下创建放置映射配置文件的目录结构 com.example.mapper,并在该目录下创建映射配置文件 BrandMapper.xml

<?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">
<mapper namespace="com.example.mapper.BrandMapper8">
<!--    解决数据和javabean字段不一致问题-->
    <resultMap id="brandResultMap" type="brand">
        <result column="brand_name" property="brandName" />
        <result column="company_name" property="companyName" />
    </resultMap>

<!--    <select id="selectAll" resultMap="brandResultMap">-->
<!--        select *-->
<!--        from tb_brand;-->
<!--    </select>-->

</mapper>

6.2 查询所有数据

  1. 在webapp目录下,新建index.html
<a href="/08JSP/selectAllServlet">查询所有</a>
  1. 在web包路径下,创建SelectAllServlet
package com.example.web;

import com.example.pojo.Brand;
import com.example.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 {
    private  BrandService service = new BrandService();
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        List<Brand> brands = service.selectAll();
        //2. 存入request域中
        request.setAttribute("brands",brands);
        //3. 转发到brand.jsp
        request.getRequestDispatcher("/brand/brand.jsp").forward(request,response);
    }

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

  1. 在service包下创建BrandService

    package com.example.service;
    
    import com.example.mapper.BrandMapper8;
    import com.example.pojo.Brand;
    import com.example.utils.SqlSessionFactoryUtils;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    
    import java.util.List;
    
    public class BrandService {
        SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory();
    
        public List<Brand> selectAll(){
            SqlSession sqlSession = factory.openSession();
            BrandMapper8 mapper = sqlSession.getMapper(BrandMapper8.class);
            List<Brand> brands = mapper.selectAll();
            sqlSession.close();
            return brands;
        }
    }
    
    
  2. 在这里使用到数据链接工具类和数据库查询的mapper

    package com.example.utils;
    
    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 {
                String resource = "mybatis-config.xml";
                InputStream inputStream = Resources.getResourceAsStream(resource);
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        public static SqlSessionFactory getSqlSessionFactory(){
            return sqlSessionFactory;
        }
    }
    
  3. 由于是简单的查询语句,一般使用注解开发

    package com.example.mapper;
    
    import com.example.pojo.Brand;
    import org.apache.ibatis.annotations.ResultMap;
    import org.apache.ibatis.annotations.Select;
    
    import java.util.List;
    
    public interface BrandMapper8 {
        @Select("select * from tb_brand")
        @ResultMap("brandResultMap")//映射字段
        List<Brand> selectAll();
    }
    
    
  4. 编写brand.jsp页面

    <%--
      Created by IntelliJ IDEA.
      User: hades
      Date: 2022/5/17
      Time: 11:55 上午
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    <%--${brands}--%>
    
    <table border="1" cellspacing="0" width="80%">
        <tr>
            <th>序号</th>
            <th>品牌名称</th>
            <th>企业名称</th>
            <th>排序</th>
            <th>品牌介绍</th>
            <th>状态</th>
            <th>操作</th>
        </tr>
    
        <c:forEach items="${brands}" var="brand" varStatus="status">
            <tr align="center">
                    <%--<td>${brand.id}</td>--%>
                <td>${status.count}</td>
                <td>${brand.brandName}</td>
                <td>${brand.companyName}</td>
                <td>${brand.ordered}</td>
                <td>${brand.description}</td>
                <c:if test="${brand.status == 1}">
                    <td>启用</td>
                </c:if>
                <c:if test="${brand.status != 1}">
                    <td>禁用</td>
                </c:if>
                <td><a href="/brand-demo/selectByIdServlet?id=${brand.id}">修改</a> <a href="#">删除</a></td>
            </tr>
        </c:forEach>
    </table>
    </body>
    </html>
    
    

6.3 新增数据

  1. 新增按钮,在查询全部页面添加一个按钮
<input type="button" value="新增" onclick='new function() {
  location.href = "addBrand.jsp";
}'>
</br>
  1. 编写addBrand.jsp 或者Brand.jsp因为是静态页面,jsp或者html都可

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>添加品牌</title>
    </head>
    <body>
    <form action="/08JSP/addServlet" method="post">
        品牌名称:<input name="brandName"><br>
        企业名称:<input name="companyName"><br>
        排序:<input name="ordered"><br>
        描述信息:<textarea rows="5" cols="20" name="description"></textarea><br>
        状态:
        <input type="radio" name="status" value="0">禁用
        <input type="radio" name="status" value="1">启用<br>
    
        <input type="submit" value="提交">
    </form>
    </body>
    </html>
    
  2. 编写addServlet

    package com.example.web;
    
    import com.example.pojo.Brand;
    import com.example.service.BrandService;
    
    import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.annotation.*;
    import java.io.IOException;
    
    @WebServlet("/addServlet")
    public class AddServlet extends HttpServlet {
        private BrandService service = new BrandService();
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //处理POST请求的乱码问题
            request.setCharacterEncoding("utf-8");
            //1. 接收表单提交的数据,封装为一个Brand对象
            String brandName = request.getParameter("brandName");
            String companyName = request.getParameter("companyName");
            Integer ordered = Integer.valueOf(request.getParameter("ordered"));
            String description = request.getParameter("description");
            Integer status = Integer.valueOf(request.getParameter("status"));
            //封装为一个Brand对象
            Brand brand = new Brand(null,brandName,companyName,ordered,description,status);
            //2. 调用service 完成添加
            service.add(brand);
            //3. 转发到查询所有Servlet
            request.getRequestDispatcher("/selectAllServlet").forward(request,response);
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doGet(request, response);
        }
    }
    
    
  3. BrandService中添加add方法

    public void add(Brand brand) {
            //2. 获取SqlSession
            SqlSession sqlSession = factory.openSession();
            //3. 获取BrandMapper
            BrandMapper8 mapper = sqlSession.getMapper(BrandMapper8.class);
            //4. 调用方法
            mapper.add(brand);
            //提交事务
            sqlSession.commit();
            //释放资源
            sqlSession.close();
        }
    
  4. BrandMapper8中接口中添加add方法

    @Insert("insert into tb_brand values(null,#{brandName},#{companyName},#{ordered},#{description},#{status})")
        void add(Brand brand);
    

6.4 修改数据

需求分析:

  • 修改数据,需要根据选择的id去数据库查询对应的数据。然后把数据回显到修改的jsp页面
  • 当数据回显,编辑修改的信息,最后提交数据。

6.4.1 先根据id查询数据

  1. 创建SelectByIdServlet查询存在数据库的数据

    package com.example.web;
    
    import com.example.pojo.Brand;
    import com.example.service.BrandService;
    
    import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.annotation.*;
    import java.io.IOException;
    
    @WebServlet("/SelectByIdServlet")
    public class SelectByIdServlet extends HttpServlet {
        private BrandService service = new BrandService();
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //1. 接收id
            String id = request.getParameter("id");
            //2. 调用service查询
            Brand brand = service.selectById(Integer.parseInt(id));
            //3. 存储到request中
            request.setAttribute("brand",brand);
            //4. 转发到update.jsp
            request.getRequestDispatcher("/update.jsp").forward(request,response);
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doGet(request, response);
        }
    }
    
    
  2. BrandService中编写对应的查询方法

    /**
         * 根据id查询
         * @return
         */
        public Brand selectById(int id){
            //调用BrandMapper.selectAll()
            //2. 获取SqlSession
            SqlSession sqlSession = factory.openSession();
            //3. 获取BrandMapper
            BrandMapper8 mapper = sqlSession.getMapper(BrandMapper8.class);
            //4. 调用方法
            Brand brand = mapper.selectById(id);
            sqlSession.close();
            return brand;
        }
    
  3. BrandMapper8接口中编写对应的查询语句

    /**
         * 根据id查询
         * @param id
         * @return
         */
        @Select("select * from tb_brand where id = #{id}")
        @ResultMap("brandResultMap")
        Brand selectById(int id);
    

6.4.2 回显数据

当查询到数据后,转发给update.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>编辑数据</title>
</head>
<body>
<form action="/08JSP/updateServlet" method="post">
   <%--隐藏域,提交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:if test="${brand.status == 0}">
        <input type="radio" name="status" value="0" checked>禁用
        <input type="radio" name="status" value="1">启用<br>
    </c:if>

    <c:if test="${brand.status == 1}">
        <input type="radio" name="status" value="0" >禁用
        <input type="radio" name="status" value="1" checked>启用<br>
    </c:if>
<%--    <input type="radio" name="status" value="0">禁用--%>
<%--    <input type="radio" name="status" value="1">启用<br>--%>

    <input type="submit" value="提交">
</form>
</body>
</html>

6.4.3 提交修改数据

  1. 创建updateServlet

    package com.example.web;
    
    import com.example.pojo.Brand;
    import com.example.service.BrandService;
    
    import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.annotation.*;
    import java.io.IOException;
    
    @WebServlet("/updateServlet")
    public class UpdateServlet extends HttpServlet {
        private BrandService service = new BrandService();
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //处理POST请求的乱码问题
            request.setCharacterEncoding("utf-8");
            //1. 接收表单提交的数据,封装为一个Brand对象
            Integer id = Integer.valueOf(request.getParameter("id"));
            String brandName = request.getParameter("brandName");
            String companyName = request.getParameter("companyName");
            Integer ordered = Integer.valueOf(request.getParameter("ordered"));
            String description = request.getParameter("description");
            Integer status = Integer.valueOf(request.getParameter("status"));
            //封装为一个Brand对象
            Brand brand = new Brand(id,brandName,companyName,ordered,description,status);
            //2. 调用service 完成修改
            service.update(brand);
            //3. 转发到查询所有Servlet
            request.getRequestDispatcher("/selectAllServlet").forward(request,response);
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doGet(request, response);
        }
    }
    
    
  2. 与之对应,在BrandService中添加update方法

    //修改数据
        public void update(Brand brand) {
            SqlSession sqlSession = factory.openSession();
            BrandMapper8 mapper = sqlSession.getMapper(BrandMapper8.class);
            mapper.update(brand);
            sqlSession.commit();
            sqlSession.close();
        }
    
  3. BrandMapper8接口中添加,update数据库语句

    void update(Brand brand);
    

    由于update语句比较长,为了方便阅读,就不使用注解编写SQL语句了,放入到BrandMapper8.xml

    <update id="update" >
            update tb_brand
            set brand_name   = #{brandName},
                company_name = #{companyName},
                ordered      = #{ordered},
                description  = #{description},
                status       = #{status}
            where id = #{id}
        </update>
    

6.5 删除数据

  1. 给删除按钮添加超链接

    <a href="/08JSP/deleteServlet?id=${brand.id}">删除</a>
    
  2. 编写DeleteServlet

    package com.example.web;
    
    import com.example.service.BrandService;
    
    import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.annotation.*;
    import java.io.IOException;
    
    @WebServlet("/deleteServlet")
    public class DeleteServlet extends HttpServlet {
        BrandService service = new BrandService();
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            Integer id = Integer.valueOf(request.getParameter("id"));
            service.deleteById(id);
            request.getRequestDispatcher("/selectAllServlet").forward(request,response);
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doGet(request, response);
        }
    }
    
    
  3. BrandService中添加deleteById方法

    //删除数据
        public void deleteById(int id){
            SqlSession sqlSession = factory.openSession();
            BrandMapper8 mapper = sqlSession.getMapper(BrandMapper8.class);
            mapper.deleteById(id);
            sqlSession.commit();
            sqlSession.close();
        }
    
  4. BrandMapper中编写删除SQL语句

    @Delete("delete from tb_brand where id= #{id}")
        void deleteById(int id);
    
Loading...