项目概述
本次项目在传统javaweb项目基础上,使用了Maven来构建整个项目,前端使用Vue框架以及Element组件库,并且使用MyBatis作为持久层框架。通过以上技术,大大提高了开发效率。
通过实现以上功能,加深自己对JavaWeb的认识,同时加强自己对Vue,Maven,Axios,MyBatis,Servlet等相关技术的掌握。
功能介绍
本次的项目是一个品牌后台管理系统,其功能包括:
- 显示所有品牌信息
- 修改品牌信息
- 删除品牌信息
- 添加品牌信息
- 批量删除品牌信息
- 显示分页
- 模糊查询
成果展示
项目实现
通过以下步骤,逐步完成本次项目所需实现的功能。
使用Maven构建项目
Maven介绍
Maven:Maven是专门用于管理和构建java项目的工具,主要功能如下:
- 标准化的项目结构
- 标准化的构建结构
- 依赖管理
使用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中修复。 修复后的项目目录如下:
使用Mybatis封装对数据库的操作
MyBatis:MyBatis是一款持久层框架,可以简化JDBC开发。 主要解决JDBC存在的以下问题:
- 硬编码
- 操作繁琐
使用MyBatis操作数据库的流程如下:
在Mysql中建表,并添加数据
在mysql数据库中创建相应的表,并添加一些数据。
drop table if exists tb_brand;
create table tb_brand
(
id int primary key auto_increment,
brand_name varchar(20),
company_name varchar(20),
ordered int,
description varchar(100),
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 {
private Integer id;
private String brandName;
private String companyName;
private Integer ordered;
private String description;
private Integer status;
@Override
public String toString() {
return "Brand{" +
"id=" + id +
", brandName='" + brandName + '\'' +
", companyName='" + companyName + '\'' +
", ordered=" + ordered +
", description='" + description + '\'' +
", status=" + status +
'}';
}
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>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<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&allowPublicKeyRetrieval=true"/>
<property name="username" value="账号"/>
<property name="password" value="密码"/>
</dataSource>
</environment>
</environments>
<mappers>
<package name="com.itheima.mapper"/>
</mappers>
</configuration>
xml代码中有两点在官网给的模板上做出了优化。
第一点:添加了typeAliases标签,并使用了包扫描的方式。这样做的好处是使用类名的小写作为类的别名,减少类完全限定名的冗余。
第二点,使用包扫描的方式方式来配置标签mappers中的内容,好处是减少代码量。
在这一步,有以下地方需要注意。在配置数据库url时,由于mysql版本问题,为了成功连接数据库并能顺利执行sql语句,需要携带两个参数,关键代码如下: <property name="url" value="jdbc:mysql:///mybatis?useSSL=false&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();
Brand selectBrandById(int id);
List<Brand> selectByCondition(@Param("status") int status, @Param("companyName") String companyName, @Param("brandName") String brandName);
List<Brand> selectByConditionSingle(Brand brand);
void add(Brand brand);
void update(Brand brand);
void deleteById(int 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>
<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 {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
List<Brand> brands = mapper.selectAll();
System.out.println(brands);
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类的方法,我们要经过以下操作:
- 获取SqlSessionFactory对象
- 通过SqlSessionFactory对象,获取SqlSession对象。
- 通过SqlSession对象,获取Mapper对象
- 通过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 {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
String uri = req.getRequestURI();
int index = uri.lastIndexOf('/');
String methodName = uri.substring(index + 1);
Class<? extends BaseServlet> aClass = this.getClass();
try {
Method method = aClass.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
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 {
List<Brand> brands = brandService.selectAll();
String brandsStr = JSON.toJSONString(brands);
response.setContentType("text/json;charset=UTF-8");
response.getWriter().write(brandsStr);
}
public void addBrand(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
BufferedReader br = request.getReader();
String params = br.readLine();
Brand brand = JSON.parseObject(params, Brand.class);
brandService.add(brand);
response.getWriter().write("success");
}
public void deleteByIds(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
BufferedReader br = request.getReader();
String params = br.readLine();
int[] ids = JSON.parseObject(params, int[].class);
brandService.deleteByIds(ids);
response.getWriter().write("success");
}
public void update(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
BufferedReader br = request.getReader();
String params = br.readLine();
Brand brand = JSON.parseObject(params, Brand.class);
brandService.update(brand);
response.getWriter().write("success");
}
public void deleteById(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
String params = request.getParameter("id");
int id = Integer.parseInt(params);
brandService.deleteById(id);
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<Brand> brands = brandService.selectByPage(pageSize*(currentPage-1), pageSize);
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{
String page = request.getParameter("currentPage");
String size = request.getParameter("pageSize");
int currentPage = Integer.parseInt(page);
int pageSize = Integer.parseInt(size);
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);
}
List<Brand> brands = brandService.selectByPageAndCondition(pageSize * (currentPage - 1), pageSize, brand);
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 作用有以下两方面:
- 与服务器进行数据交换:通过AJAX可以给服务器发送请求,服务器将数据直接响应回给浏览器。
- 异步交互:可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术。
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>
new Vue({
el:"#app",
data(){
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){
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;
},
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() {
var _this = this;
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;
})
},
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>
这里的前端代码写的比较乱还没有经过优化,后续可以通过优化使得前端代码更加简洁美观。
|