黑马程序员最新版JavaWeb综合案例(前后端完整版)

news2025/7/10 3:34:29

JavaWeb 综合案例

学习视频链接: 黑马程序员最新版JavaWeb基础教程,Java web从入门到企业实战完整版
完整代码链接: https://github.com/HaiLei-Fly/JavaWeb-brand

1、功能介绍

案例功能:

  • 用户登录(账号密码登录)
  • 用户注册(新用户注册账号)
  • 查询所有(查询所有品牌数据)
  • 新增品牌(增加新的品牌数据)
  • 修改品牌(修改品牌数据)
  • 删除品牌(删除品牌数据)
  • 批量删除(删除多条品牌数据)
  • 分页查询(分页展示品牌数据)
  • 条件查询(通过条件精确查询品牌数据)

2、工程准备

2.1 所需环境

MySQL 8.0.22
JDK 11.0.10
MAVEN 3.6.0
Navicat 16
IDEA 2021.3.3
pom.xml文件如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>brand-case</artifactId>
    <version>1.0-SNAPSHOT</version>

    <packaging>war</packaging>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

    <dependencies>
    <!--Servlet-->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>


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

    <!--jstl-->
    <dependency>
        <groupId>jstl</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>

    <dependency>
        <groupId>taglibs</groupId>
        <artifactId>standard</artifactId>
        <version>1.1.2</version>
    </dependency>

    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.5</version>
    </dependency>

    <!--MySQL-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.22</version>
    </dependency>

        <!--fastjson-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.62</version>
        </dependency>


    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>

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

</project> 

2.2 工程结构

Maven Web开发中的项目结构如下:

在这里插入图片描述
Java目录结构如下:

在这里插入图片描述
resources和webapp目录结构如下:

在这里插入图片描述

3、数据库

3.1 建立连接

Navicat 与本地MySQL数据库建立连接

在这里插入图片描述
输入MySQL数据库密码,连接成功

在这里插入图片描述
新建数据库db1

在这里插入图片描述

3.2 建表程序

创建品牌表sql语句

