当前位置: 首页 > news >正文

15天深度复习JavaWeb的详细笔记(十二)——综合案例

文章目录

  • demo12-综合案例
    • 1,功能介绍
    • 2,环境准备
      • 2.1 工程准备
      • 2.2 创建表
    • 3,查询所有功能
      • 3.1 后端实现
        • 3.1.1 dao方法实现
        • 3.1.2 service方法实现
        • 3.1.3 servlet实现
        • 3.1.4 测试后端程序
      • 3.2 前端实现
    • 4,添加功能
      • 4.1 后端实现
        • 4.1.1 dao方法实现
        • 4.1.2 service方法实现
        • 4.1.3 servlet实现
      • 4.2 前端实现
    • 5,servlet优化
      • 5.1 问题导入
      • 5.2 代码优化
        • 5.2.1 后端优化
        • 5.2.2 前端优化
    • 6,批量删除
      • 6.1 后端实现
        • 6.1.1 dao方法实现
        • 6.1.2 service方法实现
        • 6.1.3 servlet实现
      • 6.2 前端实现
        • 6.2.1 获取选中的id值并发送异步请求
        • 6.2.2 确定框实现
    • 7,分页查询
      • 7.1 分析
        • 7.1.1 分页查询sql
        • 7.1.2 前后端数据分析
        • 7.1.3 流程分析
      • 7.2 后端实现
        • 7.2.1 dao方法实现
        • 7.2.2 service方法实现
        • 7.2.3 servlet实现
      • 7.3 前端实现
        • 7.3.1 selectAll 代码改进
        • 7.3.2 改变每页条目数
        • 7.3.3 改变当前页码
    • 8,条件查询
      • 8.1 后端实现
        • 8.1.1 dao实现
        • 8.1.2 service实现
        • 8.1.3 servlet实现
      • 8.2 前端实现
    • 9,前端代码优化

demo12-综合案例

1,功能介绍

在这里插入图片描述

以上是我们在综合案例要实现的功能。对数据的除了对数据的增删改查功能外,还有一些复杂的功能,如 批量删除分页查询条件查询 等功能

  • 批量删除 功能:每条数据前都有复选框,当我选中多条数据并点击 批量删除 按钮后,会发送请求到后端并删除数据库中指定的多条数据。
  • 分页查询 功能:当数据库中有很多数据时,我们不可能将所有的数据展示在一页里,这个时候就需要分页展示数据。
  • 条件查询 功能:数据库量大的时候,我们就需要精确的查询一些想看到的数据,这个时候就需要通过条件查询。

这里的 修改品牌删除品牌 功能在课程上不做讲解,留作同学来下的练习。

2,环境准备

2.1 工程准备

按照如下工程结构进行项目准备:

在这里插入图片描述

1.创建Brand实体类:

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 String getStatusStr(){
        if (status == null){
            return "未知";
        }
        return status == 0 ? "禁用":"启用";
    }
    
    /*getter和setter和toString笔记里面就省略了*/
}

2.创建BrandMapper接口:

public interface BrandMapper {
}

3.创建SqlSessionFactoryUtils工具类:

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;
    }
}

4.创建mybatis-config.xml配置文件:

<?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:///db1?useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
       <!--扫描mapper-->
        <package name="com.itheima.mapper"/>
    </mappers>
</configuration>

5.创建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.itheima.mapper.BrandMapper">
    <resultMap id="brandResultMap" type="brand">
        <result property="brandName" column="brand_name" />
        <result property="companyName" column="company_name" />
    </resultMap>
</mapper>

6.导入element-ui文件夹、axios-0.18.0.js文件、vue.js文件、上个案例编写的前端页面brand.html

7.加入依赖坐标:

<dependencies>
    <!--Servlet-->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    <!--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.34</version>
    </dependency>
    <!--fastjson-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.62</version>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.2</version>

        </plugin>
    </plugins>
</build>

2.2 创建表

下面是创建表的语句:

