环境搭建
- 创建Maven文件引入依赖
- 实现逻辑
查询所有
后端代码
- 使用Mybatis插件创建对应的配置文件
- 创建Mapper层并在resource中创建同样目录下的xxxMapper.xml
- 后端三层架构实现
- 创建实体层
- 创建对应的Mapper层
- 创建对应的Service层(旧版)
- 创建对应的Service层(新版)
- 旧版直接在servlet中新建service对象,service层更改servlet也要更改
- 新版通过接口实现service对象,在servlet中创建对应的实现类指向接口
- 未来spring直接管理对象,可以通过接口自动分配实现类
- 优化外层代码耦合度
- 创建对应的Servlet层
- 创建实现接口类Service层对象
- 查询方法接口层调用service对象的方法
- 使用JSON.toString将对象序列化
- 处理JSON中文乱码问题使用setContentType
- 将处理的数据响应给浏览器
前端页面
- 页面加载完成后发送异步请求获取列表数据
- 使用mounted生命周期并使用axios放松ajax请i去
- 创建对应的模型数据将数据渲染到页面
- 因为axios中异步的数据是dom层的需要将数据赋值给vue
- 使用this.data获取dom层的数据,在vue层面定义方法接收该值
代码可以看出resp.data是服务器响应的数据
自定义的_this.tableData是vue自定义的渲染的数据模型
新增品牌
后端代码
Mapper层
- Mapper层写入对应的添加方法
- 使用@Insert注解添加语句
Service层
- Service层在对应的接口层写方法,实现类重写添加方法
- 调用SqlSessionFactoryUtil工具类
- 获取SqlSession对象,反射对应的Mapper类
- 调用Mapper类添加方法
- 因为是增删改操作需要开启事务commit()
Servlet层
- 获取浏览器post请求数据
- 因为是JSON数据无法使用getParameters获取
- 使用字符输入流读取数据
- 并使用JSON工具反序列化为Java对应的类的对象
- 调用Service层封装的方法
- 添加成功服务层添加响应数据
前端页面
弹窗表单
提交方法以及表单模型数据
- 添加查询方法调用selectAll()方法
- 调用mounted生命周期页面加载后异步加查询方法
- 创建添加功能,异步提交post请求携带dom层数据判断回调数据
- 成功关闭弹窗并重新调用selectAll()方法,并添加添加成功提示框
TIPS: 区别this和自定义的vue获取变量的值
- mounted()中使用this直接调用查询selectAll()方法是因为mounted和methods都属于vue标签属性并没有声明额外变量去获取DOM层的值
- 但是在methods的添加功能中提前生命了将DOM的值this赋值给vue的变量操作所以在addBrand()中使用自定义变量调用的selectAll()方法
Servlet 代码优化
实现原理
- 原有Servlet是直接继承HttpServlet重写doGet()和doPost()方法
- 源码HttpServlet的doGet()和doPost()是初始方法是service方法
- 现自定义Servlet共用类继承HttpServlet直接重写service方法
- 将接口统一定义为一个servlet并将各个路径和对应方法名绑定
获取路径名
- 使用req.getRequestURI()获取请求路径的段路径
- 使用字符串lastIndexof(‘/‘)从后往前数获取该字符串的索引
- 在使用substring()传递该字符串索引切割后,留下后面的字符串
- 最终得到路径名
获取方法名
- 获取方法使用反射特性getClass()
- 因为不是获取特定的servlet而是要根据谁调用了这个service方法而反射哪个servlet
- 所以使用this这个关键字指向调用该service
- this:谁(this所在的方法)调用我,我(this)就是谁
- 所直接对this使用getClass()放射方法获得对应的Class对象
- 获得Class对象后调用该文件字节码的Method方法对象
- 使用反射中的invoke传入方法名,以及方法需要的参数
实现方法
- 创建总业务层Servlet继承定义了方法路径绑定的BaseServlet
- 更改路径使用业务层+通配符*
- 将之前Servlet的代码复制到对应的方法名下
- 更改页面axios路径
批量删除
后端代码
- Dao层对应的Mapper创建deletByIds(int[] ids)方法
- 因为是传入一个数组,所以在对应的xml文件中使用动态sql语句
- 批量删除语句delet * from tb_brand where id in (?,?,?)
- 使用
标签循环遍历的id数组然后传递给sql语句的id - 其中collction 属性是集合,item是遍历后获得的属性值
- open和close是开始标签和结束标签,separator是分隔符
- 在Service层定义接口方法void deletByIds(int[] ids)
- 并在Impl实现层封装Mapper方法
- 增删改需要提交事务
- 在BrandServlet层定义删除方法接口为方法名
- 传入对应的HttpServletRequest request, HttpServletResponse response
- 不能使用getParameters,接收定义JSON数组必须使用字符输入流
- 使用JSON.parseObject传入对应的int[]类型数组对象
- 调用service层删除方法并响应数据
前端代码
- Dom层代码绑定点击事件与填报表格中复选框点击事件联动
- 前端代码创建批量删除点击事件
- 获取填报表格中的复选框点击事件的回调函数
- Data数据模型创建id数组
- methods方法
- 创建批量删除功能方法deletByIds
- 添加提示框内容确认提交后遍历复选框数组并传给定义的id模型数组
- 可以直接使用遍历后的索引给对应的id模型赋值
- 也可以直接使用push方法传递给集合
- 最后发送ajax的post请求将id模型数组传递给后端
- 成功给出提示,并调用selectAll()方法刷新页面
分页查询
SQL查询 — LIMIT
不规定初始参数查询10条数据
从第五个索引开始,查询5条数据
分页查询LIMIT参数逻辑:
- 参数1: 开始索引是(当前页码-1)* 每页需要显示的条数
- 参数2: 每页需要查询的条数
实现逻辑
后端代码
- Dao层创建前端需要的数据对应的方法
- 当前页List数据 — selectByPage(begin,size)
- 对应的是Limit的SQL查询语句
- begin是索引,size是查询条目
- @Select(“select * from tb_brand limit #{begin},#{size}”)
- 查询总数 — selectTotalCount()
- 使用count(*)关键字
- @Select(“select count(*) from tb_brand”)
- 创建PageBean对象创建字段封装这两个数据
- 当前页List数据 — selectByPage(begin,size)
- Service层在则封装Dao层方法
- 创建分页查询方法,返回PageBean对象,
- 参数值1: 当前页面(客户端)
- 参数值1: 每页查询数量(客户端)
- 实现层Impl实现该方法
- 常规获取sqlSession对象
- 客户端传入的当前页码currentPage
- 需要使用SQL固定分页方法
- 分页查询第一个参数是(当前页-1)* 每页显示记录数
- 所以定义变量 int begin = (currentPage -1)* pageSize
- 调用mapper定义的selectByPage该方法的数据是当前页list数据
- 将定义的begin以及客户端传入的pageSize传入该方法中
- 获取查每页数据
- 调用mapper定义的另一个方法selectTotalCount()
- 将调用后的mapper方法后的变量封装到PageBean对象中
- 最后释放资源,返回PageBean对象
- 创建分页查询方法,返回PageBean对象,
- Servlet层添加接口方法
- 获取前端传递的两个参数request.getParameter
- 当前页面使用
- 每页展示条数
- 使用Interger.parseInt转移为int类型
- 将获取的两个参数
- 传递到service层的方法selectByPage中获取每页展示数据
- 并且封装成PageBean对象
- 使用JSON.toJSONString序列化对象
- 响应该JSON对象到客户端
- 测试接口
- 获取前端传递的两个参数request.getParameter
前端代码
分页工具条:
- 前端传递后端回调函数
- handleCurrentChange是当前页数回调
- 需要作为currentPage参数传递给后端
- 是LIMIT的SQL语句的第一个参数
- handleSizeChange是每页显示行数
- 需要作为pageSize参数传递给后端
- 是LIMIT的SQL语句的第二个参数
- 前端Dom组件
- v-bind 简化成:
- current-page 当前页
- page-size 每页显示数据行
- total 总页数
- handleCurrentChange是当前页数回调
mounted生命周期:
- 前端页面加载后
- 加载异步请求调用selectByPage方法
定义data数据模型以及methods方法
- data数据模型:
- methods方法:
条件查询
SQL查询
后端代码
- Dao层逻辑代码提供两个方法
- selectByPageAndCondition(begin,size,band)
- 分页方法需要传递:
- begin当前页索引
- size当前页显示条目数据
- band是条件查询
- 因为条件是满足对应查询的brand对象
- mapper中使用@Param指向brand对象
- brand对象封装了需要调用的成员变量
- 在xml的动态sql中需要使用brand去调用其成员变量
- 分页方法需要传递:
- selectTotalCount(brand)
- 同样条件是满足条件查询的brand对象
- 所以需要将满足条件的brand对象封装
- 因为没有指定@Param对象所以可以直接使用其成员变量
- TIPS: 在多参数指定@Param是用于区别参数对象的
- SQL语句可能会存在多个对象
- @Param注解用于区别,当SQL语句含有多个对象
- 例如@Param(“brand”)Brand brand,@Param(“user”)Brand user
- 可以在xml动态语言中调用对象对应的成员变量
- #{brand.brandName}和#{user.name}
- selectByPageAndCondition(begin,size,band)
1.1 Dao层逻辑代码XML
- selectByPageAndCondition(begin,size,band) —xml
- selectTotalCount(brand) —xml
`
- Servkce层创建业务方法
- 在实现层写条件分页查询方法
- PageBean
selectByPageAndCondition(int currentPage, int pageSize, Brand brand);
- PageBean
- 返回值是之前定义接收分页查询方法的对象PageBean
- 参数:currentPage当前页
- 参数:pageSize 每页显示条数
- 参数:brand带有条件的对象
- 在实现层写条件分页查询方法
2.2 Service实现层,调用mapper方法并封装该方法
- 获取sqlSession对象,反射对应的类
- 浏览器传入的pageSize创建记录索引
- 需要将浏览器传入的brand的JSON对象进行处理
- 判断对应的brand的成员变量是否存在
- 存在则设置为字符串模糊查询(”%”+xxx+”%”)
- 调用模糊查询的封装类对象 根据brand数量调用查询的总数
- 将页面索引,查询条目数,条件对象传入到selectByPageAndCondition方法中
- 创建对象封装满足条件当前页数据以及条件对象总数目
- Servlet 层创建业务方法
- 获取前端url中携带人currentPage以及pageSize参数
- 使用request.getParameter()
- 将获取的url参数转换为integer对象
- 前端页面post和get同时携带的数据以及url数据
- 因为获取的是JSON对象(满足条件的brand对象)
- 不能使用getParameter()
- 使用字符流接收对象
- 并使用JSON.parseObject(xx,xx.Class)反序列化对象
- 将获取的currentPage和pageSize以及反序列化后的brand对象传入service方法
- 将获取的对象重新使用JSON.toJSONString序列化响应到页面
- 获取前端url中携带人currentPage以及pageSize参数
前端代码
- 页面加载后mounted异步请求加载一下不含条件的对象
- 点击按钮后携带当前页,每页显示条数,以及符合条件的对象传入到后端
- 后端调用servlet方法后,将封装好的pageBean对象序列化为JSON响应到客户端
- 原理页面更改原有分页查询数据改为条件查询数据
- 不添加任何条件则是分页查询数据
- 将currentPage,pageSize以url方式传入
- 更改提交方法为post将数据模型brand发送给服务器
- 更改回调函数then(funtion(resp){xxx})方法为箭头函数then(resp=>{xxx})
- 更改箭头函数后可以直接使用this将vue模型数据指向服务器数据
- 在查询按钮方法中直接调用分页查询方法