-- 删除tb_brand表
drop table if exists tb_brand;
-- 创建tb_brand表
create table tb_brand
(
    -- id 主键
    id           int primary key auto_increment,
    -- 品牌名称
    brand_name   varchar(20),
    -- 企业名称
    company_name varchar(20),
    -- 排序字段
    ordered      int,
    -- 描述信息
    description  varchar(100),
    -- 状态:0:禁用  1:启用
    status       int
);
-- 添加数据
insert into tb_brand (brand_name, company_name, ordered, description, status)
values 
       ('华为', '华为技术有限公司', 100, '万物互联', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
       ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
       ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
       ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
       ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
       ('华为', '华为技术有限公司', 100, '万物互联', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
       ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
       ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
       ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
       ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
       ('华为', '华为技术有限公司', 100, '万物互联', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
       ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
       ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
       ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
       ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
       ('华为', '华为技术有限公司', 100, '万物互联', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
       ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
       ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
       ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
       ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
       ('华为', '华为技术有限公司', 100, '万物互联', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
       ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
       ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
       ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
       ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
       ('华为', '华为技术有限公司', 100, '万物互联', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
       ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
       ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
       ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
       ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1)
        ;

在这里插入图片描述
创建用户表sql语句

-- 删除tb_brand表
drop table if exists tb_user;
-- 创建tb_brand表
create table tb_user
(
    -- id 主键
    id           int primary key auto_increment,
    -- 用户名称
    username   varchar(20),
    -- 用户密码
    password varchar(20)
);
-- 添加数据
insert into tb_user (username, password)
values 
       ('ming', '1234567890'),
       ('wang', '1234567890')
			 ;

在这里插入图片描述
连接数据库配置文件,在resources目录下创建 mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <typeAliases>
        <package name="com.hailei.pojo"/>
    </typeAliases>

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

4、用户登录功能

整体流程:

  • (1) 前端login.jsp页面加载完成后,通过表单发送请求和数据给Web层的LoginServlet
  • (2) 在LoginServlet中接收请求和数据(用户名和密码)
  • (3) LoginServlet接收到请求和数据后,调用Service层完成根据用户名和密码查询用户对象
  • (4) 在Service层需要编写UserService类,在类中实现login方法,方法中调用Dao层的UserMapper
  • (5) 在UserMapper接口中,声明一个根据用户名和密码查询用户信息的方法
  • (6) Dao层把数据查询出来以后,将返回数据封装到User对象,将对象交给Service层
  • (7) Service层将数据返回给Web层
  • (8) Web层获取到User对象后,判断User对象,如果为Null,则将错误信息响应给登录页面,如果不为Null,则跳转到列表页面,并把当前登录用户的信息存入Session携带到列表页面

4.1 后端实现

dao方法实现:

在java目录下的 com.hailei.mapper.UserMapper 接口中定义抽象方法,并使用 @Select 注解编写 sql 语句

/**
     * 根据用户名和密码查询用户对象
     * @param username
     * @param password
     * @return
     */
    @Select("select * from tb_user where username = #{username} and password = #{password}")
    User select(@Param("username") String username,@Param("password")  String password);

service方法实现:

在java目录下的 com.hailei.service 下再创建 impl 包;impl 表示是放 service 层接口的实现类的包。 在该包下创建名为 UserServiceImpl

public class UserServiceImpl implements UserService {
    SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory();

    /**
     * 登录方法
     * @param username
     * @param password
     * @return
     */

    public User login(String username, String password){
        //2. 获取SqlSession
        SqlSession sqlSession = factory.openSession();
        //3. 获取UserMapper
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //4. 调用方法
        User user = mapper.select(username, password);

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

        return  user;
    }
}

在java目录下的 com.hailei.service 包下创建 UserService 接口,在该接口中定义登录的抽象方法

/**
     * 登录方法
     * @param username
     * @param password
     * @return
     */

    User login(String username, String password);
}

servlet方法实现:

在java目录下的 com.hailei.web.servlet 包下定义名为 LoginServlet 的登录的 servlet

@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
    private UserService service = new UserServiceImpl();

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 获取用户名和密码
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        //获取复选框数据
        String remember = request.getParameter("remember");

        //2. 调用service查询
        User user = service.login(username, password);

        //3. 判断
        if(user != null){
            //登录成功,跳转到查询所有的BrandServlet

            //判断用户是否勾选记住我
            if("1".equals(remember)){
                //勾选了,发送Cookie

                //1. 创建Cookie对象
                Cookie c_username = new Cookie("username",username);
                Cookie c_password = new Cookie("password",password);
                // 设置Cookie的存活时间
                c_username.setMaxAge( 60 * 60 * 24 * 7);
                c_password.setMaxAge( 60 * 60 * 24 * 7);
                //2. 发送
                response.addCookie(c_username);
                response.addCookie(c_password);
            }

            //将登陆成功后的user对象,存储到session
            HttpSession session = request.getSession();
            session.setAttribute("user",user);

            String contextPath = request.getContextPath();
            response.sendRedirect(contextPath+"/brand.html");
        }else {
            // 登录失败,

            // 存储错误信息到request
            request.setAttribute("login_msg","用户名或密码错误");

            // 跳转到login.jsp
            request.getRequestDispatcher("/login.jsp").forward(request,response);

        }
    }

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

在java目录下的 com.hailei.web.filter 包下定义名为 LoginFilter 的过滤器

/**
 * 登录验证的过滤器
 */

@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);
                //break;
                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() {
    }

}

4.2 前端实现

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>login</title>
    <link href="css/login.css" rel="stylesheet">
</head>

<body>
<div id="loginDiv" style="height: 350px">
    <form action="/brand-case/loginServlet" method="post" id="form">
        <h1 id="loginMsg">LOGIN IN</h1>
        <div id="errorMsg">${login_msg} ${register_msg}</div>
        <p>Username:<input id="username" name="username" value="${cookie.username.value}" type="text"></p>

        <p>Password:<input id="password" name="password" value="${cookie.password.value}" type="password"></p>
        <p>Remember:<input id="remember" name="remember" value="1" type="checkbox"></p>
        <div id="subDiv">
            <input type="submit" class="button" value="login up">
            <input type="reset" class="button" value="reset">&nbsp;&nbsp;&nbsp;
            <a href="register.jsp">没有账号?</a>
        </div>
    </form>
</div>



</body>
</html>

启动项目:

在这里插入图片描述
功能展示:
在这里插入图片描述

5、用户注册功能

整体流程:

  • (1) 前端通过表单发送请求和数据给Web层的RegisterServlet
  • (2) 在RegisterServlet中接收请求和数据(用户名和密码)
  • (3) RegisterServlet接收到请求和数据后,调用Service层完成用户信息的保存
  • (4) 在Service层需要编写UserService类,在类中实现register方法,需要判断用户是否已经存在,如果不存在,则完成用户数据的保存
  • (5) 在UserMapper接口中,声明两个方法,一个是根据用户名查询用户信息方法,另一个是保存用户信息方法
  • (6) 在UserService类中保存成功则返回true,失败则返回false,将数据返回给Web层
  • (7) Web层获取到结果后,如果返回的是true,则提示注册成功,并转发到登录页面,如果返回false则提示用户名已存在并转发到注册页面

5.1 后端实现

dao方法实现:

在java目录下的 com.hailei.mapper.UserMapper 接口中定义抽象方法,并使用 @Select 注解编写 sql 语句

/**
     * 根据用户名查询用户对象
     * @param username
     * @return
     */
    @Select("select * from tb_user where username = #{username}")
    User selectByUsername(String username);

    /**
     * 添加用户
     * @param user
     */
    @Insert("insert into tb_user values(null,#{username},#{password})")
    void add(User user);

service方法实现:

在java目录下的 com.hailei.service 下再创建 impl 包;impl 表示是放 service 层接口的实现类的包。 在该包下创建名为 UserServiceImpl

/**
     * 注册方法
     * @return
     */

    public boolean register(User user){
        //2. 获取SqlSession
        SqlSession sqlSession = factory.openSession();
        //3. 获取UserMapper
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        //4. 判断用户名是否存在
        User u = mapper.selectByUsername(user.getUsername());

        if(u == null){
            // 用户名不存在,注册
            mapper.add(user);
            sqlSession.commit();
        }
        sqlSession.close();

        return u == null;

    }

在java目录下的 com.hailei.service 包下创建 UserService 接口,在该接口中定义注册的抽象方法

    /**
     * 注册方法
     * @return
     */

    boolean register(User user);
}

servlet方法实现:

在java目录下的 com.hailei.web.servlet 包下定义名为 LoginServlet 的登录的 servlet

@WebServlet("/registerServlet")
public class RegisterServlet extends HttpServlet {
    private UserService service = new UserServiceImpl();

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       //1. 获取用户名和密码数据
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        User user = new User();
        user.setUsername(username);
        user.setPassword(password);

        // 获取用户输入的验证码
        String checkCode = request.getParameter("checkCode");

        // 程序生成的验证码,从Session获取
        HttpSession session = request.getSession();
        String checkCodeGen = (String) session.getAttribute("checkCodeGen");

        // 比对
        if(!checkCodeGen.equalsIgnoreCase(checkCode)){

            request.setAttribute("register_msg","验证码错误");
            request.getRequestDispatcher("/register.jsp").forward(request,response);

            // 不允许注册
            return;
        }



        //2. 调用service 注册
        boolean flag = service.register(user);
        //3. 判断注册成功与否
        if(flag){
            //注册功能,跳转登陆页面

            request.setAttribute("register_msg","注册成功,请登录");
            request.getRequestDispatcher("/login.jsp").forward(request,response);
        }else {
            //注册失败,跳转到注册页面

            request.setAttribute("register_msg","用户名已存在");
            request.getRequestDispatcher("/register.jsp").forward(request,response);
        }


    }

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