-- 删除tb_brand表
drop table if exists tb_brand;
-- 创建tb_brand表
create table 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
) ENGINE=INNODB DEFAULT CHARSET=utf8;
-- 添加数据
insert into tb_brand (brand_name, company_name, ordered, description, status)
values 
       ('华为', '华为技术有限公司', 100, '万物互联', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
       ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
       ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
       ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
       ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
       ('华为', '华为技术有限公司', 100, '万物互联', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
       ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
       ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
       ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
       ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
       ('华为', '华为技术有限公司', 100, '万物互联', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
       ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
       ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
       ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
       ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
       ('华为', '华为技术有限公司', 100, '万物互联', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
       ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
       ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
       ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
       ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
       ('华为', '华为技术有限公司', 100, '万物互联', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
       ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
       ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
       ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
       ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
       ('华为', '华为技术有限公司', 100, '万物互联', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
       ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
       ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
       ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
       ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1);

3,查询所有功能

在这里插入图片描述

如上图所示是查询所有品牌数据在页面展示的效果。要实现这个功能,要先搞明白如下问题:

  • 什么时候发送异步请求?

    页面加载完毕后就需要在页面上看到所有的品牌数据。所以在 mounted() 这个构造函数中写发送异步请求的代码。

  • 请求需要携带参数吗?

    查询所有功能不需要携带什么参数。

  • 响应的数据格式是什么样?

    后端是需要将 List<Brand> 对象转换为 JSON 格式的数据并响应回给浏览器。响应数据格式如下:

在这里插入图片描述

整体流程如下

在这里插入图片描述

我们先实现后端程序,然后再实现前端程序。

3.1 后端实现

3.1.1 dao方法实现

com.itheima.mapper.BrandMapper 接口中定义抽象方法,并使用 @Select 注解编写 sql 语句

/**
     * 查询所有
     * @return
     */
@Select("select * from tb_brand")
List<Brand> selectAll();

由于表中有些字段名和实体类中的属性名没有对应,所以需要在 com/itheima/mapper/BrandMapper.xml 映射配置文件中定义结果映射 ,使用resultMap 标签。映射配置文件内容如下:

<?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.itheima.mapper.BrandMapper">
    <resultMap id="brandResultMap" type="brand">
        <result property="brandName" column="brand_name" />
        <result property="companyName" column="company_name" />
    </resultMap>
</mapper>

定义完结果映射关系后,在接口 selectAll() 方法上引用该结构映射。使用 @ResultMap("brandResultMap") 注解

完整接口的 selectAll() 方法如下:

/**
     * 查询所有
     * @return
     */
@Select("select * from tb_brand")
@ResultMap("brandResultMap")
List<Brand> selectAll();

3.1.2 service方法实现

1.在 com.itheima.service 包下创建 BrandService 接口,在该接口中定义查询所有的抽象方法

public interface BrandService {
    /**
     * 查询所有
     * @return
     */
    List<Brand> selectAll();
}

2.在 com.itheima.service.impl 下创建名为 BrandServiceImpl 的实现类

public class BrandServiceImpl implements BrandService {
    //1. 创建SqlSessionFactory 工厂对象
    SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory();
    @Override
    public List<Brand> selectAll() {
        //2. 获取SqlSession对象
        SqlSession sqlSession = factory.openSession();
        //3. 获取BrandMapper
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
        //4. 调用方法
        List<Brand> brands = mapper.selectAll();
        //5. 释放资源
        sqlSession.close();
        return brands;
    }
}

此处为什么要给 service 定义接口呢?因为service定义了接口后,在 servlet 中就可以使用多态的形式创建Service实现类的对象,如下:

在这里插入图片描述

这里使用多态是因为方便我们后期解除 Servletservice 的耦合:

  • 从上面的代码我们可以看到 SelectAllServlet 类和 BrandServiceImpl 类之间是耦合在一起的,如果后期 BrandService 有其它更好的实现类(例如叫 BrandServiceImpl),那就需要修改 SelectAllServlet 类中的代码。后面我们学习了 Spring 框架后就可以解除 SelectAllServlet 类和红色框括起来的代码耦合。而现在咱们还做不到解除耦合,在这里只需要理解为什么定义接口即可。
  • 我认为不使用spring虽然没有实现解除耦合但接口形式仍降低了耦合性:
    • 如果以后我们发现有了更好的实现类BrandServiceImpl2那么我们只需要在SelectAllServlet类的第三行修改private BrandService brandService = new BrandServiceImpl();private BrandService brandService = new BrandServiceImp2l();即可,不需要修改SelectAllServlet中其他代码,这样就降低了耦合性

3.1.3 servlet实现

com.itheima.web.servlet 包下定义名为 SelectAllServlet 的查询所有的 servlet

@WebServlet("/selectAllServlet")
public class SelectAllServlet extends HttpServlet {
    private BrandService brandService = new BrandServiceImpl();
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 调用service查询
        List<Brand> brands = brandService.selectAll();
        //2. 转为JSON
        String jsonString = JSON.toJSONString(brands);
        //3. 写数据
        response.setContentType("text/json;charset=utf-8"); //告知浏览器响应的数据是什么, 告知浏览器使用什么字符集进行解码
        response.getWriter().write(jsonString);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}

3.1.4 测试后端程序

启动服务,在地址栏输入http://localhost:8080/demo11-project/selectAllServlet进行测试

3.2 前端实现

前端需要在页面加载完毕后发送 ajax 请求,所以发送请求的逻辑应该放在 mounted() 钩子函数中。而响应回来的数据需要赋值给表格绑定的数据模型,从下图可以看出表格绑定的数据模型是 tableData

在这里插入图片描述

前端代码如下:

 mounted(){
     //当页面加载完成后,发送异步请求,获取数据
     var _this = this;
     axios({
         method:"get",
         url:"http://localhost:8080/demo11-project/selectAllServlet"
     }).then(function (resp) {
         _this.tableData = resp.data;
     })
 }

老师说this不能直接在axios中使用,需要var _this = this;我不理解!

4,添加功能

在这里插入图片描述

上图是添加数据的对话框,当点击 提交 按钮后就需要将数据提交到后端,并将数据保存到数据库中。下图是整体的流程:

在这里插入图片描述

页面发送请求时,需要将输入框输入的内容提交给后端程序,而这里是以 json 格式进行传递的。而具体的数据格式如下:

在这里插入图片描述

注意:由于是添加数据,所以上述json数据中id是没有值的。

4.1 后端实现

4.1.1 dao方法实现

BrandMapper 接口中定义 add() 添加方法,并使用 @Insert 注解编写sql语句

/**
     * 添加数据
     * @param brand
     */
@Insert("insert into tb_brand values(null,#{brandName},#{companyName},#{ordered},#{description},#{status})")
//id那个是null是因为需要让它自增
void add(Brand brand);

4.1.2 service方法实现

BrandService 接口中定义 add() 添加数据的业务逻辑方法

/**
     * 添加数据
     * @param brand
     */
void add(Brand brand);

BrandServiceImpl 类中重写 add() 方法,并进行业务逻辑实现

@Override
public void add(Brand brand) {
    //2. 获取SqlSession对象
    SqlSession sqlSession = factory.openSession();
    //3. 获取BrandMapper
    BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
    //4. 调用方法
    mapper.add(brand);
    sqlSession.commit();//提交事务
    //5. 释放资源
    sqlSession.close();
}

注意:增删改操作一定要提交事务。

4.1.3 servlet实现

com.itheima.web.servlet 包写定义名为 AddServlet 的 Servlet。该 Servlet 的逻辑如下:

  • 接收页面提交的数据。页面到时候提交的数据是 json 格式的数据,所以此处需要使用输入流读取数据
  • 将接收到的数据转换为 Brand 对象
  • 调用 service 的 add() 方法进行添加的业务逻辑处理
  • 给浏览器响应添加成功的标识,这里直接给浏览器响应 success 字符串表示成功

servlet 代码实现如下:

@WebServlet("/addServlet")
public class AddServlet extends HttpServlet {
    private BrandService brandService = new BrandServiceImpl();
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 接收品牌数据
        BufferedReader br = request.getReader();
        String params = br.readLine();//读取到的是json字符串,json是一串数据,无论你里面有多少数据,都是一行
        //转为Brand对象
        Brand brand = JSON.parseObject(params, Brand.class);
        //2. 调用service添加
        brandService.add(brand);
        //3. 响应成功的标识
        response.getWriter().write("success");
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}

4.2 前端实现

在这里插入图片描述

上图左边是页面效果,里面的 提交 按钮可以通过上图右边看出绑定了一个 单击事件,而该事件绑定的是 addBrand 函数,所以添加数据功能的逻辑代码应该写在 addBrand() 函数中。在此方法中需要发送异步请求并将表单中输入的数据作为参数进行传递。如下

// 添加数据
addBrand() {
    var _this = this;

    // 发送ajax请求,添加数据
    axios({
        method:"post",
        url:"http://localhost:8080/demo11-project/addServlet",
        data:_this.brand
    }).then(function (resp) {
       	//响应数据的处理逻辑
    })
}

then 函数中的匿名函数是成功后的回调函数,而 resp.data 就可以获取到响应回来的数据,如果值是 success 表示数据添加成功。成功后我们需要做一下逻辑处理:

  1. 关闭新增对话框窗口

    如下图所示是添加数据的对话框代码,从代码中可以看到此对话框绑定了 dialogVisible 数据模型,只需要将该数据模型的值设置为 false,就可以关闭新增对话框窗口了。

在这里插入图片描述

  1. 重新查询数据

    数据添加成功与否,用户只要能在页面上查看到数据说明添加成功。而此处需要重新发送异步请求获取所有的品牌数据,而这段代码在 查询所有 功能中已经实现,所以我们可以将此功能代码进行抽取,抽取到一个 selectAll() 函数中

    // 查询所有数据
    selectAll(){
        var _this = this;
    
        axios({
            method:"get",
            url:"http://localhost:8080/demo11-project/selectAllServlet"
        }).then(function (resp) {
            _this.tableData = resp.data;
        })
    }
    

    那么就需要将 mounted() 钩子函数中代码改进为

    mounted(){
        //当页面加载完成后,发送异步请求,获取数据
        this.selectAll();
    }
    

    同时在新增响应的回调中调用 selectAll() 进行数据的重新查询。

  2. 弹出消息给用户提示添加成功

在这里插入图片描述

上图左边就是 elementUI 官网提供的成功提示代码,而上图右边是具体的效果。

注意:上面的this需要的是表示 VUE 对象的this。

综上所述,前端代码如下:

// 添加数据
addBrand() {
    var _this = this;

    // 发送ajax请求,添加数据
    axios({
        method:"post",
        url:"http://localhost:8080/demo11-project/addServlet",
        data:_this.brand
    }).then(function (resp) {
        if(resp.data == "success"){
            //添加成功
            //关闭窗口
            _this.dialogVisible = false;
            // 重新查询数据
            _this.selectAll();
            // 弹出消息提示
            _this.$message({
                message: '恭喜你,添加成功',
                type: 'success'
            });
        }
    })
}

5,servlet优化

5.1 问题导入

Web 层的 Servlet 个数太多了,不利于管理和编写

通过之前的两个功能,我们发现每一个功能都需要定义一个 servlet,一个模块需要实现增删改查功能,就需要4个 servlet,模块一多就会造成servlet 泛滥。此时我们就想 servlet 能不能像 service 一样,一个模块只定义一个 servlet,而每一个功能只需要在该 servlet 中定义对应的方法。例如下面代码:

@WebServlet("/brand/*")
public class BrandServlet {
    //查询所有
	public void selectAll(...) {}
    
    //添加数据
    public void add(...) {}
    
     //修改数据
    public void update(...) {}
    
    //删除删除
    public void delete(...) {}
}

而我们知道发送请求 servlettomcat 会自动的调用 service() 方法,之前我们在自定义的 servlet 中重写 doGet() 方法和 doPost() 方法,当我们访问该 servlet 时会根据请求方式将请求分发给 doGet() 或者 doPost() 方法,如下图

在这里插入图片描述

那么我们也可以仿照这样请求分发的思想,在 service() 方法中根据具体的操作调用对应的方法,如:查询所有就调用 selectAll() 方法,添加企业信息就调用 add() 方法。

为了做到通用,我们定义一个通用的 servletBaseServlet使其继承HttpServlet,然后定义其他的 servlet 使其继承我们定义的 BaseServlet,在 BaseServlet 中调用具体 servlet(如BrandServlet)中的对应方法。

1.创建BaseServlet类并继承HttpServlet:

  • 需要重写HttpServlet中的service方法,替换掉HttpServlet的根据请求方式进行方法分发,使用我们自己定义的根据请求路径进行方法分发:
    • 获取最后一段路径,其实就是方法名称
    • 通过反射获取方法对象,执行方法
public class BaseServlet extends HttpServlet {
    //根据请求的最后一段路径来进行方法分发
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1.获取最后一段路径,其实就是方法名称
        // 1.1 获取请求路径
        String uri = req.getRequestURI(); // /brand-case/brand/selectAll
        // 1.2 获取最后一段路径
        int index = uri.lastIndexOf('/');
        String methodName = uri.substring(index + 1);// selectAll

        // 2. 执行方法
        // 2.1 获取BrandServlet或UserServlet 字节码对象,即Class对象
        Class<? extends BaseServlet> cls = this.getClass();//谁调用service方法,this就是谁,所以this是BrandServlet或UserServlet实例对象
        // 2.2 获取方法对象Method
        try {
            Method method = cls.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
            // 2.3 执行方法
            method.invoke(this,req,resp);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2.修改BrandServlet:

@WebServlet("/brand/*")
public class BrandServlet extends BaseServlet{
    private BrandService brandService = new BrandServiceImpl();
    public void selectAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("brand selectAll...");
    }
    public void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("brand add...");
    }
}

3.创建UserServlet:

@WebServlet("/user/*")
public class UserServlet extends BaseServlet{
    private BrandService brandService = new BrandServiceImpl();
    public void selectAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("user selectAll...");
    }
    public void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("user add...");
    }
}

4.启动服务,在地址栏分别输入以下地址进行测试:

http://localhost:8080/demo11-project/brand/selectAll

http://localhost:8080/demo11-project/brand/add

http://localhost:8080/demo11-project/user/selectAll

http://localhost:8080/demo11-project/user/add

5.2 代码优化

5.2.1 后端优化

测试成功后,我们就可以将以前写的SelectAllServlet和AddServlet中的逻辑代码拷贝到对应的方法中:

@WebServlet("/brand/*")
public class BrandServlet extends BaseServlet{
    private BrandService brandService = new BrandServiceImpl();

    public void selectAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 调用service查询
        List<Brand> brands = brandService.selectAll();
        //2. 转为JSON
        String jsonString = JSON.toJSONString(brands);
        //3. 写数据
        response.setContentType("text/json;charset=utf-8"); //告知浏览器响应的数据是什么, 告知浏览器使用什么字符集进行解码
        response.getWriter().write(jsonString);
    }

    public void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 接收品牌数据
        BufferedReader br = request.getReader();
        String params = br.readLine();//读取到的是json字符串,json是一串数据,无论你里面有多少数据,都是一行
        //转为Brand对象
        Brand brand = JSON.parseObject(params, Brand.class);
        //2. 调用service添加
        brandService.add(brand);
        //3. 响应成功的标识
        response.getWriter().write("success");
    }
}

5.2.2 前端优化

页面中之前发送的请求的路径都需要进行修改:

  • selectAll() 函数中发送异步请求的 url 应该改为 http://localhost:8080/demo11-project/brand/selectAll
  • addBrand() 函数中发送异步请求的 url 应该改为 http://localhost:8080/demo11-project/brand/add

6,批量删除

在这里插入图片描述

如上图所示点击多条数据前的复选框就意味着要删除这些数据,而点击了 批量删除 按钮后,需要让用户确认一下,因为有可能是用户误操作的,当用户确定后需要给后端发送请求并携带者需要删除数据的多个id值,后端程序删除数据库中的数据。具体的流程如下:

在这里插入图片描述

注意:

前端发送请求时需要将要删除的多个id值以json格式提交给后端,而该json格式数据如下:

[1,2,3,4]

需要使用int[] ids = JSON.parseObject(params, int[].class);将其转为int数组

6.1 后端实现

6.1.1 dao方法实现

BrandMapper 接口中定义 deleteByIds() 添加方法,由于这里面要用到动态 sql ,属于复杂的sql操作,建议使用映射配置文件。

接口方法声明如下:

 /**
     * 批量删除
     * @param ids
     */
void deleteByIds(@Param("ids") int[] ids);

BrandMapper.xml 映射配置文件中添加 statement

<delete id="deleteByIds">
    delete from tb_brand where id in
    <foreach collection="ids" item="id" separator="," open="(" close=")">
        #{id}
    </foreach>
</delete>

6.1.2 service方法实现

BrandService 接口中定义 deleteByIds() 批量删除的业务逻辑方法

/**
     * 批量删除
     * @param ids
     */
void deleteByIds( int[] ids);

BrandServiceImpl 类中重写 deleteByIds() 方法,并进行业务逻辑实现

@Override
public void deleteByIds(int[] ids) {
    //2. 获取SqlSession对象
    SqlSession sqlSession = factory.openSession();
    //3. 获取BrandMapper
    BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
    //4. 调用方法
    mapper.deleteByIds(ids);
    sqlSession.commit();//提交事务
    //5. 释放资源
    sqlSession.close();
}

6.1.3 servlet实现

BrandServlet 类中定义 deleteByIds() 方法。而该方法的逻辑如下:

  • 接收页面提交的数据。页面到时候提交的数据是 json 格式的数据,所以此处需要使用输入流读取数据
  • 将接收到的数据转换为 int[] 数组
  • 调用 service 的 deleteByIds() 方法进行批量删除的业务逻辑处理
  • 给浏览器响应添加成功的标识,这里直接给浏览器响应 success 字符串表示成功

servlet 中 deleteByIds() 方法代码实现如下:

public void deleteByIds(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //1. 接收数据 json  [1,2,3]
    BufferedReader br = request.getReader();
    String params = br.readLine();//json字符串
    
    //转为 int[]
    int[] ids = JSON.parseObject(params, int[].class);
    
    //2. 调用service添加
    brandService.deleteByIds(ids);
    //3. 响应成功的标识
    response.getWriter().write("success");
}

6.2 前端实现

此功能的前端代码实现稍微有点麻烦,分为以下几步实现

6.2.1 获取选中的id值并发送异步请求

在这里插入图片描述

从上图可以看出表格复选框绑定了一个 selection-change 事件,该事件是当选择项发生变化时会触发。该事件绑定了 handleSelectionChange 函数,而该函数有一个参数 val ,该参数是获取选中行的数据,如下

在这里插入图片描述

而我们只需要将所有选中数据的id值提交给服务端即可,获取id的逻辑我们书写在 批量删除 按钮绑定的函数中。

批量删除 按钮绑定单击事件,并给绑定触发时调用的函数,如下

在这里插入图片描述

并在Vue对象中的 methods 中定义 deleteByIds() 函数,在该函数中从 multipleSelection 数据模型中获取所选数据的id值。要完成这个功能需要在 Vue 对象中定义一个数据模型 selectedIds:[],在 deleteByIds() 函数中遍历 multipleSelection 数组,并获取到每一个所选数据的id值存储到 selectedIds 数组中,代码实现如下:

//1. 创建id数组 [1,2,3], 从 this.multipleSelection 获取即可
for (let i = 0; i < this.multipleSelection.length; i++) {
    let selectionElement = this.multipleSelection[i];
    this.selectedIds[i] = selectionElement.id;
}
//2. 发送AJAX请求
var _this = this;
// 发送ajax请求,添加数据
axios({
    method:"post",
    url:"http://localhost:8080/demo11-project/brand/deleteByIds",
    data:_this.selectedIds
}).then(function (resp) {
    if(resp.data == "success"){
        //删除成功
        // 重新查询数据
        _this.selectAll();
        // 弹出消息提示
        _this.$message({
            message: '恭喜你,删除成功',
            type: 'success'
        });
    }
})

6.2.2 确定框实现

由于删除操作是比较危险的;有时候可能是由于用户的误操作点击了 批量删除 按钮,所以在点击了按钮后需要先给用户确认提示。而确认框在 elementUI 中也提供了,如下图

在这里插入图片描述

点击取消后里面的操作我们不需要修改,我们只需要修改点击 确定 按钮后需要执行之前删除的逻辑。因此前端代码实现如下:

deleteByIds(){
    // 弹出确认提示框
    this.$confirm('此操作将删除该数据, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
    }).then(() => {
        //用户点击确认按钮
        //1. 创建id数组 [1,2,3], 从 this.multipleSelection 获取即可
        for (let i = 0; i < this.multipleSelection.length; i++) {
            let selectionElement = this.multipleSelection[i];
            this.selectedIds[i] = selectionElement.id;
        }
        //2. 发送AJAX请求
        var _this = this;
        // 发送ajax请求,添加数据
        axios({
            method:"post",
            url:"http://localhost:8080/demo11-project/brand/deleteByIds",
            data:_this.selectedIds
        }).then(function (resp) {
            if(resp.data == "success"){
                //删除成功
                // 重新查询数据
                _this.selectAll();
                // 弹出消息提示
                _this.$message({
                    message: '恭喜你,删除成功',
                    type: 'success'
                });
            }
        })
    }).catch(() => {
        //用户点击取消按钮
        this.$message({
            type: 'info',
            message: '已取消删除'
        });
    });
}

