四、Javaweb之Filter、Listener、Ajax、Vue

news2024/11/19 2:39:36

文章目录

  • 12. Filter 和 Listener
    • 12.1 Filter快速入门和执行流程
    • 12.2 Filter使用细节
    • 12.3 Filter案例:登录验证
    • 12.4 Listener
  • 13. AJAX
    • 13.1 AJAX快速入门
    • 13.2 AJAX案例
    • 13.3 Axios异步框架
    • 13.4 JSON
    • 13.5 JSON案例
      • SelectAllServlet.java
      • brand.html
      • AddServlet.java
      • addBrand.html
  • 14. Vue
    • 14.1 概述
    • 14.2 快速入门
    • 14.3 Vue常用指令
      • v-bind 和 v-model
      • v-on
      • v-if 和 v-show
      • v-for
    • 14.4 生命周期
    • 14.5 案例
    • 14.6 Element
      • 快速入门
      • Element布局
      • Element组件 - 表格 表单
  • 15. 综合案例
    • 15.1 完整项目及代码
    • 15.2 功能实现
      • 查询所有
      • 新增品牌
      • * Servlet优化 - BaseServlet
      • 批量删除
      • 分页查询
      • 条件查询
      • 前端优化

12. Filter 和 Listener

概念

Filter表示过滤器,Servlet, Filter, Listener是JavaWeb三大组件
过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能
过滤器一般完成一些通用的操作,比如:权限控制、统一编码处理、处理敏感字符等

Filter代码应写在web.filter目录下

12.1 Filter快速入门和执行流程

快速入门

  1. 定义类,实现Filter接口,并重写其所有方法
  2. 配置Filter拦截资源的路径,在类上定义@WebFilter注解
  3. 在doFilter方法中输出一句话,并放行
package org.example.web.filter;

//注意:Filter是javax.servlet.Filter
@WebFilter("/*")//拦截所有资源
public class FilterDemo implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("FilterDemo");
        //放行,如果不写下面这句话,hello.jsp不显示内容,但控制台有输出
        filterChain.doFilter(servletRequest, servletResponse);
    }
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }
    @Override
    public void destroy() {

    }
}

/* 表示拦截所有资源,即不管访问什么界面,都将来到FilterDemo.java,并执行doFilter方法

执行流程

流程:执行放行前逻辑 --> 放行 --> 访问资源 --> 执行放行后逻辑
  • 放行前:对request数据进行处理
  • 将携带处理后的request访问资源
  • 放行后:对response数据进行处理

12.2 Filter使用细节

拦截路径配置

@WebFilter("/*")
  • 拦截具体的资源:/index.jsp,只有访问index.jsp时才会被拦截
  • 目录拦截:/user/*,访问/user下的所有资源,都会被拦截
  • 后缀名拦截:*.jsp,访问后缀名为jsp的资源,都会被拦截
  • 拦截所有:/*,访问所有资源,都会被拦截

以配置 /index.jsp 为例,当访问index.jsp时,会执行 FilterDemo里面的doFilter()方法,但如果是访问 hello.jsp,doFilter方法直接不执行

过滤器链

一个Web应用,可以配置多个过滤器,这多个过滤器称为过滤器链

  • 注解配置的Filter,优先级按照过滤器类名(字符串)的自然排序先后执行

12.3 Filter案例:登录验证

需求:访问服务器资源时,需要先进行登录验证,如果没有登录,则自动转入登录界面

package org.example.web.filter;

/**
 * 登录验证的过滤器
 */
@WebFilter("/*")
public class LoginFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest req = (HttpServletRequest) request;
        //1. 判断session中是否有User
        HttpSession session = req.getSession();
        Object user = session.getAttribute("user");
        //2. 判断user是否为null
        if(user != null){
            //登录过了,放行
            chain.doFilter(request, response);
        }else{
            //没有登录,存储提示信息,跳转到登录界面
            req.setAttribute("login_msg", "您尚未登录");
            req.getRequestDispatcher("/login.jsp").forward(req, response);
        }
    }
    public void init(FilterConfig config) throws ServletException {
    }
    public void destroy() {
    }
}

先清除浏览器的浏览数据(清除缓存)
此时访问任何资源(页面)都会跳转到登录界面,且css样式都不显示了
在这里插入图片描述

这是因为css样式也被拦截下来,需要对登录注册相关的资源放行
修改后的过滤器如下

package org.example.web.filter;

/**
 * 登录验证的过滤器
 */
@WebFilter("/*")
public class LoginFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest req = (HttpServletRequest) request;

        //判断访问资源路径是否和登录注册相关
        String[] urls = {"/login.jsp", "/imgs/", "/css/", "/loginServlet", "/register.jsp", "/registerServlet", "/checkCodeServlet"};
        //获取当前访问的资源路径
        String url = req.getRequestURL().toString();
        //循环判断
        for(String u:urls){
            if(url.contains(u)){
                chain.doFilter(request, response);
                return;
            }
        }

        //1. 判断session中是否有User
        HttpSession session = req.getSession();
        Object user = session.getAttribute("user");
        //2. 判断user是否为null
        if(user != null){
            //登录过了,放行
            chain.doFilter(request, response);
        }else{
            //没有登录,存储提示信息,跳转到登录界面
            req.setAttribute("login_msg", "您尚未登录");
            req.getRequestDispatcher("/login.jsp").forward(req, response);
        }
    }
    public void init(FilterConfig config) throws ServletException {
    }
    public void destroy() {
    }
}

12.4 Listener

现在用的不多了

概念

Listener表示监听器
监听器可以用于监听application, seesion, request三个对象创建、销毁或者往其中添加修改删除属性这些事件

Listener分类
JavaWeb中提供了8个监听器

在这里插入图片描述

ServletContextListener使用

  1. 定义类,实现ServletContextListener接口
  2. 在类上添加@WebListener注解
package org.example.web.listener;

//ServletContext代表整个web应用,在服务器启动的时候,tomcat会自动创建该对象。在服务器关闭时会自动销毁该对象
@WebListener
public class ContextLoaderListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        //加载资源
        System.out.println("ContextLoadListener...");//会被自动调用
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        //释放资源
    }
}

13. AJAX

概念
AJAX (Asynchronous JavaScript And XML):异步的 JavaScript 和 XML

AJAX作用

  • 与服务器进行数据交换:通过AJAX可以给服务器发送请求,并获取服务器响应的数据
    在之前,是通过Servlet获取数据,再转发给JSP,响应给客户
    使用AJAX和服务器进行通信,就可以使用HTML+AJAX来替换JSP页面了
  • 异步交互:可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术,如:搜索联想、用户名是否可用校验等
    异步:客户端不需要阻塞等待服务器响应

13.1 AJAX快速入门

  1. 编写AjaxServlet,并使用response输出字符串
  2. 创建XMLHttpRequest对象:用于和服务器交换数据
  3. 向服务器发送请求
  4. 获取服务器响应数据

AjaxServlet.java

