IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> JavaWeb项目实战——品牌后台管理系统 -> 正文阅读

[Java知识库]JavaWeb项目实战——品牌后台管理系统

项目概述

本次项目在传统javaweb项目基础上,使用了Maven来构建整个项目,前端使用Vue框架以及Element组件库,并且使用MyBatis作为持久层框架。通过以上技术,大大提高了开发效率。

通过实现以上功能,加深自己对JavaWeb的认识,同时加强自己对Vue,Maven,Axios,MyBatis,Servlet等相关技术的掌握。

功能介绍

本次的项目是一个品牌后台管理系统,其功能包括:

  • 显示所有品牌信息
  • 修改品牌信息
  • 删除品牌信息
  • 添加品牌信息
  • 批量删除品牌信息
  • 显示分页
  • 模糊查询

成果展示

项目实现

通过以下步骤,逐步完成本次项目所需实现的功能。

使用Maven构建项目

Maven介绍

Maven:Maven是专门用于管理和构建java项目的工具,主要功能如下:

  1. 标准化的项目结构
  2. 标准化的构建结构
  3. 依赖管理

使用Maven构建项目的最大的好处是导包非常方便。在配置好Maven后,使用Maven构建项目的操作流程如下:

具体操作

第一步,在新建项目后选择Maven,为项目确定好名称后点击Finish,完成项目的创建。

第二步,右击项目,选择Add Frameworks Support,为项目添加web框架。

第三步,由于web项目需要打包成war包,而maven默认打包方式为jar包,因此需要在pom.xml中设置打包方式为war包。在maven的pom.xml文件中加入如下代码

<packaging>war</packaging>

第四步,在java目录下创建名为com.itheima的包,在itheima目录下,创建mapper,pojo,service,utils,web包。

至此便完成了使用Maven对项目的构建,项目的目录结构如下:
项目目录

由于IDEA版本原因,项目结构可能存在不同,我的web相关目录(带蓝点的)的目录名可能是web后续运行时,蓝点突然会消失,后续需要在
Facets中修复。
修复webapp
修复后的项目目录如下:

使用Mybatis封装对数据库的操作

MyBatis:MyBatis是一款持久层框架,可以简化JDBC开发。
主要解决JDBC存在的以下问题:

  1. 硬编码
  2. 操作繁琐

使用MyBatis操作数据库的流程如下:

在Mysql中建表,并添加数据

在mysql数据库中创建相应的表,并添加一些数据。

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

SELECT * FROM tb_brand;

在pojo包下创建JavaBean

根据数据库中品牌表的结构创建描述表的类,需要注意的是类中的属性,不能用基本数据类型来修饰,必须用包装类。因为有些时候包装类的对象的属性可能为null,而基本数据类型不能为null,否则会报错。Brand.java的代码如下:

package com.itheima.pojo;

public class Brand {
    // id 主键
    private Integer id;
    // 品牌名称
    private String brandName;
    // 企业名称
    private String companyName;
    // 排序字段
    private Integer ordered;
    // 描述信息
    private String description;
    // 状态:0:禁用 1:启用
    private Integer status;

    @Override
    public String toString() {
        return "Brand{" +
                "id=" + id +
                ", brandName='" + brandName + '\'' +
                ", companyName='" + companyName + '\'' +
                ", ordered=" + ordered +
                ", description='" + description + '\'' +
                ", status=" + status +
                '}';
    }
    //逻辑视图 该方法在后续的前端展示中将用文字代替0 1 null
    public String getStatusStr(){
        if (status == null){
            return "未知";
        }
        return status == 0 ? "禁用":"启用";
    }
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getBrandName() {
        return brandName;
    }

    public void setBrandName(String brandName) {
        this.brandName = brandName;
    }

    public String getCompanyName() {
        return companyName;
    }

    public void setCompanyName(String companyName) {
        this.companyName = companyName;
    }

    public Integer getOrdered() {
        return ordered;
    }

    public void setOrdered(Integer ordered) {
        this.ordered = ordered;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }
}

在pom.xml中添加依赖

在pom.xml添加mybatis,jdbc,junit的依赖,具体操作的可以百度以"maven jdbc"这样的格式搜索,通常不会有问题。或者使用alt+enter 搜索相应包名导入。

<dependencies>
        <!--        mybatis依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.5</version>
        </dependency>
        <!--        mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.29</version>
        </dependency>
        <!--        junit单元测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <!--        servlet-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <!--        fastjson-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.66</version>
        </dependency>
    </dependencies>