7,分页查询

我们之前做的 查询所有 功能中将数据库中所有的数据查询出来并展示到页面上,试想如果数据库中的数据有很多(假设有十几万条)的时候,将数据全部展示出来肯定不现实,那如何解决这个问题呢?几乎所有的网站都会使用分页解决这个问题。每次只展示一页的数据,比如一页展示10条数据,如果还想看其他的数据,可以通过点击页码进行查询

在这里插入图片描述

7.1 分析

7.1.1 分页查询sql

分页查询也是从数据库进行查询的,所以我们要分页对应的SQL语句应该怎么写。分页查询使用 LIMIT 关键字,格式为:LIMIT 开始索引 每页显示的条数。以后前端页面在发送请求携带参数时,它并不明确开始索引是什么,但是它知道查询第几页。所以 开始索引 需要在后端进行计算,计算的公式是 :开始索引 = (当前页码 - 1)* 每页显示条数

那么查询第二页的数据的 SQL 语句就是:

select * from tb_brand  limit 5,5;

7.1.2 前后端数据分析

  • 前端需要传递什么参数给后端

    根据上一步对分页查询 SQL 语句分析得出,前端需要给后端两个参数

    • 当前页码 : currentPage
    • 每页显示条数:pageSize
  • 后端需要响应什么数据给前端