在java目录下的 com.hailei.web.servlet 包下定义名为 CheckCodeServlet 的验证码生成的 servlet

@WebServlet("/checkCodeServlet")
public class CheckCodeServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 生成验证码
        ServletOutputStream os = response.getOutputStream();
        String checkCode = CheckCodeUtil.outputVerifyImage(100, 50, os, 4);


        // 存入Session
        HttpSession session = request.getSession();
        session.setAttribute("checkCodeGen",checkCode);


    }

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

5.2 前端实现

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!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.jsp">登录</a>
    </div>
    <form id="reg-form" action="/brand-case/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" >${register_msg}</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>


            <tr>
                <td>验证码</td>
                <td class="inputs">
                    <input name="checkCode" type="text" id="checkCode">
                    <img id="checkCodeImg" src="/brand-case/checkCodeServlet">
                    <a href="#" id="changeImg" >看不清?</a>
                </td>
            </tr>

        </table>

        <div class="buttons">
            <input value="注 册" type="submit" id="reg_btn">
        </div>
        <br class="clear">
    </form>

</div>

<script>
    document.getElementById("changeImg").onclick = function () {
        document.getElementById("checkCodeImg").src = "/brand-case/checkCodeServlet?"+new Date().getMilliseconds();
    }

</script>
</body>
</html>

功能展示:

在这里插入图片描述

6、查询所有功能

整体流程:

  • (1) 前端brand.html页面加载完成后,通过表单发送异步请求给Web层的BrandServlet
  • (2) BrandServlet接收到请求后,调用Service层完成查询所有功能
  • (3) 在Service层需要编写BrandServiceImpl类,在类中实现List < Brand > selectAll()方法,方法中调用Dao层的BrandMapper。编写BrandService接口,声明查询所有的List < Brand > selectAll()方法
  • (4) 在BrandMapper接口中,声明一个查询所有的方法
  • (5) Dao层把数据查询出来以后,将返回数据封装到Brand对象,将对象交给Service层
  • (6) Service层将数据返回给Web层
  • (7) Web层获取到Brand对象后,将数据转为JSON,响应JSON数据
  • (8) 前端brand.html获取列表数据,展示获取的数据

6.1 后端实现

dao方法实现:

在java目录下的 com.hailei.mapper.BrandMapper 接口中定义抽象方法,并使用 @Select 注解编写 sql 语句

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

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

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hailei.mapper.BrandMapper">

    <resultMap id="brandResultMap" type="brand">
        <result property="brandName" column="brand_name" />
        <result property="companyName" column="company_name" />
    </resultMap>
</mapper>  

service方法实现:

在java目录下的 com.hailei.service 下再创建 impl 包;impl 表示是放 service 层接口的实现类的包。 在该包下创建名为 BrandServiceImpl

public class BrandServiceImpl implements BrandService {
    //1. 创建SqlSessionFactory 工厂对象
    SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory();
    
    @Override
    public List<Brand> selectAll() {
        //2. 获取SqlSession对象
        SqlSession sqlSession = factory.openSession();
        //3. 获取BrandMapper
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);

        //4. 调用方法
        List<Brand> brands = mapper.selectAll();

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

        return brands;
    }
}

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

public interface BrandService {

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

servlet方法实现:

在java目录下的 com.hailei.web.servlet 包下定义一个通用的 servlet 类,在定义其他的 servlet 是不需要继承 HttpServlet,而继承定义的 BaseServlet,在 BaseServlet 中调用具体 servlet(如BrandServlet)中的对应方法。从而方便管理和编写web层的 servlet

/**
 * 替换HttpServlet,根据请求的最后一段路径来进行方法分发
 */

public class BaseServlet extends HttpServlet {

    //根据请求的最后一段路径来进行方法分发
    @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); //  /selectAll?

        //2. 执行方法
        //2.1 获取BrandServlet /UserServlet 字节码对象 Class

        Class<? extends BaseServlet> cls = this.getClass();
        //2.2 获取方法 Method对象
        try {
            Method method = cls.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
            //2.3 执行方法
            method.invoke(this,req,resp);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }


    }
}

在java目录下的 com.hailei.web.servlet 包下定义名为 BrandServlet 的查询所有的 servlet。该 servlet 逻辑如下:

  • 调用service的 selectAll() 方法查询所有的品牌数据,并接口返回结果
  • 将返回的结果转换为 json 数据
  • 响应 json 数据
@WebServlet("/brand/*")
public class BrandServlet extends BaseServlet{
    private BrandService brandService = new BrandServiceImpl();

    public void selectAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 调用service查询
        List<Brand> brands = brandService.selectAll();

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

6.2 前端实现

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

<!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">
    <!--搜索表单-->
    <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 @click="deleteByIds">批量删除</el-button>
        <el-button type="primary" plain @click="dialogVisible = true">新增</el-button>

    </el-row>
    <!--添加数据对话框表单-->
    <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>

            <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>
        <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">
            </el-table-column>

            <el-table-column
                    prop="brandName"
                    label="品牌名称"
                    align="center"
            >
            </el-table-column>
            <el-table-column
                    prop="companyName"
                    label="企业名称"
                    align="center"
            >
            </el-table-column>
            <el-table-column
                    prop="ordered"
                    align="center"
                    label="排序">
            </el-table-column>
            <el-table-column
                    prop="statusStr"
                    align="center"
                    label="当前状态">
            </el-table-column>

            <el-table-column
                    align="center"
                    label="操作">
                <template slot-scope="scope">
                        <el-button type="primary" plain @click="updateById(scope.$index, scope.row)">修改</el-button>
                        <el-button type="danger" plain @click="deleteById(scope.$index, scope.row)">删除</el-button>
                    <!--修改数据的对话框表单-->
                    <el-dialog
                            title="修改品牌信息"
                            :visible.sync="centerVisible"
                            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>
                            <el-form-item label="状态">
                                <el-switch v-model=" brand.status"
                                           active-text="启用"
                                           inactive-text="禁用"
                                           active-value="1"
                                           inactive-value="0">
                                </el-switch>
                            </el-form-item>