package org.example.web.servlet;

@WebServlet("/ajaxServlet")
public class AjaxServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 编写AjaxServlet,并使用response输出字符串
        response.getWriter().write("hello ajax");
    }

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

ajax-demo.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<script>
  //2. 创建XMLHttpRequest对象:用于和服务器交换数据
  //可以去https://www.w3school.com.cn/js/js_ajax_http.asp复制
  var xhttp;
  if (window.XMLHttpRequest) {
    xhttp = new XMLHttpRequest();
  }else{
    //code for IE6, IE5
    xhttp = new ActiveXObject("Microsoft.XMLHTTP");
  }
  //4. 获取服务器响应数据
  //前端后端可能部署环境不一致,所以这里写全路径
  xhttp.open("GET", "http://localhost:8080/tomcat-demo2/ajaxServlet")
  xhttp.send()
  //3. 获取响应
  xhttp.onreadystatechange = function () {
    if (this.readyState == 4 && this.status == 200){
      alert(this.responseText);
    }
  }
</script>

</body>
</html>

访问http://localhost:8080/tomcat-demo2/ajax-demo1.html,即可获取到服务端返回的数据

在这里插入图片描述

13.2 AJAX案例

需求:在完成用户注册时,当用户名输入框失去焦点时,校验用户名是否在数据库已存在

SelectUserServlet.java

package org.example.web.servlet;

@WebServlet("/selectUserServlet")
public class SelectUserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 接收用户名
        String username = request.getParameter("username");
        //2. 调用service查询User对象(模拟)
        boolean flag = true;
        //3. 响应标记
        response.getWriter().write(""+flag);
    }

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

register.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>欢迎注册</title>
    <link href="css/register.css" rel="stylesheet">
</head>
<body>

<div class="form-div">
    <div class="reg-content">
        <h1>欢迎注册</h1>
        <span>已有帐号?</span> <a href="login.html">登录</a>
    </div>
    <form id="reg-form" action="/tomcat-demo2/registerServlet" method="post">
        <table>
            <tr>
                <td>用户名</td>
                <td class="inputs">
                    <input name="username" type="text" id="username">
                    <br>
                    <span id="username_err" class="err_msg" style="display: none">用户名已存在</span>
                </td>
            </tr>
            <tr>
                <td>密码</td>
                <td class="inputs">
                    <input name="password" type="password" id="password">
                    <br>
                    <span id="password_err" class="err_msg" style="display: none">密码格式有误</span>
                </td>
            </tr>
        </table>
        <div class="buttons">
            <input value="注 册" type="submit" id="reg_btn">
        </div>
        <br class="clear">
    </form>
</div>

<script>
    document.getElementById("username").onblur = function () {
        //获取用户名的值
        var username = this.value;
        //1. 创建核心对象
        var xhttp;
        if(window.XMLHttpRequest){
            xhttp = new XMLHttpRequest();
        }else{
            //code for IE6, IE5
            xhttp = new ActiveXObject("Microsoft.XMLHTTP");
        }
        //2. 发送请求
        xhttp.open("GET", "http://localhost:8080/tomcat-demo2/selectUserServlet?username="+username)
        xhttp.send();
        //3. 获取响应
        xhttp.onreadystatechange = function () {
            if(this.readyState == 4 && this.status == 200){
                if(this.responseText == "true"){
                    //用户名存在,显示提示信息
                    document.getElementById("username_err").style.display = '';
                }else{
                    //用户名不存在,清除提示信息
                    document.getElementById("username_err").style.display = 'none';
                }
            }
        }
    }
</script>

</body>
</html>

13.3 Axios异步框架

Axios是对ajax的封装

  1. 引入axios的js文件
    在这里插入图片描述

    <script src="js/axios-0.18.0.js"></script>
    
  2. 使用axios发送请求,并获取响应结果

示例

AxiosServlet.java

package org.example.web.servlet;

@WebServlet("/axiosServlet")
public class AxiosServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("get ...");
        //1. 接收请求参数
        String username = request.getParameter("username");
        System.out.println(username);
        //2. 响应数据
        response.getWriter().write("hello axios");
    }

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

axios-demo.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script src="js/axios-0.18.0.js"></script>
<script>
  //1. 以get方式发送
  axios({
    method:"get",
    url:"http://localhost:8080/tomcat-demo2/axiosServlet?username=zhangsan"
  }).then(function (resp){
    alert(resp.data)
  })
  //2. 以post方式发送
  axios({
      method:"post",
      url:"http://localhost:8080/tomcat-demo2/axiosServlet",
      data:"username=zhangsan"
  }).then(function (resp){
      alert(resp.data)
  })
</script>
</body>
</html>

请求方式别名

为了方便,Axios已经为所有支持的请求方式提供了别名

axios.get(url[, config])
axios.delete(url[, config])
axios.head(url[, config])
axios.options(url[, config])
axios.post(url[, data[, config]])
axios.put(url[, data[, config]])
axios.patch(url[, data[, config]])

axios-demo.html

<script src="js/axios-0.18.0.js"></script>
<script>
  //1. 以get方式发送
  axios.get("http://localhost:8080/tomcat-demo2/axiosServlet?username=zhangsan").then(function (resp){
      alert(resp.data)
  })
  //2. 以post方式发送
  axios.post("http://localhost:8080/tomcat-demo2/axiosServlet", "username=zhangsan").then(function (resp){
      alert(resp.data)
  })
</script>

13.4 JSON

概念
JSON, JavaScript Object Notatio, JavaScript对象表示法
现多用于作为数据载体,在网络中进行数据传输

JSON基础语法

<script>
    var json = {
        "name":"zhangsan",
        "age":23,
        "addr":["北京","上海","西安"]
	};
	alert(json.name);
</script>

JSON数据和Java对象转换

Fastjson是阿里巴巴提供的一个Java语言编写的高性能功能完善的JSON库,是目前Java语言中最快的JSON库,可以实现Java对象和JSON字符串的相互转换

  • 导入坐标

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.62</version>
    </dependency>
    
  • Java对象转JSON

    String jsonStr = JSON.toJSONString(obj);
    
  • JSON字符串转Java对象

    User user = JSON.parseObject(jsonStr, User.class)
    

示例

public static void main(String[] args){
    //1. 将Java对象转为JSON字符串
    User user = new User();
    user.setId(1);
    user.setUsername("zhangsan");
    user.setPassword("123");

    String jsonString = JSON.toJSONString(user);
    System.out.println(jsonString);

    //2. 将JSON字符串转为Java对象
    User u = JSON.parseObject("{\"id\":1,\"password\":\"123\",\"username\":\"zhangsan\"}", User.class);
    System.out.println(u);
}

13.5 JSON案例

需求:使用Axios + JSON完成品牌列表数据查询和添加

先写完后端代码,运行查看是否能够获取数据,再写前端代码

查询所有功能

SelectAllServlet.java

package org.example.web;

