4.3 JSP 缺点
通过上面的案例,我们可以看到 JSP 的很多缺点。
由于 JSP页面内,既可以定义 HTML 标签,又可以定义 Java代码,造成了以下问题:
- 书写麻烦:特别是复杂的页面
既要写 HTML 标签,还要写 Java 代码
- 阅读麻烦
上面案例的代码,相信你后期再看这段代码时还需要花费很长的时间去梳理
-
复杂度高:运行需要依赖于各种环境,JRE,JSP容器,JavaEE…
-
占内存和磁盘:JSP会自动生成.java和.class文件占磁盘,运行的是.class文件占内存
-
调试困难:出错后,需要找到自动生成的.java文件进行调试
-
不利于团队协作:前端人员不会 Java,后端人员不精 HTML
如果页面布局发生变化,前端工程师对静态页面进行修改,然后再交给后端工程师,由后端工程师再将该页面改为 JSP 页面
由于上述的问题, ==JSP 已逐渐退出历史舞台,==以后开发更多的是使用 HTML + Ajax 来替代。Ajax 是我们后续会重点学习的技术。有个这个技术后,前端工程师负责前端页面开发,而后端工程师只负责前端代码开发。下来对技术的发展进行简单的说明
-
第一阶段:使用
servlet
即实现逻辑代码编写,也对页面进行拼接。这种模式我们之前也接触过 -
第二阶段:随着技术的发展,出现了
JSP
,人们发现JSP
使用起来比Servlet
方便很多,但是还是要在JSP
中嵌套Java
代码,也不利于后期的维护 -
第三阶段:使用
Servlet
进行逻辑代码开发,而使用JSP
进行数据展示
- 第四阶段:使用
servlet
进行后端逻辑代码开发,而使用HTML
进行数据展示。而这里面就存在问题,HTML
是静态页面,怎么进行动态数据展示呢?这就是ajax
的作用了。
那既然 JSP 已经逐渐的退出历史舞台,那我们为什么还要学习 JSP
呢?原因有两点:
-
一些公司可能有些老项目还在用
JSP
,所以要求我们必须懂JSP
-
我们如果不经历这些复杂的过程,就不能体现后面阶段开发的简单
接下来我们来学习第三阶段,使用 EL表达式
和 JSTL
标签库替换 JSP
中的 Java
代码。
5.1 概述
EL(全称Expression Language )表达式语言,用于简化 JSP 页面内的 Java 代码。
EL 表达式的主要作用是 获取数据。其实就是从域对象中获取数据,然后将数据展示在页面上。
而 EL 表达式的语法也比较简单,== e x p r e s s i o n = = 。 例 如 : {expression}== 。例如: expression==。例如:{brands} 就是获取域中存储的 key 为 brands 的数据。
5.2 代码演示
- 定义servlet,在 servlet 中封装一些数据并存储到 request 域对象中并转发到
el-demo.jsp
页面。
@WebServlet(“/demo1”)
public class ServletDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 准备数据
List brands = new ArrayList();
brands.add(new Brand(1,“三只松鼠”,“三只松鼠”,100,“三只松鼠,好吃不上火”,1));
brands.add(new Brand(2,“优衣库”,“优衣库”,200,“优衣库,服适人生”,0));
brands.add(new Brand(3,“小米”,“小米科技有限公司”,1000,“为发烧而生”,1));
//2. 存储到request域中
request.setAttribute(“brands”,brands);
//3. 转发到 el-demo.jsp
request.getRequestDispatcher(“/el-demo.jsp”).forward(request,response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
注意: 此处需要用转发,因为转发才可以使用 request 对象作为域对象进行数据共享
- 在
el-demo.jsp
中通过 EL表达式 获取数据
<%@ page contentType=“text/html;charset=UTF-8” language=“java” %>
${brands}
- 在浏览器的地址栏输入
http://localhost:8080/jsp-demo/demo1
,页面效果如下:
5.3 域对象
JavaWeb中有四大域对象,分别是:
-
page:当前页面有效
-
request:当前请求有效
-
session:当前会话有效
-
application:当前应用有效
el 表达式获取数据,会依次从这4个域中寻找,直到找到为止。而这四个域对象的作用范围如下图所示
例如: ${brands},el 表达式获取数据,会先从page域对象中获取数据,如果没有再到 requet 域对象中获取数据,如果再没有再到 session 域对象中获取,如果还没有才会到 application 中获取数据。
6.1 概述
JSP标准标签库(Jsp Standarded Tag Library) ,使用标签取代JSP页面上的Java代码。如下代码就是JSTL标签
<c:if test=“${flag == 1}”>
男
</c:if>
<c:if test=“${flag == 2}”>
女
</c:if>
上面代码看起来是不是比 JSP 中嵌套 Java 代码看起来舒服好了。而且前端工程师对标签是特别敏感的,他们看到这段代码是能看懂的。
JSTL 提供了很多标签,如下图
我们只对两个最常用的标签进行讲解,<c:forEach>
标签和 <c:if>
标签。
JSTL 使用也是比较简单的,分为如下步骤:
- 导入坐标
jstl
jstl
1.2
taglibs
standard
1.1.2
- 在JSP页面上引入JSTL标签库
<%@ taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core” %>
- 使用标签
6.2 if 标签
<c:if>
:相当于 if 判断
- 属性:test,用于定义条件表达式
<c:if test=“${flag == 1}”>
男
</c:if>
<c:if test=“${flag == 2}”>
女
</c:if>
代码演示:
- 定义一个
servlet
,在该servlet
中向 request 域对象中添加 键是status
,值为1
的数据
@WebServlet(“/demo2”)
public class ServletDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 存储数据到request域中
request.setAttribute(“status”,1);
//2. 转发到 jstl-if.jsp
数据request.getRequestDispatcher(“/jstl-if.jsp”).forward(request,response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
- 定义
jstl-if.jsp
页面,在该页面使用<c:if>
标签
<%@ page contentType=“text/html;charset=UTF-8” language=“java” %>
<%@ taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core” %>
<%–
c:if:来完成逻辑判断,替换java if else
–%>
<c:if test=“${status ==1}”>
启用
</c:if>
<c:if test=“${status ==0}”>
禁用
</c:if>
注意: 在该页面已经要引入 JSTL核心标签库
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
6.3 forEach 标签
<c:forEach>
:相当于 for 循环。java中有增强for循环和普通for循环,JSTL 中的 <c:forEach>
也有两种用法
6.3.1 用法一
类似于 Java 中的增强for循环。涉及到的 <c:forEach>
中的属性如下
-
items:被遍历的容器
-
var:遍历产生的临时变量
-
varStatus:遍历状态对象
如下代码,是从域对象中获取名为 brands 数据,该数据是一个集合;遍历遍历,并给该集合中的每一个元素起名为 brand
,是 Brand对象。在循环里面使用 EL表达式获取每一个Brand对象的属性值
<c:forEach items=“${brands}” var=“brand”>
${brand.id} ${brand.brandName} ${brand.companyName} ${brand.description}</c:forEach>
代码演示:
-
servlet
还是使用之前的名为ServletDemo1
。 -
定义名为
jstl-foreach.jsp
页面,内容如下:
<%@ page contentType=“text/html;charset=UTF-8” language=“java” %>
<%@ taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core” %>
<c:forEach items=“${brands}” var=“brand” varStatus=“status”>
<%–${brand.id}–%>
${status.count} ${brand.brandName} ${brand.companyName} ${brand.ordered} ${brand.description}<c:if test=“${brand.status == 1}”>
启用</c:if>
<c:if test=“${brand.status != 1}”>
禁用</c:if>
修改 删除</c:forEach>
6.3.2 用法二
类似于 Java 中的普通for循环。涉及到的 <c:forEach>
中的属性如下
-
begin:开始数
-
end:结束数
-
step:步长
实例代码:
从0循环到10,变量名是 i
,每次自增1
<c:forEach begin=“0” end=“10” step=“1” var=“i”>
${i}
</c:forEach>
MVC 模式和三层架构是一些理论的知识,将来我们使用了它们进行代码开发会让我们代码维护性和扩展性更好。
7.1 MVC模式
MVC 是一种分层开发的模式,其中:
-
M:Model,业务模型,处理业务
-
V:View,视图,界面展示
-
C:Controller,控制器,处理请求,调用模型和视图
控制器(serlvlet)用来接收浏览器发送过来的请求,控制器调用模型(JavaBean)来获取数据,比如从数据库查询数据;控制器获取到数据后再交由视图(JSP)进行数据展示。
MVC 好处:
-
职责单一,互不影响。每个角色做它自己的事,各司其职。
-
有利于分工协作。
-
有利于组件重用
7.2 三层架构
三层架构是将我们的项目分成了三个层面,分别是 表现层
、业务逻辑层
、数据访问层
。
-
数据访问层:对数据库的CRUD基本操作
-
业务逻辑层:对业务逻辑进行封装,组合数据访问层层中基本功能,形成复杂的业务逻辑功能。例如
注册业务功能
,我们会先调用数据访问层
的selectByName()
方法判断该用户名是否存在,如果不存在再调用数据访问层
的insert()
方法进行数据的添加操作 -
表现层:接收请求,封装数据,调用业务逻辑层,响应数据
而整个流程是,浏览器发送请求,表现层的Servlet接收请求并调用业务逻辑层的方法进行业务逻辑处理,而业务逻辑层方法调用数据访问层方法进行数据的操作,依次返回到serlvet,然后servlet将数据交由 JSP 进行展示。
三层架构的每一层都有特有的包名称:
-
表现层:
com.itheima.controller
或者com.itheima.web
-
业务逻辑层:
com.itheima.service
-
数据访问层:
com.itheima.dao
或者com.itheima.mapper
后期我们还会学习一些框架,不同的框架是对不同层进行封装的
7.3 MVC 和 三层架构
通过 MVC 和 三层架构 的学习,有些人肯定混淆了。那他们有什么区别和联系?
如上图上半部分是 MVC 模式,上图下半部分是三层架构。 MVC 模式
中的 C(控制器)和 V(视图)就是 三层架构
中的表现层,而 MVC 模式
中的 M(模型)就是 三层架构
中的 业务逻辑层 和 数据访问层。
可以将 MVC 模式
理解成是一个大的概念,而 三层架构
是对 MVC 模式
实现架构的思想。 那么我们以后按照要求将不同层的代码写在不同的包下,每一层里功能职责做到单一,将来如果将表现层的技术换掉,而业务逻辑层和数据访问层的代码不需要发生变化。
需求:完成品牌数据的增删改查操作
这个功能我们之前一直在做,而这个案例是将今天学习的所有的内容(包含 MVC模式 和 三层架构)进行应用,并将整个流程贯穿起来。
8.1 环境准备
环境准备工作,我们分以下步骤实现:
-
创建新的模块 brand_demo,引入坐标
-
创建三层架构的包结构
-
数据库表 tb_brand
-
实体类 Brand
-
MyBatis 基础环境
-
Mybatis-config.xml
-
BrandMapper.xml
-
BrandMapper接口
8.1.1 创建工程
创建新的模块 brand_demo,引入坐标。我们只要分析出要用到哪儿些技术,那么需要哪儿些坐标也就明确了
-
需要操作数据库。mysql的驱动包
-
要使用mybatis框架。mybaits的依赖包
-
web项目需要用到servlet和jsp。servlet和jsp的依赖包
-
需要使用 jstl 进行数据展示。jstl的依赖包
pom.xml
内容如下:
<project xmlns=“http://maven.apache.org/POM/4.0.0”
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=“http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd”>
4.0.0
org.example
brand-demo
1.0-SNAPSHOT
war
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
org.mybatis
mybatis
3.5.5
mysql
mysql-connector-java
5.1.34
javax.servlet
javax.servlet-api
3.1.0
provided
javax.servlet.jsp
jsp-api
2.2
provided
jstl
jstl
1.2
taglibs
standard
1.1.2
org.apache.tomcat.maven
tomcat7-maven-plugin
2.2
8.1.2 创建包
创建不同的包结构,用来存储不同的类。包结构如下
8.1.3 创建表
– 删除tb_brand表
drop table if exists tb_brand;
– 创建tb_brand表
create table tb_brand
(
– id 主键
id int primary key auto_increment,
– 品牌名称
brand_name varchar(20),
– 企业名称
company_name varchar(20),
– 排序字段
ordered int,
– 描述信息
description varchar(100),
– 状态:0:禁用 1:启用
status int
);
– 添加数据
insert into tb_brand (brand_name, company_name, ordered, description, status)
values (‘三只松鼠’, ‘三只松鼠股份有限公司’, 5, ‘好吃不上火’, 0),
(‘华为’, ‘华为技术有限公司’, 100, ‘华为致力于把数字世界带入每个人、每个家庭、每个组织,构建万物互联的智能世界’, 1),
(‘小米’, ‘小米科技有限公司’, 50, ‘are you ok’, 1);
8.1.4 创建实体类
在 pojo
包下创建名为 Brand
的类。
public class Brand {
// id 主键
private Integer id;
// 品牌名称
private String brandName;
// 企业名称
private String companyName;
// 排序字段
private Integer ordered;
// 描述信息
private String description;
// 状态:0:禁用 1:启用
private Integer status;
public Brand() {
}
public Brand(Integer id, String brandName, String companyName, String description) {
this.id = id;
this.brandName = brandName;
this.companyName = companyName;
this.description = description;
}
public Brand(Integer id, String brandName, String companyName, Integer ordered, String description, Integer status) {
this.id = id;
this.brandName = brandName;
this.companyName = companyName;
this.ordered = ordered;
this.description = description;
this.status = status;
}
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;
}
@Override
public String toString() {
return “Brand{” +
“id=” + id +
“, brandName='” + brandName + ‘’’ +
“, companyName='” + companyName + ‘’’ +
“, ordered=” + ordered +
“, description='” + description + ‘’’ +
“, status=” + status +
‘}’;
}
}
8.1.5 准备mybatis环境
定义核心配置文件 Mybatis-config.xml
,并将该文件放置在 resources
下
在 resources
下创建放置映射配置文件的目录结构 com/itheima/mapper
,并在该目录下创建映射配置文件 BrandMapper.xml
8.2 查询所有
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-818Vau8L-1642765224821)(assets/image-20210818174441917.png)]
当我们点击 index.html
页面中的 查询所有
这个超链接时,就能查询到上图右半部分的数据。
对于上述的功能,点击 查询所有
超链接是需要先请后端的 servlet
,由 servlet
跳转到对应的页面进行数据的动态展示。而整个流程如下图:
8.2.1 编写BrandMapper
在 mapper
包下创建创建 BrandMapper
接口,在接口中定义 selectAll()
方法
/**
-
查询所有
-
@return
*/
@Select(“select * from tb_brand”)
List selectAll();
8.2.2 编写工具类
在 com.itheima
包下创建 utils
包,并在该包下创建名为 SqlSessionFactoryUtils
工具类
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;
}
}
8.2.3 编写BrandService
在 service
包下创建 BrandService
类
public class BrandService {
SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory();
/**
-
查询所有
-
@return
*/
public List selectAll(){
//调用BrandMapper.selectAll()
//2. 获取SqlSession
SqlSession sqlSession = factory.openSession();
//3. 获取BrandMapper
BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
//4. 调用方法
List brands = mapper.selectAll();
sqlSession.close();
return brands;
}
}
8.2.4 编写Servlet
在 web
包下创建名为 SelectAllServlet
的 servlet
,该 servlet
的逻辑如下:
-
调用
BrandService
的selectAll()
方法进行业务逻辑处理,并接收返回的结果 -
将上一步返回的结果存储到
request
域对象中 -
跳转到
brand.jsp
页面进行数据的展示
具体的代码如下:
@WebServlet(“/selectAllServlet”)
public class SelectAllServlet extends HttpServlet {
private BrandService service = new BrandService();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 调用BrandService完成查询
List brands = service.selectAll();
//2. 存入request域中
request.setAttribute(“brands”,brands);
//3. 转发到brand.jsp
request.getRequestDispatcher(“/brand.jsp”).forward(request,response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
8.2.5 编写brand.jsp页面
将资料 资料\2. 品牌增删改查案例\静态页面
下的 brand.html
页面拷贝到项目的 webapp
目录下,并将该页面改成 brand.jsp
页面,而 brand.jsp
页面在表格中使用 JSTL
和 EL表达式
从request域对象中获取名为 brands
的集合数据并展示出来。页面内容如下:
<%@ page contentType=“text/html;charset=UTF-8” language=“java” %>
<%@ taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core” %>
<c:forEach items=“${brands}” var=“brand” varStatus=“status”>
<%–${brand.id}–%>
${status.count} ${brand.brandName} ${brand.companyName} ${brand.ordered} ${brand.description}<c:if test=“${brand.status == 1}”>
启用</c:if>
<c:if test=“${brand.status != 1}”>
禁用</c:if>
修改 删除</c:forEach>
8.2.6 测试
启动服务器,并在浏览器输入 http://localhost:8080/brand-demo/index.html
,看到如下 查询所有
的超链接,点击该链接就可以查询出所有的品牌数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zc1SpOxe-1642765224821)(assets/image-20210818182952394.png)]
为什么出现这个问题呢?是因为查询到的字段名和实体类对象的属性名没有一一对应。相比看到这大家一定会解决了,就是在映射配置文件中使用 resultMap
标签定义映射关系。映射配置文件内容如下:
并且在 BrandMapper
接口中的 selectAll()
上使用 @ResuleMap
注解指定使用该映射
/**
-
查询所有
-
@return
*/
@Select(“select * from tb_brand”)
@ResultMap(“brandResultMap”)
List selectAll();
重启服务器,再次访问就能看到我们想要的数据了
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-10DKz3WO-1642765224822)(assets/image-20210819190221889.png)]
8.3 添加
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I0RxLddH-1642765224822)(assets/image-20210819192049571.png)]
上图是做 添加 功能流程。点击 新增
按钮后,会先跳转到 addBrand.jsp
新增页面,在该页面输入要添加的数据,输入完毕后点击 提交
按钮,需要将数据提交到后端,而后端进行数据添加操作,并重新将所有的数据查询出来。整个流程如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ldr0QnFL-1642765224822)(assets/image-20210819192737982.png)]
接下来我们根据流程来实现功能:
8.3.1 编写BrandMapper方法
在 BrandMapper
接口,在接口中定义 add(Brand brand)
方法
@Insert(“insert into tb_brand values(null,#{brandName},#{companyName},#{ordered},#{description},#{status})”)
void add(Brand brand);
8.3.2 编写BrandService方法
在 BrandService
类中定义添加品牌数据方法 add(Brand brand)
/**
-
添加
-
@param brand
*/
public void add(Brand brand){
//2. 获取SqlSession
SqlSession sqlSession = factory.openSession();
//3. 获取BrandMapper
BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
//4. 调用方法
mapper.add(brand);
//提交事务
sqlSession.commit();
//释放资源
sqlSession.close();
}
8.3.3 改进brand.jsp页面
我们需要在该页面表格的上面添加 新增
按钮
并给该按钮绑定单击事件,当点击了该按钮需要跳转到 brand.jsp
添加品牌数据的页面
==注意:==该
script
标签建议放在body
结束标签前面。
8.3.4 编写addBrand.jsp页面
从资料 资料\2. 品牌增删改查案例\静态页面
中将 addBrand.html
页面拷贝到项目的 webapp
下,并改成 addBrand.jsp
动态页面
<%@ page contentType=“text/html;charset=UTF-8” language=“java” %>
添加品牌
品牌名称:
企业名称:
排序:
描述信息:
状态:
禁用
启用
8.3.5 编写servlet
在 web
包下创建 AddServlet
的 servlet
,该 servlet
的逻辑如下:
-
设置处理post请求乱码的字符集
-
接收客户端提交的数据
-
将接收到的数据封装到
Brand
对象中 -
调用
BrandService
的add()
方法进行添加的业务逻辑处理 -
跳转到
selectAllServlet
资源重新查询数据
具体的代码如下:
@WebServlet(“/addServlet”)
public class AddServlet extends HttpServlet {
private BrandService service = new BrandService();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//处理POST请求的乱码问题
request.setCharacterEncoding(“utf-8”);
//1. 接收表单提交的数据,封装为一个Brand对象
String brandName = request.getParameter(“brandName”);
String companyName = request.getParameter(“companyName”);
String ordered = request.getParameter(“ordered”);
String description = request.getParameter(“description”);
String status = request.getParameter(“status”);
//封装为一个Brand对象
Brand brand = new Brand();
brand.setBrandName(brandName);
brand.setCompanyName(companyName);
brand.setOrdered(Integer.parseInt(ordered));
brand.setDescription(description);
brand.setStatus(Integer.parseInt(status));
//2. 调用service 完成添加
service.add(brand);
//3. 转发到查询所有Servlet
request.getRequestDispatcher(“/selectAllServlet”).forward(request,response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
8.3.6 测试
点击 brand.jsp
页面的 新增
按钮,会跳转到 addBrand.jsp
页面
点击 提交
按钮,就能看到如下页面,里面就包含我们刚添加的数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E5drez4I-1642765224822)(assets/image-20210819220738074.png)]
8.4 修改
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GtzXwVb7-1642765224823)(assets/image-20210819223202473.png)]
点击每条数据后面的 编辑
按钮会跳转到修改页面,如下图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vXfaDAAT-1642765224823)(assets/image-20210819223314230.png)]
在该修改页面我们可以看到将 编辑
按钮所在行的数据 回显 到表单,然后需要修改那个数据在表单中进行修改,然后点击 提交
的按钮将数据提交到后端,后端再将数据存储到数据库中。
从上面的例子我们知道 修改
功能需要从两方面进行实现,数据回显和修改操作。
8.4.1 回显数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bwmLoI8u-1642765224824)(assets/image-20210819223830713.png)]
上图就是回显数据的效果。要实现这个效果,那当点击 修改
按钮时不能直接跳转到 update.jsp
页面,而是需要先带着当前行数据的 id
请求后端程序,后端程序根据 id
查询数据,将数据存储到域对象中跳转到 update.jsp
页面进行数据展示。整体流程如下
8.4.1.1 编写BrandMapper方法
在 BrandMapper
接口,在接口中定义 selectById(int id)
方法
/**
-
根据id查询
-
@param id
-
@return
*/
@Select(“select * from tb_brand where id = #{id}”)
@ResultMap(“brandResultMap”)
Brand selectById(int id);
8.4.1.2 编写BrandService方法
在 BrandService
类中定义根据id查询数据方法 selectById(int id)
/**
-
根据id查询
-
@return
*/
public Brand selectById(int id){
//调用BrandMapper.selectAll()
//2. 获取SqlSession
SqlSession sqlSession = factory.openSession();
//3. 获取BrandMapper
BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
//4. 调用方法
Brand brand = mapper.selectById(id);
sqlSession.close();
return brand;
}
8.4.1.3 编写servlet
在 web
包下创建 SelectByIdServlet
的 servlet
,该 servlet
的逻辑如下:
-
获取请求数据
id
-
调用
BrandService
的selectById()
方法进行数据查询的业务逻辑 -
将查询到的数据存储到 request 域对象中
-
跳转到
update.jsp
页面进行数据真实
具体代码如下:
@WebServlet(“/selectByIdServlet”)
public class SelectByIdServlet extends HttpServlet {
private BrandService service = new BrandService();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 接收id
String id = request.getParameter(“id”);
//2. 调用service查询
Brand brand = service.selectById(Integer.parseInt(id));
//3. 存储到request中
request.setAttribute(“brand”,brand);
//4. 转发到update.jsp
request.getRequestDispatcher(“/update.jsp”).forward(request,response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
8.4.1.4 编写update.jsp页面
拷贝 addBrand.jsp
页面,改名为 update.jsp
并做出以下修改:
-
title
标签内容改为修改品牌
-
form
标签的action
属性值改为/brand-demo/updateServlet
-
input
标签要进行数据回显,需要设置value
属性
品牌名称:
企业名称:
排序:
textarea
标签要进行数据回显,需要在标签体中使用EL表达式
描述信息:${brand.description}
- 单选框使用
if
标签需要判断brand.status
的值是 1 还是 0 在指定的单选框上使用checked
属性,表示被选中状态
状态:
<c:if test=“${brand.status == 0}”>
禁用
启用
</c:if>
<c:if test=“${brand.status == 1}”>
禁用
启用
</c:if>
综上,update.jsp
代码如下:
<%@ page contentType=“text/html;charset=UTF-8” language=“java” %>
<%@ taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core” %>
修改品牌
品牌名称:
企业名称:
排序:
描述信息:${brand.description}
状态:
<c:if test=“${brand.status == 0}”>
禁用
启用
</c:if>
<c:if test=“${brand.status == 1}”>
禁用
启用
</c:if>
8.4.2 修改数据
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
:
企业名称:
排序:
textarea
标签要进行数据回显,需要在标签体中使用EL表达式
描述信息:${brand.description}
- 单选框使用
if
标签需要判断brand.status
的值是 1 还是 0 在指定的单选框上使用checked
属性,表示被选中状态
状态:
<c:if test=“${brand.status == 0}”>
禁用
启用
</c:if>
<c:if test=“${brand.status == 1}”>
禁用
启用
</c:if>
综上,update.jsp
代码如下:
<%@ page contentType=“text/html;charset=UTF-8” language=“java” %>
<%@ taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core” %>
修改品牌
品牌名称:
企业名称:
排序:
描述信息:${brand.description}
状态:
<c:if test=“${brand.status == 0}”>
禁用
启用
</c:if>
<c:if test=“${brand.status == 1}”>
禁用
启用
</c:if>
8.4.2 修改数据
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-cKyzTrb1-1715714820013)]
[外链图片转存中…(img-Jq0m1Edt-1715714820013)]
[外链图片转存中…(img-RLBsxz9s-1715714820013)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!