                            <el-form-item>
                                <el-button type="primary" @click="edit">提交</el-button>
                                <el-button @click="centerVisible = false">取消</el-button>
                            </el-form-item>
                        </el-form>
                    </el-dialog>

                </template>

            </el-table-column>

        </el-table>
    </template>

    <!--分页工具条-->
    <el-pagination
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
            :current-page="currentPage"
            :page-sizes="[5, 10, 15, 20]"
            :page-size="5"
            layout="total, sizes, prev, pager, next, jumper"
            :total="totalCount">
    </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 src="js/axios-0.18.0.js"></script>

<script>
    new Vue({
        el: "#app",

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

            this.selectAll();

        },

        methods: {

            // 查询分页数据
            selectAll(){

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


            }
         }
     })
    </script>

</body>
</html>        

功能展示:

在这里插入图片描述

7、新增品牌功能

整体流程:

  • (1) 前端brand.html页面,新增品牌窗口点击提交按钮,发送ajax请求,通过表单发送请求和数据给Web层的BrandServlet
  • (2) BrandServlet接收到请求后,调用Service层完成新增品牌功能
  • (3) 在Service层BrandServiceImpl类中实现void add(brand)方法,方法中调用Dao层的BrandMapper。编写BrandService接口,声明新增品牌的add(brand)方法
  • (4) 在BrandMapper接口中,声明一个新增品牌的方法
  • (5) Dao层把新增数据添加以后,将返回数据封装到Brand对象,将对象交给Service层
  • (6) Service层将数据返回给Web层
  • (7) Web层获取到Brand对象后,将数据转为JSON,响应JSON数据
  • (8) 前端brand.html获取数据,判断是否添加成功,关闭窗口,重新加载数据

7.1 后端实现

dao方法实现:

在java目录下的 com.hailei.mapper.BrandMapper 接口中定义抽象方法,并使用 @Select 注解编写 sql 语句

    /**
     * 添加数据
     * @param brand
     */
    @Insert("insert into tb_brand values(null,#{brandName},#{companyName},#{ordered},#{description},#{status})")
    void add(Brand brand);

service方法实现:

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

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

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

@Override
    public void add(Brand brand) {
        //2. 获取SqlSession对象
        SqlSession sqlSession = factory.openSession();
        //3. 获取BrandMapper
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);

        //4. 调用方法
        mapper.add(brand);
        sqlSession.commit();//提交事务

        //5. 释放资源
        sqlSession.close();
    }

servlet方法实现:

在java目录下的 com.hailei.web.servlet 包下的名为 BrandServlet 中新增品牌的 servlet。该 servlet 逻辑如下:

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

servlet 代码实现如下:

/**
     * 新增
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    public void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //1. 接收品牌数据
        BufferedReader br = request.getReader();
        String params = br.readLine();//json字符串

        //转为Brand对象
        Brand brand = JSON.parseObject(params, Brand.class);

        //2. 调用service添加
        brandService.add(brand);

        //3. 响应成功的标识
        response.getWriter().write("success");
    }

7.2 前端实现

添加数据功能的逻辑代码写在 addBrand() 函数中。在此方法中需要发送异步请求并将表单中输入的数据作为参数进行传递。在 then 函数中的匿名函数是成功后的回调函数,而 resp.data 就可以获取到响应回来的数据,如果值是 success 表示数据添加成功。成功后关闭新增对话框窗口,重新查询数据,并弹出消息提示添加成功

<el-row>

        <el-button type="danger" plain @click="deleteByIds">批量删除</el-button>
        <el-button type="primary" plain @click="dialogVisible = true">新增</el-button>

    </el-row>
    <!--添加数据对话框表单-->
    <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>

            <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>
// 添加数据
            addBrand() {
                var _this = this;

                // 发送ajax请求,添加数据
                axios({
                    method:"post",
                    url:"http://localhost:8080/brand-case/brand/add",
                    data:_this.brand
                }).then(function (resp) {
                    if(resp.data == "success"){
                        //添加成功

                        //关闭窗口
                        _this.dialogVisible = false;

                        // 重新查询数据
                        _this.selectAll();
                        // 弹出消息提示
                        _this.$message({
                            message: '恭喜你,添加成功',
                            type: 'success'
                        });

                    }
                })


            },

功能展示:

在这里插入图片描述

8、修改品牌功能

整体流程:

  • (1) 前端brand.html页面,修改品牌窗口点击提交按钮,发送ajax请求,通过表单发送请求和数据给Web层的BrandServlet
  • (2) BrandServlet接收到请求后,调用Service层完成修改品牌功能
  • (3) 在Service层BrandServiceImpl类中实现void updateById(brand)方法,方法中调用Dao层的BrandMapper。编写BrandService接口,声明修改品牌的updateById(brand)方法
  • (4) 在BrandMapper接口中,声明一个修改品牌的方法
  • (5) Dao层把数据修改以后,将返回数据封装到Brand对象,将对象交给Service层
  • (6) Service层将数据返回给Web层
  • (7) Web层获取到Brand对象后,将数据转为JSON,响应JSON数据
  • (8) 前端brand.html获取数据,判断是否修改成功,关闭修改品牌窗口,重新加载数据

8.1 后端实现

dao方法实现:

在java目录下的 com.hailei.mapper.BrandMapper 接口中定义抽象方法,并使用 @Select 注解编写 sql 语句

    /**
     * 修改
     * @param brand
     */
    @Update("update tb_brand set brand_name = #{brandName},company_name = #{companyName},ordered = #{ordered},description = #{description},status = #{status} where id = #{id}")
    void updateById(Brand brand);

service方法实现:

BrandService 接口中定义 updateById() 修改数据的业务逻辑方法

/**
     * 修改
     * @param brand
     */
    void updateById(Brand brand); 

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