@WebServlet("/selectAllServlet")
public class SelectAllServlet extends HttpServlet {
    private BrandService service = new BrandService();
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 调用service查询
        List<Brand> brands = service.selectAll();
        //2. 将集合转换为JSON数据   序列化
        String jsonString = JSON.toJSONString(brands);
        //3. 响应数据
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write(jsonString);
    }

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

brand.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<a href="addBrand.html"><input type="button" value="新增"></a><br>
<hr>
<table id="brandTable" border="1" cellspacing="0" width="100%">
</table>

<script src="js/axios-0.18.0.js"></script>
<script>
    //1. 当页面加载完成后,发送ajax请求
    window.onload = function () {
        //2. 发送ajax请求
        axios({
            method:"get",
            url:"http://localhost:8080/tomcat-demo2/selectAllServlet"
        }).then(function (resp) {
            //获取数据
            let brands = resp.data;
            let tableData = " <tr>\n" +
                "        <th>序号</th>\n" +
                "        <th>品牌名称</th>\n" +
                "        <th>企业名称</th>\n" +
                "        <th>排序</th>\n" +
                "        <th>品牌介绍</th>\n" +
                "        <th>状态</th>\n" +
                "        <th>操作</th>\n" +
                "    </tr>";
            for (let i = 0; i < brands.length ; i++) {
                let brand = brands[i];
                tableData += "\n" +
                    "    <tr align=\"center\">\n" +
                    "        <td>"+(i+1)+"</td>\n" +
                    "        <td>"+brand.brandName+"</td>\n" +
                    "        <td>"+brand.companyName+"</td>\n" +
                    "        <td>"+brand.ordered+"</td>\n" +
                    "        <td>"+brand.description+"</td>\n" +
                    "        <td>"+brand.status+"</td>\n" +
                    "\n" +
                    "        <td><a href=\"#\">修改</a> <a href=\"#\">删除</a></td>\n" +
                    "    </tr>";
            }
            // 设置表格数据
            document.getElementById("brandTable").innerHTML = tableData;
        })
    }
</script>
</body>
</html>

新增功能

AddServlet.java

package org.example.web;

@WebServlet("/addServlet")
public class AddServlet extends HttpServlet {
    private BrandService service = new BrandService();
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 接收数据
        //request.getParameter()不能接收JSON数据
        //需要获取请求体数据
        BufferedReader br = request.getReader();
        String param = br.readLine();
        //将JSON字符串转为Java对象
        Brand brand = JSON.parseObject(param, Brand.class);
        System.out.println(brand);
        //2. 调用service添加
        service.add(brand);
        //3. 响应成功标识
        response.getWriter().write("success");
    }

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

addBrand.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>添加品牌</title>
</head>
<body>
<h3>添加品牌</h3>
<!-- 不需要指定action -->
<form action="" method="post">
    品牌名称:<input id="brandName" name="brandName"><br>
    企业名称:<input id="companyName" name="companyName"><br>
    排序:<input id="ordered" name="ordered"><br>
    描述信息:<textarea rows="5" cols="20" id="description" name="description"></textarea><br>
    状态:
    <input type="radio" name="status" value="0">禁用
    <input type="radio" name="status" value="1">启用<br>
    <input type="button" id="btn"  value="提交">
</form>

<script src="js/axios-0.18.0.js"></script>
<script>
    //1. 给按钮绑定单击事件
    document.getElementById("btn").onclick = function () {
        //将表单的数据转为JSON
        var formData = {
            brandName:"",
            companyName:"",
            ordered:"",
            description:"",
            status:""
        };
        //获取表单数据
        let brandName = document.getElementById("brandName").value;
        formData.brandName = brandName;
        let companyName = document.getElementById("companyName").value;
        formData.companyName = companyName;
        let ordered = document.getElementById("ordered").value;
        formData.ordered = ordered;
        let description = document.getElementById("description").value;
        formData.description = description;
        let status = document.getElementsByName("status");
        for(let i=0; i<status.length; ++i){
            if(status[i].checked){
                formData.status = status[i].value;
            }
        }
        console.log(formData);
        //2. 发送ajax请求
        axios({
            method:"post",
            url:"http://localhost:8080/tomcat-demo2/addServlet",
            data:formData
        }).then(function (resp){
            //判断响应数据
            if(resp.data == "success"){
                location.href = "http://localhost:8080/tomcat-demo2/brand.html"
            }
        })
    }
</script>
</body>
</html>

14. Vue

14.1 概述

  • Vue 是一套前端框架,免除原生JavaScript中的DOM操作,简化书写

    在这里插入图片描述

    像这样的大量DOM操作,Vue将对其进行简化

  • 基于MVVM(Model-View-ViewModel)思想,实现数据的双向绑定,将编程的关注点放在数据上

    对于前端而言,MVC模型中,C是 js 代码,M 就是数据,而 V 是页面上展示的内容

    MVC 思想是没法进行双向绑定的,只能是js到html标签的单向绑定,当html里的内容变化时,js可以获取到;但js对于值变化时,html是感知不到的

    双向绑定是指当数据模型数据发生变化时,页面展示的会随之发生变化,而如果表单数据发生变化,绑定的模型数据也随之发生变化

    • MVVM思想
      在这里插入图片描述

      图中的 Model 就是数据,View 是视图,也就是页面标签,用户可以通过浏览器看到的内容;ModelView 是通过 ViewModel 对象进行双向绑定的,而 ViewModel 对象是 Vue 提供的

14.2 快速入门

引入vue.js

<script src="js/vue.js"></script>

创建Vue核心对象,进行数据绑定

<script>
    new Vue({
        el:"#app",
        data() {
            return {
                username:""
            }
        }
        //这里的data(){},实际上是data:function(){}
    });
</script>

编写视图

<div id="app">
    <!-- 视图 -->
    <input name="username" v-model="username">
    <!-- 数据模型 -->
    {{username}}
</div>

示例:mvvm.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="app">
    <!-- 视图 -->
    <input name="username" v-model="username">
    <!-- 数据模型 -->
    {{username}}
</div>

<script src="js/vue.js"></script>
<script>
    new Vue({
        el:"#app",
        data() {
            return {
                username:""
            }
        }
        //这里的data(){},实际上是data:function(){}
    });
</script>

</body>
</html>

结果:

在这里插入图片描述

14.3 Vue常用指令

指令:HTML 标签上带有 v- 前缀的特殊属性,不同指令具有不同含义。例如:v-if,v-for…

常用的指令有:

指令作用
v-bind为HTML标签绑定属性值,如设置 href , css样式等
v-model在表单元素上创建双向数据绑定
v-on为HTML标签绑定事件
v-if条件性的渲染某元素,判定为true时渲染,否则不渲染
v-else
v-else-if
v-show根据条件展示某元素,区别在于切换的是display属性的值
v-for列表渲染,遍历容器的元素或者对象的属性

v-bind 和 v-model