在这里插入图片描述

上图是分页查询页面展示的效果,从上面我们可以看出需要响应以下联股份数据

  • 当前页需要展示的数据。我们在后端一般会存储到 List 集合中
  • 总共记录数。在上图页面中需要展示总的记录数,所以这部分数据也需要。总的页面 elementUI 的分页组件会自动计算,我们不需要关心

而这两部分需要封装到 PageBean 对象中,并将该对象转换为 json 格式的数据响应回给浏览器

在这里插入图片描述

通过上面的分析我们需要先在 pojo 包下创建 PageBean 类,为了做到通过会将其定义成泛型类,代码如下:

//分页查询的JavaBean
public class PageBean<T> {
    // 总记录数
    private int totalCount;
    // 当前页数据
    private List<T> rows;
    public int getTotalCount() {
        return totalCount;
    }
    public void setTotalCount(int totalCount) {
        this.totalCount = totalCount;
    }
    public List<T> getRows() {
        return rows;
    }
    public void setRows(List<T> rows) {
        this.rows = rows;
    }
}

说一下PageBean和List:

  • 变量rows是数组类型,如果我们写private List<Brand> rows;那么以后这里面只能存Brand类型的数据,如果以后还有别的功能模块要查询数据就不能使用这个实体类了
  • 如果我们写private List rows;那么我们从数组中取出来的就是Object类型,需要一一将数组中数据遍历出来并进行强制类型转换,也不合理
  • 我们可以写private List<T> rows;这样的话我们就可以在创建PageBean对象时规定rows数组中存的是什么类型的数据,既实现了实体类通用,又不需要进行强制类型转换