@Override
    public void updateById(Brand brand) {
        //2. 获取SqlSession对象
        SqlSession sqlSession = factory.openSession();
        //3. 获取BrandMapper
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);

        //4. 调用方法
        mapper.updateById(brand);

        sqlSession.commit();//提交事务

        //5. 释放资源
        sqlSession.close();
    }

servlet方法实现:

在java目录下的 com.hailei.web.servlet 包下的名为 BrandServlet 中修改品牌的 servlet。该 servlet 逻辑如下:

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

servlet 代码实现如下:

   /**
     * 修改
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    public void updateById(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //1. 接收数据
        BufferedReader br = request.getReader();
        String params = br.readLine();//json字符串

        //转为 int
        Brand brand = JSON.parseObject(params, Brand.class);


        //2. 调用service添加
        brandService.updateById(brand);

        //3. 响应成功的标识
        response.getWriter().write("success");
    }

8.2 前端实现

修改品牌功能updateById(index, row)获取id数据,逻辑代码写在edit()函数中,在此方法中需要发送异步请求并将表单中输入的数据作为参数进行传递。在 then 函数中的匿名函数是成功后的回调函数,而 resp.data 就可以获取到响应回来的数据,如果值是 success 表示数据添加成功。成功后关闭修改对话框窗口,重新查询数据,并弹出消息提示修改数据成功

<el-table-column
                    align="center"
                    label="操作">
                <template slot-scope="scope">
                        <el-button type="primary" plain @click="updateById(scope.$index, scope.row)">修改</el-button>
                        <el-button type="danger" plain @click="deleteById(scope.$index, scope.row)">删除</el-button>
                    <!--修改数据的对话框表单-->
                    <el-dialog
                            title="修改品牌信息"
                            :visible.sync="centerVisible"
                            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>
                            <el-form-item label="状态">
                                <el-switch v-model=" brand.status"
                                           active-text="启用"
                                           inactive-text="禁用"
                                           active-value="1"
                                           inactive-value="0">
                                </el-switch>
                            </el-form-item>

                            <el-form-item>
                                <el-button type="primary" @click="edit">提交</el-button>
                                <el-button @click="centerVisible = false">取消</el-button>
                            </el-form-item>
                        </el-form>
                    </el-dialog>

                </template>

            </el-table-column>
 
 updateById(index, row) {
                this.brand.id = row.id;
                this.centerVisible = true;
            },
            //修改数据的部分内容
            edit() {
                var _this = this;
                //发送ajax异步请求,添加数据
                axios({
                    method: "post",
                    url: "http://localhost:8080/brand-case/brand/updateById",
                    data: _this.brand
                }).then(function (resp) {
                    if (resp.data == "success") {
                        //关闭窗口
                        _this.centerVisible = false;
                        //查询一次
                        _this.selectAll();
                        _this.$message({
                            message: '恭喜你,修改数据成功',
                            type: 'success'
                        });
                    } else {
                        _this.$message.error('修改数据失败');
                    }
                })
            },

功能展示:

在这里插入图片描述

9、删除品牌功能

整体流程:

  • (1) 前端brand.html页面,点击删除按钮,发送ajax请求,通过表单发送请求和数据给Web层的BrandServlet
  • (2) BrandServlet接收到请求后,调用Service层完成删除品牌功能
  • (3) 在Service层BrandServiceImpl类中实现void deleteById(id)方法,方法中调用Dao层的BrandMapper。编写BrandService接口,声明删除品牌的deleteById(brand)方法
  • (4) 在BrandMapper接口中,声明一个删除品牌的方法
  • (5) Dao层把数据删除以后,将返回数据封装到Brand对象,将对象交给Service层
  • (6) Service层将数据返回给Web层
  • (7) Web层获取到Brand对象后,将数据转为JSON,响应JSON数据
  • (8) 前端brand.html获取数据,判断是否删除成功,重新加载数据

9.1 后端实现

dao方法实现:

在java目录下的 com.hailei.mapper.BrandMapper 接口中定义抽象方法,并使用 @Select 注解编写 sql 语句

    /**
     * 删除
     * @param id
     */
    @Delete("delete from tb_brand where id=#{id}")
    void deleteById(int id);

service方法实现:

BrandService 接口中定义 deleteById() 删除品牌的业务逻辑方法

    /**
     * 删除
     * @param id
     */
    void deleteById(int id);

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

    @Override
    public void deleteById(int id) {
        //2. 获取SqlSession对象
        SqlSession sqlSession = factory.openSession();
        //3. 获取BrandMapper
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);

        //4. 调用方法
        mapper.deleteById(id);

        sqlSession.commit();//提交事务

        //5. 释放资源
        sqlSession.close();
    }

servlet方法实现:

在java目录下的 com.hailei.web.servlet 包下的名为 BrandServlet 中删除品牌的 servlet。该 servlet 逻辑如下:

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