配置mybatis.xml

在resources目录下配置mybatis的xml文件,取名为mybatis-config.xml,内容模板在mybatis中文网的入门部分,mybatis-config.xml的代码如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <package name="com.itheima.pojo"/>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///mybatis?useSSL=false&amp;allowPublicKeyRetrieval=true"/>
                <property name="username" value="账号"/>
                <property name="password" value="密码"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
<!--        <mapper resource="com/itheima/mapper/UserMapper.xml"/>-->
<!--        包扫描,通过以下代码,将该目录下的文件全都导入-->
        <package name="com.itheima.mapper"/>
    </mappers>
</configuration>

xml代码中有两点在官网给的模板上做出了优化。

第一点:添加了typeAliases标签,并使用了包扫描的方式。这样做的好处是使用类名的小写作为类的别名,减少类完全限定名的冗余。

第二点,使用包扫描的方式方式来配置标签mappers中的内容,好处是减少代码量。

在这一步,有以下地方需要注意。在配置数据库url时,由于mysql版本问题,为了成功连接数据库并能顺利执行sql语句,需要携带两个参数,关键代码如下:
<property name="url" value="jdbc:mysql:///mybatis?useSSL=false&amp;allowPublicKeyRetrieval=true"/>
此外在mybatis-config.xml中可以配置多个数据库连接,具体想使用哪个数据库就让environments 中的default等于environment的id。
<environments default="development"> <environment id="development">

配置BrandMapper.xml以及BrandMapper

在开始配置之前,在IDEA的settings的plugins中下载MybatisX,可以提高配置效率(目录出现Mybatis图标表明插件成功下载并使用)。

在mybatis中,BrandMapper.xml是用来写sql语句,mapper是用来申明方法的,并且要求xml文件和java文件必须在同一目录下才能发挥作用。由于使用了maven,所有的xml文件都会被放置在resources目录中,在经过编译后,resources目录下的内容会和java目录下的内容都会出现在同一个目录下。因此,可以在resources目录下创建子目录用来放BrandMapper.xml。其目录结构与BrandMapper的包的结构相同。如图:

在创建完以上两个文件后,接着在BrandMapper接口中申明所需的方法,方法和我们项目要实现的功能相对应。BrandMapper.java的代码如下:

package com.itheima.mapper;

import com.itheima.pojo.Brand;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface BrandMapper {
    //查询所有品牌信息
    List<Brand> selectAll();
    //根据id查询品牌信息
    Brand selectBrandById(int id);
    //根据条件查询品牌信息
    List<Brand> selectByCondition(@Param("status") int status, @Param("companyName") String companyName, @Param("brandName") String brandName);
    //根据条件查询品牌信息 参数为Brand
    List<Brand> selectByConditionSingle(Brand brand);
    //添加一条品牌信息
    void add(Brand brand);
    //更新一条品牌信息
    void update(Brand brand);
    //根据id删除一条品牌信息
    void deleteById(int id);
    //根据id批量删除品牌信息
    void deleteByIds(int[] ids);
    //查询品牌记录总数
    int selectTotalCount();
    //分页查询品牌信息
    List<Brand> selectByPage(@Param("begin") int begin,@Param("size") int size);
    //根据条件分页查询品牌信息
    List<Brand> selectByPageAndCondition(@Param("begin") int begin, @Param("size") int size, @Param("brand") Brand brand);
    //根据条件查询
    int totalCountByPageAndCondition(Brand brand);
}

通过以上方法,可以完成项目功能的持久层部分。当然,一开始就写这么多方法是比较复杂或者难以想到的,所以可以先申明最简单的增删改查操作。后续再慢慢根据项目所需实现的功能,慢慢补全代码。

由于在前面,我们安装了MyBatisX插件,所以在写完这些方法后,方法名会标红。这时,我们只需要alt+enter即可来到BrandMapper.xml页面来完成方法的具体实现。

首先我们来完成查询所有的具体实现。当我们通过alt+enter来到BrandMapper.xml页面时,MyBatisX已经为我们在页面上生成了部分代码:<select id="selectAll" resultType="com.itheima.pojo.Brand"></select>我们只需要在select标签内书写相应sql即可。

但实际上这里还存在问题。由于pojo类的属性遵循驼峰原则,而tb_brand的字段使用下划线分割。因此记录中像company_name,brand_name这样的字段的值是不能被获取到brand对象中的。

