以上是我们在综合案例要实现的功能。对数据的除了对数据的增删改查功能外,还有一些复杂的功能,如 批量删除
、分页查询
、条件查询
等功能
-
批量删除
功能:每条数据前都有复选框,当我选中多条数据并点击批量删除
按钮后,会发送请求到后端并删除数据库中指定的多条数据。 -
分页查询
功能:当数据库中有很多数据时,我们不可能将所有的数据展示在一页里,这个时候就需要分页展示数据。 -
条件查询
功能:数据库量大的时候,我们就需要精确的查询一些想看到的数据,这个时候就需要通过条件查询。 -
查询所有功能
如上图所示是查询所有品牌数据在页面展示的效果。要实现这个功能,要先搞明白如下问题:
-
什么时候发送异步请求?
页面加载完毕后就需要在页面上看到所有的品牌数据。所以在
mounted()
这个构造函数中写发送异步请求的代码。 -
请求需要携带参数吗?
查询所有功能不需要携带什么参数。
-
响应的数据格式是什么样?
后端是需要将
List<Brand>
对象转换为 JSON 格式的数据并响应回给浏览器。响应数据格式如下:我们先实现后端程序,然后再实现前端程序。
dao方法实现
在
com.itheima.mapper.BrandMapper
接口中定义抽象方法,并使用@Select
注解编写 sql 语句
/**
* 查询所有
* @return
*/
@Select("select * from tb_brand")
List<Brand> selectAll();
由于表中有些字段名和实体类中的属性名没有对应,所以需要在 com/itheima/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.itheima.mapper.BrandMapper">
<resultMap id="brandResultMap" type="brand">
<result property="brandName" column="brand_name" />
<result property="companyName" column="company_name" />
</resultMap>
</mapper>
定义完结果映射关系后,在接口 selectAll()
方法上引用该结构映射。使用 @ResultMap("brandResultMap")
注解
完整接口的 selectAll()
方法如下:
/**
* 查询所有
* @return
*/
@Select("select * from tb_brand")
@ResultMap("brandResultMap")
List<Brand> selectAll();
service方法实现
在 com.itheima.service
包下创建 BrandService
接口,在该接口中定义查询所有的抽象方法
public interface BrandService {
/**
* 查询所有
* @return
*/
List<Brand> selectAll();
}
并在 com.itheima.service
下再创建 impl
包;impl
表示是放 service 层接口的实现类的包。 在该包下创建名为 BrandServiceImpl
类
public class BrandServiceImpl implements BrandService {
@Override
public List<Brand> selectAll() {
}
}
此处为什么要给 service 定义接口呢?因为service定义了接口后,在 servlet 中就可以使用多态的形式创建Service实现类的对象,如下:
这里使用多态是因为方便我们后期解除 Servlet
和 service
的耦合。从上面的代码我们可以看到 SelectAllServlet
类和 BrandServiceImpl
类之间是耦合在一起的,如果后期 BrandService
有其它更好的实现类(例如叫 BrandServiceImpl
),那就需要修改 SelectAllServlet
类中的代码。后面我们学习了 Spring
框架后就可以解除 SelectAllServlet
类和红色框括起来的代码耦合。而现在咱们还做不到解除耦合,在这里只需要理解为什么定义接口即可。
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;
}
}
servlet实现
在 com.itheima.web.servlet
包下定义名为 SelectAllServlet
的查询所有的 servlet
。该 servlet
逻辑如下:
-
调用service的
selectAll()
方法查询所有的品牌数据,并接口返回结果 -
将返回的结果转换为 json 数据
-
响应 json 数据
代码如下:
@WebServlet("/selectAllServlet")
public class SelectAllServlet extends HttpServlet {
private BrandService brandService = new BrandServiceImpl();
@Override
protected void doGet(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);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
在浏览器输入访问 servlet 的资源路径 http://localhost:8080/brand-case/selectAllServlet
,如果没有报错,并能看到如下信息表明后端程序没有问题
前端实现
前端需要在页面加载完毕后发送 ajax 请求,所以发送请求的逻辑应该放在 mounted()
钩子函数中。而响应回来的数据需要赋值给表格绑定的数据模型,从下图可以看出表格绑定的数据模型是 tableData
mounted(){
//当页面加载完成后,发送异步请求,获取数据
var _this = this;
axios({
method:"get",
url:"http://localhost:8080/brand-case/selectAllServlet"
}).then(function (resp) {
_this.tableData = resp.data;
})
}