servlet 代码实现如下:

    /**
     * 删除
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    public void deleteById(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //1. 接收数据
        BufferedReader br = request.getReader();
        String params = br.readLine();//json字符串

        //转为 int
        int id = JSON.parseObject(params,int.class);


        //2. 调用service添加
        brandService.deleteById(id);

        //3. 响应成功的标识
        response.getWriter().write("success");
    }

9.2 前端实现

删除品牌功能deleteById(index, row)获取id数据,在此方法中需要发送异步请求并将id数据作为参数进行传递。在 then 函数中的匿名函数是成功后的回调函数,而 resp.data 就可以获取到响应回来的数据,如果值是 success 表示数据删除成功。删除成功后,重新查询数据,并弹出消息提示删除数据成功

// 删除
            deleteById(index, row){

                // 弹出确认提示框

                this.$confirm('此操作将删除该数据, 是否继续?', '提示', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'warning'
                }).then(() => {
                    //用户点击确认按钮

                    //2. 发送AJAX请求
                    var _this = this;

                    // 发送ajax请求,添加数据
                    axios({
                        method:"post",
                        url:"http://localhost:8080/brand-case/brand/deleteById",
                        data:row.id
                    }).then(function (resp) {
                        if(resp.data == "success"){
                            //删除成功

                            // 重新查询数据
                            _this.selectAll();
                            // 弹出消息提示
                            _this.$message({
                                message: '恭喜你,删除成功',
                                type: 'success'
                            });

                        }
                    })
                }).catch(() => {
                    //用户点击取消按钮

                    this.$message({
                        type: 'info',
                        message: '已取消删除'
                    });
                });




            },

功能展示:

在这里插入图片描述

10、批量删除功能

整体流程:

  • (1) 前端brand.html页面,点击批量删除按钮,发送ajax请求,携带被选中的id数组给Web层的BrandServlet
  • (2) BrandServlet接收到请求后,调用Service层完成批量删除功能
  • (3) 在Service层BrandServiceImpl类中实现void deleteByIds(int[] ids)方法,方法中调用Dao层的BrandMapper。编写BrandService接口,声明批量删除的deleteByIds(ids)方法
  • (4) 在BrandMapper接口中,声明一个批量删除的方法
  • (5) Dao层把数据删除以后,将返回数据封装到Brand对象,将对象交给Service层
  • (6) Service层将数据返回给Web层
  • (7) Web层获取到Brand对象后,将数据转为JSON,响应JSON数据
  • (8) 前端brand.html获取数据,判断是否删除成功,重新加载数据

10.1 后端实现

dao方法实现:

在java目录下的 com.hailei.mapper.BrandMapper 接口中定义抽象方法,要用到动态 sql ,属于复杂的sql操作,使用映射配置文件

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

在resources目录下的 com.hailei.mapper.Mapper 中的 BrandMapper.xml 映射配置文件中添加 statement

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


    </delete>

service方法实现:

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

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

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

    @Override
    public void deleteByIds(int[] ids) {
        //2. 获取SqlSession对象
        SqlSession sqlSession = factory.openSession();
        //3. 获取BrandMapper
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);

        //4. 调用方法
        mapper.deleteByIds(ids);

        sqlSession.commit();//提交事务

        //5. 释放资源
        sqlSession.close();
    }

servlet方法实现:

在java目录下的 com.hailei.web.servlet 包下的名为 BrandServlet 中批量删除的 servlet。该 servlet 逻辑如下:

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

servlet 代码实现如下:

    /**
     * 批量删除
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    public void deleteByIds(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //1. 接收数据  [1,2,3]
        BufferedReader br = request.getReader();
        String params = br.readLine();//json字符串

        //转为 int[]
        int[] ids = JSON.parseObject(params, int[].class);

        //2. 调用service添加
        brandService.deleteByIds(ids);

        //3. 响应成功的标识
        response.getWriter().write("success");
    }

10.2 前端实现

批量删除功能deleteByIds(),此方法中需要发送异步请求并将id数组数据作为参数进行传递。在 then 函数中的匿名函数是成功后的回调函数,而 resp.data 就可以获取到响应回来的数据,如果值是 success 表示数据删除成功。删除成功后,重新查询数据,并弹出消息提示删除数据成功

            // 批量删除
            deleteByIds(){

                // 弹出确认提示框

                this.$confirm('此操作将删除该数据, 是否继续?', '提示', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'warning'
                }).then(() => {
                    //用户点击确认按钮

                    //1. 创建id数组 [1,2,3], 从 this.multipleSelection 获取即可
                    for (let i = 0; i < this.multipleSelection.length; i++) {
                        let selectionElement = this.multipleSelection[i];
                        this.selectedIds[i] = selectionElement.id;

                    }

                    //2. 发送AJAX请求
                    var _this = this;

                    // 发送ajax请求,添加数据
                    axios({
                        method:"post",
                        url:"http://localhost:8080/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: '已取消删除'
                    });
                });




            }

        },

功能展示:

在这里插入图片描述

11、分页查询功能

整体流程:

  • (1) 前端brand.html页面加载完成后,发送ajax异步请求,将当前页码和每页显示条数参数给Web层的BrandServlet
  • (2) BrandServlet接收到参数后,调用Service层完成分页查询功能
  • (3) 在Service层BrandServiceImpl类中实现PageBean < Brand > selectByPage(int currentPage, int pageSize)方法,方法中调用Dao层的BrandMapper。编写BrandService接口,声明分页查询的selectByPage(int currentPage, int pageSize)方法
  • (4) 在BrandMapper接口中,声明一个分页查询的方法
  • (5) Dao层把数据查询以后,将返回数据封装到PageBean对象,将对象交给Service层
  • (6) Service层将数据返回给Web层
  • (7) Web层获取到PageBean对象后,将数据转为JSON,响应JSON数据
  • (8) 前端brand.html获取数据,重新加载数据,将数据设置到模型上

11.1 后端实现

在pojo包下创建 PageBean 类,为了做到通过会将其定义成泛型类,代码如下:

package com.hailei.pojo;

import java.util.List;

//分页查询的JavaBean
public class PageBean<T> {
    // 总记录数
    private int totalCount;
    // 当前页数据
    private List<T> rows;


    public int getTotalCount() {
        return totalCount;
    }

    public void setTotalCount(int totalCount) {
        this.totalCount = totalCount;
    }

    public List<T> getRows() {
        return rows;
    }

    public void setRows(List<T> rows) {
        this.rows = rows;
    }
}

dao方法实现:

BrandMapper 接口中定义 selectByPage() 方法进行分页查询,代码如下:

    /**
     * 分页查询
     * @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);

BrandMapper 接口中定义 selectTotalCount() 方法进行统计记录数,代码如下:

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

service方法实现:

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

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

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

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


        //4. 计算开始索引
        int begin = (currentPage - 1) * pageSize;
        // 计算查询条目数
        int size = pageSize;

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

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

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


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

        return pageBean;
    }

servlet方法实现:

BrandServlet 类中定义 selectByPage() 方法,该方法的逻辑如下:

  • 获取页面提交的 当前页码每页显示条目数 两个数据。这两个参数是在url后进行拼接的,格式是 url?currentPage=1&pageSize=5。获取这样的参数需要使用 requet.getparameter() 方法
  • 调用 service 的 selectByPage() 方法进行分页查询的业务逻辑处理
  • 将查询到的数据转换为 json 格式的数据
  • 响应 json 数据

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

/**
     * 分页查询
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */

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

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

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

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