所以我们需要配置resultMap来代替resultType。具体操作如下:

首先,配置resultMap

    <resultMap id="brandResultMap" type="brand">

        <result column="brand_name" property="brandName"/>
        <result column="company_name" property="companyName"/>
    </resultMap>

然后将select标签中的resultTyle改成resultMap

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

通过该方法,可以解决取不到company_name,brand_name值的问题。

接着我们完成更新,删除,添加等操作。在像是根据条件查询的sql语句中,由于条件个数不固定,所以我们需要使用动态SQL,在这里先不做过多赘述,直接上BrandMapper.xml的关键代码。

 <!--根据条件分页查询品牌信息-->
    <select id="selectByPageAndCondition" resultMap="brandResultMap">
        select *
        from tb_brand
        <where>
            <if test="brand.status!=null">
                and status = #{brand.status}
            </if>
            <if test="brand.companyName!=null and brand.companyName!=''">
                and company_name like #{brand.companyName}
            </if>
            <if test="brand.brandName!=null and brand.brandName!='' ">
                and brand_name like #{brand.brandName}
            </if>
        </where>
        limit #{begin},#{size}
    </select>
    
<!--根据id批量删除品牌信息-->
    <delete id="deleteByIds">
        delete from tb_brand
        where id
        in
        <foreach collection="array" item="id" separator="," open="(" close=")">#{id}</foreach>
    </delete>

测试mapper方法

在项目的test目录下创建com.itheima.test包,在test包下创建项目MyBatisTest完成开始测试。MapperTest关键代码如下:

 @Test
    public void selectAllTest() throws IOException {
        //1,获取sqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2.获得sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();//事务开启

        //3.通过Mapper代理开发
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
        List<Brand> brands = mapper.selectAll();
        System.out.println(brands);

        //4.关闭资源
        sqlSession.close();
    }

测试完成后,发现所有方法都是可用的,至此我们完成了MyBatis部分配置。

服务器端配置及代码编写

在本次项目中,使用tomcat作为服务器。所有的资源都会被放在tomcat的webapp下。

为项目配置tomcat

在IDEA的edit configurations中配置tomcat local服务器。这一步比较简单,但还有两点需要注意:
第一点,是需要配置tomcat服务器的VM options为-Dfile.encoding=UTF-8。这样做的目的是为了解决在使用tomcat时的控制台乱码问题。
第二点,在Artifact中选择以war的方式配置,而不是以war exploded的方式。因为以war的方式,会将资源都放在tomcat的webapp下,更加符合实际开发。

编写service层代码

service层的作用,主要是调用dao层(mapper包下)的方法完成增删改查操作。通过之前编写完mapper的测试类我们可以知道,mapper中的方法不能直接调用,还需要先获取sqlsessionfactory,sqlseesion…等一系列操作,而service层将会完成这一些列繁琐操作的封装。后续web层,想要执行什么操作,只需要调用service层的对应的方法即可。

正如前面mapper测试类中的代码那样,想要调用mapper类的方法,我们要经过以下操作:

  1. 获取SqlSessionFactory对象
  2. 通过SqlSessionFactory对象,获取SqlSession对象。
  3. 通过SqlSession对象,获取Mapper对象
  4. 通过Mapper对象,执行需要的方法

每一个方法都是这样的步骤,其中会有很多重复的代码。因此我们在之前准备好utils包下,创建与此相关的工具类,SqlSessionFactoryUtils.java的代码如下:

package com.itheima.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class SqlSessionFactoryUtils {

    private static SqlSessionFactory sqlSessionFactory;

    static {
        //静态代码块会随着类的加载而自动执行,且只执行一次

        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public static SqlSessionFactory getSqlSessionFactory(){
        return sqlSessionFactory;
    }
}

通过以上代码,以后想要获取SqlSessionFactory对象,只需要调用SqlSessionFactoryUtils下的 getSqlSessionFactory()方法即可,提升开发效率。

创建完工具类之后,正式开始service类的编写。首先,我们需要创建一个名为BrandService的接口,并创建名为BrandServiceImp的类来实现接口。
接着在BrandService接口中申明方法,再通过BrandServiceImp依此实现。

为什么需要通过类来实现接口的方式来完成service层的代码编写,主要有两个原因:
一是这样只需要查看接口中申明的方法就能知道所有的方法。
二是为后来spring框架的引入做准备。

以下为BrandService.java的代码:

package com.itheima.service;

import com.itheima.pojo.Brand;

import java.util.List;

public interface BrandService {
    public List<Brand> selectAll();
    public void add(Brand brand);
    public void deleteByIds(int[] ids);
    public void update(Brand brand);
    public void deleteById(int id);
    public List<Brand> selectByPage(int begin,int size);
    public List<Brand> selectByPageAndCondition(int begin,int size,Brand brand);
    public int selectTotalCount();
    public int totalCountByPageAndCondition(Brand brand);
}

以下为BrandServiceImp.java的代码:

package com.itheima.service;

import com.itheima.mapper.BrandMapper;
import com.itheima.pojo.Brand;
import com.itheima.utils.SqlSessionFactoryUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import java.util.List;

public class BrandServiceImp implements BrandService{
    SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();

    @Override
    public List<Brand> selectAll(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
        List<Brand> brands = mapper.selectAll();
        sqlSession.close();
        return brands;
    }

    @Override
    public void add(Brand brand) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
        mapper.add(brand);
        sqlSession.commit();
        sqlSession.close();
    }

    @Override
    public void deleteByIds(int[] ids) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
        mapper.deleteByIds(ids);
        sqlSession.commit();
        sqlSession.close();
    }

    @Override
    public void update(Brand brand) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
        mapper.update(brand);
        sqlSession.commit();
        sqlSession.close();
    }

    @Override
    public void deleteById(int id) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
        mapper.deleteById(id);
        sqlSession.commit();
        sqlSession.close();
    }

    @Override
    public List<Brand> selectByPage(int begin, int size) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
        List<Brand> brands = mapper.selectByPage(begin, size);
        sqlSession.close();
        return brands;
    }

    @Override
    public List<Brand> selectByPageAndCondition(int begin, int size, Brand brand) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
        List<Brand> brands = mapper.selectByPageAndCondition(begin, size, brand);
        sqlSession.close();
        return brands;
    }

    @Override
    public int selectTotalCount() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
        int count = mapper.selectTotalCount();
        sqlSession.close();
        return count;
    }

    @Override
    public int totalCountByPageAndCondition(Brand brand) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
        int count = mapper.totalCountByPageAndCondition(brand);
        sqlSession.close();
        return count;
    }

}

通过以上代码,service层的代码就全部完成了,如果想要测试代码,可以在测试类中通过new BrandServiceImp对象,并调用其方法完成测试。

编写web层代码

web层主要用来存放web的一些组件,像是servlet、filter、listener等等。在本次项目中只需要使用到servlet。
在使用默认的servlet时,一个servlet对应一个功能,同时使用注释的方式对应一个url。
一个项目往往有很多功能,如果项目比较大型,意味着可能有几十上百个servlet,这样很不好。最好能用一个类对应一个servlet,这样可以减少servlet数量。
我们希望在网址栏中输入http://localhost:8080/类名/方法名的方式即可调用方法。
已知自己所写的servlet是继承HttpServlet的,HttpServlet的service()方法是根据请求方式来分发的。所以我们要重写HttpServlet的service()方法。让它能够实现我们想要的效果。所以我们编写BaseServlet.java的代码,其代码如下:

package com.itheima.web;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;


public class BaseServlet extends HttpServlet {
    //重写service方法 防止以get或者post方式进行路由
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
        //1.获取请求路径
        String uri = req.getRequestURI();
        //2.通过字符串截取的方式,确定请求的方法
        int index = uri.lastIndexOf('/');
        String methodName = uri.substring(index + 1);
        //3.通过反射的方式,将方法名所对应的方法运行
        //子类继承BaseServlet后,this.getClass()将会获取子类的Class对象
        Class<? extends BaseServlet> aClass = this.getClass();
        try {
            Method method = aClass.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();
        }

    }

}

通过继承BaseServlet,我们在网址栏中输入以方法名结尾的url即可调用当前Servlet的相对应的方法。接着我们再编写BrandServlet的代码,BrandServlet.java的代码如下:

package com.itheima.web;