在这里插入图片描述

  • v-bind

    <a v-bind:href="url">百度一下</a>
    

    上面的 v-bind:" 可以简化写成 : ,如下:

    <!--
    	v-bind 可以省略
    -->
    <a :href="url">百度一下</a>
    

    注意这里的a标签后面一定要跟一个空格

    示例

    <div id="app">
        <!-- <a v-bind:href="url">点击一下</a> -->
        <a :href="url">点击一下</a>
        <input v-model="url">
    </div>
    ...
    <script src="js/vue.js"></script>
    <script>
        new Vue({
            el:"#app",
            data() {
                return {
                    username:"",
                    url:"https://www.baidu.com"
                }
            }
        });
    </script>
    
  • v-model

    <input name="username" v-model="username">
    

v-on

在这里插入图片描述

<div id="app">
    <input type="button" value="一个按钮" v-on:click="show()"><br>
    <!--简化-->
    <input type="button" value="一个按钮" @click="show">
</div>
...
<script src="js/vue.js"></script>
<script>
    new Vue({
        el:"#app",
        data() {
            return {
                username:"",
                url:"https://www.baidu.com"
            }
        },
        methods:{
          show(){
              alert("msg");
          }
        }
    });
</script>

v-if 和 v-show

v-if

<div id="app">
    <div v-if="count == 3">div1</div>
    <div v-else-if="count == 4">div2</div>
    <div v-else>div1</div>
    <br>
    <input v-model="count">
</div>
...
<script src="js/vue.js"></script>
<script>
    new Vue({
        el:"#app",
        data() {
            return {
                username:"",
                url:"https://www.baidu.com",
                count:3
            }
        }
    });
</script>

v-show

和v-if用法一致

<div v-show="count == 3">div v-show</div>

和v-if的区别: v-show 不展示的原理是给对应的标签添加 display css属性,并将该属性值设置为 none ,这样就达到了隐藏的效果。而 v-if 指令是条件不满足时根本就不会渲染。

v-for

在这里插入图片描述

<div id="app">
    <div v-for="addr in addrs">
        {{addr}}<br>
    </div>
</div>
...
<script src="js/vue.js"></script>
<script>
    new Vue({
        el:"#app",
        data() {
            return {
                addrs:["北京","上海","西安"]
            }
        },
    });
</script>

加索引

<!-- 从1开始 -->
<div id="app">
    <div v-for="(addr,i) in addrs">
        {{i+1}}--{{addr}}<br>
    </div>
</div>

14.4 生命周期

生命周期的八个阶段:每触发一个生命周期事件,会自动执行一个生命周期方法,这些生命周期方法也被称为钩子方法

在这里插入图片描述

mounted:挂载完成,Vue初始化成功,HTML页面渲染成功。而以后会在该方法中发送异步请求,加载数据

<script>
    new Vue({
        el:"#app",
        <!-- 实际上是mounted:function(){} -->
        mounted(){
            alert("vue挂载完毕,发送异步请求")
        }
    });
</script>

14.5 案例

查询所有:brand.html

<div id="app">
    <a href="addBrand.html"><input type="button" value="新增"></a><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>
        <!-- 使用v-for遍历 -->
        <tr v-for="(brand,i) in brands" align="center">
            <td>{{i+1}}</td>
            <td>{{brand.brandName}}</td>
            <td>{{brand.companyName}}</td>
            <td>{{brand.ordered}}</td>
            <td>{{brand.description}}</td>
            <td v-if="brand.status==1">启用</td>
            <td v-else>禁用</td>
            <td><a href="#">修改</a> <a href="#">删除</a></td>
        </tr>
    </table>
</div>
<script src="js/axios-0.18.0.js"></script>
<script src="js/vue.js"></script>
<script>
    new Vue({
        el:"#app",
        data(){
          return{
              brands:[]
          }
        },
        mounted(){
            //页面加载完成之后,发送异步请求,查询数据
            var _this = this;
            axios({
                method:"get",
                url:"http://localhost:8080/tomcat-demo2/selectAllServlet"
            }).then(function (resp){
                _this.brands = resp.data;
                //写在axios里的this指定的是windows对象,而非Vue,因此如果使用this.brands将不能成功获取
                //这里需要使用_this做一个替换
            })
        }
    })
</script>

新增:addBrand.html

<div id="app">
    <form action="" method="post">
        品牌名称:<input id="brandName" v-model="brand.brandName" name="brandName"><br>
        企业名称:<input id="companyName" v-model="brand.companyName" name="companyName"><br>
        排序:<input id="ordered" v-model="brand.ordered" name="ordered"><br>
        描述信息:<textarea rows="5" cols="20" id="description" v-model="brand.description" name="description"></textarea><br>
        状态:
        <input type="radio" name="status" v-model="brand.status" value="0">禁用
        <input type="radio" name="status" v-model="brand.status" value="1">启用<br>
        <input type="button" id="btn" @click="submitForm" value="提交">
    </form>
</div>
<script src="js/axios-0.18.0.js"></script>
<script src="js/vue.js"></script>
<script>
    new Vue({
        el:"#app",
        data(){
          return{
              brand:{}
          }
        },
        methods:{
            submitForm(){
                // 发送ajax请求,添加
                var _this = this;
                axios({
                    method:"post",
                    url:"http://localhost:8080/tomcat-demo2/addServlet",
                    data:_this.brand
                }).then(function (resp) {
                    // 判断响应数据是否为 success
                    if(resp.data == "success"){
                        location.href = "http://localhost:8080/tomcat-demo2/brand.html";
                    }
                })
            }
        }
    })
</script>

14.6 Element

Element:是饿了么公司前端开发团队提供的一套基于 Vue 的网站组件库,用于快速构建网页
Element 提供了很多组件(组成网页的部件)供我们使用。例如 超链接、按钮、图片、表格等等
官网地址:https://element.eleme.cn/#/zh-CN

快速入门

1.引入Element 的css、js文件 和 Vue.js

在这里插入图片描述

<script src="js/vue.js"></script>
<script src="element-ui/lib/index.js"></script>
<link rel="stylesheet" href="element-ui/lib/theme-chalk/index.css">

2.创建Vue核心对象

<script>
  new Vue({
    el:"#app"
  })
</script>

3.官网复制Element组件代码

Element布局

Element 提供了两种布局方式,分别是:

  • Layout 布局:通过基础的 24 分栏,迅速简便地创建布局

    在这里插入图片描述

  • Container 布局容器:用于布局的容器组件,方便快速搭建页面的基本结构

    在这里插入图片描述

Element组件 - 表格 表单

要完成的效果如下

在这里插入图片描述

依次完成的功能

  1. 表格(表格)
  2. 搜索表单(表单)
  3. 删除和新增按钮(按钮)
  4. 点击新增按钮弹出对话框(对话框)
  5. 新增对话框里的表单(表单)
  6. 分页工具条

element-demo.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .el-table .warning-row {
            background: oldlace;
        }

        .el-table .success-row {
            background: #f0f9eb;
        }
    </style>
</head>