11.2 前端实现

// 查询分页数据
            selectAll(){

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


            },
            tableRowClassName({row, rowIndex}) {
                if (rowIndex === 1) {
                    return 'warning-row';
                } else if (rowIndex === 3) {
                    return 'success-row';
                }
                return '';
            },
            // 复选框选中后执行的方法
            handleSelectionChange(val) {
                this.multipleSelection = val;

            },
            // 查询方法
            onSubmit() {
                this.selectAll();

            },

功能展示:

在这里插入图片描述

12 条件查询功能

整体流程:

  • (1) 前端brand.html页面绑定查询条件对象模型,点击查询按钮,发送ajax异步请求,将当前查询条件参数给Web层的BrandServlet
  • (2) BrandServlet接收到参数后,调用Service层完成条件查询功能
  • (3) 在Service层BrandServiceImpl类中实现PageBean selectByPageAndCondition(int currentPage, int pageSize, Brand brand)方法,方法中调用Dao层的BrandMapper。编写BrandService接口,声明分页查询的PageBean selectByPageAndCondition(int currentPage, int pageSize, Brand brand)方法
  • (4) 在BrandMapper接口中,声明一个条件查询的方法
  • (5) Dao层把数据查询以后,将返回数据封装到PageBean对象,将对象交给Service层
  • (6) Service层将数据返回给Web层
  • (7) Web层获取到PageBean对象后,将数据转为JSON,响应JSON数据
  • (8) 前端brand.html获取数据,重新加载数据,将数据设置到模型上

12.1 后端实现

dao方法实现:

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

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

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

参数:

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

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

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

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

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

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

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

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

service方法实现:

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

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

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

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


        //4. 计算开始索引
        int begin = (currentPage - 1) * pageSize;
        // 计算查询条目数
        int size = pageSize;

        // 处理brand条件,模糊表达式
        String brandName = brand.getBrandName();
        if (brandName != null && brandName.length() > 0) {
            brand.setBrandName("%" + brandName + "%");
        }

        String companyName = brand.getCompanyName();
        if (companyName != null && companyName.length() > 0) {
            brand.setCompanyName("%" + companyName + "%");
        }


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

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

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


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

        return pageBean;
    }

servlet方法实现:

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

  • 获取页面提交的 当前页码每页显示条目数 两个数据。这两个参数是在url后进行拼接的,格式是 url?currentPage=1&pageSize=5。获取这样的参数需要使用 requet.getparameter()
  • 获取页面提交的 条件数据 ,并将数据封装到一个Brand对象中。由于这部分数据需要以 json 格式进行提交,所以需要通过流获取数据
  • 调用 service 的 selectByPageAndCondition() 方法进行分页查询的业务逻辑处理
  • 将查询到的数据转换为 json 格式的数据
  • 响应 json 数据

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

    /**
     * 分页条件查询
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */

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

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

        // 获取查询条件对象
        BufferedReader br = request.getReader();
        String params = br.readLine();//json字符串

        //转为 Brand
        Brand brand = JSON.parseObject(params, Brand.class);


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

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

12.2 前端实现

 <!--搜索表单-->
    <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>

功能展示:

在这里插入图片描述
希望本文对大家有帮助,上文若有不妥之处,欢迎指正

分享决定高度,学习拉开差距

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

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

相关文章

基于JavaSpringBoot+Vue+uniapp微信小程序实现在线房屋装修管理系统

博主介绍&#xff1a;✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

分布式Id生成方式

为什么要用分布式ID&#xff1f; 在说分布式ID的具体实现之前&#xff0c;我们来简单分析一下为什么用分布式ID&#xff1f;分布式ID应该满足哪些特征&#xff1f; 1、什么是分布式ID&#xff1f; 拿MySQL数据库举个栗子&#xff1a; 在我们业务数据量不大的时候&#xff0c…

Zotero 超好用插件的下载链接及配置方法(PDF-translate/ZotFile/茉莉花/Zotero Scihub)

目录前言插件安装方法插件一&#xff1a;文献翻译插件&#xff08;pdf-translate&#xff09;插件二&#xff1a;文献附件管理&#xff08;ZotFile&#xff09;插件三&#xff1a;中文文献插件&#xff08;茉莉花&#xff09;插件四&#xff1a;Sci-Hub 自动下载文献&#xff0…

vue3项目实战中的接口调用方法(一)async/await用法 对axios二次封装 实现异步请求

vue3 async和await联合调用接口 &#x1f525;一文搞定&#x1f525;点击进入vue专栏&#x1f525;async/await定义async/await用法&#x1f525;async/await的基本用法async/await的使用场景async/await实战&#x1f525;&#x1f525;处理一个异步请求处理多个异步请求summar…

从函数计算到 Serverless 架构

作者&#xff1a;秋雨陈 前言 随着 Serverless 架构不断发展&#xff0c;各云厂商和开源社区都已经布局 Serverless 领域&#xff0c;一方面表现在云厂商推出传统服务/业务的 Serverless 化版本&#xff0c;或者 Serverless 计算平台&#xff1b;另一方面表现在开源社区中 Se…

远程构建(命令、脚本构建)jenkins

在对应项目&#xff0c;开启远程构建开关添加API token系统设置调整用户权限获取crumbcurl调用构建 1、进入对应项目的设置页面&#xff1a;开启远程构建开关 2、 添加 API token&#xff1a;进入对应用户的设置页面 3、系统设置调整权限&#xff0c;如图 4、由于jenkins的安全…