import com.alibaba.fastjson.JSON;
import com.itheima.pojo.Brand;
import com.itheima.service.BrandService;
import com.itheima.service.BrandServiceImp;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.List;

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

    public void selectAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.调用service层查询所有的brand,返回一个List
        List<Brand> brands = brandService.selectAll();
        //2.将得到的list结果转化为JSON
        String brandsStr = JSON.toJSONString(brands);
        //3.为response设置返回的格式,并将值返回
        response.setContentType("text/json;charset=UTF-8");
        response.getWriter().write(brandsStr);
    }
    public void addBrand(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        //1. 接收品牌数据
        BufferedReader br = request.getReader();
        String params = br.readLine();//json字符串
//        System.out.println(params);
        //转为Brand对象
        Brand brand = JSON.parseObject(params, Brand.class);

        //3. 调用service添加
        brandService.add(brand);
        //4.若添加成功,则向前端写回success
        response.getWriter().write("success");
    }
    public void deleteByIds(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        //1.接收前端发送的ids
        BufferedReader br = request.getReader();
        String params = br.readLine();//
        //2.将json转化为数组
        int[] ids = JSON.parseObject(params, int[].class);
        //3.调用service的批量删除操作
        brandService.deleteByIds(ids);
        //若删除成功,则向前端写回success
        response.getWriter().write("success");
    }
    public void update(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        //1.接收前端发送的json格式数据
        BufferedReader br = request.getReader();
        String params = br.readLine();
        //2.将json格式数据转化为brand对象
        Brand brand = JSON.parseObject(params, Brand.class);
        //3.调用service的更新功能
        brandService.update(brand);
        //4.若更新成功则向前端写回success
        response.getWriter().write("success");
    }
    public void deleteById(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        //1.接收前端发送的Id
        String params = request.getParameter("id");
        //2.将得到的id从String格式转化为int格式
        int id = Integer.parseInt(params);
        //调用service的删除功能
        brandService.deleteById(id);
        //4.若删除成功,则向前端写回success
        response.getWriter().write("success");

    }
    public void selectTotalCount(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        //将总页数写回前端
        int count = brandService.selectTotalCount();
        String countStr = String.valueOf(count);
        response.getWriter().write(countStr);
    }
    public void selectByPage(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        //获取前端的两个参数,当前页数,每页显示记录条数
        String page = request.getParameter("currentPage");
        String size = request.getParameter("pageSize");
        int currentPage = Integer.parseInt(page);
        int pageSize = Integer.parseInt(size);
        //通过当前页数以及显示每页的记录条数返回list
        List<Brand> brands = brandService.selectByPage(pageSize*(currentPage-1), pageSize);
        //将list转化为json格式写回前端
        String brandJson = JSON.toJSONString(brands);
        response.setContentType("text/json;charset=UTF-8");
        response.getWriter().write(brandJson);
    }
    public void selectByPageAndCondition(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        //1.获取请求的页数以及单页记录数
        String page = request.getParameter("currentPage");
        String size = request.getParameter("pageSize");
        int currentPage = Integer.parseInt(page);
        int pageSize = Integer.parseInt(size);
        //2.获取请求的条件,并从JSON格式转化为对象
        BufferedReader br = request.getReader();
        String brandJson = br.readLine();
        Brand brand = JSON.parseObject(brandJson, Brand.class);
        //3.将前端发送的数据进行处理
        if (brand!=null) {
            String brandName = brand.getBrandName();
            String companyName = brand.getCompanyName();
            if (brandName!=null && brandName!=""){
                brandName="%"+brandName+"%";
            }
            if (companyName!=null && companyName!=""){
                companyName="%"+companyName+"%";
            }
            brand.setBrandName(brandName);
            brand.setCompanyName(companyName);
        }

        List<Brand> brands = brandService.selectByPageAndCondition(pageSize * (currentPage - 1), pageSize, brand);
        //将查询到的对象转化为JSON格式,并设定返回格式为uft-8的json然后写回
        String brandsJson = JSON.toJSONString(brands);
        response.setContentType("text/json;charset=utf-8");
        response.getWriter().write(brandsJson);
    }

    public void totalCountByPageAndCondition(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        BufferedReader br = request.getReader();
        String brandJson = br.readLine();
        Brand brand = JSON.parseObject(brandJson, Brand.class);
        if (brand!=null) {
            String brandName = brand.getBrandName();
            String companyName = brand.getCompanyName();
            if (brandName!=null && brandName!=""){
                brandName="%"+brandName+"%";
            }
            if (companyName!=null && companyName!=""){
                companyName="%"+companyName+"%";
            }
            brand.setBrandName(brandName);
            brand.setCompanyName(companyName);
        }
        int count = brandService.totalCountByPageAndCondition(brand);
        String countStr = String.valueOf(count);
        response.getWriter().write(countStr);
    }
}

