传智健康-day2
一.需求分析(预约管理功能开发)
预约管理功能,包括检查项管理、检查组管理、体检套餐管理、预约设置等、预约管理属于系统的基础功能,主要就是管理一些体检的基础数据。
检查组是检查项的集合
二.基础环境搭建
1导入预约管理模块数据表
需要用到的表和其中的关联表,检查项和检查组是多对多关系
2导入实体类POJO
根据数据表也可以自己创建实体类,两者存在对应关系,一张表对应一个实体类(POJO),关联表不存在实体类。
实体类之间存在多对多关系,可以通过在实体类中建立一个List集合来对应关系。
因为使用到检查组时一定会检索到检查组,所以在检查组中声明了检查项。
但是使用检查项时不一定会使用到检查组,所以检查项中没必要声明检查组
各个模块都有可能使用到这些实体类,将POJO实体类复制到health_common工程中
创建新的包pojo
3导入项目所需公共资源
消息常量类
返回结果Result和PageResult(分页查询返回的结果类)类,放到health_common工程中
注:返回结果指的是SpringMVC中controller的返回结果,项目中所有的增删改查操作发送的请求,基于的都是ajax异步请求(可以用F12查看过程),请求完成后,在controller中处理,完成后controller将结果封装成PageResult对象,PageResult对象将结果转换成json数据,写回到前端页面。
Result类是除了分页查询返回结果类的所有返回结果类
QueryPageBean类,封装查询条件,页面输入的查询条件作为类的参数
创建新的包entity
4导入前端静态资源
复制资源包到health_backend模块下的webapp中
注:此处js资源中的axios.js文件是使用ajax必须的文件,vue.js文件是使用vue必须的文件
启动项目,因为项目依赖zookeeper基础服务,所以需要安装windows单机的zookeeper
三.zookeeper安装使用
zookeeper是apache hadoop项目下的一个子项目,是一个树形管理目录
zookeeper是一个分布式,开源的分布式应用程序的协调服务
主要功能是:配置管理,分布式锁,集群管理
目前开发阶段需要依赖zookeeper,但是不需要启动虚拟机,所以我们直接下载文件在windows环境下运行即可。
windows环境下安装zookeeper
1.首先去官网下载文件
2.解压到常用安装软件目录
3.运行zkServer.cmd文件
执行闪退:编辑zkServer.cmd末尾添加pause 。这样运行出错就不会退出,会提示错误信息,方便找到原因。
缺少zoo.cfg文件:将conf目录下的zoo_sample.cfg文件,复制一份,重命名为zoo.cfg。
如果
出现ZooKeeper audit is disabled,zoo.cfg新增一行
audit.enable=true
成功启动后可以在logs目录中查看日志
四.分析页面结构
项目运行之前,对项目整体进行编译
因为在backend项目中的pom文件中引入了tomcat7,所以在backend的plugins中可以看到插件
如果pom文件中tomcat爆红,可以添加一个版本号
启动tomcat
根据tomcat定义来确认访问路径
成功访问
iframe标签可以直接引用其它页面。
menuList可以遍历出所有的子级菜单
menuList中的linkUrl对应页面名称,点击菜单的时候就可以跳转到相关页面
通过href超链接跳转,linkUrl对应了页面名
五.新增检查项-完善页面-弹出新增窗口
新建检查项功能应该在点击新建后弹出弹层,所以在默认情况下该弹层是隐藏的,单击新增后展示此页面
<el-dialog title="新增检查项" :visible.sync="dialogFormVisible">
visible.sync表示控制当前窗口是显示还是隐藏,:visible.sync表示绑定的控制值是动态的。
diaglogFormVisible是在vue对象中创建的一个模型数据
dialogFormVisible: false,//增加表单是否可见
默认值为false,表示默认此弹层不可见
为新建按钮绑定一个单击事件(@Click),对应的函数是handleCreate()
<el-button type="primary" class="butT" @click="handleCreate()">新建</el-button>
// 弹出添加窗口
handleCreate() {},
当单击新建按钮时,触发对应函数handleCreate(),此时修改:visible.sync对应的控制值diaglogFormVisible发生变化,使弹层展示
handleCreate() {// 弹出新增页面this.dialogFormVisible=true;},
取消按钮绑定的事件,把模型数据修改为false,从而使弹层取消展示
<el-button @click="dialogFormVisible4Edit = false">取消</el-button>
el-diaglog自带的×按钮也可以取消弹层展示
取消弹层展示后清空表单内容
表单输入框的内容和模型数据V-model绑定了,每次弹出之后,重新设置模型数据值,将数据值设置为空的json即可实现清空表单内容功能。
// 重置表单resetForm() {//重置表单数据this.formData = {};},
// 弹出添加窗口handleCreate() {// 弹出新增页面this.dialogFormVisible=true;//将json数据直接赋空值:{}this.formData = {};},
这样做可以重置表单,但是弹出新增功能就和重置表单功能粘合了,我们的原则是方法单一,即每个方法只完成一个功能。重置表单功能作为单一的一个方法,我们需要用到这个功能时直接调用这个方法即可。
六.新增检查项_输入校验
在VUE对象中定义校验规则(rules)
rules: {//校验规则code: [{ required: true, message: '项目编码为必填项', trigger: 'blur' }],name: [{ required: true, message: '项目名称为必填项', trigger: 'blur' }] }
在以下输入域中应用规则
七.新增检查项_提交表单数据
提交表单数据使用ajax异步请求方式提交,点击提交按钮后,首先对表单数据进行一个整体校验,校验成功后,将表单数据获取,表单数据都绑定在VUE对象的模型数据(formData)中了。所以提交表单就是提交formData,发送ajax请求。
注:alter();方法可以检验触发事件@handleAdd
1.表单校验
// 1.表单校验,获取表单对象refsthis.$refs["dataAddForm"].validate((valid) => {alert(valid);});
表单数据对应的ref="dataAddForm",通过this.refs获取到表单数据,validate方法是一个箭头函数,如果表单校验通过,那么其中的valid值会是ture值。
controller端收到网页请求后,会产生一个响应(res),而在之前common模块中,已经封装好了controller的返回结果,定义res是一个Reslut类型的java对象,SpringMVC会自动将Result对象转化成json,flag,message。
// console.log(this.formData); //通过开发者模式观察通过校验后的表单数据
//添加handleAdd () {alert();// 1.表单校验,获取表单对象refsthis.$refs['dataAddForm'].validate((valid) => {if(valid) {// 表单检验通过,发送Ajax请求,将录入的数据提交到后台进行处理// console.log(this.formData); //通过开发者模式观察通过校验后的表单数据//引用axios文件来发送Ajax请求,post(请求地址,请求体(json数据)),发送后需要一个回调函数then,res是服务端(controller)响应的结果axios.post("/checkitem/add.do",this.formData).then((res) =>{//Result对象中包含的flag属性,res.data是固定写法,拿到的就是controller响应的数据//表单提交后,无论添加成功或者失败,都关闭新增窗口this.dialogFormVisible = false;if(res.data.flag){//执行成功//调用分页查询方法,查询出最新的数据this.findPage();//弹出提示信息this.$message({message:res.data.message,type:'success'});}else{//执行失败//弹出提示this.$message.error(res.data.message);}});}else{//校验不通过this.$message.error("数据校验失败,请检查输入信息是否正确");return false;}});},
res.data是一个固定写法
如果controller端没有响应,则不涉及到Result类的调用,则没有res.data的使用。直接使用 this.$message.*来展示返回结果即可
八.新增检查项_后台代码
一.定义Controller(backend)
在backend模块下新建controller路径,路径下新建CheckItemController类
controller用来响应前端发送的ajax请求
1.添加注解
@RestController
//@RestController包含@Controller注解,同时包含ResponseBody;直接让方法返回java对象,SpringMVC框架会自动将java对象转化成json.
@RequestMapping("/checkitem")
//匹配请求路径
请求路径和前端发送请求的路径对应
public void add(CheckItem checkItem);
2.添加对应的方法
方法中也要加一个注解匹配请求路径,对应前端的请求路径
@RequestMapping("/add")//匹配请求public Result add(@RequestBody CheckItem checkItem){}
//此controller对应实体类是CheckItem,所以方法的参数是CheckItem。前端提交的formData是json数据,SpringMVC无法封装,需要加一个注解才能封装json数据;@RequestBody解析提交的数据,封装成CheckItem对象
3.调用服务层接口
@Reference//zookeeper服务中心去查找CheckItemService的服务private CheckItemService checkItemService;
4.调用接口对应的方法
checkItemService.add(checkItem);
5.检验调用是否成功
使用try-catch来验证是否调用服务层成功
try{checkItemService.add(checkItem);}catch(Exception e){e.printStackTrace();//服务调用失败return new Result(false, MessageConstant.ADD_CHECKITEM_FAIL);}return new Result(true, MessageConstant.ADD_CHECKITEM_SUCCESS);
二.定义服务层
服务层就是dubbo服务层,这个层级用来将controller处理过的前端提交的数据保存到数据库中
1.定义服务接口(interface)
2.声明接口方法
public void add(CheckItem checkItem);
3.定义服务实现类(service_provider)
//发布服务,使用dubbo的服务注解
@Service(interfaceClass = CheckItemService.class)
4.注入DAO对象
@Autowiredprivate CheckItemDao checkItemDao;
三.定义DAO层
1.新建对应的dao接口
2.声明新增方法()
因为基于mybatis的动态代理方式,所以dao接口无需创建实现类,匹配一个xml映射文件即可
3.新建xml映射文件
4.书写sql语句
头文件可以复制粘贴,sql语句的id对应dao接口中的方法名,parameterType(参数类型)必须和dao接口中指定的参数保持一致
mapper标签的namespace必须和dao接口的完整路径对应
<?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.dao.CheckItemDao">
<!-- 插入检查项数据--><insert id="add" parameterType="com.itheima.pojo.CheckItem" >insert into t_checkitem(code,name,sex,age,price,type,remark,attention)values(#{code},#{name},#{sex},#{age},#{price},#{type},#{remark},#{attention})</insert>
</mapper>
四.检查
配置文件中的参数,要让dubbo能够扫描到服务层
service实现类中的注解需要添加参数,因为添加了事务注解,所以@Service必须指明实现的是哪个接口
//事务注解
@Transactional
//发布服务,使用dubbo的服务注解
@Service(interfaceClass = CheckItemService.class)
五.运行准备
1.安装项目
2.启动服务层service_provider的tomcat
3.启动服务消费层backend的tomcat
4.运行网页端。
总结后台代码开发流程
九.检查项分页
1.分析检查项分页查询实现原理
项目所有分页功能都是基于ajax的异步请求来完成的,请求参数和后台响应数据格式都使用json数据格式。
前端的请求参数包括页码,每页显示记录数,查询条件
请求参数的json格式为:{currentPage:1,pageSize:10,queryString:''itcast''}
后台响应数据包括总记录数、当前页需要展示的数据集合。
响应数据的json格式为:{total:1000,rows:[]}
具体流程如下
2.完善页面
定义分页相关的模型数据 pagination
pagination: {//分页相关模型数据currentPage: 1,//当前页码pageSize:10,//每页显示的记录数total:0,//总记录数queryString:null//查询条件},dataList: [],//当前页要展示的分页列表数据
定义分页查询的方法findPage()
这个方法在页面加载完成时调用,可以使用钩子函数来完成,钩子函数:在VUE对象初始化完成后自动执行
findPage() {//发送ajax请求,提交分页相关参数(页码,每页显示记录数,查询条件)var param = {currentPage:this.pagination.currentPage,pageSize:this.pagination.pageSize,queryString:this.pagination.queryString};//构造json对象,封装相关参数axios.post("checkitem/findPage.do",param).then((res) =>{//解析controller响应回的数据,为模型数据赋值,将响应回的数据赋给模型数据进行展示this.pagination.total = res.data.total;this.dataList = res.data.rows;});},
用户点击查询按钮或者点击分页条中的页码时也需要调用findPage方法重新发起查询请求。
为查询按钮绑定单击事件,调用findPage方法
当页码发生改变时,也要调用findPage()方法,分页条自带的事件@current-change,当页码发生改变时自动触发该事件,该事件绑定的方法可以使用传入页码参数(currentPage)和调用findPage()方法来实现页码改变和分页查询功能。
//切换页码handleCurrentChange(currentPage) {//设置最新的页码this.pagination.currentPage = currentPage;//调用findPage()方法进行分页查询this.findPage();},
总结:该方法的调用时机有:页面加载完成时,页码改变时,用户点击查询按钮时
十.检查项分页_后台代码
1.Controller
在checkItemController中添加对应的方法来接受前端的参数
参数是QueryPageBean
//检查项分页查询@RequestMapping("/findPage")//匹配请求public PageResult findPAge(@RequestBody QueryPageBean queryPageBean){PageResult pageResult = checkItemService.pageQuery(queryPageBean);return pageResult;}
2.服务接口
在checkItemService中添加对应方法
在checkItemController对应的方法中调用checkItemService中对应的方法
注:var快捷键可以快速实现代码书写,例如下
checkItemService.pageQuery(queryPageBean).var == PageResult pageResult = checkItemService.pageQuery(queryPageBean);
然后将得到的参数pageResult返回
controller只是向dubbo服务调用了方法
3.服务实现类
在service的实现类中将分页查询方法拓展
4.Dao接口
在CheckItemDao接口中拓展出SQL对应方法
5.Mapper映射文件
mybatis框架了提供了分页助手插件,减少sql语句的书写量
没有分页助手插件情况下,sql语句实现分页查询,limit后面是页码和查询条数,这两个参数是动态的,根据currentPage和pageSize来计算
//select * from t_checkitem limit 0,10
使用分页助手插件后,不需手动书写limit后面的语句了,由助手进行自动拼接
在checkItemDAO.xml文件中新建SQL语句
<!-- 页面有可能会传查询条件,使用动态where条件,如果有查询条件queryString,则查询。mybatis提供了动态sql--><select id="selectByCondition" parameterType="String" resultType="com.itheima.pojo.CheckItem">select * from t_checkitem<if test="value != null and value.length > 0">where code = #{value} or name = #{value}</if></select>
在服务实现类中调用CheckItemDao中的的方法
十一.测试分页功能
关闭tomcat服务,对项目进行安装
十二.删除检查项_完善页面
删除操作需要缓冲空间,在点击删除后,弹出弹框再次确认是否删除。
ElementUI提供了$confirm方法来实现确认提示信息弹框效果
handleDelete(row) {//row对象是一个json对象,里面有//alert(row.id);this.$confirm("确定要删除这条数据吗?","提示",{type:"warning"}).then(()=>{//用户点击确定按钮,发送ajax请求,将要删除数据的id提交到controller进行处理axios.get("/checkitem/delete.do?id=" + row.id).then((res)=>{if(res.data.flag){//执行成功//弹出删除成功提示信息this.$message({type:"success",message:res.data.message});}else{//执行失败this.$message.error(res.data.message);}this.findPage();});}).catch(()=>{this.$message({type:"info",message:"操作取消"});});}
后台代码开发依据五个步骤:
1Controller(Backend)
2服务接口(interface)
3服务实现类(service_provider)
在实现类中定义实现方法:
代码逻辑:检查项和检查组之前存在n对m关系,检查项不能直接删除,需要判断当前检查项是否和检查组关联,如果已经和检查组进行了关联则不允许删除
4Dao接口(service_provider)
5Mapper映射文件(service_provider)
十三.编辑检查项
1.前端代码
绑定编辑单击事件,单击编辑时展示页面
// 弹出编辑窗口handleUpdate(row) {//显示窗口this.dialogFormVisible4Edit = true;//显示数据,发送ajax请求根据id查询当前检查项数据axios.get("/checkitem/findById.do?id=" + row.id).then((res) => {if(res.data.flag){//执行成功,进行回显,基于VUE的数据绑定来实现this.formData = res.data.data;}else{//查询失败,弹出提示this.$message.error(res.data.message);}});},
编辑完成后,点击确定按钮进行提交,进行表单校验。
//编辑完成后确认handleEdit() {//表单校验this.$refs['dataEditForm'].validate((valid) => {if(valid){//表单校验通过,提交编辑后的数据axios.post("/checkitem/edit.do",this.formData).then((res) =>{if(res.data.flag){//判断本次操作是否成功//弹出成功信息this.$message({type:"success",message:res.data.message});}else{//本次操作失败this.$message.error(res.data.message);}}).finally(() =>{//finally方法不管成功还是失败都会执行this.findPage();//关闭编辑窗口this.dialogFormVisible4Edit = false;});}else{//表单校验失败,不提交this.$message.error("表单校验失败!");return false;//后面代码不执行}});},
axios自带的方法:
//finally方法不管成功还是失败都会执行
2.Controller
首先显示要编辑的数据
//显示要编辑的检查项@RequestMapping("/findById")//匹配请求public Result findById(Integer id){try{//查询应该存在一个返回对象,返回对象是checkItemCheckItem checkItem = checkItemService.findById(id);return new Result(true, MessageConstant.QUERY_CHECKITEM_SUCCESS,checkItem);}catch(Exception e){e.printStackTrace();//服务调用失败return new Result(false, MessageConstant.QUERY_CHECKITEM_FAIL);}}
再实现检查项的编辑更新
//编辑检查项@RequestMapping("/edit")//匹配请求public Result delete(@RequestBody CheckItem checkItem){try{checkItemService.edit(checkItem);}catch(Exception e){e.printStackTrace();//服务调用失败return new Result(false, MessageConstant.EDIT_CHECKGROUP_FAIL);}return new Result(true, MessageConstant.EDIT_CHECKGROUP_SUCCESS);}
3.服务接口interface
4.服务实现类Impl
声明实现方法后,调用Dao方法
5.Dao接口
声明方法
6.Mapper文件
使用动态sql来实现编辑操作,如果传过来的参数不为空,则将参数进行更新
至此检查项功能完成