JavaWeb---综合案例
我只想卷死各位,或者被各位卷死,在此特别感谢黑马程序员的JavaWeb教程
项目源码:链接:https://pan.baidu.com/s/1iyXBAU4ct4dPDxQM52TCEA?pwd=y02r 提取码:y02r
本文摘要:
- 用Element组件编写一个好看的页面
- 能够完成查询所有功能
- 能够完成添加功能
- 能够理解 BaseServlet 思想
- 能够完成批量删除功能
- 能够完成分页查询功能
- 能够完成条件查询功能
- 完善了课程中没讲的修改和删除功能
案例页面
我们要完成如下页面效果
那我们现在就开始从上往下找组件来拼凑这个页面,在此之前,我们先创建一个brand_case
的项目,并在webapp
下新建brand.html,引入Element 的css、js文件 和 Vue.js
1 |
|
搜索表单的展示
Element-组件-Form表单-行内表单,这个组件可以完成我们的搜索表单,直接把代码Copy过来进行修改
将活动区域
换成当前状态
,并将区域一,区域二
换成启用,禁用
,审批人
换成企业名称
,然后在复制一份,改成品牌名称
data和methods都放到我们创建的vue对象中,同时将绑定的对象也改一下
1 | <!--这里的model要改成brand_-> |
表单部分的修改
1 | <el-form :inline="true" :model="brand" class="demo-form-inline"> |
data部分的修改
1 | brand: { |
methods部分的修改
1 | onSubmit() { |
打开浏览器测试,状态选启用,企业名称写华为技术有限公司,品牌名称写华为,控制台输出如下,符合我们的预期
id:“”
brandName: “华为”
companyName: “华为技术有限公司”
description: “”
ordered: “”
status: “1”
批量删除和修改的按钮
Element-组件-Button按钮-基础用法,这个组件可以给我们提供好看的按钮,直接Copy过来
1 | <el-row> |
新增对话框展示
删除按钮我们暂时不动,但是当我们点击新增
按钮时,需要弹出一个对话框让我们填写信息
Element-组件-Dialog对话框,这个组件可以帮我们达到目的
需要设置visible属性,它接收Boolean,当为true时显示 Dialog。Dialog 分为两个部分:body和footer,footer需要具名为footer的slot。title属性用于定义标题,它是可选的,默认值为空。最后,本例还展示了before-close的用法。
1 | <!--这里绑定了一个点击事件,当点击时,将dialogVisible设为true, |
由于我们要在对话框中再搞一个表单,所以我们继续去官网看看有没有合适的组件
Element-组件-典型表单可以完成我们的需求
1 | <!--绑定的model可以用我们之前写的brand_-> |
其实这里偷懒了,点击提交后,对话框不会自动关闭(后面会修改addBrand函数,就可以自动关闭了),而且在对话框中输入数据,搜索栏也会跟着变
1 | <el-dialog |
在浏览器访问页面,输入数据,点击提交之前,打开浏览器的控制台,得到以下输出,符合预期
id: “”
brandName: “EA”
companyName: “Apex”
description: “大逃杀”
ordered: “10”
status: “1”
表格展示
Element-组件-Table表格可以完成我们的需求
1 | <template> |
1 | <template> |
data部分
1 | tableData: [{ |
method部分直接照抄就行
1 | tableRowClassName({row, rowIndex}) { |
分页条展示
Element-组件-Pagination 分页可以帮我们完成需求
1 | <template> |
HTML部分
1 | <el-pagination |
data部分
1 | currentPage: 1 |
method部分直接照抄
完整代码如下
1 |
|
环境准备
工程准备
在Java目录下创建com.blog.mapper
,com.blog.pojo
,com.blog.service
,com.blog.util
,com.blog.web
这五个包
- 在mapper包下新建
BrandMapper
接口
1 | import java.util.List; |
- 在resource目录下新建
com/blog/mapper
路径,新建一个BrandMapper.xml
文件
1 |
|
- 在resource目录下新建
mybatis-config.xml
1 |
|
- 在pojo包下新建
Brand
类
1 | public class Brand { |
- 在util包下导入工具类
1 | public class SqlSessionFactoryUtils { |
- 在pom.xml中导入坐标
1 |
|
创建表
1 | -- 删除tb_brand表 |
查询所有功能
后端实现
dao方法实现
- 由于表中有些字段名和实体类中的属性名没有对应,所以需要在
com/itheima/mapper/BrandMapper.xml
映射配置文件中定义结果映射 ,使用resultMap
标签。映射配置文件内容如下:
1 |
|
- 在
com.blog.mapper.BrandMapper
接口中定义抽象方法,并使用@Select
注解编写SQL语句
1 | /** |
service方法实现
- 在
com.itheima.service
包下创建BrandService
接口,在该接口中定义查询所有的抽象方法
1 | public interface BrandService { |
- 并在
com.itheima.service
下再创建impl
包;impl
表示是放 service 层接口的实现类的包。 在该包下创建名为BrandServiceImpl
类
1 | public class BrandServiceImpl implements BrandService { |
- 为什么要创建BrandServiceImpl?
- 因为service定义了接口后,在 servlet 中就可以使用多态的形式创建Service实现类的对象
这里使用多态是因为方便解除Servlet
和service
的耦合。从上面的代码我们可以看到SelectAllServlet
类和BrandServiceImpl
类之间是耦合在一起的,如果后期BrandService
有其它的实现类(例如叫BrandServiceImpl1
),那就需要修改SelectAllServlet
类中的代码。后面学习了Spring
框架后就可以解除SelectAllServlet
类和BrandServiceImpl
的代码耦合。但现在还做不到解耦合,在这里只需要理解为什么定义接口即可。
- 因为service定义了接口后,在 servlet 中就可以使用多态的形式创建Service实现类的对象
servlet方法实现
- 在
com.itheima.web.servlet
包下定义名为SelectAllServlet
的查询所有的servlet
。该servlet
逻辑如下:- 调用service的
selectAll()
方法查询所有的品牌数据,并接口返回结果 - 将返回的结果转换为 json 数据
- 响应 json 数据
- 调用service的
1 |
|
测试后端程序
在浏览器输入访问 servlet 的资源路径 http://localhost:8080/brand_case/selectAllServlet
,如果没有报错,并能看到如下信息表明后端程序没有问题
[{“brandName”:“华为”,“companyName”:“华为技术有限公司”,“description”:“万物互联”,“id”:1,“ordered”:100,“status”:1,“statusStr”:“启用”},
前端实现
前端需要在页面加载完毕后发送 ajax 请求,所以发送请求的逻辑应该放在 mounted()
钩子函数中。而响应回来的数据需要赋值给表格绑定的数据模型
1 | mounted(){ |
添加功能
上图是添加数据的对话框,当点击 提交
按钮后就需要将数据提交到后端,并将数据保存到数据库中。
页面发送请求时,需要将输入框输入的内容提交给后端程序,而这里是以 json 格式进行传递的。
后端实现
dao方法实现
- 在
BrandMapper
接口中定义add()
添加方法,并使用@Insert
注解编写sql语句
1 | /** |
service方法实现
- 在
BrandService
接口中定义add()
添加数据的业务逻辑方法
1 | /** |
- 在
BrandServiceImpl
类中重写add()
方法,并进行业务逻辑实现
1 |
|
servlet方法实现
-
在
com.blog.web.servlet
包写定义名为AddServlet
的 Servlet。该 Servlet 的逻辑如下:- 接收页面提交的数据。页面到时候提交的数据是 json 格式的数据,所以此处需要使用输入流读取数据
- 将接收到的数据转换为
Brand
对象 - 调用 service 的
add()
方法进行添加的业务逻辑处理 - 给浏览器响应添加成功的标识,这里直接给浏览器响应
success
字符串表示成功
-
servlet 代码实现如下:
1 |
|
前端实现
我们之前给提交按钮的点击事件绑定了一个addBrand
函数,所以添加数据功能的逻辑代码应该写在 addBrand()
函数中。在此方法中需要发送异步请求并将表单中输入的数据作为参数进行传递。如下
1 | addBrand() { |
在 then
函数中的匿名函数是成功后的回调函数,而 resp.data
就可以获取到响应回来的数据,如果值是 success
表示数据添加成功。那么添加成功之后有哪些操作呢?
- 先将对话框关闭,设置dialogVisible为false,就可以关闭对话框了
1 | _this.dialogVisible = false |
- 重新查询数据,这部分代码其实就是刚刚查询所有的前端代码,将其封装成一个selectAll()函数
1 | var _this = this; |
- 给出提示信息,这部分其实是直接从ElementUI官网扒的代码,想用花里胡哨的可以戳我
1 | _this.$message({ |
servlet优化
问题导入
Web 层的 Servlet 个数太多了,不利于管理和编写。
每一个功能都需要定义一个 servlet
,一个模块需要实现增删改查功能,就需要4个 servlet
,模块一多就会造成servlet
泛滥。此时我们就想 servlet
能不能像 service
一样,一个模块只定义一个 servlet
,而每一个功能只需要在该 servlet
中定义对应的方法。例如下面代码:
1 |
|
而我们知道发送请求 servlet
,tomcat
会自动的调用 service()
方法,HttpServlet的service()方法如下,当我们访问该 servlet
时会根据请求方式将请求分发给 doGet()
或者 doPost()
等方法
1 | protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { |
那么我们也可以仿照这样请求分发的思想,在 service()
方法中根据具体的操作调用对应的方法,如:查询所有就调用 selectAll()
方法,添加企业信息就调用 add()
方法。
为了做到通用,我们定义一个通用的 servlet
类,再定义其他的 servlet
就不用继承 HttpServlet
,而是继承我们自定义的 BaseServlet
,在BaseServlet
中调用具体 servlet
(如BrandServlet
)中的对应方法。
1 | public class BaseServlet extends HttpServlet { |
BrandServlet定义修改如下
1 | public class BrandServlet extends BaseServlet{ |
那么如何在 BaseServlet
中调用对应的方法呢?比如查询所有就调用 selectAll()
方法。
可以规定在发送请求时,请求资源的二级路径(/brandServlet/selectAll)和需要调用的方法名相同,如:
查询所有数据的路径以后就需要写成: http://localhost:8080/brand_case/brand/selectAll
添加数据的路径以后就需要写成: http://localhost:8080/brand_case/brand/add
修改数据的路径以后就需要写成: http://localhost:8080/brand_case/brand/update
删除数据的路径以后就需要写成: http://localhost:8080/brand_case/brand/delete
这样的话,在 BaseServlet
中就需要获取到资源的二级路径作为方法名,然后调用该方法
1 | public class BaseServlet extends HttpServlet { |
通过上面代码发现根据方法名获取对应方法的 Method
对象时需要指定方法参数的字节码对象。解决这个问题,可以将方法的参数类型规定死,而方法中可能需要用到 request
对象和 response
对象,所以指定方法的参数为 HttpServletRequest
和 HttpServletResponse
,那么 BrandServlet
代码就可以改进为:
1 | public class BrandServlet extends BaseServlet{ |
BaseServlet代码可以改进为:
1 | public class BaseServlet extends HttpServlet { |
代码优化
后端优化
定义了 BaseServlet
后,针对品牌模块我们定义一个 BrandServlet
的 Servlet,并使其继承 BaseServlet
。在BrandServlet
中定义 以下功能的方法:
查询所有
功能:方法名声明为selectAll
,并将之前的SelectAllServlet
中的逻辑代码拷贝到该方法中添加数据
功能:方法名声明为add
,并将之前的AddServlet
中的逻辑代码拷贝到该方法中
具体代码如下:
1 |
|
前端优化
页面中之前发送的请求的路径都需要进行修改,selectAll()
和addBrand()
函数中发送异步请求的 url
应该改为http://localhost:8080/brand_case/brand/selectAll
和http://localhost:8080/brand_case/brand/add
1 | selectAll(){ |
批量删除
点击多条数据前的复选框就意味着要删除这些数据,而点击了 批量删除
按钮后,需要让用户确认一下,因为有可能是用户误操作的,当用户确定后需要给后端发送请求并携带者需要删除数据的多个id值,前端发送请求时需要将要删除的多个id值以json格式提交给后端
后端实现
dao方法实现
- 接口方法声明如下
1 | /** |
- 在
BrandMapper.xml
映射配置文件中添加 statement,需要用到动态sql的知识,在前面的文章已经详细说过了
1 | <delete id="deleteByIdIs"> |
service方法实现
- 在
BrandService
接口中定义deleteByIds()
批量删除的业务逻辑方法
1 | /** |
- 在
BrandServiceImpl
类中重写deleteByIds()
方法,并进行业务逻辑实现
1 |
|
servlet方法实现
-
在
BrandServlet
类中定义deleteByIds()
方法。而该方法的逻辑如下:- 接收页面提交的数据。页面到时候提交的数据是 json 格式的数据,所以此处需要使用输入流读取数据
- 将接收到的数据转换为
int[]
数组 - 调用 service 的
deleteByIds()
方法进行批量删除的业务逻辑处理 - 给浏览器响应添加成功的标识,这里直接给浏览器响应
success
字符串表示成功
-
servlet 中
deleteByIds()
方法代码实现如下:
1 | /** |
前端实现
- 先去ElementUI官网看看复选框都有什么属性,发现表单绑定了一个事件
@selection-change="handleSelectionChange
1 | handleSelectionChange(val) { |
-
该事件是当选择项发生变化时会触发。该事件绑定了
handleSelectionChange
函数,而该函数有一个参数val
,该参数是获取选中行的数据,选中多行也就是相当于选中了一个brand数组,我们可以通过遍历brand数组来获取其id,然后使用 axios 发送异步请求并经刚刚获取到的存储所有的 id 数组作为请求参数,那么现在就分析完毕了,开始敲代码 -
给批量删除绑定一个点击事件,并绑定触发时的调用函数
deleteByIds
1 | <el-button @click="deleteByIds" type="danger" plain>批量删除</el-button> |
- 我们要在
deleteByIds
函数中遍历选中的brand数组,也就是遍历this.multipleSelection
,获取brand.id
,将其加入到id数组,所以我们先在Vue对象的data中添加selectedIds: []
1 | //获取选中的id值,并加入到selectedIds数组中 |
- 由于删除操作是一个危险的操作,所以在删除之前,我们需要让用户确认一下是否删除,要完成这个需求,我们继续去ElementUI中找个组件,MessageBox弹框
1 | <template> |
- 直接把这个open函数的函数体搬走就可以,修改完成的
deleteByIds
函数代码如下
1 | deleteByIds() { |
分页查询
我们之前做的 查询所有
功能中将数据库中所有的数据查询出来并展示到页面上,试想如果数据库中的数据有很多(假设有十几万条)的时候,将数据全部展示出来肯定不现实,那如何解决这个问题呢?几乎所有的网站都会使用分页解决这个问题。每次只展示一页的数据,比如一页展示10条数据,如果还想看其他的数据,可以通过点击页码进行查询
分析
分页查询sql
- 分页查询也是从数据库进行查询的,所以我们要分页对应的SQL语句应该怎么写。分页查询使用
LIMIT
关键字,格式为:LIMIT 开始索引 每页显示的条数
。以后前端页面在发送请求携带参数时,它并不明确开始索引是什么,但是它知道查询第几页。所以开始索引
需要在后端进行计算,计算的公式是 :开始索引 = (当前页码 - 1)* 每页显示条数 - 比如查询第一页的数据的 SQL 语句是:
1 | select * from tb_brand limit 0,5; |
- 查询第二页的数据的 SQL 语句是:
1 | select * from tb_brand limit 5,5; |
- 查询第三页的数据的 SQL 语句是:
1 | select * from tb_brand limit 10,5; |
前后端数据分析
分页查询功能时候比较复杂的,所以我们要先分析清楚以下两个问题:
-
前端需要传递什么参数给后端
根据上一步对分页查询 SQL 语句分析得出,前端需要给后端两个参数- 当前页码 :currentPage
- 每页显示条数:pageSize
-
后端需要响应什么数据给前端
- 当前页需要展示的数据。我们在后端一般会存储到 List 集合中
- 总共记录数。在上图页面中需要展示总的记录数,所以这部分数据也需要。总的页面 ElementUI 的分页组件会自动计算,我们不需要关心
- 将以上两部分封装到 PageBean 对象中,并将该对象转换为 json 格式的数据响应回给浏览器
-
通过上面的分析我们需要先在
pojo
包下创建PageBean
类,为了做到通用性会将其定义成泛型类,代码如下:
1 | //分页查询的JavaBean |
后端实现
dao方法实现
- 在
BrandMapper
接口中定义selectByPage()
方法进行分页查询,代码如下:
1 | /** |
- 在
BrandMapper
接口中定义selectTotalCount()
方法进行统计记录数,代码如下:
1 | /** |
service方法实现
在 BrandService
接口中定义 selectByPage()
分页查询数据的业务逻辑方法
1 | /** |
在 BrandServiceImpl
类中重写 selectByPage()
方法,并进行业务逻辑实现
1 |
|
servlet方法实现
- 在
BrandServlet
类中定义selectByPage()
方法。而该方法的逻辑如下:- 获取页面提交的
当前页码
和每页显示条目数
两个数据。这两个参数是在url后进行拼接的,格式是url?currentPage=1&pageSize=5
。获取这 样的参数需要使用requet.getparameter()
方法获取。 - 调用 service 的
selectByPage()
方法进行分页查询的业务逻辑处理 - 将查询到的数据转换为 json 格式的数据
- 响应 json 数据
- 获取页面提交的
- servlet 中
selectByPage()
方法代码实现如下:
1 | public void selectByPage(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { |
测试
在浏览器上地址栏输入 http://localhost:8080/brand_case/brand/selectByPage?currentPage=1&pageSize=5
,可以查询到数据
前端实现
selectAll 代码改进
selectAll()
函数之前是查询所有数据,现需要改成分页查询。 请求路径应改为 http://localhost:8080/brand_case/brand/selectByPage?currentPage=1&pageSize=5
,而 currentPage
和 pageSize
是需要携带的参数,分别是 当前页码
和 每页显示的条目数
。
刚才我们对后端代码进行测试可以看出响应回来的数据,所以在异步请求的成功回调函数(then
中的匿名函数)中给页面表格的数据模型赋值。整体代码如下
1 | selectAll() { |
改变当前页的条目数和当前页码
先来看看分页条的代码
@size-change
就是每页显示的条目数发生变化时会触发的事件,而该事件绑定了一个 handleSizeChange
函数
@current-change
就是页码发生变化时会触发的事件,而该事件绑定了一个 handleSizeChange
函数
1 | <el-pagination |
我们只需要在这两个函数中重新设置当前页的条目数和当前页码,然后调用selectAll
函数重新分页查询数据
1 | handleSizeChange(val) { |
条件查询
要做条件查询功能,先明确以下三个问题
- 3个条件之间什么关系?
- 同时满足,所用 SQL 中多个条件需要使用 and 关键字连接
- 3个条件必须全部填写吗?
- 不需要。想根据哪儿个条件查询就写那个,所以这里需要使用动态 sql 语句
- 条件查询需要分页吗?
- 需要
后端实现
dao实现
在 BrandMapper
接口中定义 selectByPageAndCondition()
方法 和 selectTotalCountByCondition
方法,用来进行条件分页查询功能,方法如下:
1 | /** |
参数:
begin
分页查询的起始索引size
分页查询的每页条目数brand
用来封装条件的对象
由于这是一个复杂的查询语句,需要使用动态sql;所以我们在映射配置文件中书写 sql 语句。brand_name
字段和 company_name
字段需要进行模糊查询,所以需要使用 %
占位符。映射配置文件中 statement 书写如下:
1 | <!--查询满足条件的数据并进行分页--> |
service实现
在 BrandService
接口中定义 selectByPageAndCondition()
分页查询数据的业务逻辑方法
1 | /** |
在 BrandServiceImpl
类中重写 selectByPageAndCondition()
方法,并进行业务逻辑实现
1 |
|
servlet实现
在 BrandServlet
类中定义 selectByPageAndCondition()
方法。而该方法的逻辑如下:
-
获取页面提交的
当前页码
和每页显示条目数
两个数据。这两个参数是在url后进行拼接的,格式是url?currentPage=1&pageSize=5
。获取这样的参数需要使用requet.getparameter()
方法获取。 -
获取页面提交的
条件数据
,并将数据封装到一个Brand对象中。由于这部分数据到时候是需要以 json 格式进行提交的,所以我们需要通过流获取数据,具体代码如下:1
2
3
4
5
6// 获取查询条件对象
BufferedReader br = request.getReader();
String params = br.readLine();//json字符串
//转为 Brand
Brand brand = JSON.parseObject(params, Brand.class); -
调用 service 的
selectByPageAndCondition()
方法进行分页查询的业务逻辑处理 -
将查询到的数据转换为 json 格式的数据
-
响应 json 数据
servlet 中 selectByPageAndCondition()
方法代码实现如下:
1 | /** |
前端实现
前端代码我们从以下几方面实现:
-
查询表单绑定查询条件对象模型
这一步在页面上已经实现了,页面代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<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="onSubmit">查询</el-button>
</el-form-item>
</el-form> -
点击查询按钮查询数据
从上面的代码可以看到给查询
按钮绑定了onSubmit()
函数,而在onSubmit()
函数中只需要调用selectAll()
函数进行条件分页查询。 -
改进 selectAll() 函数
子页面加载完成后发送异步请求,需要携带当前页码、每页显示条数、查询条件对象。接下来先对携带的数据进行说明:当前页码
和每页显示条数
这两个参数我们会拼接到 URL 的后面查询条件对象
这个参数需要以 json 格式提交给后端程序- 修改
selectAll()
函数逻辑为
1
2
3
4
5
6
7
8
9
10
11
12
13var _this = this;
axios({
method:"post",
url:"http://localhost:8080/brand_case/brand/selectByPageAndCondition?currentPage="+this.currentPage+"&pageSize="+this.pageSize,
data:this.brand
}).then(function (resp) {
//设置表格数据
_this.tableData = resp.data.rows; // {rows:[],totalCount:100}
//设置总记录数
_this.totalCount = resp.data.totalCount;
})
前端代码优化
咱们已经将所有的功能实现完毕。而针对前端代码中的发送异步请求的代码,如下
1 | var _this = this; |
需要在成功的回调函数(也就是then
函数中的匿名函数)中使用this,都需要在外边使用 _this
记录一下 this
所指向的对象;因为在外边的 this
表示的是 Vue 对象,而回调函数中的 this
表示的不是 vue 对象。这里我们可以使用 ECMAScript6
中的新语法(箭头函数)来简化这部分代码,如上面的代码可以简化为:
1 | axios({ |
箭头函数语法:
1 | (参数) => { |
箭头函数的作用:
替换(简化)匿名函数。
补充
由于课程中没有删除和修改的功能,所以我这里完善了一下
删除功能
删除功能的难点在于如果获取本行数据的id,但成功获取id之后的操作就与批量删除的操作一样了
批量删除是选中多行数据,然后将多行数据的id放到ids数组中,那么单行数据就只需要将当前行的id放到ids数组中
具体操作就是this.selectedIds[0] = this.currentRow.id;
,前端代码也只需要将for循环替换掉
那现在我们只需要复制一份deleteByIds
,然后改个名,将for循环替换掉,就大功告成了
1 | deleteById() { |
如何获取当前行数据
其实我们在写前端页面的时候,就已经遇到过了,那现在我们仔细看看
Table 组件提供了单选的支持,只需要配置highlight-current-row属性即可实现单选。之后由current-change事件来管理选中时触发的事件,它会传入currentRow,oldCurrentRow。如果需要显示索引,可以增加一列el-table-column,设置type属性为index即可显示从 1 开始的索引号。
1 | <template> |
提取一下信息就是我们要在table中配置highlight-current-row
属性,current-change
事件,和事件绑定的handleCurrentChange
函数,然后在Vue的data中配置currentRow
属性(默认为null),然后就大功告成了
- table标签的修改如下
1 | <el-table |
- data中新增属性(示例代码中已经提供好了)
1 | currentRow: null |
- methods中新增方法(示例代码中已经提供好了,直接CV,我这里改了个名)
1 | handleCurrentChangeRow(val) { |
修改功能
- 修改功能依旧是分为
回显
和修改
两部分 - 修改功能的需求就是当我们点击
修改
按钮(给修改按钮绑定echo()
回显函数)时,会弹出一个对话框,里面是已经填好了的品牌信息,我们只需要修改我们需要改的部分,其他部分不用动,然后点击提交按钮
(给提交按钮绑定update()
更新函数),完成修改功能
前端页面
- 前端页面我们直接照抄新增页面即可,注意将设置
:visible.sync="updateVisible"
,同时在Vue对象的data中,新增updateVisible属性updateVisible: false
,该属性默认为false,用来控制修改对话框是否显示
1 | <!--对话框弹出修改品牌--> |
回显功能
- 回显功能是要当我们点击
修改
按钮时,弹出对话框,同时显示原有数据,那我们就给修改按钮的点击事件绑定一个回显函数 - 而回显函数的功能就是刚刚说的,弹出对话框(设置
updateVisible为true
),显示原有数据(将本行数据赋给brand即可,因为修改对话框已经绑定了brand模型) - 代码如下
1 | echo(){ |
修改功能
######## dao实现
- 接口方法声明如下
1 | /** |
######## service实现
- 在
BrandService
接口中定义update()
更新数据的业务逻辑方法
1 | /** |
- 在
BrandServiceImpl
类中重写update()
方法,并进行业务逻辑实现
1 |
|
######## servlet实现
- servlet 中
update()
方法代码实现如下:
1 | public void update(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { |
######## 前端实现
- 前面当我们点击
修改
按钮时,已经帮我们弹出对话框,且对话框中有原有的数据,当我们修改完毕之后,点击提交
按钮,就会帮我们完成更新操作
那现在我们只需要来写一个update()
函数就完事儿了,而update()函数和addBrand()函数几乎没有区别,只需要将url改成update,然后提示信息改一下,就大功告成了(区别就是底层的SQL语句不一样,addBrand()执行insert,update()执行update)
1 | update() { |
- 至此我们就完成了课程中没讲的修改和删除功能啦
完结撒花
JavaWeb的学习到此就结束了,后面就是学一些主流的框架了,最近先好好复盘一遍JavaWeb巩固基础再往后学。