<body>
<div id="app">
    <!-- 去Element官网复制,然后修改 -->
    <!-- 如果要设置属性如居中,在官网中的表格-Table-column Attributes -->

    <!-- 搜索表单 -->
    <el-form :inline="true" :model="brand" class="demo-form-inline">
        <el-form-item label="当前状态">
            <el-select v-model="brand.status" placeholder="当前状态">
                <el-option label="启用" value="1"></el-option>
                <el-option label="禁用" value="0"></el-option>
            </el-select>
        </el-form-item>
        <el-form-item label="企业名称">
            <el-input v-model="brand.companyName" placeholder="企业名称"></el-input>
        </el-form-item>
        <el-form-item label="品牌名称">
            <el-input v-model="brand.brandName" placeholder="品牌名称"></el-input>
        </el-form-item>
        <el-form-item>
            <el-button type="primary" @click="onSubmit">查询</el-button>
        </el-form-item>
    </el-form>

    <!-- 删除和新增按钮 -->
    <el-row>
        <el-button type="danger" plain>批量删除</el-button>
        <el-button type="primary" @click="dialogVisible = true" plain>新增</el-button>
    </el-row>

    <!-- 弹出新增数据的对话框 -->
    <!-- <el-button type="text" @click="dialogVisible = true">点击打开 Dialog</el-button> -->
    <el-dialog
            title="编辑品牌"
            :visible.sync="dialogVisible"
            width="30%">

        <!-- 新增数据对话框里面的表单 -->
        <el-form ref="form" :model="brand" label-width="80px">
            <el-form-item label="品牌名称">
                <el-input v-model="brand.brandName"></el-input>
            </el-form-item>
            <el-form-item label="企业名称">
                <el-input v-model="brand.companyName"></el-input>
            </el-form-item>
            <el-form-item label="排序">
                <el-input v-model="brand.ordered"></el-input>
            </el-form-item>
            <el-form-item label="备注">
                <el-input type="textarea" v-model="brand.description"></el-input>
            </el-form-item>
            <!-- Switch 开关 -->
            <el-form-item label="状态">
                <el-switch v-model="brand.status"
                           active-value="1"
                           inactive-value="0"
                ></el-switch>
            </el-form-item>
            <el-form-item>
                <el-button type="primary" @click="addBrand">提交</el-button>
                <el-button @click="dialogVisible = false">取消</el-button>
            </el-form-item>
        </el-form>
    </el-dialog>

    <!-- 表格 -->
    <template>
        <!-- 复选框需要设置方法 @selection-change -->
        <el-table
                :data="tableData"
                style="width: 100%"
                :row-class-name="tableRowClassName"
                @selection-change="handleSelectionChange"
        >
            <el-table-column
                    type="selection"
                    width="55">
            </el-table-column>
            <el-table-column
                    type="index"
                    width="50"
                    label="序号">
            </el-table-column>
            <el-table-column
                    prop="brandName"
                    align="center"
                    label="品牌名称">
            </el-table-column>
            <el-table-column
                    prop="companyName"
                    align="center"
                    label="企业名称">
            </el-table-column>
            <el-table-column
                    prop="ordered"
                    align="center"
                    label="排序">
            </el-table-column>
            <el-table-column
                    prop="status"
                    align="center"
                    label="当前状态">
            </el-table-column>
            <el-table-column
                    align="center"
                    label="操作">
                <el-row>
                    <el-button type="primary">修改</el-button>
                    <el-button type="danger">删除</el-button>
                </el-row>
            </el-table-column>
        </el-table>
    </template>

    <!-- 分页工具条 -->
    <el-pagination
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
            :current-page="currentPage"
            :page-sizes="[100, 200, 300, 400]"
            :page-size="100"
            layout="total, sizes, prev, pager, next, jumper"
            :total="400">
    </el-pagination>
</div>

<script src="js/vue.js"></script>
<script src="element-ui/lib/index.js"></script>
<link rel="stylesheet" href="element-ui/lib/theme-chalk/index.css">

<script>
  new Vue({
      el:"#app",
      methods: {
          tableRowClassName({row, rowIndex}) {
              if (rowIndex === 1) {
                  return 'warning-row';
              } else if (rowIndex === 3) {
                  return 'success-row';
              }
              return '';
          },
          //复选框选中后执行的方法
          handleSelectionChange(val) {
              this.multipleSelection = val;
              // console.log(this.multipleSelection);//在控制台可以看到选中的输出
          },
          //查询数据方法
          onSubmit() {
              // console.log(this.brand);//查看是否绑定成功
              //以后在这里添加和后端交互的代码
          },
          //添加数据
          addBrand(){
            console.log(this.brand);//查看是否绑定成功
          },
          //分页工具条函数
          handleSizeChange(val) {
              console.log(`每页 ${val}`);
          },
          handleCurrentChange(val) {
              console.log(`当前页: ${val}`);
          }
      },
      data() {
          return {
              //品牌模型数据
              brand: {
                  id:'',
                  status: '',
                  brandName: '',
                  companyName:'',
                  ordered:'',
                  description:''
              },
              //复选框选中数据集合
              multipleSelection: [],
              //表格数据
              tableData: [{
                  brandName: '华为',
                  companyName: '华为科技有限公司',
                  ordered: '100',
                  status:"1"
              }, {
                  brandName: '华为',
                  companyName: '华为科技有限公司',
                  ordered: '100',
                  status:"1"
              }, {
                  brandName: '华为',
                  companyName: '华为科技有限公司',
                  ordered: '100',
                  status:"1"
              }, {
                  brandName: '华为',
                  companyName: '华为科技有限公司',
                  ordered: '100',
                  status:"1"
              }],
              //新增按钮的弹出对话框默认显示为false
              dialogVisible: false,
              //当前页数
              currentPage: 4
          }
      }
  })
</script>

</body>
</html>

15. 综合案例

功能列表

  1. 查询所有
  2. 新增品牌
  3. 修改品牌(略)
  4. 删除品牌(略)
  5. 批量删除
  6. 分页查询
  7. 条件查询

准备工作

  1. 创建brand-case项目,设置JavaWeb相关配置

  2. 创建tb_brand表

  3. 导入一些基础文件,如element-ui,vue.js,以及上一小节编写的element-demo.html页面,更名为brand.html

  4. 在BrandMapper.xml记得做列名和属性名的转换

    <mapper namespace="org.example.mapper.BrandMapper">
        <resultMap id="brandResultMap" type="org.example.pojo.Brand">
            <result column="brand_name" property="brandName"/>
            <result column="company_name" property="companyName"/>
        </resultMap>
    </mapper>
    

    注意,这里路径有问题会报找不到ResultMap,可以去classes里看BrandMapper.class和BrandMapper.xml是否在同一路径

15.1 完整项目及代码

在这里插入图片描述

链接:https://pan.baidu.com/s/1cU2eXbEOInovl4B-aL8BQw
提取码:744t

15.2 功能实现