7.1.3 流程分析

后端需要响应总记录数当前页的数据 两部分数据给前端,所以在 BrandMapper 接口中需要定义两个方法:

  • selectByPage() :查询当前页的数据的方法
  • selectTotalCount() :查询总记录的方法

整体流程如下:

在这里插入图片描述

7.2 后端实现

7.2.1 dao方法实现

/**
     * 分页查询
     * @param begin
     * @param size
     * @return
     */
@Select("select * from tb_brand limit #{begin} , #{size}")
@ResultMap("brandResultMap")
List<Brand> selectByPage(@Param("begin") int begin,@Param("size") int size);

/**
     * 查询总记录数
     * @return
     */
@Select("select count(*) from tb_brand ")
int selectTotalCount();

7.2.2 service方法实现

BrandService 接口中定义 selectByPage() 分页查询数据的业务逻辑方法

/**
     * 分页查询
     * @param currentPage  当前页码
     * @param pageSize   每页展示条数
     * @return
     */
    PageBean<Brand>  selectByPage(int currentPage,int pageSize);

BrandServiceImpl 类中重写 selectByPage() 方法,并进行业务逻辑实现

@Override
public PageBean<Brand> selectByPage(int currentPage, int pageSize) {
    //2. 获取SqlSession对象
    SqlSession sqlSession = factory.openSession();
    //3. 获取BrandMapper
    BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
    //4. 计算开始索引
    int begin = (currentPage - 1) * pageSize;
    // 计算查询条目数
    int size = pageSize;
    //5. 查询当前页数据
    List<Brand> rows = mapper.selectByPage(begin, size);
    //6. 查询总记录数
    int totalCount = mapper.selectTotalCount();
    //7. 封装PageBean对象
    PageBean<Brand> pageBean = new PageBean<>();
    pageBean.setRows(rows);
    pageBean.setTotalCount(totalCount);
    //8. 释放资源
    sqlSession.close();
    return pageBean;
}

