四、Javaweb之Filter、Listener、Ajax、Vue

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/1YdaqWLo7kD09-7U-v-DUxw
提取码:rfm3

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操作合并一起

mybatis-config.xml优化

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>
    <properties resource="jdbc.properties"></properties>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--数据库连接信息-->
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <package name="org.example.mapper"/>
    </mappers>
</configuration>

在resources下创建:jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///test?useSSL=false&amp;useServerPrepStmts=true
jdbc.username=root
jdbc.password=123456
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值