和第10节案例brand_demo相同的后端代码,这里省略

查询所有

后端:SelectAllServlet.java
和之前一致,需要注意的的是,这里sevice分为了接口和实现包

在这里插入图片描述

前端:brand.html
brand.html就是上一节的element-demo.html,下面是需要修改的部分

<script src="js/axios-0.18.0.js"></script>
...
mounted() {
    //当页面加载完成后,发送异步请求,获取数据
    this.selectAll();
},
methods: {
    //因为selectAll()经常用到,于是单独抽取一个函数
    selectAll() {
        var _this = this;
        axios({
            method: "get",
            url: "http://localhost:8080/brand-case/selectAllServlet"
        }).then(function (resp) {
            _this.tableData = resp.data;
        })
    },
}

新增品牌

后端:AddServlet.java

package org.example.web;

@WebServlet("/addServlet")
public class AddServlet extends HttpServlet {
    private BrandService service = new BrandServiceImpl();
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取请求体数据
        BufferedReader br = request.getReader();
        String param = br.readLine();
        //JSON转为Brand对象
        Brand brand = JSON.parseObject(param, Brand.class);
        //添加
        service.add(brand);
        //成功标识
        response.getWriter().write("success");
    }

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

前端:brand.html

el-button type="primary" @click="addBrand">提交</el-button>
...
data() {
    return {
        //品牌模型数据
        brand: {
            id: '',
            status: '',
            brandName: '',
            companyName: '',
            ordered: '',
            description: ''
        },
    }
},
methods: {
    addBrand() {
        // console.log(this.brand);//查看是否绑定成功
        var _this = this;
        axios({
            method: "post",
            url: "http://localhost:8080/brand-case/addServlet",
            data: this.brand
        }).then(function (resp) {
            if (resp.data == "success") {
                // location.href = "http://localhost:8080/brand-case/brand.html"
                //关闭对话框窗口
                _this.dialogVisible = false;
                //重新查询数据
                _this.selectAll();
                //弹出消息提示
                _this.$message({
                    message: '恭喜你,添加成功',
                    type: 'success'
                });
            }
        })
    },
}

* Servlet优化 - BaseServlet

问题:Servlet太多了,每一个功能都需要写一个Servlet
解决:Servlet归类

需求:希望像BrandService那样,同一类的Servlet写在一个文件里,如

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

之前的Servlet都是继承自HttpServlet,然后实现doPost方法,显然归类后不能再这么写,书写方法如下:

  • BaseServlet.java

    !详细理解下面的代码

    package org.example.web.servlet;
    
    /**
     * 替换HttpServlet,根据请求的最后一段路径来进行分发
     */
    public class BaseServlet extends HttpServlet {
        //根据请求的最后一段路径来进行分发,需要重写service方法
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //1. 获取请求路径
            String uri = req.getRequestURI();//获取的路径形如 "/brand-case/brand/selectAll"
            //2. 获取最后一段路径,方法名
            int index = uri.lastIndexOf('/');
            String methodName = uri.substring(index+1);
            //3. 执行对象
            //this:谁调用我(this所在的方法,service),我(this)代表谁
            //以后使用BrandServlet extends BaseServlet,那么BrandServlet将调用父类的service,因此是BrandServlet进行调用,this代表BrandServlet
            //System.out.println(this);//这里的this以后代表的是BrandServlet
            //3.1 获取 BrandServlet / UserServlet 字节码对象 Class
            Class<? extends BaseServlet> cls = this.getClass();
            //3.2 获取方法Method对象,根据方法名和所有参数的class获取
            try {
                Method method = cls.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
                //3.3 执行方法
                //假设访问的是/brand/*,那么this指代的是BrandServlet,下面语句代表执行BrandServlet里面的method
                method.invoke(this, req, resp);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
    }
    
  • BrandServlet.java

    package org.example.web.servlet;
    
    @WebServlet("/brand/*")
    public class BrandServlet extends BaseServlet {
        private BrandService service = new BrandServiceImpl();
        public void selectAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //1. 获取数据
            List<Brand> brands = service.selectAll();
            //2. 封装JSON
            String jsonStr = JSON.toJSONString(brands);
            //3. 响应数据
            response.setContentType("text/html;charset=utf-8");
            response.getWriter().write(jsonStr);
        }
        public void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //获取请求体数据
            BufferedReader br = request.getReader();
            String param = br.readLine();
            //JSON转为Brand对象
            Brand brand = JSON.parseObject(param, Brand.class);
            //添加
            service.add(brand);
            //成功标识
            response.getWriter().write("success");
        }
    }
    

    这里的service没有调用doGet或者doPost方法,个人理解为:一是这里没有用到get传递参数,二是通过axois进行数据交互时,一般会使用post,这样后端只需要使用getReader()即可

  • brand.html

    前端代码的地址要修改一下

    url: "http://localhost:8080/brand-case/brand/add"
    

批量删除

后端

  • BrandMapper.java

    /**
     * 批量删除
     * 操作比较复杂,不再使用注解,而使用xml
     * @param ids
     */
    void deleteByIds(@Param("ids") int[] ids);
    
  • BrandMapper.xml

    <delete id="deleteByIds">
        delete from tb_brand where id in
        <foreach collection="ids" item="id" separator="," open="(" close=")">#{id}</foreach>;
    </delete>
    
  • BrandService接口和BrandServiceImpl.java

    /**
     * 批量删除
     * @param ids
     */
    void deleteByIds(int[] ids);
    
    @Override
    public void deleteByIds(int[] ids) {
        SqlSession session = factory.openSession();
        BrandMapper mapper = session.getMapper(BrandMapper.class);
        mapper.deleteByIds(ids);
        session.commit();
        session.close();
    }
    
  • 在BrandServlet.java里面添加deleteByIds方法

    public void deleteByIds(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取请求体数据
        BufferedReader br = request.getReader();
        String param = br.readLine();
        //JSON转为int[]
        int[] ids = JSON.parseObject(param, int[].class);
        //批量删除
        service.deleteByIds(ids);
        //成功标识
        response.getWriter().write("success");
    }
    

前端:brand.html

<el-button type="danger" @click="deleteByIds" plain>批量删除</el-button>
...
data() {
    return {
        //复选框选中数据集合
        multipleSelection: [],
        //被选中的ids,用于批量删除
        selectedIds:[],
    }
},
methods: {
	deleteByIds(){
        //弹出确认提示框,显示是否删除(官网代码)
        this.$confirm('此操作将永久删除该数据, 是否继续?', '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
        }).then(() => {
            //用户点击确认按钮
            //1. 创建id数组,并从this.multipleSelection中获取数据
            for(let i=0; i<this.multipleSelection.length; i++){
                let selectionElement = this.multipleSelection[i];
                this.selectedIds[i] = selectionElement.id;
            }
            console.log(this.selectedIds);
            //2. 发送ajax请求
            var _this = this;
            axios({
                method: "post",
                url: "http://localhost:8080/brand-case/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: '已取消删除'
            });
        });

    },
}