7.2.3 servlet实现

BrandServlet 类中定义 selectByPage() 方法:

public void selectByPage(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //1. 接收 当前页码 和 每页展示条数    url?currentPage=1&pageSize=5
    String _currentPage = request.getParameter("currentPage");
    String _pageSize = request.getParameter("pageSize");

    int currentPage = Integer.parseInt(_currentPage);
    int pageSize = Integer.parseInt(_pageSize);

    //2. 调用service查询
    PageBean<Brand> pageBean = brandService.selectByPage(currentPage, pageSize);

    //2. 转为JSON
    String jsonString = JSON.toJSONString(pageBean);
    //3. 写数据
    response.setContentType("text/json;charset=utf-8");
    response.getWriter().write(jsonString);
}

7.3 前端实现

7.3.1 selectAll 代码改进

1.selectAll() 函数之前是查询所有数据,现需要改成分页查询

var _this = this;
axios({
    method:"get",
    url:"http://localhost:8080/demo11-project/brand/selectByPage?currentPage=1&pageSize=5"
}).then(resp =>{
    //设置表格数据
    _this.tableData = resp.data.rows; // {rows:[],totalCount:100}
})

2.响应的数据中还有总记录数,要进行总记录数展示需要在页面绑定数据模型

在这里插入图片描述

这里我们以前是写死了,写的是 :total=“400”

现在我们不想写死,所以就改为了 :total="totalCount"并在Vue对象中声明该数据模型 totalCount:100,

那异步请求的代码就可以优化为

var _this = this;
axios({
    method:"get",
    url:"http://localhost:8080/demo11-project/brand/selectByPage?currentPage=1&pageSize=5"
}).then(resp =>{
    //设置表格数据
    _this.tableData = resp.data.rows; // {rows:[],totalCount:100}
    //设置总记录数
    _this.totalCount = resp.data.totalCount;
})

3.brand.html的当前页码数据模型currentPage我们以前设置的4,我们当然是想打开页面时的页码为1,所以将4改为1

4.页面中分页组件给 当前页码每页显示的条目数 都绑定了数据模型

在这里插入图片描述

所以 selectAll() 函数中发送异步请求的资源路径中不能将当前页码和 每页显示条目数写死,代码就可以优化为

var _this = this;
axios({
    method:"get",
    url:"http://localhost:8080/demo11-project/brand/selectByPage?currentPage="+this.currentPage+"&pageSize=" + this.pageSize
}).then(resp =>{
    //设置表格数据
    _this.tableData = resp.data.rows; // {rows:[],totalCount:100}
    //设置总记录数
    _this.totalCount = resp.data.totalCount;
})

7.3.2 改变每页条目数

在这里插入图片描述

当我们改变每页显示的条目数后,需要重新发送异步请求。而下图是分页组件代码,@size-change 就是每页显示的条目数发生变化时会触发的事件

在这里插入图片描述

而该事件绑定了一个 handleSizeChange 函数,整个逻辑如下:

handleSizeChange(val) { //我们选择的是 ‘5条/页’ 此值就是 5.而我们选择了 `10条/页` 此值就是 10
    // 重新设置每页显示的条数
    this.pageSize  = val; 
    //调用 selectAll 函数重新分页查询数据
    this.selectAll();
}

7.3.3 改变当前页码

当我们改变页码时,需要重新发送异步请求。而下图是分页组件代码,@current-change 就是页码发生变化时会触发的事件

在这里插入图片描述

而该事件绑定了一个 handleSizeChange 函数,整个逻辑如下:

handleCurrentChange(val) { //val 就是改变后的页码
    // 重新设置当前页码
    this.currentPage  = val;
    //调用 selectAll 函数重新分页查询数据
    this.selectAll();
}

8,条件查询

在这里插入图片描述

上图就是用来输入条件查询的条件数据的。要做条件查询功能,先明确以下三个问题

  • 3个条件之间什么关系?

    同时满足,所用 SQL 中多个条件需要使用 and 关键字连接

  • 3个条件必须全部填写吗?

    不需要。想根据哪儿个条件查询就写那个,所以这里需要使用动态 sql 语句

  • 条件查询需要分页吗?

    需要

根据上面三个问题的明确,我们就可以确定sql语句了:

在这里插入图片描述

整个条件分页查询流程如下

在这里插入图片描述

8.1 后端实现

8.1.1 dao实现

BrandMapper 接口中定义 selectByPageAndCondition() 方法 和 selectTotalCountByCondition 方法,用来进行条件分页查询功能,方法如下:

/**
     * 分页条件查询
     * @param begin
     * @param size
     * @return
     */
List<Brand> selectByPageAndCondition(@Param("begin") int begin,@Param("size") int size,@Param("brand") Brand brand);

/**
     * 根据条件查询总记录数
     * @return
     */
int selectTotalCountByCondition(Brand brand);

参数:

  • begin 分页查询的起始索引
  • size 分页查询的每页条目数
  • brand 用来封装条件的对象