使用element-ui中的el-upload自定义上传

题引&#xff1a; 日常开发系统的时候&#xff0c;我们都会有上传文件的功能。但是用原生的文件上传是很繁琐的&#xff0c;那么我们都会选择使用UI组件库&#xff0c;如element-plus、ant-design等。这些UI组件库是非常容易上手且实用的&#xff0c;但是万恶的需求是奇怪多变…

vue项目引入百度地图BMapGL和BMap实例,以及辅助工具BMapGLLib 的引入,BMapGL鼠标绘制功能

记录一下vue项目使用百度地图所用的api和踩过的坑&#xff0c;减少以后引用少走弯路。旨在记录&#xff0c;第一次开贴&#xff0c;不足之处请多多指教。废话不多说&#xff0c;开撸&#xff01; 1、引用百度地图 这里账号密钥不多说&#xff0c;上链接&#xff0c;自己注册。…

【kubernetes】k8s集群搭建(完整详解)

目录 一、准备工作 二、配置 1、修改主机名 2、修改hosts文件 3、关闭防火墙和SELinux 4、关闭swap 5、修改网卡配置 6、系统模块配置 7、免密登录 8、安装k8s和docker 9、查看k8s集群需要的镜像版本 10、初始化Master节点 11、node配置 12、拉取Nginx镜像进行配置…

【uniapp小程序】视图容器cover-view

&#x1f352;观众老爷们好呀&#xff0c;这里是前端小刘不怕牛牛频道&#xff0c;小程序系列又更新新文章啦&#xff0c;今天的内容是uniapp小程序的视图容器&#xff0c;cover-view &#x1f352;准备好了吗&#xff1f;那我们就发车啦&#xff0c;赶紧拿起小本本把笔记做起来…

10Wqps 超高并发 API网关 架构演进之路

说在前面 在尼恩的&#xff08;50&#xff09;读者社群中&#xff0c;经常遇到一个 API网关 架构方面的问题&#xff1a; (1) 尼恩老师&#xff0c;最近公司我们在规划业务出口网关(目的&#xff0c;整合规范外部调用&#xff0c;如短信平台 mqtt 等) 我在做整理技术方案&…

智能车竞赛:Infineon TC264单片机使用总结快速入门

本文主要是为了备赛第十八届全国大学生智能车竞赛&#xff0c;基于逐飞开源库和芯片数据手册的一些学习总结&#xff0c;使用英飞凌官方的AURIX Development Studio开发环境。 正如STM32的开发方式有标准库和HAL库&#xff0c;Infineon单片机也有官方库&#xff0c;而逐飞开源…

阿里P8大牛用实例跟你讲明白“Java 微服务架构实战”

全文一共十五章&#xff0c;核心内容为SpringBoot、SpringCloud、Docker、RabbitMQ消息组件。其中&#xff0c;SpringBoot是SpringMVC 技术的延伸&#xff0c;使用它进行程序开发会更简单&#xff0c;服务整合也会更容易。SpringCloud 是当前微架构的核心技术方案&#xff0c;属…

Spring Cloud Alibaba 微服务1,系统架构演变 + Nginx反向代理与负载均衡

目录专栏导读一、系统架构演变二、什么是Nginx&#xff1f;三、servername匹配规则四、正向代理与反向代理1、正向代理2、反向代理3、LVS五、负载均衡策略1、轮询2、权重3、ip_hash4、least_conn5、url_hash6、fair7、小结六、动静分离七、URLRewrite专栏导读 &#x1f3c6;作者…

【Linux系统】进程概念

目录 1 冯诺依曼体系结构 2 操作系统(Operator System) 概念 设计OS的目的 定位 总结 系统调用和库函数概念 3 进程 3.1 基本概念 3.2 描述进程-PCB 3.2 组织进程 3.3 查看进程 3.4 通过系统调用获取进程标示符 3.5 进程状态 在了解进程概念前我们还得了解下冯诺…

MongoDB详解,用心看这篇就够了【重点】

1.1 MongoDB概述 MongoDB是一个基于分布式文件存储的数据库。由C语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。 MongoDB是一个介于关系数据库和非关系数据库之间的产品&#xff0c;是非关系数据库当中功能最丰富&#xff0c;最像关系数据库的。 它支持的数据…

业内人士真心话,软件测试是没有前途的,我慌了......

我在测试行业爬模滚打7年&#xff0c;从点点点的功能测试到现在成为高级测试&#xff0c;工资也翻了几倍。个人觉得&#xff0c;测试的前景并不差&#xff0c;只要自己肯努力。 我刚出来的时候是在鹅厂做外包的功能测试&#xff0c;天天点点点&#xff0c;很悠闲&#xff0c;点…

JS中的构造函数

构造函数 1.构造函数 创建一个构造函数&#xff0c;专门用来创建一个指定的对象的构造函数就是普通的函数&#xff0c;创建方式和普通函数没有区别&#xff0c;不同的是构造函数习惯上首字母大写构造函数和普通函数的区别就是调用方式不同 普通函数是直接调用的&#xff0c;而…

真题解析 | 2022数模美赛C题:股票投资策略

1、准备工作 1.1 题目背景 市场交易者频繁买卖波动性资产&#xff0c;目标是最大化其总回报。每次买卖通常都会有佣金。 两种这样的资产是黄金和比特币。 图 1&#xff1a;黄金每日价格&#xff0c;每金衡盎司美元。 资料来源&#xff1a;伦敦金银市场协会&#xff0c;2021 年…

javaScript实现动态规划(Dynamic Programming)01背包问题

&#x1f431; 个人主页&#xff1a;不叫猫先生 &#x1f64b;‍♂️ 作者简介&#xff1a;前端领域新星创作者、阿里云专家博主&#xff0c;专注于前端各领域技术&#xff0c;共同学习共同进步&#xff0c;一起加油呀&#xff01; &#x1f4ab;系列专栏&#xff1a;vue3从入门…