注意:这里删除时获取的id和页面中展示的序号不一样

分页查询

后端

  • PageBean.java

    package org.example.pojo;
    
    //使用泛型,以后更加通用
    public class PageBean<T> {
        private int totalCount;
        private List<T> rows;
        //省略getter, setter, toString
    }
    
  • BrandMapper.java

    /**
     * 分页查询
     * @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();
    
  • BrandService接口

    /**
     * 分页查询,根据当前页数和每页大小,返回当页数据和总记录数
     * @param currentPage
     * @param pageSize
     * @return
     */
    public PageBean selectByPage(int currentPage, int pageSize);
    
  • BrandServiceImpl.java

    @Override
    public PageBean selectByPage(int currentPage, int pageSize) {
        SqlSession session = factory.openSession();
        BrandMapper mapper = session.getMapper(BrandMapper.class);
        //计算开始索引
        int begin = (currentPage-1) * pageSize;
        //计算查询条目数
        int size = pageSize;
        //查询当前页数据
        List<Brand> rows = mapper.selectByPage(begin, size);
        //查询总记录数
        int totalCount = mapper.selectTotalCount();
        PageBean<Brand> pageBean = new PageBean<>();
        pageBean.setRows(rows);
        pageBean.setTotalCount(totalCount);
        session.close();
        return pageBean;
    }
    
  • BrandServlet.java

    public void selectByPage(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 接收参数 当前页码 和 每页展示条数 url?currentPage=1&pageSize=5
        int currentPage = Integer.parseInt(request.getParameter("currentPage"));
        int pageSize = Integer.parseInt(request.getParameter("pageSize"));
        //2. 查询数据
        PageBean<Brand> pageBean = service.selectByPage(currentPage, pageSize);
        //3. 返回数据
        String jsonStr = JSON.toJSONString(pageBean);
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write(jsonStr);
    }
    

前端:brand.html

<!-- 分页工具条 -->
<el-pagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="currentPage"
        :page-sizes="[5, 10, 20, 30, 40]"
        :page-size="pageSize"
        layout="total, sizes, prev, pager, next, jumper"
        :total="totalCount">
</el-pagination>


data() {
    return {
        //分页数据:当前页数和每页展示量
        currentPage: 1,
        pageSize: 5,
        totalCount: 100,
    }
},
methods: {
    //这里selectAll也要改变一下
    selectAll() {
        var _this = this;
        axios({
            method: "get",
            url: "http://localhost:8080/brand-case/brand/selectByPage?currentPage="+_this.currentPage+"&pageSize="+_this.pageSize
        }).then(function (resp) {
            _this.tableData = resp.data.rows;
            _this.totalCount = resp.data.totalCount;
        })
    },
	handleSizeChange(val) {
        // console.log(`每页 ${val} 条`);
        this.pageSize = val;
        this.selectAll();
    },
    handleCurrentChange(val) {
        // console.log(`当前页: ${val}`);
        this.currentPage = val;
        this.selectAll();
    },
}

条件查询

后端

  • BrandMapper.java

    /**
     * 条件分页查询
     * @param begin
     * @param size
     * @param brand
     * @return
     */
    List<Brand> selectByPageCondition(@Param("begin") int begin, @Param("size") int size, @Param("brand") Brand brand);
    
    /**
     * 条件分页查询出来的总数
     * @param brand
     * @return
     */
    int selectTotalCountByCondition(Brand brand);
    

    有了条件分页查询之后,之前的普通分页查询其实已经用不上了

  • BrandMapper.xml

    <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>
    
  • BrandService接口

    /**
     * 分页条件查询
     * @param currentPage
     * @param pageSize
     * @param brand
     * @return
     */
    public PageBean selectByPageAndCondition(int currentPage, int pageSize, Brand brand);
    
  • BrandServiceImpl.java

    @Override
    public PageBean selectByPageAndCondition(int currentPage, int pageSize, Brand brand) {
        SqlSession session = factory.openSession();
        BrandMapper mapper = session.getMapper(BrandMapper.class);
        //计算开始索引
        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+"%");
        }
        //查询当前页数据
        List<Brand> rows = mapper.selectByPageAndCondition(begin, size, brand);
        //查询总记录数
        int totalCount = mapper.selectTotalCountByCondition(brand)
        PageBean<Brand> pageBean = new PageBean<>();
        pageBean.setRows(rows);
        pageBean.setTotalCount(totalCount);
        session.close();
        return pageBean;
    }
    
  • BrandServlet.java

    public void selectByPageAndCondition(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 接收参数 当前页码 和 每页展示条数 url?currentPage=1&pageSize=5
        int currentPage = Integer.parseInt(request.getParameter("currentPage"));
        int pageSize = Integer.parseInt(request.getParameter("pageSize"));
        //2. 获取查询条件对象
        BufferedReader br = request.getReader();
        String param = br.readLine();
        Brand brand = JSON.parseObject(param, Brand.class);
        //2. 查询数据
        PageBean<Brand> pageBean = service.selectByPageAndCondition(currentPage, pageSize, brand);
        //3. 返回数据
        String jsonStr = JSON.toJSONString(pageBean);
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write(jsonStr);
    }
    

前端:brand.html

修改selectAll方法

<el-button type="primary" @click="onSubmit">查询</el-button>
...
methods:{
	//和之前的分页查询合并
	selectAll() {
        var _this = this;
        axios({
            method: "post",
            url:"http://localhost:8080/brand-case/brand/selectByPageAndCondition?currentPage=" + _this.currentPage + "&pageSize=" + _this.pageSize,
            data:this.brand
            //then外面可以直接用this,then里面用+this
        }).then(function (resp) {
            _this.tableData = resp.data.rows;
            _this.totalCount = resp.data.totalCount;
        })
    },
	//条件分页查询
    onSubmit() {
    // console.log(this.brand);//查看是否绑定成功
    this.selectAll();
    },
}

前端优化

selectAll() {
    axios({
        method: "post",
        url:"http://localhost:8080/brand-case/brand/selectByPageAndCondition?currentPage=" + _this.currentPage + "&pageSize=" + _this.pageSize,
        data:this.brand
        //then外面可以直接用this,then里面用+this
    }).then(resp=>{
        //新的写法
        this.tableData = resp.data.rows;
        this.totalCount = resp.data.totalCount;
    })
},

之后可以练习,将之前的登录注册、用户操作、brand操作合并一起

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

某集团汽车配件电子图册性能分析案例(二)

背景 汽车配件电子图册系统是某汽车集团的重要业务系统。业务部门反映&#xff0c;汽车配件电子图册调用图纸时&#xff0c;出现访问慢现象。 某汽车集团总部已部署NetInside流量分析系统&#xff0c;使用流量分析系统提供实时和历史原始流量。本次分析重点针对汽车配件电子图…

JDBC简介及原理和使用介绍