由于这是一个复杂的查询语句,需要使用动态sql;所以我们在映射配置文件中书写 sql 语句。brand_name 字段和 company_name 字段需要进行模糊查询,所以需要使用 % 占位符。映射配置文件中 statement 书写如下:

<!--查询满足条件的数据并进行分页-->
<select id="selectByPageAndCondition" resultMap="brandResultMap">
    select *
    from tb_brand
    <where>
        <if test="brand.brandName != null and brand.brandName != '' ">
            and  brand_name like #{brand.brandName}
        </if>

        <if test="brand.companyName != null and brand.companyName != '' ">
            and  company_name like #{brand.companyName}
        </if>

        <if test="brand.status != null">
            and  status = #{brand.status}
        </if>
    </where>
    limit #{begin} , #{size}
</select>

<!--查询满足条件的数据条目数-->
<select id="selectTotalCountByCondition" resultType="java.lang.Integer">
    select count(*)
    from tb_brand
    <where>
        <if test="brandName != null and brandName != '' ">
            and  brand_name like #{brandName}
        </if>

        <if test="companyName != null and companyName != '' ">
            and  company_name like #{companyName}
        </if>

        <if test="status != null">
            and  status = #{status}
        </if>
    </where>
</select>

为什么第6行是brand.brandName而第26行是brandName:

  • 因为方法selectByPageAndCondition的第三个参数加了注解@Param(“brand”)而方法selectTotalCountByCondition没有加

8.1.2 service实现

BrandService 接口中定义 selectByPageAndCondition() 分页查询数据的业务逻辑方法

 /**
     * 分页条件查询
     * @param currentPage
     * @param pageSize
     * @param brand
     * @return
     */
PageBean<Brand>  selectByPageAndCondition(int currentPage,int pageSize,Brand brand);

BrandServiceImpl 类中重写 selectByPageAndCondition() 方法,并进行业务逻辑实现

 @Override
    public PageBean<Brand> selectByPageAndCondition(int currentPage, int pageSize, Brand brand) {
        //2. 获取SqlSession对象
        SqlSession sqlSession = factory.openSession();
        //3. 获取BrandMapper
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);

        //4. 计算开始索引
        int begin = (currentPage - 1) * pageSize;
        // 计算查询条目数
        int size = pageSize;
        // 处理brand条件,模糊表达式
        String brandName = brand.getBrandName();
        if (brandName != null && brandName.length() > 0) {
            brand.setBrandName("%" + brandName + "%");
        }
        String companyName = brand.getCompanyName();
        if (companyName != null && companyName.length() > 0) {
            brand.setCompanyName("%" + companyName + "%");
        }

        //5. 查询当前页数据
        List<Brand> rows = mapper.selectByPageAndCondition(begin, size, brand);

        //6. 查询总记录数
        int totalCount = mapper.selectTotalCountByCondition(brand);

        //7. 封装PageBean对象
        PageBean<Brand> pageBean = new PageBean<>();
        pageBean.setRows(rows);
        pageBean.setTotalCount(totalCount);

        //8. 释放资源
        sqlSession.close();

        return pageBean;
    

注意:brandName 和 companyName 属性值到时候需要进行模糊查询,所以前后需要拼接上 %

8.1.3 servlet实现

BrandServlet 类中定义 selectByPageAndCondition() 方法。而该方法的逻辑如下:

  • 获取页面提交的 当前页码每页显示条目数 两个数据。这两个参数是在url后进行拼接的,格式是 url?currentPage=1&pageSize=5。获取这样的参数需要使用 requet.getparameter() 方法获取。

  • 获取页面提交的 条件数据 ,并将数据封装到一个Brand对象中。由于这部分数据到时候是需要以 json 格式进行提交的,所以我们需要通过流获取数据,具体代码如下:

    // 获取查询条件对象
    BufferedReader br = request.getReader();
    String params = br.readLine();//json字符串
    //转为 Brand
    Brand brand = JSON.parseObject(params, Brand.class);
    
  • 调用 service 的 selectByPageAndCondition() 方法进行分页查询的业务逻辑处理

  • 将查询到的数据转换为 json 格式的数据

  • 响应 json 数据

servlet 中 selectByPageAndCondition() 方法代码实现如下:

/**
     * 分页条件查询
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
public void selectByPageAndCondition(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //1. 接收 当前页码 和 每页展示条数    url?currentPage=1&pageSize=5
    String _currentPage = request.getParameter("currentPage");
    String _pageSize = request.getParameter("pageSize");
    int currentPage = Integer.parseInt(_currentPage);
    int pageSize = Integer.parseInt(_pageSize);

    // 2.获取查询条件对象
    BufferedReader br = request.getReader();
    String params = br.readLine();//json字符串
    //转为 Brand
    Brand brand = JSON.parseObject(params, Brand.class);

    //3. 调用service查询
    PageBean<Brand> pageBean = brandService.selectByPageAndCondition(currentPage,pageSize,brand);
    //4. 转为JSON
    String jsonString = JSON.toJSONString(pageBean);
    //5. 写数据
    response.setContentType("text/json;charset=utf-8");
    response.getWriter().write(jsonString);
}

8.2 前端实现

前端代码我们从以下几方面实现:

  1. 查询表单绑定查询条件对象模型

    这一步我们以前在页面上已经实现了,页面代码如下:

在这里插入图片描述

  1. 点击查询按钮查询数据

在这里插入图片描述

从上面页面可以看到给 查询 按钮绑定了 onSubmit() 函数,而在 onSubmit() 函数中只需要调用 selectAll() 函数进行条件分页查询

onSubmit() {
	this.selectAll();
}
  1. 改进 selectAll() 函数

    子页面加载完成后发送异步请求,需要携带当前页码、每页显示条数、查询条件对象。接下来先对携带的数据进行说明:

    • 当前页码每页显示条数 这两个参数我们会拼接到 URL 的后面
    • 查询条件对象 这个参数需要以 json 格式提交给后端程序

    修改 selectAll() 函数逻辑为

    var _this = this;
    
    axios({
        method:"post",
        url:"http://localhost:8080/demo11-project/brand/selectByPageAndCondition?currentPage="+this.currentPage+"&pageSize="+this.pageSize,
        data:this.brand
    }).then(function (resp) {
        //设置表格数据
        _this.tableData = resp.data.rows; // {rows:[],totalCount:100}
        //设置总记录数
        _this.totalCount = resp.data.totalCount;
    })
    

axios的then里面不能用this,then外面可以用this

当查询中文时一直查询不出来数据,只能查询英文或数字的数据,鼓捣俩小时还是没整好,我估计哪里的乱码没处理好

4.代码优化:

我们想让他显示启动或禁用而不是显示1或0:

  • 在Brand实体类添加方法getStatusStr:
//逻辑视图
public String getStatusStr(){
    if (status == null){
        return "未知";
    }
    return status == 0 ? "禁用":"启用";
}
  • 在brand.html中将prop="status"改为prop="statusStr"
    • 框架会自动调用对象的getStatusgetStatusStr方法而不是调用对象的status成员变量statusStr成员变量,因为成员变量是私有的
      • 所以呢,我们只需要添加getStatusStr而不用添加statusStr属性

9,前端代码优化

咱们已经将所有的功能实现完毕。而针对前端代码中的发送异步请求的代码,如下

var _this = this;

axios({
    method:"post",
    url:"http://localhost:8080/brand-case/brand/selectByPageAndCondition?currentPage="+this.currentPage+"&pageSize="+this.pageSize,
    data:this.brand
}).then(function (resp) {

    //设置表格数据
    _this.tableData = resp.data.rows; // {rows:[],totalCount:100}
    //设置总记录数
    _this.totalCount = resp.data.totalCount;
})

需要在成功的回调函数(也就是then 函数中的匿名函数)中使用this,都需要在外边使用 _this 记录一下 this 所指向的对象;因为在外边的 this 表示的是 Vue 对象,而回调函数中的 this 表示的不是 vue 对象。这里我们可以使用 ECMAScript6 中的新语法(箭头函数)来简化这部分代码,如上面的代码可以简化为:

axios({
    method:"post",
    url:"http://localhost:8080/brand-case/brand/selectByPageAndCondition?currentPage="+this.currentPage+"&pageSize="+this.pageSize,
    data:this.brand
}).then((resp) => {

    //设置表格数据
    this.tableData = resp.data.rows; // {rows:[],totalCount:100}
    //设置总记录数
    this.totalCount = resp.data.totalCount;
})

箭头函数语法:

(参数) => {
	逻辑代码
}

箭头函数的作用:

替换(简化)匿名函数。

相关文章:

  • AD生成Gerber及CAM350检查
  • Python数据分析:折线图和散点图的绘制
  • 【Vue2基础】Vue项目搭建及组件使用
  • 艾美捷衣霉素Tunicamycin 化学性质及引用文献
  • 【小样本分割】Self-Support Few-Shot Semantic Segmentation
  • ch01变量和数据结构
  • 五分钟学会一门编程语言?
  • 【Python数据分析 - 11】:DataFrame索引操作(pandas篇)
  • [Vue]数据代理
  • VSCODE 系列(二)常用插件
  • 【zabbix】解决zabbix在web页面显示中文乱码问题
  • ESP32/ESP8266自动下载电路波形,ESP32/ESP8266不能UART流控自动下载的解决方法
  • c语言分层理解(枚举和联合体)
  • 网站死链抓取sitemap递交工具
  • 大意了,一次多线程操作不当导致的线上事故...
  • JS创建对象模式及其对象原型链探究(一):Object模式
  • linux学习笔记
  • Nacos系列:Nacos的Java SDK使用
  • Quartz实现数据同步 | 从0开始构建SpringCloud微服务(3)
  • vue自定义指令实现v-tap插件
  • 阿里研究院入选中国企业智库系统影响力榜
  • 测试如何在敏捷团队中工作?
  • 从输入URL到页面加载发生了什么
  • 对超线程几个不同角度的解释
  • 计算机在识别图像时“看到”了什么?
  • 离散点最小(凸)包围边界查找
  • 利用jquery编写加法运算验证码
  • 利用阿里云 OSS 搭建私有 Docker 仓库
  • 浅谈Kotlin实战篇之自定义View图片圆角简单应用(一)
  • #{}和${}的区别是什么 -- java面试
  • #stm32驱动外设模块总结w5500模块
  • #我与Java虚拟机的故事#连载11: JVM学习之路
  • (4)事件处理——(2)在页面加载的时候执行任务(Performing tasks on page load)...
  • (C语言)共用体union的用法举例
  • (java)关于Thread的挂起和恢复
  • (Java数据结构)ArrayList
  • (八)光盘的挂载与解挂、挂载CentOS镜像、rpm安装软件详细学习笔记
  • (附源码)springboot炼糖厂地磅全自动控制系统 毕业设计 341357
  • (附源码)计算机毕业设计SSM基于健身房管理系统
  • (六)激光线扫描-三维重建
  • (四) Graphivz 颜色选择
  • (四)TensorRT | 基于 GPU 端的 Python 推理
  • (一)使用IDEA创建Maven项目和Maven使用入门(配图详解)
  • (原创)Stanford Machine Learning (by Andrew NG) --- (week 9) Anomaly DetectionRecommender Systems...
  • .apk文件,IIS不支持下载解决
  • .NET Core/Framework 创建委托以大幅度提高反射调用的性能
  • [].slice.call()将类数组转化为真正的数组
  • [《百万宝贝》观后]To be or not to be?
  • [<MySQL优化总结>]
  • [14]内置对象
  • [20190401]关于semtimedop函数调用.txt
  • [acwing周赛复盘] 第 94 场周赛20230311
  • [Android]使用Retrofit进行网络请求
  • [COI2007] Sabor
  • [Gamma]阶段测试报告