通过编写以上代码,我们可以在浏览器输入http://localhost:8080/javaweb_demo/brand/addBrand的方式调用BrandServlet的addBrand方法。

此处,在编写Servlet代码时,涉及到获取前端数据,这里有一点需要注意。
前端传递数据的方式分为get和post,其中post方式得到的数据是json格式。request.getParameter("xxx")是获取不到的。必须使用BufferedReader br = request.getReader();String params = br.readLine();//json字符串

此外,在编写servlet要充分考虑前端发送的数据类型与参数名称。有些时候,前端发送的数据得用两种方式获取。

至此,完成了所有后端代码的编写。

搭建前端页面

前端的技术涉及到Ajax ,Vue,Element技术。

前端技术介绍

Ajax 作用有以下两方面:

  1. 与服务器进行数据交换:通过AJAX可以给服务器发送请求,服务器将数据直接响应回给浏览器。
  2. 异步交互:可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术。

Axios 对原生的AJAX进行封装,简化书写。
以下是使用Axios完成向服务器发送异步请求的简单案例:

 axios({
                     method:"get",
                     url:"http://localhost:8080/pro_maven/brand/selectAll",
                 }).then(function (resp) {
                     console.log(resp.data);
                 })

Vue 是一套前端框架,免除原生JavaScript中的DOM操作,简化书写。
Vue 基于MVVM(Model-View-ViewModel)思想,实现数据的双向绑定,将编程的关注点放在数据上。
在使用Vue之前,需要导入它的js文件。<script src="js/vue.js"></script>
接着在html页面中创建Vue对象,并修改视图即可。以下是一个例子

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <input v-model="username">
        <!--插值表达式-->
        {{username}}
    </div>
</body>
<script>
    //1. 创建Vue核心对象
    new Vue({
        el:"#app",
        data(){ // data() 是 ECMAScript 6 版本的新的写法
            return {
                username:""
            }
        }
    });
</script>
</html>

Element:是饿了么公司前端开发团队提供的一套基于 Vue 的网站组件库,用于快速构建网页。
Element 提供了很多组件(组成网页的部件)供我们使用。例如 超链接、按钮、图片、表格等等。
想要使用Element的组件,只需要复制官网的组件的代码即可。

brand页面代码实现

项目的前端代码brand.html内如如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>brand</title>
    <script src="js/vue.js"></script>
    <script src="element-ui/lib/index.js"></script>
    <script src="js/axios-0.18.0.js"></script>
    <link rel="stylesheet" href="element-ui/lib/theme-chalk/index.css"></link>
</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="selectByPageAndCondition">查询</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="dialogVisible1"
            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="updateBrand">提交</el-button>
                <el-button @click="clearBrand">取消</el-button>
            </el-form-item>
        </el-form>

    </el-dialog>
    <!--添加数据对话框表单-->
    <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"
                    width="180">
            </el-table-column>
            <el-table-column
                    prop="companyName"
                    label="企业名称"
                    align="center"
                    width="180">
            </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-row>
                    <el-button type="primary"  @click="update(scope.row)" type="text" size="small">修改</el-button>
                    <el-button type="danger" @click="deleteById(scope.row.id)" type="text" size="small">删除</el-button>
                </el-row>
                </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="pageSize"
            layout="total, sizes, prev, pager, next, jumper"
            :total="rowCount">
    </el-pagination>