JDBC简介及原理和使用介绍JDBC简介 jdbc概述 ​ Java数据库连接&#xff0c;&#xff08;Java Database Connectivity&#xff0c;简称JDBC&#xff09;是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口&#xff0c;提供了诸如查询和更新数据库中数据的方法。 …

WebGL-iTwin.js】实战篇(二):用nodejs代码详解iTwin.js中PhysicalObject生成方法

PhysicalObject 即真实存在的物理对象&#xff0c;比如&#xff1a;电脑、桌子等。在webgl中&#xff0c;我们人眼能看到的模型都是PhysicalObject&#xff0c;由多种几何图元类型构成&#xff0c;如&#xff1a;网格、实体、曲面、曲线&#xff0c;点云等。 其中带索引的多边…

XCTF:cat

打开是一个输入框&#xff0c;要求输入域名&#xff0c;尝试输入baidu.com进行测试 并无任何回显&#xff0c;测试下127.0.0.1本地地址 执行成功&#xff0c;并出现ping命令结果&#xff0c;这里很容易联想到命令注入&#xff0c;尝试进行命令拼接注入 但测试了常用的拼接字…

【5】变量和常量

一、什么是变量 首先我们要理解这么一个概念&#xff0c;在程序的运行过程中所有数据是保存在内存中的&#xff0c;我们代码中想使用这个数据的时候就要从内存中找&#xff0c;而变量的作用类似就是将内存地址保存&#xff0c;之后直接通过这个变量找内存中的数在Go语言中&…

JNI和Ndk开发

按照一下配置&#xff0c;基本能保证demo跑通 1、下载NDK&#xff0c;下载需要的版本 2、下载Cmake版本 3、项目结构&#xff1a;含C源码 4、编写JNI的加载类 public class YjkModel {static {System.loadLibrary("nativ"); //跟CMakeLists.txt 库名一致}public nat…

基于 APISIX 的服务网格方案 Amesh 积极开发中!

作者lingsamuel&#xff0c;API7.ai 云原生技术专家&#xff0c;Apache APISIX Committer。 在云原生快速发展的前提下&#xff0c;服务网格领域也开始逐渐火热。目前阶段&#xff0c;大家所熟知的服务网格解决方案很多&#xff0c;每种产品又各有其优势。因此在面对不同的行业…

python直接赋值、浅拷贝与深拷贝

本文主要参考这篇博文python浅拷贝与深拷贝 基本概念 首先了解python中的一些基本概念 变量&#xff1a;是一个系统表的元素&#xff0c;拥有指向对象的连接空间对象&#xff1a;被分配的一块内存&#xff0c;存储其所代表的值引用&#xff1a;是自动形成的从变量到对象的指…

ECU Extract + OS Task Mapping 步骤

纲要&#xff1a; 通过 Composition里面的Assembly Connection (Intra-ECU Communication)System Extract 里面的SystemDataMapping (Inter-ECU Communication) 已经把SWC的所有Data Element都连接上了&#xff0c;接下来就是把SWC的Runnable给Mapping到对应的OS Task上&…

(三)redis五大数据类型和key

目录 一、redis键&#xff08;key&#xff09;的常用操作 二、redis字符串&#xff08;String&#xff09; 1、简介 2、常用命令 3、数据结构 三、redis列表&#xff08;List&#xff09; 1、简介 2、常用命令 3、数据结构 四、redis集合&#xff08;Set&#xff09;…

Django(16):rest_framework框架使用指南

目录1.安装配置2.数据序列化2.1 Serializer2.2 ModelSerializer2.3 序列化对象的属性和方法3.请求和响应3.1 Request3.2 Response3.3 状态码3.4 as_view3.5 format_suffix_patterns3.6 示例4.CBV构建&#xff08;基于类的视图&#xff09;4.1 如何构建4.2 类型视图的扩展功能4.…

DMIPS, FLOPS, OPS概念

DMIPS DMIPS(Dhrystone Million Instructions executed Per Second)&#xff1a;Dhrystone是测量处理器运算能力的最常见基准程序之一&#xff0c;常用于处理器的整型运算性能的测量。Dhrystone是一种整数运算测试程序。换句话说&#xff0c;就是使用Dhrystone这种程序在不同的…

【云原生 | 52】Docker三剑客之Docker Compose第三节

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 &#x1f3c5;阿里云ACE认证高级工程师 &#x1f3c5;阿里云开发者社区专…

FineReport填报报表

二次确认&#xff0c;删除行&#xff1a;参考&#xff1a; JS实现删除时二次确认- FineReport帮助文档 - 全面的报表使用教程和学习资料JS实现记录填报操作- FineReport帮助文档 - 全面的报表使用教程和学习资料确认后直接校验提交// 二次确认 var cell this.options.location…

开始安装Domino 12.0.2

大家好&#xff0c;才是真的好。 上周我们话题是NotesDomino12.0.2产品发布&#xff0c;主要说到了Domino12.0.2的新特性&#xff0c;新特性很多&#xff0c;要用很多篇来进行测试和说明。 今天我们主要谈谈Domino 12.0.2的系统要求和安装等。 首先&#xff0c;Domino12.0.2…

一、初识FreeRTOS之FreeRTOS简介

目录 一、什么是FreeRTOS&#xff1f; 二、为什么选择FreeRTOS&#xff1f; 三、FreeRTOS的特点 四、FreeRTOS资料与源码下载 五、FreeRTOS源码文件介绍 一、什么是FreeRTOS&#xff1f; Free即免费的&#xff0c;RTOS的全称是Real time operating system,中文就是实时操作…

python数据结构(一):字符串

一、字符串的格式化输出 1.1、格式化运算符 print("我跑完了第" str(lap 1) "圈")上面这段输出的代码使用了两个加号做了字符串拼接&#xff0c;并且将整形转换成了字符串。也可以使用一种更好的办法&#xff0c;格式化输出来打印这句话。 print(&quo…

xilinx srio ip学习笔记之再识srio

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 xilinx srio ip学习笔记之再识srio前言SRIO的理解IP核的理解前言 这段时间&#xff0c;随着对SRIO的学习&#xff0c;又有了更深的一点认识&#xff0c;不像一开始这么慌张了…

年终汇报工作,如何用项目管理工具展现成果

据报道&#xff0c;2022年11月20日的一次京东内部会议上&#xff0c;刘强东痛批京东中高层管理人员&#xff0c;表示部分高管醉心于 PPT 和奇妙词汇&#xff0c;或吹得天花乱坠但是执行一塌糊涂。 不可否认&#xff0c;刘强东提到的现象&#xff0c;的确是当今众多互联网大厂和…

基于frp实现外网访问个人本地服务器

适用对象想要通过frp实现内网服务被外网访问的人。关键词描述内网&#xff1a;内网指的是局域网&#xff0c;几台或者几十台电脑之间互访&#xff0c;也叫私网。外网&#xff1a;指的是我们上的Internet网络&#xff0c;也叫公网。需要具备的知识基础和条件1&#xff1a;外网服…