</div>
<script>
    new Vue({
        el:"#app",
        data() {
            return {
                rowCount:"",
                currentPage: 1,
                pageSize:5,
                dialogVisible: false,
                dialogVisible1: false,
                multipleSelection: [],
                selectedIds:[],
                brand: {
                    status: '',
                    brandName: '',
                    companyName: '',
                    id: "",
                    ordered: "",
                    description: ""
                },
                tableData: [{
                    brandName: '华为',
                    companyName: '华为科技有限公司',
                    ordered: '100',
                    status: "1"
                }]
            }
        },
        methods:{
            selectByPageAndCondition(){
                var _this = this
                axios({
                    method:"post",
                    url:"http://localhost:8080/pro_maven/brand/selectByPageAndCondition?currentPage="+this.currentPage+"&pageSize="+this.pageSize,
                    data:this.brand
                }).then(function (resp){
                    _this.tableData=resp.data;
                    _this.totalCountByPageAndCondition();
                })
            },
            handleSizeChange(val) {
                console.log(`每页 ${val}`);
                this.currentPage=1;
                this.pageSize=val;
                this.selectByPageAndCondition();


            },
            handleCurrentChange(val) {
                console.log(`当前页: ${val}`);
                this.currentPage=val;
                this.selectByPageAndCondition();
            },

           update(row){
               this.dialogVisible1 = true;
               this.brand=row
           },
            updateBrand(){
               var _this = this;
               axios({
                   method:"post",
                   url:"http://localhost:8080/pro_maven/brand/update",
                   data:_this.brand
               }).then(function (resp){
                   if (resp.data=="success"){
                       _this.$message({
                           message: '恭喜你,修改成功',
                           type: 'success'
                       });
                   }
                   _this.dialogVisible1 =false;
                   _this.selectByPageAndCondition();
                   _this.clearBrand();
               })
            },
            deleteById(id){
                // console.log(id);
                this.$confirm('此操作将删除该数据, 是否继续?', '提示', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'warning'
                }).then(() =>{
                    var _this=this;
                    axios({
                        url:"http://localhost:8080/pro_maven/brand/deleteById?id="+id,
                        method:"get"
                    }).then(function (resp){
                        if (resp.data=="success"){
                            _this.$message({
                                message: '恭喜你,删除成功',
                                type: 'success'
                            });
                            _this.selectByPageAndCondition();
                        }
                    })
                }).catch(() => {
                    //用户点击取消按钮
                    this.$message({
                        type: 'info',
                        message: '已取消删除'
                    });
                });

            },

            handleSelectionChange(val) {
                this.multipleSelection = val;
                // console.log(this.multipleSelection)
            },
            deleteByIds(){
                this.$confirm('此操作将删除该数据, 是否继续?', '提示', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'warning'
                }).then(() =>{
                    for (let i = 0; i < this.multipleSelection.length; i++) {
                        let selectionElement = this.multipleSelection[i];
                        this.selectedIds[i] = selectionElement.id;
                    }
                    var _this=this;
                    axios({
                        url:"http://localhost:8080/pro_maven/brand/deleteByIds",
                        method:"post",
                        data:this.selectedIds
                    }).then(function (resp){
                        if(resp.data=="success"){
                            _this.$message({
                                message: '恭喜你,删除成功',
                                type: 'success'
                            });
                            _this.selectByPageAndCondition();
                        }
                    })

                }).catch(() => {
                    //用户点击取消按钮
                    this.$message({
                        type: 'info',
                        message: '已取消删除'
                    });
                });
            },
            clearBrand(){
                this.brand.id="";
                this.brand.brandName='';
                this.brand.status= '';
                this.brand.brandName= '';
                this.brand.companyName= '';
                this.brand.ordered= "";
                this.brand.description= "";
                this.dialogVisible1 = false;
                this.selectByPageAndCondition();
            },
            addBrand() {
                // console.log(this.brand);
                var _this = this;

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

                    }
                })
            },
            selectByPage(){
               var _this = this;
               axios({
                   method:"get",
                   url:"http://localhost:8080/pro_maven/brand/selectByPage?currentPage="+this.currentPage+"&pageSize="+this.pageSize
               }).then(function (resp){
                   _this.tableData=resp.data;
               })
            },
            totalCount(){
                var _this = this;
                axios({
                    method:"get",
                    url:"http://localhost:8080/pro_maven/brand/selectTotalCount"
                }).then(function (resp){
                    _this.rowCount = resp.data;
                    // console.log(_this.pageSize)
                    // console.log(_this.currentPage)
                })

            },
            totalCountByPageAndCondition(){
                var _this = this;
                axios({
                    url:"http://localhost:8080/pro_maven/brand/totalCountByPageAndCondition",
                    method:"post",
                    data:this.brand,
                }).then(function (resp){
                    _this.rowCount = resp.data;

                })
            },
            selectAll(){
                 var _this = this;
                 axios({
                     method:"get",
                     url:"http://localhost:8080/pro_maven/brand/selectAll",
                 }).then(function (resp) {
                     _this.tableData = resp.data;
                 })
            }
        },
        mounted(){
            this.selectByPageAndCondition();

        }
    })
</script>
</body>
</html>

这里的前端代码写的比较乱还没有经过优化,后续可以通过优化使得前端代码更加简洁美观。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-07-03 10:36:15  更:2022-07-03 10:38:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 17:21:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码